diff options
author | Christian Grothoff <christian@grothoff.org> | 2021-12-16 20:18:44 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2021-12-16 20:18:44 +0100 |
commit | 1acc851deb38c52e4212823100eec8a00d5f385a (patch) | |
tree | 67d62b84291996a0def04e9cec16e06025a285ed /src | |
parent | 3b6a0dd5994b824ecbf246bb17e5be7611e89386 (diff) | |
download | exchange-1acc851deb38c52e4212823100eec8a00d5f385a.tar.xz |
-fix recoup ugliness
Diffstat (limited to 'src')
-rw-r--r-- | src/auditor/taler-helper-auditor-coins.c | 53 | ||||
-rw-r--r-- | src/auditor/taler-helper-auditor-reserves.c | 49 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_recoup.c | 45 | ||||
-rw-r--r-- | src/exchangedb/exchange-0001.sql | 5 | ||||
-rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 4 | ||||
-rw-r--r-- | src/exchangedb/test_exchangedb.c | 39 | ||||
-rw-r--r-- | src/include/taler_crypto_lib.h | 57 | ||||
-rw-r--r-- | src/include/taler_signatures.h | 11 | ||||
-rw-r--r-- | src/lib/exchange_api_common.c | 46 | ||||
-rw-r--r-- | src/lib/exchange_api_recoup.c | 30 | ||||
-rw-r--r-- | src/testing/test_exchange_api.c | 2 | ||||
-rw-r--r-- | src/testing/test_exchange_api_revocation.c | 20 | ||||
-rw-r--r-- | src/util/wallet_signatures.c | 47 |
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 */ |