aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/auditor/taler-helper-auditor-coins.c53
-rw-r--r--src/auditor/taler-helper-auditor-reserves.c49
-rw-r--r--src/exchange/taler-exchange-httpd_recoup.c45
-rw-r--r--src/exchangedb/exchange-0001.sql5
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c4
-rw-r--r--src/exchangedb/test_exchangedb.c39
-rw-r--r--src/include/taler_crypto_lib.h57
-rw-r--r--src/include/taler_signatures.h11
-rw-r--r--src/lib/exchange_api_common.c46
-rw-r--r--src/lib/exchange_api_recoup.c30
-rw-r--r--src/testing/test_exchange_api.c2
-rw-r--r--src/testing/test_exchange_api_revocation.c20
-rw-r--r--src/util/wallet_signatures.c47
13 files changed, 248 insertions, 160 deletions
diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c
index 937613cce..393fc464b 100644
--- a/src/auditor/taler-helper-auditor-coins.c
+++ b/src/auditor/taler-helper-auditor-coins.c
@@ -1983,38 +1983,29 @@ check_recoup (struct CoinContext *cc,
cc->qs = qs;
return GNUNET_SYSERR;
}
+ if (GNUNET_OK !=
+ TALER_wallet_recoup_verify (&coin->denom_pub_hash,
+ coin_blind,
+ amount,
+ &coin->coin_pub,
+ coin_sig))
{
- struct TALER_RecoupRequestPS pr = {
- .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
- .purpose.size = htonl (sizeof (pr)),
- .coin_pub = coin->coin_pub,
- .coin_blind = *coin_blind,
- .h_denom_pub = coin->denom_pub_hash
- };
-
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
- &pr,
- &coin_sig->eddsa_signature,
- &coin->coin_pub.eddsa_pub))
- {
- TALER_ARL_report (report_bad_sig_losses,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("operation",
- operation),
- GNUNET_JSON_pack_uint64 ("row",
- rowid),
- TALER_JSON_pack_amount ("loss",
- amount),
- GNUNET_JSON_pack_data_auto ("coin_pub",
- &coin->coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
- amount);
- if (TALER_ARL_do_abort ())
- return GNUNET_SYSERR;
- return GNUNET_OK;
- }
+ TALER_ARL_report (report_bad_sig_losses,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ operation),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ TALER_JSON_pack_amount ("loss",
+ amount),
+ GNUNET_JSON_pack_data_auto ("coin_pub",
+ &coin->coin_pub)));
+ TALER_ARL_amount_add (&total_bad_sig_loss,
+ &total_bad_sig_loss,
+ amount);
+ if (TALER_ARL_do_abort ())
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
}
ds = get_denomination_summary (cc,
issue,
diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c
index 2ce120202..b6b969fea 100644
--- a/src/auditor/taler-helper-auditor-reserves.c
+++ b/src/auditor/taler-helper-auditor-reserves.c
@@ -684,7 +684,7 @@ handle_reserve_out (void *cls,
* @param coin_blind blinding factor used to blind the coin
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
-static int
+static enum GNUNET_GenericReturnValue
handle_recoup_by_reserve (
void *cls,
uint64_t rowid,
@@ -711,35 +711,26 @@ handle_recoup_by_reserve (
ppr.last_reserve_recoup_serial_id = rowid + 1;
/* We know that denom_pub matches denom_pub_hash because this
is how the SQL statement joined the tables. */
+ if (GNUNET_OK !=
+ TALER_wallet_recoup_verify (&coin->denom_pub_hash,
+ coin_blind,
+ amount,
+ &coin->coin_pub,
+ coin_sig))
{
- struct TALER_RecoupRequestPS pr = {
- .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
- .purpose.size = htonl (sizeof (pr)),
- .h_denom_pub = coin->denom_pub_hash,
- .coin_pub = coin->coin_pub,
- .coin_blind = *coin_blind
- };
-
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
- &pr,
- &coin_sig->eddsa_signature,
- &coin->coin_pub.eddsa_pub))
- {
- TALER_ARL_report (report_bad_sig_losses,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("operation",
- "recoup"),
- GNUNET_JSON_pack_uint64 ("row",
- rowid),
- TALER_JSON_pack_amount ("loss",
- amount),
- GNUNET_JSON_pack_data_auto ("key_pub",
- &coin->coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
- amount);
- }
+ TALER_ARL_report (report_bad_sig_losses,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ "recoup"),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ TALER_JSON_pack_amount ("loss",
+ amount),
+ GNUNET_JSON_pack_data_auto ("key_pub",
+ &coin->coin_pub)));
+ TALER_ARL_amount_add (&total_bad_sig_loss,
+ &total_bad_sig_loss,
+ amount);
}
/* check that the coin was eligible for recoup!*/
diff --git a/src/exchange/taler-exchange-httpd_recoup.c b/src/exchange/taler-exchange-httpd_recoup.c
index ec67efc26..58495e530 100644
--- a/src/exchange/taler-exchange-httpd_recoup.c
+++ b/src/exchange/taler-exchange-httpd_recoup.c
@@ -87,6 +87,7 @@ struct RecoupContext
* Set by #recoup_transaction() to the amount that will be paid back
*/
struct TALER_Amount amount;
+ const struct TALER_Amount *requested_amount;
/**
* Set by #recoup_transaction to the timestamp when the recoup
@@ -234,6 +235,15 @@ recoup_transaction (void *cls,
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
tl);
pc->now = GNUNET_TIME_timestamp_get ();
+ if (0 != TALER_amount_cmp (&pc->amount,
+ pc->requested_amount))
+ {
+ *mhd_ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,
+ TALER_amount2s (&pc->amount));
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
/* add coin to list of wire transfers for recoup */
if (pc->refreshed)
@@ -284,6 +294,7 @@ recoup_transaction (void *cls,
* @param coin information about the coin
* @param coin_bks blinding data of the coin (to be checked)
* @param coin_sig signature of the coin
+ * @param requested_amount requested amount to be recouped
* @param refreshed true if the coin was refreshed
* @return MHD result code
*/
@@ -293,6 +304,7 @@ verify_and_execute_recoup (
const struct TALER_CoinPublicInfo *coin,
const union TALER_DenominationBlindingKeyP *coin_bks,
const struct TALER_CoinSpendSignatureP *coin_sig,
+ const struct TALER_Amount *requested_amount,
bool refreshed)
{
struct RecoupContext pc;
@@ -352,27 +364,18 @@ verify_and_execute_recoup (
}
/* check recoup request signature */
+ if (GNUNET_OK !=
+ TALER_wallet_recoup_verify (&coin->denom_pub_hash,
+ coin_bks,
+ requested_amount,
+ &coin->coin_pub,
+ coin_sig))
{
- struct TALER_RecoupRequestPS pr = {
- .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
- .purpose.size = htonl (sizeof (pr)),
- .coin_pub = coin->coin_pub,
- .h_denom_pub = coin->denom_pub_hash,
- .coin_blind = *coin_bks
- };
-
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
- &pr,
- &coin_sig->eddsa_signature,
- &coin->coin_pub.eddsa_pub))
- {
- TALER_LOG_WARNING ("Invalid signature on recoup request\n");
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_EXCHANGE_RECOUP_SIGNATURE_INVALID,
- NULL);
- }
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_FORBIDDEN,
+ TALER_EC_EXCHANGE_RECOUP_SIGNATURE_INVALID,
+ NULL);
}
{
@@ -404,6 +407,7 @@ verify_and_execute_recoup (
pc.coin_bks = coin_bks;
pc.coin = coin;
pc.refreshed = refreshed;
+ pc.requested_amount = requested_amount;
{
MHD_RESULT mhd_ret = MHD_NO;
@@ -552,6 +556,7 @@ TEH_handler_recoup (struct MHD_Connection *connection,
&coin,
&coin_bks,
&coin_sig,
+ &amount,
refreshed);
GNUNET_JSON_parse_free (spec);
return res;
diff --git a/src/exchangedb/exchange-0001.sql b/src/exchangedb/exchange-0001.sql
index 1725b70e0..a267fe137 100644
--- a/src/exchangedb/exchange-0001.sql
+++ b/src/exchangedb/exchange-0001.sql
@@ -697,8 +697,6 @@ CREATE INDEX IF NOT EXISTS revolving_work_shards_index
-- Stored procedures
-DROP FUNCTION IF EXISTS exchange_do_withdraw(bigint,integer,bytea,bytea,bytea,bytea,bytea,bigint,bigint) ;
-
CREATE OR REPLACE FUNCTION exchange_do_withdraw(
IN amount_val INT8,
IN amount_frac INT4,
@@ -857,9 +855,6 @@ COMMENT ON FUNCTION exchange_do_withdraw(INT8, INT4, BYTEA, BYTEA, BYTEA, BYTEA,
-DROP FUNCTION IF EXISTS exchange_do_withdraw_limit_check(bigint,bigint,bigint,int) ;
-
-
CREATE OR REPLACE FUNCTION exchange_do_withdraw_limit_check(
IN ruuid INT8,
IN start_time INT8,
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 23307bf80..99ebd7c7b 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -3246,8 +3246,8 @@ postgres_get_denomination_info (
rs);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
return qs;
- issue->properties.purpose.size = htonl (sizeof (struct
- TALER_DenominationKeyValidityPS));
+ issue->properties.purpose.size
+ = htonl (sizeof (struct TALER_DenominationKeyValidityPS));
issue->properties.purpose.purpose = htonl (
TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY);
issue->properties.denom_hash = *denom_pub_hash;
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index a8a9f3e16..65689d872 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -238,23 +238,26 @@ create_denom_key_pair (unsigned int size,
sizeof (struct TALER_EXCHANGEDB_DenominationKey));
dki.denom_pub = dkp->pub;
dki.issue.properties.start = GNUNET_TIME_timestamp_hton (now);
- dki.issue.properties.expire_withdraw = GNUNET_TIME_timestamp_hton
- (GNUNET_TIME_absolute_to_timestamp
- (GNUNET_TIME_absolute_add (
- now.abs_time,
- GNUNET_TIME_UNIT_HOURS)));
- dki.issue.properties.expire_deposit = GNUNET_TIME_timestamp_hton (
- GNUNET_TIME_absolute_to_timestamp
- (GNUNET_TIME_absolute_add
- (now.abs_time,
- GNUNET_TIME_relative_multiply (
- GNUNET_TIME_UNIT_HOURS, 2))));
- dki.issue.properties.expire_legal = GNUNET_TIME_timestamp_hton (
- GNUNET_TIME_absolute_to_timestamp
- (GNUNET_TIME_absolute_add
- (now.abs_time,
- GNUNET_TIME_relative_multiply (
- GNUNET_TIME_UNIT_HOURS, 3))));
+ dki.issue.properties.expire_withdraw
+ = GNUNET_TIME_timestamp_hton
+ (GNUNET_TIME_absolute_to_timestamp
+ (GNUNET_TIME_absolute_add (
+ now.abs_time,
+ GNUNET_TIME_UNIT_HOURS)));
+ dki.issue.properties.expire_deposit
+ = GNUNET_TIME_timestamp_hton (
+ GNUNET_TIME_absolute_to_timestamp
+ (GNUNET_TIME_absolute_add
+ (now.abs_time,
+ GNUNET_TIME_relative_multiply (
+ GNUNET_TIME_UNIT_HOURS, 2))));
+ dki.issue.properties.expire_legal
+ = GNUNET_TIME_timestamp_hton (
+ GNUNET_TIME_absolute_to_timestamp
+ (GNUNET_TIME_absolute_add
+ (now.abs_time,
+ GNUNET_TIME_relative_multiply (
+ GNUNET_TIME_UNIT_HOURS, 3))));
TALER_amount_hton (&dki.issue.properties.value, value);
TALER_amount_hton (&dki.issue.properties.fee_withdraw, fee_withdraw);
TALER_amount_hton (&dki.issue.properties.fee_deposit, fee_deposit);
@@ -276,6 +279,8 @@ create_denom_key_pair (unsigned int size,
destroy_denom_key_pair (dkp);
return NULL;
}
+ memset (&issue2, 0, sizeof (issue2));
+ plugin->commit (plugin->cls);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->get_denomination_info (plugin->cls,
&dki.issue.properties.denom_hash,
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index 0a59ab9e3..5292cd09b 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -1738,6 +1738,63 @@ TALER_wallet_link_verify (
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
const struct TALER_CoinSpendSignatureP *coin_sig);
+
+/**
+ * Sign link data.
+ *
+ * @param h_denom_pub hash of the denomiantion public key of the new coin
+ * @param transfer_pub transfer public key
+ * @param coin_ev coin envelope
+ * @param coin_ev_size number of bytes in @a coin_ev
+ * @param old_coin_priv private key to sign with
+ * @param[out] coin_sig resulting signature
+ */
+void
+TALER_wallet_link_sign (const struct TALER_DenominationHash *h_denom_pub,
+ const struct TALER_TransferPublicKeyP *transfer_pub,
+ const void *coin_ev,
+ size_t coin_ev_size,
+ const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
+ struct TALER_CoinSpendSignatureP *coin_sig);
+
+
+/**
+ * Verify recoup signature.
+ *
+ * @param h_denom_pub hash of the denomiantion public key of the coin
+ * @param coin_bks blinding factor used when withdrawing the coin
+ * @param requested_amount amount that is left to be recouped
+ * @param coin_pub coin key of the coin to be recouped
+ * @param coin_sig resulting signature
+ * @return #GNUNET_OK if the signature is valid
+ */
+enum GNUNET_GenericReturnValue
+TALER_wallet_recoup_verify (
+ const struct TALER_DenominationHash *h_denom_pub,
+ const union TALER_DenominationBlindingKeyP *coin_bks,
+ const struct TALER_Amount *requested_amount,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_CoinSpendSignatureP *coin_sig);
+
+
+/**
+ * Create recoup signature.
+ *
+ * @param h_denom_pub hash of the denomiantion public key of the coin
+ * @param coin_bks blinding factor used when withdrawing the coin
+ * @param requested_amount amount that is left to be recouped
+ * @param coin_priv coin key of the coin to be recouped
+ * @param coin_sig resulting signature
+ */
+void
+TALER_wallet_recoup_sign (
+ const struct TALER_DenominationHash *h_denom_pub,
+ const union TALER_DenominationBlindingKeyP *coin_bks,
+ const struct TALER_Amount *requested_amount,
+ const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+ struct TALER_CoinSpendSignatureP *coin_sig);
+
+
/* ********************* offline signing ************************** */
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index 87a004e31..643aa80de 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -1497,11 +1497,6 @@ struct TALER_RecoupRequestPS
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
- * Public key of the coin to be refunded.
- */
- struct TALER_CoinSpendPublicKeyP coin_pub;
-
- /**
* Hash of the (revoked) denomination public key of the coin.
*/
struct TALER_DenominationHash h_denom_pub;
@@ -1510,6 +1505,12 @@ struct TALER_RecoupRequestPS
* Blinding factor that was used to withdraw the coin.
*/
union TALER_DenominationBlindingKeyP coin_blind;
+
+ /**
+ * How much of the coin's value will be recouped?
+ */
+ struct TALER_AmountNBO recoup_amount;
+
};
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index b14714ac6..93b992e65 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -688,17 +688,16 @@ TALER_EXCHANGE_verify_coin_history (
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
.coin_pub = *coin_pub
};
- struct TALER_RecoupRequestPS rr = {
- .purpose.size = htonl (sizeof (pc)),
- .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
- .coin_pub = *coin_pub
- };
+ union TALER_DenominationBlindingKeyP coin_bks;
+ struct TALER_Amount recoup_amount;
struct TALER_ExchangePublicKeyP exchange_pub;
struct TALER_ExchangeSignatureP exchange_sig;
struct TALER_CoinSpendSignatureP coin_sig;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any_nbo ("amount",
&pc.recoup_amount),
+ TALER_JSON_spec_amount_any ("amount",
+ &recoup_amount),
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
&exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
@@ -708,9 +707,9 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_JSON_spec_fixed_auto ("coin_sig",
&coin_sig),
GNUNET_JSON_spec_fixed_auto ("coin_blind",
- &rr.coin_blind),
+ &coin_bks),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
- &rr.h_denom_pub),
+ h_denom_pub),
GNUNET_JSON_spec_timestamp_nbo ("timestamp",
&pc.timestamp),
GNUNET_JSON_spec_end ()
@@ -736,15 +735,15 @@ TALER_EXCHANGE_verify_coin_history (
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
- &rr,
- &coin_sig.eddsa_signature,
- &coin_pub->eddsa_pub))
+ TALER_wallet_recoup_verify (h_denom_pub,
+ &coin_bks,
+ &recoup_amount,
+ coin_pub,
+ &coin_sig))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- *h_denom_pub = rr.h_denom_pub;
add = GNUNET_YES;
}
else if (0 == strcasecmp (type,
@@ -758,17 +757,16 @@ TALER_EXCHANGE_verify_coin_history (
TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
.coin_pub = *coin_pub
};
- struct TALER_RecoupRequestPS rr = {
- .purpose.size = htonl (sizeof (pc)),
- .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
- .coin_pub = *coin_pub
- };
+ union TALER_DenominationBlindingKeyP coin_bks;
+ struct TALER_Amount recoup_amount;
struct TALER_ExchangePublicKeyP exchange_pub;
struct TALER_ExchangeSignatureP exchange_sig;
struct TALER_CoinSpendSignatureP coin_sig;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any_nbo ("amount",
&pc.recoup_amount),
+ TALER_JSON_spec_amount_any ("amount",
+ &recoup_amount),
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
&exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
@@ -778,9 +776,9 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_JSON_spec_fixed_auto ("old_coin_pub",
&pc.old_coin_pub),
GNUNET_JSON_spec_fixed_auto ("coin_blind",
- &rr.coin_blind),
+ &coin_bks),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
- &rr.h_denom_pub),
+ h_denom_pub),
GNUNET_JSON_spec_timestamp_nbo ("timestamp",
&pc.timestamp),
GNUNET_JSON_spec_end ()
@@ -807,15 +805,15 @@ TALER_EXCHANGE_verify_coin_history (
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
- &rr,
- &coin_sig.eddsa_signature,
- &coin_pub->eddsa_pub))
+ TALER_wallet_recoup_verify (h_denom_pub,
+ &coin_bks,
+ &recoup_amount,
+ coin_pub,
+ &coin_sig))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- *h_denom_pub = rr.h_denom_pub;
add = GNUNET_YES;
}
else if (0 == strcasecmp (type,
diff --git a/src/lib/exchange_api_recoup.c b/src/lib/exchange_api_recoup.c
index 92b59f4b0..05012926f 100644
--- a/src/lib/exchange_api_recoup.c
+++ b/src/lib/exchange_api_recoup.c
@@ -95,7 +95,7 @@ struct TALER_EXCHANGE_RecoupHandle
* @return #GNUNET_OK if the signature is valid and we called the callback;
* #GNUNET_SYSERR if not (callback must still be called)
*/
-static int
+static enum GNUNET_GenericReturnValue
process_recoup_response (const struct TALER_EXCHANGE_RecoupHandle *ph,
const json_t *json)
{
@@ -312,8 +312,8 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
{
struct TALER_EXCHANGE_RecoupHandle *ph;
struct GNUNET_CURL_Context *ctx;
- struct TALER_RecoupRequestPS pr;
struct TALER_CoinSpendSignatureP coin_sig;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_DenominationHash h_denom_pub;
json_t *recoup_obj;
CURL *eh;
@@ -321,17 +321,15 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
- pr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP);
- pr.purpose.size = htonl (sizeof (struct TALER_RecoupRequestPS));
GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
- &pr.coin_pub.eddsa_pub);
+ &coin_pub.eddsa_pub);
TALER_denom_pub_hash (&pk->key,
&h_denom_pub);
- pr.h_denom_pub = pk->h_key;
- pr.coin_blind = ps->blinding_key;
- GNUNET_CRYPTO_eddsa_sign (&ps->coin_priv.eddsa_priv,
- &pr,
- &coin_sig.eddsa_signature);
+ TALER_wallet_recoup_sign (&h_denom_pub,
+ &ps->blinding_key,
+ amount,
+ &ps->coin_priv,
+ &coin_sig);
recoup_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
&h_denom_pub),
@@ -349,11 +347,11 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
char *end;
- end = GNUNET_STRINGS_data_to_string (&pr.coin_pub,
- sizeof (struct
- TALER_CoinSpendPublicKeyP),
- pub_str,
- sizeof (pub_str));
+ end = GNUNET_STRINGS_data_to_string (
+ &coin_pub,
+ sizeof (struct TALER_CoinSpendPublicKeyP),
+ pub_str,
+ sizeof (pub_str));
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
@@ -362,7 +360,7 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
}
ph = GNUNET_new (struct TALER_EXCHANGE_RecoupHandle);
- ph->coin_pub = pr.coin_pub;
+ ph->coin_pub = coin_pub;
ph->exchange = exchange;
ph->pk = *pk;
memset (&ph->pk.key,
diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c
index 3e1df3841..6dced3e37 100644
--- a/src/testing/test_exchange_api.c
+++ b/src/testing/test_exchange_api.c
@@ -855,7 +855,7 @@ run (void *cls,
MHD_HTTP_OK,
"recoup-withdraw-coin-2a",
NULL,
- NULL),
+ "EUR:0.5"),
TALER_TESTING_cmd_deposit ("recoup-deposit-revoked",
"recoup-withdraw-coin-2b",
0,
diff --git a/src/testing/test_exchange_api_revocation.c b/src/testing/test_exchange_api_revocation.c
index 9b66e20be..1a334a71b 100644
--- a/src/testing/test_exchange_api_revocation.c
+++ b/src/testing/test_exchange_api_revocation.c
@@ -139,7 +139,7 @@ run (void *cls,
MHD_HTTP_GONE,
"refresh-reveal-1#0",
"refresh-melt-1",
- NULL),
+ "EUR:0.1"),
/* Make refreshed coin invalid */
TALER_TESTING_cmd_revoke ("revoke-2-EUR:5",
MHD_HTTP_OK,
@@ -155,44 +155,44 @@ run (void *cls,
MHD_HTTP_CONFLICT,
"withdraw-revocation-coin-2",
NULL,
- NULL),
+ "EUR:0.1"),
/* Refund coin to original coin */
TALER_TESTING_cmd_recoup ("recoup-1a",
MHD_HTTP_OK,
"refresh-reveal-1#0",
"refresh-melt-1",
- NULL),
+ "EUR:1"),
TALER_TESTING_cmd_recoup ("recoup-1b",
MHD_HTTP_OK,
"refresh-reveal-1#1",
"refresh-melt-1",
- NULL),
+ "EUR:1"),
TALER_TESTING_cmd_recoup ("recoup-1c",
MHD_HTTP_OK,
"refresh-reveal-1#2",
"refresh-melt-1",
- NULL),
+ "EUR:1"),
/* Repeat recoup to test idempotency */
TALER_TESTING_cmd_recoup ("recoup-1c",
MHD_HTTP_OK,
"refresh-reveal-1#2",
"refresh-melt-1",
- NULL),
+ "EUR:1"),
TALER_TESTING_cmd_recoup ("recoup-1c",
MHD_HTTP_OK,
"refresh-reveal-1#2",
"refresh-melt-1",
- NULL),
+ "EUR:1"),
TALER_TESTING_cmd_recoup ("recoup-1c",
MHD_HTTP_OK,
"refresh-reveal-1#2",
"refresh-melt-1",
- NULL),
+ "EUR:1"),
TALER_TESTING_cmd_recoup ("recoup-1c",
MHD_HTTP_OK,
"refresh-reveal-1#2",
"refresh-melt-1",
- NULL),
+ "EUR:1"),
/* Now we have EUR:3.83 EUR back after 3x EUR:1 in recoups */
/* Melt original coin AGAIN, but only create one 0.1 EUR coin;
This costs EUR:0.03 in refresh and EUR:01 in withdraw fees,
@@ -223,7 +223,7 @@ run (void *cls,
MHD_HTTP_OK,
"refresh-reveal-2",
"refresh-melt-2",
- NULL),
+ "EUR:0.1"),
/* Due to recoup, original coin is now at EUR:3.79 */
/* Refund original (now zombie) coin to reserve */
TALER_TESTING_cmd_recoup ("recoup-3",
diff --git a/src/util/wallet_signatures.c b/src/util/wallet_signatures.c
index b895de14b..81ce9cc5f 100644
--- a/src/util/wallet_signatures.c
+++ b/src/util/wallet_signatures.c
@@ -155,4 +155,51 @@ TALER_wallet_link_verify (
}
+enum GNUNET_GenericReturnValue
+TALER_wallet_recoup_verify (
+ const struct TALER_DenominationHash *h_denom_pub,
+ const union TALER_DenominationBlindingKeyP *coin_bks,
+ const struct TALER_Amount *requested_amount,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_CoinSpendSignatureP *coin_sig)
+{
+ struct TALER_RecoupRequestPS pr = {
+ .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
+ .purpose.size = htonl (sizeof (pr)),
+ .h_denom_pub = *h_denom_pub,
+ .coin_blind = *coin_bks
+ };
+
+ TALER_amount_hton (&pr.recoup_amount,
+ requested_amount);
+ return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
+ &pr,
+ &coin_sig->eddsa_signature,
+ &coin_pub->eddsa_pub);
+}
+
+
+void
+TALER_wallet_recoup_sign (
+ const struct TALER_DenominationHash *h_denom_pub,
+ const union TALER_DenominationBlindingKeyP *coin_bks,
+ const struct TALER_Amount *requested_amount,
+ const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+ struct TALER_CoinSpendSignatureP *coin_sig)
+{
+ struct TALER_RecoupRequestPS pr = {
+ .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
+ .purpose.size = htonl (sizeof (struct TALER_RecoupRequestPS)),
+ .h_denom_pub = *h_denom_pub,
+ .coin_blind = *coin_bks
+ };
+
+ TALER_amount_hton (&pr.recoup_amount,
+ requested_amount);
+ GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
+ &pr,
+ &coin_sig->eddsa_signature);
+}
+
+
/* end of wallet_signatures.c */