aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2024-04-01 20:35:58 +0200
committerChristian Grothoff <christian@grothoff.org>2024-04-01 20:35:58 +0200
commit2e4727bfff65d52114ea8ae300836d71c05e342e (patch)
tree2353ef04abd358090f9a4aae2bb35429314e1da1
parent7e5ab53a78beb172cba18005e2370904c653e3df (diff)
implement protocol v19: consider refunds when returning transaction aggregation data
-rw-r--r--src/exchange/taler-exchange-httpd_config.h2
-rw-r--r--src/exchange/taler-exchange-httpd_transfers_get.c146
-rw-r--r--src/include/taler_crypto_lib.h10
-rw-r--r--src/include/taler_exchangedb_plugin.h15
-rw-r--r--src/lib/Makefile.am2
-rw-r--r--src/lib/exchange_api_handle.c4
-rw-r--r--src/lib/exchange_api_transfers_get.c22
7 files changed, 159 insertions, 42 deletions
diff --git a/src/exchange/taler-exchange-httpd_config.h b/src/exchange/taler-exchange-httpd_config.h
index 40293e89a..640e3b6e9 100644
--- a/src/exchange/taler-exchange-httpd_config.h
+++ b/src/exchange/taler-exchange-httpd_config.h
@@ -41,7 +41,7 @@
*
* Returned via both /config and /keys endpoints.
*/
-#define EXCHANGE_PROTOCOL_VERSION "18:1:1"
+#define EXCHANGE_PROTOCOL_VERSION "19:0:2"
/**
diff --git a/src/exchange/taler-exchange-httpd_transfers_get.c b/src/exchange/taler-exchange-httpd_transfers_get.c
index 2a6dc8776..18d96f955 100644
--- a/src/exchange/taler-exchange-httpd_transfers_get.c
+++ b/src/exchange/taler-exchange-httpd_transfers_get.c
@@ -59,14 +59,20 @@ struct AggregatedDepositDetail
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
- * Total value of the coin in the deposit.
+ * Total value of the coin in the deposit (after
+ * refunds).
*/
struct TALER_Amount deposit_value;
/**
- * Fees charged by the exchange for the deposit of this coin.
+ * Fees charged by the exchange for the deposit of this coin (possibly after reduction due to refunds).
*/
struct TALER_Amount deposit_fee;
+
+ /**
+ * Total amount refunded for this coin.
+ */
+ struct TALER_Amount refund_total;
};
@@ -120,6 +126,13 @@ reply_transfer_details (struct MHD_Connection *connection,
&wdd_pos->h_contract_terms),
GNUNET_JSON_pack_data_auto ("coin_pub",
&wdd_pos->coin_pub),
+
+ GNUNET_JSON_pack_allow_null (
+ TALER_JSON_pack_amount ("refund_total",
+ TALER_amount_is_zero (
+ &wdd_pos->refund_total)
+ ? NULL
+ : &wdd_pos->refund_total)),
TALER_JSON_pack_amount ("deposit_value",
&wdd_pos->deposit_value),
TALER_JSON_pack_amount ("deposit_fee",
@@ -248,6 +261,31 @@ struct WtidTransactionContext
/**
+ * Callback that totals up the applicable refunds.
+ *
+ * @param cls a `struct TALER_Amount` where we keep the total
+ * @param amount_with_fee amount being refunded
+ */
+static enum GNUNET_GenericReturnValue
+add_refunds (void *cls,
+ const struct TALER_Amount *amount_with_fee)
+
+{
+ struct TALER_Amount *total = cls;
+
+ if (0 >
+ TALER_amount_add (total,
+ total,
+ amount_with_fee))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
* Function called with the results of the lookup of the individual deposits
* that were aggregated for the given wire transfer.
*
@@ -260,29 +298,96 @@ struct WtidTransactionContext
* @param h_contract_terms which proposal was this payment about
* @param denom_pub denomination public key of the @a coin_pub (ignored)
* @param coin_pub which public key was this payment about
- * @param deposit_value amount contributed by this coin in total
+ * @param deposit_value amount contributed by this coin in total (including fee)
* @param deposit_fee deposit fee charged by exchange for this coin
*/
static void
-handle_deposit_data (void *cls,
- uint64_t rowid,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const char *account_payto_uri,
- const struct TALER_PaytoHashP *h_payto,
- struct GNUNET_TIME_Timestamp exec_time,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- const struct TALER_DenominationPublicKey *denom_pub,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_Amount *deposit_value,
- const struct TALER_Amount *deposit_fee)
+handle_deposit_data (
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const char *account_payto_uri,
+ const struct TALER_PaytoHashP *h_payto,
+ struct GNUNET_TIME_Timestamp exec_time,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_Amount *deposit_value,
+ const struct TALER_Amount *deposit_fee)
{
struct WtidTransactionContext *ctx = cls;
+ struct TALER_Amount total_refunds;
+ struct TALER_Amount dval;
+ struct TALER_Amount dfee;
+ enum GNUNET_DB_QueryStatus qs;
(void) rowid;
(void) denom_pub;
(void) h_payto;
if (GNUNET_SYSERR == ctx->is_valid)
return;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (deposit_value->currency,
+ &total_refunds));
+ qs = TEH_plugin->select_refunds_by_coin (TEH_plugin->cls,
+ coin_pub,
+ merchant_pub,
+ h_contract_terms,
+ &add_refunds,
+ &total_refunds);
+ if (qs < 0)
+ {
+ GNUNET_break (0);
+ ctx->is_valid = GNUNET_SYSERR;
+ return;
+ }
+ if (1 ==
+ TALER_amount_cmp (&total_refunds,
+ deposit_value))
+ {
+ /* Refunds exceeded total deposit? not OK! */
+ GNUNET_break (0);
+ ctx->is_valid = GNUNET_SYSERR;
+ return;
+ }
+ if (0 ==
+ TALER_amount_cmp (&total_refunds,
+ deposit_value))
+ {
+ /* total_refunds == deposit_value;
+ in this case, the total contributed to the
+ wire transfer is zero (as are fees) */
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (deposit_value->currency,
+ &dval));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (deposit_value->currency,
+ &dfee));
+
+ }
+ else
+ {
+ /* Compute deposit value by subtracting refunds */
+ GNUNET_assert (0 <
+ TALER_amount_subtract (&dval,
+ deposit_value,
+ &total_refunds));
+ if (-1 ==
+ TALER_amount_cmp (&dval,
+ deposit_fee))
+ {
+ /* dval < deposit_fee, so after refunds less than
+ the deposit fee remains; reduce deposit fee to
+ the remaining value of the coin */
+ dfee = dval;
+ }
+ else
+ {
+ /* Partial refund, deposit fee remains */
+ dfee = *deposit_fee;
+ }
+ }
+
if (GNUNET_NO == ctx->is_valid)
{
/* First one we encounter, setup general information in 'ctx' */
@@ -292,8 +397,8 @@ handle_deposit_data (void *cls,
ctx->is_valid = GNUNET_YES;
if (0 >
TALER_amount_subtract (&ctx->total,
- deposit_value,
- deposit_fee))
+ &dval,
+ &dfee))
{
GNUNET_break (0);
ctx->is_valid = GNUNET_SYSERR;
@@ -317,8 +422,8 @@ handle_deposit_data (void *cls,
}
if (0 >
TALER_amount_subtract (&delta,
- deposit_value,
- deposit_fee))
+ &dval,
+ &dfee))
{
GNUNET_break (0);
ctx->is_valid = GNUNET_SYSERR;
@@ -339,8 +444,9 @@ handle_deposit_data (void *cls,
struct AggregatedDepositDetail *wdd;
wdd = GNUNET_new (struct AggregatedDepositDetail);
- wdd->deposit_value = *deposit_value;
- wdd->deposit_fee = *deposit_fee;
+ wdd->deposit_value = dval;
+ wdd->deposit_fee = dfee;
+ wdd->refund_total = total_refunds;
wdd->h_contract_terms = *h_contract_terms;
wdd->coin_pub = *coin_pub;
GNUNET_CONTAINER_DLL_insert (ctx->wdd_head,
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index e3ae829fd..b941316b5 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -1336,15 +1336,21 @@ struct TALER_TrackTransferDetails
struct TALER_CoinSpendPublicKeyP coin_pub;
/**
- * Value of the deposit (including fee).
+ * Value of the deposit (including fee), after refunds.
*/
struct TALER_Amount coin_value;
/**
- * Fee charged by the exchange for the deposit.
+ * Fee charged by the exchange for the deposit,
+ * possibly reduced (or waived) due to refunds.
*/
struct TALER_Amount coin_fee;
+ /**
+ * Total amount of refunds applied to this coin.
+ */
+ struct TALER_Amount refund_total;
+
};
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index 985664c43..2d5857677 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -4483,14 +4483,13 @@ struct TALER_EXCHANGEDB_Plugin
* @return query result status
*/
enum GNUNET_DB_QueryStatus
- (*select_refunds_by_coin)(void *cls,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct
- TALER_MerchantPublicKeyP *merchant_pub,
- const struct
- TALER_PrivateContractHashP *h_contract,
- TALER_EXCHANGEDB_RefundCoinCallback cb,
- void *cb_cls);
+ (*select_refunds_by_coin)(
+ void *cls,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_PrivateContractHashP *h_contract,
+ TALER_EXCHANGEDB_RefundCoinCallback cb,
+ void *cb_cls);
/**
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 256efd11d..30d7c744e 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -18,7 +18,7 @@ lib_LTLIBRARIES = \
libtalerexchange.la
libtalerexchange_la_LDFLAGS = \
- -version-info 6:0:0 \
+ -version-info 7:0:1 \
-no-undefined
libtalerexchange_la_SOURCES = \
exchange_api_add_aml_decision.c \
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index bce3f2876..fdadc8d2a 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -40,12 +40,12 @@
* Which version of the Taler protocol is implemented
* by this library? Used to determine compatibility.
*/
-#define EXCHANGE_PROTOCOL_CURRENT 17
+#define EXCHANGE_PROTOCOL_CURRENT 19
/**
* How many versions are we backwards compatible with?
*/
-#define EXCHANGE_PROTOCOL_AGE 0
+#define EXCHANGE_PROTOCOL_AGE 2
/**
* Set to 1 for extra debug logging.
diff --git a/src/lib/exchange_api_transfers_get.c b/src/lib/exchange_api_transfers_get.c
index 14cf51ff9..c558fb42e 100644
--- a/src/lib/exchange_api_transfers_get.c
+++ b/src/lib/exchange_api_transfers_get.c
@@ -153,21 +153,27 @@ check_transfers_get_response_ok (
GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&detail->h_contract_terms),
GNUNET_JSON_spec_fixed_auto ("coin_pub", &detail->coin_pub),
- TALER_JSON_spec_amount_any ("deposit_value", &detail->coin_value),
- TALER_JSON_spec_amount_any ("deposit_fee", &detail->coin_fee),
+ TALER_JSON_spec_amount ("deposit_value",
+ total_expected.currency,
+ &detail->coin_value),
+ TALER_JSON_spec_amount ("deposit_fee",
+ total_expected.currency,
+ &detail->coin_fee),
+ GNUNET_JSON_spec_mark_optional (
+ TALER_JSON_spec_amount ("refund_total",
+ total_expected.currency,
+ &detail->refund_total),
+ NULL),
GNUNET_JSON_spec_end ()
};
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (td->total_amount.currency,
+ &detail->refund_total));
if ( (GNUNET_OK !=
GNUNET_JSON_parse (detail_j,
spec_detail,
NULL, NULL)) ||
- (GNUNET_OK !=
- TALER_amount_cmp_currency (&total_expected,
- &detail->coin_value)) ||
- (GNUNET_OK !=
- TALER_amount_cmp_currency (&total_expected,
- &detail->coin_fee)) ||
(0 >
TALER_amount_add (&total_expected,
&total_expected,