summaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_kyc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange/taler-exchange-httpd_kyc.c')
-rw-r--r--src/exchange/taler-exchange-httpd_kyc.c1019
1 files changed, 0 insertions, 1019 deletions
diff --git a/src/exchange/taler-exchange-httpd_kyc.c b/src/exchange/taler-exchange-httpd_kyc.c
deleted file mode 100644
index ea90c08a6..000000000
--- a/src/exchange/taler-exchange-httpd_kyc.c
+++ /dev/null
@@ -1,1019 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-exchange-httpd_kyc.c
- * @brief KYC API for the exchange
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler-exchange-httpd.h"
-#include "taler-exchange-httpd_kyc.h"
-#include "taler_exchangedb_plugin.h"
-
-/**
- * Information about a KYC provider.
- */
-struct TEH_KycProvider;
-
-
-/**
- * Abstract representation of a KYC check.
- */
-struct TEH_KycCheck
-{
- /**
- * Human-readable name given to the KYC check.
- */
- char *name;
-
- /**
- * Array of @e num_providers providers that offer this type of KYC check.
- */
- struct TEH_KycProvider **providers;
-
- /**
- * Length of the @e providers array.
- */
- unsigned int num_providers;
-
-};
-
-
-struct TEH_KycProvider
-{
- /**
- * Name of the provider (configuration section name).
- */
- const char *provider_section_name;
-
- /**
- * Array of @e num_checks checks performed by this provider.
- */
- struct TEH_KycCheck **provided_checks;
-
- /**
- * Logic to run for this provider.
- */
- struct TALER_KYCLOGIC_Plugin *logic;
-
- /**
- * @e provider_section_name specific details to
- * pass to the @e logic functions.
- */
- struct TALER_KYCLOGIC_ProviderDetails *pd;
-
- /**
- * Cost of running this provider's KYC.
- */
- unsigned long long cost;
-
- /**
- * Length of the @e checks array.
- */
- unsigned int num_checks;
-
- /**
- * Type of user this provider supports.
- */
- enum TEH_KycUserType user_type;
-};
-
-
-/**
- * Condition that triggers a need to perform KYC.
- */
-struct TEH_KycTrigger
-{
-
- /**
- * Timeframe to consider for computing the amount
- * to compare against the @e limit. Zero for the
- * wallet balance trigger (as not applicable).
- */
- struct GNUNET_TIME_Relative timeframe;
-
- /**
- * Maximum amount that can be transacted until
- * the rule triggers.
- */
- struct TALER_Amount threshold;
-
- /**
- * Array of @e num_checks checks to apply on this trigger.
- */
- struct TEH_KycCheck **required_checks;
-
- /**
- * Length of the @e checks array.
- */
- unsigned int num_checks;
-
- /**
- * What event is this trigger for?
- */
- enum TEH_KycTriggerEvent trigger;
-
-};
-
-
-/**
- * Array of @e num_kyc_logics KYC logic plugins we have loaded.
- */
-static struct TALER_KYCLOGIC_Plugin **kyc_logics;
-
-/**
- * Length of the #kyc_logics array.
- */
-static unsigned int num_kyc_logics;
-
-/**
- * Array of @e num_kyc_checks known types of
- * KYC checks.
- */
-static struct TEH_KycCheck **kyc_checks;
-
-/**
- * Length of the #kyc_checks array.
- */
-static unsigned int num_kyc_checks;
-
-/**
- * Array of configured triggers.
- */
-static struct TEH_KycTrigger **kyc_triggers;
-
-/**
- * Length of the #kyc_triggers array.
- */
-static unsigned int num_kyc_triggers;
-
-/**
- * Array of configured providers.
- */
-static struct TEH_KycProvider **kyc_providers;
-
-/**
- * Length of the #kyc_providers array.
- */
-static unsigned int num_kyc_providers;
-
-
-enum GNUNET_GenericReturnValue
-TEH_kyc_trigger_from_string (const char *trigger_s,
- enum TEH_KycTriggerEvent *trigger)
-{
- struct
- {
- const char *in;
- enum TEH_KycTriggerEvent out;
- } map [] = {
- { "withdraw", TEH_KYC_TRIGGER_WITHDRAW },
- { "deposit", TEH_KYC_TRIGGER_DEPOSIT },
- { "merge", TEH_KYC_TRIGGER_P2P_RECEIVE },
- { "balance", TEH_KYC_TRIGGER_WALLET_BALANCE },
- { NULL, 0 }
- };
-
- for (unsigned int i = 0; NULL != map[i].in; i++)
- if (0 == strcasecmp (map[i].in,
- trigger_s))
- {
- *trigger = map[i].out;
- return GNUNET_OK;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Invalid KYC trigger `%s'\n",
- trigger_s);
- return GNUNET_SYSERR;
-}
-
-
-const char *
-TEH_kyc_trigger2s (enum TEH_KycTriggerEvent trigger)
-{
- switch (trigger)
- {
- case TEH_KYC_TRIGGER_WITHDRAW:
- return "withdraw";
- case TEH_KYC_TRIGGER_DEPOSIT:
- return "deposit";
- case TEH_KYC_TRIGGER_P2P_RECEIVE:
- return "merge";
- case TEH_KYC_TRIGGER_WALLET_BALANCE:
- return "balance";
- }
- GNUNET_break (0);
- return NULL;
-}
-
-
-enum GNUNET_GenericReturnValue
-TEH_kyc_user_type_from_string (const char *ut_s,
- enum TEH_KycUserType *ut)
-{
- struct
- {
- const char *in;
- enum TEH_KycTriggerEvent out;
- } map [] = {
- { "individual", TEH_KYC_UT_INDIVIDUAL },
- { "business", TEH_KYC_UT_BUSINESS },
- { NULL, 0 }
- };
-
- for (unsigned int i = 0; NULL != map[i].in; i++)
- if (0 == strcasecmp (map[i].in,
- ut_s))
- {
- *ut = map[i].out;
- return GNUNET_OK;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Invalid user type `%s'\n",
- ut_s);
- return GNUNET_SYSERR;
-}
-
-
-const char *
-TEH_kyc_user_type2s (enum TEH_KycUserType ut)
-{
- switch (ut)
- {
- case TEH_KYC_UT_INDIVIDUAL:
- return "individual";
- case TEH_KYC_UT_BUSINESS:
- return "business";
- }
- GNUNET_break (0);
- return NULL;
-}
-
-
-/**
- * Load KYC logic plugin.
- *
- * @param name name of the plugin
- * @return NULL on error
- */
-static struct TALER_KYCLOGIC_Plugin *
-load_logic (const char *name)
-{
- char *lib_name;
- struct TALER_KYCLOGIC_Plugin *plugin;
-
- GNUNET_asprintf (&lib_name,
- "libtaler_plugin_kyclogic_%s",
- name);
- plugin = GNUNET_PLUGIN_load (lib_name,
- (void *) TEH_cfg);
- if (NULL != plugin)
- plugin->library_name = lib_name;
- else
- GNUNET_free (lib_name);
- return plugin;
-}
-
-
-/**
- * Add check type to global array of checks.
- * First checks if the type already exists, otherwise
- * adds a new one.
- *
- * @param check name of the check
- * @return pointer into the global list
- */
-static struct TEH_KycCheck *
-add_check (const char *check)
-{
- struct TEH_KycCheck *kc;
-
- for (unsigned int i = 0; i<num_kyc_checks; i++)
- if (0 == strcasecmp (check,
- kyc_checks[i]->name))
- return kyc_checks[i];
- kc = GNUNET_new (struct TEH_KycCheck);
- kc->name = GNUNET_strdup (check);
- GNUNET_array_append (kyc_checks,
- num_kyc_checks,
- kc);
- return kc;
-}
-
-
-/**
- * Parse list of checks from @a checks and build an
- * array of aliases into the global checks array
- * in @a provided_checks.
- *
- * @param[in,out] checks list of checks; clobbered
- * @param[out] p_checks where to put array of aliases
- * @param[out] num_p_checks set to length of @a p_checks array
- */
-static void
-add_checks (char *checks,
- struct TEH_KycCheck ***p_checks,
- unsigned int *num_p_checks)
-{
- char *sptr;
- struct TEH_KycCheck **rchecks = NULL;
- unsigned int num_rchecks = 0;
-
- for (char *tok = strtok_r (checks, " ", &sptr);
- NULL != tok;
- tok = strtok_r (NULL, " ", &sptr))
- {
- struct TEH_KycCheck *kc;
-
- kc = add_check (tok);
- GNUNET_array_append (rchecks,
- num_rchecks,
- kc);
- }
- *p_checks = rchecks;
- *num_p_checks = num_rchecks;
-}
-
-
-/**
- * Parse configuration of a KYC provider.
- *
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-add_provider (const char *section)
-{
- unsigned long long cost;
- char *logic;
- char *ut_s;
- enum TEH_KycUserType ut;
- char *checks;
- struct TALER_KYCLOGIC_Plugin *lp;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (TEH_cfg,
- section,
- "COST",
- &cost))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "COST",
- "number required");
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
- section,
- "USER_TYPE",
- &ut_s))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "USER_TYPE");
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TEH_kyc_user_type_from_string (ut_s,
- &ut))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "USER_TYPE",
- "valid user type required");
- GNUNET_free (ut_s);
- return GNUNET_SYSERR;
- }
- GNUNET_free (ut_s);
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
- section,
- "LOGIC",
- &logic))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "LOGIC");
- return GNUNET_SYSERR;
- }
- lp = load_logic (logic);
- if (NULL == lp)
- {
- GNUNET_free (logic);
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "LOGIC",
- "logic plugin could not be loaded");
- return GNUNET_SYSERR;
- }
- GNUNET_free (logic);
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
- section,
- "PROVIDED_CHECKS",
- &checks))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "PROVIDED_CHECKS");
- return GNUNET_SYSERR;
- }
- {
- struct TEH_KycProvider *kp;
-
- kp = GNUNET_new (struct TEH_KycProvider);
- kp->provider_section_name = section;
- kp->user_type = ut;
- kp->logic = lp;
- kp->cost = cost;
- add_checks (checks,
- &kp->provided_checks,
- &kp->num_checks);
- GNUNET_free (checks);
- kp->pd = lp->load_configuration (lp->cls,
- section);
- if (NULL == kp->pd)
- {
- GNUNET_free (kp);
- return GNUNET_SYSERR;
- }
- GNUNET_array_append (kyc_providers,
- num_kyc_providers,
- kp);
- for (unsigned int i = 0; i<kp->num_checks; i++)
- {
- struct TEH_KycCheck *kc = kp->provided_checks[i];
-
- GNUNET_array_append (kc->providers,
- kc->num_providers,
- kp);
- }
- }
- return GNUNET_OK;
-}
-
-
-static enum GNUNET_GenericReturnValue
-add_trigger (const char *section)
-{
- char *ot_s;
- struct TALER_Amount threshold;
- struct GNUNET_TIME_Relative timeframe;
- char *checks;
- enum TEH_KycTriggerEvent ot;
-
- if (GNUNET_OK !=
- TALER_config_get_amount (TEH_cfg,
- section,
- "THRESHOLD",
- &threshold))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "THRESHOLD",
- "amount required");
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
- section,
- "OPERATION_TYPE",
- &ot_s))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "OPERATION_TYPE");
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TEH_kyc_trigger_from_string (ot_s,
- &ot))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "OPERATION_TYPE",
- "valid trigger type required");
- GNUNET_free (ot_s);
- return GNUNET_SYSERR;
- }
- GNUNET_free (ot_s);
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (TEH_cfg,
- section,
- "TIMEFRAME",
- &timeframe))
- {
- if (TEH_KYC_TRIGGER_WALLET_BALANCE == ot)
- {
- timeframe = GNUNET_TIME_UNIT_ZERO;
- }
- else
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section,
- "TIMEFRAME",
- "duration required");
- return GNUNET_SYSERR;
- }
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
- section,
- "REQUIRED_CHECKS",
- &checks))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- section,
- "REQUIRED_CHECKS");
- return GNUNET_SYSERR;
- }
-
- {
- struct TEH_KycTrigger *kt;
-
- kt = GNUNET_new (struct TEH_KycTrigger);
- kt->timeframe = timeframe;
- kt->threshold = threshold;
- kt->trigger = ot;
- add_checks (checks,
- &kt->required_checks,
- &kt->num_checks);
- GNUNET_free (checks);
- GNUNET_array_append (kyc_triggers,
- num_kyc_triggers,
- kt);
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function to iterate over configuration sections.
- *
- * @param cls closure, `boolean *`, set to false on failure
- * @param section name of the section
- */
-static void
-handle_section (void *cls,
- const char *section)
-{
- bool *ok = cls;
-
- if (0 == strncasecmp (section,
- "kyc-provider-",
- strlen ("kyc-provider-")))
- {
- if (GNUNET_OK !=
- add_provider (section))
- *ok = false;
- return;
- }
- if (0 == strncasecmp (section,
- "kyc-legitimization-",
- strlen ("kyc-legitimization-")))
- {
- if (GNUNET_OK !=
- add_trigger (section))
- *ok = false;
- return;
- }
-}
-
-
-/**
- * Comparator for qsort. Compares two triggers
- * by timeframe to sort triggers by time.
- *
- * @param p1 first trigger to compare
- * @param p2 second trigger to compare
- * @return -1 if p1 < p2, 0 if p1==p2, 1 if p1 > p2.
- */
-static int
-sort_by_timeframe (const void *p1,
- const void *p2)
-{
- struct TEH_KycTrigger **t1 = (struct TEH_KycTrigger **) p1;
- struct TEH_KycTrigger **t2 = (struct TEH_KycTrigger **) p2;
-
- if (GNUNET_TIME_relative_cmp ((*t1)->timeframe,
- <,
- (*t2)->timeframe))
- return -1;
- if (GNUNET_TIME_relative_cmp ((*t1)->timeframe,
- >,
- (*t2)->timeframe))
- return 1;
- return 0;
-}
-
-
-enum GNUNET_GenericReturnValue
-TEH_kyc_init (void)
-{
- bool ok = true;
-
- GNUNET_CONFIGURATION_iterate_sections (TEH_cfg,
- &handle_section,
- &ok);
- if (! ok)
- {
- TEH_kyc_done ();
- return GNUNET_SYSERR;
- }
-
- /* sanity check: ensure at least one provider exists
- for any trigger and indidivual or business. */
- for (unsigned int i = 0; i<num_kyc_checks; i++)
- if (0 == kyc_checks[i]->num_providers)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "No provider available for required KYC check `%s'\n",
- kyc_checks[i]->name);
- TEH_kyc_done ();
- return GNUNET_SYSERR;
- }
- qsort (kyc_triggers,
- num_kyc_triggers,
- sizeof (struct TEH_KycTrigger *),
- &sort_by_timeframe);
- return GNUNET_OK;
-}
-
-
-void
-TEH_kyc_done (void)
-{
- for (unsigned int i = 0; i<num_kyc_triggers; i++)
- {
- struct TEH_KycTrigger *kt = kyc_triggers[i];
-
- GNUNET_array_grow (kt->required_checks,
- kt->num_checks,
- 0);
- GNUNET_free (kt);
- }
- GNUNET_array_grow (kyc_triggers,
- num_kyc_triggers,
- 0);
- for (unsigned int i = 0; i<num_kyc_providers; i++)
- {
- struct TEH_KycProvider *kp = kyc_providers[i];
-
- kp->logic->unload_configuration (kp->pd);
- GNUNET_array_grow (kp->provided_checks,
- kp->num_checks,
- 0);
- GNUNET_free (kp);
- }
- GNUNET_array_grow (kyc_providers,
- num_kyc_providers,
- 0);
- for (unsigned int i = 0; i<num_kyc_logics; i++)
- {
- struct TALER_KYCLOGIC_Plugin *lp = kyc_logics[i];
- char *lib_name = lp->library_name;
-
- GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name,
- lp));
- GNUNET_free (lib_name);
- }
- GNUNET_array_grow (kyc_logics,
- num_kyc_logics,
- 0);
- for (unsigned int i = 0; i<num_kyc_checks; i++)
- {
- struct TEH_KycCheck *kc = kyc_checks[i];
-
- GNUNET_free (kc->name);
- GNUNET_free (kc);
- }
- GNUNET_array_grow (kyc_checks,
- num_kyc_checks,
- 0);
-}
-
-
-/**
- * Closure for the #eval_trigger().
- */
-struct ThresholdTestContext
-{
- /**
- * Total amount so far.
- */
- struct TALER_Amount total;
-
- /**
- * Trigger event to evaluate triggers of.
- */
- enum TEH_KycTriggerEvent event;
-
- /**
- * Offset in the triggers array where we need to start
- * checking for triggers. All trigges below this
- * offset were already hit.
- */
- unsigned int start;
-
- /**
- * Array of checks needed so far.
- */
- struct TEH_KycCheck **needed;
-
- /**
- * Pointer to number of entries used in @a needed.
- */
- unsigned int *needed_cnt;
-
-};
-
-
-/**
- * Function called on each @a amount that was found to
- * be relevant for a KYC check.
- *
- * @param cls closure to allow the KYC module to
- * total up amounts and evaluate rules
- * @param amount encountered transaction amount
- * @param date when was the amount encountered
- * @return #GNUNET_OK to continue to iterate,
- * #GNUNET_NO to abort iteration
- * #GNUNET_SYSERR on internal error (also abort itaration)
- */
-static enum GNUNET_GenericReturnValue
-eval_trigger (void *cls,
- const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute date)
-{
- struct ThresholdTestContext *ttc = cls;
- struct GNUNET_TIME_Relative duration;
- bool bump = true;
-
- duration = GNUNET_TIME_absolute_get_duration (date);
- if (0 >
- TALER_amount_add (&ttc->total,
- &ttc->total,
- amount))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- for (unsigned int i = ttc->start; i<num_kyc_triggers; i++)
- {
- const struct TEH_KycTrigger *kt = kyc_triggers[i];
-
- if (ttc->event != kt->trigger)
- continue;
- duration = GNUNET_TIME_relative_max (duration,
- kt->timeframe);
- if (GNUNET_TIME_relative_cmp (kt->timeframe,
- >,
- duration))
- {
- if (bump)
- ttc->start = i;
- return GNUNET_OK;
- }
- if (-1 ==
- TALER_amount_cmp (&ttc->total,
- &kt->threshold))
- {
- if (bump)
- ttc->start = i;
- bump = false;
- continue; /* amount too low to trigger */
- }
- /* add check to list of required checks, unless
- already present... */
- for (unsigned int j = 0; j<kt->num_checks; j++)
- {
- struct TEH_KycCheck *rc = kt->required_checks[j];
- bool found = false;
-
- for (unsigned int k = 0; k<*ttc->needed_cnt; k++)
- if (ttc->needed[k] == rc)
- {
- found = true;
- break;
- }
- if (! found)
- {
- ttc->needed[*ttc->needed_cnt] = rc;
- (*ttc->needed_cnt)++;
- }
- }
- }
- if (bump)
- return GNUNET_NO; /* we hit all possible triggers! */
- return GNUNET_OK;
-}
-
-
-/**
- * Closure for the #remove_satisfied().
- */
-struct RemoveContext
-{
-
- /**
- * Array of checks needed so far.
- */
- struct TEH_KycCheck **needed;
-
- /**
- * Pointer to number of entries used in @a needed.
- */
- unsigned int *needed_cnt;
-
-};
-
-
-/**
- * Remove all checks satisfied by @a provider_name from
- * our list of checks.
- *
- * @param cls a `struct RemoveContext`
- * @param provider_name section name of provider that was already run previously
- */
-static void
-remove_satisfied (void *cls,
- const char *provider_name)
-{
- struct RemoveContext *rc = cls;
-
- for (unsigned int i = 0; i<num_kyc_providers; i++)
- {
- const struct TEH_KycProvider *kp = kyc_providers[i];
-
- if (0 != strcasecmp (provider_name,
- kp->provider_section_name))
- continue;
- for (unsigned int j = 0; j<kp->num_checks; j++)
- {
- const struct TEH_KycCheck *kc = kp->provided_checks[j];
-
- for (unsigned int k = 0; k<*rc->needed_cnt; k++)
- if (kc == rc->needed[k])
- {
- rc->needed[k] = rc->needed[*rc->needed_cnt - 1];
- (*rc->needed_cnt)--;
- if (0 == *rc->needed_cnt)
- return; /* for sure finished */
- break;
- }
- }
- break;
- }
-}
-
-
-const char *
-TEH_kyc_test_required (enum TEH_KycTriggerEvent event,
- const struct TALER_PaytoHashP *h_payto,
- TEH_KycAmountIterator ai,
- void *ai_cls)
-{
- struct TEH_KycCheck *needed[num_kyc_checks];
- unsigned int needed_cnt = 0;
- struct GNUNET_TIME_Relative timeframe;
- unsigned long long min_cost = ULONG_LONG_MAX;
- unsigned int max_checks = 0;
- const struct TEH_KycProvider *kp_best = NULL;
-
- timeframe = GNUNET_TIME_UNIT_ZERO;
- for (unsigned int i = 0; i<num_kyc_triggers; i++)
- {
- const struct TEH_KycTrigger *kt = kyc_triggers[i];
-
- if (event != kt->trigger)
- continue;
- timeframe = GNUNET_TIME_relative_max (timeframe,
- kt->timeframe);
- }
- {
- struct GNUNET_TIME_Absolute now;
- struct ThresholdTestContext ttc = {
- .event = event,
- .needed = needed,
- .needed_cnt = &needed_cnt
- };
-
- TALER_amount_set_zero (TEH_currency,
- &ttc.total);
- now = GNUNET_TIME_absolute_get ();
- ai (ai_cls,
- GNUNET_TIME_absolute_subtract (now,
- timeframe),
- &eval_trigger,
- &ttc);
- }
- if (0 == needed_cnt)
- return NULL;
- {
- struct RemoveContext rc = {
- .needed = needed,
- .needed_cnt = &needed_cnt
- };
- enum GNUNET_DB_QueryStatus qs;
-
- /* Check what provider checks are already satisfied for h_payto (with
- database), remove those from the 'needed' array. */
- GNUNET_break (0);
- qs = TEH_plugin->select_satisfied_kyc_processes (TEH_plugin->cls,
- h_payto,
- &remove_satisfied,
- &rc);
- GNUNET_break (qs >= 0); // FIXME: handle DB failure more nicely?
- }
-
- /* Count maximum number of remaining checks covered by any
- provider */
- for (unsigned int i = 0; i<num_kyc_providers; i++)
- {
- const struct TEH_KycProvider *kp = kyc_providers[i];
- unsigned int matched = 0;
-
- for (unsigned int j = 0; j<kp->num_checks; j++)
- {
- const struct TEH_KycCheck *kc = kp->provided_checks[j];
-
- for (unsigned int k = 0; k<needed_cnt; k++)
- if (kc == needed[k])
- {
- matched++;
- break;
- }
- }
- max_checks = GNUNET_MAX (max_checks,
- matched);
- }
-
- /* Find min-cost provider covering max_checks. */
- for (unsigned int i = 0; i<num_kyc_providers; i++)
- {
- const struct TEH_KycProvider *kp = kyc_providers[i];
- unsigned int matched = 0;
-
- for (unsigned int j = 0; j<kp->num_checks; j++)
- {
- const struct TEH_KycCheck *kc = kp->provided_checks[j];
-
- for (unsigned int k = 0; k<needed_cnt; k++)
- if (kc == needed[k])
- {
- matched++;
- break;
- }
- }
- if ( (max_checks == matched) &&
- (kp->cost < min_cost) )
- {
- min_cost = kp->cost;
- kp_best = kp;
- }
- }
-
- GNUNET_assert (NULL != kp_best);
- return kp_best->provider_section_name;
-}
-
-
-enum GNUNET_GenericReturnValue
-TEH_kyc_get_logic (const char *provider_section_name,
- struct TALER_KYCLOGIC_Plugin **plugin,
- struct TALER_KYCLOGIC_ProviderDetails **pd)
-{
- for (unsigned int i = 0; i<num_kyc_providers; i++)
- {
- struct TEH_KycProvider *kp = kyc_providers[i];
-
- if (0 !=
- strcasecmp (provider_section_name,
- kp->provider_section_name))
- continue;
- *plugin = kp->logic;
- *pd = kp->pd;
- return GNUNET_OK;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Provider `%s' unknown\n",
- provider_section_name);
- return GNUNET_SYSERR;
-}
-
-
-/* end of taler-exchange-httpd_kyc.c */