gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] 65/277: db implementation of claiming


From: gnunet
Subject: [taler-merchant] 65/277: db implementation of claiming
Date: Sun, 05 Jul 2020 20:49:38 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

commit e3d91bf74804871c5d7438a0b04265b69feba34a
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Mon Apr 27 15:58:32 2020 +0200

    db implementation of claiming
---
 src/backend/merchant.conf                          |   4 +
 src/backend/taler-merchant-httpd.c                 |  19 +
 src/backend/taler-merchant-httpd.h                 |   8 +
 .../taler-merchant-httpd_post-orders-ID-claim.c    |  14 +-
 ...taler-merchant-httpd_private-delete-orders-ID.c |  14 +-
 src/backenddb/plugin_merchantdb_postgres.c         | 638 +++++---------
 src/backenddb/test_merchantdb.c                    | 970 +--------------------
 src/include/taler_merchantdb_plugin.h              |  33 +-
 8 files changed, 294 insertions(+), 1406 deletions(-)

diff --git a/src/backend/merchant.conf b/src/backend/merchant.conf
index 4aac2da..6a0cc53 100644
--- a/src/backend/merchant.conf
+++ b/src/backend/merchant.conf
@@ -17,6 +17,10 @@ PORT = 9966
 # if left empty.  Only used if "SERVE" is 'tcp'.
 # BIND_TO =
 
+# How long do we keep contract / payment information around after the
+# purchase (for tax records and other legal reasons).
+LEGAL_PRESERVATION = 11 years
+
 
 # Which unix domain path should we bind to? Only used if "SERVE" is 'unix'.
 UNIXPATH = ${TALER_RUNTIME_DIR}/merchant.http
diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index 7406d1f..f11d18c 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -73,6 +73,13 @@ struct TALER_MERCHANTDB_Plugin *TMH_db;
  */
 struct GNUNET_CONTAINER_MultiHashMap *TMH_by_id_map;
 
+/**
+ * How long do we need to keep information on paid contracts on file for tax
+ * or other legal reasons?  Used to block deletions for younger transaction
+ * data.
+ */
+struct GNUNET_TIME_Relative TMH_legal_expiration;
+
 /**
  * The port we are running on
  */
@@ -1189,6 +1196,18 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg,
+                                           "merchant",
+                                           "LEGAL_PRESERVATION",
+                                           &TMH_legal_expiration))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "merchant",
+                               "LEGAL_PRESERVATION");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
   if (GNUNET_YES ==
       GNUNET_CONFIGURATION_get_value_yesno (cfg,
                                             "merchant",
diff --git a/src/backend/taler-merchant-httpd.h 
b/src/backend/taler-merchant-httpd.h
index a6867e2..ceb7dfe 100644
--- a/src/backend/taler-merchant-httpd.h
+++ b/src/backend/taler-merchant-httpd.h
@@ -352,6 +352,14 @@ extern struct TALER_MERCHANTDB_Plugin *TMH_db;
  */
 extern struct GNUNET_CONTAINER_MultiHashMap *TMH_by_id_map;
 
+/**
+ * How long do we need to keep information on paid contracts on file for tax
+ * or other legal reasons?  Used to block deletions for younger transaction
+ * data.
+ */
+extern struct GNUNET_TIME_Relative TMH_legal_expiration;
+
+
 /**
  * Kick MHD to run now, to be called after MHD_resume_connection().
  * Basically, we need to explicitly resume MHD's event loop whenever
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-claim.c 
b/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
index e58a73c..6b3a922 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
@@ -31,7 +31,7 @@
 
 
 /**
- * How often do we retry the simple INSERT database transaction?
+ * How often do we retry the database transaction?
  */
 #define MAX_RETRIES 3
 
@@ -103,7 +103,17 @@ claim_order (const char *instance_id,
       *contract_terms = NULL;
       return qs;
     }
-    // FIXME: should we remove the ORDER from the order table here?
+    qs = TMH_db->delete_order (TMH_db->cls,
+                               instance_id,
+                               order_id);
+    if (0 >= qs)
+    {
+      GNUNET_break (0);
+      TMH_db->rollback (TMH_db->cls);
+      json_decref (*contract_terms);
+      *contract_terms = NULL;
+      return qs;
+    }
     qs = TMH_db->commit (TMH_db->cls);
     if (0 > qs)
       return qs;
diff --git a/src/backend/taler-merchant-httpd_private-delete-orders-ID.c 
b/src/backend/taler-merchant-httpd_private-delete-orders-ID.c
index f699bdc..7399432 100644
--- a/src/backend/taler-merchant-httpd_private-delete-orders-ID.c
+++ b/src/backend/taler-merchant-httpd_private-delete-orders-ID.c
@@ -40,13 +40,14 @@ TMH_private_delete_orders_ID (const struct 
TMH_RequestHandler *rh,
   enum GNUNET_DB_QueryStatus qs;
 
   GNUNET_assert (NULL != mi);
-  // FIXME: do we delete ORDERS or (claimed) contract_terms?
-  // FIXME: what SHOULD be the semantics here?
-  // NOTE: We MAY need the delete_order() DB API to
-  //       clean up the order table when claiming orders...
   qs = TMH_db->delete_order (TMH_db->cls,
                              mi->settings.id,
                              hc->infix);
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+    qs = TMH_db->delete_contract_terms (TMH_db->cls,
+                                        mi->settings.id,
+                                        hc->infix,
+                                        TMH_legal_expiration);
   switch (qs)
   {
   case GNUNET_DB_STATUS_HARD_ERROR:
@@ -65,6 +66,11 @@ TMH_private_delete_orders_ID (const struct 
TMH_RequestHandler *rh,
                                mi->settings.id,
                                hc->infix,
                                NULL);
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+      qs = TMH_db->lookup_contract_terms (TMH_db->cls,
+                                          mi->settings.id,
+                                          hc->infix,
+                                          NULL);
     if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
       return TALER_MHD_reply_with_error (connection,
                                          MHD_HTTP_NOT_FOUND,
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index bb43fd4..f02d090 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -26,6 +26,7 @@
 #include <taler/taler_util.h>
 #include <taler/taler_pq_lib.h>
 #include <taler/taler_json_lib.h>
+#include <taler/taler_mhd_lib.h>
 #include "taler_merchantdb_plugin.h"
 
 /**
@@ -1351,28 +1352,25 @@ postgres_insert_order_lock (void *cls,
 }
 
 
-/* ********************* OLD API ************************** */
-
 /**
- * Retrieve proposal data given its proposal data's hashcode
+ * Retrieve contract terms given its @a order_id
  *
  * @param cls closure
- * @param contract_terms where to store the retrieved proposal data
- * @param h_contract_terms proposal data's hashcode that will be used to
- * perform the lookup
+ * @param instance_id instance's identifier
+ * @param order_id order_id used to lookup.
+ * @param[out] contract_terms where to store the result, NULL to only check 
for existence
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_find_contract_terms_from_hash (
-  void *cls,
-  json_t **contract_terms,
-  const struct GNUNET_HashCode *h_contract_terms,
-  const struct TALER_MerchantPublicKeyP *merchant_pub)
+postgres_lookup_contract_terms (void *cls,
+                                const char *instance_id,
+                                const char *order_id,
+                                json_t **contract_terms)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (order_id),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
@@ -1381,73 +1379,149 @@ postgres_find_contract_terms_from_hash (
     GNUNET_PQ_result_spec_end
   };
 
+  *contract_terms = NULL;
   check_connection (pg);
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"find_contract_terms_from_hash",
+                                                   "lookup_contract_terms",
                                                    params,
                                                    rs);
 }
 
 
 /**
- * Retrieve proposal data given its proposal data's hashcode
+ * Store contract terms given its @a order_id. Note that some attributes are
+ * expected to be calculated inside of the function, like the hash of the
+ * contract terms (to be hashed), the creation_time and pay_deadline (to be
+ * obtained from the merchant_orders table). The "session_id" should be
+ * initially set to the empty string.  The "fulfillment_url" and 
"refund_deadline"
+ * must be extracted from @a contract_terms.
  *
  * @param cls closure
- * @param contract_terms where to store the retrieved proposal data
- * @param h_contract_terms proposal data's hashcode that will be used to
- * perform the lookup
- * @return transaction status
+ * @param instance_id instance's identifier
+ * @param order_id order_id used to store
+ * @param contract_terms contract to store
+ * @return transaction status, #GNUNET_DB_STATUS_HARD_ERROR if @a 
contract_terms
+ *          is malformed
  */
 static enum GNUNET_DB_QueryStatus
-postgres_find_paid_contract_terms_from_hash (void *cls,
-                                             json_t **contract_terms,
-                                             const struct
-                                             GNUNET_HashCode *h_contract_terms,
-                                             const struct
-                                             TALER_MerchantPublicKeyP *
-                                             merchant_pub)
+postgres_insert_contract_terms (void *cls,
+                                const char *instance_id,
+                                const char *order_id,
+                                json_t *contract_terms)
 {
   struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute pay_deadline;
+  struct GNUNET_TIME_Absolute refund_deadline;
+  const char *fulfillment_url;
+  struct GNUNET_HashCode h_contract_terms;
+
+  if (GNUNET_OK !=
+      TALER_JSON_hash (contract_terms,
+                       &h_contract_terms))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  {
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_string ("fulfillment_url",
+                               &fulfillment_url),
+      GNUNET_JSON_spec_absolute_time ("pay_deadline",
+                                      &pay_deadline),
+      GNUNET_JSON_spec_absolute_time ("refund_deadline",
+                                      &refund_deadline),
+      GNUNET_JSON_spec_end ()
+    };
+    enum GNUNET_GenericReturnValue res;
+
+    res = TALER_MHD_parse_json_data (NULL,
+                                     contract_terms,
+                                     spec);
+    if (GNUNET_OK != res)
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
+
+  check_connection (pg);
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_string (instance_id),
+      GNUNET_PQ_query_param_string (order_id),
+      TALER_PQ_query_param_json (contract_terms),
+      GNUNET_PQ_query_param_auto_from_type (&h_contract_terms),
+      GNUNET_PQ_query_param_absolute_time (&pay_deadline),
+      GNUNET_PQ_query_param_absolute_time (&refund_deadline),
+      GNUNET_PQ_query_param_string (fulfillment_url),
+      GNUNET_PQ_query_param_end
+    };
+
+    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "insert_contract_terms",
+                                               params);
+  }
+}
+
+
+/**
+ * Delete information about a contract. Note that the transaction must
+ * enforce that the contract is not awaiting payment anymore AND was not
+ * paid, or is past the legal expiration.
+ *
+ * @param cls closure
+ * @param instance_id instance to delete order of
+ * @param order_id order to delete
+ * @param legal_expiration how long do we need to keep (paid) contracts on
+ *          file for legal reasons (i.e. taxation)
+ * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+ *           if locks prevent deletion OR order unknown
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_delete_contract_terms (void *cls,
+                                const char *instance_id,
+                                const char *order_id,
+                                struct GNUNET_TIME_Relative legal_expiration)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_string (order_id),
+    GNUNET_PQ_query_param_relative_time (&legal_expiration),
+    GNUNET_PQ_query_param_absolute_time (&now),
     GNUNET_PQ_query_param_end
   };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_result_spec_json ("contract_terms",
-                               contract_terms),
-    GNUNET_PQ_result_spec_end
-  };
 
-  /* no preflight check here, runs in its own transaction from
-     caller (in /pay case) */
   check_connection (pg);
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"find_paid_contract_terms_from_hash",
-                                                   params,
-                                                   rs);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "delete_contract_terms",
+                                             params);
 }
 
 
+/* ********************* OLD API ************************** */
+
 /**
- * Retrieve proposal data given its order id.  Ignores if the
- * proposal has been paid or not.
+ * Retrieve proposal data given its proposal data's hashcode
  *
  * @param cls closure
- * @param[out] contract_terms where to store the retrieved contract terms
- * @param order id order id used to perform the lookup
+ * @param contract_terms where to store the retrieved proposal data
+ * @param h_contract_terms proposal data's hashcode that will be used to
+ * perform the lookup
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_find_contract_terms (void *cls,
-                              json_t **contract_terms,
-                              const char *order_id,
-                              const struct
-                              TALER_MerchantPublicKeyP *merchant_pub)
+postgres_find_contract_terms_from_hash (
+  void *cls,
+  json_t **contract_terms,
+  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_MerchantPublicKeyP *merchant_pub)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (order_id),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
@@ -1457,64 +1531,51 @@ postgres_find_contract_terms (void *cls,
     GNUNET_PQ_result_spec_end
   };
 
-  *contract_terms = NULL;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Finding contract term, order_id: '%s', merchant_pub: '%s'.\n",
-              order_id,
-              TALER_B2S (merchant_pub));
   check_connection (pg);
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "find_contract_terms",
+                                                   
"find_contract_terms_from_hash",
                                                    params,
                                                    rs);
 }
 
 
 /**
- * Insert proposal data and its hashcode into db
+ * Retrieve proposal data given its proposal data's hashcode
  *
  * @param cls closure
- * @param order_id identificator of the proposal being stored
- * @param merchant_pub merchant's public key
- * @param timestamp timestamp of this proposal data
- * @param contract_terms proposal data to store
+ * @param contract_terms where to store the retrieved proposal data
+ * @param h_contract_terms proposal data's hashcode that will be used to
+ * perform the lookup
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_insert_contract_terms (void *cls,
-                                const char *order_id,
-                                const struct
-                                TALER_MerchantPublicKeyP *merchant_pub,
-                                struct GNUNET_TIME_Absolute timestamp,
-                                const json_t *contract_terms)
+postgres_find_paid_contract_terms_from_hash (void *cls,
+                                             json_t **contract_terms,
+                                             const struct
+                                             GNUNET_HashCode *h_contract_terms,
+                                             const struct
+                                             TALER_MerchantPublicKeyP *
+                                             merchant_pub)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_HashCode h_contract_terms;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (order_id),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_absolute_time (&timestamp),
-    TALER_PQ_query_param_json (contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (&h_contract_terms),
     GNUNET_PQ_query_param_end
   };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_result_spec_json ("contract_terms",
+                               contract_terms),
+    GNUNET_PQ_result_spec_end
+  };
 
-  if (GNUNET_OK !=
-      TALER_JSON_hash (contract_terms,
-                       &h_contract_terms))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "inserting contract terms: order_id: %s, merchant_pub: %s, 
h_contract_terms: %s.\n",
-              order_id,
-              TALER_B2S (merchant_pub),
-              GNUNET_h2s (&h_contract_terms));
+  /* no preflight check here, runs in its own transaction from
+     caller (in /pay case) */
   check_connection (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_contract_terms",
-                                             params);
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"find_paid_contract_terms_from_hash",
+                                                   params,
+                                                   rs);
 }
 
 
@@ -1764,205 +1825,6 @@ postgres_store_transfer_to_proof (void *cls,
 }
 
 
-/**
- * Lookup for a proposal, respecting the signature used by the
- * /history's db methods.
- *
- * @param cls db plugin handle
- * @param order_id order id used to search for the proposal data
- * @param merchant_pub public key of the merchant using this method
- * @param cb the callback
- * @param cb_cls closure to pass to the callback
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_find_contract_terms_history (void *cls,
-                                      const char *order_id,
-                                      const struct
-                                      TALER_MerchantPublicKeyP *merchant_pub,
-                                      TALER_MERCHANTDB_ProposalDataCallback cb,
-                                      void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  json_t *contract_terms;
-  enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (order_id),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_result_spec_json ("contract_terms",
-                               &contract_terms),
-    GNUNET_PQ_result_spec_end
-  };
-
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "find_contract_terms_history",
-                                                 params,
-                                                 rs);
-  if (qs <= 0)
-    return qs;
-  if (NULL != cb)
-    cb (cb_cls,
-        order_id,
-        0,
-        contract_terms);
-  GNUNET_PQ_cleanup_result (rs);
-  return qs;
-}
-
-
-/**
- * Closure for #find_contracts_cb().
- */
-struct FindContractsContext
-{
-  /**
-   * Function to call on each result.
-   */
-  TALER_MERCHANTDB_ProposalDataCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Transaction status code to set.
-   */
-  enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls of type `struct FindContractsContext *`
- * @param result the postgres result
- * @param num_result the number of results in @a result
- */
-static void
-find_contracts_cb (void *cls,
-                   PGresult *result,
-                   unsigned int num_results)
-{
-  struct FindContractsContext *fcctx = cls;
-
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    char *order_id;
-    json_t *contract_terms;
-    uint64_t row_id;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_string ("order_id",
-                                    &order_id),
-      TALER_PQ_result_spec_json ("contract_terms",
-                                 &contract_terms),
-      GNUNET_PQ_result_spec_uint64 ("row_id",
-                                    &row_id),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      fcctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
-      return;
-    }
-    fcctx->qs = i + 1;
-    fcctx->cb (fcctx->cb_cls,
-               order_id,
-               row_id,
-               contract_terms);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
- * Return proposals whose timestamp are older than `date`.
- * Among those proposals, only those ones being between the
- * start-th and (start-nrows)-th record are returned.  The rows
- * are sorted having the youngest first.
- *
- * @param cls our plugin handle.
- * @param date only results older than this date are returned.
- * @param merchant_pub instance's public key; only rows related to this
- * instance are returned.
- * @param start only rows with serial id less than start are returned.
- * In other words, you lower `start` to get older records. The tipical
- * usage is to firstly call `find_contract_terms_by_date`, so that you get
- * the `nrows` youngest records. The oldest of those records will tell you
- * from which timestamp and `start` you can query the DB in order to get
- * furtherly older records, and so on. Alternatively, you can use always
- * the same timestamp and just go behind in history by tuning `start`.
- * @param nrows only nrows rows are returned.
- * @param past if set to #GNUNET_YES, retrieves rows older than `date`.
- * @param ascending if #GNUNET_YES, results will be sorted in chronological 
order.
- * This is typically used to show live updates on the merchant's backoffice
- * Web interface.
- * @param cb function to call with transaction data, can be NULL.
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_find_contract_terms_by_date_and_range (void *cls,
-                                                struct GNUNET_TIME_Absolute
-                                                date,
-                                                const struct
-                                                TALER_MerchantPublicKeyP *
-                                                merchant_pub,
-                                                uint64_t start,
-                                                uint64_t nrows,
-                                                int past,
-                                                unsigned int ascending,
-                                                
TALER_MERCHANTDB_ProposalDataCallback
-                                                cb,
-                                                void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_absolute_time (&date),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_uint64 (&start),
-    GNUNET_PQ_query_param_uint64 (&nrows),
-    GNUNET_PQ_query_param_end
-  };
-  const char *stmt;
-  enum GNUNET_DB_QueryStatus qs;
-  struct FindContractsContext fcctx = {
-    .cb = cb,
-    .cb_cls = cb_cls
-  };
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "DB serving /history with date %s\n",
-              GNUNET_STRINGS_absolute_time_to_string (date));
-  stmt =
-    (GNUNET_YES == past)
-    ? ( (GNUNET_YES == ascending)
-        ? "find_contract_terms_by_date_and_range_past_asc"
-        : "find_contract_terms_by_date_and_range_past")
-    : ( (GNUNET_YES == ascending)
-        ? "find_contract_terms_by_date_and_range_asc"
-        : "find_contract_terms_by_date_and_range");
-  check_connection (pg);
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             stmt,
-                                             params,
-                                             &find_contracts_cb,
-                                             &fcctx);
-  if (0 >= qs)
-    return qs;
-  return fcctx.qs;
-}
-
-
 /**
  * Closure for #find_tip_authorizations_cb().
  */
@@ -2103,53 +1965,6 @@ postgres_get_authorized_tip_amount (void *cls,
 }
 
 
-/**
- * Return proposals whose timestamp are older than `date`.
- * The rows are sorted having the youngest first.
- *
- * @param cls our plugin handle.
- * @param date only results older than this date are returned.
- * @param merchant_pub instance's public key; only rows related to this
- * instance are returned.
- * @param nrows at most nrows rows are returned.
- * @param cb function to call with transaction data, can be NULL.
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_find_contract_terms_by_date (void *cls,
-                                      struct GNUNET_TIME_Absolute date,
-                                      const struct
-                                      TALER_MerchantPublicKeyP *merchant_pub,
-                                      uint64_t nrows,
-                                      TALER_MERCHANTDB_ProposalDataCallback cb,
-                                      void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_absolute_time (&date),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_uint64 (&nrows),
-    GNUNET_PQ_query_param_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-  struct FindContractsContext fcctx = {
-    .cb = cb,
-    .cb_cls = cb_cls
-  };
-
-  check_connection (pg);
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "find_contract_terms_by_date",
-                                             params,
-                                             &find_contracts_cb,
-                                             &fcctx);
-  if (0 >= qs)
-    return qs;
-  return fcctx.qs;
-}
-
-
 /**
  * Closure for #find_payments_cb().
  */
@@ -5136,7 +4951,60 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             "        FROM merchant_order_locks"
                             "        WHERE product_serial=tmp.product_serial)",
                             4),
+    /* for postgres_lookup_contract_terms() */
+    GNUNET_PQ_make_prepare ("lookup_contract_terms",
+                            "SELECT contract_terms"
+                            " FROM merchant_contract_terms"
+                            " WHERE order_id=$2"
+                            "   AND merchant_serial="
+                            "     (SELECT merchant_serial"
+                            "        FROM merchant_instances"
+                            "        WHERE merchant_id=$1)",
+                            2),
+    /* for postgres_insert_contract_terms() */
+    GNUNET_PQ_make_prepare ("insert_contract_terms",
+                            "INSERT INTO merchant_contract_terms"
+                            "(order_serial"
+                            ",merchant_serial"
+                            ",order_id"
+                            ",contract_terms"
+                            ",h_contract_terms"
+                            ",creation_time"
+                            ",pay_deadline"
+                            ",refund_deadline"
+                            ",fulfillment_url)"
+                            "SELECT"
+                            " order_serial"
+                            ",merchant_serial"
+                            ",order_id"
+                            ",$3"  /* contract_terms */
+                            ",$4"  /* h_contract_terms */
+                            ",creation_time"
+                            ",$5" /* pay_deadline */
+                            ",$6" /* refund_deadline */
+                            ",$7" /* fulfillment_url */
+                            "FROM merchant_orders"
+                            " WHERE order_id=$2"
+                            "   AND merchant_serial="
+                            "     (SELECT merchant_serial"
+                            "        FROM merchant_instances"
+                            "        WHERE merchant_id=$1)",
+                            7),
+    /* for postgres_delete_contract_terms() */
+    GNUNET_PQ_make_prepare ("delete_contract_terms",
+                            "DELETE FROM merchant_contract_terms"
+                            " WHERE order_id=$2"
+                            "   AND merchant_serial="
+                            "     (SELECT merchant_serial"
+                            "        FROM merchant_instances"
+                            "        WHERE merchant_id=$1)"
+                            "   AND ( ( (pay_deadline < $4) AND"
+                            "           (NOT paid) ) OR"
+                            "         (creation_time + $3 > $4) )",
+                            4),
+
     /* OLD API: */
+
 #if 0
     GNUNET_PQ_make_prepare ("insert_deposit",
                             "INSERT INTO merchant_deposits"
@@ -5253,7 +5121,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             "   AND merchant_pub=$2"
                             "   AND paid=TRUE",
                             2),
-
     GNUNET_PQ_make_prepare ("find_refunds",
                             "SELECT"
                             " refund_amount_val"
@@ -5261,23 +5128,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             " FROM merchant_refunds"
                             " WHERE coin_pub=$1",
                             1),
-    GNUNET_PQ_make_prepare ("find_contract_terms_history",
-                            "SELECT"
-                            " contract_terms"
-                            " FROM merchant_contract_terms"
-                            " WHERE"
-                            " order_id=$1"
-                            " AND merchant_pub=$2"
-                            " AND paid=TRUE",
-                            2),
-    GNUNET_PQ_make_prepare ("find_contract_terms",
-                            "SELECT"
-                            " contract_terms"
-                            " FROM merchant_contract_terms"
-                            " WHERE"
-                            " order_id=$1"
-                            " AND merchant_pub=$2",
-                            2),
     GNUNET_PQ_make_prepare ("find_session_info",
                             "SELECT"
                             " order_id"
@@ -5287,19 +5137,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             " AND session_id=$2"
                             " AND merchant_pub=$3",
                             2),
-    GNUNET_PQ_make_prepare ("find_contract_terms_by_date",
-                            "SELECT"
-                            " contract_terms"
-                            ",order_id"
-                            ",row_id"
-                            " FROM merchant_contract_terms"
-                            " WHERE"
-                            " timestamp<$1"
-                            " AND merchant_pub=$2"
-                            " AND paid=TRUE"
-                            " ORDER BY row_id DESC, timestamp DESC"
-                            " LIMIT $3",
-                            3),
     GNUNET_PQ_make_prepare ("find_refunds_from_contract_terms_hash",
                             "SELECT"
                             " coin_pub"
@@ -5337,62 +5174,6 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             " VALUES "
                             "($1, $2, $3, $4, $5, $6)",
                             6),
-    GNUNET_PQ_make_prepare ("find_contract_terms_by_date_and_range_asc",
-                            "SELECT"
-                            " contract_terms"
-                            ",order_id"
-                            ",row_id"
-                            " FROM merchant_contract_terms"
-                            " WHERE"
-                            " timestamp>$1"
-                            " AND merchant_pub=$2"
-                            " AND row_id>$3"
-                            " AND paid=TRUE"
-                            " ORDER BY row_id ASC, timestamp ASC"
-                            " LIMIT $4",
-                            4),
-    GNUNET_PQ_make_prepare ("find_contract_terms_by_date_and_range",
-                            "SELECT"
-                            " contract_terms"
-                            ",order_id"
-                            ",row_id"
-                            " FROM merchant_contract_terms"
-                            " WHERE"
-                            " timestamp>$1"
-                            " AND merchant_pub=$2"
-                            " AND row_id>$3"
-                            " AND paid=TRUE"
-                            " ORDER BY row_id DESC, timestamp DESC"
-                            " LIMIT $4",
-                            4),
-    GNUNET_PQ_make_prepare ("find_contract_terms_by_date_and_range_past_asc",
-                            "SELECT"
-                            " contract_terms"
-                            ",order_id"
-                            ",row_id"
-                            " FROM merchant_contract_terms"
-                            " WHERE"
-                            " timestamp<$1"
-                            " AND merchant_pub=$2"
-                            " AND row_id<$3"
-                            " AND paid=TRUE"
-                            " ORDER BY row_id ASC, timestamp ASC"
-                            " LIMIT $4",
-                            4),
-    GNUNET_PQ_make_prepare ("find_contract_terms_by_date_and_range_past",
-                            "SELECT"
-                            " contract_terms"
-                            ",order_id"
-                            ",row_id"
-                            " FROM merchant_contract_terms"
-                            " WHERE"
-                            " timestamp<$1"
-                            " AND merchant_pub=$2"
-                            " AND row_id<$3"
-                            " AND paid=TRUE"
-                            " ORDER BY row_id DESC, timestamp DESC"
-                            " LIMIT $4",
-                            4),
     GNUNET_PQ_make_prepare ("find_deposits",
                             "SELECT"
                             " coin_pub"
@@ -5634,7 +5415,14 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
   plugin->insert_order = &postgres_insert_order;
   plugin->unlock_inventory = &postgres_unlock_inventory;
   plugin->insert_order_lock = &postgres_insert_order_lock;
-  /* old API: */
+  plugin->lookup_contract_terms = &postgres_lookup_contract_terms;
+  plugin->insert_contract_terms = &postgres_insert_contract_terms;
+  plugin->delete_contract_terms = &postgres_delete_contract_terms;
+  /* OLD API: */
+  plugin->find_contract_terms_from_hash =
+    &postgres_find_contract_terms_from_hash;
+  plugin->find_paid_contract_terms_from_hash =
+    &postgres_find_paid_contract_terms_from_hash;
   plugin->store_deposit = &postgres_store_deposit;
   plugin->store_coin_to_transfer = &postgres_store_coin_to_transfer;
   plugin->store_transfer_to_proof = &postgres_store_transfer_to_proof;
@@ -5645,17 +5433,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
   plugin->find_transfers_by_hash = &postgres_find_transfers_by_hash;
   plugin->find_deposits_by_wtid = &postgres_find_deposits_by_wtid;
   plugin->find_proof_by_wtid = &postgres_find_proof_by_wtid;
-  plugin->insert_contract_terms = &postgres_insert_contract_terms;
-  plugin->find_contract_terms = &postgres_find_contract_terms;
-  plugin->find_contract_terms_history = &postgres_find_contract_terms_history;
-  plugin->find_contract_terms_by_date = &postgres_find_contract_terms_by_date;
   plugin->get_authorized_tip_amount = &postgres_get_authorized_tip_amount;
-  plugin->find_contract_terms_by_date_and_range =
-    &postgres_find_contract_terms_by_date_and_range;
-  plugin->find_contract_terms_from_hash =
-    &postgres_find_contract_terms_from_hash;
-  plugin->find_paid_contract_terms_from_hash =
-    &postgres_find_paid_contract_terms_from_hash;
   plugin->get_refunds_from_contract_terms_hash =
     &postgres_get_refunds_from_contract_terms_hash;
   plugin->lookup_wire_fee = &postgres_lookup_wire_fee;
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index 20d0247..fdcf879 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014-2017 Taler Systems SA
+  (C) 2014-2017, 2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Lesser General Public License as published by the Free 
Software
@@ -19,37 +19,12 @@
  * @author Marcello Stanisci
  * @author Christian Grothoff
  */
-
 #include "platform.h"
 #include <taler/taler_util.h>
 #include <taler/taler_json_lib.h>
 #include "taler_merchantdb_lib.h"
-#include <jansson.h>
-
-
-#define FAILIF(cond)                            \
-  do {                                          \
-    if (! (cond)) { break;}                       \
-    GNUNET_break (0);                           \
-    return;                                  \
-  } while (0)
-
-#define RND_BLK(ptr)                                                    \
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr))
 
 
-/**
- * Currency we use for the coins.
- */
-#define CURRENCY "EUR"
-
-/**
- * URL we use for the exchange in the database.
- * Note that an exchange does not actually have
- * to run at this address.
- */
-#define EXCHANGE_URL "http://localhost:8888/";
-
 /**
  * Global return value for the test.  Initially -1, set to 0 upon
  * completion.  Other values indicate some kind of error.
@@ -61,937 +36,6 @@ static int result;
  */
 static struct TALER_MERCHANTDB_Plugin *plugin;
 
-/**
- * Hash of the wire transfer address.  Set to some random value.
- */
-static struct GNUNET_HashCode h_wire;
-
-/**
- * Transaction ID.
- */
-const char *order_id;
-
-/**
- * Transaction ID used to test the db query
- * `find_contract_terms_by_date_and_range_future`
- */
-const char *order_id_future;
-
-/**
- * Proposal's hash
- */
-struct GNUNET_HashCode h_contract_terms;
-
-/**
- * Proposal's hash.
- */
-struct GNUNET_HashCode h_contract_terms_future;
-
-/**
- * Time of the transaction.
- */
-static struct GNUNET_TIME_Absolute timestamp;
-
-/**
- * Delta aimed to test the "by_date" query on transactions.
- */
-static struct GNUNET_TIME_Relative delta;
-
-/**
- * Deadline until which refunds are allowed.
- */
-static struct GNUNET_TIME_Absolute refund_deadline;
-
-/**
- * Total amount, including deposit fee.
- */
-static struct TALER_Amount amount_with_fee;
-
-/**
- * Deposit fee for the coin.
- */
-static struct TALER_Amount deposit_fee;
-
-/**
- * Wire fee of the exchange.
- */
-static struct TALER_Amount wire_fee;
-
-/**
- * Refund fee for the coin.
- */
-static struct TALER_Amount refund_fee;
-
-/**
- * Amount to be refunded.
- */
-static struct TALER_Amount refund_amount;
-
-/**
- * Amount to be refunded.  Used to trigger error about
- * subsequent refund amount being lesser than the previous
- * ones.
- */
-static struct TALER_Amount little_refund_amount;
-
-
-/**
- * Amount to be refunded in a call which is subsequent
- * to the good one, expected to succeed.
- */
-static struct TALER_Amount right_second_refund_amount;
-
-/**
- * Refund amount meant to raise an error because the
- * contract's coins aren't enough to pay it back
- */
-static struct TALER_Amount too_big_refund_amount;
-
-/**
- * Public key of the coin.  Set to some random value.
- */
-static struct TALER_CoinSpendPublicKeyP coin_pub;
-
-/**
- * Public key of the exchange.  Set to some random value.
- */
-static struct TALER_ExchangePublicKeyP signkey_pub;
-
-/**
- * Public Key of the merchant. Set to some random value.
- * Used as merchant instances now do store their keys.
- */
-static struct TALER_MerchantPublicKeyP merchant_pub;
-
-/**
- * Wire transfer identifier.  Set to some random value.
- */
-static struct TALER_WireTransferIdentifierRawP wtid;
-
-/**
- * "Proof" of deposit from the exchange. Set to some valid JSON.
- */
-static json_t *deposit_proof;
-
-/**
- * "Proof" of wire transfer from the exchange. Set to some valid JSON.
- */
-static json_t *transfer_proof;
-
-/**
- * A mock contract, not need to be well-formed
- */
-static json_t *contract;
-
-/**
- * Mock proposal data, not need to be well-formed
- */
-static json_t *contract_terms;
-
-/**
- * Mock proposal data, not need to be well-formed
- */
-static json_t *contract_terms_future;
-
-
-/**
- * Function called with information about a refund.
- *
- * @param cls closure
- * @param coin_pub public coin from which the refund comes from
- * @param exchange_url URL of the exchange that issued the @a coin_pub
- * @param rtransaction_id identificator of the refund
- * @param reason human-readable explanation of the refund
- * @param refund_amount refund amount which is being taken from @a coin_pub
- * @param refund_fee cost of this refund operation
- */
-static void
-refund_cb (void *cls,
-           const struct TALER_CoinSpendPublicKeyP *coin_pub,
-           const char *exchange_url,
-           uint64_t rtransaction_id,
-           const char *reason,
-           const struct TALER_Amount *refund_amount,
-           const struct TALER_Amount *refund_fee)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "refund_cb\n");
-  /* FIXME, more logic here? */
-}
-
-
-/**
- * Callback for `find_contract_terms_by_date`.
- *
- * @param cls closure
- * @param order_id order id
- * @param row_id row id in db
- * @param contract_terms proposal data
- */
-static void
-pd_cb (void *cls,
-       const char *order_id,
-       uint64_t row_id,
-       const json_t *contract_terms)
-{
-  return;
-}
-
-
-#define CHECK(a) do { if (! (a)) { GNUNET_break (0); result = 3; } } while (0)
-
-
-/**
- * Function called with information about a coin that was deposited.
- *
- * @param cls closure
- * @param transaction_id of the contract
- * @param acoin_pub public key of the coin
- * @param aexchange_url exchange associated with @a acoin_pub in DB
- * @param aamount_with_fee amount the exchange will deposit for this coin
- * @param adeposit_fee fee the exchange will charge for this coin
- * @param adeposit_fee fee the exchange will charge for refunding this coin
- * @param exchange_proof proof from exchange that coin was accepted
- */
-static void
-deposit_cb (void *cls,
-            const struct GNUNET_HashCode *ah_contract_terms,
-            const struct TALER_CoinSpendPublicKeyP *acoin_pub,
-            const char *aexchange_url,
-            const struct TALER_Amount *aamount_with_fee,
-            const struct TALER_Amount *adeposit_fee,
-            const struct TALER_Amount *arefund_fee,
-            const struct TALER_Amount *awire_fee,
-            const json_t *aexchange_proof)
-{
-  CHECK (0 == GNUNET_memcmp (ah_contract_terms,
-                             &h_contract_terms));
-  CHECK (0 == GNUNET_memcmp (acoin_pub,
-                             &coin_pub));
-  CHECK (0 == strcmp (aexchange_url,
-                      EXCHANGE_URL));
-  CHECK (0 == TALER_amount_cmp (aamount_with_fee,
-                                &amount_with_fee));
-  CHECK (0 == TALER_amount_cmp (adeposit_fee,
-                                &deposit_fee));
-  CHECK (0 == TALER_amount_cmp (awire_fee,
-                                &wire_fee));
-  CHECK (1 == json_equal ((json_t *) aexchange_proof,
-                          deposit_proof));
-}
-
-
-/**
- * Information about the wire transfer corresponding to
- * a deposit operation.  Note that it is in theory possible
- * that we have a @a transaction_id and @a coin_pub in the
- * result that do not match a deposit that we know about,
- * for example because someone else deposited funds into
- * our account.
- *
- * @param cls closure
- * @param transaction_id ID of the contract
- * @param coin_pub public key of the coin
- * @param wtid identifier of the wire transfer in which the exchange
- *             send us the money for the coin deposit
- * @param execution_time when was the @a wtid transfer executed
- * @param exchange_proof proof from exchange about what the deposit was for
- *             NULL if we have not asked for this signature
- */
-static void
-transfer_cb (void *cls,
-             const struct GNUNET_HashCode *ah_contract_terms,
-             const struct TALER_CoinSpendPublicKeyP *acoin_pub,
-             const struct TALER_WireTransferIdentifierRawP *awtid,
-             struct GNUNET_TIME_Absolute execution_time,
-             const json_t *exchange_proof)
-{
-  CHECK (0 == GNUNET_memcmp (ah_contract_terms,
-                             &h_contract_terms));
-
-  CHECK (0 == GNUNET_memcmp (acoin_pub,
-                             &coin_pub));
-  CHECK (0 == GNUNET_memcmp (awtid,
-                             &wtid));
-  CHECK (1 == json_equal ((json_t *) exchange_proof,
-                          transfer_proof));
-}
-
-
-/**
- * Function called with information about a wire transfer identifier.
- *
- * @param cls closure
- * @param proof proof from exchange about what the wire transfer was for
- */
-static void
-proof_cb (void *cls,
-          const json_t *proof)
-{
-  CHECK (1 == json_equal ((json_t *) proof,
-                          transfer_proof));
-}
-
-
-#undef CHECK
-
-
-/**
- * Test the wire fee storage.
- *
- * @return #GNUNET_OK on success
- */
-static int
-test_wire_fee ()
-{
-  struct TALER_MasterPublicKeyP exchange_pub;
-  struct GNUNET_HashCode h_wire_method;
-  struct GNUNET_TIME_Absolute contract_date;
-  struct TALER_Amount wire_fee1;
-  struct TALER_Amount closing_fee1;
-  struct TALER_Amount wire_fee2;
-  struct TALER_Amount closing_fee2;
-  struct TALER_Amount wire_fee3;
-  struct TALER_Amount closing_fee3;
-  struct GNUNET_TIME_Absolute date1;
-  struct GNUNET_TIME_Absolute date2;
-  struct GNUNET_TIME_Absolute date3;
-  struct GNUNET_TIME_Absolute start_date;
-  struct GNUNET_TIME_Absolute end_date;
-  struct TALER_MasterSignatureP exchange_sig;
-  struct TALER_MasterSignatureP exchange_sig2;
-
-  RND_BLK (&exchange_pub);
-  RND_BLK (&h_wire_method);
-  RND_BLK (&exchange_sig);
-  date1 = GNUNET_TIME_absolute_get ();
-  (void) GNUNET_TIME_round_abs (&date1);
-  date2 = GNUNET_TIME_absolute_add (date1,
-                                    GNUNET_TIME_UNIT_DAYS);
-  date3 = GNUNET_TIME_absolute_add (date2,
-                                    GNUNET_TIME_UNIT_DAYS);
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":5",
-                                         &closing_fee1));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":4",
-                                         &wire_fee1));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":3",
-                                         &closing_fee2));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":2",
-                                         &wire_fee2));
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      plugin->store_wire_fee_by_exchange (plugin->cls,
-                                          &exchange_pub,
-                                          &h_wire_method,
-                                          &wire_fee1,
-                                          &closing_fee1,
-                                          date1,
-                                          date2,
-                                          &exchange_sig))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      plugin->store_wire_fee_by_exchange (plugin->cls,
-                                          &exchange_pub,
-                                          &h_wire_method,
-                                          &wire_fee2,
-                                          &closing_fee2,
-                                          date2,
-                                          date3,
-                                          &exchange_sig))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  contract_date = date2; /* test inclusive/exclusive range */
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      plugin->lookup_wire_fee (plugin->cls,
-                               &exchange_pub,
-                               &h_wire_method,
-                               contract_date,
-                               &wire_fee3,
-                               &closing_fee3,
-                               &start_date,
-                               &end_date,
-                               &exchange_sig2))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if ( (start_date.abs_value_us != date2.abs_value_us) ||
-       (end_date.abs_value_us != date3.abs_value_us) ||
-       (0 != GNUNET_memcmp (&exchange_sig,
-                            &exchange_sig2)) ||
-       (0 != TALER_amount_cmp (&wire_fee2,
-                               &wire_fee3)) ||
-       (0 != TALER_amount_cmp (&closing_fee2,
-                               &closing_fee3)) )
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  contract_date = GNUNET_TIME_absolute_add (date1,
-                                            GNUNET_TIME_UNIT_SECONDS);
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      plugin->lookup_wire_fee (plugin->cls,
-                               &exchange_pub,
-                               &h_wire_method,
-                               contract_date,
-                               &wire_fee3,
-                               &closing_fee3,
-                               &start_date,
-                               &end_date,
-                               &exchange_sig2))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if ( (start_date.abs_value_us != date1.abs_value_us) ||
-       (end_date.abs_value_us != date2.abs_value_us) ||
-       (0 != GNUNET_memcmp (&exchange_sig,
-                            &exchange_sig2)) ||
-       (0 != TALER_amount_cmp (&wire_fee1,
-                               &wire_fee3)) ||
-       (0 != TALER_amount_cmp (&closing_fee1,
-                               &closing_fee3)) )
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  contract_date = date3; /* outside of valid range! */
-  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
-      plugin->lookup_wire_fee (plugin->cls,
-                               &exchange_pub,
-                               &h_wire_method,
-                               contract_date,
-                               &wire_fee3,
-                               &closing_fee3,
-                               &start_date,
-                               &end_date,
-                               &exchange_sig2))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Test APIs related to tipping.
- *
- * @return #GNUNET_OK upon success
- */
-static int
-test_tipping ()
-{
-  struct TALER_ReservePrivateKeyP tip_reserve_priv;
-  struct TALER_ReservePrivateKeyP pres;
-  struct GNUNET_HashCode tip_id;
-  struct GNUNET_HashCode tip_credit_uuid;
-  struct GNUNET_HashCode pickup_id;
-  struct GNUNET_TIME_Absolute tip_expiration;
-  struct GNUNET_TIME_Absolute reserve_expiration;
-  struct TALER_Amount total;
-  struct TALER_Amount amount;
-  struct TALER_Amount inc;
-  char *url;
-
-  RND_BLK (&tip_reserve_priv);
-  if (TALER_EC_TIP_AUTHORIZE_INSUFFICIENT_FUNDS !=
-      plugin->authorize_tip_TR (plugin->cls,
-                                "testing tips reserve unknown",
-                                json_object (),
-                                &amount,
-                                &tip_reserve_priv,
-                                "http://localhost:8081/";,
-                                &tip_expiration,
-                                &tip_id))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  RND_BLK (&tip_credit_uuid);
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":5",
-                                         &total));
-  /* Pick short expiration, but long enough to
-     run 2 DB interactions even on very slow systems. */
-  reserve_expiration = GNUNET_TIME_relative_to_absolute (
-    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
-                                   2));
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      plugin->enable_tip_reserve_TR (plugin->cls,
-                                     &tip_reserve_priv,
-                                     &tip_credit_uuid,
-                                     &total,
-                                     reserve_expiration))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  /* check idempotency */
-  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
-      plugin->enable_tip_reserve_TR (plugin->cls,
-                                     &tip_reserve_priv,
-                                     &tip_credit_uuid,
-                                     &total,
-                                     reserve_expiration))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  /* Make sure it has expired, so at this point the value is back at ZERO! */
-  sleep (3);
-  if (TALER_EC_TIP_AUTHORIZE_RESERVE_EXPIRED !=
-      plugin->authorize_tip_TR (plugin->cls,
-                                "testing tips too late",
-                                json_object (),
-                                &amount,
-                                &tip_reserve_priv,
-                                "http://localhost:8081/";,
-                                &tip_expiration,
-                                &tip_id))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  /* Re-add some funds again */
-  RND_BLK (&tip_credit_uuid);
-  reserve_expiration = GNUNET_TIME_relative_to_absolute (
-    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
-                                   2));
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      plugin->enable_tip_reserve_TR (plugin->cls,
-                                     &tip_reserve_priv,
-                                     &tip_credit_uuid,
-                                     &total,
-                                     reserve_expiration))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  /* top it up by adding more with a fresh UUID
-     and even longer expiration time (until end of test) */
-  RND_BLK (&tip_credit_uuid);
-  reserve_expiration = GNUNET_TIME_relative_to_absolute 
(GNUNET_TIME_UNIT_DAYS);
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      plugin->enable_tip_reserve_TR (plugin->cls,
-                                     &tip_reserve_priv,
-                                     &tip_credit_uuid,
-                                     &total,
-                                     reserve_expiration))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  /* Now authorize some tips */
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":4",
-                                         &amount));
-  if (TALER_EC_NONE !=
-      plugin->authorize_tip_TR (plugin->cls,
-                                "testing tips",
-                                json_object (),
-                                &amount,
-                                &tip_reserve_priv,
-                                "http://localhost:8081/";,
-                                &tip_expiration,
-                                &tip_id))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (tip_expiration.abs_value_us != reserve_expiration.abs_value_us)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      plugin->lookup_tip_by_id (plugin->cls,
-                                &tip_id,
-                                &url,
-                                NULL, NULL, NULL, NULL))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (0 != strcmp ("http://localhost:8081/";,
-                   url))
-  {
-    GNUNET_free (url);
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_free (url);
-  if (TALER_EC_NONE !=
-      plugin->authorize_tip_TR (plugin->cls,
-                                "testing tips more",
-                                json_object (),
-                                &amount,
-                                &tip_reserve_priv,
-                                "http://localhost:8081/";,
-                                &tip_expiration,
-                                &tip_id))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (tip_expiration.abs_value_us != reserve_expiration.abs_value_us)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  /* Let's try to pick up the authorized tip in 2 increments */
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":2",
-                                         &inc));
-  RND_BLK (&pickup_id);
-  if (TALER_EC_NONE !=
-      plugin->pickup_tip_TR (plugin->cls,
-                             &inc,
-                             &tip_id,
-                             &pickup_id,
-                             &pres))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (0 != GNUNET_memcmp (&pres,
-                          &tip_reserve_priv))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  RND_BLK (&pickup_id);
-  if (TALER_EC_NONE !=
-      plugin->pickup_tip_TR (plugin->cls,
-                             &inc,
-                             &tip_id,
-                             &pickup_id,
-                             &pres))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (0 != GNUNET_memcmp (&pres,
-                          &tip_reserve_priv))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  /* Third attempt should fail, as we've picked up 4/4 in amount */
-  RND_BLK (&pickup_id);
-  if (TALER_EC_TIP_PICKUP_NO_FUNDS !=
-      plugin->pickup_tip_TR (plugin->cls,
-                             &inc,
-                             &tip_id,
-                             &pickup_id,
-                             &pres))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  /* We authorized 8 out of 10, so going for another 4 should fail with 
insufficient funds */
-  if (TALER_EC_TIP_AUTHORIZE_INSUFFICIENT_FUNDS !=
-      plugin->authorize_tip_TR (plugin->cls,
-                                "testing tips insufficient funds",
-                                json_object (),
-                                &amount,
-                                &tip_reserve_priv,
-                                "http://localhost:8081/";,
-                                &tip_expiration,
-                                &tip_id))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  /* Test that picking up with random (unauthorized) tip_id fails as well */
-  RND_BLK (&tip_id);
-  RND_BLK (&pickup_id);
-  if (TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN !=
-      plugin->pickup_tip_TR (plugin->cls,
-                             &inc,
-                             &tip_id,
-                             &pickup_id,
-                             &pres))
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-
-  return GNUNET_OK;
-}
-
-
-static void
-test (struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_TIME_Absolute fake_now;
-  json_t *out;
-
-  /* Prepare data for 'store_payment()' */
-  RND_BLK (&h_wire);
-  RND_BLK (&h_contract_terms);
-  order_id = "test_ID";
-  order_id_future = "test_ID_future";
-  RND_BLK (&signkey_pub);
-  RND_BLK (&merchant_pub);
-  RND_BLK (&wtid);
-  timestamp = GNUNET_TIME_absolute_get ();
-  (void) GNUNET_TIME_round_abs (&timestamp);
-  delta = GNUNET_TIME_UNIT_MINUTES;
-  fake_now = GNUNET_TIME_absolute_add (timestamp, delta);
-  refund_deadline = GNUNET_TIME_absolute_get ();
-  (void) GNUNET_TIME_round_abs (&refund_deadline);
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":5",
-                                         &amount_with_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":0.000010",
-                                         &deposit_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":0.000001",
-                                         &wire_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":0.000010",
-                                         &refund_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":2",
-                                         &refund_amount));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":1",
-                                         &little_refund_amount));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":3",
-                                         &right_second_refund_amount));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount (CURRENCY ":30",
-                                         &too_big_refund_amount));
-  RND_BLK (&coin_pub);
-  deposit_proof = json_object ();
-  GNUNET_assert (0 ==
-                 json_object_set_new (deposit_proof,
-                                      "x-taler-bank",
-                                      json_string ("backenddb test A")));
-  transfer_proof = json_object ();
-  GNUNET_assert (0 ==
-                 json_object_set_new (transfer_proof,
-                                      "x-taler-bank",
-                                      json_string ("backenddb test B")));
-  contract = json_object ();
-  contract_terms = json_object ();
-  GNUNET_assert (0 ==
-                 json_object_set_new (contract_terms,
-                                      "order",
-                                      json_string ("1")));
-
-  contract_terms_future = json_object ();
-  GNUNET_assert (0 ==
-                 json_object_set_new (contract_terms_future,
-                                      "order",
-                                      json_string ("2")));
-
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_JSON_hash (contract_terms,
-                                  &h_contract_terms));
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->insert_contract_terms (plugin->cls,
-                                         order_id,
-                                         &merchant_pub,
-                                         timestamp,
-                                         contract_terms));
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
-          plugin->find_paid_contract_terms_from_hash (plugin->cls,
-                                                      &out,
-                                                      &h_contract_terms,
-                                                      &merchant_pub));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->mark_proposal_paid (plugin->cls,
-                                      &h_contract_terms,
-                                      &merchant_pub));
-
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->mark_proposal_paid (plugin->cls,
-                                      &h_contract_terms,
-                                      &merchant_pub));
-
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->find_contract_terms_history (plugin->cls,
-                                               order_id,
-                                               &merchant_pub,
-                                               &pd_cb,
-                                               NULL));
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->find_paid_contract_terms_from_hash (plugin->cls,
-                                                      &out,
-                                                      &h_contract_terms,
-                                                      &merchant_pub));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->find_contract_terms_from_hash (plugin->cls,
-                                                 &out,
-                                                 &h_contract_terms,
-                                                 &merchant_pub));
-  FAILIF (1 !=
-          plugin->find_contract_terms_by_date_and_range (plugin->cls,
-                                                         fake_now,
-                                                         &merchant_pub,
-                                                         2,
-                                                         1,
-                                                         GNUNET_YES,
-                                                         GNUNET_NO,
-                                                         &pd_cb,
-                                                         NULL));
-  timestamp = GNUNET_TIME_absolute_get ();
-  (void) GNUNET_TIME_round_abs (&timestamp);
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->insert_contract_terms (plugin->cls,
-                                         order_id_future,
-                                         &merchant_pub,
-                                         timestamp,
-                                         contract_terms_future));
-
-  fake_now = GNUNET_TIME_absolute_subtract (timestamp, delta);
-
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_JSON_hash (contract_terms_future,
-                                  &h_contract_terms_future));
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->mark_proposal_paid (plugin->cls,
-                                      &h_contract_terms_future,
-                                      &merchant_pub));
-  FAILIF (2 !=
-          plugin->find_contract_terms_by_date_and_range (plugin->cls,
-                                                         fake_now,
-                                                         &merchant_pub,
-                                                         0,
-                                                         5,
-                                                         GNUNET_NO,
-                                                         GNUNET_NO,
-                                                         &pd_cb,
-                                                         NULL));
-
-  FAILIF (0 !=
-          plugin->find_contract_terms_by_date (plugin->cls,
-                                               fake_now,
-                                               &merchant_pub,
-                                               1,
-                                               &pd_cb,
-                                               NULL));
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->store_deposit (plugin->cls,
-                                 &h_contract_terms,
-                                 &merchant_pub,
-                                 &coin_pub,
-                                 EXCHANGE_URL,
-                                 &amount_with_fee,
-                                 &deposit_fee,
-                                 &refund_fee,
-                                 &wire_fee,
-                                 &signkey_pub,
-                                 deposit_proof));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->store_coin_to_transfer (plugin->cls,
-                                          &h_contract_terms,
-                                          &coin_pub,
-                                          &wtid));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->store_transfer_to_proof (plugin->cls,
-                                           EXCHANGE_URL,
-                                           &wtid,
-                                           GNUNET_TIME_UNIT_ZERO_ABS,
-                                           &signkey_pub,
-                                           transfer_proof));
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->find_payments (plugin->cls,
-                                 &h_contract_terms,
-                                 &merchant_pub,
-                                 &deposit_cb,
-                                 NULL));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->find_transfers_by_hash (plugin->cls,
-                                          &h_contract_terms,
-                                          &transfer_cb,
-                                          NULL));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->find_deposits_by_wtid (plugin->cls,
-                                         &wtid,
-                                         &deposit_cb,
-                                         NULL));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->find_proof_by_wtid (plugin->cls,
-                                      EXCHANGE_URL,
-                                      &wtid,
-                                      &proof_cb,
-                                      NULL));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
-          plugin->get_refunds_from_contract_terms_hash (plugin->cls,
-                                                        &merchant_pub,
-                                                        &h_contract_terms,
-                                                        &refund_cb,
-                                                        NULL));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->increase_refund_for_contract_NT (plugin->cls,
-                                                   &h_contract_terms,
-                                                   &merchant_pub,
-                                                   &refund_amount,
-                                                   "refund testing"));
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->increase_refund_for_contract_NT (plugin->cls,
-                                                   &h_contract_terms,
-                                                   &merchant_pub,
-                                                   &refund_amount,
-                                                   "same refund amount as "
-                                                   "the previous one, should 
succeed without changes (1)"));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->increase_refund_for_contract_NT (plugin->cls,
-                                                   &h_contract_terms,
-                                                   &merchant_pub,
-                                                   &little_refund_amount,
-                                                   "lower refund amount as the 
previous one, should succeed without changes (1)"));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->increase_refund_for_contract_NT (plugin->cls,
-                                                   &h_contract_terms,
-                                                   &merchant_pub,
-                                                   &right_second_refund_amount,
-                                                   "right refund increase"));
-
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
-          plugin->increase_refund_for_contract_NT (plugin->cls,
-                                                   &h_contract_terms,
-                                                   &merchant_pub,
-                                                   &too_big_refund_amount,
-                                                   "make refund testing fail 
due to too big refund amount"));
-
-  FAILIF (GNUNET_OK !=
-          test_wire_fee ());
-  FAILIF (GNUNET_OK !=
-          test_tipping ());
-  if (-1 == result)
-    result = 0;
-}
-
 
 /**
  * Main function that will be run by the scheduler.
@@ -1023,19 +67,12 @@ run (void *cls)
     return;
   }
 
-  if (0)
-    test (cfg); /* disabled for now */
-  else
-    result = 0;
+  result = 0;
 
   GNUNET_break (GNUNET_OK ==
                 plugin->drop_tables (plugin->cls));
   TALER_MERCHANTDB_plugin_unload (plugin);
   plugin = NULL;
-  if (NULL != deposit_proof)
-    json_decref (deposit_proof);
-  if (NULL != transfer_proof)
-    json_decref (transfer_proof);
 }
 
 
@@ -1049,7 +86,8 @@ main (int argc,
   struct GNUNET_CONFIGURATION_Handle *cfg;
 
   result = -1;
-  if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
+  if (NULL == (plugin_name = strrchr (argv[0],
+                                      (int) '-')))
   {
     GNUNET_break (0);
     return -1;
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index fa255e6..818e7dd 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -802,7 +802,7 @@ struct TALER_MERCHANTDB_Plugin
    * @param cls closure
    * @param instance_id instance's identifier
    * @param order_id order_id used to lookup.
-   * @param[out] contract_terms where to store the result
+   * @param[out] contract_terms where to store the result, NULL to only check 
for existence
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
@@ -813,13 +813,19 @@ struct TALER_MERCHANTDB_Plugin
 
 
   /**
-   * Store contract terms given its @a order_id
+   * Store contract terms given its @a order_id. Note that some attributes are
+   * expected to be calculated inside of the function, like the hash of the
+   * contract terms (to be hashed), the creation_time and pay_deadline (to be
+   * obtained from the merchant_orders table). The "session_id" should be
+   * initially set to the empty string.  The "fulfillment_url" and 
"refund_deadline"
+   * must be extracted from @a contract_terms.
    *
    * @param cls closure
    * @param instance_id instance's identifier
    * @param order_id order_id used to store
-   * @param[out] contract_terms contract to store
-   * @return transaction status
+   * @param contract_terms contract to store
+   * @return transaction status, #GNUNET_DB_STATUS_HARD_ERROR if @a 
contract_terms
+   *          is malformed
    */
   enum GNUNET_DB_QueryStatus
   (*insert_contract_terms)(void *cls,
@@ -828,6 +834,25 @@ struct TALER_MERCHANTDB_Plugin
                            json_t *contract_terms);
 
 
+  /**
+   * Delete information about a contract. Note that the transaction must
+   * enforce that the contract is not awaiting payment anymore AND was not
+   * paid, or is past the legal expiration.
+   *
+   * @param cls closure
+   * @param instance_id instance to delete order of
+   * @param order_id order to delete
+   * @param legal_expiration how long do we need to keep (paid) contracts on
+   *          file for legal reasons (i.e. taxation)
+   * @return DB status code, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+   *           if locks prevent deletion OR order unknown
+   */
+  enum GNUNET_DB_QueryStatus
+  (*delete_contract_terms)(void *cls,
+                           const char *instance_id,
+                           const char *order_id,
+                           struct GNUNET_TIME_Relative legal_expiration);
+
   /* ****************** OLD API ******************** */
 
 

-- 
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]