exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 4571665a1340be1cbdeda4988c2f94b5b617daec
parent 578f3dc30c7ce3f65578067638c9999e530f2b81
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 14 May 2024 09:57:40 +0200

implement kyc_test_required

Diffstat:
Msrc/exchange/taler-exchange-aggregator.c | 8+++++---
Msrc/exchange/taler-exchange-httpd_kyc-wallet.c | 13+++++++++----
Msrc/exchange/taler-exchange-httpd_purses_merge.c | 16++++++++++------
Msrc/exchange/taler-exchange-httpd_reserves_close.c | 6++++--
Msrc/exchange/taler-exchange-httpd_reserves_purse.c | 18+++++++++++-------
Msrc/exchange/taler-exchange-httpd_withdraw.c | 18+++++++++++-------
Msrc/include/taler_kyclogic_lib.h | 11++++++-----
Msrc/kyclogic/kyclogic_api.c | 535++++++++++++++++++++++++++++++-------------------------------------------------
Msrc/kyclogic/taler-exchange-kyc-tester.c | 17+++++++++++------
9 files changed, 269 insertions(+), 373 deletions(-)

diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c @@ -459,8 +459,9 @@ trigger_wire_transfer (const struct AggregationUnit *au_active) * @param limit time limit for the iteration * @param cb function to call with the amounts * @param cb_cls closure for @a cb + * @return transaction status */ -static void +static enum GNUNET_DB_QueryStatus return_relevant_amounts (void *cls, struct GNUNET_TIME_Absolute limit, TALER_EXCHANGEDB_KycAmountCallback cb, @@ -476,7 +477,7 @@ return_relevant_amounts (void *cls, cb (cb_cls, &au_active->total_amount, GNUNET_TIME_absolute_get ())) - return; + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; qs = db_plugin->select_aggregation_amounts_for_kyc_check ( db_plugin->cls, &au_active->h_payto, @@ -488,6 +489,7 @@ return_relevant_amounts (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to select aggregation amounts for KYC limit check!\n"); } + return qs; } @@ -501,7 +503,7 @@ static bool legitimization_satisfied (struct AggregationUnit *au_active) { struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs = NULL; - struct TALER_KYCLOGIC_KycRule *requirement; + const struct TALER_KYCLOGIC_KycRule *requirement; enum GNUNET_DB_QueryStatus qs; json_t *jrule; diff --git a/src/exchange/taler-exchange-httpd_kyc-wallet.c b/src/exchange/taler-exchange-httpd_kyc-wallet.c @@ -73,18 +73,23 @@ struct KycRequestContext * order * @param cb_cls closure for @a cb */ -static void +static enum GNUNET_DB_QueryStatus balance_iterator (void *cls, struct GNUNET_TIME_Absolute limit, TALER_EXCHANGEDB_KycAmountCallback cb, void *cb_cls) { struct KycRequestContext *krc = cls; + enum GNUNET_GenericReturnValue ret; (void) limit; - cb (cb_cls, - &krc->balance, - GNUNET_TIME_absolute_get ()); + ret = cb (cb_cls, + &krc->balance, + GNUNET_TIME_absolute_get ()); + GNUNET_break (GNUNET_SYSERR != ret); + if (GNUNET_OK != ret) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; } diff --git a/src/exchange/taler-exchange-httpd_purses_merge.c b/src/exchange/taler-exchange-httpd_purses_merge.c @@ -230,21 +230,24 @@ reply_merge_success (struct MHD_Connection *connection, * events must be returned in reverse chronological * order * @param cb_cls closure for @a cb + * @return transaction status */ -static void +static enum GNUNET_DB_QueryStatus amount_iterator (void *cls, struct GNUNET_TIME_Absolute limit, TALER_EXCHANGEDB_KycAmountCallback cb, void *cb_cls) { struct PurseMergeContext *pcc = cls; + enum GNUNET_GenericReturnValue ret; enum GNUNET_DB_QueryStatus qs; - if (GNUNET_OK != - cb (cb_cls, - &pcc->target_amount, - GNUNET_TIME_absolute_get ())) - return; + ret = cb (cb_cls, + &pcc->target_amount, + GNUNET_TIME_absolute_get ()); + GNUNET_break (GNUNET_SYSERR != ret); + if (GNUNET_OK != ret) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; qs = TEH_plugin->select_merge_amounts_for_kyc_check ( TEH_plugin->cls, &pcc->h_payto, @@ -256,6 +259,7 @@ amount_iterator (void *cls, qs, (unsigned long long) limit.abs_value_us); GNUNET_break (qs >= 0); + return qs; } diff --git a/src/exchange/taler-exchange-httpd_reserves_close.c b/src/exchange/taler-exchange-httpd_reserves_close.c @@ -131,8 +131,9 @@ reply_reserve_close_success (struct MHD_Connection *connection, * events must be returned in reverse chronological * order * @param cb_cls closure for @a cb + * @return transaction status */ -static void +static enum GNUNET_DB_QueryStatus amount_it (void *cls, struct GNUNET_TIME_Absolute limit, TALER_EXCHANGEDB_KycAmountCallback cb, @@ -146,7 +147,7 @@ amount_it (void *cls, GNUNET_TIME_absolute_get ()); GNUNET_break (GNUNET_SYSERR != ret); if (GNUNET_OK != ret) - return; + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; rcc->qs = TEH_plugin->iterate_reserve_close_info ( TEH_plugin->cls, @@ -154,6 +155,7 @@ amount_it (void *cls, limit, cb, cb_cls); + return rcc->qs; } diff --git a/src/exchange/taler-exchange-httpd_reserves_purse.c b/src/exchange/taler-exchange-httpd_reserves_purse.c @@ -143,8 +143,9 @@ struct ReservePurseContext * events must be returned in reverse chronological * order * @param cb_cls closure for @a cb + * @return transaction status */ -static void +static enum GNUNET_DB_QueryStatus amount_iterator (void *cls, struct GNUNET_TIME_Absolute limit, TALER_EXCHANGEDB_KycAmountCallback cb, @@ -152,12 +153,14 @@ amount_iterator (void *cls, { struct ReservePurseContext *rpc = cls; enum GNUNET_DB_QueryStatus qs; - - if (GNUNET_OK != - cb (cb_cls, - &rpc->deposit_total, - GNUNET_TIME_absolute_get ())) - return; + enum GNUNET_GenericReturnValue ret; + + ret = cb (cb_cls, + &rpc->deposit_total, + GNUNET_TIME_absolute_get ()); + GNUNET_break (GNUNET_SYSERR != ret); + if (GNUNET_OK != ret) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; qs = TEH_plugin->select_merge_amounts_for_kyc_check ( TEH_plugin->cls, &rpc->h_payto, @@ -169,6 +172,7 @@ amount_iterator (void *cls, qs, (unsigned long long) limit.abs_value_us); GNUNET_break (qs >= 0); + return qs; } diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c @@ -47,7 +47,7 @@ TEH_legitimization_check ( void *ai_cls) { struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs = NULL; - struct TALER_KYCLOGIC_KycRule *requirement; + const struct TALER_KYCLOGIC_KycRule *requirement; enum GNUNET_DB_QueryStatus qs; { @@ -165,8 +165,9 @@ struct WithdrawContext * @param cb function to call on each event found, events must be returned * in reverse chronological order * @param cb_cls closure for @a cb, of type struct AgeWithdrawContext + * @return transaction status */ -static void +static enum GNUNET_DB_QueryStatus withdraw_amount_cb ( void *cls, struct GNUNET_TIME_Absolute limit, @@ -174,16 +175,18 @@ withdraw_amount_cb ( void *cb_cls) { struct WithdrawContext *wc = cls; + enum GNUNET_GenericReturnValue ret; enum GNUNET_DB_QueryStatus qs; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Signaling amount %s for KYC check during age-withdrawal\n", TALER_amount2s (wc->withdraw_total)); - if (GNUNET_OK != - cb (cb_cls, - wc->withdraw_total, - wc->now.abs_time)) - return; + ret = cb (cb_cls, + wc->withdraw_total, + wc->now.abs_time); + GNUNET_break (GNUNET_SYSERR != ret); + if (GNUNET_OK != ret) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; qs = TEH_plugin->select_withdraw_amounts_for_kyc_check ( TEH_plugin->cls, &wc->h_payto, @@ -195,6 +198,7 @@ withdraw_amount_cb ( qs, (unsigned long long) limit.abs_value_us); GNUNET_break (qs >= 0); + return qs; } diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h @@ -137,8 +137,9 @@ TALER_KYCLOGIC_get_wallet_thresholds (void); * events must be returned in reverse chronological * order * @param cb_cls closure for @a cb + * @return transaction status */ -typedef void +typedef enum GNUNET_DB_QueryStatus (*TALER_KYCLOGIC_KycAmountIterator)( void *cls, struct GNUNET_TIME_Absolute limit, @@ -217,19 +218,19 @@ TALER_KYCLOGIC_kyc_test_required ( const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, TALER_KYCLOGIC_KycAmountIterator ai, void *ai_cls, - struct TALER_KYCLOGIC_KycRule **triggered_rule); + const struct TALER_KYCLOGIC_KycRule **triggered_rule); const char * -TALER_KYCLOGIC_rule2s (struct TALER_KYCLOGIC_KycRule *r); +TALER_KYCLOGIC_rule2s (const struct TALER_KYCLOGIC_KycRule *r); json_t * -TALER_KYCLOGIC_rule2j (struct TALER_KYCLOGIC_KycRule *r); +TALER_KYCLOGIC_rule2j (const struct TALER_KYCLOGIC_KycRule *r); uint32_t -TALER_KYCLOGIC_rule2priority (struct TALER_KYCLOGIC_KycRule *r); +TALER_KYCLOGIC_rule2priority (const struct TALER_KYCLOGIC_KycRule *r); /** diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c @@ -247,6 +247,21 @@ struct TALER_KYCLOGIC_KycRule /** + * KYC measure that can be taken. + */ +struct TALER_KYCLOGIC_Measure +{ + /** + * Name of the KYC measure. + */ + char *measure_name; + + // FIXME: other fields!? + +}; + + +/** * Set of rules that applies to an account. */ struct TALER_KYCLOGIC_LegitimizationRuleSet @@ -272,7 +287,7 @@ struct TALER_KYCLOGIC_LegitimizationRuleSet * Array of custom measures the @e kyc_rules may refer * to. */ - struct TALER_KYCLOGIC_Measures *custom_measures; + struct TALER_KYCLOGIC_Measure *custom_measures; /** * Length of the @e kyc_rules array. @@ -306,14 +321,14 @@ TALER_KYCLOGIC_rules_free (struct TALER_KYCLOGIC_LegitimizationRuleSet *krs) const char * -TALER_KYCLOGIC_rule2s (struct TALER_KYCLOGIC_KycRule *r) +TALER_KYCLOGIC_rule2s (const struct TALER_KYCLOGIC_KycRule *r) { return r->rule_name; } json_t * -TALER_KYCLOGIC_rule2j (struct TALER_KYCLOGIC_KycRule *r) +TALER_KYCLOGIC_rule2j (const struct TALER_KYCLOGIC_KycRule *r) { // FIXME! GNUNET_break (0); @@ -322,7 +337,7 @@ TALER_KYCLOGIC_rule2j (struct TALER_KYCLOGIC_KycRule *r) uint32_t -TALER_KYCLOGIC_rule2priority (struct TALER_KYCLOGIC_KycRule *r) +TALER_KYCLOGIC_rule2priority (const struct TALER_KYCLOGIC_KycRule *r) { return r->display_priority; } @@ -624,21 +639,25 @@ TALER_KYCLOGIC_kyc_trigger2s ( json_t * TALER_KYCLOGIC_get_wallet_thresholds (void) { -#if 0 json_t *ret; ret = json_array (); GNUNET_assert (NULL != ret); - GNUNET_assert ( - 0 == - json_array_append_new ( - ret, - TALER_JSON_from_amount ( - threshold))); + for (unsigned int i = 0; i<default_rules.num_kyc_rules; i++) + { + struct TALER_KYCLOGIC_KycRule *rule + = default_rules.kyc_rules[i]; + + if (TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE != rule->trigger) + continue; + GNUNET_assert ( + 0 == + json_array_append_new ( + ret, + TALER_JSON_from_amount ( + &rule->threshold))); + } return ret; -#endif - GNUNET_break (0); // FIXME: implement! - return NULL; } @@ -1524,6 +1543,69 @@ TALER_KYCLOGIC_requirements_to_logic ( struct TALER_KYCLOGIC_ProviderDetails **pd, const char **configuration_section) { + bool found = false; + const struct TALER_KYCLOGIC_Measure *measure = NULL; + + for (unsigned int i=0; i<kyc_rule->num_measures; i++) + { + if (0 != strcmp (measure_name, + kyc_rule->next_measures[i])) + continue; + found = true; + break; + } + if (! found) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Measure `%s' not allowed for rule `%s'\n", + measure_name, + kyc_rule->rule_name); + return GNUNET_SYSERR; + } + if (kyc_rule->verboten) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Rule says operation is categorically is verboten, cannot take measures\n"); + return GNUNET_SYSERR; + } + if (NULL != lrs) + { + for (unsigned int i=0; i<lrs->num_custom_measures; i++) + { + const struct TALER_KYCLOGIC_Measure *cm + = &lrs->custom_measures[i]; + + if (0 != strcmp (measure_name, + cm->measure_name)) + continue; + measure = cm; + break; + } + } + if (NULL == measure) + { + /* Try measures from default rules */ + for (unsigned int i=0; i<default_rules.num_custom_measures; i++) + { + const struct TALER_KYCLOGIC_Measure *cm + = &default_rules.custom_measures[i]; + + if (0 != strcmp (measure_name, + cm->measure_name)) + continue; + measure = cm; + break; + } + } + if (NULL == measure) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Measure `%s' unknown (but allowed by rule `%s')\n", + measure_name, + kyc_rule->rule_name); + return GNUNET_SYSERR; + } + #if FIXME struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks]; unsigned int needed_cnt = 0; @@ -1674,154 +1756,129 @@ TALER_KYCLOGIC_kyc_get_details ( } +/** + * Closure for check_amount(). + */ +struct KycTestContext +{ + /** + * Rule set we apply. + */ + const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs; + + /** + * Events we care about. + */ + enum TALER_KYCLOGIC_KycTriggerEvent event; + + /** + * Total amount encountered so far, invalid if zero. + */ + struct TALER_Amount sum; + + /** + * Set to the triggered rule. + */ + const struct TALER_KYCLOGIC_KycRule *triggered_rule; +}; + + +/** + * Function called on each @a amount that was found to + * be relevant for a KYC check. Evaluates the given + * @a amount and @a date against all the applicable + * rules in the legitimization rule set. + * + * @param cls our `struct KycTestContext *` + * @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 +check_amount ( + void *cls, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Absolute date) +{ + struct KycTestContext *ktc = cls; + struct GNUNET_TIME_Relative dur; + + dur = GNUNET_TIME_absolute_get_duration (date); + if (GNUNET_OK != + TALER_amount_is_valid (&ktc->sum)) + ktc->sum = *amount; + else + GNUNET_assert (0 <= + TALER_amount_add (&ktc->sum, + &ktc->sum, + amount)); + for (unsigned int i=0; i<ktc->lrs->num_kyc_rules; i++) + { + const struct TALER_KYCLOGIC_KycRule *rule + = ktc->lrs->kyc_rules[i]; + + if (ktc->event != rule->trigger) + continue; /* wrong trigger event type */ + if (GNUNET_TIME_relative_cmp (dur, + >, + rule->timeframe)) + continue; /* out of time range for rule */ + if (-1 == TALER_amount_cmp (&ktc->sum, + &rule->threshold)) + continue; /* sum < threshold */ + if ( (NULL != ktc->triggered_rule) && + (1 == TALER_amount_cmp (&ktc->triggered_rule->threshold, + &rule->threshold)) ) + continue; /* threshold of triggered_rule > rule */ + ktc->triggered_rule = rule; + } + return GNUNET_OK; +} + + enum GNUNET_DB_QueryStatus TALER_KYCLOGIC_kyc_test_required ( enum TALER_KYCLOGIC_KycTriggerEvent event, const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, TALER_KYCLOGIC_KycAmountIterator ai, void *ai_cls, - struct TALER_KYCLOGIC_KycRule **triggered_rule) + const struct TALER_KYCLOGIC_KycRule **triggered_rule) { -#if FIXME - struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks]; - unsigned int needed_cnt = 0; - char *ret; - struct GNUNET_TIME_Relative timeframe; + struct GNUNET_TIME_Relative range + = GNUNET_TIME_UNIT_ZERO; + enum GNUNET_DB_QueryStatus qs; - timeframe = GNUNET_TIME_UNIT_ZERO; - for (unsigned int i = 0; i<num_kyc_triggers; i++) + if (NULL == lrs) + lrs = &default_rules; + for (unsigned int i=0; i<lrs->num_kyc_rules; i++) { - const struct TALER_KYCLOGIC_KycTrigger *kt = kyc_triggers[i]; + const struct TALER_KYCLOGIC_KycRule *rule + = lrs->kyc_rules[i]; - if (event != kt->trigger) + if (event != rule->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 - }; - - now = GNUNET_TIME_absolute_get (); - ai (ai_cls, - GNUNET_TIME_absolute_subtract (now, - timeframe), - &eval_trigger, - &ttc); - } - if (0 == needed_cnt) - { - *required = NULL; - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + range = GNUNET_TIME_relative_max (range, + rule->timeframe); } - timeframe = GNUNET_TIME_UNIT_ZERO; - for (unsigned int i = 0; i<num_kyc_triggers; i++) - { - const struct TALER_KYCLOGIC_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 + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct KycTestContext ktc = { + .lrs = lrs, + .event = event }; - now = GNUNET_TIME_absolute_get (); - ai (ai_cls, - GNUNET_TIME_absolute_subtract (now, - timeframe), - &eval_trigger, - &ttc); - } - if (0 == needed_cnt) - { - *required = NULL; - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - { - 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. */ - qs = ki (ki_cls, - h_payto, - &remove_satisfied, - &rc); - if (qs < 0) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } - } - if (0 == needed_cnt) - { - *required = NULL; - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - { - 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. */ - qs = ki (ki_cls, - h_payto, - &remove_satisfied, - &rc); - if (qs < 0) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } + qs = ai (ai_cls, + GNUNET_TIME_absolute_subtract (now, + range), + &check_amount, + &ktc); + *triggered_rule = ktc.triggered_rule; } - if (0 == needed_cnt) - { - *required = NULL; - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - ret = NULL; - for (unsigned int k = 0; k<needed_cnt; k++) - { - const struct TALER_KYCLOGIC_KycCheck *kc = needed[k]; - - if (NULL == ret) - { - ret = GNUNET_strdup (kc->name); - } - else /* append */ - { - char *tmp = ret; - - GNUNET_asprintf (&ret, - "%s %s", - tmp, - kc->name); - GNUNET_free (tmp); - } - } - *required = ret; - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -#else - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; -#endif + return qs; } @@ -1984,194 +2041,6 @@ eval_trigger (void *cls, } -/** - * Closure for the #remove_satisfied(). - */ -struct RemoveContext -{ - - /** - * Array of checks needed so far. - */ - struct TALER_KYCLOGIC_KycCheck **needed; - - /** - * Pointer to number of entries used in @a needed. - */ - unsigned int *needed_cnt; - - /** - * Object with information about collected KYC data. - */ - json_t *kyc_details; -}; - - -/** - * 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 TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i]; - - if (0 != strcasecmp (provider_name, - kp->provider_section_name)) - continue; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Provider `%s' satisfied\n", - provider_name); - for (unsigned int j = 0; j<kp->num_checks; j++) - { - const struct TALER_KYCLOGIC_KycCheck *kc = kp->provided_checks[j]; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Provider satisfies check `%s'\n", - kc->name); - if (NULL != rc->kyc_details) - { - GNUNET_assert (0 == - json_object_set_new ( - rc->kyc_details, - kc->name, - json_object ())); - } - for (unsigned int k = 0; k<*rc->needed_cnt; k++) - if (kc == rc->needed[k]) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Removing check `%s' from list\n", - kc->name); - rc->needed[k] = rc->needed[*rc->needed_cnt - 1]; - (*rc->needed_cnt)--; - if (0 == *rc->needed_cnt) - return; /* for sure finished */ - break; - } - } - break; - } -} - - -enum GNUNET_DB_QueryStatus -TALER_KYCLOGIC_check_satisfied ( - char **requirements, - const struct TALER_PaytoHashP *h_payto, - json_t **kyc_details, - TALER_KYCLOGIC_KycSatisfiedIterator ki, - void *ki_cls, - bool *satisfied) -{ - struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks]; - unsigned int needed_cnt = 0; - - if (NULL == requirements) - { - *satisfied = true; - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - } - { - char *req = *requirements; - - for (const char *tok = strtok (req, " "); - NULL != tok; - tok = strtok (NULL, " ")) - needed[needed_cnt++] = add_check (tok); - GNUNET_free (req); - *requirements = NULL; - } - - { - struct RemoveContext rc = { - .needed = needed, - .needed_cnt = &needed_cnt, - }; - enum GNUNET_DB_QueryStatus qs; - - rc.kyc_details = json_object (); - GNUNET_assert (NULL != rc.kyc_details); - - /* Check what provider checks are already satisfied for h_payto (with - database), remove those from the 'needed' array. */ - qs = ki (ki_cls, - h_payto, - &remove_satisfied, - &rc); - if (qs < 0) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - *satisfied = false; - return qs; - } - if (0 != needed_cnt) - { - json_decref (rc.kyc_details); - *kyc_details = NULL; - } - else - { - *kyc_details = rc.kyc_details; - } - } - *satisfied = (0 == needed_cnt); - - { - char *res = NULL; - - for (unsigned int i = 0; i<needed_cnt; i++) - { - const struct TALER_KYCLOGIC_KycCheck *need = needed[i]; - - if (NULL == res) - { - res = GNUNET_strdup (need->name); - } - else - { - char *tmp; - - GNUNET_asprintf (&tmp, - "%s %s", - res, - need->name); - GNUNET_free (res); - res = tmp; - } - } - *requirements = res; - } - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; -} - - -void -TALER_KYCLOGIC_kyc_iterate_thresholds ( - enum TALER_KYCLOGIC_KycTriggerEvent event, - TALER_KYCLOGIC_KycThresholdIterator it, - void *it_cls) -{ - for (unsigned int i = 0; i<num_kyc_triggers; i++) - { - const struct TALER_KYCLOGIC_KycTrigger *kt = kyc_triggers[i]; - - if (event != kt->trigger) - continue; - it (it_cls, - &kt->threshold); - } -} - - void TALER_KYCLOGIC_lookup_checks (const char *section_name, unsigned int *num_checks, diff --git a/src/kyclogic/taler-exchange-kyc-tester.c b/src/kyclogic/taler-exchange-kyc-tester.c @@ -1439,8 +1439,9 @@ initiate_cb ( * events must be returned in reverse chronological * order * @param cb_cls closure for @a cb + * @return transaction status */ -static void +static enum GNUNET_DB_QueryStatus amount_iterator ( void *cls, struct GNUNET_TIME_Absolute limit, @@ -1449,14 +1450,18 @@ amount_iterator ( { const struct TALER_Amount *amount = cls; struct GNUNET_TIME_Absolute date; + enum GNUNET_GenericReturnValue ret; date = GNUNET_TIME_absolute_subtract (limit, GNUNET_TIME_UNIT_SECONDS); - GNUNET_break (GNUNET_SYSERR != - cb (cb_cls, - amount, - date)); + ret = cb (cb_cls, + amount, + date); + GNUNET_break (GNUNET_SYSERR != ret); + if (GNUNET_OK != ret) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; } @@ -1477,7 +1482,7 @@ run (void *cls, { enum TALER_KYCLOGIC_KycTriggerEvent event; struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs = NULL; - struct TALER_KYCLOGIC_KycRule *rule = NULL; + const struct TALER_KYCLOGIC_KycRule *rule = NULL; int fh; (void) cls;