merchant

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

taler-merchant-kyccheck.c (67663B)


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