commit bc30273e1810d4f78b199a3fbbed774d8518edcb
parent 53fe2cc9d1cc7417361925b1861075c79d3a0250
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 8 Dec 2024 19:15:13 +0100
implement #9303
Diffstat:
14 files changed, 527 insertions(+), 15 deletions(-)
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
@@ -131,6 +131,7 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
pg_batch_ensure_coin_known.h pg_batch_ensure_coin_known.c \
pg_begin_revolving_shard.h pg_begin_revolving_shard.c \
pg_begin_shard.h pg_begin_shard.c \
+ pg_clear_aml_lock.h pg_clear_aml_lock.c \
pg_commit.h pg_commit.c \
pg_complete_shard.h pg_complete_shard.c \
pg_compute_shard.h pg_compute_shard.c \
@@ -304,6 +305,7 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
pg_select_wire_out_above_serial_id_by_account.h pg_select_wire_out_above_serial_id_by_account.c \
pg_select_withdraw_amounts_for_kyc_check.h pg_select_withdraw_amounts_for_kyc_check.c \
pg_select_withdrawals_above_serial_id.h pg_select_withdrawals_above_serial_id.c \
+ pg_set_aml_lock.h pg_set_aml_lock.c \
pg_set_extension_manifest.h pg_set_extension_manifest.c \
pg_set_purse_balance.h pg_set_purse_balance.c \
pg_start.h pg_start.c \
diff --git a/src/exchangedb/exchange_do_set_aml_lock.sql b/src/exchangedb/exchange_do_set_aml_lock.sql
@@ -0,0 +1,46 @@
+--
+-- This file is part of TALER
+-- Copyright (C) 2024 Taler Systems SA
+--
+-- TALER is free software; you can redistribute it and/or modify it under the
+-- terms of the GNU 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 General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License along with
+-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+--
+
+DROP FUNCTION IF EXISTS exchange_do_set_aml_lock;
+CREATE FUNCTION exchange_do_set_aml_lock (
+ IN in_h_payto BYTEA,
+ IN in_now INT8,
+ IN in_expiration INT8,
+ OUT out_aml_program_lock_timeout INT8) -- set if we have an existing lock
+LANGUAGE plpgsql
+AS $$
+BEGIN
+
+UPDATE wire_targets
+ SET aml_program_lock_timeout=in_expiration
+ WHERE h_normalized_payto=in_h_payto
+ AND ( (aml_program_lock_timeout IS NULL)
+ OR (aml_program_lock_timeout < in_now) );
+IF NOT FOUND
+THEN
+ SELECT aml_program_lock_timeout
+ INTO out_aml_program_lock_timeout
+ FROM wire_targets
+ WHERE h_normalized_payto=in_h_payto;
+ELSE
+ out_aml_program_lock_timeout = 0;
+END IF;
+
+END $$;
+
+
+COMMENT ON FUNCTION exchange_do_set_aml_lock(BYTEA, INT8, INT8)
+ IS 'Tries to lock an account for running an AML program. Returns the timeout of the existing lock, 0 if there is no existing lock, and NULL if we do not know the account.';
diff --git a/src/exchangedb/exchangedb_aml.c b/src/exchangedb/exchangedb_aml.c
@@ -22,6 +22,7 @@
#include "taler_exchangedb_lib.h"
#include "taler_kyclogic_lib.h"
#include "taler_json_lib.h"
+#include "taler_dbevents.h"
#include <gnunet/gnunet_common.h>
/**
@@ -31,6 +32,13 @@
*/
#define MAX_DEPTH 16
+/**
+ * How long do we allow an AML program to run for at most?
+ * If an AML program runs longer, we kill it and mark it as
+ * failed.
+ */
+#define MAX_AML_PROGRAM_RUNTIME GNUNET_TIME_UNIT_MINUTES
+
enum GNUNET_DB_QueryStatus
TALER_EXCHANGEDB_persist_aml_program_result (
@@ -41,13 +49,9 @@ TALER_EXCHANGEDB_persist_aml_program_result (
{
enum GNUNET_DB_QueryStatus qs;
-#if 0
- /* FIXME: also clear lock on AML program (#9303) */
qs = plugin->clear_aml_lock (
plugin->cls,
- account_id,
- lock_id);
-#endif
+ account_id);
switch (apr->status)
{
case TALER_KYCLOGIC_AMLR_FAILURE:
@@ -116,11 +120,23 @@ struct TALER_EXCHANGEDB_RuleUpdater
struct GNUNET_SCHEDULER_Task *t;
/**
+ * Handler waiting notification that (previous) AML program
+ * finished.
+ */
+ struct GNUNET_DB_EventHandler *eh;
+
+ /**
* Handle to running AML program.
*/
struct TALER_KYCLOGIC_AmlProgramRunnerHandle *amlh;
/**
+ * Name of the AML program we were running asynchronously,
+ * for diagnostics.
+ */
+ char *aml_program_name;
+
+ /**
* Error hint to return with @e ec.
*/
const char *hint;
@@ -227,6 +243,8 @@ aml_result_callback (
enum GNUNET_GenericReturnValue res;
ru->amlh = NULL;
+ GNUNET_SCHEDULER_cancel (ru->t);
+ ru->t = NULL;
res = ru->plugin->start (ru->plugin->cls,
"aml-persist-aml-program-result");
if (GNUNET_OK != res)
@@ -304,6 +322,121 @@ aml_result_callback (
static void
+aml_program_timeout (void *cls)
+{
+ struct TALER_EXCHANGEDB_RuleUpdater *ru = cls;
+ struct TALER_KYCLOGIC_AmlProgramResult apr = {
+ .status = TALER_KYCLOGIC_AMLR_FAILURE,
+ .details.failure.fallback_measure
+ = TALER_KYCLOGIC_get_aml_program_fallback (ru->aml_program_name),
+ .details.failure.error_message = ru->aml_program_name,
+ .details.failure.ec = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT
+ };
+ enum GNUNET_GenericReturnValue res;
+ enum GNUNET_DB_QueryStatus qs;
+
+ ru->t = NULL;
+ TALER_KYCLOGIC_run_aml_program_cancel (ru->amlh);
+ ru->amlh = NULL;
+ GNUNET_assert (NULL != apr.details.failure.fallback_measure);
+ res = ru->plugin->start (ru->plugin->cls,
+ "aml-persist-aml-program-timeout");
+ if (GNUNET_OK != res)
+ {
+ GNUNET_break (0);
+ fail_update (ru,
+ TALER_EC_GENERIC_DB_START_FAILED,
+ "aml-persist-aml-program-timeout");
+ return;
+ }
+ /* Update database update based on result */
+ qs = TALER_EXCHANGEDB_persist_aml_program_result (
+ ru->plugin,
+ 0LLU, /* 0: no existing legitimization process, creates new row */
+ &ru->account,
+ &apr);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ fail_update (ru,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "persist_aml_program_timeout");
+ return;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ /* Bad, couldn't persist AML result. Try again... */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Serialization issue persisting timeout of AML program. Restarting.\n");
+ fail_update (ru,
+ TALER_EC_GENERIC_DB_SOFT_FAILURE,
+ "persist_aml_program_timeout");
+ return;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* Strange, but let's just continue */
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* normal case */
+ break;
+ }
+ {
+ const char *fmn = apr.details.failure.fallback_measure;
+ const struct TALER_KYCLOGIC_Measure *m;
+
+ m = TALER_KYCLOGIC_get_measure (ru->lrs,
+ fmn);
+ if (NULL == m)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Fallback measure `%s' does not exist (anymore?).\n",
+ fmn);
+ TALER_KYCLOGIC_rules_free (ru->lrs);
+ ru->lrs = NULL;
+ return_result (ru);
+ return;
+ }
+ run_measure (ru,
+ m);
+ return;
+ }
+}
+
+
+/**
+ * Entrypoint that fetches the latest rules from the database
+ * and starts processing them. Called without an open database
+ * transaction, will start one.
+ *
+ * @param[in] cls the `struct TALER_EXCHANGEDB_RuleUpdater *` to run
+ */
+static void
+fetch_latest_rules (void *cls);
+
+
+/**
+ * Notification called when we either timeout on the AML program lock
+ * or when the (previous) AML program finished and we can thus try again.
+ *
+ * @param cls the `struct TALER_EXCHANGEDB_RuleUpdater *` to continue
+ * @param extra additional event data provided (unused)
+ * @param extra_size number of bytes in @a extra (unused)
+ */
+static void
+trigger_fetch_latest_rules (void *cls,
+ const void *extra,
+ size_t extra_size)
+{
+ struct TALER_EXCHANGEDB_RuleUpdater *ru = cls;
+
+ (void) extra;
+ (void) extra_size;
+ if (NULL != ru->t)
+ return; /* multiple events triggered us, ignore */
+ ru->t = GNUNET_SCHEDULER_add_now (&fetch_latest_rules,
+ ru);
+}
+
+
+static void
run_measure (struct TALER_EXCHANGEDB_RuleUpdater *ru,
const struct TALER_KYCLOGIC_Measure *m)
{
@@ -334,8 +467,37 @@ run_measure (struct TALER_EXCHANGEDB_RuleUpdater *ru,
.attribute_key = &ru->attribute_key
};
enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_TIME_Absolute xlock;
- // FIXME: #9303 logic here?
+ /* Free previous one, in case we are iterating... */
+ GNUNET_free (ru->aml_program_name);
+ ru->aml_program_name = GNUNET_strdup (m->prog_name);
+ qs = ru->plugin->set_aml_lock (
+ ru->plugin->cls,
+ &ru->account,
+ GNUNET_TIME_relative_multiply (MAX_AML_PROGRAM_RUNTIME,
+ 2),
+ &xlock);
+ if (GNUNET_TIME_absolute_is_future (xlock))
+ {
+ struct TALER_KycCompletedEventP eh = {
+ .header.size = htons (sizeof (eh)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = ru->account
+ };
+ /* Wait for either timeout or notification */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "AML program already running, waiting for it to finish\n");
+ ru->plugin->rollback (ru->plugin->cls);
+ ru->eh
+ = ru->plugin->event_listen (
+ ru->plugin->cls,
+ GNUNET_TIME_absolute_get_remaining (xlock),
+ &eh.header,
+ &trigger_fetch_latest_rules,
+ ru);
+ return;
+ }
qs = ru->plugin->commit (ru->plugin->cls);
if (qs < 0)
{
@@ -350,6 +512,11 @@ run_measure (struct TALER_EXCHANGEDB_RuleUpdater *ru,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Check is of type 'skip', running AML program %s.\n",
m->prog_name);
+ GNUNET_assert (NULL == ru->t);
+ ru->t = GNUNET_SCHEDULER_add_delayed (
+ MAX_AML_PROGRAM_RUNTIME,
+ &aml_program_timeout,
+ ru);
ru->amlh = TALER_KYCLOGIC_run_aml_program3 (
m,
&TALER_EXCHANGEDB_current_attributes_builder,
@@ -476,13 +643,6 @@ check_rules (struct TALER_EXCHANGEDB_RuleUpdater *ru)
}
-/**
- * Entrypoint that fetches the latest rules from the database
- * and starts processing them. Called without an open database
- * transaction, will start one.
- *
- * @param[in] cls the `struct TALER_EXCHANGEDB_RuleUpdater *` to run
- */
static void
fetch_latest_rules (void *cls)
{
@@ -492,6 +652,13 @@ fetch_latest_rules (void *cls)
enum GNUNET_GenericReturnValue res;
ru->t = NULL;
+ if (NULL != ru->eh)
+ {
+ /* cancel event listener, if we have one */
+ ru->plugin->event_listen_cancel (ru->plugin->cls,
+ ru->eh);
+ ru->eh = NULL;
+ }
GNUNET_break (NULL == ru->lrs);
res = ru->plugin->start (ru->plugin->cls,
"aml-begin-lookup-rules-by-access-token");
@@ -568,5 +735,12 @@ TALER_EXCHANGEDB_update_rules_cancel (
TALER_KYCLOGIC_rules_free (ru->lrs);
ru->lrs = NULL;
}
+ if (NULL != ru->eh)
+ {
+ ru->plugin->event_listen_cancel (ru->plugin->cls,
+ ru->eh);
+ ru->eh = NULL;
+ }
+ GNUNET_free (ru->aml_program_name);
GNUNET_free (ru);
}
diff --git a/src/exchangedb/pg_clear_aml_lock.c b/src/exchangedb/pg_clear_aml_lock.c
@@ -0,0 +1,50 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/pg_clear_aml_lock.c
+ * @brief Implementation of the clear_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_clear_aml_lock.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_clear_aml_lock (
+ void *cls,
+ const struct TALER_NormalizedPaytoHashP *h_payto)
+{
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "clear_aml_lock",
+ "UPDATE wire_targets"
+ " SET"
+ " aml_program_lock_timeout=NULL"
+ " WHERE h_normalized_payto=$1");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "clear_aml_lock",
+ params);
+}
diff --git a/src/exchangedb/pg_clear_aml_lock.h b/src/exchangedb/pg_clear_aml_lock.h
@@ -0,0 +1,46 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/pg_clear_aml_lock.h
+ * @brief implementation of the clear_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_CLEAR_AML_LOCK_H
+#define PG_CLEAR_AML_LOCK_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+
+/**
+ * Clear a lock on running AML programs for the @a h_payto
+ * account. Returns 0 if @a h_payto is not known; does not
+ * actually care if there was a lock. Also does not by
+ * itself notify clients waiting for the lock, that
+ * notification the caller must do separately after finishing
+ * the database update.
+ *
+ * @param cls closure
+ * @param h_payto account to clear the lock for
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_clear_aml_lock (
+ void *cls,
+ const struct TALER_NormalizedPaytoHashP *h_payto);
+
+#endif
diff --git a/src/exchangedb/pg_insert_kyc_requirement_process.c b/src/exchangedb/pg_insert_kyc_requirement_process.c
@@ -26,6 +26,7 @@
#include "pg_helper.h"
#include <gnunet/gnunet_pq_lib.h>
+
enum GNUNET_DB_QueryStatus
TEH_PG_insert_kyc_requirement_process (
void *cls,
diff --git a/src/exchangedb/pg_set_aml_lock.c b/src/exchangedb/pg_set_aml_lock.c
@@ -0,0 +1,74 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/pg_set_aml_lock.c
+ * @brief Implementation of the set_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_set_aml_lock.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_set_aml_lock (
+ void *cls,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Relative lock_duration,
+ struct GNUNET_TIME_Absolute *existing_lock)
+{
+
+ struct PostgresClosure *pg = cls;
+ struct GNUNET_TIME_Absolute expires
+ = GNUNET_TIME_relative_to_absolute (lock_duration);
+ struct GNUNET_TIME_Absolute now
+ = GNUNET_TIME_absolute_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_absolute_time (&expires),
+ GNUNET_PQ_query_param_end
+ };
+ bool nx; /* true if the *account* is not known */
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_absolute_time ("out_aml_program_lock_timeout",
+ existing_lock),
+ &nx),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "set_aml_lock",
+ "SELECT out_aml_program_lock_timeout"
+ " FROM exchange_do_set_aml_lock($1,$2,$3);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "set_aml_lock",
+ params,
+ rs);
+ if (qs <= 0)
+ return qs;
+ if (nx)
+ {
+ *existing_lock = GNUNET_TIME_UNIT_ZERO_ABS;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ return qs;
+}
diff --git a/src/exchangedb/pg_set_aml_lock.h b/src/exchangedb/pg_set_aml_lock.h
@@ -0,0 +1,48 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/pg_set_aml_lock.h
+ * @brief implementation of the set_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef PG_SET_AML_LOCK_H
+#define PG_SET_AML_LOCK_H
+
+#include "taler_util.h"
+#include "taler_json_lib.h"
+#include "taler_exchangedb_plugin.h"
+
+/**
+ * Set a lock for @a lock_duration on running AML programs for the @a h_payto
+ * account. If a lock already exists, returns the timeout of the
+ * @a existing_lock. Returns 0 if @a h_payto is not known.
+ *
+ * @param cls closure
+ * @param h_payto account to lock
+ * @param lock_duration how long to lock the account
+ * @param[out] existing_lock set to timeout of existing lock, or
+ * to zero if there is no existing lock
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TEH_PG_set_aml_lock (
+ void *cls,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Relative lock_duration,
+ struct GNUNET_TIME_Absolute *existing_lock);
+
+
+#endif
diff --git a/src/exchangedb/pg_update_auditor.c b/src/exchangedb/pg_update_auditor.c
@@ -43,7 +43,7 @@ TEH_PG_update_auditor (void *cls,
GNUNET_PQ_query_param_timestamp (&change_date),
GNUNET_PQ_query_param_end
};
- /* used in #postgres_update_auditor() */
+
PREPARE (pg,
"update_auditor",
"UPDATE auditors"
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -35,6 +35,7 @@
#include "pg_batch_ensure_coin_known.h"
#include "pg_begin_revolving_shard.h"
#include "pg_begin_shard.h"
+#include "pg_clear_aml_lock.h"
#include "pg_commit.h"
#include "pg_complete_shard.h"
#include "pg_compute_shard.h"
@@ -208,6 +209,7 @@
#include "pg_select_wire_out_above_serial_id_by_account.h"
#include "pg_select_withdraw_amounts_for_kyc_check.h"
#include "pg_select_withdrawals_above_serial_id.h"
+#include "pg_set_aml_lock.h"
#include "pg_set_extension_manifest.h"
#include "pg_set_purse_balance.h"
#include "pg_start.h"
@@ -771,6 +773,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &TEH_PG_insert_aml_program_failure;
plugin->persist_kyc_attributes
= &TEH_PG_persist_kyc_attributes;
+ plugin->clear_aml_lock
+ = &TEH_PG_clear_aml_lock;
+ plugin->set_aml_lock
+ = &TEH_PG_set_aml_lock;
return plugin;
}
diff --git a/src/exchangedb/procedures.sql.in b/src/exchangedb/procedures.sql.in
@@ -58,5 +58,6 @@ SET search_path TO exchange;
#include "exchange_do_select_aggregations_above_serial.sql"
#include "exchange_do_persist_kyc_attributes.sql"
#include "exchange_do_insert_aml_program_failure.sql"
+#include "exchange_do_set_aml_lock.sql"
COMMIT;
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
@@ -7798,6 +7798,44 @@ struct TALER_EXCHANGEDB_Plugin
enum GNUNET_GenericReturnValue
(*inject_auditor_triggers)(void *cls);
+
+ /**
+ * Set a lock for @a lock_duration on running AML programs for the @a h_payto
+ * account. If a lock already exists, returns the timeout of the
+ * @a existing_lock. Returns 0 if @a h_payto is not known.
+ *
+ * @param cls closure
+ * @param h_payto account to lock
+ * @param lock_duration how long to lock the account
+ * @param[out] existing_lock set to timeout of existing lock, or
+ * to zero if there is no existing lock
+ * @return transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*set_aml_lock) (
+ void *cls,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Relative lock_duration,
+ struct GNUNET_TIME_Absolute *existing_lock);
+
+
+ /**
+ * Clear a lock on running AML programs for the @a h_payto
+ * account. Returns 0 if @a h_payto is not known; does not
+ * actually care if there was a lock. Also does not by
+ * itself notify clients waiting for the lock, that
+ * notification the caller must do separately after finishing
+ * the database update.
+ *
+ * @param cls closure
+ * @param h_payto account to clear the lock for
+ * @return transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*clear_aml_lock) (
+ void *cls,
+ const struct TALER_NormalizedPaytoHashP *h_payto);
+
};
#endif /* _TALER_EXCHANGE_DB_H */
diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h
@@ -410,6 +410,16 @@ TALER_KYCLOGIC_get_zero_limits (void);
/**
+ * Obtain the fallback measure to be run if @a prog_name fails
+ *
+ * @param prog_name name of an AML program
+ * @return NULL if @a prog_name is unknown
+ */
+const char *
+TALER_KYCLOGIC_get_aml_program_fallback (const char *prog_name);
+
+
+/**
* Obtain set of all measures that
* could be triggered at an amount of zero and that
* thus might be requested before a client even
diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c
@@ -1291,7 +1291,8 @@ TALER_KYCLOGIC_get_measure (
const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
const char *measure_name)
{
- return find_measure (lrs, measure_name);
+ return find_measure (lrs,
+ measure_name);
}
@@ -3745,6 +3746,21 @@ TALER_KYCLOGIC_check_form (
}
+const char *
+TALER_KYCLOGIC_get_aml_program_fallback (const char *prog_name)
+{
+ struct TALER_KYCLOGIC_AmlProgram *prog;
+
+ prog = find_program (prog_name);
+ if (NULL == prog)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ return prog->fallback;
+}
+
+
const struct TALER_KYCLOGIC_KycProvider *
TALER_KYCLOGIC_check_to_provider (const char *check_name)
{