summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2024-04-01 21:05:45 +0200
committerChristian Grothoff <christian@grothoff.org>2024-04-01 21:05:45 +0200
commite6a4545620933a325b1e7e0d122c2281468bef62 (patch)
tree46f765209f5002b82fae3ff6e7ac3ad1bd7bea3e
parentab8e426cae07d43ec7862c9ea9cc4279902bde8b (diff)
downloadmerchant-e6a4545620933a325b1e7e0d122c2281468bef62.tar.gz
merchant-e6a4545620933a325b1e7e0d122c2281468bef62.tar.bz2
merchant-e6a4545620933a325b1e7e0d122c2281468bef62.zip
consider refunds when checking exchange transfer claims
-rw-r--r--src/backenddb/pg_lookup_deposits_by_contract_and_coin.c135
-rw-r--r--src/backenddb/pg_lookup_refunds.h12
-rw-r--r--src/backenddb/pg_lookup_refunds_detailed.h11
3 files changed, 141 insertions, 17 deletions
diff --git a/src/backenddb/pg_lookup_deposits_by_contract_and_coin.c b/src/backenddb/pg_lookup_deposits_by_contract_and_coin.c
index 9bf46d0c..29ff3926 100644
--- a/src/backenddb/pg_lookup_deposits_by_contract_and_coin.c
+++ b/src/backenddb/pg_lookup_deposits_by_contract_and_coin.c
@@ -46,6 +46,11 @@ struct LookupDepositsByCnCContext
struct PostgresClosure *pg;
/**
+ * Total amount refunded on this coin and contract.
+ */
+ struct TALER_Amount refund_total;
+
+ /**
* Transaction result.
*/
enum GNUNET_DB_QueryStatus qs;
@@ -61,6 +66,51 @@ struct LookupDepositsByCnCContext
* @param num_results the number of results in @a result
*/
static void
+lookup_refunds_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupDepositsByCnCContext *ldcc = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_Amount refund_amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_amount_with_currency ("refund_amount",
+ &refund_amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ldcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ if (0 == i)
+ ldcc->refund_total = refund_amount;
+ else
+ GNUNET_assert (0 <=
+ TALER_amount_add (&ldcc->refund_total,
+ &ldcc->refund_total,
+ &refund_amount));
+ GNUNET_PQ_cleanup_result (rs); /* technically useless here */
+ }
+}
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls of type `struct LookupDepositsByCnCContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
lookup_deposits_by_contract_and_coin_cb (void *cls,
PGresult *result,
unsigned int num_results)
@@ -112,6 +162,50 @@ lookup_deposits_by_contract_and_coin_cb (void *cls,
ldcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
return;
}
+ if (TALER_amount_is_valid (&ldcc->refund_total))
+ {
+ if (1 ==
+ TALER_amount_cmp (&ldcc->refund_total,
+ &amount_with_fee))
+ {
+ /* Refunds exceeded total deposit? not OK! */
+ GNUNET_break (0);
+ ldcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ if (0 ==
+ TALER_amount_cmp (&ldcc->refund_total,
+ &amount_with_fee))
+ {
+ /* refund_total == amount_with_fee;
+ in this case, the total contributed to the
+ wire transfer is zero (as are fees) */
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (ldcc->refund_total.currency,
+ &amount_with_fee));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (ldcc->refund_total.currency,
+ &deposit_fee));
+
+ }
+ else
+ {
+ /* Compute deposit value by subtracting refunds */
+ GNUNET_assert (0 <
+ TALER_amount_subtract (&amount_with_fee,
+ &amount_with_fee,
+ &ldcc->refund_total));
+ if (-1 ==
+ TALER_amount_cmp (&amount_with_fee,
+ &deposit_fee))
+ {
+ /* amount_with_fee < deposit_fee, so after refunds less than
+ the deposit fee remains; reduce deposit fee to
+ the remaining value of the coin */
+ deposit_fee = amount_with_fee;
+ }
+ }
+ }
ldcc->cb (ldcc->cb_cls,
exchange_url,
&amount_with_fee,
@@ -128,13 +222,15 @@ lookup_deposits_by_contract_and_coin_cb (void *cls,
ldcc->qs = num_results;
}
+
enum GNUNET_DB_QueryStatus
-TMH_PG_lookup_deposits_by_contract_and_coin (void *cls,
- const char *instance_id,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- TALER_MERCHANTDB_CoinDepositCallback cb,
- void *cb_cls)
+TMH_PG_lookup_deposits_by_contract_and_coin (
+ void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ TALER_MERCHANTDB_CoinDepositCallback cb,
+ void *cb_cls)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
@@ -151,6 +247,33 @@ TMH_PG_lookup_deposits_by_contract_and_coin (void *cls,
enum GNUNET_DB_QueryStatus qs;
check_connection (pg);
+ /* no preflight check here, run in transaction by caller! */
+ TALER_LOG_DEBUG ("Looking for refund of h_contract_terms %s at `%s'\n",
+ GNUNET_h2s (&h_contract_terms->hash),
+ instance_id);
+ check_connection (pg);
+ PREPARE (pg,
+ "lookup_refunds_by_coin_and_contract",
+ "SELECT"
+ " refund_amount"
+ " FROM merchant_refunds"
+ " WHERE coin_pub=$3"
+ " AND order_serial="
+ " (SELECT order_serial"
+ " FROM merchant_contract_terms"
+ " WHERE h_contract_terms=$2"
+ " AND merchant_serial="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1))");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "lookup_refunds_by_coin_and_contract",
+ params,
+ &lookup_refunds_cb,
+ &ldcc);
+ if (0 > qs)
+ return qs;
+
PREPARE (pg,
"lookup_deposits_by_contract_and_coin",
"SELECT"
diff --git a/src/backenddb/pg_lookup_refunds.h b/src/backenddb/pg_lookup_refunds.h
index 2b047019..20f44e9d 100644
--- a/src/backenddb/pg_lookup_refunds.h
+++ b/src/backenddb/pg_lookup_refunds.h
@@ -36,11 +36,11 @@
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
-TMH_PG_lookup_refunds (void *cls,
- const char *instance_id,
- const struct
- TALER_PrivateContractHashP *h_contract_terms,
- TALER_MERCHANTDB_RefundCallback rc,
- void *rc_cls);
+TMH_PG_lookup_refunds (
+ void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ TALER_MERCHANTDB_RefundCallback rc,
+ void *rc_cls);
#endif
diff --git a/src/backenddb/pg_lookup_refunds_detailed.h b/src/backenddb/pg_lookup_refunds_detailed.h
index c2531446..665f06cf 100644
--- a/src/backenddb/pg_lookup_refunds_detailed.h
+++ b/src/backenddb/pg_lookup_refunds_detailed.h
@@ -36,10 +36,11 @@
* @return transaction status
*/
enum GNUNET_DB_QueryStatus
-TMH_PG_lookup_refunds_detailed (void *cls,
- const char *instance_id,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- TALER_MERCHANTDB_RefundDetailCallback rc,
- void *rc_cls);
+TMH_PG_lookup_refunds_detailed (
+ void *cls,
+ const char *instance_id,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ TALER_MERCHANTDB_RefundDetailCallback rc,
+ void *rc_cls);
#endif