summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-06-20 18:22:33 +0200
committerChristian Grothoff <christian@grothoff.org>2020-06-20 18:22:33 +0200
commitda5f393967e9a4e6b7c78b72f1c9f74a49bb52c6 (patch)
tree95e94f74d7c9661865a5dfe11c73fdc16147a188
parent9bae03573f31f22893839bbbbdaeba94821e3a57 (diff)
downloadmerchant-da5f393967e9a4e6b7c78b72f1c9f74a49bb52c6.tar.gz
merchant-da5f393967e9a4e6b7c78b72f1c9f74a49bb52c6.tar.bz2
merchant-da5f393967e9a4e6b7c78b72f1c9f74a49bb52c6.zip
start with reserve processing logic
-rw-r--r--src/backend/Makefile.am4
-rw-r--r--src/backend/taler-merchant-httpd.c16
-rw-r--r--src/backend/taler-merchant-httpd_private-post-reserves.c9
-rw-r--r--src/backend/taler-merchant-httpd_reserves.c142
-rw-r--r--src/backend/taler-merchant-httpd_reserves.h61
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c134
-rw-r--r--src/include/taler_merchantdb_plugin.h32
7 files changed, 384 insertions, 14 deletions
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 3682363f..bb3f2bf9 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -84,7 +84,9 @@ taler_merchant_httpd_SOURCES = \
taler-merchant-httpd_post-orders-ID-pay.c \
taler-merchant-httpd_post-orders-ID-pay.h \
taler-merchant-httpd_post-tips-ID-pickup.c \
- taler-merchant-httpd_post-tips-ID-pickup.h
+ taler-merchant-httpd_post-tips-ID-pickup.h \
+ taler-merchant-httpd_reserves.c \
+ taler-merchant-httpd_reserves.h
DEAD = \
taler-merchant-httpd_check-payment.c taler-merchant-httpd_check-payment.h \
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index 804e10e1..f3d8d757 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -59,7 +59,7 @@
#include "taler-merchant-httpd_post-orders-ID-claim.h"
#include "taler-merchant-httpd_post-orders-ID-pay.h"
#include "taler-merchant-httpd_post-tips-ID-pickup.h"
-
+#include "taler-merchant-httpd_reserves.h"
/**
* Backlog for listen operation on unix-domain sockets.
@@ -472,6 +472,7 @@ do_shutdown (void *cls)
MHD_stop_daemon (mhd);
mhd = NULL;
}
+ TMH_RESERVES_done ();
if (NULL != TMH_db)
{
TALER_MERCHANTDB_plugin_unload (TMH_db);
@@ -1361,6 +1362,11 @@ run (void *cls,
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
+ resume_timeout_heap
+ = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
+ payment_trigger_map
+ = GNUNET_CONTAINER_multihashmap_create (16,
+ GNUNET_YES);
if (GNUNET_OK !=
TALER_config_get_currency (cfg,
&TMH_currency))
@@ -1425,7 +1431,8 @@ run (void *cls,
return;
}
}
-
+ /* start watching reserves */
+ TMH_RESERVES_init ();
fh = TALER_MHD_bind (cfg,
"merchant",
&port);
@@ -1435,11 +1442,6 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
- resume_timeout_heap
- = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
- payment_trigger_map
- = GNUNET_CONTAINER_multihashmap_create (16,
- GNUNET_YES);
mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME | MHD_USE_DUAL_STACK,
port,
NULL, NULL,
diff --git a/src/backend/taler-merchant-httpd_private-post-reserves.c b/src/backend/taler-merchant-httpd_private-post-reserves.c
index 77854a19..01bba5d4 100644
--- a/src/backend/taler-merchant-httpd_private-post-reserves.c
+++ b/src/backend/taler-merchant-httpd_private-post-reserves.c
@@ -301,11 +301,10 @@ TMH_private_post_reserves (const struct TMH_RequestHandler *rh,
&rc->initial_balance,
rc->reserve_expiration);
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
- // Do this temporarily for testing
- qs = TMH_db->activate_reserve (TMH_db->cls,
- mi->settings.id,
- &reserve_pub,
- &rc->initial_balance);
+ TMH_RESERVES_check (mi->settings.id,
+ rc->exchange_url,
+ &reserve_pub,
+ &rc->initial_balance);
if (qs < 0)
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
diff --git a/src/backend/taler-merchant-httpd_reserves.c b/src/backend/taler-merchant-httpd_reserves.c
new file mode 100644
index 00000000..5876243b
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_reserves.c
@@ -0,0 +1,142 @@
+/*
+ This file is part of TALER
+ (C) 2020 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
+ 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 backend/taler-merchant-httpd_reserves.c
+ * @brief logic for initially tracking a reserve's status
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <taler/taler_json_lib.h>
+#include "taler-merchant-httpd.h"
+#include "taler-merchant-httpd_reserves.h"
+
+
+/**
+ * Our representation of a reserve that we are (still) checking the status of.
+ */
+struct Reserve
+{
+ /**
+ * Reserve's public key.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Amount the merchant expects to see in the reserve initially.
+ * We log a warning if there is a missmatch.
+ */
+ struct TALER_Amount expected_amount;
+
+ /**
+ * URL of the exchange hosting this reserve.
+ */
+ char *exchange_url;
+
+ /**
+ * Instance this reserve belongs with.
+ */
+ char *instance_id;
+};
+
+
+/**
+ * Function called with information about a reserve that we need
+ * to check the status from at the exchange to see if/when it has
+ * been filled (and with what amount).
+ *
+ * @param cls closure
+ * @param instance_id for which instance is this reserve
+ * @param exchange_url base URL of the exchange at which the reserve lives
+ * @param reserve_pub public key of the reserve
+ * @param expected_amount how much do we expect to see in the reserve
+ */
+static void
+add_reserve (void *cls,
+ const char *instance_id,
+ const char *exchange_url,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *expected_amount)
+{
+ struct Reserve *r;
+
+ r = GNUNET_new (struct Reserve);
+ r->exchange_url = GNUNET_strdup (exchange_url);
+ r->instance_id = GNUNET_strdup (instance_id);
+ r->reserve_pub = *reserve_pub;
+ r->expected_amount = *expected_amount;
+ // ....
+}
+
+
+/**
+ * Load information about reserves and start querying reserve status.
+ * Must be called after the database is available.
+ */
+void
+TMH_RESERVES_init (void)
+{
+ TMH_db->lookup_pending_reserves (TMH_db->cls,
+ &add_reserve,
+ NULL);
+}
+
+
+/**
+ * Add a reserve to the list of reserves to check.
+ *
+ * @param instance_id which instance is the reserve for
+ * @param exchange_url URL of the exchange with the reserve
+ * @param reserve_pub public key of the reserve to check
+ * @param expected_amount amount the merchant expects to see initially in the reserve
+ */
+void
+TMH_RESERVES_check (const char *instance_id,
+ const char *exchange_url,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *expected_amount)
+{
+ enum GNUNET_DB_QueryStatus qs;
+
+ add_reserve (NULL,
+ instance_id,
+ exchange_url,
+ reserve_pub,
+ expected_amount);
+
+ // Do this temporarily for testing
+ qs = TMH_db->activate_reserve (TMH_db->cls,
+ instance_id,
+ reserve_pub,
+ expected_amount); // FIXME: change to REAL amount later!
+ if (qs <= 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to commit reserve activation to database (%d)\n",
+ (int) qs);
+ }
+}
+
+
+/**
+ * Stop checking reserve status.
+ */
+void
+TMH_RESERVES_done (void)
+{
+}
+
+
+/* end of taler-merchant-httpd_reserves.c */
diff --git a/src/backend/taler-merchant-httpd_reserves.h b/src/backend/taler-merchant-httpd_reserves.h
new file mode 100644
index 00000000..e7cab1b9
--- /dev/null
+++ b/src/backend/taler-merchant-httpd_reserves.h
@@ -0,0 +1,61 @@
+/*
+ This file is part of TALER
+ (C) 2020 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
+ 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 backend/taler-merchant-httpd_reserves.h
+ * @brief logic for initially tracking a reserve's status
+ * @author Christian Grothoff
+ */
+#ifndef TALER_MERCHANT_HTTPD_RESERVES_H
+#define TALER_MERCHANT_HTTPD_RESERVES_H
+
+#include <jansson.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_util.h>
+#include <taler/taler_exchange_service.h>
+#include "taler-merchant-httpd.h"
+
+
+/**
+ * Load information about reserves and start querying reserve status.
+ * Must be called after the database is available.
+ */
+void
+TMH_RESERVES_init (void);
+
+
+/**
+ * Add a reserve to the list of reserves to check.
+ *
+ * @param instance_id which instance is the reserve for
+ * @param exchange_url URL of the exchange with the reserve
+ * @param reserve_pub public key of the reserve to check
+ * @param expected_amount amount the merchant expects to see initially in the reserve
+ */
+void
+TMH_RESERVES_check (const char *instance_id,
+ const char *exchange_url,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *expected_amount);
+
+
+/**
+ * Stop checking reserve status.
+ */
+void
+TMH_RESERVES_done (void);
+
+
+#endif
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index f218e438..12dc3498 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -4239,7 +4239,7 @@ postgres_activate_reserve (void *cls,
/**
- * Closure for #lookup_accounts_cb.
+ * Closure for #lookup_reserves_cb.
*/
struct LookupReservesContext
{
@@ -4420,6 +4420,123 @@ postgres_lookup_reserves (void *cls,
/**
+ * Closure for #lookup_pending_reserves_cb.
+ */
+struct LookupPendingReservesContext
+{
+ /**
+ * Postgres context.
+ */
+ struct PostgresClosure *pg;
+
+ /**
+ * Function to call with the results
+ */
+ TALER_MERCHANTDB_PendingReservesCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Set in case of errors.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about accounts.
+ *
+ * @param[in,out] cls of type `struct LookupReservesContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+lookup_pending_reserves_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupPendingReservesContext *lrc = cls;
+ struct PostgresClosure *pg = lrc->pg;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_Amount merchant_initial_balance;
+ char *exchange_url;
+ char *instance_id;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ GNUNET_PQ_result_spec_string ("exchange_url",
+ &exchange_url),
+ GNUNET_PQ_result_spec_string ("instance_id",
+ &instance_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("merchant_initial_balance",
+ &merchant_initial_balance),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ lrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ lrc->cb (lrc->cb_cls,
+ instance_id,
+ exchange_url,
+ &reserve_pub,
+ &merchant_initial_balance);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Lookup reserves pending activation across all instances.
+ *
+ * @param cls closure
+ * @param cb function to call with reserve summary data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_lookup_pending_reserves (void *cls,
+ TALER_MERCHANTDB_PendingReservesCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pg = cls;
+ struct LookupPendingReservesContext lrc = {
+ .pg = pg,
+ .cb = cb,
+ .cb_cls = cb_cls
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ check_connection (pg);
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "lookup_pending_reserves",
+ params,
+ &lookup_pending_reserves_cb,
+ &lrc);
+ if (lrc.qs < 0)
+ return lrc.qs;
+ return qs;
+}
+
+
+/**
* Closure for #lookup_reserve_tips_cb().
*/
struct LookupTipsContext
@@ -7572,6 +7689,20 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
" FROM merchant_instances"
" WHERE merchant_id=$1)",
2),
+ /* For postgres_lookup_pending_reserves() */
+ GNUNET_PQ_make_prepare ("lookup_pending_reserves",
+ "SELECT"
+ " reserve_pub"
+ ",merchant_id"
+ ",exchange_url"
+ ",merchant_initial_balance_val"
+ ",merchant_initial_balance_frac"
+ " FROM merchant_tip_reserves"
+ " JOIN merchant_instances USING (merchant_serial)"
+ " JOIN merchant_tip_reserve_keys USING (reserve_serial)"
+ " WHERE exchange_initial_balance_val=0"
+ " AND exchange_initial_balance_frac=0",
+ 0),
/* For postgres_lookup_reserve() */
GNUNET_PQ_make_prepare ("lookup_reserve",
"SELECT"
@@ -8011,6 +8142,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
plugin->insert_reserve = &postgres_insert_reserve;
plugin->activate_reserve = &postgres_activate_reserve;
plugin->lookup_reserves = &postgres_lookup_reserves;
+ plugin->lookup_pending_reserves = &postgres_lookup_pending_reserves;
plugin->lookup_reserve = &postgres_lookup_reserve;
plugin->delete_reserve = &postgres_delete_reserve;
plugin->purge_reserve = &postgres_purge_reserve;
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index e8c71546..abd1ef03 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -484,6 +484,24 @@ typedef void
/**
+ * Callback with details about a reserve pending exchange confirmation.
+ *
+ * @param cls closure
+ * @param instance_id for which instance is this reserve
+ * @param exchange_url base URL of the exchange
+ * @param reserve_pub public key of the reserve
+ * @param expected_amount how much do we expect to see in the reserve
+ */
+typedef void
+(*TALER_MERCHANTDB_PendingReservesCallback)(
+ void *cls,
+ const char *instance_id,
+ const char *exchange_url,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *expected_amount);
+
+
+/**
* Details about a tip.
*/
struct TALER_MERCHANTDB_TipDetails
@@ -1703,6 +1721,20 @@ struct TALER_MERCHANTDB_Plugin
/**
+ * Lookup reserves pending activation across all instances.
+ *
+ * @param cls closure
+ * @param cb function to call with reserve data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*lookup_pending_reserves)(void *cls,
+ TALER_MERCHANTDB_PendingReservesCallback cb,
+ void *cb_cls);
+
+
+ /**
* Lookup reserve details.
*
* @param cls closure