summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exchange/taler-exchange-httpd_db.c26
-rw-r--r--src/exchange/taler-exchange-httpd_payback.c20
-rw-r--r--src/exchange/taler-exchange-httpd_refund.c6
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c88
-rw-r--r--src/exchangedb/plugin_exchangedb_common.c4
-rw-r--r--src/include/taler_signatures.h45
6 files changed, 166 insertions, 23 deletions
diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c
index 1f47f8e1..3b9dc36b 100644
--- a/src/exchange/taler-exchange-httpd_db.c
+++ b/src/exchange/taler-exchange-httpd_db.c
@@ -168,8 +168,8 @@ TEH_DB_run_transaction (struct MHD_Connection *connection,
// FIXME: maybe move to another module, i.e. exchangedb???
int
TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionList *tl,
- const struct TALER_Amount *off,
- struct TALER_Amount *ret)
+ const struct TALER_Amount *off,
+ struct TALER_Amount *ret)
{
struct TALER_Amount spent = *off;
struct TALER_Amount refunded;
@@ -222,6 +222,17 @@ TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionLis
return GNUNET_SYSERR;
}
break;
+ case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK:
+ /* refunded += pos->value */
+ if (GNUNET_OK !=
+ TALER_amount_add (&refunded,
+ &refunded,
+ &pos->details.old_coin_payback->value))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ break;
case TALER_EXCHANGEDB_TT_PAYBACK:
/* spent += pos->value */
if (GNUNET_OK !=
@@ -233,6 +244,17 @@ TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionLis
return GNUNET_SYSERR;
}
break;
+ case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH:
+ /* spent += pos->value */
+ if (GNUNET_OK !=
+ TALER_amount_add (&spent,
+ &spent,
+ &pos->details.payback_refresh->value))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ break;
}
}
/* spent = spent - refunded */
diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c
index 232c639e..2f1a2dde 100644
--- a/src/exchange/taler-exchange-httpd_payback.c
+++ b/src/exchange/taler-exchange-httpd_payback.c
@@ -285,26 +285,6 @@ payback_transaction (void *cls,
}
return qs;
}
- /* increment reserve balance */
- qs = TEH_plugin->increment_reserve_balance (TEH_plugin->cls,
- session,
- &pc->reserve_pub,
- pc->coin,
- pc->coin_sig,
- pc->coin_bks,
- &pc->amount,
- &pc->h_blind,
- pc->now);
- if (0 > qs)
- {
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- TALER_LOG_WARNING ("Failed to store /payback information in database\n");
- *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
- TALER_EC_PAYBACK_DB_PUT_FAILED);
- }
- return qs;
- }
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}
diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c
index ee6aac1b..69b5cae9 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -236,9 +236,15 @@ refund_transaction (void *cls,
}
}
break;
+ case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK:
+ /* Paybacks cannot be refunded, ignore here */
+ break;
case TALER_EXCHANGEDB_TT_PAYBACK:
/* Paybacks cannot be refunded, ignore here */
break;
+ case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH:
+ /* Paybacks cannot be refunded, ignore here */
+ break;
}
}
/* handle if deposit was NOT found */
diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c
index 5881cbe5..3cf3e781 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -632,6 +632,50 @@ TEH_RESPONSE_compile_transaction_history (const struct TALER_EXCHANGEDB_Transact
}
}
break;
+ case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK:
+ {
+ struct TALER_EXCHANGEDB_PaybackRefresh *pr = pos->details.old_coin_payback;
+ struct TALER_PaybackRefreshConfirmationPS pc;
+ struct TALER_ExchangePublicKeyP epub;
+ struct TALER_ExchangeSignatureP esig;
+
+ pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH);
+ pc.purpose.size = htonl (sizeof (pc));
+ pc.timestamp = GNUNET_TIME_absolute_hton (pr->timestamp);
+ TALER_amount_hton (&pc.payback_amount,
+ &pr->value);
+ pc.coin_pub = pr->coin.coin_pub;
+ pc.old_coin_pub = pr->old_coin_pub;
+ if (GNUNET_OK !=
+ TEH_KS_sign (&pc.purpose,
+ &epub,
+ &esig))
+ {
+ GNUNET_break (0);
+ json_decref (history);
+ return NULL;
+ }
+ /* NOTE: we could also provide coin_pub's coin_sig, denomination key hash and
+ the denomination key's RSA signature over coin_pub, but as the
+ wallet should really already have this information (and cannot
+ check or do anything with it anyway if it doesn't), it seems
+ strictly unnecessary. */
+ if (0 !=
+ json_array_append_new (history,
+ json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}",
+ "type", "OLD-COIN-PAYBACK",
+ "amount", TALER_JSON_from_amount (&pr->value),
+ "exchange_sig", GNUNET_JSON_from_data_auto (&esig),
+ "exchange_pub", GNUNET_JSON_from_data_auto (&epub),
+ "coin_pub", GNUNET_JSON_from_data_auto (&pr->coin.coin_pub),
+ "timestamp", GNUNET_JSON_from_time_abs (pr->timestamp))))
+ {
+ GNUNET_break (0);
+ json_decref (history);
+ return NULL;
+ }
+ break;
+ }
case TALER_EXCHANGEDB_TT_PAYBACK:
{
const struct TALER_EXCHANGEDB_Payback *payback = pos->details.payback;
@@ -671,6 +715,50 @@ TEH_RESPONSE_compile_transaction_history (const struct TALER_EXCHANGEDB_Transact
}
}
break;
+ case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH:
+ {
+ struct TALER_EXCHANGEDB_PaybackRefresh *pr = pos->details.payback_refresh;
+ struct TALER_PaybackRefreshConfirmationPS pc;
+ struct TALER_ExchangePublicKeyP epub;
+ struct TALER_ExchangeSignatureP esig;
+
+ pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH);
+ pc.purpose.size = htonl (sizeof (pc));
+ pc.timestamp = GNUNET_TIME_absolute_hton (pr->timestamp);
+ TALER_amount_hton (&pc.payback_amount,
+ &pr->value);
+ pc.coin_pub = pr->coin.coin_pub;
+ pc.old_coin_pub = pr->old_coin_pub;
+ if (GNUNET_OK !=
+ TEH_KS_sign (&pc.purpose,
+ &epub,
+ &esig))
+ {
+ GNUNET_break (0);
+ json_decref (history);
+ return NULL;
+ }
+ /* NOTE: we could also provide coin_pub's coin_sig, denomination key
+ hash and the denomination key's RSA signature over coin_pub, but as
+ the wallet should really already have this information (and cannot
+ check or do anything with it anyway if it doesn't), it seems
+ strictly unnecessary. */
+ if (0 !=
+ json_array_append_new (history,
+ json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}",
+ "type", "PAYBACK-REFRESH",
+ "amount", TALER_JSON_from_amount (&pr->value),
+ "exchange_sig", GNUNET_JSON_from_data_auto (&esig),
+ "exchange_pub", GNUNET_JSON_from_data_auto (&epub),
+ "old_coin_pub", GNUNET_JSON_from_data_auto (&pr->old_coin_pub),
+ "timestamp", GNUNET_JSON_from_time_abs (pr->timestamp))))
+ {
+ GNUNET_break (0);
+ json_decref (history);
+ return NULL;
+ }
+ break;
+ }
default:
GNUNET_assert (0);
}
diff --git a/src/exchangedb/plugin_exchangedb_common.c b/src/exchangedb/plugin_exchangedb_common.c
index 4a72f546..4c381586 100644
--- a/src/exchangedb/plugin_exchangedb_common.c
+++ b/src/exchangedb/plugin_exchangedb_common.c
@@ -100,6 +100,8 @@ common_free_coin_transaction_list (void *cls,
GNUNET_free (list->details.melt);
break;
case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK:
+ if (NULL != list->details.payback_refresh->coin.denom_sig.rsa_signature)
+ GNUNET_CRYPTO_rsa_signature_free (list->details.payback_refresh->coin.denom_sig.rsa_signature);
GNUNET_free (list->details.old_coin_payback);
break;
case TALER_EXCHANGEDB_TT_REFUND:
@@ -113,6 +115,8 @@ common_free_coin_transaction_list (void *cls,
GNUNET_free (list->details.payback);
break;
case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH:
+ if (NULL != list->details.payback_refresh->coin.denom_sig.rsa_signature)
+ GNUNET_CRYPTO_rsa_signature_free (list->details.payback_refresh->coin.denom_sig.rsa_signature);
GNUNET_free (list->details.payback_refresh);
break;
}
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index b738e315..aedf93e3 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -129,6 +129,11 @@
*/
#define TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED 1040
+/**
+ * Signature where the Exchange confirms a payback-refresh operation.
+ */
+#define TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH 1041
+
/**********************/
/* Auditor signatures */
@@ -1229,7 +1234,7 @@ struct TALER_PaybackRequestPS
/**
* Response by which the exchange affirms that it will
* refund a coin as part of the emergency /payback
- * protocol. The refund will go back to the bank
+ * protocol. The payback will go back to the bank
* account that created the reserve.
*/
struct TALER_PaybackConfirmationPS
@@ -1266,6 +1271,44 @@ struct TALER_PaybackConfirmationPS
/**
+ * Response by which the exchange affirms that it will refund a refreshed coin
+ * as part of the emergency /payback protocol. The payback will go back to the
+ * old coin's balance.
+ */
+struct TALER_PaybackRefreshConfirmationPS
+{
+
+ /**
+ * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH
+ */
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+ /**
+ * When did the exchange receive the payback request?
+ * Indirectly determines when the wire transfer is (likely)
+ * to happen.
+ */
+ struct GNUNET_TIME_AbsoluteNBO timestamp;
+
+ /**
+ * How much of the coin's value will the exchange transfer?
+ * (Needed in case the coin was partially spent.)
+ */
+ struct TALER_AmountNBO payback_amount;
+
+ /**
+ * Public key of the refreshed coin.
+ */
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+
+ /**
+ * Public key of the old coin that will receive the payback.
+ */
+ struct TALER_CoinSpendPublicKeyP old_coin_pub;
+};
+
+
+/**
* Response by which the exchange affirms that it has
* closed a reserve and send back the funds.
*/