diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/auditor/taler-helper-auditor-coins.c | 57 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_refund.c | 36 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_responses.c | 22 | ||||
-rw-r--r-- | src/include/taler_crypto_lib.h | 44 | ||||
-rw-r--r-- | src/include/taler_signatures.h | 6 | ||||
-rw-r--r-- | src/lib/exchange_api_common.c | 29 | ||||
-rw-r--r-- | src/lib/exchange_api_refund.c | 113 | ||||
-rw-r--r-- | src/util/Makefile.am | 1 | ||||
-rw-r--r-- | src/util/merchant_signatures.c | 78 |
9 files changed, 228 insertions, 158 deletions
diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c index 0544edfbc..a295a035a 100644 --- a/src/auditor/taler-helper-auditor-coins.c +++ b/src/auditor/taler-helper-auditor-coins.c @@ -1794,41 +1794,30 @@ refund_cb (void *cls, } /* verify refund signature */ + if (GNUNET_OK != + TALER_merchant_refund_verify (coin_pub, + h_contract_terms, + rtransaction_id, + amount_with_fee, + merchant_pub, + merchant_sig)) { - struct TALER_RefundRequestPS rr = { - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .purpose.size = htonl (sizeof (rr)), - .h_contract_terms = *h_contract_terms, - .coin_pub = *coin_pub, - .merchant = *merchant_pub, - .rtransaction_id = GNUNET_htonll (rtransaction_id), - }; - - TALER_amount_hton (&rr.refund_amount, - amount_with_fee); - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, - &rr, - &merchant_sig->eddsa_sig, - &merchant_pub->eddsa_pub)) - { - TALER_ARL_report (report_bad_sig_losses, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("operation", - "refund"), - GNUNET_JSON_pack_uint64 ("row", - rowid), - TALER_JSON_pack_amount ("loss", - amount_with_fee), - GNUNET_JSON_pack_data_auto ("coin_pub", - coin_pub))); - TALER_ARL_amount_add (&total_bad_sig_loss, - &total_bad_sig_loss, - amount_with_fee); - 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", + "refund"), + GNUNET_JSON_pack_uint64 ("row", + rowid), + TALER_JSON_pack_amount ("loss", + amount_with_fee), + GNUNET_JSON_pack_data_auto ("coin_pub", + coin_pub))); + TALER_ARL_amount_add (&total_bad_sig_loss, + &total_bad_sig_loss, + amount_with_fee); + if (TALER_ARL_do_abort ()) + return GNUNET_SYSERR; + return GNUNET_OK; } TALER_amount_ntoh (&refund_fee, diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c index a3b066280..9cc019a14 100644 --- a/src/exchange/taler-exchange-httpd_refund.c +++ b/src/exchange/taler-exchange-httpd_refund.c @@ -209,31 +209,19 @@ verify_and_execute_refund (struct MHD_Connection *connection, .refund = refund }; - // FIXME: move to libtalerutil! + if (GNUNET_OK != + TALER_merchant_refund_verify (&refund->coin.coin_pub, + &refund->details.h_contract_terms, + refund->details.rtransaction_id, + &refund->details.refund_amount, + &refund->details.merchant_pub, + &refund->details.merchant_sig)) { - struct TALER_RefundRequestPS rr = { - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .purpose.size = htonl (sizeof (rr)), - .h_contract_terms = refund->details.h_contract_terms, - .coin_pub = refund->coin.coin_pub, - .merchant = refund->details.merchant_pub, - .rtransaction_id = GNUNET_htonll (refund->details.rtransaction_id) - }; - - TALER_amount_hton (&rr.refund_amount, - &refund->details.refund_amount); - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, - &rr, - &refund->details.merchant_sig.eddsa_sig, - &refund->details.merchant_pub.eddsa_pub)) - { - TALER_LOG_WARNING ("Invalid signature on refund request\n"); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_FORBIDDEN, - TALER_EC_EXCHANGE_REFUND_MERCHANT_SIGNATURE_INVALID, - NULL); - } + TALER_LOG_WARNING ("Invalid signature on refund request\n"); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_FORBIDDEN, + TALER_EC_EXCHANGE_REFUND_MERCHANT_SIGNATURE_INVALID, + NULL); } /* Fetch the coin's denomination (hash) */ diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 5739e6709..66a3b0af9 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -165,25 +165,15 @@ TEH_RESPONSE_compile_transaction_history ( const struct TALER_EXCHANGEDB_RefundListEntry *refund = pos->details.refund; struct TALER_Amount value; - // FIXME: move to libtalerutil! - struct TALER_RefundRequestPS rr = { - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .purpose.size = htonl (sizeof (rr)), - .h_contract_terms = refund->h_contract_terms, - .coin_pub = *coin_pub, - .merchant = refund->merchant_pub, - .rtransaction_id = GNUNET_htonll (refund->rtransaction_id) - }; - TALER_amount_hton (&rr.refund_amount, - &refund->refund_amount); #if ENABLE_SANITY_CHECKS - /* internal sanity check before we hand out a bogus sig... */ if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, - &rr, - &refund->merchant_sig.eddsa_sig, - &refund->merchant_pub.eddsa_pub)) + TALER_merchant_refund_verify (coin_pub, + &refund->h_contract_terms, + refund->rtransaction_id, + &refund->refund_amount, + &refund->merchant_pub, + &refund->merchant_sig)) { GNUNET_break (0); json_decref (history); diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 03edb4462..db38c0c22 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -1897,6 +1897,50 @@ TALER_wallet_recoup_refresh_sign ( struct TALER_CoinSpendSignatureP *coin_sig); +/* ********************* merchant signing ************************** */ + + +/** + * Create merchant signature approving a refund. + * + * @param coin_pub coin to be refunded + * @param h_contract_terms contract to be refunded + * @param rtransaction_id unique ID for this (partial) refund + * @param amount amount to be refunded + * @param merchant_priv private key to sign with + * @param[out] merchant_sig where to write the signature + */ +void +TALER_merchant_refund_sign ( + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHash *h_contract_terms, + uint64_t rtransaction_id, + const struct TALER_Amount *amount, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + struct TALER_MerchantSignatureP *merchant_sig); + + +/** + * Verify merchant signature approving a refund. + * + * @param coin_pub coin to be refunded + * @param h_contract_terms contract to be refunded + * @param rtransaction_id unique ID for this (partial) refund + * @param amount amount to be refunded + * @param merchant_pub public key of the merchant + * @param merchant_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_merchant_refund_verify ( + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHash *h_contract_terms, + uint64_t rtransaction_id, + const struct TALER_Amount *amount, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantSignatureP *merchant_sig); + + /* ********************* offline signing ************************** */ diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index abd10323e..bcfa863c1 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -631,12 +631,6 @@ struct TALER_RefundRequestPS struct TALER_CoinSpendPublicKeyP coin_pub; /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant; - - /** * Merchant-generated transaction ID for the refund. */ uint64_t rtransaction_id GNUNET_PACKED; diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c index 139b10665..7a719461b 100644 --- a/src/lib/exchange_api_common.c +++ b/src/lib/exchange_api_common.c @@ -598,25 +598,23 @@ TALER_EXCHANGE_verify_coin_history ( else if (0 == strcasecmp (type, "REFUND")) { + struct TALER_PrivateContractHash h_contract_terms; + struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_MerchantSignatureP sig; struct TALER_Amount refund_fee; struct TALER_Amount sig_amount; - struct TALER_RefundRequestPS rr = { - .purpose.size = htonl (sizeof (rr)), - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .coin_pub = *coin_pub - }; + uint64_t rtransaction_id; struct GNUNET_JSON_Specification spec[] = { TALER_JSON_spec_amount_any ("refund_fee", &refund_fee), GNUNET_JSON_spec_fixed_auto ("merchant_sig", &sig), GNUNET_JSON_spec_fixed_auto ("h_contract_terms", - &rr.h_contract_terms), + &h_contract_terms), GNUNET_JSON_spec_fixed_auto ("merchant_pub", - &rr.merchant), + &merchant_pub), GNUNET_JSON_spec_uint64 ("rtransaction_id", - &rr.rtransaction_id), + &rtransaction_id), GNUNET_JSON_spec_end () }; @@ -636,16 +634,13 @@ TALER_EXCHANGE_verify_coin_history ( GNUNET_break_op (0); return GNUNET_SYSERR; } - TALER_amount_hton (&rr.refund_amount, - &sig_amount); - rr.rtransaction_id = GNUNET_htonll (rr.rtransaction_id); - TALER_amount_hton (&rr.refund_amount, - &sig_amount); if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, - &rr, - &sig.eddsa_sig, - &rr.merchant.eddsa_pub)) + TALER_merchant_refund_verify (coin_pub, + &h_contract_terms, + rtransaction_id, + &sig_amount, + &merchant_pub, + &sig)) { GNUNET_break_op (0); return GNUNET_SYSERR; diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c index a3030e6cf..94909470a 100644 --- a/src/lib/exchange_api_refund.c +++ b/src/lib/exchange_api_refund.c @@ -95,8 +95,10 @@ verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, { 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), + GNUNET_JSON_spec_fixed_auto ("exchange_sig", + exchange_sig), + GNUNET_JSON_spec_fixed_auto ("exchange_pub", + exchange_pub), GNUNET_JSON_spec_end () }; @@ -291,22 +293,20 @@ verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh, struct TALER_MerchantSignatureP sig; struct TALER_Amount refund_fee; struct TALER_Amount sig_amount; - struct TALER_RefundRequestPS rr = { - .purpose.size = htonl (sizeof (rr)), - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .coin_pub = rh->depconf.coin_pub - }; + struct TALER_PrivateContractHash h_contract_terms; + uint64_t rtransaction_id; + struct TALER_MerchantPublicKeyP merchant_pub; struct GNUNET_JSON_Specification ispec[] = { TALER_JSON_spec_amount_any ("refund_fee", &refund_fee), GNUNET_JSON_spec_fixed_auto ("merchant_sig", &sig), GNUNET_JSON_spec_fixed_auto ("h_contract_terms", - &rr.h_contract_terms), + &h_contract_terms), GNUNET_JSON_spec_fixed_auto ("merchant_pub", - &rr.merchant), + &merchant_pub), GNUNET_JSON_spec_uint64 ("rtransaction_id", - &rr.rtransaction_id), /* Note: converted to NBO below */ + &rtransaction_id), GNUNET_JSON_spec_end () }; @@ -328,30 +328,29 @@ verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh, GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } - TALER_amount_hton (&rr.refund_amount, - &sig_amount); - rr.rtransaction_id = GNUNET_htonll (rr.rtransaction_id); if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, - &rr, - &sig.eddsa_sig, - &rr.merchant.eddsa_pub)) + TALER_merchant_refund_verify (&rh->depconf.coin_pub, + &h_contract_terms, + rtransaction_id, + &sig_amount, + &merchant_pub, + &sig)) { GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } if ( (0 != GNUNET_memcmp (&rh->depconf.h_contract_terms, - &rr.h_contract_terms)) || + &h_contract_terms)) || (0 != GNUNET_memcmp (&rh->depconf.merchant, - &rr.merchant)) ) + &merchant_pub)) ) { /* refund is about a different merchant/contract */ GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } - if (rr.rtransaction_id == rh->depconf.rtransaction_id) + if (rtransaction_id == rh->depconf.rtransaction_id) { /* Eh, this shows either a dependency failure or idempotency, but must not happen in a conflict reply. Fail! */ @@ -468,15 +467,13 @@ verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, e = json_array_get (h, 0); { struct TALER_Amount amount; + struct TALER_Amount depconf_amount; const char *type; struct TALER_MerchantSignatureP sig; struct TALER_Amount refund_fee; - struct TALER_RefundRequestPS rr = { - .purpose.size = htonl (sizeof (rr)), - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .coin_pub = rh->depconf.coin_pub - }; + struct TALER_PrivateContractHash h_contract_terms; uint64_t rtransaction_id; + struct TALER_MerchantPublicKeyP merchant_pub; struct GNUNET_JSON_Specification ispec[] = { TALER_JSON_spec_amount_any ("amount", &amount), @@ -487,9 +484,9 @@ verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, GNUNET_JSON_spec_fixed_auto ("merchant_sig", &sig), GNUNET_JSON_spec_fixed_auto ("h_contract_terms", - &rr.h_contract_terms), + &h_contract_terms), GNUNET_JSON_spec_fixed_auto ("merchant_pub", - &rr.merchant), + &merchant_pub), GNUNET_JSON_spec_uint64 ("rtransaction_id", &rtransaction_id), GNUNET_JSON_spec_end () @@ -504,26 +501,27 @@ verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } - rr.rtransaction_id = GNUNET_htonll (rtransaction_id); - TALER_amount_hton (&rr.refund_amount, - &amount); if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, - &rr, - &sig.eddsa_sig, - &rh->depconf.merchant.eddsa_pub)) + TALER_merchant_refund_verify (&rh->depconf.coin_pub, + &h_contract_terms, + rtransaction_id, + &amount, + &merchant_pub, + &sig)) { GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } - if ( (rr.rtransaction_id != rh->depconf.rtransaction_id) || + TALER_amount_ntoh (&depconf_amount, + &rh->depconf.refund_amount); + if ( (rtransaction_id != rh->depconf.rtransaction_id) || (0 != GNUNET_memcmp (&rh->depconf.h_contract_terms, - &rr.h_contract_terms)) || + &h_contract_terms)) || (0 != GNUNET_memcmp (&rh->depconf.merchant, - &rr.merchant)) || - (0 == TALER_amount_cmp_nbo (&rh->depconf.refund_amount, - &rr.refund_amount)) ) + &merchant_pub)) || + (0 == TALER_amount_cmp (&depconf_amount, + &amount)) ) { GNUNET_break_op (0); GNUNET_JSON_parse_free (spec); @@ -675,13 +673,7 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, TALER_EXCHANGE_RefundCallback cb, void *cb_cls) { - struct TALER_RefundRequestPS rr = { - .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), - .purpose.size = htonl (sizeof (rr)), - .h_contract_terms = *h_contract_terms, - .rtransaction_id = GNUNET_htonll (rtransaction_id), - .coin_pub = *coin_pub - }; + struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_MerchantSignatureP merchant_sig; struct TALER_EXCHANGE_RefundHandle *rh; struct GNUNET_CURL_Context *ctx; @@ -692,23 +684,22 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, GNUNET_assert (GNUNET_YES == TEAH_handle_is_ready (exchange)); GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, - &rr.merchant.eddsa_pub); - TALER_amount_hton (&rr.refund_amount, - amount); - GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv, - &rr, - &merchant_sig.eddsa_sig); - - + &merchant_pub.eddsa_pub); + TALER_merchant_refund_sign (coin_pub, + h_contract_terms, + rtransaction_id, + amount, + merchant_priv, + &merchant_sig); { char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; char *end; - end = GNUNET_STRINGS_data_to_string (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), @@ -723,7 +714,7 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, GNUNET_JSON_pack_uint64 ("rtransaction_id", rtransaction_id), GNUNET_JSON_pack_data_auto ("merchant_pub", - &rr.merchant), + &merchant_pub), GNUNET_JSON_pack_data_auto ("merchant_sig", &merchant_sig)); rh = GNUNET_new (struct TALER_EXCHANGE_RefundHandle); @@ -742,7 +733,7 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, rh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND); rh->depconf.h_contract_terms = *h_contract_terms; rh->depconf.coin_pub = *coin_pub; - rh->depconf.merchant = rr.merchant; + rh->depconf.merchant = merchant_pub; rh->depconf.rtransaction_id = GNUNET_htonll (rtransaction_id); TALER_amount_hton (&rh->depconf.refund_amount, amount); diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 6c64d77b2..cae1a205e 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -76,6 +76,7 @@ libtalerutil_la_SOURCES = \ getopt.c \ lang.c \ iban.c \ + merchant_signatures.c \ mhd.c \ offline_signatures.c \ payto.c \ diff --git a/src/util/merchant_signatures.c b/src/util/merchant_signatures.c new file mode 100644 index 000000000..ae1769552 --- /dev/null +++ b/src/util/merchant_signatures.c @@ -0,0 +1,78 @@ +/* + This file is part of TALER + Copyright (C) 2020 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file merchant_signatures.c + * @brief Utility functions for Taler merchant signatures + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_util.h" +#include "taler_signatures.h" + + +void +TALER_merchant_refund_sign ( + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHash *h_contract_terms, + uint64_t rtransaction_id, + const struct TALER_Amount *amount, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + struct TALER_MerchantSignatureP *merchant_sig) +{ + struct TALER_RefundRequestPS rr = { + .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), + .purpose.size = htonl (sizeof (rr)), + .h_contract_terms = *h_contract_terms, + .coin_pub = *coin_pub, + .rtransaction_id = GNUNET_htonll (rtransaction_id) + }; + + TALER_amount_hton (&rr.refund_amount, + amount); + GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv, + &rr, + &merchant_sig->eddsa_sig); +} + + +enum GNUNET_GenericReturnValue +TALER_merchant_refund_verify ( + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHash *h_contract_terms, + uint64_t rtransaction_id, + const struct TALER_Amount *amount, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantSignatureP *merchant_sig) +{ + struct TALER_RefundRequestPS rr = { + .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND), + .purpose.size = htonl (sizeof (rr)), + .h_contract_terms = *h_contract_terms, + .coin_pub = *coin_pub, + .rtransaction_id = GNUNET_htonll (rtransaction_id) + }; + + TALER_amount_hton (&rr.refund_amount, + amount); + return + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, + &rr, + &merchant_sig->eddsa_sig, + &merchant_pub->eddsa_pub); +} + + +/* end of merchant_signatures.c */ |