merchant

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

taler-merchant-kyccheck.c (61175B)


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