gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated: implement #9303


From: gnunet
Subject: [taler-exchange] branch master updated: implement #9303
Date: Sun, 08 Dec 2024 19:15:37 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new bc30273e1 implement #9303
bc30273e1 is described below

commit bc30273e1810d4f78b199a3fbbed774d8518edcb
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Dec 8 19:15:13 2024 +0100

    implement #9303
---
 contrib/gana                                       |   2 +-
 src/exchangedb/Makefile.am                         |   2 +
 src/exchangedb/exchange_do_set_aml_lock.sql        |  46 +++++
 src/exchangedb/exchangedb_aml.c                    | 200 +++++++++++++++++++--
 .../{pg_update_auditor.c => pg_clear_aml_lock.c}   |  39 ++--
 src/exchangedb/pg_clear_aml_lock.h                 |  46 +++++
 src/exchangedb/pg_insert_kyc_requirement_process.c |   1 +
 src/exchangedb/pg_set_aml_lock.c                   |  74 ++++++++
 src/exchangedb/pg_set_aml_lock.h                   |  48 +++++
 src/exchangedb/pg_update_auditor.c                 |   2 +-
 src/exchangedb/plugin_exchangedb_postgres.c        |   6 +
 src/exchangedb/procedures.sql.in                   |   1 +
 src/include/taler_exchangedb_plugin.h              |  38 ++++
 src/include/taler_kyclogic_lib.h                   |  10 ++
 src/kyclogic/kyclogic_api.c                        |  18 +-
 15 files changed, 493 insertions(+), 40 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index e87822f88..4a422477b 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit e87822f88ce82d0d14df6673842b6523a2c371a1
+Subproject commit 4a422477b82fbe24a8cb623bbc2f085f3e4f7411
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index 0d99d9759..2755c7e70 100644
--- 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
new file mode 100644
index 000000000..377ea9797
--- /dev/null
+++ 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
index 147f25286..6d73a179e 100644
--- 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:
@@ -115,11 +119,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.
    */
@@ -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)
@@ -303,6 +321,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_update_auditor.c 
b/src/exchangedb/pg_clear_aml_lock.c
similarity index 51%
copy from src/exchangedb/pg_update_auditor.c
copy to src/exchangedb/pg_clear_aml_lock.c
index 167a270b9..a206f2275 100644
--- a/src/exchangedb/pg_update_auditor.c
+++ b/src/exchangedb/pg_clear_aml_lock.c
@@ -1,6 +1,6 @@
 /*
    This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
+   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
@@ -14,46 +14,37 @@
    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 /**
- * @file exchangedb/pg_update_auditor.c
- * @brief Implementation of the update_auditor function for Postgres
+ * @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_update_auditor.h"
+#include "pg_clear_aml_lock.h"
 #include "pg_helper.h"
 
 
 enum GNUNET_DB_QueryStatus
-TEH_PG_update_auditor (void *cls,
-                       const struct TALER_AuditorPublicKeyP *auditor_pub,
-                       const char *auditor_url,
-                       const char *auditor_name,
-                       struct GNUNET_TIME_Timestamp change_date,
-                       bool enabled)
+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 (auditor_pub),
-    GNUNET_PQ_query_param_string (auditor_url),
-    GNUNET_PQ_query_param_string (auditor_name),
-    GNUNET_PQ_query_param_bool (enabled),
-    GNUNET_PQ_query_param_timestamp (&change_date),
+    GNUNET_PQ_query_param_auto_from_type (h_payto),
+
     GNUNET_PQ_query_param_end
   };
-  /* used in #postgres_update_auditor() */
+
   PREPARE (pg,
-           "update_auditor",
-           "UPDATE auditors"
+           "clear_aml_lock",
+           "UPDATE wire_targets"
            " SET"
-           "  auditor_url=$2"
-           " ,auditor_name=$3"
-           " ,is_active=$4"
-           " ,last_change=$5"
-           " WHERE auditor_pub=$1");
+           "  aml_program_lock_timeout=NULL"
+           " WHERE h_normalized_payto=$1");
   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "update_auditor",
+                                             "clear_aml_lock",
                                              params);
 }
diff --git a/src/exchangedb/pg_clear_aml_lock.h 
b/src/exchangedb/pg_clear_aml_lock.h
new file mode 100644
index 000000000..489da196c
--- /dev/null
+++ 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
index 13a94219d..57424f46d 100644
--- 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
new file mode 100644
index 000000000..eb0143b98
--- /dev/null
+++ 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
new file mode 100644
index 000000000..f2b8aaaff
--- /dev/null
+++ 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
index 167a270b9..672bf0946 100644
--- 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
index a7457d991..febdbe2c7 100644
--- 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
index 038149275..16c1f2b2b 100644
--- 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
index be331a784..14bba3f36 100644
--- 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
index 92ea3ebed..82d10e551 100644
--- a/src/include/taler_kyclogic_lib.h
+++ b/src/include/taler_kyclogic_lib.h
@@ -409,6 +409,16 @@ json_t *
 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
diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c
index 952d52c0f..e14c573d5 100644
--- 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)
 {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]