gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] 142/277: wip on DB plugin for tip pickup


From: gnunet
Subject: [taler-merchant] 142/277: wip on DB plugin for tip pickup
Date: Sun, 05 Jul 2020 20:50:55 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

commit 0c4ff0eb09285481b9e78a3bdc3c1c9db8d5f239
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat May 23 12:18:47 2020 +0200

    wip on DB plugin for tip pickup
---
 src/backenddb/plugin_merchantdb_postgres.c | 375 +++++++++++++++--------------
 src/backenddb/test_merchantdb.c            |  13 +-
 src/include/taler_merchantdb_plugin.h      |   2 +-
 3 files changed, 200 insertions(+), 190 deletions(-)

diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 97c9c3a..8f96295 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -4202,6 +4202,51 @@ postgres_purge_reserve (void *cls,
 }
 
 
+/**
+ * Closure for #lookup_reserve_for_tip_cb().
+ */
+struct LookupReserveForTipContext
+{
+  /**
+   * Postgres context.
+   */
+  struct PostgresClosure *pg;
+
+  /**
+   * Public key of the reserve we found.
+   */
+  struct TALER_ReservePublicKeyP reserve_pub;
+
+  /**
+   * How much money must be left in the reserve.
+   */
+  struct TALER_Amount required_amount;
+
+  /**
+   * Set to the expiration time of the reserve we found.
+   * #GNUNET_TIME_UNIT_FOREVER_ABS if we found none.
+   */
+  struct GNUNET_TIME_Absolute expiration;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about accounts.
+ *
+ * @param[in,out] cls of type `struct LookupReserveForTipContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+lookup_reserve_for_tip_cb (void *cls,
+                           PGresult *result,
+                           unsigned int num_results)
+{
+  struct LookupReserveForTipContext *lac = cls;
+}
+
+
 /**
  * Authorize a tip over @a amount from reserve @a reserve_pub.  Remember
  * the authorization under @a tip_id for later, together with the
@@ -4234,22 +4279,20 @@ postgres_authorize_tip (void *cls,
                         struct GNUNET_TIME_Absolute *expiration)
 {
   struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_string (instance_id),
-    // FIXME: not so easy: reserve_pub MAY be NULL!
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-    TALER_PQ_query_param_amount (amount),
-    GNUNET_PQ_query_param_string (justification),
-    GNUNET_PQ_query_param_string (next_url),
-    GNUNET_PQ_query_param_auto_from_type (tip_id),
-    GNUNET_PQ_query_param_end
-  };
+  unsigned int retries = 0;
+  enum GNUNET_DB_QueryStatus qs;
   struct TALER_Amount tips_committed;
   struct TALER_Amount exchange_initial_balance;
+  const struct TALER_ReservePublicKeyP *reserve_pubp;
+  struct LookupReserveForTipContext lac = {
+    .pg = pg,
+    .required_amount = *amount,
+    .expiration = GNUNET_TIME_UNIT_FOREVER_ABS
+  };
 
-  retries = 0;
   check_connection (pg);
 RETRY:
+  reserve_pubp = reserve_pub;
   if (MAX_RETRIES < ++retries)
     return GNUNET_DB_STATUS_SOFT_ERROR; // FIXME: wrong EC!
   if (GNUNET_OK !=
@@ -4259,7 +4302,7 @@ RETRY:
     GNUNET_break (0);
     return GNUNET_DB_STATUS_HARD_ERROR; // FIXME: wrong EC!
   }
-  if (NULL == reserve_pub)
+  if (NULL == reserve_pubp)
   {
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_string (instance_id),
@@ -4267,29 +4310,152 @@ RETRY:
       GNUNET_PQ_query_param_end
     };
     qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                               "lookup_reserve",
+                                               "lookup_reserve", // FIXME: 
write SQL!
                                                params,
-                                               &lookup_accounts_cb,
-                                               lic);
-
+                                               &lookup_reserve_for_tip_cb,
+                                               &lac);
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    {
+      postgres_rollback (pg);
+      goto RETRY;
+    }
+    if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+    {
+      GNUNET_break (0);
+      postgres_rollback (pg);
+      return GNUNET_DB_STATUS_HARD_ERROR; // FIXME: wrong EC!
+    }
+    if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us ==
+        lac.expiration.abs_value_us)
+    {
+      postgres_rollback (pg);
+      return 0; // FIXME: EC for 'no reserve available!'
+    }
+    reserve_pubp = &lac.reserve_pub;
   }
 
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_string (instance_id),
+      GNUNET_PQ_query_param_auto_from_type (reserve_pubp),
+      TALER_PQ_query_param_amount (amount),
+      GNUNET_PQ_query_param_string (justification),
+      GNUNET_PQ_query_param_string (next_url),
+      GNUNET_PQ_query_param_auto_from_type (tip_id),
+      GNUNET_PQ_query_param_end
+    };
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_absolute_time ("expiration",
+                                           expiration),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("tips_committed",
+                                   &tips_committed),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("exchange_initial_balance",
+                                   &exchange_initial_balance),
+      GNUNET_PQ_result_spec_end
+    };
 
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_absolute_time ("expiration",
-                                         &old_expiration),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("tips_committed",
-                                 &tips_committed),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("exchange_initial_balance",
-                                 &exchange_initial_balance),
-    GNUNET_PQ_result_spec_end
-  };
+    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "lookup_reserve_status", // 
FIXME: write SQL!
+                                                   params,
+                                                   rs);
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    {
+      postgres_rollback (pg);
+      goto RETRY;
+    }
+    if (qs < 0)
+    {
+      GNUNET_break (0);
+      postgres_rollback (pg);
+      return GNUNET_DB_STATUS_HARD_ERROR; // FIXME: ec!
+    }
+  }
+  {
+    struct TALER_Amount remaining;
 
+    if (0 >=
+        TALER_amount_subtract (&remaining,
+                               &exchange_initial_balance,
+                               &tips_committed))
+    {
+      GNUNET_break (0);
+      postgres_rollback (pg);
+      return GNUNET_DB_STATUS_HARD_ERROR; // FIXME: EC: invariant failure!
+    }
+    if (0 <
+        TALER_amount_cmp (&remaining,
+                          amount))
+    {
+      postgres_rollback (pg);
+      return GNUNET_DB_STATUS_HARD_ERROR; // FIXME: EC: insufficient funds!
+    }
+  }
+  GNUNET_assert (0 <=
+                 TALER_amount_add (&tips_committed,
+                                   &tips_committed,
+                                   amount));
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_string (instance_id),
+      GNUNET_PQ_query_param_auto_from_type (reserve_pubp),
+      TALER_PQ_query_param_amount (&tips_committed),
+      GNUNET_PQ_query_param_end
+    };
 
-  check_connection (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "purge_reserve",
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "update_reserve_tips_committed", 
// FIXME: write SQL!
                                              params);
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    {
+      postgres_rollback (pg);
+      goto RETRY;
+    }
+    if (qs < 0)
+    {
+      GNUNET_break (0);
+      postgres_rollback (pg);
+      return GNUNET_DB_STATUS_HARD_ERROR; // FIXME: ec!
+    }
+  }
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+                              tip_id,
+                              sizeof (*tip_id));
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_string (instance_id),
+      GNUNET_PQ_query_param_auto_from_type (reserve_pubp),
+      TALER_PQ_query_param_amount (amount),
+      GNUNET_PQ_query_param_string (justification),
+      GNUNET_PQ_query_param_string (next_url),
+      GNUNET_PQ_query_param_auto_from_type (tip_id),
+      GNUNET_PQ_query_param_end
+    };
+
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             
"update_reserve_tips_committed",// FIXME: write SQL!
+                                             params);
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    {
+      postgres_rollback (pg);
+      goto RETRY;
+    }
+    if (qs < 0)
+    {
+      GNUNET_break (0);
+      postgres_rollback (pg);
+      return GNUNET_DB_STATUS_HARD_ERROR; // FIXME: ec!
+    }
+  }
+  qs = postgres_commit (pg);
+  if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+    goto RETRY;
+  if (qs < 0)
+  {
+    GNUNET_break (0);
+    postgres_rollback (pg);
+    return GNUNET_DB_STATUS_HARD_ERROR;   // FIXME: ec!
+  }
+  return TALER_EC_NONE;
 }
 
 
@@ -4364,8 +4530,8 @@ postgres_lookup_tip (void *cls,
                                          expiration),
     GNUNET_PQ_result_spec_string ("exchange_url",
                                   exchange_url),
-    GNUNET_PQ_result_spec_fixed_auto ("reserve_priv",
-                                      reserve_priv),
+    GNUNET_PQ_result_spec_auto_from_type ("reserve_priv",
+                                          reserve_priv),
     GNUNET_PQ_result_spec_end
   };
 
@@ -4943,155 +5109,6 @@ RETRY:
 }
 
 
-/**
- * Authorize a tip over @a amount from reserve @a reserve_priv.  Remember
- * the authorization under @a tip_id for later, together with the
- * @a justification.
- *
- * @param cls closure, typically a connection to the db
- * @param justification why was the tip approved
- * @param extra extra data for the customer's wallet
- * @param amount how high is the tip (with fees)
- * @param reserve_priv which reserve is debited
- * @param exchange_url which exchange manages the tip
- * @param[out] expiration set to when the tip expires
- * @param[out] tip_id set to the unique ID for the tip
- * @return taler error code
- *      #TALER_EC_TIP_AUTHORIZE_RESERVE_EXPIRED if the reserve is known but 
has expired
- *      #TALER_EC_TIP_AUTHORIZE_RESERVE_UNKNOWN if the reserve is not known
- *      #TALER_EC_TIP_AUTHORIZE_INSUFFICIENT_FUNDS if the reserve has 
insufficient funds left
- *      #TALER_EC_TIP_AUTHORIZE_DB_HARD_ERROR on hard DB errors
- *      #TALER_EC_TIP_AUTHORIZE_DB_SOFT_ERROR on soft DB errors (client should 
retry)
- *      #TALER_EC_NONE upon success
- */
-static enum TALER_ErrorCode
-postgres_authorize_tip (void *cls,
-                        const char *justification,
-                        const json_t *extra,
-                        const struct TALER_Amount *amount,
-                        const struct TALER_ReservePrivateKeyP *reserve_priv,
-                        const char *exchange_url,
-                        struct GNUNET_TIME_Absolute *expiration,
-                        struct GNUNET_HashCode *tip_id)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (reserve_priv),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_TIME_Absolute old_expiration;
-  struct TALER_Amount old_balance;
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_absolute_time ("expiration",
-                                         &old_expiration),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
-                                 &old_balance),
-    GNUNET_PQ_result_spec_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-  struct TALER_Amount new_balance;
-  unsigned int retries;
-
-  retries = 0;
-  check_connection (pg);
-RETRY:
-  if (MAX_RETRIES < ++retries)
-    return TALER_EC_TIP_AUTHORIZE_DB_SOFT_ERROR;
-  if (GNUNET_OK !=
-      postgres_start (pg,
-                      "authorize tip"))
-  {
-    GNUNET_break (0);
-    return TALER_EC_TIP_AUTHORIZE_DB_HARD_ERROR;
-  }
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "lookup_tip_reserve_balance",
-                                                 params,
-                                                 rs);
-  if (0 >= qs)
-  {
-    /* reserve unknown */
-    postgres_rollback (pg);
-    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
-      goto RETRY;
-    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
-      return TALER_EC_TIP_AUTHORIZE_INSUFFICIENT_FUNDS;
-    return TALER_EC_TIP_AUTHORIZE_DB_HARD_ERROR;
-  }
-  if (0 == GNUNET_TIME_absolute_get_remaining (old_expiration).rel_value_us)
-  {
-    /* reserve expired, can't be used */
-    postgres_rollback (pg);
-    return TALER_EC_TIP_AUTHORIZE_RESERVE_EXPIRED;
-  }
-  if (0 >
-      TALER_amount_subtract (&new_balance,
-                             &old_balance,
-                             amount))
-  {
-    /* insufficient funds left in reserve */
-    postgres_rollback (pg);
-    return TALER_EC_TIP_AUTHORIZE_INSUFFICIENT_FUNDS;
-  }
-  /* Update reserve balance */
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserve_priv),
-      GNUNET_PQ_query_param_absolute_time (&old_expiration),
-      TALER_PQ_query_param_amount (&new_balance),
-      GNUNET_PQ_query_param_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "update_tip_reserve_balance",
-                                             params);
-    if (0 > qs)
-    {
-      postgres_rollback (pg);
-      if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
-        goto RETRY;
-      return TALER_EC_TIP_AUTHORIZE_DB_HARD_ERROR;
-    }
-  }
-  /* Generate and store tip ID */
-  *expiration = old_expiration;
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    tip_id);
-  {
-    struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserve_priv),
-      GNUNET_PQ_query_param_auto_from_type (tip_id),
-      GNUNET_PQ_query_param_string (exchange_url),
-      GNUNET_PQ_query_param_string (justification),
-      TALER_PQ_query_param_json (extra),
-      GNUNET_PQ_query_param_absolute_time (&now),
-      TALER_PQ_query_param_amount (amount), /* overall amount */
-      TALER_PQ_query_param_amount (amount), /* amount left */
-      GNUNET_PQ_query_param_end
-    };
-
-    (void) GNUNET_TIME_round_abs (&now);
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_tip_justification",
-                                             params);
-    if (0 > qs)
-    {
-      postgres_rollback (pg);
-      if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
-        goto RETRY;
-      return TALER_EC_TIP_AUTHORIZE_DB_HARD_ERROR;
-    }
-  }
-  qs = postgres_commit (pg);
-  if (0 <= qs)
-    return TALER_EC_NONE; /* success! */
-  if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
-    goto RETRY;
-  return TALER_EC_TIP_AUTHORIZE_DB_HARD_ERROR;
-}
-
-
 /**
  * Find out tip authorization details associated with @a tip_id
  *
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index c2c0a7d..5354d8e 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -395,10 +395,7 @@ test_instances (void *cls)
                 "Lookup instance failed: incorrect number of accounts returned 
%d\n", instances_accounts_length[0]);
     //plugin->drop_tables (plugin->cls);
     return 1;
-  }*/
-
-  /* Test instance private key deletion */
-  if (0 > plugin->delete_instance_private_key (plugin->cls,
+  }*//* Test instance private key deletion */if (0 > 
plugin->delete_instance_private_key (plugin->cls,
                                                "test_inst"))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -438,9 +435,7 @@ test_instances (void *cls)
     result = 1;
     plugin->drop_tables (plugin->cls);
     return;
-  }*/
-
-  json_decref (is.address);
+  }*/json_decref (is.address);
   json_decref (is.jurisdiction);
 
   return 0;
@@ -774,9 +769,7 @@ test_products (void *cls)
                 "Purge instance failed\n");
     plugin->drop_tables (plugin->cls);
     return 1;
-  }*/
-
-  json_decref (is.address);
+  }*/json_decref (is.address);
   json_decref (is.jurisdiction);
 
   return 0;
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index bb8249c..1324b4d 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -51,7 +51,7 @@ struct TALER_MERCHANTDB_AccountDetails
   /**
    * Actual account address as a payto://-URI.
    */
-  char *payto_uri;
+  const char *payto_uri;
 
   /**
    * Is the account set for active use in new contracts?

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