diff options
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; } |