commit 640f0a6186e4581d89b4616d4620ba7344d09ac1
parent ceb2b95a60570d7cb4d97a683773a8c95530b3e6
Author: Christian Grothoff <christian@grothoff.org>
Date: Mon, 6 May 2024 21:41:52 +0200
work on DD23
Diffstat:
5 files changed, 101 insertions(+), 136 deletions(-)
diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2016-2022 Taler Systems SA
+ Copyright (C) 2016-2024 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
@@ -490,49 +490,90 @@ return_relevant_amounts (void *cls,
/**
- * Test if KYC is required for a transfer to @a h_payto.
+ * Test if legitimization rules are satisfied for a transfer to @a h_payto.
*
* @param[in,out] au_active aggregation unit to check for
* @return true if KYC checks are satisfied
*/
static bool
-kyc_satisfied (struct AggregationUnit *au_active)
+legitimization_satisfied (struct AggregationUnit *au_active)
{
- char *requirement;
+ struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs = NULL;
+ struct TALER_KYCLOGIC_KycRule *requirement;
+ struct GNUNET_TIME_Timestamp expiration_time;
enum GNUNET_DB_QueryStatus qs;
+ json_t *jrule;
if (kyc_off)
return true;
+
+ {
+ json_t *jrules;
+
+ qs = db_plugin->get_kyc_rules (db_plugin->cls,
+ &au_active->h_payto,
+ &expiration_time,
+ &jrules);
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return false;
+ }
+ if ( (qs > 0) &&
+ (GNUNET_TIME_absolute_is_past (expiration_time.abs_time)) )
+ {
+ json_decref (jrules);
+ jrules = NULL;
+ qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ if (qs > 0)
+ {
+ lrs = TALER_KYCLOGIC_rules_parse (jrules);
+ if (NULL == lrs)
+ {
+ GNUNET_break (0);
+ json_decref (jrules);
+ return false;
+ }
+ json_decref (jrules);
+ }
+ }
qs = TALER_KYCLOGIC_kyc_test_required (
TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT,
&au_active->h_payto,
- db_plugin->select_satisfied_kyc_processes,
- db_plugin->cls,
+ lrs,
&return_relevant_amounts,
(void *) au_active,
&requirement);
if (qs < 0)
{
+ TALER_KYCLOGIC_rules_free (lrs);
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return false;
}
if (NULL == requirement)
+ {
+ TALER_KYCLOGIC_rules_free (lrs);
return true;
+ }
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"KYC requirement for %s is %s\n",
TALER_amount2s (&au_active->total_amount),
- requirement);
- qs = db_plugin->insert_kyc_requirement_for_account (
+ TALER_KYCLOGIC_rule2s (requirement));
+ jrule = TALER_KYCLOGIC_rule2j (requirement);
+ qs = db_plugin->trigger_kyc_rule_for_account (
db_plugin->cls,
- requirement,
&au_active->h_payto,
- NULL, /* not a reserve */
+ NULL,
+ jrule,
+ TALER_KYCLOGIC_rule2priority (requirement),
&au_active->requirement_row);
+ json_decref (jrule);
if (qs < 0)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to persist KYC requirement `%s' in DB!\n",
- requirement);
+ TALER_KYCLOGIC_rule2s (requirement));
}
else
{
@@ -540,114 +581,7 @@ kyc_satisfied (struct AggregationUnit *au_active)
"Legitimization process %llu started\n",
(unsigned long long) au_active->requirement_row);
}
- GNUNET_free (requirement);
- return false;
-}
-
-
-/**
- * Function called on each @a amount that was found to
- * be relevant for an AML check.
- *
- * @param cls closure with the `struct TALER_Amount *` where we store the sum
- * @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
-sum_for_aml (
- void *cls,
- const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute date)
-{
- struct TALER_Amount *sum = cls;
-
- (void) date;
- if (0 >
- TALER_amount_add (sum,
- sum,
- amount))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Test if AML is required for a transfer to @a h_payto.
- *
- * @param[in,out] au_active aggregation unit to check for
- * @return true if AML checks are satisfied
- */
-static bool
-aml_satisfied (struct AggregationUnit *au_active)
-{
- enum GNUNET_DB_QueryStatus qs;
- struct TALER_Amount total;
- struct TALER_Amount threshold;
- enum TALER_AmlDecisionState decision;
- struct TALER_EXCHANGEDB_KycStatus kyc;
-
- total = au_active->final_amount;
- qs = db_plugin->select_aggregation_amounts_for_kyc_check (
- db_plugin->cls,
- &au_active->h_payto,
- GNUNET_TIME_absolute_subtract (GNUNET_TIME_absolute_get (),
- GNUNET_TIME_UNIT_MONTHS),
- &sum_for_aml,
- &total);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- return false;
- }
- qs = db_plugin->select_aml_threshold (db_plugin->cls,
- &au_active->h_payto,
- &decision,
- &kyc,
- &threshold);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- return false;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- threshold = aml_threshold; /* use default */
- decision = TALER_AML_NORMAL;
- }
- switch (decision)
- {
- case TALER_AML_NORMAL:
- if (0 >= TALER_amount_cmp (&total,
- &threshold))
- {
- /* total <= threshold, do nothing */
- return true;
- }
- qs = db_plugin->trigger_aml_process (db_plugin->cls,
- &au_active->h_payto,
- &total);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- return false;
- }
- return false;
- case TALER_AML_PENDING:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "AML already pending, doing nothing\n");
- return false;
- case TALER_AML_FROZEN:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Account frozen, doing nothing\n");
- return false;
- }
- GNUNET_assert (0);
+ TALER_KYCLOGIC_rules_free (lrs);
return false;
}
@@ -783,8 +717,7 @@ do_aggregate (struct AggregationUnit *au)
TALER_amount_round_down (&au->final_amount,
¤cy_round_unit)) ||
(TALER_amount_is_zero (&au->final_amount)) ||
- (! kyc_satisfied (au)) ||
- (! aml_satisfied (au)) )
+ (! legitimization_satisfied (au)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not ready for wire transfer (%d/%s)\n",
diff --git a/src/exchangedb/0005-legitimization_measures.sql b/src/exchangedb/0005-legitimization_measures.sql
@@ -26,7 +26,7 @@ BEGIN
'(legitimization_measure_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY'
',target_token BYTEA NOT NULL CHECK (LENGTH(target_token)=32)'
',start_time INT8 NOT NULL'
- ',jmeasures TEXT NOT NULL'
+ ',jmeasures TEXT NOT NULL' -- FIXME: rename to jrule?
',display_priority INT4 NOT NULL'
',is_finished BOOL NOT NULL DEFAULT(FALSE)'
') %s ;'
@@ -57,6 +57,8 @@ BEGIN
,'legitimization_measures'
,partition_suffix
);
+ -- FIXME: LegitimizationMeasures is *bad* here, as we only have the KycRule; the specific measure may
+ -- not yet have been selected at the time of the trigger!
PERFORM comment_partitioned_column(
'JSON object of type LegitimizationMeasures with KYC/AML measures for the account encoded'
,'jmeasures'
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
@@ -998,7 +998,7 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData
{
/**
* Serial of the denomination key as in the DB.
- * Can be used in calls to stored procedures in order to spare
+ * Can be used calls to stored procedures in order to spare
* additional lookups.
*/
uint64_t serial;
@@ -6717,18 +6717,20 @@ struct TALER_EXCHANGEDB_Plugin
* Insert KYC requirement for @a h_payto account into table.
*
* @param cls closure
- * @param requirements requirements that must be checked
* @param h_payto account that must be KYC'ed
- * @param reserve_pub if account is a reserve, its public key, NULL otherwise
+ * @param account_pub public key authorizing access, NULL if not known
+ * @param jrule serialized KYC rule that was triggered
+ * @param display_priority priority of the rule
* @param[out] requirement_row set to legitimization requirement row for this check
* @return database transaction status
*/
enum GNUNET_DB_QueryStatus
- (*insert_kyc_requirement_for_account)(
+ (*trigger_kyc_rule_for_account)(
void *cls,
- const char *requirements,
const struct TALER_PaytoHashP *h_payto,
- const struct TALER_ReservePublicKeyP *reserve_pub,
+ const union TALER_AccountPublicKeyP *account_pub,
+ const json_t *jrule,
+ uint32_t display_priority,
uint64_t *requirement_row);
diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h
@@ -158,20 +158,17 @@ struct TALER_KYCLOGIC_KycRule;
/**
* Set of rules that applies to an account.
*/
-struct TALER_KYCLOGIC_KycRuleSet;
+struct TALER_KYCLOGIC_LegitimizationRuleSet;
/**
* Parse set of rules that applies to an account.
*
* @param jrules JSON representation to parse
- * @param[out] lrs set to rule set
- * @return #GNUNET_SYSERR JSON is invalid
+ * @return rule set, NULL if JSON is invalid
*/
-enum GNUNET_GenericReturnValue
-TALER_KYCLOGIC_rules_parse (
- const json_t *jrules,
- struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs);
+struct TALER_KYCLOGIC_LegitimizationRuleSet *
+TALER_KYCLOGIC_rules_parse (const json_t *jrules);
/**
@@ -192,7 +189,8 @@ TALER_KYCLOGIC_rules_free (struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs);
* @param event what type of operation is triggering the
* test if KYC is required
* @param h_payto account the event is about
- * @param lrs legitimization rules for @a h_payto
+ * @param lrs legitimization rules for @a h_payto,
+ * NULL to use default rules
* @param ai callback offered to inquire about historic
* amounts involved in this type of operation
* at the given account
@@ -213,6 +211,17 @@ TALER_KYCLOGIC_kyc_test_required (
struct TALER_KYCLOGIC_KycRule **triggered_rule);
+const char *
+TALER_KYCLOGIC_rule2s (struct TALER_KYCLOGIC_KycRule *r);
+
+
+json_t *
+TALER_KYCLOGIC_rule2j (struct TALER_KYCLOGIC_KycRule *r);
+
+
+uint32_t
+TALER_KYCLOGIC_rule2priority (struct TALER_KYCLOGIC_KycRule *r);
+
/**
* Iterate over all thresholds that are applicable to a particular type of @a
* event under exposed global rules.
diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c
@@ -278,6 +278,11 @@ struct TALER_KYCLOGIC_LegitimizationRuleSet
* Length of the @e custom_measures array.
*/
unsigned int num_custom_measures;
+
+ /**
+ * Display priority for this rule.
+ */
+ uint32_t display_priority;
};
@@ -298,6 +303,20 @@ TALER_KYCLOGIC_rules_free (struct TALER_KYCLOGIC_KycRuleSet *krs)
}
+const char *
+TALER_KYCLOGIC_rule2s (struct TALER_KYCLOGIC_KycRule *r)
+{
+ return r->rule_name;
+}
+
+
+uint32_t
+TALER_KYCLOGIC_rule2priority (struct TALER_KYCLOGIC_KycRule *r)
+{
+ return r->display_priority;
+}
+
+
/**
* AML programs.
*/