merchant

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

taler-merchant-kyccheck.c (63103B)


      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/iterate_outdated_kyc_statuses.h"
     40 #include "merchant-database/insert_kyc_status.h"
     41 #include "merchant-database/delete_tos_accepted_early.h"
     42 #include "merchant-database/get_kyc_status.h"
     43 #include "merchant-database/get_tos_accepted_early.h"
     44 #include "merchant-database/set_instance.h"
     45 #include "merchant-database/iterate_accounts.h"
     46 #include "merchant-database/get_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  * "iterate_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  * Should we enable HTTP/2 and HTTP/3 when talking to the exchange?
    431  * Those are not expected to be terribly beneficial for a client with
    432  * stable connections to a few servers, but they could cause stability
    433  * issues with libcurl.  Hence we *default* to HTTP/1.1-only, as that
    434  * is the conservative and most tested code path.
    435  */
    436 static int enable_h3;
    437 
    438 /**
    439  * #GNUNET_YES if we are in test mode and should exit when idle.
    440  */
    441 static int test_mode;
    442 
    443 /**
    444  * True if the last DB query was limited by the
    445  * #OPEN_INQUIRY_LIMIT and we thus should check again
    446  * as soon as we are substantially below that limit,
    447  * and not only when we get a DB notification.
    448  */
    449 static bool at_limit;
    450 
    451 
    452 /**
    453  * Check about performing a /kyc-check request with the
    454  * exchange for the given inquiry.
    455  *
    456  * @param cls a `struct Inquiry` to process
    457  */
    458 static void
    459 inquiry_work (void *cls);
    460 
    461 
    462 /**
    463  * An inquiry finished, check if we should resume others.
    464  */
    465 static void
    466 end_inquiry (void)
    467 {
    468   GNUNET_assert (active_inquiries > 0);
    469   active_inquiries--;
    470   if ( (active_inquiries < OPEN_INQUIRY_LIMIT / 2) &&
    471        (at_limit) )
    472   {
    473     at_limit = false;
    474     for (struct Account *a = a_head;
    475          NULL != a;
    476          a = a->next)
    477     {
    478       for (struct Inquiry *i = a->i_head;
    479            NULL != i;
    480            i = i->next)
    481       {
    482         if (! i->limited)
    483           continue;
    484         i->limited = false;
    485         GNUNET_assert (NULL == i->task);
    486         /* done synchronously so that the active_inquiries
    487            is updated immediately */
    488         inquiry_work (i);
    489         if (at_limit)
    490           break;
    491       }
    492       if (at_limit)
    493         break;
    494     }
    495   }
    496   if ( (! at_limit) &&
    497        (0 == active_inquiries) &&
    498        (test_mode) )
    499   {
    500     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    501                 "No more open inquiries and in test mode. Existing.\n");
    502     GNUNET_SCHEDULER_shutdown ();
    503     return;
    504   }
    505 }
    506 
    507 
    508 /**
    509  * Pack the given @a limit into the JSON @a limits array.
    510  *
    511  * @param limit account limit to pack
    512  * @param[in,out] limits JSON array to extend
    513  */
    514 static void
    515 pack_limit (const struct TALER_EXCHANGE_AccountLimit *limit,
    516             json_t *limits)
    517 {
    518   json_t *jl;
    519 
    520   jl = GNUNET_JSON_PACK (
    521     TALER_JSON_pack_kycte ("operation_type",
    522                            limit->operation_type),
    523     GNUNET_JSON_pack_time_rel ("timeframe",
    524                                limit->timeframe),
    525     TALER_JSON_pack_amount ("threshold",
    526                             &limit->threshold),
    527     GNUNET_JSON_pack_bool ("soft_limit",
    528                            limit->soft_limit)
    529     );
    530   GNUNET_assert (0 ==
    531                  json_array_append_new (limits,
    532                                         jl));
    533 }
    534 
    535 
    536 /**
    537  * Update KYC status for @a i based on
    538  * @a account_kyc_status
    539  *
    540  * @param[in,out] i inquiry context, jlimits is updated
    541  * @param account_kyc_status account KYC status details
    542  */
    543 static void
    544 store_kyc_status (
    545   struct Inquiry *i,
    546   const struct TALER_EXCHANGE_AccountKycStatus *account_kyc_status)
    547 {
    548   json_t *jlimits;
    549 
    550   json_decref (i->jlimits);
    551   jlimits = json_array ();
    552   GNUNET_assert (NULL != jlimits);
    553   i->zero_limited = false;
    554   for (unsigned int j = 0; j<account_kyc_status->limits_length; j++)
    555   {
    556     const struct TALER_EXCHANGE_AccountLimit *limit
    557       = &account_kyc_status->limits[j];
    558 
    559     pack_limit (limit,
    560                 jlimits);
    561     if (TALER_amount_is_zero (&limit->threshold) &&
    562         limit->soft_limit &&
    563         ( (TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT == limit->operation_type) ||
    564           (TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE == limit->operation_type) ||
    565           (TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION == limit->operation_type) ) )
    566     {
    567       i->zero_limited = true;
    568     }
    569   }
    570   i->jlimits = jlimits;
    571   GNUNET_break (! GNUNET_is_zero (&account_kyc_status->access_token));
    572   i->access_token = account_kyc_status->access_token;
    573   i->aml_review = account_kyc_status->aml_review;
    574   i->kyc_ok = (MHD_HTTP_OK == i->last_http_status);
    575 }
    576 
    577 
    578 /**
    579  * The current interaction with the exchange for inquiry @a i is
    580  * complete (or was aborted).  Schedule the next periodic KYC check
    581  * at @a i->due and release the active-inquiry slot.
    582  *
    583  * @param[in,out] i the inquiry to reschedule
    584  */
    585 static void
    586 finish_inquiry (struct Inquiry *i)
    587 {
    588   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    589               "Will repeat inquiry in %s\n",
    590               GNUNET_TIME_relative2s (
    591                 GNUNET_TIME_absolute_get_remaining (i->due),
    592                 true));
    593   if (! GNUNET_TIME_absolute_is_never (i->due))
    594     i->task = GNUNET_SCHEDULER_add_at (i->due,
    595                                        &inquiry_work,
    596                                        i);
    597   end_inquiry ();
    598 }
    599 
    600 
    601 /**
    602  * Clear the tos-accepted data from the user, we do not
    603  * need the flag anymore, either because we passed it on
    604  * to the exchange or because they are too old.
    605  *
    606  * @param i inquiry this is about
    607  */
    608 static void
    609 clear_tos (const struct Inquiry *i)
    610 {
    611   enum GNUNET_DB_QueryStatus qs;
    612 
    613   qs = TALER_MERCHANTDB_set_instance (pg,
    614                                       i->a->instance_id);
    615   if (qs < 0)
    616   {
    617     GNUNET_break (0);
    618     global_ret = EXIT_FAILURE;
    619     GNUNET_SCHEDULER_shutdown ();
    620     return;
    621   }
    622   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
    623   {
    624     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    625                 "Instance `%s' vanished, nothing to clear\n",
    626                 i->a->instance_id);
    627     return;
    628   }
    629   qs = TALER_MERCHANTDB_delete_tos_accepted_early (
    630     pg,
    631     i->a->instance_id,
    632     i->e->keys->exchange_url);
    633   GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    634                 TALER_MERCHANTDB_set_instance (pg,
    635                                                NULL));
    636   if (qs < 0)
    637   {
    638     GNUNET_break (0);
    639     global_ret = EXIT_FAILURE;
    640     GNUNET_SCHEDULER_shutdown ();
    641     return;
    642   }
    643 }
    644 
    645 
    646 /**
    647  * Function called with the result of submitting an automatic
    648  * terms-of-service acceptance to the exchange via /kyc-upload.
    649  *
    650  * @param i the inquiry the acceptance was for
    651  * @param pr the exchange's response
    652  */
    653 static void
    654 tos_upload_cb (struct Inquiry *i,
    655                const struct TALER_EXCHANGE_PostKycUploadResponse *pr)
    656 {
    657   unsigned int http_status = pr->hr.http_status;
    658 
    659   i->tos_upload = NULL;
    660   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    661               "Automatic ToS acceptance for `%s' at `%s' returned HTTP %u\n",
    662               i->a->merchant_account_uri.full_payto,
    663               i->e->keys->exchange_url,
    664               http_status);
    665   switch (http_status)
    666   {
    667   case MHD_HTTP_OK:
    668   case MHD_HTTP_NO_CONTENT:
    669     /* Exchange accepted the terms of service: re-check KYC now. */
    670     i->due = GNUNET_TIME_UNIT_ZERO_ABS;
    671     clear_tos (i);
    672     break;
    673   case 0: /* no answer, like network failure */
    674   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    675   case MHD_HTTP_BAD_GATEWAY:
    676   case MHD_HTTP_REQUEST_ENTITY_TOO_LARGE: /* Wild error */
    677     /* Internal/transient error at the exchange: do NOT clear the early
    678        acceptance, but back off for at least an hour before retrying
    679        with a regular periodic KYC check. */
    680     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    681                 "Exchange `%s' failed to process automatic ToS acceptance (HTTP %u); retrying later\n",
    682                 i->e->keys->exchange_url,
    683                 http_status);
    684     i->due = GNUNET_TIME_relative_to_absolute (
    685       GNUNET_TIME_randomize (TOS_ERROR_RETRY_DELAY));
    686     break;
    687   case MHD_HTTP_NOT_FOUND:
    688     /* Something must have changed exchange-side, try again
    689        immediately, but do not clear ToS acceptance */
    690     i->due = GNUNET_TIME_UNIT_ZERO_ABS;
    691     clear_tos (i);
    692     break;
    693   case MHD_HTTP_BAD_REQUEST:
    694     /* This should not happen, go back to manual KYC */
    695     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    696                 "Exchange `%s' failed to process automatic ToS acceptance (HTTP %u); retrying later\n",
    697                 i->e->keys->exchange_url,
    698                 http_status);
    699     i->due = GNUNET_TIME_relative_to_absolute (
    700       GNUNET_TIME_randomize (TOS_ERROR_RETRY_DELAY));
    701     break;
    702   case MHD_HTTP_CONFLICT:
    703     /* Exchange rejected the accepted ToS version (ETag not acceptable
    704        or ToS acceptance disappeared):
    705        clear the early acceptance so we do not loop, then re-check KYC
    706        (the user will have to accept the ToS through the regular flow
    707        if it still applies). */
    708     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    709                 "Exchange `%s' rejected early ToS acceptance (version `%s', HTTP %u); clearing early acceptance\n",
    710                 i->e->keys->exchange_url,
    711                 i->tos_etag,
    712                 http_status);
    713     clear_tos (i);
    714     i->due = GNUNET_TIME_UNIT_ZERO_ABS;
    715     break;
    716   }
    717   GNUNET_free (i->tos_etag);
    718   finish_inquiry (i);
    719 }
    720 
    721 
    722 /**
    723  * Submit an automatic terms-of-service acceptance for inquiry @a i to
    724  * the exchange, using the @a id of the corresponding KYC requirement
    725  * (obtained from /kyc-info) and the early-accepted version in
    726  * @a i->tos_etag.
    727  *
    728  * @param[in,out] i inquiry to submit the ToS acceptance for
    729  * @param id KYC requirement / upload ID for the terms-of-service form
    730  */
    731 static void
    732 start_tos_upload (struct Inquiry *i,
    733                   const char *id)
    734 {
    735   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    736               "Submitting automatic ToS acceptance (version `%s', id `%s') to `%s'\n",
    737               i->tos_etag,
    738               id,
    739               i->e->keys->exchange_url);
    740   i->tos_upload = TALER_EXCHANGE_post_kyc_upload_accept_tos_create (
    741     ctx,
    742     i->e->keys->exchange_url,
    743     id,
    744     i->tos_etag);
    745   if ( (NULL == i->tos_upload) ||
    746        (TALER_EC_NONE !=
    747         TALER_EXCHANGE_post_kyc_upload_start (i->tos_upload,
    748                                               &tos_upload_cb,
    749                                               i)) )
    750   {
    751     GNUNET_break (0);
    752     if (NULL != i->tos_upload)
    753     {
    754       TALER_EXCHANGE_post_kyc_upload_cancel (i->tos_upload);
    755       i->tos_upload = NULL;
    756     }
    757     /* Could not even start the upload: treat as transient, keep the
    758        early acceptance and retry with a regular periodic check. */
    759     GNUNET_free (i->tos_etag);
    760     finish_inquiry (i);
    761   }
    762 }
    763 
    764 
    765 /**
    766  * Function called with the result of fetching /kyc-info while trying
    767  * to automatically accept the terms of service.  Finds the ID of the
    768  * terms-of-service requirement and submits the acceptance.
    769  *
    770  * @param i the inquiry the lookup was for
    771  * @param ir the exchange's response
    772  */
    773 static void
    774 tos_info_cb (struct Inquiry *i,
    775              const struct TALER_EXCHANGE_GetKycInfoResponse *ir)
    776 {
    777   i->kyc_info = NULL;
    778   if (MHD_HTTP_OK == ir->hr.http_status)
    779   {
    780     const char *id = NULL;
    781 
    782     for (size_t j = 0; j < ir->details.ok.requirements_length; j++)
    783     {
    784       const struct TALER_EXCHANGE_RequirementInformation *req
    785         = &ir->details.ok.requirements[j];
    786 
    787       if ( (NULL != req->form) &&
    788            (NULL != req->id) &&
    789            (0 == strcmp (req->form,
    790                          ACCEPT_TOS_FORM)) )
    791       {
    792         id = req->id;
    793         break;
    794       }
    795     }
    796     if (NULL != id)
    797     {
    798       start_tos_upload (i,
    799                         id);
    800       return;
    801     }
    802     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    803                 "No `%s' requirement at `%s'; cannot auto-accept ToS, falling back to periodic check\n",
    804                 ACCEPT_TOS_FORM,
    805                 i->e->keys->exchange_url);
    806   }
    807   else
    808   {
    809     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    810                 "GET /kyc-info at `%s' returned HTTP %u; cannot auto-accept ToS now\n",
    811                 i->e->keys->exchange_url,
    812                 ir->hr.http_status);
    813   }
    814   /* Could not determine the upload ID: keep the early acceptance and
    815      retry on the next regular periodic KYC check. */
    816   GNUNET_free (i->tos_etag);
    817   finish_inquiry (i);
    818 }
    819 
    820 
    821 /**
    822  * Start the automatic terms-of-service acceptance for inquiry @a i by
    823  * fetching /kyc-info to discover the ID of the terms-of-service
    824  * requirement.  The early-accepted version is in @a i->tos_etag.
    825  *
    826  * @param[in,out] i inquiry to auto-accept the terms of service for
    827  */
    828 static void
    829 start_tos_info (struct Inquiry *i)
    830 {
    831   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    832               "Fetching /kyc-info from `%s' to auto-accept ToS for `%s'\n",
    833               i->e->keys->exchange_url,
    834               i->a->merchant_account_uri.full_payto);
    835   i->kyc_info = TALER_EXCHANGE_get_kyc_info_create (ctx,
    836                                                     i->e->keys->exchange_url,
    837                                                     &i->access_token);
    838   if ( (NULL == i->kyc_info) ||
    839        (TALER_EC_NONE !=
    840         TALER_EXCHANGE_get_kyc_info_start (i->kyc_info,
    841                                            &tos_info_cb,
    842                                            i)) )
    843   {
    844     GNUNET_break (0);
    845     if (NULL != i->kyc_info)
    846     {
    847       TALER_EXCHANGE_get_kyc_info_cancel (i->kyc_info);
    848       i->kyc_info = NULL;
    849     }
    850     /* Could not start the lookup: keep the early acceptance and retry
    851        with a regular periodic check. */
    852     GNUNET_free (i->tos_etag);
    853     finish_inquiry (i);
    854   }
    855 }
    856 
    857 
    858 /**
    859  * The exchange asked us (via @a tos_required) to accept its terms of
    860  * service.  Check whether the user already accepted the terms of
    861  * service early (via ``POST /private/accept-tos-early``).  If so,
    862  * remember the accepted version in @a i->tos_etag so that we will try
    863  * to submit it to the exchange automatically.
    864  *
    865  * @param[in,out] i inquiry for which the exchange requires ToS acceptance
    866  * @param req required ETag for the accepted ToS
    867  */
    868 static void
    869 check_early_tos_acceptance (struct Inquiry *i,
    870                             const char *req)
    871 {
    872   enum GNUNET_DB_QueryStatus qs;
    873   char *tos_version = NULL;
    874 
    875   qs = TALER_MERCHANTDB_set_instance (pg,
    876                                       i->a->instance_id);
    877   if (qs < 0)
    878   {
    879     GNUNET_break (0);
    880     global_ret = EXIT_FAILURE;
    881     GNUNET_SCHEDULER_shutdown ();
    882     return;
    883   }
    884   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
    885   {
    886     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    887                 "Instance `%s' vanished, skipping ToS check\n",
    888                 i->a->instance_id);
    889     return;
    890   }
    891   qs = TALER_MERCHANTDB_get_tos_accepted_early (pg,
    892                                                 i->a->instance_id,
    893                                                 i->e->keys->exchange_url,
    894                                                 &tos_version);
    895   GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    896                 TALER_MERCHANTDB_set_instance (pg,
    897                                                NULL));
    898   if (qs < 0)
    899   {
    900     GNUNET_break (0);
    901     global_ret = EXIT_FAILURE;
    902     GNUNET_SCHEDULER_shutdown ();
    903     return;
    904   }
    905   if (NULL == tos_version)
    906   {
    907     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    908                 "Exchange `%s' supports early ToS acceptance, but user did not accept ToS early\n",
    909                 i->e->keys->exchange_url);
    910     return;
    911   }
    912   if (0 != strcmp (tos_version,
    913                    req))
    914   {
    915     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    916                 "User accepted outdated ToS version `%s' early, but exchange wants `%s'. User will need to accept the ToS again!\n",
    917                 tos_version,
    918                 req);
    919     GNUNET_free (tos_version);
    920     return;
    921   }
    922   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    923               "User accepted ToS version `%s' early; will submit to `%s'\n",
    924               tos_version,
    925               i->e->keys->exchange_url);
    926   GNUNET_free (i->tos_etag);
    927   i->tos_etag = tos_version;
    928 }
    929 
    930 
    931 /**
    932  * Function called with the result of a KYC check.
    933  *
    934  * @param cls a `struct Inquiry *`
    935  * @param ks the account's KYC status details
    936  */
    937 static void
    938 exchange_check_cb (
    939   struct Inquiry *i,
    940   const struct TALER_EXCHANGE_GetKycCheckResponse *ks)
    941 {
    942   bool progress = false;
    943 
    944   i->kyc = NULL;
    945   if (! i->not_first_time)
    946     progress = true;
    947   if ( (i->last_http_status != ks->hr.http_status) &&
    948        (0 != ks->hr.http_status) )
    949     progress = true;
    950   if (0 != ks->hr.http_status)
    951   {
    952     i->last_http_status = ks->hr.http_status;
    953     i->last_ec = ks->hr.ec;
    954   }
    955   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    956               "KYC status of `%s' / %s at `%s' is %u\n",
    957               i->a->merchant_account_uri.full_payto,
    958               i->a->instance_id,
    959               i->e->keys->exchange_url,
    960               ks->hr.http_status);
    961   switch (ks->hr.http_status)
    962   {
    963   case 0:
    964     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    965                 "Exchange did not responded to /kyc-check request!\n");
    966     i->backoff
    967       = GNUNET_TIME_randomized_backoff (i->backoff,
    968                                         EXCHANGE_TIMEOUT);
    969     i->due = GNUNET_TIME_relative_to_absolute (i->backoff);
    970     break;
    971   case MHD_HTTP_OK:
    972     if (i->rule_gen != ks->details.ok.rule_gen)
    973       progress = true;
    974     i->rule_gen = ks->details.ok.rule_gen;
    975     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
    976     /* exchange says KYC is OK, gives status information */
    977     i->auth_ok = true;
    978     store_kyc_status (i,
    979                       &ks->details.ok);
    980     i->backoff = GNUNET_TIME_UNIT_MINUTES;
    981     if (i->aml_review || i->zero_limited)
    982     {
    983       if (! progress)
    984         i->due = GNUNET_TIME_relative_to_absolute (
    985           GNUNET_TIME_randomize (GNUNET_TIME_relative_max (aml_freq,
    986                                                            i->backoff)));
    987     }
    988     else
    989     {
    990       /* KYC is OK, only check again if triggered */
    991       if (! progress)
    992         i->due = GNUNET_TIME_relative_to_absolute (
    993           GNUNET_TIME_randomize (GNUNET_TIME_relative_max (aml_low_freq,
    994                                                            i->backoff)));
    995     }
    996     break;
    997   case MHD_HTTP_ACCEPTED:
    998     if (i->rule_gen != ks->details.accepted.rule_gen)
    999       progress = true;
   1000     i->rule_gen = ks->details.accepted.rule_gen;
   1001     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
   1002     /* exchange says KYC is required */
   1003     i->auth_ok = true;
   1004     store_kyc_status (i,
   1005                       &ks->details.accepted);
   1006     i->backoff = GNUNET_TIME_UNIT_MINUTES;
   1007     /* Start immediately with long-polling */
   1008     if (! progress)
   1009       i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time,
   1010                                          i->timeout);
   1011     if (NULL != ks->details.accepted.tos_required)
   1012     {
   1013       /* Exchange wants the user to accept its terms of service.
   1014          If the user already accepted them early, try to submit that
   1015          acceptance to the exchange automatically. */
   1016       check_early_tos_acceptance (i,
   1017                                   ks->details.accepted.tos_required);
   1018     }
   1019     break;
   1020   case MHD_HTTP_NO_CONTENT:
   1021     i->rule_gen = 0;
   1022     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
   1023     i->backoff = GNUNET_TIME_UNIT_MINUTES;
   1024     /* exchange claims KYC is off! */
   1025     i->kyc_ok = true;
   1026     i->aml_review = false;
   1027     /* Clear limits, in case exchange had KYC on previously */
   1028     json_decref (i->jlimits);
   1029     i->jlimits = NULL;
   1030     /* KYC is OK, only check again if triggered */
   1031     i->due = GNUNET_TIME_relative_to_absolute (
   1032       GNUNET_TIME_randomize (GNUNET_TIME_relative_max (aml_low_freq,
   1033                                                        i->backoff)));
   1034     break;
   1035   case MHD_HTTP_FORBIDDEN: /* bad signature */
   1036     i->rule_gen = 0;
   1037     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
   1038     /* Forbidden => KYC auth must be wrong */
   1039     i->auth_ok = false;
   1040     /* Start with long-polling */
   1041     if (! progress)
   1042       i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time,
   1043                                          i->timeout);
   1044     i->backoff = GNUNET_TIME_UNIT_MINUTES;
   1045     break;
   1046   case MHD_HTTP_NOT_FOUND: /* account unknown */
   1047     i->rule_gen = 0;
   1048     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
   1049     /* Account unknown => no KYC auth yet */
   1050     i->auth_ok = false;
   1051     /* unknown account => wire transfer required! */
   1052     i->kyc_ok = false;
   1053     /* There should not be any limits yet, but clear them
   1054        just in case the exchange has amnesia */
   1055     json_decref (i->jlimits);
   1056     i->jlimits = NULL;
   1057     /* Start immediately with Long-polling */
   1058     if (! progress)
   1059       i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time,
   1060                                          i->timeout);
   1061     i->backoff = GNUNET_TIME_UNIT_MINUTES;
   1062     break;
   1063   case MHD_HTTP_CONFLICT: /* no account_pub known */
   1064     i->rule_gen = 0;
   1065     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
   1066     /* Conflict => KYC auth wire transfer missing! */
   1067     i->auth_ok = false;
   1068     /* Start immediately with Long-polling */
   1069     if (! progress)
   1070       i->due = GNUNET_TIME_absolute_max (i->last_kyc_check.abs_time,
   1071                                          i->timeout);
   1072     i->backoff = GNUNET_TIME_UNIT_MINUTES;
   1073     break;
   1074   default:
   1075     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1076                 "Exchange responded with HTTP status %u (%d) to /kyc-check request!\n",
   1077                 ks->hr.http_status,
   1078                 ks->hr.ec);
   1079     i->backoff
   1080       = GNUNET_TIME_randomized_backoff (i->backoff,
   1081                                         EXCHANGE_TIMEOUT);
   1082     i->last_kyc_check = GNUNET_TIME_timestamp_get ();
   1083     i->due = GNUNET_TIME_relative_to_absolute (i->backoff);
   1084     i->auth_ok = false;
   1085     break;
   1086   }
   1087 
   1088   {
   1089     enum GNUNET_DB_QueryStatus qs;
   1090 
   1091     qs = TALER_MERCHANTDB_set_instance (pg,
   1092                                         i->a->instance_id);
   1093     if (qs < 0)
   1094     {
   1095       GNUNET_break (0);
   1096       global_ret = EXIT_FAILURE;
   1097       GNUNET_SCHEDULER_shutdown ();
   1098       return;
   1099     }
   1100     if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   1101     {
   1102       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1103                   "Instance `%s' vanished, discarding KYC status\n",
   1104                   i->a->instance_id);
   1105       finish_inquiry (i);
   1106       return;
   1107     }
   1108     qs = TALER_MERCHANTDB_insert_kyc_status (
   1109       pg,
   1110       i->a->instance_id,
   1111       &i->a->h_wire,
   1112       i->e->keys->exchange_url,
   1113       i->last_kyc_check,
   1114       i->due,
   1115       i->backoff,
   1116       i->last_http_status,
   1117       i->last_ec,
   1118       i->rule_gen,
   1119       (i->auth_ok)
   1120       ? &i->access_token
   1121       : NULL,
   1122       i->jlimits,
   1123       i->aml_review,
   1124       i->kyc_ok);
   1125     GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
   1126                   TALER_MERCHANTDB_set_instance (
   1127                     pg,
   1128                     NULL));
   1129     if (qs < 0)
   1130     {
   1131       GNUNET_break (0);
   1132       global_ret = EXIT_FAILURE;
   1133       GNUNET_SCHEDULER_shutdown ();
   1134       return;
   1135     }
   1136     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1137                 "insert_kyc_status (%s, %s, %u, %s, %s) returned %d\n",
   1138                 i->a->instance_id,
   1139                 i->e->keys->exchange_url,
   1140                 i->last_http_status,
   1141                 i->auth_ok ? "auth OK" : "auth needed",
   1142                 NULL == i->jlimits ? "default limits" : "custom limits",
   1143                 (int) qs);
   1144     i->not_first_time = true;
   1145   }
   1146   if (NULL != i->tos_etag)
   1147   {
   1148     /* The user accepted the terms of service early and the exchange now
   1149        requires acceptance: try to submit it automatically (this keeps
   1150        the active-inquiry slot) instead of waiting for the next check. */
   1151     start_tos_info (i);
   1152     return;
   1153   }
   1154   finish_inquiry (i);
   1155 }
   1156 
   1157 
   1158 static void
   1159 inquiry_work (void *cls)
   1160 {
   1161   struct Inquiry *i = cls;
   1162   enum TALER_EXCHANGE_KycLongPollTarget lpt;
   1163 
   1164   i->task = NULL;
   1165   if (! GNUNET_TIME_absolute_is_past (i->due))
   1166   {
   1167     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1168                 "Will start inquiry on %s for %s in %s\n",
   1169                 i->a->merchant_account_uri.full_payto,
   1170                 i->e->keys->exchange_url,
   1171                 GNUNET_TIME_relative2s (
   1172                   GNUNET_TIME_absolute_get_remaining (i->due),
   1173                   true));
   1174     i->task
   1175       = GNUNET_SCHEDULER_add_at (i->due,
   1176                                  &inquiry_work,
   1177                                  i);
   1178     goto finish;
   1179   }
   1180 
   1181   GNUNET_assert (OPEN_INQUIRY_LIMIT >= active_inquiries);
   1182   if (OPEN_INQUIRY_LIMIT <= active_inquiries)
   1183   {
   1184     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1185                 "Not looking for work: at limit\n");
   1186     i->limited = true;
   1187     at_limit = true;
   1188     return;
   1189   }
   1190   at_limit = false;
   1191   i->timeout
   1192     = GNUNET_TIME_relative_to_absolute (EXCHANGE_TIMEOUT);
   1193   lpt = TALER_EXCHANGE_KLPT_NONE;
   1194   if (! i->auth_ok)
   1195     lpt = TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER;
   1196   else if (! i->kyc_ok)
   1197     lpt = TALER_EXCHANGE_KLPT_KYC_OK;
   1198   else if (i->aml_review)
   1199     lpt = TALER_EXCHANGE_KLPT_INVESTIGATION_DONE;
   1200   if (! i->not_first_time)
   1201     lpt = TALER_EXCHANGE_KLPT_NONE; /* no long polling on 1st call */
   1202   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1203               "Starting KYC status of `%s' for %s at `%s' (%d, %d, %d) using LPT %d\n",
   1204               i->a->merchant_account_uri.full_payto,
   1205               i->a->instance_id,
   1206               i->e->keys->exchange_url,
   1207               i->not_first_time,
   1208               i->auth_ok,
   1209               i->kyc_ok,
   1210               lpt);
   1211   i->kyc = TALER_EXCHANGE_get_kyc_check_create (
   1212     ctx,
   1213     i->e->keys->exchange_url,
   1214     &i->a->h_payto,
   1215     &i->a->ap);
   1216   if (NULL == i->kyc)
   1217   {
   1218     GNUNET_break (0);
   1219     i->due = i->timeout;
   1220     i->task
   1221       = GNUNET_SCHEDULER_add_at (i->due,
   1222                                  &inquiry_work,
   1223                                  i);
   1224     goto finish;
   1225   }
   1226   GNUNET_assert (GNUNET_OK ==
   1227                  TALER_EXCHANGE_get_kyc_check_set_options (
   1228                    i->kyc,
   1229                    TALER_EXCHANGE_get_kyc_check_option_known_rule_gen (
   1230                      i->rule_gen),
   1231                    TALER_EXCHANGE_get_kyc_check_option_lpt (lpt),
   1232                    TALER_EXCHANGE_get_kyc_check_option_timeout (
   1233                      i->not_first_time && (! test_mode)
   1234                      ? EXCHANGE_TIMEOUT
   1235                      : GNUNET_TIME_UNIT_ZERO)));
   1236   GNUNET_assert (TALER_EC_NONE ==
   1237                  TALER_EXCHANGE_get_kyc_check_start (i->kyc,
   1238                                                      &exchange_check_cb,
   1239                                                      i));
   1240   active_inquiries++;
   1241 finish:
   1242   if ( (0 == active_inquiries) &&
   1243        (test_mode) )
   1244   {
   1245     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1246                 "No more open inquiries and in test mode. Existing.\n");
   1247     GNUNET_SCHEDULER_shutdown ();
   1248     return;
   1249   }
   1250 }
   1251 
   1252 
   1253 /**
   1254  * Check if the account @a could work with exchange that
   1255  * has keys @a keys.
   1256  *
   1257  * @param keys the keys of an exchange
   1258  * @param a an account
   1259  */
   1260 static bool
   1261 is_eligible (const struct TALER_EXCHANGE_Keys *keys,
   1262              const struct Account *a)
   1263 {
   1264   struct TALER_NormalizedPayto np;
   1265   bool ret;
   1266 
   1267   np = TALER_payto_normalize (a->merchant_account_uri);
   1268   ret = TALER_EXCHANGE_keys_test_account_allowed (keys,
   1269                                                   true,
   1270                                                   np);
   1271   GNUNET_free (np.normalized_payto);
   1272   return ret;
   1273 }
   1274 
   1275 
   1276 /**
   1277  * Start the KYC checking for account @a at exchange @a e.
   1278  *
   1279  * @param e an exchange
   1280  * @param a an account
   1281  */
   1282 static void
   1283 start_inquiry (struct Exchange *e,
   1284                struct Account *a)
   1285 {
   1286   struct Inquiry *i;
   1287   enum GNUNET_DB_QueryStatus qs;
   1288 
   1289   i = GNUNET_new (struct Inquiry);
   1290   i->e = e;
   1291   i->a = a;
   1292   GNUNET_CONTAINER_DLL_insert (a->i_head,
   1293                                a->i_tail,
   1294                                i);
   1295   qs = TALER_MERCHANTDB_set_instance (pg,
   1296                                       a->instance_id);
   1297   if (qs < 0)
   1298   {
   1299     GNUNET_break (0);
   1300     global_ret = EXIT_FAILURE;
   1301     GNUNET_SCHEDULER_shutdown ();
   1302     return;
   1303   }
   1304   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   1305   {
   1306     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1307                 "Instance `%s' vanished, not starting inquiry\n",
   1308                 a->instance_id);
   1309     return;
   1310   }
   1311   qs = TALER_MERCHANTDB_get_kyc_status (pg,
   1312                                         a->merchant_account_uri,
   1313                                         a->instance_id,
   1314                                         e->keys->exchange_url,
   1315                                         &i->auth_ok,
   1316                                         &i->access_token,
   1317                                         &i->kyc_ok,
   1318                                         &i->last_http_status,
   1319                                         &i->last_ec,
   1320                                         &i->rule_gen,
   1321                                         &i->last_kyc_check,
   1322                                         &i->due,
   1323                                         &i->backoff,
   1324                                         &i->aml_review,
   1325                                         &i->jlimits);
   1326   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1327               "iterate_kyc_statuses (%s, %s, %s) returned %d (%u, #%llu)\n",
   1328               i->a->instance_id,
   1329               e->keys->exchange_url,
   1330               a->merchant_account_uri.full_payto,
   1331               (int) qs,
   1332               i->last_http_status,
   1333               (unsigned long long) i->rule_gen);
   1334   if (qs < 0)
   1335   {
   1336     GNUNET_break (0);
   1337     global_ret = EXIT_FAILURE;
   1338     GNUNET_SCHEDULER_shutdown ();
   1339     return;
   1340   }
   1341   if (qs > 0)
   1342     i->not_first_time = true;
   1343   if (GNUNET_YES == test_mode)
   1344     i->due = GNUNET_TIME_UNIT_ZERO_ABS; /* immediately */
   1345   inquiry_work (i);
   1346 }
   1347 
   1348 
   1349 /**
   1350  * Stop KYC inquiry @a i.
   1351  *
   1352  * @param[in] i the inquiry to stop
   1353  */
   1354 static void
   1355 stop_inquiry (struct Inquiry *i)
   1356 {
   1357   struct Account *a = i->a;
   1358 
   1359   GNUNET_CONTAINER_DLL_remove (a->i_head,
   1360                                a->i_tail,
   1361                                i);
   1362   if (NULL != i->task)
   1363   {
   1364     GNUNET_SCHEDULER_cancel (i->task);
   1365     i->task = NULL;
   1366   }
   1367   if (NULL != i->kyc)
   1368   {
   1369     TALER_EXCHANGE_get_kyc_check_cancel (i->kyc);
   1370     i->kyc = NULL;
   1371   }
   1372   if (NULL != i->kyc_info)
   1373   {
   1374     TALER_EXCHANGE_get_kyc_info_cancel (i->kyc_info);
   1375     i->kyc_info = NULL;
   1376   }
   1377   if (NULL != i->tos_upload)
   1378   {
   1379     TALER_EXCHANGE_post_kyc_upload_cancel (i->tos_upload);
   1380     i->tos_upload = NULL;
   1381   }
   1382   GNUNET_free (i->tos_etag);
   1383   if (NULL != i->jlimits)
   1384   {
   1385     json_decref (i->jlimits);
   1386     i->jlimits = NULL;
   1387   }
   1388   GNUNET_free (i);
   1389 }
   1390 
   1391 
   1392 /**
   1393  * Stop KYC inquiry for account @a at exchange @a e.
   1394  *
   1395  * @param e an exchange
   1396  * @param a an account
   1397  */
   1398 static void
   1399 stop_inquiry_at (struct Exchange *e,
   1400                  struct Account *a)
   1401 {
   1402   for (struct Inquiry *i = a->i_head;
   1403        NULL != i;
   1404        i = i->next)
   1405   {
   1406     if (e == i->e)
   1407     {
   1408       stop_inquiry (i);
   1409       return;
   1410     }
   1411   }
   1412   /* strange, there should have been a match! */
   1413   GNUNET_break (0);
   1414 }
   1415 
   1416 
   1417 /**
   1418  * Set the account @a h_wire of @a instance_id to be ineligible
   1419  * for the exchange at @a exchange_url and thus no need to do KYC checks.
   1420  *
   1421  * @param instance_id instance that has the account
   1422  * @param exchange_url base URL of the exchange
   1423  * @param h_wire hash of the merchant bank account that is ineligible
   1424  */
   1425 static void
   1426 flag_ineligible (const char *instance_id,
   1427                  const char *exchange_url,
   1428                  const struct TALER_MerchantWireHashP *h_wire)
   1429 {
   1430   enum GNUNET_DB_QueryStatus qs;
   1431 
   1432   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1433               "Account %s not eligible at exchange %s\n",
   1434               TALER_B2S (h_wire),
   1435               exchange_url);
   1436   qs = TALER_MERCHANTDB_set_instance (pg,
   1437                                       instance_id);
   1438   if (qs < 0)
   1439   {
   1440     GNUNET_break (0);
   1441     global_ret = EXIT_FAILURE;
   1442     GNUNET_SCHEDULER_shutdown ();
   1443     return;
   1444   }
   1445   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   1446   {
   1447     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1448                 "Instance `%s' vanished, not flagging account\n",
   1449                 instance_id);
   1450     return;
   1451   }
   1452   qs = TALER_MERCHANTDB_insert_kyc_status (
   1453     pg,
   1454     instance_id,
   1455     h_wire,
   1456     exchange_url,
   1457     GNUNET_TIME_timestamp_get (),
   1458     GNUNET_TIME_UNIT_FOREVER_ABS,
   1459     GNUNET_TIME_UNIT_FOREVER_REL,
   1460     0,
   1461     TALER_EC_MERCHANT_PRIVATE_ACCOUNT_NOT_ELIGIBLE_FOR_EXCHANGE,
   1462     0,
   1463     NULL,
   1464     NULL,
   1465     false,
   1466     false);
   1467   GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
   1468                 TALER_MERCHANTDB_set_instance (
   1469                   pg,
   1470                   NULL));
   1471   if (qs < 0)
   1472   {
   1473     GNUNET_break (0);
   1474     global_ret = EXIT_FAILURE;
   1475     GNUNET_SCHEDULER_shutdown ();
   1476     return;
   1477   }
   1478   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1479               "insert_kyc_status (%s) returned %d\n",
   1480               exchange_url,
   1481               (int) qs);
   1482 }
   1483 
   1484 
   1485 /**
   1486  * Start inquries for all exchanges on account @a a.
   1487  *
   1488  * @param a an account
   1489  */
   1490 static void
   1491 start_inquiries (struct Account *a)
   1492 {
   1493   for (struct Exchange *e = e_head;
   1494        NULL != e;
   1495        e = e->next)
   1496   {
   1497     if (is_eligible (e->keys,
   1498                      a))
   1499     {
   1500       start_inquiry (e,
   1501                      a);
   1502     }
   1503     else
   1504     {
   1505       flag_ineligible (a->instance_id,
   1506                        e->keys->exchange_url,
   1507                        &a->h_wire);
   1508     }
   1509   }
   1510 }
   1511 
   1512 
   1513 /**
   1514  * Stop all inquries involving account @a a.
   1515  *
   1516  * @param a an account
   1517  */
   1518 static void
   1519 stop_inquiries (struct Account *a)
   1520 {
   1521   struct Inquiry *i;
   1522 
   1523   while (NULL != (i = a->i_head))
   1524     stop_inquiry (i);
   1525 }
   1526 
   1527 
   1528 /**
   1529  * Callback invoked with information about a bank account.
   1530  *
   1531  * @param cls closure
   1532  * @param merchant_priv private key of the merchant instance
   1533  * @param ad details about the account
   1534  */
   1535 static void
   1536 account_cb (
   1537   void *cls,
   1538   const struct TALER_MerchantPrivateKeyP *merchant_priv,
   1539   const struct TALER_MERCHANTDB_AccountDetails *ad)
   1540 {
   1541   struct TALER_FullPayto payto_uri = ad->payto_uri;
   1542 
   1543   if (! ad->active)
   1544     return;
   1545   if (NULL == merchant_priv)
   1546     return; /* instance was deleted */
   1547   for (struct Account *a = a_head;
   1548        NULL != a;
   1549        a = a->next)
   1550   {
   1551     if ( (0 ==
   1552           TALER_full_payto_cmp (payto_uri,
   1553                                 a->merchant_account_uri)) &&
   1554          (0 ==
   1555           GNUNET_memcmp (&a->h_wire,
   1556                          &ad->h_wire)) &&
   1557          (0 ==
   1558           strcmp (ad->instance_id,
   1559                   a->instance_id)) )
   1560     {
   1561       a->account_gen = database_gen;
   1562       return;
   1563     }
   1564   }
   1565   {
   1566     struct Account *a = GNUNET_new (struct Account);
   1567 
   1568     a->account_gen = database_gen;
   1569     a->merchant_account_uri.full_payto
   1570       = GNUNET_strdup (ad->payto_uri.full_payto);
   1571     a->instance_id
   1572       = GNUNET_strdup (ad->instance_id);
   1573     a->h_wire
   1574       = ad->h_wire;
   1575     a->ap.merchant_priv
   1576       = *merchant_priv;
   1577     TALER_full_payto_normalize_and_hash (a->merchant_account_uri,
   1578                                          &a->h_payto);
   1579     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1580                 "Found account %s of instance %s with H_PAYTO %s\n",
   1581                 ad->payto_uri.full_payto,
   1582                 ad->instance_id,
   1583                 GNUNET_sh2s (&a->h_payto.hash));
   1584     GNUNET_CONTAINER_DLL_insert (a_head,
   1585                                  a_tail,
   1586                                  a);
   1587     start_inquiries (a);
   1588   }
   1589 }
   1590 
   1591 
   1592 /**
   1593  * The set of bank accounts has changed, update our
   1594  * list of active inquiries.
   1595  *
   1596  * @param cls unused
   1597  */
   1598 static void
   1599 find_accounts (void *cls)
   1600 {
   1601   enum GNUNET_DB_QueryStatus qs;
   1602 
   1603   (void) cls;
   1604   account_task = NULL;
   1605   database_gen++;
   1606   qs = TALER_MERCHANTDB_iterate_accounts (pg,
   1607                                           &account_cb,
   1608                                           NULL);
   1609   if (qs < 0)
   1610   {
   1611     GNUNET_break (0);
   1612     global_ret = EXIT_FAILURE;
   1613     GNUNET_SCHEDULER_shutdown ();
   1614     return;
   1615   }
   1616   for (struct Account *a = a_head;
   1617        NULL != a;
   1618        a = a->next)
   1619   {
   1620     if (a->account_gen < database_gen)
   1621       stop_inquiries (a);
   1622   }
   1623   if ( (! at_limit) &&
   1624        (0 == active_inquiries) &&
   1625        (test_mode) )
   1626   {
   1627     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1628                 "No more open inquiries and in test mode. Existing.\n");
   1629     GNUNET_SCHEDULER_shutdown ();
   1630     return;
   1631   }
   1632 }
   1633 
   1634 
   1635 /**
   1636  * Function called when transfers are added to the merchant database.  We look
   1637  * for more work.
   1638  *
   1639  * @param cls closure (NULL)
   1640  * @param extra additional event data provided
   1641  * @param extra_size number of bytes in @a extra
   1642  */
   1643 static void
   1644 account_changed (void *cls,
   1645                  const void *extra,
   1646                  size_t extra_size)
   1647 {
   1648   (void) cls;
   1649   (void) extra;
   1650   (void) extra_size;
   1651   if (NULL != account_task)
   1652     return;
   1653   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1654               "Received account change notification: reloading accounts\n");
   1655   account_task
   1656     = GNUNET_SCHEDULER_add_now (&find_accounts,
   1657                                 NULL);
   1658 }
   1659 
   1660 
   1661 /**
   1662  * Interact with the database to get the current set
   1663  * of exchange keys known to us.
   1664  *
   1665  * @param exchange_url the exchange URL to check
   1666  */
   1667 static void
   1668 find_keys (const char *exchange_url)
   1669 {
   1670   enum GNUNET_DB_QueryStatus qs;
   1671   struct TALER_EXCHANGE_Keys *keys;
   1672   struct Exchange *e;
   1673   struct GNUNET_TIME_Absolute first_retry;
   1674 
   1675   qs = TALER_MERCHANTDB_get_exchange_keys (pg,
   1676                                            exchange_url,
   1677                                            &first_retry,
   1678                                            &keys);
   1679   if (qs < 0)
   1680   {
   1681     GNUNET_break (0);
   1682     global_ret = EXIT_FAILURE;
   1683     GNUNET_SCHEDULER_shutdown ();
   1684     return;
   1685   }
   1686   if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) ||
   1687        (NULL == keys) )
   1688   {
   1689     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1690                 "No %s/keys yet!\n",
   1691                 exchange_url);
   1692     return;
   1693   }
   1694   for (e = e_head; NULL != e; e = e->next)
   1695   {
   1696     if (0 == strcmp (e->keys->exchange_url,
   1697                      keys->exchange_url))
   1698     {
   1699       struct TALER_EXCHANGE_Keys *old_keys = e->keys;
   1700 
   1701       e->keys = keys;
   1702       for (struct Account *a = a_head;
   1703            NULL != a;
   1704            a = a->next)
   1705       {
   1706         bool was_eligible = is_eligible (old_keys,
   1707                                          a);
   1708         bool now_eligible = is_eligible (keys,
   1709                                          a);
   1710 
   1711         if (was_eligible == now_eligible)
   1712           continue; /* no change, do nothing */
   1713         if (was_eligible)
   1714           stop_inquiry_at (e,
   1715                            a);
   1716         else /* is_eligible */
   1717           start_inquiry (e,
   1718                          a);
   1719       }
   1720       TALER_EXCHANGE_keys_decref (old_keys);
   1721       return;
   1722     }
   1723   }
   1724   e = GNUNET_new (struct Exchange);
   1725   e->keys = keys;
   1726   GNUNET_CONTAINER_DLL_insert (e_head,
   1727                                e_tail,
   1728                                e);
   1729   for (struct Account *a = a_head;
   1730        NULL != a;
   1731        a = a->next)
   1732   {
   1733     if (a->account_gen != database_gen)
   1734       continue;
   1735     if (is_eligible (e->keys,
   1736                      a))
   1737     {
   1738       start_inquiry (e,
   1739                      a);
   1740     }
   1741     else
   1742     {
   1743       flag_ineligible (a->instance_id,
   1744                        e->keys->exchange_url,
   1745                        &a->h_wire);
   1746     }
   1747   }
   1748 }
   1749 
   1750 
   1751 /**
   1752  * Function called when keys were changed in the
   1753  * merchant database. Updates ours.
   1754  *
   1755  * @param cls closure (NULL)
   1756  * @param extra additional event data provided
   1757  * @param extra_size number of bytes in @a extra
   1758  */
   1759 static void
   1760 keys_changed (void *cls,
   1761               const void *extra,
   1762               size_t extra_size)
   1763 {
   1764   const char *url = extra;
   1765 
   1766   (void) cls;
   1767   if ( (NULL == extra) ||
   1768        (0 == extra_size) )
   1769   {
   1770     GNUNET_break (0);
   1771     global_ret = EXIT_FAILURE;
   1772     GNUNET_SCHEDULER_shutdown ();
   1773     return;
   1774   }
   1775   if ('\0' != url[extra_size - 1])
   1776   {
   1777     GNUNET_break (0);
   1778     global_ret = EXIT_FAILURE;
   1779     GNUNET_SCHEDULER_shutdown ();
   1780     return;
   1781   }
   1782   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1783               "Received keys change notification: reload `%s'\n",
   1784               url);
   1785   find_keys (url);
   1786 }
   1787 
   1788 
   1789 /**
   1790  * Function called when a KYC rule was triggered by
   1791  * a transaction and we need to get the latest KYC
   1792  * status immediately.
   1793  *
   1794  * @param cls closure (NULL)
   1795  * @param extra additional event data provided
   1796  * @param extra_size number of bytes in @a extra
   1797  */
   1798 static void
   1799 rule_triggered (void *cls,
   1800                 const void *extra,
   1801                 size_t extra_size)
   1802 {
   1803   const char *text = extra;
   1804   const char *space;
   1805   struct TALER_MerchantWireHashP h_wire;
   1806   const char *exchange_url;
   1807 
   1808   (void) cls;
   1809   if ( (NULL == extra) ||
   1810        (0 == extra_size) )
   1811   {
   1812     GNUNET_break (0);
   1813     global_ret = EXIT_FAILURE;
   1814     GNUNET_SCHEDULER_shutdown ();
   1815     return;
   1816   }
   1817   if ('\0' != text[extra_size - 1])
   1818   {
   1819     GNUNET_break (0);
   1820     global_ret = EXIT_FAILURE;
   1821     GNUNET_SCHEDULER_shutdown ();
   1822     return;
   1823   }
   1824   space = memchr (extra,
   1825                   ' ',
   1826                   extra_size);
   1827   if (NULL == space)
   1828   {
   1829     GNUNET_break (0);
   1830     global_ret = EXIT_FAILURE;
   1831     GNUNET_SCHEDULER_shutdown ();
   1832     return;
   1833   }
   1834   if (GNUNET_OK !=
   1835       GNUNET_STRINGS_string_to_data (extra,
   1836                                      space - text,
   1837                                      &h_wire,
   1838                                      sizeof (h_wire)))
   1839   {
   1840     GNUNET_break (0);
   1841     global_ret = EXIT_FAILURE;
   1842     GNUNET_SCHEDULER_shutdown ();
   1843     return;
   1844   }
   1845   exchange_url = &space[1];
   1846   if (! TALER_is_web_url (exchange_url))
   1847   {
   1848     GNUNET_break (0);
   1849     global_ret = EXIT_FAILURE;
   1850     GNUNET_SCHEDULER_shutdown ();
   1851     return;
   1852   }
   1853 
   1854   for (struct Account *a = a_head;
   1855        NULL != a;
   1856        a = a->next)
   1857   {
   1858     if (0 !=
   1859         GNUNET_memcmp (&h_wire,
   1860                        &a->h_wire))
   1861       continue;
   1862     for (struct Inquiry *i = a->i_head;
   1863          NULL != i;
   1864          i = i->next)
   1865     {
   1866       if (0 != strcmp (exchange_url,
   1867                        i->e->keys->exchange_url))
   1868         continue;
   1869       i->kyc_ok = false;
   1870       i->due = GNUNET_TIME_UNIT_ZERO_ABS;
   1871       if (NULL != i->task)
   1872       {
   1873         GNUNET_SCHEDULER_cancel (i->task);
   1874         i->task = NULL;
   1875       }
   1876       if (NULL != i->kyc)
   1877       {
   1878         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1879                     "/kyc-check already running for %s\n",
   1880                     text);
   1881         return;
   1882       }
   1883       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1884                   "Starting %skyc-check for `%s' due to KYC rule trigger\n",
   1885                   exchange_url,
   1886                   i->a->merchant_account_uri.full_payto);
   1887       i->task = GNUNET_SCHEDULER_add_at (i->due,
   1888                                          &inquiry_work,
   1889                                          i);
   1890       return;
   1891     }
   1892   }
   1893   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1894               "KYC rule trigger notification `%s' matches none of our accounts\n",
   1895               text);
   1896 }
   1897 
   1898 
   1899 /**
   1900  * Function called on each configuration section. Finds sections
   1901  * about exchanges, parses the entries.
   1902  *
   1903  * @param cls NULL
   1904  * @param section name of the section
   1905  */
   1906 static void
   1907 accept_exchanges (void *cls,
   1908                   const char *section)
   1909 {
   1910   char *url;
   1911 
   1912   (void) cls;
   1913   if (0 !=
   1914       strncasecmp (section,
   1915                    "merchant-exchange-",
   1916                    strlen ("merchant-exchange-")))
   1917     return;
   1918   if (GNUNET_YES ==
   1919       GNUNET_CONFIGURATION_get_value_yesno (cfg,
   1920                                             section,
   1921                                             "DISABLED"))
   1922     return;
   1923   if (GNUNET_OK !=
   1924       GNUNET_CONFIGURATION_get_value_string (cfg,
   1925                                              section,
   1926                                              "EXCHANGE_BASE_URL",
   1927                                              &url))
   1928   {
   1929     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   1930                                section,
   1931                                "EXCHANGE_BASE_URL");
   1932     global_ret = EXIT_NOTCONFIGURED;
   1933     GNUNET_SCHEDULER_shutdown ();
   1934     return;
   1935   }
   1936   find_keys (url);
   1937   GNUNET_free (url);
   1938 }
   1939 
   1940 
   1941 /**
   1942  * We're being aborted with CTRL-C (or SIGTERM). Shut down.
   1943  *
   1944  * @param cls closure (NULL)
   1945  */
   1946 static void
   1947 shutdown_task (void *cls)
   1948 {
   1949   (void) cls;
   1950   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1951               "Running shutdown\n");
   1952   while (NULL != e_head)
   1953   {
   1954     struct Exchange *e = e_head;
   1955 
   1956     if (NULL != e->keys)
   1957     {
   1958       TALER_EXCHANGE_keys_decref (e->keys);
   1959       e->keys = NULL;
   1960     }
   1961     GNUNET_CONTAINER_DLL_remove (e_head,
   1962                                  e_tail,
   1963                                  e);
   1964     GNUNET_free (e);
   1965   }
   1966   while (NULL != a_head)
   1967   {
   1968     struct Account *a = a_head;
   1969 
   1970     stop_inquiries (a);
   1971     GNUNET_CONTAINER_DLL_remove (a_head,
   1972                                  a_tail,
   1973                                  a);
   1974     GNUNET_free (a->merchant_account_uri.full_payto);
   1975     GNUNET_free (a->instance_id);
   1976     GNUNET_free (a);
   1977   }
   1978   if (NULL != eh_accounts)
   1979   {
   1980     TALER_MERCHANTDB_event_listen_cancel (eh_accounts);
   1981     eh_accounts = NULL;
   1982   }
   1983   if (NULL != account_task)
   1984   {
   1985     GNUNET_SCHEDULER_cancel (account_task);
   1986     account_task = NULL;
   1987   }
   1988   if (NULL != eh_keys)
   1989   {
   1990     TALER_MERCHANTDB_event_listen_cancel (eh_keys);
   1991     eh_keys = NULL;
   1992   }
   1993   if (NULL != eh_rule)
   1994   {
   1995     TALER_MERCHANTDB_event_listen_cancel (eh_rule);
   1996     eh_rule = NULL;
   1997   }
   1998   if (NULL != eh_update_forced)
   1999   {
   2000     TALER_MERCHANTDB_event_listen_cancel (eh_update_forced);
   2001     eh_update_forced = NULL;
   2002   }
   2003   if (NULL != keys_rule)
   2004   {
   2005     TALER_MERCHANTDB_event_listen_cancel (keys_rule);
   2006     keys_rule = NULL;
   2007   }
   2008   if (NULL != pg)
   2009   {
   2010     TALER_MERCHANTDB_disconnect (pg);
   2011     pg = NULL;
   2012   }
   2013   cfg = NULL;
   2014   if (NULL != ctx)
   2015   {
   2016     GNUNET_CURL_fini (ctx);
   2017     ctx = NULL;
   2018   }
   2019   if (NULL != rc)
   2020   {
   2021     GNUNET_CURL_gnunet_rc_destroy (rc);
   2022     rc = NULL;
   2023   }
   2024 }
   2025 
   2026 
   2027 /**
   2028  * Function called when we urgently need to re-check the KYC status
   2029  * of some account. Finds the respective inquiry and re-launches
   2030  * the check, unless we are already doing it.
   2031  *
   2032  * @param cls NULL
   2033  * @param instance_id instance for which to force the check
   2034  * @param exchange_url base URL of the exchange to check
   2035  * @param h_wire hash of the wire account to check KYC status for
   2036  */
   2037 static void
   2038 force_check_now (void *cls,
   2039                  const char *instance_id,
   2040                  const char *exchange_url,
   2041                  const struct TALER_MerchantWireHashP *h_wire)
   2042 {
   2043   for (struct Account *a = a_head;
   2044        NULL != a;
   2045        a = a->next)
   2046   {
   2047     if (0 !=
   2048         strcmp (instance_id,
   2049                 a->instance_id))
   2050       continue;
   2051     if (0 !=
   2052         GNUNET_memcmp (h_wire,
   2053                        &a->h_wire))
   2054       continue;
   2055     for (struct Inquiry *i = a->i_head;
   2056          NULL != i;
   2057          i = i->next)
   2058     {
   2059       if (0 !=
   2060           strcmp (i->e->keys->exchange_url,
   2061                   exchange_url))
   2062         continue;
   2063       /* If we are not actively checking with the exchange, do start
   2064          to check immediately */
   2065       if (NULL == i->kyc)
   2066       {
   2067         i->due = GNUNET_TIME_absolute_get (); /* now! */
   2068         if (NULL != i->task)
   2069           GNUNET_SCHEDULER_cancel (i->task);
   2070         i->task = GNUNET_SCHEDULER_add_at (i->due,
   2071                                            &inquiry_work,
   2072                                            i);
   2073       }
   2074       return;
   2075     }
   2076   }
   2077   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2078               "No inquiry at `%s' for exchange `%s' and h_wire `%s'. Likely the account is not eligible.\n",
   2079               instance_id,
   2080               exchange_url,
   2081               TALER_B2S (h_wire));
   2082   /* In this case, set the due date back to FOREVER */
   2083   flag_ineligible (instance_id,
   2084                    exchange_url,
   2085                    h_wire);
   2086 }
   2087 
   2088 
   2089 /**
   2090  * Function called when a KYC status update was forced by an
   2091  * application checking the KYC status of an account.
   2092  *
   2093  * @param cls closure (NULL)
   2094  * @param extra additional event data provided
   2095  * @param extra_size number of bytes in @a extra
   2096  */
   2097 static void
   2098 update_forced (void *cls,
   2099                const void *extra,
   2100                size_t extra_size)
   2101 {
   2102   enum GNUNET_DB_QueryStatus qs;
   2103 
   2104   (void) cls;
   2105   (void) extra;
   2106   (void) extra_size;
   2107   qs = TALER_MERCHANTDB_iterate_outdated_kyc_statuses (
   2108     pg,
   2109     &force_check_now,
   2110     NULL);
   2111   if (qs < 0)
   2112   {
   2113     GNUNET_break (0);
   2114     global_ret = EXIT_FAILURE;
   2115     GNUNET_SCHEDULER_shutdown ();
   2116     return;
   2117   }
   2118 }
   2119 
   2120 
   2121 /**
   2122  * First task.
   2123  *
   2124  * @param cls closure, NULL
   2125  * @param args remaining command-line arguments
   2126  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
   2127  * @param c configuration
   2128  */
   2129 static void
   2130 run (void *cls,
   2131      char *const *args,
   2132      const char *cfgfile,
   2133      const struct GNUNET_CONFIGURATION_Handle *c)
   2134 {
   2135   (void) args;
   2136   (void) cfgfile;
   2137 
   2138   cfg = c;
   2139   TALER_EXCHANGE_setup (enable_h3
   2140                         ? TALER_EXCHANGE_GO_ENABLE_HTTP3
   2141                         : TALER_EXCHANGE_GO_FORCE_HTTP1_1);
   2142   if (GNUNET_OK !=
   2143       GNUNET_CONFIGURATION_get_value_time (cfg,
   2144                                            "merchant-kyccheck",
   2145                                            "AML_FREQ",
   2146                                            &aml_freq))
   2147   {
   2148     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
   2149                                "merchant-kyccheck",
   2150                                "AML_FREQ");
   2151     /* use default */
   2152     aml_freq = AML_FREQ;
   2153   }
   2154   if (GNUNET_OK !=
   2155       GNUNET_CONFIGURATION_get_value_time (cfg,
   2156                                            "merchant-kyccheck",
   2157                                            "AML_LOW_FREQ",
   2158                                            &aml_low_freq))
   2159   {
   2160     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
   2161                                "merchant-kyccheck",
   2162                                "AML_LOW_FREQ");
   2163     /* use default */
   2164     aml_low_freq = AML_LOW_FREQ;
   2165   }
   2166   if (GNUNET_TIME_relative_cmp (aml_low_freq,
   2167                                 <,
   2168                                 aml_freq))
   2169   {
   2170     aml_low_freq = GNUNET_TIME_relative_multiply (aml_freq,
   2171                                                   10);
   2172     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2173                 "AML_LOW_FREQ was set to less than AML_FREQ. Using %s instead\n",
   2174                 GNUNET_TIME_relative2s (aml_low_freq,
   2175                                         true));
   2176   }
   2177   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
   2178                                  NULL);
   2179   ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
   2180                           &rc);
   2181   if (NULL == ctx)
   2182   {
   2183     GNUNET_break (0);
   2184     GNUNET_SCHEDULER_shutdown ();
   2185     global_ret = EXIT_FAILURE;
   2186     return;
   2187   }
   2188   rc = GNUNET_CURL_gnunet_rc_create (ctx);
   2189   if (NULL ==
   2190       (pg = TALER_MERCHANTDB_connect (cfg)))
   2191   {
   2192     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2193                 "Failed to initialize DB subsystem. Consider running taler-merchant-dbconfig.\n");
   2194     GNUNET_SCHEDULER_shutdown ();
   2195     global_ret = EXIT_FAILURE;
   2196     return;
   2197   }
   2198   {
   2199     struct GNUNET_DB_EventHeaderP es = {
   2200       .size = htons (sizeof (es)),
   2201       .type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KEYS)
   2202     };
   2203 
   2204     eh_keys
   2205       = TALER_MERCHANTDB_event_listen (pg,
   2206                                        &es,
   2207                                        GNUNET_TIME_UNIT_FOREVER_REL,
   2208                                        &keys_changed,
   2209                                        NULL);
   2210   }
   2211   {
   2212     struct GNUNET_DB_EventHeaderP es = {
   2213       .size = htons (sizeof (es)),
   2214       .type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_UPDATE_FORCED)
   2215     };
   2216 
   2217     eh_update_forced
   2218       = TALER_MERCHANTDB_event_listen (pg,
   2219                                        &es,
   2220                                        GNUNET_TIME_UNIT_FOREVER_REL,
   2221                                        &update_forced,
   2222                                        NULL);
   2223   }
   2224   {
   2225     struct GNUNET_DB_EventHeaderP es = {
   2226       .size = htons (sizeof (es)),
   2227       .type = htons (TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_RULE_TRIGGERED)
   2228     };
   2229 
   2230     eh_rule
   2231       = TALER_MERCHANTDB_event_listen (pg,
   2232                                        &es,
   2233                                        GNUNET_TIME_UNIT_FOREVER_REL,
   2234                                        &rule_triggered,
   2235                                        NULL);
   2236   }
   2237   GNUNET_CONFIGURATION_iterate_sections (cfg,
   2238                                          &accept_exchanges,
   2239                                          NULL);
   2240   {
   2241     struct GNUNET_DB_EventHeaderP es = {
   2242       .size = htons (sizeof (es)),
   2243       .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED)
   2244     };
   2245 
   2246     eh_accounts
   2247       = TALER_MERCHANTDB_event_listen (pg,
   2248                                        &es,
   2249                                        GNUNET_TIME_UNIT_FOREVER_REL,
   2250                                        &account_changed,
   2251                                        NULL);
   2252   }
   2253   GNUNET_assert (NULL == account_task);
   2254   account_task
   2255     = GNUNET_SCHEDULER_add_now (&find_accounts,
   2256                                 NULL);
   2257 }
   2258 
   2259 
   2260 /**
   2261  * The main function of taler-merchant-kyccheck
   2262  *
   2263  * @param argc number of arguments from the command line
   2264  * @param argv command line arguments
   2265  * @return 0 ok, 1 on error
   2266  */
   2267 int
   2268 main (int argc,
   2269       char *const *argv)
   2270 {
   2271   struct GNUNET_GETOPT_CommandLineOption options[] = {
   2272     GNUNET_GETOPT_option_flag ('3',
   2273                                "http3",
   2274                                "enable support for HTTP/2 and HTTP/3",
   2275                                &enable_h3),
   2276     GNUNET_GETOPT_option_timetravel ('T',
   2277                                      "timetravel"),
   2278     GNUNET_GETOPT_option_flag ('t',
   2279                                "test",
   2280                                "run in test mode and exit when idle",
   2281                                &test_mode),
   2282     GNUNET_GETOPT_option_version (VERSION),
   2283     GNUNET_GETOPT_OPTION_END
   2284   };
   2285   enum GNUNET_GenericReturnValue ret;
   2286 
   2287   ret = GNUNET_PROGRAM_run (
   2288     TALER_MERCHANT_project_data (),
   2289     argc, argv,
   2290     "taler-merchant-kyccheck",
   2291     gettext_noop (
   2292       "background process that checks the KYC state of our bank accounts at various exchanges"),
   2293     options,
   2294     &run, NULL);
   2295   if (GNUNET_SYSERR == ret)
   2296     return EXIT_INVALIDARGUMENT;
   2297   if (GNUNET_NO == ret)
   2298     return EXIT_SUCCESS;
   2299   return global_ret;
   2300 }
   2301 
   2302 
   2303 /* end of taler-merchant-kyccheck.c */