aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/auditor/taler-helper-auditor-coins.c57
-rw-r--r--src/exchange/taler-exchange-httpd_refund.c36
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c22
-rw-r--r--src/include/taler_crypto_lib.h44
-rw-r--r--src/include/taler_signatures.h6
-rw-r--r--src/lib/exchange_api_common.c29
-rw-r--r--src/lib/exchange_api_refund.c113
-rw-r--r--src/util/Makefile.am1
-rw-r--r--src/util/merchant_signatures.c78
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 */