[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.
- [taler-merchant] 132/277: Merge branch 'protocolV1' of git+ssh://git.taler.net/merchant into protocolV1, (continued)
- [taler-merchant] 132/277: Merge branch 'protocolV1' of git+ssh://git.taler.net/merchant into protocolV1, gnunet, 2020/07/05
- [taler-merchant] 136/277: add GET /tips/ID handler, gnunet, 2020/07/05
- [taler-merchant] 138/277: wrote some db tests for orders, gnunet, 2020/07/05
- [taler-merchant] 123/277: added tests for instance creation and lookup, gnunet, 2020/07/05
- [taler-merchant] 127/277: implement reserve deletion, gnunet, 2020/07/05
- [taler-merchant] 135/277: fix ftbfs, gnunet, 2020/07/05
- [taler-merchant] 130/277: added more instance tests and fixed mem leaks/code style in tests, gnunet, 2020/07/05
- [taler-merchant] 133/277: fix ftbfs, gnunet, 2020/07/05
- [taler-merchant] 139/277: wrote db tests for accounts, gnunet, 2020/07/05
- [taler-merchant] 140/277: DB prep work, gnunet, 2020/07/05
- [taler-merchant] 142/277: wip on DB plugin for tip pickup,
gnunet <=
- [taler-merchant] 144/277: refactored instance test code, gnunet, 2020/07/05
- [taler-merchant] 146/277: wrote tests for deposits in the db api, gnunet, 2020/07/05
- [taler-merchant] 149/277: more db tests for transfers and tips, gnunet, 2020/07/05
- [taler-merchant] 151/277: backenddb tests for lookup_transfers, lookup_transfer_summary, lookup_transfer_details, gnunet, 2020/07/05
- [taler-merchant] 150/277: backenddb tests for refunds, gnunet, 2020/07/05
- [taler-merchant] 153/277: fixed test for increase_refund, gnunet, 2020/07/05
- [taler-merchant] 108/277: sketch for GET /transfers cmd, gnunet, 2020/07/05
- [taler-merchant] 134/277: finished writing db tests for products, gnunet, 2020/07/05
- [taler-merchant] 137/277: implement POST /tips/ID/pickup, gnunet, 2020/07/05
- [taler-merchant] 141/277: Merge branch 'protocolV1' of git+ssh://git.taler.net/merchant into protocolV1, gnunet, 2020/07/05