gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] 137/277: implement POST /tips/ID/pickup


From: gnunet
Subject: [taler-merchant] 137/277: implement POST /tips/ID/pickup
Date: Sun, 05 Jul 2020 20:50:50 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

commit 49157c0beaeae761cac5daa22d8734880ee726dd
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Fri May 22 13:01:11 2020 +0200

    implement POST /tips/ID/pickup
---
 src/backend/Makefile.am                            |   4 +-
 .../taler-merchant-httpd_post-tips-ID-pickup.c     | 166 +++++++++++++--------
 src/include/taler_merchantdb_plugin.h              |  47 ++++++
 3 files changed, 153 insertions(+), 64 deletions(-)

diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
index 1c42b7f..8960b15 100644
--- a/src/backend/Makefile.am
+++ b/src/backend/Makefile.am
@@ -74,7 +74,9 @@ taler_merchant_httpd_SOURCES = \
   taler-merchant-httpd_post-orders-ID-claim.c \
     taler-merchant-httpd_post-orders-ID-claim.h \
   taler-merchant-httpd_post-orders-ID-pay.c \
-    taler-merchant-httpd_post-orders-ID-pay.h
+    taler-merchant-httpd_post-orders-ID-pay.h \
+  taler-merchant-httpd_post-tips-ID-pickup.c \
+    taler-merchant-httpd_post-tips-ID-pickup.h
 
 DEAD = \
   taler-merchant-httpd_check-payment.c taler-merchant-httpd_check-payment.h \
diff --git a/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c 
b/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c
index c24c2c0..e6437c3 100644
--- a/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c
+++ b/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c
@@ -26,7 +26,7 @@
 #include "taler-merchant-httpd.h"
 #include "taler-merchant-httpd_mhd.h"
 #include "taler-merchant-httpd_exchanges.h"
-#include "taler-merchant-httpd_tip-pickup.h"
+#include "taler-merchant-httpd_post-tips-ID-pickup.h"
 
 
 /**
@@ -58,6 +58,16 @@ struct PlanchetOperation
    */
   struct PickupContext *pc;
 
+  /**
+   * Kept in a DLL.
+   */
+  struct PlanchetOperation *prev;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct PlanchetOperation *next;
+
   /**
    * Find operation (while active), later NULL.
    */
@@ -128,13 +138,19 @@ struct PickupContext
   /**
    * Which reserve are we draining?
    */
-  struct TALER_ReservePrivateKey reserve_priv;
+  struct TALER_ReservePrivateKeyP reserve_priv;
 
   /**
    * Which tip is being picked up?
    */
   struct GNUNET_HashCode tip_id;
 
+  /**
+   * What is the ID of the pickup operation? (Basically a
+   * hash over the key inputs).
+   */
+  struct GNUNET_HashCode pickup_id;
+
   /**
    * Array of our planchets.
    */
@@ -264,6 +280,7 @@ withdraw_cb (void *cls,
 {
   struct PlanchetOperation *po = cls;
   struct PickupContext *pc = po->pc;
+  enum GNUNET_DB_QueryStatus qs;
 
   GNUNET_CONTAINER_DLL_remove (pc->po_head,
                                pc->po_tail,
@@ -383,9 +400,9 @@ try_withdraw (struct PickupContext *pc,
                                         &do_withdraw,
                                         po);
   GNUNET_assert (NULL != po->fo);
-  GNUNET_CONTAINER_DLL_insert (pc->fo_head,
-                               pc->fo_tail,
-                               fo);
+  GNUNET_CONTAINER_DLL_insert (pc->po_head,
+                               pc->po_tail,
+                               po);
 }
 
 
@@ -460,7 +477,7 @@ compute_total_requested (void *cls,
                                                        &pd->denom_pub_hash);
     if (NULL == dpk)
     {
-      pc->http_status = MHD_HTTP_BAD_REQUEST;
+      pc->http_status = MHD_HTTP_CONFLICT;
       pc->response =
         TALER_MHD_make_json_pack (
           "{s:I, s:I, s:I, s:O}",
@@ -489,8 +506,48 @@ compute_total_requested (void *cls,
     }
   }
   pc->tr_initialized = true;
+}
+
+
+/**
+ * The tip lookup operation failed. Generate an error response based on the @a 
qs.
+ *
+ * @param connection connection to generate error for
+ * @param qs DB status to base error creation on
+ * @return MHD result code
+ */
+static MHD_RESULT
+reply_lookup_tip_failed (struct MHD_Connection *connection,
+                         enum GNUNET_DB_QueryStatus qs)
+{
+  unsigned int response_code;
+  enum TALER_ErrorCode ec;
 
-  return;
+  TMH_db->rollback (TMH_db->cls);
+  switch (qs)
+  {
+  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+    ec = TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN;
+    response_code = MHD_HTTP_NOT_FOUND;
+    break;
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    ec = TALER_EC_TIP_PICKUP_DB_ERROR_SOFT;
+    response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    break;
+  case GNUNET_DB_STATUS_HARD_ERROR:
+    ec = TALER_EC_TIP_PICKUP_DB_ERROR_HARD;
+    response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    break;
+  default:
+    GNUNET_break (0);
+    ec = TALER_EC_INTERNAL_LOGIC_ERROR;
+    response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    break;
+  }
+  return TALER_MHD_reply_with_error (connection,
+                                     response_code,
+                                     ec,
+                                     "Could not process pickup");
 }
 
 
@@ -509,19 +566,13 @@ TMH_post_tips_ID_pickup (const struct TMH_RequestHandler 
*rh,
                          struct TMH_HandlerContext *hc)
 {
   struct PickupContext *pc = hc->ctx;
-
-  char *justification;
   char *exchange_url;
-
   struct TALER_Amount total_authorized;
+  struct TALER_Amount total_requested;
   struct TALER_Amount total_picked_up;
   struct TALER_Amount total_remaining;
   struct GNUNET_TIME_Absolute expiration;
-  struct GNUNET_TIME_Absolute timestamp_expire;
-  struct TALER_ReservePrivateKey reserve_priv;
-  MHD_RESULT ret;
   enum GNUNET_DB_QueryStatus qs;
-  unsigned int num_coins;
   unsigned int num_retries;
 
   if (NULL == pc)
@@ -613,6 +664,8 @@ TMH_post_tips_ID_pickup (const struct TMH_RequestHandler 
*rh,
                                        sizeof (pc->tip_id));
       for (unsigned int i = 0; i<pc->planchets_length; i++)
       {
+        struct TALER_PlanchetDetail *pd = &pc->planchets[index];
+
         GNUNET_CRYPTO_hash_context_read (hc,
                                          &pd->denom_pub_hash,
                                          sizeof (pd->denom_pub_hash));
@@ -627,7 +680,7 @@ TMH_post_tips_ID_pickup (const struct TMH_RequestHandler 
*rh,
 
   if (NULL != pc->response)
   {
-    MDH_RESULT ret;
+    MHD_RESULT ret;
 
     ret = MHD_queue_response (connection,
                               pc->http_status,
@@ -638,6 +691,17 @@ TMH_post_tips_ID_pickup (const struct TMH_RequestHandler 
*rh,
 
   if (! pc->tr_initialized)
   {
+    qs = TMH_db->lookup_tip (TMH_db->cls,
+                             hc->instance->settings.id,
+                             &pc->tip_id,
+                             &total_authorized,
+                             &total_picked_up,
+                             &expiration,
+                             &exchange_url,
+                             &pc->reserve_priv);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+      return reply_lookup_tip_failed (connection,
+                                      qs);
     MHD_suspend_connection (connection);
     pc->tt = GNUNET_SCHEDULER_add_delayed (EXCHANGE_TIMEOUT,
                                            &do_timeout,
@@ -674,25 +738,25 @@ RETRY:
                                        "Could not begin transaction");
   }
   {
-    struct GNUNET_CRYPTO_RsaSignature *sigs[num_coins];
+    struct GNUNET_CRYPTO_RsaSignature *sigs[GNUNET_NZL (pc->planchets_length)];
 
     qs = TMH_db->lookup_pickup (TMH_db->cls,
                                 hc->instance->settings.id,
-                                &tip_id,
-                                &pickup_id,
+                                &pc->tip_id,
+                                &pc->pickup_id,
                                 &exchange_url,
-                                &pc->reserve_priv;
-                                num_coins,
+                                &pc->reserve_priv,
+                                pc->planchets_length,
                                 sigs);
     if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
     {
-      for (unsigned int i = 0; i<num_coins; i++)
+      for (unsigned int i = 0; i< pc->planchets_length; i++)
       {
         if (NULL == sigs[i])
         {
           try_withdraw (pc,
                         exchange_url,
-                        planchets[i],
+                        &pc->planchets[i],
                         i);
           qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
         }
@@ -703,7 +767,7 @@ RETRY:
         GNUNET_CONTAINER_DLL_insert (pc_head,
                                      pc_tail,
                                      pc);
-        pc->tt = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+        pc->tt = GNUNET_SCHEDULER_add_delayed (EXCHANGE_TIMEOUT,
                                                &do_timeout,
                                                pc);
         TMH_db->rollback (TMH_db->cls);
@@ -724,7 +788,7 @@ RETRY:
 
           blind_sigs = json_array ();
           GNUNET_assert (NULL != blind_sigs);
-          for (unsigned int i = 0; i<num_coins; i++)
+          for (unsigned int i = 0; i<pc->planchets_length; i++)
           {
             GNUNET_assert (0 ==
                            json_array_append_new (
@@ -761,51 +825,27 @@ RETRY:
 
   qs = TMH_db->lookup_tip (TMH_db->cls,
                            hc->instance->settings.id,
-                           &tip_id,
+                           &pc->tip_id,
                            &total_authorized,
                            &total_picked_up,
                            &expiration,
                            &exchange_url,
                            &pc->reserve_priv);
+  if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    goto RETRY;
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
-  {
-    unsigned int response_code;
-    enum TALER_ErrorCode ec;
-
-    TMH_db->rollback (TMH_db->cls);
-    switch (qs)
-    {
-    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      ec = TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN;
-      response_code = MHD_HTTP_NOT_FOUND;
-      break;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      goto RETRY;
-    case GNUNET_DB_STATUS_HARD_ERROR:
-      ec = TALER_EC_TIP_PICKUP_DB_ERROR_HARD;
-      response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-      break;
-    default:
-      GNUNET_break (0);
-      ec = TALER_EC_INTERNAL_LOGIC_ERROR;
-      response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
-      break;
-    }
-    return TALER_MHD_reply_with_error (connection,
-                                       response_code,
-                                       ec,
-                                       "Could not process pickup");
-  }
+    return reply_lookup_tip_failed (connection,
+                                    qs);
   if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
   {
     TMH_db->rollback (TMH_db->cls);
     return TALER_MHD_reply_with_error (connection,
-                                       response_code,
-                                       ec,
-                                       "Could not process pickup");
+                                       MHD_HTTP_GONE,
+                                       TALER_EC_TIP_PICKUP_HAS_EXPIRED,
+                                       "Could not process pickup: it is too 
late");
   }
   if (0 >
-      TALER_amount_subtract (&total_left,
+      TALER_amount_subtract (&total_remaining,
                              &total_authorized,
                              &total_picked_up))
   {
@@ -818,14 +858,14 @@ RETRY:
   }
 
   if (0 >
-      TALER_amount_cmp (&total_left,
+      TALER_amount_cmp (&total_remaining,
                         &total_requested))
   {
     GNUNET_break (0);
     TMH_db->rollback (TMH_db->cls);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_BAD_REQUEST,
-                                       
TALER_EC_PICKUP_AMOUNT_EXCEEDS_TIP_REMAINING,
+                                       
TALER_EC_TIP_PICKUP_AMOUNT_EXCEEDS_TIP_REMAINING,
                                        "requested amount exceeds amount left 
in tip");
   }
 
@@ -835,9 +875,9 @@ RETRY:
                                    &total_requested));
   qs = TMH_db->insert_pickup (TMH_db->cls,
                               hc->instance->settings.id,
-                              &tip_id,
+                              &pc->tip_id,
                               &total_picked_up,
-                              &pickup_id,
+                              &pc->pickup_id,
                               &total_requested);
   if (qs < 0)
   {
@@ -864,11 +904,11 @@ RETRY:
   pc->tt = GNUNET_SCHEDULER_add_delayed (EXCHANGE_TIMEOUT,
                                          &do_timeout,
                                          pc);
-  for (unsigned int i = 0; i<num_coins; i++)
+  for (unsigned int i = 0; i<pc->planchets_length; i++)
   {
     try_withdraw (pc,
                   exchange_url,
-                  planchets[i],
+                  &pc->planchets[i],
                   i);
   }
   return MHD_YES;
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index 2dc764e..1324b4d 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -1781,6 +1781,53 @@ struct TALER_MERCHANTDB_Plugin
                         struct TALER_MERCHANTDB_PickupDetails **pickups);
 
 
+  /**
+   * Insert details about a tip pickup operation.  The @a total_picked_up
+   * UPDATES the total amount under the @a tip_id, while the @a
+   * total_requested is the amount to be associated with this @a pickup_id.
+   * While there is usually only one pickup event that picks up the entire
+   * amount, our schema allows for wallets to pick up the amount incrementally
+   * over multiple pick up operations.
+   *
+   * @param cls closure, typically a connection to the db
+   * @param tip_id the unique ID for the tip
+   * @param total_picked_up how much was picked up overall at this
+   *          point (includes @total_requested)
+   * @param pickup_id unique ID for the operation
+   * @param total_requested how much is being picked up in this operation
+   * @return transaction status, usually
+   *      #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success
+   *      #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a credit_uuid already known
+   */
+  enum GNUNET_DB_QueryStatus
+  (*insert_pickup)(void *cls,
+                   const char *instance_id,
+                   const struct GNUNET_HashCode *tip_id,
+                   const struct TALER_Amount *total_picked_up,
+                   const struct GNUNET_HashCode *pickup_id,
+                   const struct TALER_Amount *total_requested);
+
+
+  /**
+   * Insert blind signature obtained from the exchange during a
+   * tip pickup operation.
+   *
+   * @param cls closure, typically a connection to the db
+   * @param pickup_id unique ID for the operation
+   * @param offset offset of the blind signature for the pickup
+   * @param blind_sig the blind signature
+   * @return transaction status, usually
+   *      #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT for success
+   *      #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if @a credit_uuid already known
+   */
+  enum GNUNET_DB_QueryStatus
+  (*insert_pickup_blind_signature)(
+    void *cls,
+    const struct GNUNET_HashCode *pickup_id,
+    uint32_t offset,
+    const struct GNUNET_CRYPTO_RsaSignature *blind_sig);
+
+
   /* ****************** 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]