commit 7b76f21accd51cea246b26ccb378a9f26114ec27
parent 733659b83b5e66ce07195a955ab6f1c38489545d
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 23 Sep 2025 17:09:25 +0200
fix #10444
Diffstat:
5 files changed, 188 insertions(+), 19 deletions(-)
diff --git a/src/backend/taler-merchant-donaukeyupdate.c b/src/backend/taler-merchant-donaukeyupdate.c
@@ -17,6 +17,7 @@
* @file taler-merchant-donaukeyupdate.c
* @brief Process that ensures our /keys data for all Donau instances is current
* @author Bohdan Potuzhnyi
+ * @author Christian Grothoff
*/
#include "platform.h"
#include "microhttpd.h"
@@ -728,7 +729,6 @@ force_donau_charity_id (void *cls,
extra,
sizeof(uint64_t));
di_serial = GNUNET_ntohll (di_serial);
-
qs = db_plugin->select_donau_instance_by_serial (db_plugin->cls,
di_serial,
&donau_url,
@@ -809,7 +809,8 @@ force_donau_keys (void *cls,
if (NULL == d)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Donau instance `%s' not found. Creating new instance.\n", url);
+ "Donau instance `%s' not found. Creating new instance.\n",
+ url);
d = GNUNET_new (struct Donau);
d->donau_url = GNUNET_strdup (url);
@@ -910,6 +911,75 @@ shutdown_task (void *cls)
/**
+ * Callback function typically used by `select_donau_instances` to handle
+ * the details of each Donau instance retrieved from the database.
+ *
+ * @param cls Closure to pass additional context or data to the callback function.
+ * @param donau_instance_serial Serial number of the Donau instance in the merchant database.
+ * @param donau_url The URL of the Donau instance.
+ * @param charity_name The name of the charity associated with the Donau instance.
+ * @param charity_pub_key Pointer to the charity's public key used for cryptographic operations.
+ * @param charity_id The unique identifier for the charity within the Donau instance.
+ * @param charity_max_per_year Maximum allowed donations to the charity for the current year.
+ * @param charity_receipts_to_date Total donations received by the charity so far in the current year.
+ * @param current_year The year for which the donation data is being tracked.
+ * @param donau_keys_json JSON object containing additional key-related information for the Donau instance.
+ */
+static void
+accept_donau (
+ void *cls,
+ uint64_t donau_instance_serial,
+ const char *donau_url,
+ const char *charity_name,
+ const struct DONAU_CharityPublicKeyP *charity_pub_key,
+ uint64_t charity_id,
+ const struct TALER_Amount *charity_max_per_year,
+ const struct TALER_Amount *charity_receipts_to_date,
+ int64_t current_year,
+ const json_t *donau_keys_json
+ )
+{
+ struct Donau *d;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Donau instance `%s' not found. Creating new instance.\n",
+ donau_url);
+ d = GNUNET_new (struct Donau);
+ d->donau_url = GNUNET_strdup (donau_url);
+ d->retry_delay = DONAU_MAXFREQ;
+ d->first_retry = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_ZERO);
+ GNUNET_CONTAINER_DLL_insert (d_head,
+ d_tail,
+ d);
+ if (NULL == donau_keys_json)
+ {
+ download_keys (d);
+ return;
+ }
+ d->keys = DONAU_keys_from_json (donau_keys_json);
+ if (NULL == d->keys)
+ {
+ GNUNET_break (0);
+ download_keys (d);
+ return;
+ }
+ d->retry_delay = DONAU_MAXFREQ;
+ d->first_retry = GNUNET_TIME_relative_to_absolute (DONAU_MAXFREQ);
+
+ {
+ struct GNUNET_TIME_Absolute n;
+
+ n = GNUNET_TIME_absolute_min (
+ d->first_retry,
+ d->keys->sign_keys[0].expire_sign.abs_time);
+ d->retry_task = GNUNET_SCHEDULER_add_at (n,
+ &download_keys,
+ d);
+ }
+}
+
+
+/**
* First task.
*
* @param cls closure, NULL
@@ -990,11 +1060,25 @@ run (void *cls,
NULL);
}
+ {
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = db_plugin->select_donau_instances (db_plugin->cls,
+ NULL,
+ &accept_donau,
+ NULL);
+ if (qs < 0)
+ {
+ GNUNET_break (0);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ }
if ( (0 == active_inquiries) &&
(test_mode) )
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "No donaukeys inquiries to start, exiting.\n");
+ "No donau keys inquiries to start, exiting.\n");
GNUNET_SCHEDULER_shutdown ();
return;
}
diff --git a/src/backenddb/pg_select_donau_instances.c b/src/backenddb/pg_select_donau_instances.c
@@ -122,11 +122,18 @@ select_donau_instance_cb (void *cls,
}
-enum GNUNET_DB_QueryStatus
-TMH_PG_select_donau_instances (void *cls,
- const char *id,
- TALER_MERCHANTDB_DonauInstanceCallback cb,
- void *cb_cls)
+/**
+ * Select all Donau instances (independent of instance) from the database.
+ *
+ * @param cls the closure for the database context
+ * @param cb callback function to call with each result
+ * @param cb_cls closure for the callback
+ * @return status of the PG
+ */
+static enum GNUNET_DB_QueryStatus
+select_all_donau_instances (void *cls,
+ TALER_MERCHANTDB_DonauInstanceCallback cb,
+ void *cb_cls)
{
struct PostgresClosure *pg = cls;
struct SelectDonauInstanceContext sdc = {
@@ -135,7 +142,63 @@ TMH_PG_select_donau_instances (void *cls,
/* Can be overwritten by the select_donau_instance_cb */
.extract_failed = false,
};
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ check_connection (pg);
+ PREPARE (pg,
+ "select_all_donau_instances",
+ "SELECT"
+ " di.donau_instances_serial"
+ ",di.donau_url"
+ ",di.charity_name"
+ ",mi.merchant_pub AS charity_pub_key"
+ ",di.charity_id"
+ ",di.charity_max_per_year"
+ ",di.charity_receipts_to_date"
+ ",di.current_year"
+ ",dk.keys_json"
+ " FROM merchant_donau_instances di"
+ " JOIN merchant_donau_keys dk"
+ " ON di.donau_url = dk.donau_url");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "select_all_donau_instances",
+ params,
+ &select_donau_instance_cb,
+ &sdc);
+
+ /* If there was an error inside select_donau_instance_cb, return a hard error. */
+ if (sdc.extract_failed)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+
+ return qs;
+}
+
+/**
+ * Select Donau instances from an instance @a id from the database.
+ *
+ * @param cls the closure for the database context
+ * @param id the ID of the merchant instance
+ * @param cb callback function to call with each result
+ * @param cb_cls closure for the callback
+ * @return status of the PG
+ */
+static enum GNUNET_DB_QueryStatus
+select_donau_instances (void *cls,
+ const char *id,
+ TALER_MERCHANTDB_DonauInstanceCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pg = cls;
+ struct SelectDonauInstanceContext sdc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ /* Can be overwritten by the select_donau_instance_cb */
+ .extract_failed = false,
+ };
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (id),
GNUNET_PQ_query_param_end
@@ -156,20 +219,42 @@ TMH_PG_select_donau_instances (void *cls,
",di.current_year"
",dk.keys_json"
" FROM merchant_donau_instances di"
- " JOIN merchant_donau_keys dk ON di.donau_url = dk.donau_url"
- " JOIN merchant_instances mi ON di.merchant_instance_serial = mi.merchant_serial"
+ " JOIN merchant_donau_keys dk"
+ " ON di.donau_url = dk.donau_url"
+ " JOIN merchant_instances mi"
+ " ON di.merchant_instance_serial = mi.merchant_serial"
" WHERE mi.merchant_id = $1");
-
-
qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
"select_donau_instances",
params,
&select_donau_instance_cb,
&sdc);
- /* If there was an error inside select_donau_instance_cb, return a hard error. */
+/* If there was an error inside select_donau_instance_cb, return a hard error. */
if (sdc.extract_failed)
return GNUNET_DB_STATUS_HARD_ERROR;
return qs;
-}
-\ No newline at end of file
+}
+
+
+enum GNUNET_DB_QueryStatus
+TMH_PG_select_donau_instances (void *cls,
+ const char *id,
+ TALER_MERCHANTDB_DonauInstanceCallback cb,
+ void *cb_cls)
+{
+ if (NULL == id)
+ {
+ return select_all_donau_instances (cls,
+ cb,
+ cb_cls);
+ }
+ else
+ {
+ return select_donau_instances (cls,
+ id,
+ cb,
+ cb_cls);
+ }
+}
diff --git a/src/backenddb/pg_select_donau_instances.h b/src/backenddb/pg_select_donau_instances.h
@@ -28,10 +28,10 @@
#include "taler_merchant_donau.h"
/**
- * Select multiple Donau instances from the database.
+ * Select Donau instances from the database.
*
* @param cls the closure for the database context
- * @param id the ID of the merchant instance
+ * @param id the ID of the merchant instance, NULL for all instances
* @param cb callback function to call with each result
* @param cb_cls closure for the callback
* @return status of the PG
diff --git a/src/include/taler_merchant_donau.h b/src/include/taler_merchant_donau.h
@@ -128,6 +128,7 @@ struct TALER_MERCHANTDB_DonauInstance
json_t *donau_keys_json;
};
+
/**
* Callback function typically used by `select_donau_instances` to handle
* the details of each Donau instance retrieved from the database.
@@ -393,4 +394,4 @@ void
TALER_MERCHANT_donau_instance_delete_cancel (
struct TALER_MERCHANT_DonauInstanceDeleteHandle *ddh);
-#endif
-\ No newline at end of file
+#endif
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
@@ -4317,6 +4317,7 @@ struct TALER_MERCHANTDB_Plugin
* Select all Donau instances.
*
* @param cls closure
+ * @param id instance to restrict to, NULL for all
* @param cb function to call on all Donau instances found
* @param cb_cls closure for @a cb
*/