aboutsummaryrefslogtreecommitdiff
path: root/src/exchange
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-02-09 17:54:14 +0100
committerChristian Grothoff <christian@grothoff.org>2023-02-09 17:54:14 +0100
commit19132b67165d04bede03ba83e98359849e357536 (patch)
tree754cd0806eeb267f18b3807e3003caeac663f6c9 /src/exchange
parentd0b43b0e6aeb10b54318265c5fcf64375c3fb764 (diff)
-start on AML work (incomplete)
Diffstat (limited to 'src/exchange')
-rw-r--r--src/exchange/taler-exchange-aggregator.c99
-rw-r--r--src/exchange/taler-exchange-httpd_batch-deposit.c24
2 files changed, 106 insertions, 17 deletions
diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c
index 823326d0..af3e111d 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -149,6 +149,12 @@ struct Shard
static struct TALER_Amount currency_round_unit;
/**
+ * What is the largest amount we transfer before triggering
+ * an AML check?
+ */
+static struct TALER_Amount aml_threshold;
+
+/**
* What is the base URL of this exchange? Used in the
* wire transfer subjects so that merchants and governments
* can ask for the list of aggregated deposits.
@@ -294,11 +300,20 @@ parse_aggregator_config (void)
"taler",
"CURRENCY_ROUND_UNIT",
&currency_round_unit)) ||
- ( (0 != currency_round_unit.fraction) &&
- (0 != currency_round_unit.value) ) )
+ (TALER_amount_is_zero (&currency_round_unit)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Need non-zero value in section `TALER' under `CURRENCY_ROUND_UNIT'\n");
+ "Need non-zero amount in section `TALER' under `CURRENCY_ROUND_UNIT'\n");
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ TALER_config_get_amount (cfg,
+ "taler",
+ "AML_THRESHOLD",
+ &aml_threshold))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Need amount in section `TALER' under `AML_THRESHOLD'\n");
return GNUNET_SYSERR;
}
@@ -525,6 +540,81 @@ kyc_satisfied (struct AggregationUnit *au_active)
/**
+ * 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;
+
+ 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;
+ }
+ if (0 >= TALER_amount_cmp (&total,
+ &aml_threshold))
+ {
+ /* total <= aml_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;
+}
+
+
+/**
* Perform the main aggregation work for @a au. Expects to be in
* a working transaction, which the caller must also ultimately commit
* (or rollback) depending on our return value.
@@ -649,7 +739,8 @@ do_aggregate (struct AggregationUnit *au)
TALER_amount_round_down (&au->final_amount,
&currency_round_unit)) ||
(TALER_amount_is_zero (&au->final_amount)) ||
- (! kyc_satisfied (au)) )
+ (! kyc_satisfied (au)) ||
+ (! aml_satisfied (au)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not ready for wire transfer (%d/%s)\n",
diff --git a/src/exchange/taler-exchange-httpd_batch-deposit.c b/src/exchange/taler-exchange-httpd_batch-deposit.c
index 0545c393..d000c454 100644
--- a/src/exchange/taler-exchange-httpd_batch-deposit.c
+++ b/src/exchange/taler-exchange-httpd_batch-deposit.c
@@ -233,9 +233,8 @@ again:
MHD_HTTP_OK,
GNUNET_JSON_pack_timestamp ("exchange_timestamp",
bdc->exchange_timestamp),
- GNUNET_JSON_pack_data_auto (
- "exchange_pub",
- &pub),
+ GNUNET_JSON_pack_data_auto ("exchange_pub",
+ &pub),
GNUNET_JSON_pack_array_steal ("exchange_sigs",
arr));
}
@@ -268,13 +267,12 @@ batch_deposit_transaction (void *cls,
* insert or update the record. */
if (dc->has_policy)
{
- qs = TEH_plugin->persist_policy_details (TEH_plugin->cls,
- &dc->policy_details,
- &dc->policy_details_serial_id,
- &dc->policy_details.
- accumulated_total,
- &dc->policy_details.
- fulfillment_state);
+ qs = TEH_plugin->persist_policy_details (
+ TEH_plugin->cls,
+ &dc->policy_details,
+ &dc->policy_details_serial_id,
+ &dc->policy_details.accumulated_total,
+ &dc->policy_details.fulfillment_state);
if (qs < 0)
return qs;
}
@@ -295,9 +293,9 @@ batch_deposit_transaction (void *cls,
deposit,
known_coin_id,
&dc->h_payto,
- (dc->has_policy)
- ? &dc->policy_details_serial_id
- : NULL,
+ dc->has_policy
+ ? &dc->policy_details_serial_id
+ : NULL,
&dc->exchange_timestamp,
&balance_ok,
&in_conflict);