aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/exchange-lib/exchange_api_payback.c8
-rw-r--r--src/exchange/taler-exchange-httpd_db.c8
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c163
-rw-r--r--src/exchange/taler-exchange-httpd_responses.h4
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c11
-rw-r--r--src/exchangedb/test_exchangedb.c5
-rw-r--r--src/include/taler_exchange_service.h4
-rw-r--r--src/include/taler_exchangedb_plugin.h4
-rw-r--r--src/include/taler_signatures.h48
9 files changed, 185 insertions, 70 deletions
diff --git a/src/exchange-lib/exchange_api_payback.c b/src/exchange-lib/exchange_api_payback.c
index b08fe3b68..eff459693 100644
--- a/src/exchange-lib/exchange_api_payback.c
+++ b/src/exchange-lib/exchange_api_payback.c
@@ -94,13 +94,13 @@ verify_payback_signature_ok (const struct TALER_EXCHANGE_PaybackHandle *ph,
struct TALER_ExchangePublicKeyP exchange_pub;
struct TALER_ExchangeSignatureP exchange_sig;
struct TALER_Amount amount;
- struct GNUNET_TIME_Absolute deadline;
+ struct GNUNET_TIME_Absolute timestamp;
const struct TALER_EXCHANGE_Keys *key_state;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub),
TALER_JSON_spec_amount ("amount", &amount),
- GNUNET_JSON_spec_absolute_time ("payback_deadline", &deadline),
+ GNUNET_JSON_spec_absolute_time ("timestamp", &timestamp),
GNUNET_JSON_spec_fixed_auto ("reserve_pub", &pc.reserve_pub),
GNUNET_JSON_spec_end()
};
@@ -123,7 +123,7 @@ verify_payback_signature_ok (const struct TALER_EXCHANGE_PaybackHandle *ph,
}
pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
pc.purpose.size = htonl (sizeof (pc));
- pc.payback_deadline = GNUNET_TIME_absolute_hton (deadline);
+ pc.timestamp = GNUNET_TIME_absolute_hton (timestamp);
TALER_amount_hton (&pc.payback_amount,
&amount);
pc.coin_pub = ph->coin_pub;
@@ -140,7 +140,7 @@ verify_payback_signature_ok (const struct TALER_EXCHANGE_PaybackHandle *ph,
MHD_HTTP_OK,
TALER_EC_NONE,
&amount,
- deadline,
+ timestamp,
&pc.reserve_pub,
json);
return GNUNET_OK;
diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c
index 3dc4a3248..11f8d31d3 100644
--- a/src/exchange/taler-exchange-httpd_db.c
+++ b/src/exchange/taler-exchange-httpd_db.c
@@ -2335,7 +2335,7 @@ TEH_DB_execute_payback (struct MHD_Connection *connection,
struct TALER_ReservePublicKeyP reserve_pub;
struct TALER_Amount amount;
struct TALER_Amount spent;
- struct GNUNET_TIME_Absolute payback_deadline;
+ struct GNUNET_TIME_Absolute now;
if (NULL == (session = TEH_plugin->get_session (TEH_plugin->cls)))
{
@@ -2406,6 +2406,8 @@ TEH_DB_execute_payback (struct MHD_Connection *connection,
}
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
tl);
+ now = GNUNET_TIME_absolute_get ();
+ (void) GNUNET_TIME_round_abs (&now);
/* add coin to list of wire transfers for payback */
ret = TEH_plugin->insert_payback_request (TEH_plugin->cls,
@@ -2416,7 +2418,7 @@ TEH_DB_execute_payback (struct MHD_Connection *connection,
coin_blind,
&amount,
h_blind,
- &payback_deadline);
+ now);
if (GNUNET_SYSERR == ret)
{
TALER_LOG_WARNING ("Failed to store /payback information in database\n");
@@ -2432,7 +2434,7 @@ TEH_DB_execute_payback (struct MHD_Connection *connection,
&coin->coin_pub,
&reserve_pub,
&amount,
- payback_deadline);
+ now);
}
diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c
index 01dcb6ca0..29ba9e02f 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015, 2016, 2017 Inria & GNUnet e.V.
+ Copyright (C) 2014-2017 Inria & GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -554,32 +554,34 @@ compile_transaction_history (const struct TALER_EXCHANGEDB_TransactionList *tl)
case TALER_EXCHANGEDB_TT_PAYBACK:
{
const struct TALER_EXCHANGEDB_Payback *payback = pos->details.payback;
- struct TALER_PaybackRequestPS pr;
+ struct TALER_PaybackConfirmationPS pc;
+ struct TALER_ExchangePublicKeyP epub;
+ struct TALER_ExchangeSignatureP esig;
type = "PAYBACK";
value = payback->value;
- pr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_PAYBACK);
- pr.purpose.size = htonl (sizeof (pr));
- pr.coin_pub = payback->coin_pub;
- GNUNET_CRYPTO_rsa_public_key_hash (payback->denom_pub.rsa_public_key,
- &pr.h_denom_pub);
- pr.coin_blind = payback->coin_blind;
-
- /* internal sanity check before we hand out a bogus sig... */
- sig = &payback->coin_sig.eddsa_signature;
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_PAYBACK,
- &pr.purpose,
- sig,
- &payback->coin_pub.eddsa_pub))
- {
- GNUNET_break (0);
- json_decref (history);
- return NULL;
- }
- details = GNUNET_JSON_from_data_auto (&pr);
+ pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
+ pc.purpose.size = htonl (sizeof (pc));
+ pc.timestamp = GNUNET_TIME_absolute_hton (payback->timestamp);
+ TALER_amount_hton (&pc.payback_amount,
+ &payback->value);
+ pc.coin_pub = payback->coin_pub;
+ pc.reserve_pub = payback->reserve_pub;
+ TEH_KS_sign (&pc.purpose,
+ &epub,
+ &esig);
+ details = GNUNET_JSON_from_data_auto (&pc);
+ GNUNET_assert (0 ==
+ json_array_append_new (history,
+ json_pack ("{s:s, s:o, s:o, s:o, s:o}",
+ "type", type,
+ "amount", TALER_JSON_from_amount (&value),
+ "exchange_sig", GNUNET_JSON_from_data_auto (&esig),
+ "exchange_pub", GNUNET_JSON_from_data_auto (&epub),
+ "details", details)));
}
- break;
+ /* do not go to the default handler, we already appended! */
+ continue;
default:
GNUNET_assert (0);
}
@@ -646,6 +648,11 @@ compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHistory *rh,
int ret;
const struct TALER_EXCHANGEDB_ReserveHistory *pos;
struct TALER_WithdrawRequestPS wr;
+ const struct TALER_EXCHANGEDB_Payback *payback;
+ struct TALER_PaybackConfirmationPS pc;
+ struct TALER_ReserveCloseConfirmationPS rcc;
+ struct TALER_ExchangePublicKeyP pub;
+ struct TALER_ExchangeSignatureP sig;
json_history = json_array ();
ret = 0;
@@ -654,7 +661,7 @@ compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHistory *rh,
switch (pos->type)
{
case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
- if (0 == ret)
+ if (0 == (1 & ret))
deposit_total = pos->details.bank->amount;
else
if (GNUNET_OK !=
@@ -665,7 +672,7 @@ compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHistory *rh,
json_decref (json_history);
return NULL;
}
- ret = 1;
+ ret |= 1;
GNUNET_assert (0 ==
json_array_append_new (json_history,
json_pack ("{s:s, s:O, s:O, s:o}",
@@ -675,20 +682,8 @@ compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHistory *rh,
"amount", TALER_JSON_from_amount (&pos->details.bank->amount))));
break;
case TALER_EXCHANGEDB_RO_WITHDRAW_COIN:
- break;
- }
- }
-
- ret = 0;
- for (pos = rh; NULL != pos; pos = pos->next)
- {
- switch (pos->type)
- {
- case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
- break;
- case TALER_EXCHANGEDB_RO_WITHDRAW_COIN:
value = pos->details.withdraw->amount_with_fee;
- if (0 == ret)
+ if (0 == (2 & ret))
{
withdraw_total = value;
}
@@ -703,7 +698,7 @@ compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHistory *rh,
return NULL;
}
}
- ret = 1;
+ ret |= 2;
wr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
wr.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
wr.reserve_pub = pos->details.withdraw->reserve_pub;
@@ -720,11 +715,91 @@ compile_reserve_history (const struct TALER_EXCHANGEDB_ReserveHistory *rh,
"type", "WITHDRAW",
"signature", GNUNET_JSON_from_data_auto (&pos->details.withdraw->reserve_sig),
"details", GNUNET_JSON_from_data_auto (&wr),
+
+ "amount", TALER_JSON_from_amount (&value))));
+ break;
+ case TALER_EXCHANGEDB_RO_PAYBACK_COIN:
+ payback = pos->details.payback;
+ if (0 == (1 & ret))
+ deposit_total = payback->value;
+ else
+ if (GNUNET_OK !=
+ TALER_amount_add (&deposit_total,
+ &deposit_total,
+ &payback->value))
+ {
+ json_decref (json_history);
+ return NULL;
+ }
+ ret |= 1;
+ pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
+ pc.purpose.size = htonl (sizeof (struct TALER_PaybackConfirmationPS));
+ pc.timestamp = GNUNET_TIME_absolute_hton (payback->timestamp);
+ TALER_amount_hton (&pc.payback_amount,
+ &payback->value);
+ pc.coin_pub = payback->coin_pub;
+ pc.reserve_pub = payback->reserve_pub;
+ TEH_KS_sign (&pc.purpose,
+ &pub,
+ &sig);
+
+ GNUNET_assert (0 ==
+ json_array_append_new (json_history,
+ json_pack ("{s:s, s:o, s:o, s:o, s:o}",
+ "type", "PAYBACK",
+ "exchange_pub", GNUNET_JSON_from_data_auto (&pub),
+ "exchange_sig", GNUNET_JSON_from_data_auto (&sig),
+ "timestamp", GNUNET_JSON_from_time_abs (payback->timestamp),
+ "amount", TALER_JSON_from_amount (&payback->value))));
+ break;
+ case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK:
+ value = pos->details.bank->amount;
+ if (0 == (2 & ret))
+ {
+ withdraw_total = value;
+ }
+ else
+ {
+ if (GNUNET_OK !=
+ TALER_amount_add (&withdraw_total,
+ &withdraw_total,
+ &value))
+ {
+ json_decref (json_history);
+ return NULL;
+ }
+ }
+ ret |= 2;
+
+ rcc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED);
+ rcc.purpose.size = htonl (sizeof (struct TALER_ReserveCloseConfirmationPS));
+ rcc.timestamp = GNUNET_TIME_absolute_hton (pos->details.bank->execution_date);
+ TALER_amount_hton (&rcc.closing_amount,
+ &value);
+ rcc.reserve_pub = pos->details.bank->reserve_pub;
+ TALER_JSON_hash (pos->details.bank->sender_account_details,
+ &rcc.h_wire);
+ TEH_KS_sign (&rcc.purpose,
+ &pub,
+ &sig);
+ GNUNET_assert (0 ==
+ json_array_append_new (json_history,
+ json_pack ("{s:s, s:o, s:o, s:o, s:o}",
+ "type", "CLOSING",
+ "exchange_pub", GNUNET_JSON_from_data_auto (&pub),
+ "exchange_sig", GNUNET_JSON_from_data_auto (&sig),
+ "details", GNUNET_JSON_from_data_auto (&rcc),
"amount", TALER_JSON_from_amount (&value))));
break;
}
}
- if (0 == ret)
+ if (0 == (1 & ret))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ if (0 == (2 & ret))
{
/* did not encounter any withdraw operations, set to zero */
TALER_amount_get_zero (deposit_total.currency,
@@ -1352,7 +1427,7 @@ TEH_RESPONSE_reply_payback_unknown (struct MHD_Connection *connection,
* @param coin_pub coin for which we are processing the payback request
* @param reserve_pub public key of the reserve that will receive the payback
* @param amount the amount we will wire back
- * @param payback_deadline deadline by which the exchange promises to pay
+ * @param timestamp when did the exchange receive the /payback request
* @return MHD result code
*/
int
@@ -1360,7 +1435,7 @@ TEH_RESPONSE_reply_payback_success (struct MHD_Connection *connection,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute payback_deadline)
+ struct GNUNET_TIME_Absolute timestamp)
{
struct TALER_PaybackConfirmationPS pc;
struct TALER_ExchangePublicKeyP pub;
@@ -1368,7 +1443,7 @@ TEH_RESPONSE_reply_payback_success (struct MHD_Connection *connection,
pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
pc.purpose.size = htonl (sizeof (struct TALER_PaybackConfirmationPS));
- pc.payback_deadline = GNUNET_TIME_absolute_hton (payback_deadline);
+ pc.timestamp = GNUNET_TIME_absolute_hton (timestamp);
TALER_amount_hton (&pc.payback_amount,
amount);
pc.coin_pub = *coin_pub;
@@ -1380,7 +1455,7 @@ TEH_RESPONSE_reply_payback_success (struct MHD_Connection *connection,
MHD_HTTP_OK,
"{s:o, s:o, s:o, s:o, s:o}",
"reserve_pub", GNUNET_JSON_from_data_auto (reserve_pub),
- "payback_deadline", GNUNET_JSON_from_time_abs (payback_deadline),
+ "timestamp", GNUNET_JSON_from_time_abs (timestamp),
"amount", TALER_JSON_from_amount (amount),
"exchange_sig", GNUNET_JSON_from_data_auto (&sig),
"exchange_pub", GNUNET_JSON_from_data_auto (&pub));
diff --git a/src/exchange/taler-exchange-httpd_responses.h b/src/exchange/taler-exchange-httpd_responses.h
index 6b68949e5..83dafdca3 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -579,7 +579,7 @@ TEH_RESPONSE_reply_payback_unknown (struct MHD_Connection *connection,
* @param coin_pub coin for which we are processing the payback request
* @param reserve_pub public key of the reserve that will receive the payback
* @param amount the amount we will wire back
- * @param payback_deadline deadline by which the exchange promises to pay
+ * @param timestamp when did the exchange receive the /payback request
* @return MHD result code
*/
int
@@ -587,7 +587,7 @@ TEH_RESPONSE_reply_payback_success (struct MHD_Connection *connection,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute payback_deadline);
+ struct GNUNET_TIME_Absolute timestamp);
#endif
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index df0c1a5fc..e869bcd95 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -5629,7 +5629,7 @@ postgres_select_wire_out_above_serial_id (void *cls,
* @param amount total amount to be paid back
* @param receiver_account_details who should receive the funds
* @parma h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry)
- * @param[out] deadline set to absolute time by when the exchange plans to pay it back
+ * @param timestamp current time (rounded)
* @return #GNUNET_OK on success,
* #GNUNET_SYSERR on DB errors
*/
@@ -5642,10 +5642,9 @@ postgres_insert_payback_request (void *cls,
const struct TALER_DenominationBlindingKeyP *coin_blind,
const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_blind_ev,
- struct GNUNET_TIME_Absolute *deadline)
+ struct GNUNET_TIME_Absolute timestamp)
{
PGresult *result;
- struct GNUNET_TIME_Absolute now;
struct GNUNET_TIME_Absolute expiry;
struct TALER_EXCHANGEDB_Reserve reserve;
struct GNUNET_PQ_QueryParam params[] = {
@@ -5654,12 +5653,11 @@ postgres_insert_payback_request (void *cls,
GNUNET_PQ_query_param_auto_from_type (coin_sig),
GNUNET_PQ_query_param_auto_from_type (coin_blind),
TALER_PQ_query_param_amount (amount),
- GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_absolute_time (&timestamp),
GNUNET_PQ_query_param_auto_from_type (h_blind_ev),
GNUNET_PQ_query_param_end
};
- now = GNUNET_TIME_absolute_get ();
result = GNUNET_PQ_exec_prepared (session->conn,
"payback_insert",
params);
@@ -5689,7 +5687,7 @@ postgres_insert_payback_request (void *cls,
GNUNET_break (0);
return GNUNET_SYSERR;
}
- expiry = GNUNET_TIME_absolute_add (now,
+ expiry = GNUNET_TIME_absolute_add (timestamp,
TALER_IDLE_RESERVE_EXPIRATION_TIME);
reserve.expiry = GNUNET_TIME_absolute_max (expiry,
reserve.expiry);
@@ -5700,7 +5698,6 @@ postgres_insert_payback_request (void *cls,
GNUNET_break (0);
return GNUNET_SYSERR;
}
- *deadline = reserve.expiry;
return GNUNET_OK;
}
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 0fc0f92b4..e8fd21194 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -1511,6 +1511,7 @@ run (void *cls)
RND_BLK (&coin_sig);
RND_BLK (&coin_blind);
+ deadline = GNUNET_TIME_absolute_get ();
FAILIF (GNUNET_OK !=
plugin->insert_payback_request (plugin->cls,
session,
@@ -1520,7 +1521,7 @@ run (void *cls)
&coin_blind,
&value,
&cbc.h_coin_envelope,
- &deadline));
+ deadline));
result = 7;
rh = plugin->get_reserve_history (plugin->cls,
@@ -1719,7 +1720,7 @@ run (void *cls)
&coin_blind,
&value,
&cbc.h_coin_envelope,
- &deadline));
+ deadline));
auditor_row_cnt = 0;
FAILIF (GNUNET_OK !=
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 39aa96d11..4aa3d0240 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -1344,7 +1344,7 @@ struct TALER_EXCHANGE_PaybackHandle;
* 0 if the exchange's reply is bogus (fails to follow the protocol)
* @param ec taler-specific error code, #TALER_EC_NONE on success
* @param amount amount the exchange will wire back for this coin
- * @param deadline by when will the exchange wire the funds?
+ * @param timestamp what time did the exchange receive the /payback request
* @param reserve_pub public key of the reserve receiving the payback
* @param full_response full response from the exchange (for logging, in case of errors)
*/
@@ -1353,7 +1353,7 @@ typedef void
unsigned int http_status,
enum TALER_ErrorCode ec,
const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute deadline,
+ struct GNUNET_TIME_Absolute timestamp,
const struct TALER_ReservePublicKeyP *reserve_pub,
const json_t *full_response);
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index b578abf95..8a1a82838 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -1956,7 +1956,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param amount total amount to be paid back
* @param receiver_account_details who should receive the funds
* @parma h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry)
- * @param[out] deadline set to absolute time by when the exchange plans to pay it back
+ * @param now timestamp to store
* @return #GNUNET_OK on success,
* #GNUNET_SYSERR on DB errors
*/
@@ -1969,7 +1969,7 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_DenominationBlindingKeyP *coin_blind,
const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_blind_ev,
- struct GNUNET_TIME_Absolute *deadline);
+ struct GNUNET_TIME_Absolute timestamp);
/**
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index 2d0e8bb37..c58ea1915 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -131,6 +131,11 @@
*/
#define TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK 1039
+/**
+ * Signature where the Exchange confirms it closed a reserve.
+ */
+#define TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED 1040
+
/*********************/
/* Wallet signatures */
@@ -1170,15 +1175,16 @@ struct TALER_PaybackConfirmationPS
{
/**
- * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK
+ * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
- * By what deadline does the exchange promise to initiate
- * the wire transfer?
+ * When did the exchange receive the payback request?
+ * Indirectly determines when the wire transfer is (likely)
+ * to happen.
*/
- struct GNUNET_TIME_AbsoluteNBO payback_deadline;
+ struct GNUNET_TIME_AbsoluteNBO timestamp;
/**
* How much of the coin's value will the exchange transfer?
@@ -1198,6 +1204,40 @@ struct TALER_PaybackConfirmationPS
};
+/**
+ * Response by which the exchange affirms that it has
+ * closed a reserve and send back the funds.
+ */
+struct TALER_ReserveCloseConfirmationPS
+{
+
+ /**
+ * Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED
+ */
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+ /**
+ * When did the exchange initiate the wire transfer.
+ */
+ struct GNUNET_TIME_AbsoluteNBO timestamp;
+
+ /**
+ * How much did the exchange send?
+ */
+ struct TALER_AmountNBO closing_amount;
+
+ /**
+ * Public key of the reserve that received the payback.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Hash of the receiver's bank account.
+ */
+ struct GNUNET_HashCode h_wire;
+};
+
+
GNUNET_NETWORK_STRUCT_END
#endif