diff options
31 files changed, 427 insertions, 158 deletions
diff --git a/.gitignore b/.gitignore index 1c3cba8fe..9dac85a62 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ src/util/test_amount src/util/test_crypto src/util/test_json src/util/test_wireformats +src/util/taler-arm doc/paper/llncs.cls doc/paper/taler.bbl doc/paper/taler.blg @@ -0,0 +1,2 @@ +Wed May 4 10:19:36 CEST 2016 + Releasing taler-exchange 0.0. -CG diff --git a/configure.ac b/configure.ac index aaf6c204d..939e8f7c0 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ AC_INIT([taler-exchange], [0.0.0], [taler-bug@gnunet.org]) AC_CONFIG_SRCDIR([src/util/util.c]) AC_CONFIG_HEADERS([taler_config.h]) # support for non-recursive builds -AM_INIT_AUTOMAKE([subdir-objects]) +AM_INIT_AUTOMAKE([subdir-objects 1.9 tar-pax]) # pretty build rules AM_SILENT_RULES([yes]) @@ -152,6 +152,35 @@ AS_IF([test $libgnunetcurl != 1], *** ]])]) + +# Check for GNUnet's libgnunetpq. +libgnunetpq=0 +AC_MSG_CHECKING([for libgnunetpq]) +AC_ARG_WITH(gnunet, + [AS_HELP_STRING([--with-gnunet=PFX], [base of GNUnet installation])], + [AC_MSG_RESULT([given as $with_gnunet])], + [AC_MSG_RESULT(not given) + with_gnunet=yes]) +AS_CASE([$with_gnunet], + [yes], [], + [no], [AC_MSG_ERROR([--with-gnunet is required])], + [LDFLAGS="-L$with_gnunet/lib $LDFLAGS" + CPPFLAGS="-I$with_gnunet/include $CPPFLAGS"]) +AC_CHECK_HEADERS([gnunet/platform.h gnunet/gnunet_pq_lib.h], + [AC_CHECK_LIB([gnunetpq], [GNUNET_PQ_result_spec_string], libgnunetpq=1)], + [], [#ifdef HAVE_GNUNET_PLATFORM_H + #include <gnunet/platform.h> + #endif]) +AS_IF([test $libgnunetpq != 1], + [AC_MSG_ERROR([[ +*** +*** You need libgnunetpq to build this program. +*** Make sure you have Postgres installed while +*** building GNUnet (and that your GNUnet version +*** is recent!) +*** ]])]) + + # check for libmicrohttpd microhttpd=0 AC_MSG_CHECKING([for microhttpd]) diff --git a/src/Makefile.am b/src/Makefile.am index ee66bb39b..74956a6ab 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,6 +19,9 @@ pkgcfgdir = $(prefix)/share/taler/config.d/ pkgcfg_DATA = \ taler.conf +EXTRA_DIST = \ + taler.conf + SUBDIRS = include util json $(PQ_DIR) $(BANK_LIB) wire exchangedb exchange exchange-tools if HAVE_LIBCURL SUBDIRS += exchange-lib diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am index f7f5dd738..7e4dd51f4 100644 --- a/src/bank-lib/Makefile.am +++ b/src/bank-lib/Makefile.am @@ -28,7 +28,7 @@ libtalerbank_la_LIBADD = \ $(XLIB) libfakebank_la_SOURCES = \ - fakebank.c + fakebank.c fakebank.h libfakebank_la_LIBADD = \ $(top_builddir)/src/json/libtalerjson.la \ diff --git a/src/bank-lib/bank_api_admin.c b/src/bank-lib/bank_api_admin.c index df3525185..5cd82b093 100644 --- a/src/bank-lib/bank_api_admin.c +++ b/src/bank-lib/bank_api_admin.c @@ -143,7 +143,7 @@ handle_admin_add_incoming_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; diff --git a/src/bank-lib/test_bank_api_with_fakebank.c b/src/bank-lib/test_bank_api_with_fakebank.c index d0f730655..4241f075a 100644 --- a/src/bank-lib/test_bank_api_with_fakebank.c +++ b/src/bank-lib/test_bank_api_with_fakebank.c @@ -53,15 +53,15 @@ run (void *cls) .details.admin_add_incoming.credit_account_no = 3, .details.admin_add_incoming.debit_account_no = 2, .details.admin_add_incoming.amount = "PUDOS:3.21" }, - /* check transactions arrived at fakebank */ - { .oc = TBI_OC_EXPECT_TRANSACTION, + /* check transfers arrived at fakebank */ + { .oc = TBI_OC_EXPECT_TRANSFER, .label = "expect-2", - .details.expect_transaction.cmd_ref = "deposit-2" }, - { .oc = TBI_OC_EXPECT_TRANSACTION, + .details.expect_transfer.cmd_ref = "deposit-2" }, + { .oc = TBI_OC_EXPECT_TRANSFER, .label = "expect-1", - .details.expect_transaction.cmd_ref = "deposit-1" }, - /* check transaction list is now empty */ - { .oc = TBI_OC_EXPECT_TRANSACTIONS_EMPTY, + .details.expect_transfer.cmd_ref = "deposit-1" }, + /* check transfer list is now empty */ + { .oc = TBI_OC_EXPECT_TRANSFERS_EMPTY, .label = "expect-empty" }, { .oc = TBI_OC_END } }; diff --git a/src/bank-lib/test_bank_interpreter.c b/src/bank-lib/test_bank_interpreter.c index 39129a549..840f9942b 100644 --- a/src/bank-lib/test_bank_interpreter.c +++ b/src/bank-lib/test_bank_interpreter.c @@ -235,9 +235,9 @@ interpreter_run (void *cls) return; } return; - case TBI_OC_EXPECT_TRANSACTION: + case TBI_OC_EXPECT_TRANSFER: ref = find_command (is, - cmd->details.expect_transaction.cmd_ref); + cmd->details.expect_transfer.cmd_ref); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (ref->details.admin_add_incoming.amount, &amount)); @@ -264,7 +264,7 @@ interpreter_run (void *cls) is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, is); return; - case TBI_OC_EXPECT_TRANSACTIONS_EMPTY: + case TBI_OC_EXPECT_TRANSFERS_EMPTY: if (GNUNET_OK != FAKEBANK_check_empty (is->fakebank)) { GNUNET_break (0); diff --git a/src/bank-lib/test_bank_interpreter.h b/src/bank-lib/test_bank_interpreter.h index 329b51461..7f56caf4d 100644 --- a/src/bank-lib/test_bank_interpreter.h +++ b/src/bank-lib/test_bank_interpreter.h @@ -45,14 +45,14 @@ enum TBI_OpCode TBI_OC_ADMIN_ADD_INCOMING, /** - * Expect that we have received the specified transaction at fakebank. + * Expect that we have received the specified transfer at fakebank. */ - TBI_OC_EXPECT_TRANSACTION, + TBI_OC_EXPECT_TRANSFER, /** - * Expect that we have exhaustively gone over all transactions at fakebank. + * Expect that we have exhaustively gone over all transfers at fakebank. */ - TBI_OC_EXPECT_TRANSACTIONS_EMPTY + TBI_OC_EXPECT_TRANSFERS_EMPTY }; @@ -118,8 +118,8 @@ struct TBI_Command } admin_add_incoming; /** - * If @e opcode is #TBI_OC_EXPECT_TRANSACTION, this - * specifies which transaction we expected. + * If @e opcode is #TBI_OC_EXPECT_TRANSFER, this + * specifies which transfer we expected. */ struct { @@ -129,7 +129,7 @@ struct TBI_Command */ const char *cmd_ref; - } expect_transaction; + } expect_transfer; } details; diff --git a/src/exchange-lib/Makefile.am b/src/exchange-lib/Makefile.am index 5fd506562..757955579 100644 --- a/src/exchange-lib/Makefile.am +++ b/src/exchange-lib/Makefile.am @@ -21,6 +21,7 @@ libtalerexchange_la_SOURCES = \ exchange_api_deposit_wtid.c \ exchange_api_refresh.c \ exchange_api_refresh_link.c \ + exchange_api_refund.c \ exchange_api_reserve.c \ exchange_api_wire.c \ exchange_api_wire_deposits.c @@ -63,7 +64,7 @@ test_exchange_api_LDADD = \ -ljansson EXTRA_DIST = \ - test_taler_exchange_api_home/.local/share/taler/exchange/offline-keys/master.priv \ - test_taler_exchange_api_home/.config/taler/test.json \ - test_taler_exchange_api_home/.config/taler/sepa.json \ - test_taler_exchange_api.conf + test_exchange_api_home/.local/share/taler/exchange/offline-keys/master.priv \ + test_exchange_api_home/.config/taler/test.json \ + test_exchange_api_home/.config/taler/sepa.json \ + test_exchange_api.conf diff --git a/src/exchange-lib/exchange_api_admin.c b/src/exchange-lib/exchange_api_admin.c index 06a39ffa4..068a11e02 100644 --- a/src/exchange-lib/exchange_api_admin.c +++ b/src/exchange-lib/exchange_api_admin.c @@ -122,7 +122,7 @@ handle_admin_add_incoming_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; diff --git a/src/exchange-lib/exchange_api_deposit.c b/src/exchange-lib/exchange_api_deposit.c index d5dbdcff1..0dc036379 100644 --- a/src/exchange-lib/exchange_api_deposit.c +++ b/src/exchange-lib/exchange_api_deposit.c @@ -246,7 +246,7 @@ handle_deposit_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; @@ -380,20 +380,20 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki, */ struct TALER_EXCHANGE_DepositHandle * TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_Amount *amount, - struct GNUNET_TIME_Absolute wire_deadline, - json_t *wire_details, - const struct GNUNET_HashCode *h_contract, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_DenominationPublicKey *denom_pub, - struct GNUNET_TIME_Absolute timestamp, - uint64_t transaction_id, - const struct TALER_MerchantPublicKeyP *merchant_pub, - struct GNUNET_TIME_Absolute refund_deadline, - const struct TALER_CoinSpendSignatureP *coin_sig, - TALER_EXCHANGE_DepositResultCallback cb, - void *cb_cls) + const struct TALER_Amount *amount, + struct GNUNET_TIME_Absolute wire_deadline, + json_t *wire_details, + const struct GNUNET_HashCode *h_contract, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_DenominationSignature *denom_sig, + const struct TALER_DenominationPublicKey *denom_pub, + struct GNUNET_TIME_Absolute timestamp, + uint64_t transaction_id, + const struct TALER_MerchantPublicKeyP *merchant_pub, + struct GNUNET_TIME_Absolute refund_deadline, + const struct TALER_CoinSpendSignatureP *coin_sig, + TALER_EXCHANGE_DepositResultCallback cb, + void *cb_cls) { const struct TALER_EXCHANGE_Keys *key_state; const struct TALER_EXCHANGE_DenomPublicKey *dki; diff --git a/src/exchange-lib/exchange_api_deposit_wtid.c b/src/exchange-lib/exchange_api_deposit_wtid.c index dc3bf1677..b3c5b3282 100644 --- a/src/exchange-lib/exchange_api_deposit_wtid.c +++ b/src/exchange-lib/exchange_api_deposit_wtid.c @@ -110,7 +110,7 @@ verify_deposit_wtid_signature_ok (const struct TALER_EXCHANGE_DepositWtidHandle key_state = TALER_EXCHANGE_get_keys (dwh->exchange); if (GNUNET_OK != TALER_EXCHANGE_test_signing_key (key_state, - &exchange_pub)) + &exchange_pub)) { GNUNET_break_op (0); return GNUNET_SYSERR; @@ -224,7 +224,7 @@ handle_deposit_wtid_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; @@ -308,7 +308,7 @@ TALER_EXCHANGE_deposit_wtid (struct TALER_EXCHANGE_Handle *exchange, dwh->cb = cb; dwh->cb_cls = cb_cls; dwh->url = MAH_path_to_url (exchange, "/deposit/wtid"); - dwh->depconf.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)); + dwh->depconf.purpose.size = htonl (sizeof (struct TALER_ConfirmWirePS)); dwh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE); dwh->depconf.h_wire = *h_wire; dwh->depconf.h_contract = *h_contract; diff --git a/src/exchange-lib/exchange_api_handle.c b/src/exchange-lib/exchange_api_handle.c index 04508aa34..e5586022f 100644 --- a/src/exchange-lib/exchange_api_handle.c +++ b/src/exchange-lib/exchange_api_handle.c @@ -632,7 +632,7 @@ keys_completed_cb (void *cls, default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); break; } diff --git a/src/exchange-lib/exchange_api_refresh.c b/src/exchange-lib/exchange_api_refresh.c index f112152ca..a63f03ac8 100644 --- a/src/exchange-lib/exchange_api_refresh.c +++ b/src/exchange-lib/exchange_api_refresh.c @@ -1325,7 +1325,7 @@ handle_refresh_melt_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; @@ -1860,7 +1860,7 @@ handle_refresh_reveal_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; diff --git a/src/exchange-lib/exchange_api_refresh_link.c b/src/exchange-lib/exchange_api_refresh_link.c index e809c3f14..cd3f6d72b 100644 --- a/src/exchange-lib/exchange_api_refresh_link.c +++ b/src/exchange-lib/exchange_api_refresh_link.c @@ -364,7 +364,7 @@ handle_refresh_link_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; diff --git a/src/exchange-lib/exchange_api_refund.c b/src/exchange-lib/exchange_api_refund.c index ade070093..a6069f0b4 100644 --- a/src/exchange-lib/exchange_api_refund.c +++ b/src/exchange-lib/exchange_api_refund.c @@ -17,7 +17,6 @@ /** * @file exchange-lib/exchange_api_refund.c * @brief Implementation of the /refund request of the exchange's HTTP API - * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Christian Grothoff */ #include "platform.h" @@ -138,8 +137,8 @@ verify_refund_signature_ok (const struct TALER_EXCHANGE_RefundHandle *rh, */ static void handle_refund_finished (void *cls, - long response_code, - const json_t *json) + long response_code, + const json_t *json) { struct TALER_EXCHANGE_RefundHandle *rh = cls; @@ -178,7 +177,7 @@ handle_refund_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; @@ -205,7 +204,7 @@ handle_refund_finished (void *cls, * * @param exchange the exchange handle; the exchange must be ready to operate * @param amount the amount to be refunded; must be larger than the refund fee - * (as that fee is still being subtracted), and smaller than the amount + * (as that fee is still being subtracted), and smaller than the amount * (with deposit fee) of the original deposit contribution of this coin * @param refund_fee fee applicable to this coin for the refund * @param h_contract hash of the contact of the merchant with the customer that is being refunded @@ -226,6 +225,7 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, const struct TALER_Amount *amount, const struct TALER_Amount *refund_fee, const struct GNUNET_HashCode *h_contract, + uint64_t transaction_id, const struct TALER_CoinSpendPublicKeyP *coin_pub, uint64_t rtransaction_id, const struct TALER_MerchantPrivateKeyP *merchant_priv, @@ -234,8 +234,8 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, { struct TALER_EXCHANGE_RefundHandle *rh; struct GNUNET_CURL_Context *ctx; + struct TALER_RefundRequestPS rr; struct TALER_MerchantSignatureP merchant_sig; - struct TALER_MerchantPublicKeyP merchant_pub; json_t *refund_obj; CURL *eh; @@ -245,8 +245,22 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, GNUNET_break (0); return NULL; } - /* FIXME: create signature! */ - + rr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND); + rr.purpose.size = htonl (sizeof (struct TALER_RefundRequestPS)); + rr.h_contract = *h_contract; + rr.transaction_id = GNUNET_htonll (transaction_id); + rr.coin_pub = *coin_pub; + GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, + &rr.merchant.eddsa_pub); + rr.rtransaction_id = GNUNET_htonll (rtransaction_id); + TALER_amount_hton (&rr.refund_amount, + amount); + TALER_amount_hton (&rr.refund_fee, + refund_fee); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv, + &rr.purpose, + &merchant_sig.eddsa_sig)); refund_obj = json_pack ("{s:o, s:o," /* amount/fee */ " s:o, s:o," /* H_contract, coin_pub */ " s:I, s:I," /* transaction id, rtransaction id */ @@ -259,8 +273,8 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, sizeof (*coin_pub)), "transaction_id", (json_int_t) transaction_id, "rtransaction_id", (json_int_t) rtransaction_id, - "merchant_pub", GNUNET_JSON_from_data (&merchant_pub, - sizeof (merchant_pub)), + "merchant_pub", GNUNET_JSON_from_data (&rr.merchant, + sizeof (struct TALER_MerchantPublicKeyP)), "merchant_sig", GNUNET_JSON_from_data (&merchant_sig, sizeof (merchant_sig)) ); @@ -274,13 +288,13 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, rh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND); rh->depconf.h_contract = *h_contract; rh->depconf.transaction_id = GNUNET_htonll (transaction_id); + rh->depconf.coin_pub = *coin_pub; + rh->depconf.merchant = rr.merchant; rh->depconf.rtransaction_id = GNUNET_htonll (rtransaction_id); TALER_amount_hton (&rh->depconf.refund_amount, amount); TALER_amount_hton (&rh->depconf.refund_fee, refund_fee); - rh->depconf.coin_pub = *coin_pub; - rh->depconf.merchant = *merchant_pub; eh = curl_easy_init (); GNUNET_assert (NULL != (rh->json_enc = diff --git a/src/exchange-lib/exchange_api_reserve.c b/src/exchange-lib/exchange_api_reserve.c index d3e55ed93..056d2f085 100644 --- a/src/exchange-lib/exchange_api_reserve.c +++ b/src/exchange-lib/exchange_api_reserve.c @@ -363,7 +363,7 @@ handle_reserve_status_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; @@ -738,7 +738,7 @@ handle_reserve_withdraw_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; diff --git a/src/exchange-lib/exchange_api_wire.c b/src/exchange-lib/exchange_api_wire.c index 453da14d2..7515806a7 100644 --- a/src/exchange-lib/exchange_api_wire.c +++ b/src/exchange-lib/exchange_api_wire.c @@ -203,7 +203,7 @@ handle_wire_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; diff --git a/src/exchange-lib/exchange_api_wire_deposits.c b/src/exchange-lib/exchange_api_wire_deposits.c index bcb29e872..0601f9b4a 100644 --- a/src/exchange-lib/exchange_api_wire_deposits.c +++ b/src/exchange-lib/exchange_api_wire_deposits.c @@ -96,12 +96,12 @@ handle_wire_deposits_finished (void *cls, struct TALER_ExchangePublicKeyP exchange_pub; struct TALER_ExchangeSignatureP exchange_sig; struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_amount ("total", &total_amount), + GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub), GNUNET_JSON_spec_fixed_auto ("H_wire", &h_wire), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub), + GNUNET_JSON_spec_json ("deposits", &details_j), GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig), - GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub), - TALER_JSON_spec_amount ("total_amount", &total_amount), - GNUNET_JSON_spec_json ("details", &details_j), + GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub), GNUNET_JSON_spec_end() }; @@ -129,10 +129,10 @@ handle_wire_deposits_finished (void *cls, struct json_t *detail_j = json_array_get (details_j, i); struct GNUNET_JSON_Specification spec_detail[] = { GNUNET_JSON_spec_fixed_auto ("H_contract", &detail->h_contract), - TALER_JSON_spec_amount ("deposit_value", &detail->coin_value), - TALER_JSON_spec_amount ("deposit_fee", &detail->coin_fee), GNUNET_JSON_spec_uint64 ("transaction_id", &detail->transaction_id), GNUNET_JSON_spec_fixed_auto ("coin_pub", &detail->coin_pub), + TALER_JSON_spec_amount ("deposit_value", &detail->coin_value), + TALER_JSON_spec_amount ("deposit_fee", &detail->coin_fee), GNUNET_JSON_spec_end() }; @@ -217,7 +217,7 @@ handle_wire_deposits_finished (void *cls, /* unexpected response code */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected response code %u\n", - response_code); + (unsigned int) response_code); GNUNET_break (0); response_code = 0; break; diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c index b20f77067..49c124c80 100644 --- a/src/exchange-lib/test_exchange_api.c +++ b/src/exchange-lib/test_exchange_api.c @@ -139,12 +139,12 @@ enum OpCode /** * Check that the fakebank has received a certain transaction. */ - OC_CHECK_BANK_DEPOSIT, + OC_CHECK_BANK_TRANSFER, /** * Check that the fakebank has not received any other transactions. */ - OC_CHECK_BANK_DEPOSITS_EMPTY + OC_CHECK_BANK_TRANSFERS_EMPTY }; @@ -514,8 +514,13 @@ struct Command struct TALER_EXCHANGE_WireDepositsHandle *wdh; /** - * Reference to a /deposit/wtid command. If set, we use the - * WTID from that command. + * Reference to a command providing a WTID. If set, we use the + * WTID from that command. The command can be either an + * #OC_DEPOSIT_WTID or an #OC_CHECK_BANK_TRANSFER. In the + * case of the bank transfer, we check that the total amount + * claimed by the exchange matches the total amount transferred + * by the bank. In the case of a /deposit/wtid, we check + * that the wire details match. */ const char *wtid_ref; @@ -524,6 +529,13 @@ struct Command */ struct TALER_WireTransferIdentifierRawP wtid; + /** + * What is the expected total amount? Only used if + * @e expected_response_code was #MHD_HTTP_OK. + */ + const char *total_amount_expected; + + /* TODO: may want to add list of deposits we expected to see aggregated here in the future. */ @@ -545,10 +557,9 @@ struct Command const char *deposit_ref; /** - * What is the expected total amount? Only used if - * @e expected_response_code was #MHD_HTTP_OK. + * Which #OC_CHECK_BANK_TRANSFER wtid should this match? NULL for none. */ - struct TALER_Amount total_amount_expected; + const char *bank_transfer_ref; /** * Wire transfer identifier, set if #MHD_HTTP_OK was the response code. @@ -588,7 +599,7 @@ struct Command */ struct TALER_WireTransferIdentifierRawP wtid; - } check_bank_deposit; + } check_bank_transfer; } details; @@ -625,6 +636,18 @@ struct InterpreterState /** + * Pipe used to communicate child death via signal. + */ +static struct GNUNET_DISK_PipeHandle *sigpipe; + +/** + * ID of task called whenever we get a SIGCHILD. + */ +static struct GNUNET_SCHEDULER_Task *child_death_task; + + + +/** * The testcase failed, return with an error code. * * @param is interpreter state to clean up @@ -1185,6 +1208,30 @@ link_cb (void *cls, /** + * Task triggered whenever we receive a SIGCHLD (child + * process died). + * + * @param cls closure, NULL if we need to self-restart + */ +static void +maint_child_death (void *cls) +{ + struct InterpreterState *is = cls; + struct Command *cmd = &is->commands[is->ip]; + const struct GNUNET_DISK_FileHandle *pr; + char c[16]; + + child_death_task = NULL; + pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); + GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); + GNUNET_OS_process_wait (cmd->details.run_aggregator.aggregator_proc); + GNUNET_OS_process_destroy (cmd->details.run_aggregator.aggregator_proc); + cmd->details.run_aggregator.aggregator_proc = NULL; + next_command (is); +} + + +/** * Find denomination key matching the given amount. * * @param keys array of keys to search @@ -1223,9 +1270,9 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Have denomination key for `%s', but with wrong expiration range %llu vs [%llu,%llu)\n", str, - now.abs_value_us, - pk->valid_from.abs_value_us, - pk->withdraw_valid_until.abs_value_us); + (unsigned long long) now.abs_value_us, + (unsigned long long) pk->valid_from.abs_value_us, + (unsigned long long) pk->withdraw_valid_until.abs_value_us); GNUNET_free (str); return NULL; } @@ -1321,6 +1368,7 @@ wire_deposits_cb (void *cls, struct InterpreterState *is = cls; struct Command *cmd = &is->commands[is->ip]; const struct Command *ref; + struct TALER_Amount expected_amount; cmd->details.wire_deposits.wdh = NULL; if (cmd->expected_response_code != http_status) @@ -1336,42 +1384,82 @@ wire_deposits_cb (void *cls, switch (http_status) { case MHD_HTTP_OK: - ref = find_command (is, - cmd->details.wire_deposits.wtid_ref); - GNUNET_assert (NULL != ref); + if (GNUNET_OK != + TALER_string_to_amount (cmd->details.wire_deposits.total_amount_expected, + &expected_amount)) + { + GNUNET_break (0); + fail (is); + return; + } if (0 != TALER_amount_cmp (total_amount, - &ref->details.deposit_wtid.total_amount_expected)) + &expected_amount)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Total amount missmatch to command %s\n", - http_status, cmd->label); json_dumpf (json, stderr, 0); fail (is); return; } - if (NULL != ref->details.deposit_wtid.deposit_ref) + ref = find_command (is, + cmd->details.wire_deposits.wtid_ref); + GNUNET_assert (NULL != ref); + switch (ref->oc) { - const struct Command *dep; - struct GNUNET_HashCode hw; - - dep = find_command (is, - ref->details.deposit_wtid.deposit_ref); - GNUNET_assert (NULL != dep); - GNUNET_CRYPTO_hash (dep->details.deposit.wire_details, - strlen (dep->details.deposit.wire_details), - &hw); - if (0 != memcmp (&hw, - h_wire, - sizeof (struct GNUNET_HashCode))) + case OC_DEPOSIT_WTID: + if (NULL != ref->details.deposit_wtid.deposit_ref) + { + const struct Command *dep; + struct GNUNET_HashCode hw; + json_t *wire; + + dep = find_command (is, + ref->details.deposit_wtid.deposit_ref); + GNUNET_assert (NULL != dep); + wire = json_loads (dep->details.deposit.wire_details, + JSON_REJECT_DUPLICATES, + NULL); + TALER_JSON_hash (wire, + &hw); + json_decref (wire); + if (0 != memcmp (&hw, + h_wire, + sizeof (struct GNUNET_HashCode))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Wire hash missmatch to command %s\n", + cmd->label); + json_dumpf (json, stderr, 0); + fail (is); + return; + } + } + break; + case OC_CHECK_BANK_TRANSFER: + if (GNUNET_OK != + TALER_string_to_amount (ref->details.check_bank_transfer.amount, + &expected_amount)) + { + GNUNET_break (0); + fail (is); + return; + } + if (0 != TALER_amount_cmp (total_amount, + &expected_amount)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Wire hash missmatch to command %s\n", + "Total amount missmatch to command %s\n", cmd->label); json_dumpf (json, stderr, 0); fail (is); return; } + break; + default: + GNUNET_break (0); + fail (is); + return; } break; default: @@ -1421,6 +1509,22 @@ deposit_wtid_cb (void *cls, { case MHD_HTTP_OK: cmd->details.deposit_wtid.wtid = *wtid; + if (NULL != cmd->details.deposit_wtid.bank_transfer_ref) + { + const struct Command *ref; + + ref = find_command (is, + cmd->details.deposit_wtid.bank_transfer_ref); + GNUNET_assert (NULL != ref); + if (0 != memcmp (wtid, + &ref->details.check_bank_transfer.wtid, + sizeof (struct TALER_WireTransferIdentifierRawP))) + { + GNUNET_break (0); + fail (is); + return; + } + } break; default: break; @@ -1698,7 +1802,7 @@ interpreter_run (void *cls) GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.deposit.merchant_priv.eddsa_priv, &merchant_pub.eddsa_pub); - wire_deadline = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS); + wire_deadline = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_ZERO); timestamp = GNUNET_TIME_absolute_get (); GNUNET_TIME_round_abs (×tamp); { @@ -1919,8 +2023,8 @@ interpreter_run (void *cls) case OC_DEPOSIT_WTID: cmd->details.wire_deposits.wtid = ref->details.deposit_wtid.wtid; break; - case OC_CHECK_BANK_DEPOSIT: - cmd->details.wire_deposits.wtid = ref->details.check_bank_deposit.wtid; + case OC_CHECK_BANK_TRANSFER: + cmd->details.wire_deposits.wtid = ref->details.check_bank_transfer.wtid; break; default: GNUNET_break (0); @@ -1999,6 +2103,8 @@ interpreter_run (void *cls) return; case OC_RUN_AGGREGATOR: { + const struct GNUNET_DISK_FileHandle *pr; + cmd->details.run_aggregator.aggregator_proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, @@ -2014,16 +2120,16 @@ interpreter_run (void *cls) fail (is); return; } - GNUNET_OS_process_wait (cmd->details.run_aggregator.aggregator_proc); - GNUNET_OS_process_destroy (cmd->details.run_aggregator.aggregator_proc); - cmd->details.run_aggregator.aggregator_proc = NULL; - next_command (is); + pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); + child_death_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + pr, + &maint_child_death, is); return; } - case OC_CHECK_BANK_DEPOSIT: + case OC_CHECK_BANK_TRANSFER: { if (GNUNET_OK != - TALER_string_to_amount (cmd->details.check_bank_deposit.amount, + TALER_string_to_amount (cmd->details.check_bank_transfer.amount, &amount)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -2036,9 +2142,9 @@ interpreter_run (void *cls) if (GNUNET_OK != FAKEBANK_check (fakebank, &amount, - cmd->details.check_bank_deposit.account_debit, - cmd->details.check_bank_deposit.account_credit, - &cmd->details.check_bank_deposit.wtid)) + cmd->details.check_bank_transfer.account_debit, + cmd->details.check_bank_transfer.account_credit, + &cmd->details.check_bank_transfer.wtid)) { GNUNET_break (0); fail (is); @@ -2047,7 +2153,7 @@ interpreter_run (void *cls) next_command (is); return; } - case OC_CHECK_BANK_DEPOSITS_EMPTY: + case OC_CHECK_BANK_TRANSFERS_EMPTY: { if (GNUNET_OK != FAKEBANK_check_empty (fakebank)) @@ -2072,6 +2178,24 @@ interpreter_run (void *cls) /** + * Signal handler called for SIGCHLD. Triggers the + * respective handler by writing to the trigger pipe. + */ +static void +sighandler_child_death () +{ + static char c; + int old_errno = errno; /* back-up errno */ + + GNUNET_break (1 == + GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle + (sigpipe, GNUNET_DISK_PIPE_END_WRITE), + &c, sizeof (c))); + errno = old_errno; /* restore errno */ +} + + +/** * Function run when the test terminates (good or bad) with timeout. * * @param cls NULL @@ -2251,9 +2375,9 @@ do_shutdown (void *cls) cmd->details.run_aggregator.aggregator_proc = NULL; } break; - case OC_CHECK_BANK_DEPOSIT: + case OC_CHECK_BANK_TRANSFER: break; - case OC_CHECK_BANK_DEPOSITS_EMPTY: + case OC_CHECK_BANK_TRANSFERS_EMPTY: break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -2526,7 +2650,7 @@ run (void *cls) .details.deposit.amount = "EUR:0.1", .details.deposit.coin_ref = "refresh-reveal-1", .details.deposit.coin_idx = 4, - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_uri\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_uri\":\"http://localhost:8082/\", \"account_number\":43 }", .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }", .details.deposit.transaction_id = 2 }, @@ -2563,12 +2687,59 @@ run (void *cls) .label = "wire-deposit-failing", .expected_response_code = MHD_HTTP_NOT_FOUND }, + /* Run transfers. Note that _actual_ aggregation will NOT + happen here, as each deposit operation is run with a + fresh merchant public key! */ { .oc = OC_RUN_AGGREGATOR, .label = "run-aggregator" }, - { .oc = OC_CHECK_BANK_DEPOSITS_EMPTY, + { .oc = OC_CHECK_BANK_TRANSFER, + .label = "check_bank_transfer-499c", + .details.check_bank_transfer.amount = "EUR:4.99", + .details.check_bank_transfer.account_debit = 2, + .details.check_bank_transfer.account_credit = 42 + }, + { .oc = OC_CHECK_BANK_TRANSFER, + .label = "check_bank_transfer-99c1", + .details.check_bank_transfer.amount = "EUR:0.99", + .details.check_bank_transfer.account_debit = 2, + .details.check_bank_transfer.account_credit = 42 + }, + { .oc = OC_CHECK_BANK_TRANSFER, + .label = "check_bank_transfer-99c2", + .details.check_bank_transfer.amount = "EUR:0.99", + .details.check_bank_transfer.account_debit = 2, + .details.check_bank_transfer.account_credit = 42 + }, + { .oc = OC_CHECK_BANK_TRANSFER, + .label = "check_bank_transfer-9c", + .details.check_bank_transfer.amount = "EUR:0.09", + .details.check_bank_transfer.account_debit = 2, + .details.check_bank_transfer.account_credit = 43 + }, + + { .oc = OC_CHECK_BANK_TRANSFERS_EMPTY, .label = "check_bank_empty" }, + { .oc = OC_DEPOSIT_WTID, + .label = "deposit-wtid-ok", + .expected_response_code = MHD_HTTP_OK, + .details.deposit_wtid.deposit_ref = "deposit-simple", + .details.deposit_wtid.bank_transfer_ref = "check_bank_transfer-499c" }, + + { .oc = OC_WIRE_DEPOSITS, + .label = "wire-deposits-sucess-bank", + .expected_response_code = MHD_HTTP_OK, + .details.wire_deposits.wtid_ref = "check_bank_transfer-99c1", + .details.wire_deposits.total_amount_expected = "EUR:0.99" }, + + { .oc = OC_WIRE_DEPOSITS, + .label = "wire-deposits-sucess-wtid", + .expected_response_code = MHD_HTTP_OK, + .details.wire_deposits.wtid_ref = "deposit-wtid-ok", + .details.wire_deposits.total_amount_expected = "EUR:4.99" }, + + /* TODO: trigger aggregation logic and then check the cases where tracking succeeds! */ @@ -2613,6 +2784,7 @@ main (int argc, { struct GNUNET_OS_Process *proc; struct GNUNET_OS_Process *exchanged; + struct GNUNET_SIGNAL_Context *shc_chld; GNUNET_log_setup ("test-exchange-api", "WARNING", @@ -2646,7 +2818,14 @@ main (int argc, while (0 != system ("wget -q -t 1 -T 1 http://127.0.0.1:8081/keys -o /dev/null -O /dev/null")); fprintf (stderr, "\n"); result = GNUNET_SYSERR; + sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); + GNUNET_assert (NULL != sigpipe); + shc_chld = GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, + &sighandler_child_death); GNUNET_SCHEDULER_run (&run, NULL); + GNUNET_SIGNAL_handler_uninstall (shc_chld); + shc_chld = NULL; + GNUNET_DISK_pipe_close (sigpipe); GNUNET_OS_process_kill (exchanged, SIGTERM); GNUNET_OS_process_wait (exchanged); diff --git a/src/exchange-tools/Makefile.am b/src/exchange-tools/Makefile.am index 631f3af20..a1e4f67a2 100644 --- a/src/exchange-tools/Makefile.am +++ b/src/exchange-tools/Makefile.am @@ -8,7 +8,6 @@ pkgcfg_DATA = \ exchange-signkeys.conf \ coins.conf - if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov @@ -93,4 +92,5 @@ taler_exchange_dbinit_CPPFLAGS = \ EXTRA_DIST = \ - auditor.conf + auditor.conf \ + $(pkgcfg_DATA) diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am index 3dba0bb77..314bf8ba4 100644 --- a/src/exchange/Makefile.am +++ b/src/exchange/Makefile.am @@ -94,4 +94,5 @@ EXTRA_DIST = \ test-taler-exchange-aggregator-postgres.conf \ test_taler_exchange_httpd_home/.local/share/taler/exchange/offline-keys/master.priv \ test_taler_exchange_httpd.conf \ - exchange.conf + exchange.conf \ + $(check_SCRIPTS) diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index aeafd60f6..7d9390abf 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -434,6 +434,7 @@ deposit_cb (void *cls, au->row_id = row_id; au->wire = (json_t *) wire; au->execution_time = GNUNET_TIME_absolute_get (); + (void) GNUNET_TIME_round_abs (&au->execution_time); TALER_JSON_hash (au->wire, &au->h_wire); json_incref (au->wire); diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index f8ff67228..c8a72f499 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -1131,7 +1131,7 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, &sig); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, - "{s:o, s:o, s:o, s:o, s:o, s:o}", + "{s:o, s:o, s:o, s:o, s:o}", "wtid", GNUNET_JSON_from_data (wtid, sizeof (*wtid)), "execution_time", GNUNET_JSON_from_time_abs (exec_time), @@ -1184,14 +1184,14 @@ TMH_RESPONSE_reply_wire_deposit_details (struct MHD_Connection *connection, &dd, sizeof (struct TALER_WireDepositDetailP)); json_array_append (deposits, - json_pack ("{s:o, s:o, s:o, s:I, s:o}", - "deposit_value", TALER_JSON_from_amount (&wdd_pos->deposit_value), - "deposit_fee", TALER_JSON_from_amount (&wdd_pos->deposit_fee), + json_pack ("{s:o, s:I, s:o, s:o, s:o}", "H_contract", GNUNET_JSON_from_data (&wdd_pos->h_contract, sizeof (struct GNUNET_HashCode)), "transaction_id", (json_int_t) wdd_pos->transaction_id, "coin_pub", GNUNET_JSON_from_data (&wdd_pos->coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP)))); + sizeof (struct TALER_CoinSpendPublicKeyP)), + "deposit_value", TALER_JSON_from_amount (&wdd_pos->deposit_value), + "deposit_fee", TALER_JSON_from_amount (&wdd_pos->deposit_fee))); } wdp.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT); wdp.purpose.size = htonl (sizeof (struct TALER_WireDepositDataPS)); @@ -1206,11 +1206,11 @@ TMH_RESPONSE_reply_wire_deposit_details (struct MHD_Connection *connection, &sig); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, - "{s:o, s:o, s:o, s:o}", + "{s:o, s:o, s:o, s:o, s:o, s:o}", "total", TALER_JSON_from_amount (total), "merchant_pub", GNUNET_JSON_from_data (merchant_pub, sizeof (struct TALER_MerchantPublicKeyP)), - "h_wire", GNUNET_JSON_from_data (h_wire, + "H_wire", GNUNET_JSON_from_data (h_wire, sizeof (struct GNUNET_HashCode)), "deposits", deposits, "exchange_sig", GNUNET_JSON_from_data (&sig, diff --git a/src/exchange/taler-exchange-httpd_validation.c b/src/exchange/taler-exchange-httpd_validation.c index 830120a31..ba3543afa 100644 --- a/src/exchange/taler-exchange-httpd_validation.c +++ b/src/exchange/taler-exchange-httpd_validation.c @@ -175,25 +175,6 @@ TMH_json_validate_wireformat (const json_t *wire, /** - * Check if we support the given wire method. - * - * @param type type of wire method to check - * @return #GNUNET_YES if the method is supported - */ -int -TMH_VALIDATION_test_method (const char *type) -{ - struct Plugin *p; - - for (p=wire_head;NULL != p;p = p->next) - if (0 == strcasecmp (type, - p->type)) - return GNUNET_YES; - return GNUNET_NO; -} - - -/** * Obtain JSON of the supported wire methods for a given * account name prefix. * diff --git a/src/exchange/taler-exchange-httpd_validation.h b/src/exchange/taler-exchange-httpd_validation.h index bd04994ef..4ff50d081 100644 --- a/src/exchange/taler-exchange-httpd_validation.h +++ b/src/exchange/taler-exchange-httpd_validation.h @@ -54,15 +54,6 @@ int TMH_json_validate_wireformat (const json_t *wire, int ours); -/** - * Check if we support the given wire method. - * - * @param type type of wire method to check - * @return #GNUNET_YES if the method is supported - */ -int -TMH_VALIDATION_test_method (const char *type); - /** * Obtain JSON of the supported wire methods for a given diff --git a/src/exchangedb/exchangedb_keyio.c b/src/exchangedb/exchangedb_keyio.c index 9f170f645..5f29cb0d8 100644 --- a/src/exchangedb/exchangedb_keyio.c +++ b/src/exchangedb/exchangedb_keyio.c @@ -70,7 +70,7 @@ signkeys_iterate_dir_iter (void *cls, "Invalid signkey file `%s': wrong size (%d, expected %u)\n", filename, (int) nread, - sizeof (struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP)); + (unsigned int) sizeof (struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP)); return GNUNET_OK; } return skc->it (skc->it_cls, diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 794051e26..4fbadb79b 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -504,7 +504,7 @@ typedef void * * @param exchange the exchange handle; the exchange must be ready to operate * @param amount the amount to be refunded; must be larger than the refund fee - * (as that fee is still being subtracted), and smaller than the amount + * (as that fee is still being subtracted), and smaller than the amount * (with deposit fee) of the original deposit contribution of this coin * @param refund_fee fee applicable to this coin for the refund * @param h_contract hash of the contact of the merchant with the customer that is being refunded @@ -525,6 +525,7 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, const struct TALER_Amount *amount, const struct TALER_Amount *refund_fee, const struct GNUNET_HashCode *h_contract, + uint64_t transaction_id, const struct TALER_CoinSpendPublicKeyP *coin_pub, uint64_t rtransaction_id, const struct TALER_MerchantPrivateKeyP *merchant_priv, @@ -534,7 +535,7 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, /** * Cancel a refund permission request. This function cannot be used - * on a request handle if a response is already served for it. If + * on a request handle if a response is already served for it. If * this function is called, the refund may or may not have happened. * However, it is fine to try to refund the coin a second time. * diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index e338916e1..c31cc6b93 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -117,6 +117,11 @@ */ #define TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT 1037 +/** + * Signature where the Exchange confirms a refund request. + */ +#define TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND 1038 + /*********************/ /* Wallet signatures */ @@ -454,6 +459,64 @@ struct TALER_RefundRequestPS /** + * @brief Format used to generate the signature on a request to refund + * a coin into the account of the customer. + */ +struct TALER_RefundConfirmationPS +{ + /** + * Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND. + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Hash over the contract which is being refunded. + */ + struct GNUNET_HashCode h_contract GNUNET_PACKED; + + /** + * Merchant-generated transaction ID of the orginal transaction. + */ + uint64_t transaction_id GNUNET_PACKED; + + /** + * The coin's public key. This is the value that must have been + * signed (blindly) by the Exchange. + */ + 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; + + /** + * Amount to be refunded, including refund fee charged by the + * exchange to the customer. + */ + struct TALER_AmountNBO refund_amount; + + /** + * Refund fee charged by the exchange. This must match the + * Exchange's denomination key's refund fee. If the client puts in + * an invalid refund fee (too high or too low) that does not match + * the Exchange's denomination key, the refund operation is invalid + * and will be rejected by the exchange. The @e amount_with_fee + * minus the @e refund_fee is the amount that will be credited to + * the original coin. + */ + struct TALER_AmountNBO refund_fee; + +}; + + +/** * @brief Message signed by a coin to indicate that the coin should be * melted. */ diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 61a8a766d..c0713df8e 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -14,7 +14,9 @@ pkgcfg_DATA = \ paths.conf EXTRA_DIST = \ - paths.conf + paths.conf \ + taler-config.in \ + taler-arm.in templated_scripts = taler-config taler-arm dist_bin_SCRIPTS = $(templated_scripts) |