diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-04-02 14:24:45 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-04-02 14:29:44 +0200 |
commit | cb55c1a3af9f56a6da38e5589e72df0b70d355b1 (patch) | |
tree | 5f9a3af7d9073249f77ce56c690844a6cb27c3e7 /src/exchange-lib | |
parent | 7a20062bafed42f937c5388aed09042aad7014c0 (diff) |
Changing configuration structure to enable multiple accounts.
This change enables using multiple wire plugins at the same time.
Also, we now distinguish between the wire plugin (i.e. EBICS or
taler_bank) and the wire method (i.e. SEPA or x-taler-bank) that
the wire plugin is implementing. The "taler-bank" wire method
was renamed from "test" to "x-taler-bank".
This also changes the format of the /wire response of the exchange,
as we now need to return multiple accounts. Note that wire fees
are specified per wire method, not per wire account.
taler-exchange-keyup now automatically signs all of the /wire
responses in the location specified by the configuration.
Account identification in wire plugins was changed to use
payto://-URLs instead of method-specific JSON fields. Signing
and validation of /wire responses was moved from each wire
plugin to a generic validation method in libtalerutil (crypto)
or libtalerjson (for JSON-formatted inputs).
Convenience methods were added to generate JSON for wire accounts
(salting, signing).
Various section and option names were adjusted to streamline the
configuration and make it more consistent overall. Documentation
was updated as well.
Diffstat (limited to 'src/exchange-lib')
21 files changed, 694 insertions, 637 deletions
diff --git a/src/exchange-lib/Makefile.am b/src/exchange-lib/Makefile.am index 5e0833b31..57c935088 100644 --- a/src/exchange-lib/Makefile.am +++ b/src/exchange-lib/Makefile.am @@ -61,6 +61,7 @@ libtalertesting_la_SOURCES = \ testing_api_trait_coin_priv.c \ testing_api_trait_denom_pub.c \ testing_api_trait_denom_sig.c \ + testing_api_trait_json.c \ testing_api_trait_process.c \ testing_api_trait_reserve_priv.c \ testing_api_trait_number.c \ @@ -69,8 +70,8 @@ libtalertesting_la_SOURCES = \ testing_api_trait_key_peer.c \ testing_api_trait_wtid.c \ testing_api_trait_amount.c - libtalertesting_la_LIBADD = \ + $(top_builddir)/src/wire/libtalerwire.la \ $(top_builddir)/src/json/libtalerjson.la \ $(top_builddir)/src/util/libtalerutil.la \ $(top_builddir)/src/bank-lib/libtalerfakebank.la \ diff --git a/src/exchange-lib/exchange_api_deposit.c b/src/exchange-lib/exchange_api_deposit.c index 76e3e4da9..7e499a434 100644 --- a/src/exchange-lib/exchange_api_deposit.c +++ b/src/exchange-lib/exchange_api_deposit.c @@ -416,8 +416,8 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, MAH_handle_is_ready (exchange)); /* initialize h_wire */ if (GNUNET_OK != - TALER_JSON_hash (wire_details, - &h_wire)) + TALER_JSON_wire_signature_hash (wire_details, + &h_wire)) { GNUNET_break (0); return NULL; diff --git a/src/exchange-lib/exchange_api_reserve.c b/src/exchange-lib/exchange_api_reserve.c index 72429d4e8..86a83fdb0 100644 --- a/src/exchange-lib/exchange_api_reserve.c +++ b/src/exchange-lib/exchange_api_reserve.c @@ -139,7 +139,7 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle *exchange, if (0 == strcasecmp (type, "DEPOSIT")) { - json_t *wire_account; + const char *wire_url; void *wire_reference; size_t wire_reference_size; struct GNUNET_TIME_Absolute timestamp; @@ -150,8 +150,8 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle *exchange, &wire_reference_size), GNUNET_JSON_spec_absolute_time ("timestamp", ×tamp), - GNUNET_JSON_spec_json ("sender_account_details", - &wire_account), + GNUNET_JSON_spec_string ("sender_account_url", + &wire_url), GNUNET_JSON_spec_end() }; @@ -173,7 +173,7 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle *exchange, GNUNET_break_op (0); return GNUNET_SYSERR; } - rhistory[off].details.in_details.sender_account_details = wire_account; + rhistory[off].details.in_details.sender_url = GNUNET_strdup (wire_url); rhistory[off].details.in_details.wire_reference = wire_reference; rhistory[off].details.in_details.wire_reference_size = wire_reference_size; rhistory[off].details.in_details.timestamp = timestamp; @@ -361,8 +361,8 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle *exchange, TALER_amount_hton (&rcc.closing_amount, &amount); if (GNUNET_OK != - TALER_JSON_hash (rhistory[off].details.close_details.receiver_account_details, - &rcc.h_wire)) + TALER_JSON_wire_signature_hash (rhistory[off].details.close_details.receiver_account_details, + &rcc.h_wire)) { GNUNET_break (0); return GNUNET_SYSERR; @@ -440,8 +440,7 @@ free_rhistory (struct TALER_EXCHANGE_ReserveHistory *rhistory, { case TALER_EXCHANGE_RTT_DEPOSIT: GNUNET_free_non_null (rhistory[i].details.in_details.wire_reference); - if (NULL != rhistory[i].details.in_details.sender_account_details) - json_decref (rhistory[i].details.in_details.sender_account_details); + GNUNET_free_non_null (rhistory[i].details.in_details.sender_url); break; case TALER_EXCHANGE_RTT_WITHDRAWAL: break; diff --git a/src/exchange-lib/exchange_api_wire.c b/src/exchange-lib/exchange_api_wire.c index f1056fdd2..12789b2bc 100644 --- a/src/exchange-lib/exchange_api_wire.c +++ b/src/exchange-lib/exchange_api_wire.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015, 2016 Inria and GNUnet e.V. + Copyright (C) 2014-2018 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 @@ -27,6 +27,7 @@ #include <gnunet/gnunet_curl_lib.h> #include "taler_exchange_service.h" #include "taler_json_lib.h" +#include "taler_wire_lib.h" #include "taler_signatures.h" #include "taler_wire_plugin.h" #include "exchange_api_handle.h" @@ -63,66 +64,133 @@ struct TALER_EXCHANGE_WireHandle */ void *cb_cls; +}; + + +/** + * List of wire fees by method. + */ +struct FeeMap +{ /** - * Set to the "methods" JSON array returned by the - * /wire request. + * Next entry in list. */ - json_t *methods; + struct FeeMap *next; /** - * Current iteration offset in the @e methods array. + * Wire method this fee structure is for. */ - unsigned int methods_off; + char *method; + /** + * Array of wire fees, also linked list, but allocated + * only once. + */ + struct TALER_EXCHANGE_WireAggregateFees *fee_list; }; /** - * Verify that the signature on the "200 OK" response - * for /wire/METHOD from the exchange is valid. + * Frees @a fm. * - * @param wh wire handle with key material - * @param method method to verify the reply for - * @param json json reply with the signature - * @return #GNUNET_SYSERR if @a json is invalid, - * #GNUNET_NO if the method is unknown, - * #GNUNET_OK if the json is valid + * @param fm memory to release */ -static int -verify_wire_method_signature_ok (const struct TALER_EXCHANGE_WireHandle *wh, - const char *method, - const json_t *json) +static void +free_fees (struct FeeMap *fm) { - const struct TALER_EXCHANGE_Keys *key_state; - struct TALER_WIRE_Plugin *plugin; - char *lib_name; - char *emsg; - enum TALER_ErrorCode ec; - - key_state = TALER_EXCHANGE_get_keys (wh->exchange); - (void) GNUNET_asprintf (&lib_name, - "libtaler_plugin_wire_%s", - method); - plugin = GNUNET_PLUGIN_load (lib_name, - NULL); - if (NULL == plugin) + while (NULL != fm) { - GNUNET_free (lib_name); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Wire transfer method `%s' not supported\n", - method); - return GNUNET_NO; + struct FeeMap *fe = fm->next; + + GNUNET_free (fm->fee_list); + GNUNET_free (fm->method); + GNUNET_free (fm); + fm = fe; + } +} + + +/** + * Parse wire @a fees and return map. + * + * @param fees json AggregateTransferFee to parse + * @return NULL on error + */ +static struct FeeMap * +parse_fees (json_t *fees) +{ + struct FeeMap *fm = NULL; + const char *key; + json_t *fee_array; + + json_object_foreach (fees, key, fee_array) { + struct FeeMap *fe = GNUNET_new (struct FeeMap); + int len; + unsigned int idx; + json_t *fee; + + if (0 == (len = json_array_size (fee_array))) + { + GNUNET_break_op (0); + GNUNET_free (fe); + continue; /* skip */ + } + fe->method = GNUNET_strdup (key); + fe->next = fm; + fe->fee_list = GNUNET_new_array (len, + struct TALER_EXCHANGE_WireAggregateFees); + fm = fe; + json_array_foreach (fee_array, idx, fee) + { + struct TALER_EXCHANGE_WireAggregateFees *wa = &fe->fee_list[idx]; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_fixed_auto ("sig", + &wa->master_sig), + TALER_JSON_spec_amount ("wire_fee", + &wa->wire_fee), + TALER_JSON_spec_amount ("closing_fee", + &wa->closing_fee), + GNUNET_JSON_spec_absolute_time ("start_date", + &wa->start_date), + GNUNET_JSON_spec_absolute_time ("end_date", + &wa->end_date), + GNUNET_JSON_spec_end() + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (fee, + spec, + NULL, + NULL)) + { + GNUNET_break_op (0); + free_fees (fm); + return NULL; + } + if (idx < len) + wa->next = &fe->fee_list[idx + 1]; + } } - plugin->library_name = lib_name; - ec = plugin->wire_validate (plugin->cls, - json, - &key_state->master_pub, - &emsg); - GNUNET_free_non_null (emsg); - GNUNET_PLUGIN_unload (lib_name, - plugin); - GNUNET_free (lib_name); - return (TALER_EC_NONE == ec) ? GNUNET_OK : GNUNET_SYSERR; + return fm; +} + + +/** + * Find fee by @a method. + * + * @param fm map to look in + * @param method key to look for + * @return NULL if fee is not specified in @a fm + */ +static const struct TALER_EXCHANGE_WireAggregateFees * +lookup_fee (const struct FeeMap *fm, + const char *method) +{ + for (;NULL != fm; fm = fm->next) + if (0 == strcasecmp (fm->method, + method)) + return fm->fee_list; + return NULL; } @@ -140,70 +208,131 @@ handle_wire_finished (void *cls, const json_t *json) { struct TALER_EXCHANGE_WireHandle *wh = cls; - json_t *keep = NULL; + enum TALER_ErrorCode ec; wh->job = NULL; + ec = TALER_EC_NONE; switch (response_code) { case 0: break; case MHD_HTTP_OK: { - const struct TALER_EXCHANGE_Keys *keys; - const struct TALER_MasterPublicKeyP *master_pub; - const char *key; - json_t *method; - int ret; - - /* We 'keep' methods that we support and that are well-formed; - we fail (by setting response_code=0) if any method that we do - support fails to verify. */ - keep = json_object (); - json_object_foreach ((json_t *) json, key, method) { - ret = verify_wire_method_signature_ok (wh, - key, - method); - if (GNUNET_SYSERR == ret) - { - /* bogus reply */ - GNUNET_break_op (0); - response_code = 0; - } - /* GNUNET_NO: not understood by us, simply skip! */ - if (GNUNET_OK == ret) - { - /* supported and valid, keep! */ - json_object_set (keep, - key, - method); - } - } - /* check fees */ - keys = TALER_EXCHANGE_get_keys (wh->exchange); - if (NULL == keys) - master_pub = NULL; - else - master_pub = &keys->master_pub; + json_t *accounts; + json_t *fees; + int num_accounts; + struct FeeMap *fm; + const struct TALER_EXCHANGE_Keys *key_state; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_json ("accounts", &accounts), + GNUNET_JSON_spec_json ("fees", &fees), + GNUNET_JSON_spec_end() + }; + if (GNUNET_OK != - TALER_EXCHANGE_wire_get_fees (master_pub, - keep, - NULL, - NULL)) + GNUNET_JSON_parse (json, + spec, + NULL, NULL)) { /* bogus reply */ GNUNET_break_op (0); response_code = 0; + ec = TALER_EC_SERVER_JSON_INVALID; + break; } - if (0 != response_code) + if (0 == (num_accounts = json_array_size (accounts))) { - /* all supported methods were valid, use 'keep' for 'json' */ + /* bogus reply */ + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + response_code = 0; + ec = TALER_EC_SERVER_JSON_INVALID; break; } - /* some supported methods were invalid, release 'keep', preserve - full 'json' for application-level error handling. */ - json_decref (keep); - keep = NULL; - } + if (NULL == (fm = parse_fees (fees))) + { + /* bogus reply */ + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + response_code = 0; + ec = TALER_EC_SERVER_JSON_INVALID; + break; + } + + key_state = TALER_EXCHANGE_get_keys (wh->exchange); + /* parse accounts */ + { + struct TALER_EXCHANGE_WireAccount was[num_accounts]; + + for (unsigned int i=0;i<num_accounts;i++) + { + struct TALER_EXCHANGE_WireAccount *wa = &was[i]; + json_t *account; + struct GNUNET_JSON_Specification spec_account[] = { + GNUNET_JSON_spec_string ("url", &wa->url), + GNUNET_JSON_spec_string ("salt", &wa->salt), + GNUNET_JSON_spec_fixed_auto ("master_sig", &wa->master_sig), + GNUNET_JSON_spec_end() + }; + char *method; + + account = json_array_get (accounts, + i); + if (GNUNET_OK != + TALER_JSON_wire_signature_check (account, + &key_state->master_pub)) + { + /* bogus reply */ + GNUNET_break_op (0); + response_code = 0; + ec = TALER_EC_SERVER_SIGNATURE_INVALID; + break; + } + if (GNUNET_OK != + GNUNET_JSON_parse (account, + spec_account, + NULL, NULL)) + { + /* bogus reply */ + GNUNET_break_op (0); + response_code = 0; + ec = TALER_EC_SERVER_JSON_INVALID; + break; + } + if (NULL == (method = TALER_WIRE_payto_get_method (wa->url))) + { + /* bogus reply */ + GNUNET_break_op (0); + response_code = 0; + ec = TALER_EC_SERVER_JSON_INVALID; + break; + } + if (NULL == (wa->fees = lookup_fee (fm, + method))) + { + /* bogus reply */ + GNUNET_break_op (0); + response_code = 0; + ec = TALER_EC_SERVER_JSON_INVALID; + GNUNET_free (method); + break; + } + GNUNET_free (method); + } /* end 'for all accounts */ + if ( (0 != response_code) && + (NULL != wh->cb) ) + { + wh->cb (wh->cb_cls, + response_code, + TALER_EC_NONE, + num_accounts, + was); + wh->cb = NULL; + } + } /* end of 'parse accounts */ + free_fees (fm); + GNUNET_JSON_parse_free (spec); + } /* end of MHD_HTTP_OK */ break; case MHD_HTTP_BAD_REQUEST: /* This should never happen, either us or the exchange is buggy @@ -226,12 +355,12 @@ handle_wire_finished (void *cls, response_code = 0; break; } - wh->cb (wh->cb_cls, - response_code, - TALER_JSON_get_error_code (json), - (NULL != keep) ? keep : json); - if (NULL != keep) - json_decref (keep); + if (NULL != wh->cb) + wh->cb (wh->cb_cls, + response_code, + (0 == response_code) ? ec : TALER_JSON_get_error_code (json), + 0, + NULL); TALER_EXCHANGE_wire_cancel (wh); } @@ -306,157 +435,9 @@ TALER_EXCHANGE_wire_cancel (struct TALER_EXCHANGE_WireHandle *wh) GNUNET_CURL_job_cancel (wh->job); wh->job = NULL; } - if (NULL != wh->methods) - { - json_decref (wh->methods); - wh->methods = NULL; - } GNUNET_free (wh->url); GNUNET_free (wh); } -/** - * Parse wire @a fee and store the result in @a af. - * - * @param[out] af where to write the result - * @param fee json AggregateTransferFee to parse - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -parse_json_fees (struct TALER_EXCHANGE_WireAggregateFees *af, - json_t *fee) -{ - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("sig", - &af->master_sig), - TALER_JSON_spec_amount ("wire_fee", - &af->wire_fee), - TALER_JSON_spec_amount ("closing_fee", - &af->closing_fee), - GNUNET_JSON_spec_absolute_time ("start_date", - &af->start_date), - GNUNET_JSON_spec_absolute_time ("end_date", - &af->end_date), - GNUNET_JSON_spec_end() - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (fee, - spec, - NULL, - NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Check the #TALER_SIGNATURE_MASTER_WIRE_FEES signature. - * - * @param af record to check - * @param wire_method wire method to check against - * @param master_pub expected signing key - * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure - */ -static int -check_sig (const struct TALER_EXCHANGE_WireAggregateFees *af, - const char *wire_method, - const struct TALER_MasterPublicKeyP *master_pub) -{ - struct TALER_MasterWireFeePS wp; - - wp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_FEES); - wp.purpose.size = htonl (sizeof (wp)); - GNUNET_CRYPTO_hash (wire_method, - strlen (wire_method) + 1, - &wp.h_wire_method); - wp.start_date = GNUNET_TIME_absolute_hton (af->start_date); - wp.end_date = GNUNET_TIME_absolute_hton (af->end_date); - TALER_amount_hton (&wp.wire_fee, - &af->wire_fee); - TALER_amount_hton (&wp.closing_fee, - &af->closing_fee); - return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES, - &wp.purpose, - &af->master_sig.eddsa_signature, - &master_pub->eddsa_pub); -} - - -/** - * Obtain information about wire fees encoded in @a obj - * by wire method. - * - * @param master_pub public key to use to verify signatures, NULL to not verify - * @param obj wire information as encoded in the #TALER_EXCHANGE_WireResultCallback - * @param cb callback to invoke for the fees - * @param cb_cls closure for @a cb - * @return #GNUNET_OK in success, #GNUNET_SYSERR if @a obj is ill-formed - */ -int -TALER_EXCHANGE_wire_get_fees (const struct TALER_MasterPublicKeyP *master_pub, - const json_t *obj, - TALER_EXCHANGE_WireFeeCallback cb, - void *cb_cls) -{ - const char *wire_method; - json_t *value; - - json_object_foreach (((json_t *) obj), wire_method, value) - { - json_t *fees; - size_t num_fees; - - fees = json_object_get (value, "fees"); - if ( (NULL == fees) || - (! json_is_array (fees)) ) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - num_fees = json_array_size (fees); - if (num_fees > 1024) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - { - struct TALER_EXCHANGE_WireAggregateFees af[num_fees + 1]; - - for (size_t i=0;i<num_fees;i++) - { - af[i].next = &af[i+1]; - if (GNUNET_OK != - parse_json_fees (&af[i], - json_array_get (fees, - i))) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ( (NULL != master_pub) && - (GNUNET_OK != - check_sig (&af[i], - wire_method, - master_pub)) ) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - } - af[num_fees - 1].next = NULL; - if (NULL != cb) - cb (cb_cls, - wire_method, - &af[0]); - } - } - return GNUNET_OK; -} - - /* end of exchange_api_wire.c */ diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c index fe3877790..7ca74a227 100644 --- a/src/exchange-lib/test_exchange_api.c +++ b/src/exchange-lib/test_exchange_api.c @@ -36,9 +36,12 @@ #define WIRE_TEST 1 /** - * Is the configuration file is set to include wire format 'sepa'? + * Is the configuration file is set to include wire format 'ebics'? + * Requires that EBICS /history function is implemented, which it + * is currently not. Once it is, set ENABLE_CREDIT to YES in the + * configuration and then set this option to 1. */ -#define WIRE_SEPA 1 +#define WIRE_EBICS 0 /** * Account number of the exchange at the bank. @@ -1539,12 +1542,15 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys, } +#if LEGACY +/* Tests the *old* /wire API, the _modern_ testcase was adapted, + but little point in right now adapting the old testcase */ /** * Function called with information about the wire fees * for each wire method. * * @param cls closure - * @param wire_method name of the wire method (i.e. "sepa") + * @param wire_method name of the wire method (i.e. "ebics") * @param fees fee structure for this method */ static void @@ -1556,9 +1562,9 @@ check_fee_cb (void *cls, struct Command *cmd = &is->commands[is->ip]; struct TALER_Amount expected_amount; - GNUNET_break ( (0 == strcasecmp ("test", + GNUNET_break ( (0 == strcasecmp ("x-taler-bank", wire_method)) || - (0 == strcasecmp ("sepa", + (0 == strcasecmp ("ebics", wire_method)) ); if (GNUNET_OK != TALER_string_to_amount (cmd->details.wire.expected_fee, @@ -1582,6 +1588,7 @@ check_fee_cb (void *cls, fees = fees->next; } } +#endif /** @@ -1592,14 +1599,15 @@ check_fee_cb (void *cls, * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request; * 0 if the exchange's reply is bogus (fails to follow the protocol) * @param ec taler-specific error code, #TALER_EC_NONE on success - * @param obj the received JSON reply, if successful this should be the wire - * format details as provided by /wire. + * @param accounts_len length of the @a accounts array + * @param accounts list of wire accounts of the exchange, NULL on error */ static void wire_cb (void *cls, unsigned int http_status, enum TALER_ErrorCode ec, - const json_t *obj) + unsigned int accounts_len, + const struct TALER_EXCHANGE_WireAccount *accounts) { struct InterpreterState *is = cls; struct Command *cmd = &is->commands[is->ip]; @@ -1611,7 +1619,9 @@ wire_cb (void *cls, "Unexpected response code %u to command %s\n", http_status, cmd->label); +#if LEGACY json_dumpf (obj, stderr, 0); +#endif fail (is); return; } @@ -1619,6 +1629,7 @@ wire_cb (void *cls, { case MHD_HTTP_OK: { +#if LEGACY json_t *method; method = json_object_get (obj, @@ -1646,6 +1657,7 @@ wire_cb (void *cls, fail (is); return; } +#endif } break; default: @@ -1760,8 +1772,8 @@ wire_deposits_cb (void *cls, JSON_REJECT_DUPLICATES, NULL); GNUNET_assert (GNUNET_OK == - TALER_JSON_hash (wire, - &hw)); + TALER_JSON_wire_signature_hash (wire, + &hw)); json_decref (wire); if (0 != memcmp (&hw, h_wire, @@ -2331,13 +2343,15 @@ interpreter_run (void *cls) { struct TALER_DepositRequestPS dr; - memset (&dr, 0, sizeof (dr)); + memset (&dr, + 0, + sizeof (dr)); dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS)); dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT); dr.h_contract_terms = h_contract_terms; GNUNET_assert (GNUNET_OK == - TALER_JSON_hash (wire, - &dr.h_wire)); + TALER_JSON_wire_signature_hash (wire, + &dr.h_wire)); dr.timestamp = GNUNET_TIME_absolute_hton (timestamp); dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline); TALER_amount_hton (&dr.amount_with_fee, @@ -2581,8 +2595,8 @@ interpreter_run (void *cls) NULL); GNUNET_assert (NULL != wire); GNUNET_assert (GNUNET_OK == - TALER_JSON_hash (wire, - &h_wire)); + TALER_JSON_wire_signature_hash (wire, + &h_wire)); json_decref (wire); contract_terms = json_loads (ref->details.deposit.contract_terms, JSON_REJECT_DUPLICATES, @@ -2640,7 +2654,6 @@ interpreter_run (void *cls) "taler-exchange-wirewatch", "taler-exchange-wirewatch", "-c", "test_exchange_api.conf", - "-t", "test", /* use Taler's bank/fakebank */ "-T", /* exit when done */ NULL); if (NULL == cmd->details.run_wirewatch.wirewatch_proc) @@ -3204,15 +3217,15 @@ run (void *cls) .label = "wire-test", /* expecting 'test' method in response */ .expected_response_code = MHD_HTTP_OK, - .details.wire.format = "test", + .details.wire.format = "x-taler-bank", .details.wire.expected_fee = "EUR:0.01" }, #endif -#if WIRE_SEPA +#if WIRE_EBICS { .oc = OC_WIRE, .label = "wire-sepa", - /* expecting 'sepa' method in response */ + /* expecting 'ebics' method in response */ .expected_response_code = MHD_HTTP_OK, - .details.wire.format = "sepa", + .details.wire.format = "ebics", .details.wire.expected_fee = "EUR:0.01" }, #endif /* *************** end of /wire testing ************** */ @@ -3252,7 +3265,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_OK, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }" }, /* Try to overdraw funds ... */ @@ -3268,7 +3281,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_FORBIDDEN, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":43 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/43\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }" }, /* Try to double-spend the 5 EUR coin at the same merchant (but different transaction ID) */ @@ -3277,7 +3290,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_FORBIDDEN, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }" }, /* Try to double-spend the 5 EUR coin at the same merchant (but different proposal) */ @@ -3286,7 +3299,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_FORBIDDEN, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\":[{ \"name\":\"ice cream\", \"value\":2 } ] }" }, /* ***************** /refresh testing ******************** */ @@ -3316,7 +3329,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_OK, .details.deposit.amount = "EUR:1", .details.deposit.coin_ref = "refresh-withdraw-coin-1", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\" : [ { \"name\":\"ice cream\", \"value\":\"EUR:1\" } ] }" }, /* Melt the rest of the coin's value (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */ @@ -3357,7 +3370,7 @@ run (void *cls) .details.deposit.amount = "EUR:1", .details.deposit.coin_ref = "refresh-reveal-1-idempotency", .details.deposit.coin_idx = 0, - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }" }, /* Test successfully spending coins from the refresh operation: @@ -3368,7 +3381,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_url\":\"http://localhost:8082/\", \"account_number\":43 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/43\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }" }, /* Test running a failing melt operation (same operation again must fail) */ @@ -3507,7 +3520,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_OK, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-r1", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\" : [ { \"name\":\"ice cream\", \"value\":\"EUR:5\" } ] }", .details.deposit.refund_deadline = { 60LL * 1000 * 1000 } /* 60 s */, }, @@ -3539,7 +3552,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_OK, .details.deposit.amount = "EUR:4.99", .details.deposit.coin_ref = "withdraw-coin-r1", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\" : [ { \"name\":\"more ice cream\", \"value\":\"EUR:5\" } ] }", }, /* Run transfers. This will do the transfer as refund deadline was 0 */ @@ -3591,9 +3604,9 @@ run (void *cls) .expected_response_code = MHD_HTTP_OK, .details.deposit.amount = "EUR:5", .details.deposit.coin_ref = "withdraw-coin-rb", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", .details.deposit.contract_terms = "{ \"items\" : [ { \"name\":\"ice cream\", \"value\":\"EUR:5\" } ] }", .details.deposit.refund_deadline = { 0 }, + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }" }, { .oc = OC_CHECK_BANK_TRANSFER, .label = "check_bank_transfer-aai-3b", @@ -3695,7 +3708,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_OK, .details.deposit.amount = "EUR:0.5", .details.deposit.coin_ref = "payback-withdraw-coin-2a", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"more ice cream\", \"value\":1 } ] }" }, { .oc = OC_REVOKE, .label = "revoke-2", @@ -3716,7 +3729,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_NOT_FOUND, .details.deposit.amount = "EUR:1", .details.deposit.coin_ref = "payback-withdraw-coin-2b", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"more ice cream\", \"value\":1 } ] }" }, /* Test deposit fails after payback, with proof in payback */ @@ -3727,7 +3740,7 @@ run (void *cls) .expected_response_code = MHD_HTTP_NOT_FOUND, .details.deposit.amount = "EUR:0.5", .details.deposit.coin_ref = "payback-withdraw-coin-2a", - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_url\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"url\":\"payto://x-taler-bank/localhost:8082/42\", \"salt\":\"my salt\" }", .details.deposit.contract_terms = "{ \"items\": [ { \"name\":\"extra ice cream\", \"value\":1 } ] }" }, @@ -3999,6 +4012,7 @@ 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_NO; sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); GNUNET_assert (NULL != sigpipe); diff --git a/src/exchange-lib/test_exchange_api.conf b/src/exchange-lib/test_exchange_api.conf index 7d8761f94..8c8bd7ef5 100644 --- a/src/exchange-lib/test_exchange_api.conf +++ b/src/exchange-lib/test_exchange_api.conf @@ -9,7 +9,6 @@ TALER_TEST_HOME = test_exchange_api_home/ CURRENCY = EUR [exchange] - # HTTP port the exchange listens to PORT = 8081 @@ -23,23 +22,58 @@ DB = postgres # exchange (or the twister) is actually listening. BASE_URL = "http://localhost:8081/" +# Keep it short so the test runs fast. +LOOKAHEAD_SIGN = 12 h + [exchangedb-postgres] -DB_CONN_STR = "postgres:///talercheck" +CONFIG = "postgres:///talercheck" [auditordb-postgres] -DB_CONN_STR = "postgres:///talercheck" +CONFIG = "postgres:///talercheck" + +# Sections starting with "account-" configure the bank accounts +# of the exchange. The "URL" specifies the account in +# payto://-format, while the WIRE_JSON specifies the +# (possibly offline) signed version to be returned in /wire. +# WIRE_JSON is optional, as not all accounts must be +# advertised in /wire. +[account-1] +# What is the URL of our account? +URL = "payto://sepa/CH9300762011623852957" +# This is the response we give out for the /wire request. It provides +# wallets with the bank information for transfers to the exchange. +WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-1.json +# Which wire plugin should we used to access the account? +PLUGIN = ebics -[exchange-wire-sepa] -# Enable 'sepa' to test SEPA-specific routines. -ENABLE = YES +# ENABLE_CREDIT = YES + +[account-2] +# What is the bank account (with the "Taler Bank" demo system)? +URL = "payto://x-taler-bank/localhost:8082/2" # This is the response we give out for the /wire request. It provides # wallets with the bank information for transfers to the exchange. -SEPA_RESPONSE_FILE = ${TALER_CONFIG_HOME}/sepa.json +WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-2.json + +# Which wire plugin should we used to access the account? +PLUGIN = taler_bank + +# Authentication information for basic authentication +TALER_BANK_AUTH_METHOD = "basic" +USERNAME = user +PASSWORD = pass + +ENABLE_DEBIT = YES + +ENABLE_CREDIT = YES + +# Sections starting with "fee-" configure the wire fee for the +# respective wire method. +[fees-sepa] # Fees for the forseeable future... # If you see this after 2017, update to match the next 10 years... -WIRE-FEE-2017 = EUR:0.01 WIRE-FEE-2018 = EUR:0.01 WIRE-FEE-2019 = EUR:0.01 WIRE-FEE-2020 = EUR:0.01 @@ -49,8 +83,8 @@ WIRE-FEE-2023 = EUR:0.01 WIRE-FEE-2024 = EUR:0.01 WIRE-FEE-2025 = EUR:0.01 WIRE-FEE-2026 = EUR:0.01 +WIRE-FEE-2027 = EUR:0.01 -CLOSING-FEE-2017 = EUR:0.01 CLOSING-FEE-2018 = EUR:0.01 CLOSING-FEE-2019 = EUR:0.01 CLOSING-FEE-2020 = EUR:0.01 @@ -60,18 +94,11 @@ CLOSING-FEE-2023 = EUR:0.01 CLOSING-FEE-2024 = EUR:0.01 CLOSING-FEE-2025 = EUR:0.01 CLOSING-FEE-2026 = EUR:0.01 +CLOSING-FEE-2027 = EUR:0.01 -[exchange_keys] -# Keep it short so the test runs fast. -LOOKAHEAD_SIGN = 12 h - -[exchange-wire-test] -# Enable 'test' for testing of the actual coin operations. -ENABLE = YES - +[fees-x-taler-bank] # Fees for the forseeable future... # If you see this after 2017, update to match the next 10 years... -WIRE-FEE-2017 = EUR:0.01 WIRE-FEE-2018 = EUR:0.01 WIRE-FEE-2019 = EUR:0.01 WIRE-FEE-2020 = EUR:0.01 @@ -81,8 +108,8 @@ WIRE-FEE-2023 = EUR:0.01 WIRE-FEE-2024 = EUR:0.01 WIRE-FEE-2025 = EUR:0.01 WIRE-FEE-2026 = EUR:0.01 +WIRE-FEE-2027 = EUR:0.01 -CLOSING-FEE-2017 = EUR:0.01 CLOSING-FEE-2018 = EUR:0.01 CLOSING-FEE-2019 = EUR:0.01 CLOSING-FEE-2020 = EUR:0.01 @@ -92,17 +119,10 @@ CLOSING-FEE-2023 = EUR:0.01 CLOSING-FEE-2024 = EUR:0.01 CLOSING-FEE-2025 = EUR:0.01 CLOSING-FEE-2026 = EUR:0.01 +CLOSING-FEE-2027 = EUR:0.01 -# This is the response we give out for the /wire request. It provides -# wallets with the bank information for transfers to the exchange. -TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json - -# What is the main website of the bank? -BANK_URL = "http://localhost:8082/" -# From which account at the 'bank' should outgoing wire transfers be made? -BANK_ACCOUNT_NUMBER = 2 - - +# Sections starting with "coin_" specify which denominations +# the exchange should support (and their respective fee structure) [coin_eur_ct_1] value = EUR:0.01 duration_overlap = 5 minutes diff --git a/src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json b/src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json new file mode 100644 index 000000000..48093f2aa --- /dev/null +++ b/src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json @@ -0,0 +1,5 @@ +{ + "url": "payto://sepa/CH9300762011623852957", + "salt": "N83T9J9202WCC8TQFDMJDWEGZNBEKA33C1ZM241VNYH88RZNTHPW509Y1M2YF7Y098R8VRESWQ05H03BK1SPAZCWE54KARDCKT5N8AG", + "master_sig": "D4V5GJ998YK7D6N0N56AD0J6MZNFEW6MRZT2CFPVQ5ME3NMQ59AA2007CXYESSFGRN70CNCFM06858QSSENCWTZM8VHEJ93YQ20ZJ1R" +}
\ No newline at end of file diff --git a/src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json b/src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json new file mode 100644 index 000000000..85d80de56 --- /dev/null +++ b/src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json @@ -0,0 +1,5 @@ +{ + "url": "payto://x-taler-bank/localhost:8082/2", + "salt": "TMXB995ZZVKA02AG4074X3C6XX0BFTHY8XK76EF4BSG5XVDF069FEBN4TCKW9GS7NKZH409GKAVHMQPA3T361MC6VM7J268V3GBH42R", + "master_sig": "CK7BGHKYVAT7DMVCN00DQ0761NCTJVESZT69049BCF3SKNJKVHXXEQ5X6FH2HFGHCJ18YA1MGHBD8RRG4W3G4KJWQJDY2CGPGTHDJ2G" +}
\ No newline at end of file diff --git a/src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json b/src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json new file mode 100644 index 000000000..9445f048e --- /dev/null +++ b/src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json @@ -0,0 +1,5 @@ +{ + "url": "payto://x-taler-bank/http://localhost:8082/2", + "salt": "WGRD0W7YKD8ZAN960B0JBRARRY0K5FQ4920Q3DJBTYH4GY7W0XNAX1F04R5B1E0RWH1NFG08TM8K1517WNCXTJM9KMH4913Q5XPK0N8", + "master_sig": "J4N0KP64MGNEQX9HST9TDWK67152MSHHM9CTZH8GSMKD607BXSAF209AQYDKYT6QJP0NQXYXC1JMM9Z405DJHGV75JFMWP4G6WB6A00" +}
\ No newline at end of file diff --git a/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf b/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf index 38b952824..7193bf11e 100644 --- a/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf +++ b/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf @@ -23,20 +23,53 @@ DB = postgres # exchange (or the twister) is actually listening. BASE_URL = "http://localhost:8081/" +# Keep it short so we can prolong later! +LOOKAHEAD_SIGN = 60 s + + [exchangedb-postgres] -DB_CONN_STR = "postgres:///talercheck" +CONFIG = "postgres:///talercheck" [auditordb-postgres] -DB_CONN_STR = "postgres:///talercheck" +CONFIG = "postgres:///talercheck" + + +[account-1] +# This is the response we give out for the /wire request. It provides +# wallets with the bank information for transfers to the exchange. +WIRE_RESPONSE = ${TALER_CONFIG_HOME}/iban.json + +# What is the URL of our bank account? Must match WIRE_RESPONSE above! +URL = payto://sepa/FIXME -[exchange-wire-sepa] -# Enable 'sepa' to test SEPA-specific routines. -ENABLE = YES +# Which plugin implements access for this account? +PLUGIN = "ebics" + +[account-2] # This is the response we give out for the /wire request. It provides # wallets with the bank information for transfers to the exchange. -SEPA_RESPONSE_FILE = ${TALER_CONFIG_HOME}/sepa.json +WIRE_RESPONSE = ${TALER_CONFIG_HOME}/x-taler-bank.json + +# What is the URL of our bank account? Must match WIRE_RESPONSE above! +URL = payto://x-taler-bank/http://localhost:8082/2 + +# Which plugin implements access for this account? +PLUGIN = "taler_bank" + +# Authentication information for basic authentication +TALER_BANK_AUTH_METHOD = "basic" +USERNAME = user +PASSWORD = pass + +ENABLE_DEBIT = YES +ENABLE_CREDIT = YES + + + + +[fees-x-taler-bank] # Fees for the forseeable future... # If you see this after 2017, update to match the next 10 years... WIRE-FEE-2017 = EUR:0.01 @@ -61,14 +94,7 @@ CLOSING-FEE-2024 = EUR:0.01 CLOSING-FEE-2025 = EUR:0.01 CLOSING-FEE-2026 = EUR:0.01 -[exchange_keys] -# Keep it short so we can prolong later! -LOOKAHEAD_SIGN = 60 s - -[exchange-wire-test] -# Enable 'test' for testing of the actual coin operations. -ENABLE = YES - +[fees-sepa] # Fees for the forseeable future... # If you see this after 2017, update to match the next 10 years... WIRE-FEE-2017 = EUR:0.01 @@ -93,16 +119,6 @@ CLOSING-FEE-2024 = EUR:0.01 CLOSING-FEE-2025 = EUR:0.01 CLOSING-FEE-2026 = EUR:0.01 -# This is the response we give out for the /wire request. It provides -# wallets with the bank information for transfers to the exchange. -TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json - -# What is the main website of the bank? -BANK_URL = "http://localhost:8082/" -# From which account at the 'bank' should outgoing wire transfers be made? -BANK_ACCOUNT_NUMBER = 2 - - [coin_eur_ct_1] value = EUR:0.01 duration_overlap = 5 s diff --git a/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf b/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf index 3becf3d68..29290c99c 100644 --- a/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf +++ b/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf @@ -1,5 +1,5 @@ @INLINE@ test_exchange_api_keys_cherry_picking.conf -[exchange_keys] +[exchange] # Lengthen over original value (60 s) LOOKAHEAD_SIGN = 100 s diff --git a/src/exchange-lib/test_exchange_api_new.c b/src/exchange-lib/test_exchange_api_new.c index c3e1ce85e..a33f8d014 100644 --- a/src/exchange-lib/test_exchange_api_new.c +++ b/src/exchange-lib/test_exchange_api_new.c @@ -43,6 +43,14 @@ #define CONFIG_FILE "test_exchange_api.conf" /** + * Is the configuration file is set to include wire format 'ebics'? + * Requires that EBICS /history function is implemented, which it + * is currently not. Once it is, set ENABLE_CREDIT to YES in the + * configuration and then set this option to 1. + */ +#define WIRE_EBICS 0 + +/** * URL of the fakebank. Obtained from CONFIG_FILE's * "exchange-wire-test:BANK_URI" option. */ @@ -145,23 +153,23 @@ run (void *cls, CMD_EXEC_WIREWATCH ("wirewatch-1"), /** - * Check if 'test' wire method is offered by the exchange. + * Check if 'x-taler-bank' wire method is offered by the exchange. */ - TALER_TESTING_cmd_wire ("wire-test-1", + TALER_TESTING_cmd_wire ("wire-taler-bank-1", is->exchange, - "test", + "x-taler-bank", NULL, MHD_HTTP_OK), - +#if WIRE_EBICS /** - * Check if 'sepa' wire method is offered by the exchange. + * Check if 'ebics' wire method is offered by the exchange. */ TALER_TESTING_cmd_wire ("wire-sepa-1", is->exchange, - "sepa", + "ebics", NULL, MHD_HTTP_OK), - +#endif /****** End of "wire" testing ******/ /****** Start of withdraw and spend testing ******/ @@ -188,9 +196,8 @@ run (void *cls, */ TALER_TESTING_cmd_deposit ("deposit-simple", is->exchange, "withdraw-coin-1", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\",\"account_number\":42}", - fakebank_url), + TALER_TESTING_make_wire_details (42, + fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_OK), @@ -208,9 +215,8 @@ run (void *cls, */ TALER_TESTING_cmd_deposit ("deposit-double-1", is->exchange, "withdraw-coin-1", 0, - TALER_TESTING_make_wire_details - ("{\"type\":\"test\",\"account_number\":43}", - fakebank_url), + TALER_TESTING_make_wire_details (43, + fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN), @@ -225,9 +231,8 @@ run (void *cls, */ TALER_TESTING_cmd_deposit ("deposit-double-1", is->exchange, "withdraw-coin-1", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\", \"account_number\":43}", - fakebank_url), + TALER_TESTING_make_wire_details (43, + fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN), @@ -236,12 +241,11 @@ run (void *cls, */ TALER_TESTING_cmd_deposit ("deposit-double-2", is->exchange, "withdraw-coin-1", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\", \"account_number\":43}", - fakebank_url), + TALER_TESTING_make_wire_details (43, + fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN), - + /****** End of withdraw and spend testing ******/ /****** Start of refresh testing ******/ @@ -254,7 +258,7 @@ run (void *cls, */ CMD_TRANSFER_TO_EXCHANGE ("refresh-create-reserve-1", "EUR:5.01"), - + /** * Make previous command effective. */ @@ -277,9 +281,8 @@ run (void *cls, TALER_TESTING_cmd_deposit ("refresh-deposit-partial", is->exchange, "refresh-withdraw-coin-1", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\",\"account_number\":42}", - fakebank_url), + TALER_TESTING_make_wire_details (42, + fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\ \"value\":\"EUR:1\"}]}", GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_OK), @@ -297,7 +300,7 @@ run (void *cls, TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-1", is->exchange, "refresh-melt-1", MHD_HTTP_OK), - + /** * Do it again to check idempotency */ @@ -318,9 +321,8 @@ run (void *cls, TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-1a", is->exchange, "refresh-reveal-1-idempotency", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\",\"account_number\":42}", - fakebank_url), + TALER_TESTING_make_wire_details (42, + fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\ \"value\":3}]}", GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_OK), @@ -331,9 +333,8 @@ run (void *cls, TALER_TESTING_cmd_deposit ("refresh-deposit-refreshed-1b", is->exchange, "refresh-reveal-1", 4, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\",\"account_number\":43}", - fakebank_url), + TALER_TESTING_make_wire_details (43, + fakebank_url), "{\"items\":[{\"name\":\"ice cream\",\ \"value\":3}]}", GNUNET_TIME_UNIT_ZERO, "EUR:0.1", MHD_HTTP_OK), @@ -463,9 +464,8 @@ run (void *cls, */ TALER_TESTING_cmd_deposit ("deposit-refund-1", is->exchange, "withdraw-coin-r1", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\", \"account_number\":42}", - fakebank_url), + TALER_TESTING_make_wire_details (42, + fakebank_url), "{\"items\":[{\"name\":\"ice cream\"," "\"value\":\"EUR:5\"}]}", GNUNET_TIME_UNIT_MINUTES, "EUR:5", MHD_HTTP_OK), @@ -502,9 +502,8 @@ run (void *cls, * 1 ct deposit fee) */ TALER_TESTING_cmd_deposit ("deposit-refund-2", is->exchange, "withdraw-coin-r1", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\", \"account_number\":42}", - fakebank_url), + TALER_TESTING_make_wire_details (42, + fakebank_url), "{\"items\":[{\"name\":\"more ice cream\"," "\"value\":\"EUR:5\"}]}", GNUNET_TIME_UNIT_ZERO, "EUR:4.99", MHD_HTTP_OK), @@ -555,9 +554,8 @@ run (void *cls, TALER_TESTING_cmd_deposit ("deposit-refund-1b", is->exchange, "withdraw-coin-rb", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\", \"account_number\":42}", - fakebank_url), + TALER_TESTING_make_wire_details (42, + fakebank_url), "{\"items\":[{\"name\":\"ice cream\"," "\"value\":\"EUR:5\"}]}", GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_OK), @@ -602,7 +600,7 @@ run (void *cls, is->exchange, "payback-create-reserve-1", "EUR:5", - MHD_HTTP_OK), + MHD_HTTP_OK), TALER_TESTING_cmd_revoke ("revoke-1", MHD_HTTP_OK, "payback-withdraw-coin-1", @@ -648,9 +646,8 @@ run (void *cls, TALER_TESTING_cmd_deposit ("payback-deposit-partial", is->exchange, "payback-withdraw-coin-2a", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\",\"account_number\":42}", - fakebank_url), + TALER_TESTING_make_wire_details (42, + fakebank_url), "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:0.5", MHD_HTTP_OK), @@ -670,9 +667,8 @@ run (void *cls, TALER_TESTING_cmd_deposit ("payback-deposit-revoked", is->exchange, "payback-withdraw-coin-2b", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\",\"account_number\":42}", - fakebank_url), + TALER_TESTING_make_wire_details (42, + fakebank_url), "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_NOT_FOUND), @@ -685,9 +681,8 @@ run (void *cls, TALER_TESTING_cmd_deposit ("payback-deposit-partial-after-payback", is->exchange, "payback-withdraw-coin-2a", 0, - TALER_TESTING_make_wire_details - ("{ \"type\":\"test\",\"account_number\":42}", - fakebank_url), + TALER_TESTING_make_wire_details (42, + fakebank_url), "{\"items\":[{\"name\":\"extra ice cream\",\"value\":1}]}", GNUNET_TIME_UNIT_ZERO, "EUR:0.5", MHD_HTTP_NOT_FOUND), @@ -740,6 +735,7 @@ run (void *cls, fakebank_url); } + int main (int argc, char * const *argv) @@ -753,7 +749,8 @@ main (int argc, if (NULL == (fakebank_url /* Check fakebank port is available and config cares * about bank url. */ - = TALER_TESTING_prepare_fakebank (CONFIG_FILE))) + = TALER_TESTING_prepare_fakebank (CONFIG_FILE, + "account-2"))) return 77; TALER_TESTING_cleanup_files (CONFIG_FILE); /* @helpers. Run keyup, create tables, ... Note: it diff --git a/src/exchange-lib/testing_api_cmd_deposit.c b/src/exchange-lib/testing_api_cmd_deposit.c index 6f66e8ad0..5854bf8ba 100644 --- a/src/exchange-lib/testing_api_cmd_deposit.c +++ b/src/exchange-lib/testing_api_cmd_deposit.c @@ -50,9 +50,9 @@ struct DepositState unsigned int coin_index; /** - * JSON string describing the merchant's "wire details". + * payto://-URL of the merchant's bank account. */ - char *wire_details; + json_t *wire_details; /** * JSON string describing what a proposal is about. @@ -126,6 +126,7 @@ deposit_cb (void *cls, TALER_TESTING_interpreter_next (ds->is); } + /** * Run the command. * @@ -133,7 +134,7 @@ deposit_cb (void *cls, * @param cmd the command to execute, a /wire one. * @param i the interpreter state. */ -void +static void deposit_run (void *cls, const struct TALER_TESTING_Command *cmd, struct TALER_TESTING_Interpreter *is) @@ -153,7 +154,6 @@ deposit_run (void *cls, struct TALER_MerchantPublicKeyP merchant_pub; struct GNUNET_HashCode h_contract_terms; json_t *contract_terms; - json_t *wire; struct TALER_Amount amount; ds->is = is; @@ -166,7 +166,7 @@ deposit_run (void *cls, if (NULL == coin_cmd) { GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); + TALER_TESTING_interpreter_fail (is); return; } @@ -213,21 +213,6 @@ deposit_run (void *cls, TALER_JSON_hash (contract_terms, &h_contract_terms)); json_decref (contract_terms); - - wire = json_loads (ds->wire_details, - JSON_REJECT_DUPLICATES, - NULL); - if (NULL == wire) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse wire details `%s' at %u/%s\n", - ds->wire_details, - is->ip, - this_cmd->label); - TALER_TESTING_interpreter_fail (is); - return; - } - GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, &coin_pub.eddsa_pub); @@ -267,8 +252,9 @@ deposit_run (void *cls, dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT); dr.h_contract_terms = h_contract_terms; - GNUNET_assert (GNUNET_OK == TALER_JSON_hash - (wire, &dr.h_wire)); + GNUNET_assert (GNUNET_OK == + TALER_JSON_wire_signature_hash (ds->wire_details, + &dr.h_wire)); dr.timestamp = GNUNET_TIME_absolute_hton (timestamp); dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline); @@ -286,7 +272,7 @@ deposit_run (void *cls, (ds->exchange, &amount, wire_deadline, - wire, + ds->wire_details, &h_contract_terms, &coin_pub, denom_pub_sig, @@ -301,21 +287,20 @@ deposit_run (void *cls, if (NULL == ds->dh) { GNUNET_break (0); - json_decref (wire); TALER_TESTING_interpreter_fail (is); return; } - json_decref (wire); return; } + /** * Cleanup the state. * * @param cls closure, typically a #struct WireState. * @param cmd the command which is being cleaned up. */ -void +static void deposit_cleanup (void *cls, const struct TALER_TESTING_Command *cmd) { @@ -331,10 +316,11 @@ deposit_cleanup (void *cls, ds->dh = NULL; } - GNUNET_free (ds->wire_details); + json_decref (ds->wire_details); GNUNET_free (ds); } + /** * Extract information from a command that is useful for other * commands. @@ -354,7 +340,7 @@ deposit_traits (void *cls, unsigned int index) { struct DepositState *ds = cls; - const struct TALER_TESTING_Command *coin_cmd; + const struct TALER_TESTING_Command *coin_cmd; /* Will point to coin cmd internals. */ struct TALER_CoinSpendPrivateKeyP *coin_spent_priv; @@ -382,7 +368,7 @@ deposit_traits (void *cls, TALER_TESTING_make_trait_contract_terms (0, ds->contract_terms), TALER_TESTING_make_trait_peer_key (0, &ds->merchant_priv.eddsa_priv), - TALER_TESTING_trait_end () + TALER_TESTING_trait_end () }; return TALER_TESTING_get_trait (traits, @@ -402,8 +388,8 @@ deposit_traits (void *cls, * coins, this parameter selects which one in that array. * This value is currently ignored, as only one-coin * withdrawals are implemented. - * @param wire_details bank details of the merchant performing the - * deposit + * @param wire_details JSON details of the wire account of the merchant performing the + * deposit, reference is captured by this command * @param contract_terms contract terms to be signed over by the * coin * @param refund_deadline refund deadline, zero means 'no refunds' @@ -419,7 +405,7 @@ TALER_TESTING_cmd_deposit struct TALER_EXCHANGE_Handle *exchange, const char *coin_reference, unsigned int coin_index, - char *wire_details, + json_t *wire_details, const char *contract_terms, struct GNUNET_TIME_Relative refund_deadline, const char *amount, @@ -427,7 +413,7 @@ TALER_TESTING_cmd_deposit { struct TALER_TESTING_Command cmd; struct DepositState *ds; - + ds = GNUNET_new (struct DepositState); ds->exchange = exchange; ds->coin_reference = coin_reference; diff --git a/src/exchange-lib/testing_api_cmd_exec_wirewatch.c b/src/exchange-lib/testing_api_cmd_exec_wirewatch.c index 1ff466f56..fd8404bec 100644 --- a/src/exchange-lib/testing_api_cmd_exec_wirewatch.c +++ b/src/exchange-lib/testing_api_cmd_exec_wirewatch.c @@ -68,7 +68,6 @@ wirewatch_run (void *cls, "taler-exchange-wirewatch", "taler-exchange-wirewatch", "-c", ws->config_filename, - "-t", "test", /* use Taler's bank/fakebank */ "-T", /* exit when done */ NULL); if (NULL == ws->wirewatch_proc) diff --git a/src/exchange-lib/testing_api_cmd_payback.c b/src/exchange-lib/testing_api_cmd_payback.c index 3a750e7fc..65665c9c8 100644 --- a/src/exchange-lib/testing_api_cmd_payback.c +++ b/src/exchange-lib/testing_api_cmd_payback.c @@ -31,7 +31,7 @@ struct RevokeState { - /** + /** * Expected HTTP status code. */ unsigned int expected_response_code; @@ -65,7 +65,7 @@ struct RevokeState struct PaybackState { - /** + /** * Expected HTTP status code. */ unsigned int expected_response_code; @@ -154,7 +154,7 @@ payback_cb (void *cls, TALER_TESTING_interpreter_fail (is); return; } - + if (GNUNET_OK != TALER_TESTING_get_trait_reserve_priv (reserve_cmd, 0, &reserve_priv)) { @@ -201,6 +201,7 @@ payback_cb (void *cls, TALER_TESTING_interpreter_next (is); } + /** * Run the command. * @@ -208,7 +209,7 @@ payback_cb (void *cls, * @param cmd the command to execute, a /wire one. * @param is the interpreter state. */ -void +static void payback_run (void *cls, const struct TALER_TESTING_Command *cmd, struct TALER_TESTING_Interpreter *is) @@ -230,7 +231,7 @@ payback_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv @@ -238,7 +239,7 @@ payback_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } if (GNUNET_OK != TALER_TESTING_get_trait_blinding_key @@ -246,7 +247,7 @@ payback_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } planchet.coin_priv = *coin_priv; planchet.blinding_key = *blinding_key; @@ -256,7 +257,7 @@ payback_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } if (GNUNET_OK != TALER_TESTING_get_trait_denom_sig @@ -264,13 +265,13 @@ payback_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Trying to get '%s..' paid back\n", TALER_B2S (&denom_pub->h_key)); - + ps->ph = TALER_EXCHANGE_payback (ps->exchange, denom_pub, coin_sig, @@ -280,13 +281,14 @@ payback_run (void *cls, GNUNET_assert (NULL != ps->ph); } + /** * Cleanup the state. * * @param cls closure, typically a #struct WireState. * @param cmd the command which is being cleaned up. */ -void +static void revoke_cleanup (void *cls, const struct TALER_TESTING_Command *cmd) { @@ -302,17 +304,18 @@ revoke_cleanup (void *cls, rs->revoke_proc = NULL; } - GNUNET_free (rs->dhks); + GNUNET_free_non_null (rs->dhks); GNUNET_free (rs); } + /** * Cleanup the state. * * @param cls closure, typically a #struct WireState. * @param cmd the command which is being cleaned up. */ -void +static void payback_cleanup (void *cls, const struct TALER_TESTING_Command *cmd) { @@ -325,6 +328,7 @@ payback_cleanup (void *cls, GNUNET_free (ps); } + /** * Extract information from a command that is useful for other * commands. @@ -366,7 +370,7 @@ revoke_traits (void *cls, * @param cmd the command to execute, a /wire one. * @param is the interpreter state. */ -void +static void revoke_run (void *cls, const struct TALER_TESTING_Command *cmd, struct TALER_TESTING_Interpreter *is) @@ -384,7 +388,7 @@ revoke_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_denom_pub @@ -395,8 +399,8 @@ revoke_run (void *cls, TALER_B2S (&denom_pub->h_key)); rs->dhks = GNUNET_STRINGS_data_to_string_alloc - (&denom_pub->h_key, sizeof (struct GNUNET_HashCode)); - + (&denom_pub->h_key, sizeof (struct GNUNET_HashCode)); + rs->revoke_proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, @@ -441,7 +445,7 @@ TALER_TESTING_cmd_payback (const char *label, { struct PaybackState *ps; struct TALER_TESTING_Command cmd; - + ps = GNUNET_new (struct PaybackState); ps->expected_response_code = expected_response_code; ps->coin_reference = coin_reference; @@ -455,6 +459,7 @@ TALER_TESTING_cmd_payback (const char *label, return cmd; } + /** * Make a /revoke command. * diff --git a/src/exchange-lib/testing_api_cmd_refund.c b/src/exchange-lib/testing_api_cmd_refund.c index a092ee2d2..35cb20d26 100644 --- a/src/exchange-lib/testing_api_cmd_refund.c +++ b/src/exchange-lib/testing_api_cmd_refund.c @@ -139,7 +139,7 @@ refund_run (void *cls, const struct TALER_TESTING_Command *cmd, struct TALER_TESTING_Interpreter *is) { - struct RefundState *rs = cls; + struct RefundState *rs = cls; struct TALER_CoinSpendPrivateKeyP *coin_priv; struct TALER_CoinSpendPublicKeyP coin; const char *contract_terms; @@ -193,7 +193,7 @@ refund_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } j_contract_terms = json_loads @@ -201,8 +201,9 @@ refund_run (void *cls, /* Very unlikely to fail */ GNUNET_assert (NULL != j_contract_terms); - GNUNET_assert (GNUNET_OK == TALER_JSON_hash - (j_contract_terms, &h_contract_terms)); + GNUNET_assert (GNUNET_OK == + TALER_JSON_hash (j_contract_terms, + &h_contract_terms)); json_decref (j_contract_terms); @@ -222,7 +223,7 @@ refund_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } rs->rh = TALER_EXCHANGE_refund diff --git a/src/exchange-lib/testing_api_cmd_track.c b/src/exchange-lib/testing_api_cmd_track.c index 3f14c5110..638329d69 100644 --- a/src/exchange-lib/testing_api_cmd_track.c +++ b/src/exchange-lib/testing_api_cmd_track.c @@ -183,7 +183,7 @@ deposit_wtid_cb tts->wtid = *wtid; if (NULL != tts->bank_transfer_reference) { - const struct TALER_TESTING_Command *bank_transfer_cmd; + const struct TALER_TESTING_Command *bank_transfer_cmd; char *ws; ws = GNUNET_STRINGS_data_to_string_alloc (wtid, @@ -205,7 +205,7 @@ deposit_wtid_cb { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } if (0 != strcmp (ws, transfer_subject)) @@ -248,14 +248,13 @@ track_transaction_run (void *cls, const struct TALER_TESTING_Command *transaction_cmd; struct TALER_CoinSpendPrivateKeyP *coin_priv; struct TALER_CoinSpendPublicKeyP coin_pub; - const char *wire_details; const char *contract_terms; - json_t *j_wire_details; + const json_t *wire_details; json_t *j_contract_terms; struct GNUNET_HashCode h_wire_details; struct GNUNET_HashCode h_contract_terms; const struct GNUNET_CRYPTO_EddsaPrivateKey *merchant_priv; - + tts->is = is; transaction_cmd = TALER_TESTING_interpreter_lookup_command (tts->is, tts->transaction_reference); @@ -264,7 +263,7 @@ track_transaction_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (tts->is); - return; + return; } if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv @@ -272,7 +271,7 @@ track_transaction_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (tts->is); - return; + return; } GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, @@ -296,31 +295,31 @@ track_transaction_run (void *cls, } /* Parse them.. */ - j_wire_details = json_loads - (wire_details, JSON_REJECT_DUPLICATES, NULL); j_contract_terms = json_loads (contract_terms, JSON_REJECT_DUPLICATES, NULL); - - if ((NULL == j_wire_details) || (NULL == j_contract_terms)) + + if ((NULL == wire_details) || (NULL == j_contract_terms)) { GNUNET_break (0); TALER_TESTING_interpreter_fail (tts->is); - return; + return; } /* Should not fail here, json has been parsed already */ GNUNET_assert - ( (GNUNET_OK == TALER_JSON_hash (j_wire_details, - &h_wire_details)) && - (GNUNET_OK == TALER_JSON_hash (j_contract_terms, - &h_contract_terms)) ); + ( (GNUNET_OK == + TALER_JSON_wire_signature_hash (wire_details, + &h_wire_details)) && + (GNUNET_OK == + TALER_JSON_hash (j_contract_terms, + &h_contract_terms)) ); if (GNUNET_OK != TALER_TESTING_get_trait_peer_key (transaction_cmd, 0, &merchant_priv)) { GNUNET_break (0); TALER_TESTING_interpreter_fail (tts->is); - return; + return; } tts->tth = TALER_EXCHANGE_track_transaction @@ -580,7 +579,7 @@ track_transfer_cb { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } /** @@ -594,8 +593,7 @@ track_transfer_cb if (NULL != tts->wire_details_reference) { const struct TALER_TESTING_Command *wire_details_cmd; - const char *wire_details; - json_t *j_wire_details; + const json_t *wire_details; struct GNUNET_HashCode h_wire_details; if (NULL == (wire_details_cmd @@ -615,13 +613,9 @@ track_transfer_cb return; } - j_wire_details = json_loads - (wire_details, JSON_REJECT_DUPLICATES, NULL); - - GNUNET_assert (NULL != j_wire_details); - - GNUNET_assert (GNUNET_OK == TALER_JSON_hash - (j_wire_details, &h_wire_details)); + GNUNET_assert (GNUNET_OK == + TALER_JSON_wire_signature_hash (wire_details, + &h_wire_details)); if (0 != memcmp (&h_wire_details, h_wire, @@ -647,7 +641,7 @@ track_transfer_cb { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); - return; + return; } if (GNUNET_OK != TALER_TESTING_get_trait_amount @@ -657,7 +651,7 @@ track_transfer_cb TALER_TESTING_interpreter_fail (is); return; } - + GNUNET_assert (GNUNET_OK == TALER_string_to_amount (total_amount_from_reference_str, &total_amount_from_reference)); @@ -699,7 +693,7 @@ track_transfer_run (void *cls, * WTID */ memset (&wtid, 0, sizeof (wtid)); wtid_ptr = &wtid; - + tts->is = is; if (NULL != tts->wtid_reference) { @@ -720,7 +714,7 @@ track_transfer_run (void *cls, { GNUNET_break (0); TALER_TESTING_interpreter_fail (tts->is); - return; + return; } GNUNET_assert (NULL != wtid_ptr); } @@ -756,7 +750,7 @@ TALER_TESTING_cmd_track_transfer_empty { struct TrackTransferState *tts; struct TALER_TESTING_Command cmd; - + tts = GNUNET_new (struct TrackTransferState); tts->wtid_reference = wtid_reference; @@ -769,7 +763,7 @@ TALER_TESTING_cmd_track_transfer_empty cmd.run = &track_transfer_run; cmd.cleanup = &track_transfer_cleanup; - return cmd; + return cmd; } /** @@ -801,7 +795,7 @@ TALER_TESTING_cmd_track_transfer { struct TrackTransferState *tts; struct TALER_TESTING_Command cmd; - + tts = GNUNET_new (struct TrackTransferState); tts->wtid_reference = wtid_reference; @@ -816,5 +810,5 @@ TALER_TESTING_cmd_track_transfer cmd.run = &track_transfer_run; cmd.cleanup = &track_transfer_cleanup; - return cmd; + return cmd; } diff --git a/src/exchange-lib/testing_api_cmd_wire.c b/src/exchange-lib/testing_api_cmd_wire.c index f65daec00..cf8304e29 100644 --- a/src/exchange-lib/testing_api_cmd_wire.c +++ b/src/exchange-lib/testing_api_cmd_wire.c @@ -27,6 +27,7 @@ #include "taler_json_lib.h" #include <gnunet/gnunet_curl_lib.h> #include "exchange_api_handle.h" +#include "taler_wire_lib.h" #include "taler_testing_lib.h" struct WireState @@ -71,19 +72,6 @@ struct WireState /** - * Check all the expected values have been returned by /wire. - * - * @param cls closure - * @param wire_method name of the wire method (i.e. "sepa") - * @param fees fee structure for this method - */ -static void -check_method_and_fee_cb - (void *cls, - const char *wire_method, - const struct TALER_EXCHANGE_WireAggregateFees *fees); - -/** * Callbacks called with the result(s) of a wire format inquiry * request to the exchange. * @@ -92,23 +80,20 @@ check_method_and_fee_cb * for successful request; 0 if the exchange's * reply is bogus (fails to follow the protocol) * @param ec taler-specific error code, #TALER_EC_NONE on success - * @param obj the received JSON reply, if successful this should - * be the wire format details as provided by /wire. + * @param accounts_len length of the @a accounts array + * @param accounts list of wire accounts of the exchange, NULL on error */ static void wire_cb (void *cls, unsigned int http_status, enum TALER_ErrorCode ec, - const json_t *obj) + unsigned int accounts_len, + const struct TALER_EXCHANGE_WireAccount *accounts) { struct WireState *ws = cls; - struct TALER_TESTING_Command *cmd - = &ws->is->commands[ws->is->ip]; + struct TALER_TESTING_Command *cmd = &ws->is->commands[ws->is->ip]; + struct TALER_Amount expected_fee; - /** - * The handle has been free'd by GNUnet curl-lib. FIXME: - * shouldn't GNUnet nullify it once it frees it? - */ ws->wh = NULL; if (ws->expected_response_code != http_status) { @@ -117,74 +102,54 @@ wire_cb (void *cls, return; } - if (GNUNET_OK != TALER_EXCHANGE_wire_get_fees - (&TALER_EXCHANGE_get_keys (ws->exchange)->master_pub, - obj, - // will check synchronously. - &check_method_and_fee_cb, - ws)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Wire fee extraction in command %s failed\n", - cmd->label); - json_dumpf (obj, stderr, 0); - TALER_TESTING_interpreter_fail (ws->is); - return; - } - - if (ws->method_found != GNUNET_OK) + if (MHD_HTTP_OK == http_status) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "/wire does not offer method '%s'\n", - ws->expected_method); - TALER_TESTING_interpreter_fail (ws->is); - return; - } - TALER_TESTING_interpreter_next (ws->is); -} - -/** - * Check all the expected values have been returned by /wire. - * - * @param cls closure - * @param wire_method name of the wire method (i.e. "sepa") - * @param fees fee structure for this method - */ -static void -check_method_and_fee_cb - (void *cls, - const char *wire_method, - const struct TALER_EXCHANGE_WireAggregateFees *fees) -{ - struct WireState *ws = cls; - struct TALER_TESTING_Command *cmd - = &ws->is->commands[ws->is->ip]; // ugly? - struct TALER_Amount expected_fee; - - if (0 == strcmp (ws->expected_method, wire_method)) - ws->method_found = GNUNET_OK; - - if ( ws->expected_fee && (ws->method_found == GNUNET_OK) ) - { - GNUNET_assert (GNUNET_OK == TALER_string_to_amount - (ws->expected_fee, - &expected_fee)); - while (NULL != fees) + for (unsigned int i=0;i<accounts_len;i++) { - if (0 != TALER_amount_cmp (&fees->wire_fee, - &expected_fee)) + char *method; + + method = TALER_WIRE_payto_get_method (accounts[i].url); + if (0 == strcmp (ws->expected_method, + method)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Wire fee missmatch to command %s\n", - cmd->label); - TALER_TESTING_interpreter_fail (ws->is); - return; + ws->method_found = GNUNET_OK; + if (NULL != ws->expected_fee) + { + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (ws->expected_fee, + &expected_fee)); + for (const struct TALER_EXCHANGE_WireAggregateFees *waf = accounts[i].fees; + NULL != waf; + waf = waf->next) + { + if (0 != TALER_amount_cmp (&waf->wire_fee, + &expected_fee)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Wire fee missmatch to command %s\n", + cmd->label); + TALER_TESTING_interpreter_fail (ws->is); + GNUNET_free (method); + return; + } + } + } } - fees = fees->next; + GNUNET_free (method); + } + if (GNUNET_OK != ws->method_found) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "/wire does not offer method '%s'\n", + ws->expected_method); + TALER_TESTING_interpreter_fail (ws->is); + return; } } + TALER_TESTING_interpreter_next (ws->is); } + /** * Run the command. * diff --git a/src/exchange-lib/testing_api_helpers.c b/src/exchange-lib/testing_api_helpers.c index a942b6522..3aff0a3cc 100644 --- a/src/exchange-lib/testing_api_helpers.c +++ b/src/exchange-lib/testing_api_helpers.c @@ -416,42 +416,54 @@ TALER_TESTING_url_port_free (const char *url) return GNUNET_OK; } + /** - * Allocate and return a piece of wire-details. Mostly, it adds - * the bank_url to the JSON. + * Allocate and return a piece of wire-details. Combines + * the @a account_no and the @a bank_url to a + * @a payto://-URL and adds some salt to create the JSON. * - * @param template the wire-details template. + * @param account_no account number * @param bank_url the bank_url - * - * @return the filled out and stringified wire-details. To - * be manually free'd. + * @return JSON describing the account, including the + * payto://-URL of the account, must be manually decref'd */ -char * -TALER_TESTING_make_wire_details (const char *template, +json_t * +TALER_TESTING_make_wire_details (unsigned long long account_no, const char *bank_url) { - json_t *jtemplate; - - GNUNET_assert (NULL != (jtemplate = json_loads - (template, JSON_REJECT_DUPLICATES, NULL))); - GNUNET_assert (0 == json_object_set - (jtemplate, "bank_url", json_string (bank_url))); - return json_dumps (jtemplate, JSON_COMPACT); + char *payto; + json_t *ret; + + GNUNET_asprintf (&payto, + "payto://x-taler-bank/%s/%llu", + bank_url, + account_no); + ret = json_pack ("{s:s, s:s}", + "url", payto, + "salt", "test-salt (must be constant for aggregation tests)"); + GNUNET_free (payto); + return ret; } + /** * Prepare launching a fakebank. Check that the configuration * file has the right option, and that the port is available. * If everything is OK, return the configured URL of the fakebank. * * @param config_filename configuration file to use + * @param config_section which account to use (must match x-taler-bank) * @return NULL on error, fakebank URL otherwise */ char * -TALER_TESTING_prepare_fakebank (const char *config_filename) +TALER_TESTING_prepare_fakebank (const char *config_filename, + const char *config_section) { struct GNUNET_CONFIGURATION_Handle *cfg; + char *payto_url; char *fakebank_url; + const char *start; + const char *end; cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, @@ -459,17 +471,37 @@ TALER_TESTING_prepare_fakebank (const char *config_filename) return NULL; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "exchange-wire-test", - "BANK_URL", - &fakebank_url)) + config_section, + "URL", + &payto_url)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, - "exchange-wire-test", - "BANK_URL"); + config_section, + "URL"); GNUNET_CONFIGURATION_destroy (cfg); return NULL; } GNUNET_CONFIGURATION_destroy (cfg); + if (0 != strncasecmp (payto_url, + "payto://x-taler-bank/", + strlen ("payto://x-taler-bank/"))) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, + config_section, + "URL", + "expected `x-taler-bank' payto://-URL"); + GNUNET_CONFIGURATION_destroy (cfg); + GNUNET_free (payto_url); + return NULL; + } + start = &payto_url [strlen ("payto://x-taler-bank/")]; + end = strchr (start, + (unsigned char) '/'); + if (NULL == end) + end = &start[strlen (start)]; + fakebank_url = GNUNET_strndup (start, + end - start); + GNUNET_free (payto_url); if (GNUNET_OK != TALER_TESTING_url_port_free (fakebank_url)) { diff --git a/src/exchange-lib/testing_api_trait_json.c b/src/exchange-lib/testing_api_trait_json.c new file mode 100644 index 000000000..40dddbfa3 --- /dev/null +++ b/src/exchange-lib/testing_api_trait_json.c @@ -0,0 +1,76 @@ +/* + This file is part of TALER + Copyright (C) 2018 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 exchange-lib/testing_api_trait_json.c + * @brief offers JSON traits. + * @author Marcello Stanisci + */ +#include "platform.h" +#include "taler_json_lib.h" +#include <gnunet/gnunet_curl_lib.h> +#include "exchange_api_handle.h" +#include "taler_signatures.h" +#include "taler_testing_lib.h" + +#define TALER_TESTING_TRAIT_WIRE_DETAILS "wire-details" + +/** + * Obtain wire details from @a cmd. + * + * @param cmd command to extract trait from + * @param index always (?) zero, as one command sticks + * to one bank account + * @param wire_details[out] where to write the wire details. + * @return #GNUNET_OK on success + */ +int +TALER_TESTING_get_trait_wire_details + (const struct TALER_TESTING_Command *cmd, + unsigned int index, + const json_t **wire_details) +{ + return cmd->traits (cmd->cls, + (void **) wire_details, + TALER_TESTING_TRAIT_WIRE_DETAILS, + index); +} + +/** + * Offer wire details in a trait. + * + * @param index always (?) zero, as one command sticks + * to one bank account + * @param wire_details wire details to offer + * @return the trait, to be put in the traits array of the command + */ +struct TALER_TESTING_Trait +TALER_TESTING_make_trait_wire_details + (unsigned int index, + const json_t *wire_details) +{ + struct TALER_TESTING_Trait ret = { + .index = index, + .trait_name = TALER_TESTING_TRAIT_WIRE_DETAILS, + .ptr = (const json_t *) wire_details + }; + return ret; +} + +/* end of testing_api_trait_json.c */ diff --git a/src/exchange-lib/testing_api_trait_string.c b/src/exchange-lib/testing_api_trait_string.c index 1b1b42219..fb5af93e5 100644 --- a/src/exchange-lib/testing_api_trait_string.c +++ b/src/exchange-lib/testing_api_trait_string.c @@ -30,7 +30,6 @@ #include "taler_signatures.h" #include "taler_testing_lib.h" -#define TALER_TESTING_TRAIT_WIRE_DETAILS "wire-details" #define TALER_TESTING_TRAIT_CONTRACT_TERMS "contract-terms" #define TALER_TESTING_TRAIT_TRANSFER_SUBJECT "transfer-subject" #define TALER_TESTING_TRAIT_AMOUNT "amount" @@ -81,49 +80,6 @@ TALER_TESTING_make_trait_contract_terms /** - * Obtain wire details from @a cmd. - * - * @param cmd command to extract trait from - * @param index always (?) zero, as one command sticks - * to one bank account - * @param wire_details[out] where to write the wire details. - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_get_trait_wire_details - (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const char **wire_details) -{ - return cmd->traits (cmd->cls, - (void **) wire_details, - TALER_TESTING_TRAIT_WIRE_DETAILS, - index); -} - -/** - * Offer wire details in a trait. - * - * @param index always (?) zero, as one command sticks - * to one bank account - * @param wire_details wire details to offer - * @return the trait, to be put in the traits array of the command - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_wire_details - (unsigned int index, - const char *wire_details) -{ - struct TALER_TESTING_Trait ret = { - .index = index, - .trait_name = TALER_TESTING_TRAIT_WIRE_DETAILS, - .ptr = (const void *) wire_details - }; - return ret; -} - - -/** * Obtain a transfer subject from @a cmd. * * @param cmd command to extract trait from @@ -289,7 +245,7 @@ TALER_TESTING_make_trait_order_id struct TALER_TESTING_Trait ret = { .index = index, .trait_name = TALER_TESTING_TRAIT_ORDER_ID, - .ptr = (const void *) order_id + .ptr = (const void *) order_id }; return ret; } @@ -333,7 +289,7 @@ TALER_TESTING_make_trait_rejected struct TALER_TESTING_Trait ret = { .index = index, .trait_name = TALER_TESTING_TRAIT_REJECTED, - .ptr = (const void *) rejected + .ptr = (const void *) rejected }; return ret; } |