aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exchange/taler-exchange-httpd_payback.c1
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_reveal.c10
-rw-r--r--src/exchange/taler-exchange-httpd_reserve_withdraw.c6
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c14
-rw-r--r--src/include/taler_exchange_service.h1
-rw-r--r--src/include/taler_testing_lib.h15
-rw-r--r--src/lib/Makefile.am4
-rw-r--r--src/lib/exchange_api_refresh.c32
-rw-r--r--src/lib/test_auditor_api.c4
-rw-r--r--src/lib/test_exchange_api.c12
-rw-r--r--src/lib/test_exchange_api_revocation.c46
-rw-r--r--src/lib/test_exchange_api_twisted.c4
-rw-r--r--src/lib/testing_api_cmd_refresh.c157
13 files changed, 186 insertions, 120 deletions
diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c
index 8cfc1aecc..50c0ffdbc 100644
--- a/src/exchange/taler-exchange-httpd_payback.c
+++ b/src/exchange/taler-exchange-httpd_payback.c
@@ -305,6 +305,7 @@ payback_transaction (void *cls,
}
return qs;
}
+
GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (pc->value.currency,
&spent));
diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c
index d34c85a92..47287b155 100644
--- a/src/exchange/taler-exchange-httpd_refresh_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c
@@ -556,7 +556,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
GNUNET_break_op (0);
return TEH_RESPONSE_reply_arg_invalid (connection,
TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE,
- "new_denoms");
+ "new_denoms_h");
}
if (json_array_size (new_denoms_h_json) !=
@@ -640,7 +640,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
TEH_KS_release (key_state);
return TEH_RESPONSE_reply_arg_invalid (connection,
TALER_EC_REFRESH_REVEAL_FRESH_DENOMINATION_KEY_NOT_FOUND,
- "new_denoms");
+ "new_denoms_h");
}
GNUNET_assert (NULL != dkis[i]->denom_priv.rsa_private_key);
}
@@ -674,7 +674,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
/* lookup old_coin_pub in database */
{
enum GNUNET_DB_QueryStatus qs;
-
+
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
(qs = TEH_plugin->get_melt (TEH_plugin->cls,
NULL,
@@ -725,7 +725,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
ldp.purpose.size = htonl (sizeof (ldp));
ldp.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK);
ldp.h_denom_pub = dki_h[i];
- ldp.old_coin_pub = refresh_melt.session.coin.coin_pub;
+ ldp.old_coin_pub = refresh_melt.session.coin.coin_pub;
ldp.transfer_pub = rctx->gamma_tp;
GNUNET_CRYPTO_hash (rcds[i].coin_ev,
rcds[i].coin_ev_size,
@@ -744,7 +744,7 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
}
}
}
-
+
rctx->num_fresh_coins = num_fresh_coins;
rctx->rcds = rcds;
rctx->dkis = dkis;
diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c b/src/exchange/taler-exchange-httpd_reserve_withdraw.c
index 32d53980d..65bca25e5 100644
--- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c
@@ -286,7 +286,7 @@ withdraw_transaction (void *cls,
return GNUNET_DB_STATUS_HARD_ERROR;
}
*mhd_ret = reply_reserve_withdraw_insufficient_funds (connection,
- rh);
+ rh);
TEH_plugin->free_reserve_history (TEH_plugin->cls,
rh);
return GNUNET_DB_STATUS_HARD_ERROR;
@@ -319,8 +319,8 @@ withdraw_transaction (void *cls,
wc->collectable.h_coin_envelope = wc->wsrd.h_coin_envelope;
wc->collectable.reserve_sig = wc->signature;
qs = TEH_plugin->insert_withdraw_info (TEH_plugin->cls,
- session,
- &wc->collectable);
+ session,
+ &wc->collectable);
if (0 > qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index c95ed2616..72e77fa6b 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -2593,8 +2593,8 @@ postgres_insert_withdraw_info (void *cls,
now = GNUNET_TIME_absolute_get ();
(void) GNUNET_TIME_round_abs (&now);
qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
- "insert_withdraw_info",
- params);
+ "insert_withdraw_info",
+ params);
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
@@ -2627,6 +2627,9 @@ postgres_insert_withdraw_info (void *cls,
TALER_B2S (&collectable->reserve_pub));
return GNUNET_DB_STATUS_SOFT_ERROR;
}
+ /* FIXME: idle_reserve_expiration_time is not a good value here,
+ we should base this on the LEGAL expiration time of coins
+ as we need reserve data for payback! */
expiry = GNUNET_TIME_absolute_add (now,
pg->idle_reserve_expiration_time);
reserve.expiry = GNUNET_TIME_absolute_max (expiry,
@@ -7721,11 +7724,12 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
return NULL;
}
}
+
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (cfg,
- "exchangedb",
- "IDLE_RESERVE_EXPIRATION_TIME",
- &pg->idle_reserve_expiration_time))
+ "exchangedb",
+ "IDLE_RESERVE_EXPIRATION_TIME",
+ &pg->idle_reserve_expiration_time))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchangedb",
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 7bcfee9e4..4ced8ad92 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -511,6 +511,7 @@ TALER_EXCHANGE_get_signing_key_details (const struct TALER_EXCHANGE_Keys *keys,
const char *
TALER_EXCHANGE_get_base_url (const struct TALER_EXCHANGE_Handle *exchange);
+
/**
* Obtain the denomination key details from the exchange.
*
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index c08cfdc5c..41cc8b501 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -131,6 +131,7 @@ TALER_TESTING_cert_cb
const struct TALER_EXCHANGE_Keys *keys,
enum TALER_EXCHANGE_VersionCompatibility compat);
+
/**
* Wait for the exchange to have started. Waits for at
* most 10s, after that returns 77 to indicate an error.
@@ -1108,19 +1109,18 @@ TALER_TESTING_cmd_deposit_with_retry
* Create a "refresh melt" command.
*
* @param label command label.
- * @param amount amount to be melted.
* @param coin_reference reference to a command
* that will provide a coin to refresh.
* @param expected_response_code expected HTTP code.
- *
+ * @param ... NULL-terminated list of amounts to be melted
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_refresh_melt
(const char *label,
- const char *amount,
const char *coin_reference,
- unsigned int expected_response_code);
+ unsigned int expected_response_code,
+ ...);
/**
@@ -1129,19 +1129,18 @@ TALER_TESTING_cmd_refresh_melt
* request, see #5312.
*
* @param label command label
- * @param amount FIXME not used.
* @param coin_reference reference to a command that will provide
* a coin to refresh
* @param expected_response_code expected HTTP code
- *
+ * @param ... NULL-terminated list of amounts to be melted
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_refresh_melt_double
(const char *label,
- const char *amount,
const char *coin_reference,
- unsigned int expected_response_code);
+ unsigned int expected_response_code,
+ ...);
/**
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 71301e58d..fddc961f5 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -192,8 +192,8 @@ TESTS = \
$(check_PROGRAMS)
# expected to fail for now: test incomplete, feature not implemented!
-XFAIL_TESTS = \
- test_exchange_api_revocation
+#XFAIL_TESTS = \
+# test_exchange_api_revocation
test_exchange_api_SOURCES = \
test_exchange_api.c
diff --git a/src/lib/exchange_api_refresh.c b/src/lib/exchange_api_refresh.c
index c12fd32db..617eab393 100644
--- a/src/lib/exchange_api_refresh.c
+++ b/src/lib/exchange_api_refresh.c
@@ -1518,11 +1518,11 @@ handle_refresh_reveal_finished (void *cls,
*/
struct TALER_EXCHANGE_RefreshRevealHandle *
TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
- size_t refresh_data_length,
- const char *refresh_data,
- uint32_t noreveal_index,
- TALER_EXCHANGE_RefreshRevealCallback reveal_cb,
- void *reveal_cb_cls)
+ size_t refresh_data_length,
+ const char *refresh_data,
+ uint32_t noreveal_index,
+ TALER_EXCHANGE_RefreshRevealCallback reveal_cb,
+ void *reveal_cb_cls)
{
struct TALER_EXCHANGE_RefreshRevealHandle *rrh;
json_t *transfer_privs;
@@ -1535,15 +1535,6 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
struct MeltData *md;
struct TALER_TransferPublicKeyP transfer_pub;
- GNUNET_assert (GNUNET_YES ==
- TEAH_handle_is_ready (exchange));
- md = deserialize_melt_data (refresh_data,
- refresh_data_length);
- if (NULL == md)
- {
- GNUNET_break (0);
- return NULL;
- }
if (noreveal_index >= TALER_CNC_KAPPA)
{
/* We check this here, as it would be really bad to below just
@@ -1553,6 +1544,19 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_break (0);
return NULL;
}
+ if (GNUNET_YES !=
+ TEAH_handle_is_ready (exchange))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ md = deserialize_melt_data (refresh_data,
+ refresh_data_length);
+ if (NULL == md)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
/* now transfer_pub */
GNUNET_CRYPTO_ecdhe_key_get_public (&md->melted_coin.transfer_priv[noreveal_index].ecdhe_priv,
diff --git a/src/lib/test_auditor_api.c b/src/lib/test_auditor_api.c
index 6595ea767..df69eac9e 100644
--- a/src/lib/test_auditor_api.c
+++ b/src/lib/test_auditor_api.c
@@ -231,9 +231,9 @@ run (void *cls,
* Melt the rest of the coin's value (EUR:4.00 = 3x EUR:1.03 + 7x
* EUR:0.13) */
TALER_TESTING_cmd_refresh_melt_double ("refresh-melt-1",
- "EUR:4",
"refresh-withdraw-coin-1",
- MHD_HTTP_OK),
+ MHD_HTTP_OK,
+ NULL),
/**
* Complete (successful) melt operation, and withdraw the coins
*/
diff --git a/src/lib/test_exchange_api.c b/src/lib/test_exchange_api.c
index dc868d1d3..33a2df9dd 100644
--- a/src/lib/test_exchange_api.c
+++ b/src/lib/test_exchange_api.c
@@ -309,8 +309,10 @@ run (void *cls,
* Melt the rest of the coin's value
* (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
TALER_TESTING_cmd_refresh_melt_double
- ("refresh-melt-1", "EUR:4",
- "refresh-withdraw-coin-1", MHD_HTTP_OK),
+ ("refresh-melt-1",
+ "refresh-withdraw-coin-1",
+ MHD_HTTP_OK,
+ NULL),
/**
* Complete (successful) melt operation, and
* withdraw the coins
@@ -360,8 +362,10 @@ run (void *cls,
/* Test running a failing melt operation (same operation
* again must fail) */
TALER_TESTING_cmd_refresh_melt
- ("refresh-melt-failing", "EUR:4",
- "refresh-withdraw-coin-1", MHD_HTTP_FORBIDDEN),
+ ("refresh-melt-failing",
+ "refresh-withdraw-coin-1",
+ MHD_HTTP_FORBIDDEN,
+ NULL),
/* FIXME: also test with coin that was already melted
* (signature differs from coin that was deposited...) */
diff --git a/src/lib/test_exchange_api_revocation.c b/src/lib/test_exchange_api_revocation.c
index bd1d91c66..14bb4553f 100644
--- a/src/lib/test_exchange_api_revocation.c
+++ b/src/lib/test_exchange_api_revocation.c
@@ -142,11 +142,13 @@ run (void *cls,
\"value\":\"EUR:1\"}]}",
GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_OK),
/**
- * Melt the rest of the coin's value
- * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
- TALER_TESTING_cmd_refresh_melt_double
- ("refresh-melt-1", "EUR:4",
- "withdraw-coin-1", MHD_HTTP_OK),
+ * Melt SOME of the rest of the coin's value
+ * (EUR:3.17 = 3x EUR:1.03 + 7x EUR:0.13) */
+ TALER_TESTING_cmd_refresh_melt
+ ("refresh-melt-1",
+ "withdraw-coin-1",
+ MHD_HTTP_OK,
+ NULL),
/**
* Complete (successful) melt operation, and withdraw the coins
*/
@@ -174,45 +176,49 @@ run (void *cls,
"refresh-reveal-1#2",
"EUR:1",
"refresh-melt-1"),
- /* Melt original coin AGAIN (FIXME: this command
- is simply WRONG as it neither matches
- the EUR:3 that were paid back NOR is melt_double
- precisely right here!) -- it always tries to MELT EUR:4, which is too much! */
- TALER_TESTING_cmd_refresh_melt_double
- ("refresh-melt-2", "EUR:3",
- "withdraw-coin-1", MHD_HTTP_OK),
+ /* Now we have EUR:3.83 EUR back after 3x EUR:1 in paybacks */
+ /* Melt original coin AGAIN, but only create one 0.1 EUR coin;
+ This costs EUR:0.03 in refresh and EUR:01 in withdraw fees,
+ leaving EUR:3.69. */
+ TALER_TESTING_cmd_refresh_melt
+ ("refresh-melt-2",
+ "withdraw-coin-1",
+ MHD_HTTP_OK,
+ "EUR:0.1",
+ NULL),
/**
* Complete (successful) melt operation, and withdraw the coins
*/
TALER_TESTING_cmd_refresh_reveal
("refresh-reveal-2",
"refresh-melt-2", MHD_HTTP_OK),
- /* Make refreshed coin invalid */
+ /* Revokes refreshed EUR:0.1 coin */
TALER_TESTING_cmd_revoke ("revoke-2",
MHD_HTTP_OK,
"refresh-reveal-2",
CONFIG_FILE),
- /* Make also original coin invalid */
+ /* Revoke also original coin denomination */
TALER_TESTING_cmd_revoke ("revoke-3",
MHD_HTTP_OK,
"withdraw-coin-1",
CONFIG_FILE),
- /* Refund coin to original coin */
+ /* Refund coin EUR:0.1 to original coin, creating zombie! */
TALER_TESTING_cmd_payback ("payback-2",
MHD_HTTP_OK,
- "refresh-melt-2",
- "EUR:1",
+ "refresh-reveal-2",
+ "EUR:0.1",
"refresh-melt-2"),
- /* Refund original coin to reserve */
+ /* Due to payback, original coin is now at EUR:3.79 */
+ /* Refund original (now zombie) coin to reserve */
TALER_TESTING_cmd_payback ("payback-3",
MHD_HTTP_OK,
"withdraw-coin-1",
- "EUR:1",
+ "EUR:3.79",
NULL),
/* Check the money is back with the reserve */
TALER_TESTING_cmd_status ("payback-reserve-status-1",
"create-reserve-1",
- "EUR:1.0",
+ "EUR:3.79",
MHD_HTTP_OK),
TALER_TESTING_cmd_end ()
};
diff --git a/src/lib/test_exchange_api_twisted.c b/src/lib/test_exchange_api_twisted.c
index 7ba9cbaae..48a4ed36e 100644
--- a/src/lib/test_exchange_api_twisted.c
+++ b/src/lib/test_exchange_api_twisted.c
@@ -187,9 +187,9 @@ run (void *cls,
* (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
TALER_TESTING_cmd_refresh_melt
("refresh-melt",
- "EUR:4",
"refresh-withdraw-coin",
- MHD_HTTP_OK),
+ MHD_HTTP_OK,
+ NULL),
/* Trigger 409 Conflict. */
TALER_TESTING_cmd_flip_upload
diff --git a/src/lib/testing_api_cmd_refresh.c b/src/lib/testing_api_cmd_refresh.c
index bc67af7f9..b2754edd8 100644
--- a/src/lib/testing_api_cmd_refresh.c
+++ b/src/lib/testing_api_cmd_refresh.c
@@ -37,16 +37,6 @@
struct MeltDetails
{
- /**
- * Amount to melt (including fee).
- */
- const char *amount;
-
- /**
- * Reference to reserve_withdraw operations for coin to
- * be used for the /refresh/melt operation.
- */
- const char *coin_reference;
};
@@ -57,9 +47,10 @@ struct RefreshMeltState
{
/**
- * Information about coins to be melted.
+ * Reference to reserve_withdraw operations for coin to
+ * be used for the /refresh/melt operation.
*/
- struct MeltDetails melted_coin;
+ const char *coin_reference;
/**
* "Crypto data" used in the refresh operation.
@@ -108,6 +99,11 @@ struct RefreshMeltState
size_t refresh_data_length;
/**
+ * Amounts to be generated during melt.
+ */
+ const char **melt_fresh_amounts;
+
+ /**
* Number of fresh coins generated by the melt.
*/
unsigned int num_fresh_coins;
@@ -314,12 +310,12 @@ reveal_cb (void *cls,
"Retrying refresh reveal failed with %u/%d\n",
http_status,
(int) ec);
- /* on DB conflicts, do not use backoff */
- if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
- rrs->backoff = GNUNET_TIME_UNIT_ZERO;
- else
- rrs->backoff = EXCHANGE_LIB_BACKOFF (rrs->backoff);
- rrs->retry_task = GNUNET_SCHEDULER_add_delayed (rrs->backoff,
+ /* on DB conflicts, do not use backoff */
+ if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
+ rrs->backoff = GNUNET_TIME_UNIT_ZERO;
+ else
+ rrs->backoff = EXCHANGE_LIB_BACKOFF (rrs->backoff);
+ rrs->retry_task = GNUNET_SCHEDULER_add_delayed (rrs->backoff,
&do_reveal_retry,
rrs);
return;
@@ -691,12 +687,9 @@ refresh_link_run (void *cls,
/* find reserve_withdraw command */
{
- const struct MeltDetails *md;
-
rms = melt_cmd->cls;
- md = &rms->melted_coin;
coin_cmd = TALER_TESTING_interpreter_lookup_command
- (rls->is, md->coin_reference);
+ (rls->is, rms->coin_reference);
if (NULL == coin_cmd)
{
GNUNET_break (0);
@@ -879,11 +872,14 @@ refresh_melt_run (void *cls,
{
struct RefreshMeltState *rms = cls;
unsigned int num_fresh_coins;
- /* FIXME: this should be dynamic */
- const char *melt_fresh_amounts[] = {
+ const char *default_melt_fresh_amounts[] = {
"EUR:1", "EUR:1", "EUR:1", "EUR:0.1",
- NULL};
+ NULL
+ };
+ const char **melt_fresh_amounts;
+ if (NULL == (melt_fresh_amounts = rms->melt_fresh_amounts))
+ melt_fresh_amounts = default_melt_fresh_amounts;
rms->is = is;
rms->noreveal_index = UINT16_MAX;
for (num_fresh_coins=0;
@@ -899,11 +895,10 @@ refresh_melt_run (void *cls,
const struct TALER_DenominationSignature *melt_sig;
const struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub;
const struct TALER_TESTING_Command *coin_command;
- const struct MeltDetails *md = &rms->melted_coin;
if (NULL == (coin_command
= TALER_TESTING_interpreter_lookup_command
- (is, md->coin_reference)))
+ (is, rms->coin_reference)))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (rms->is);
@@ -919,18 +914,6 @@ refresh_melt_run (void *cls,
}
if (GNUNET_OK !=
- TALER_string_to_amount (md->amount,
- &melt_amount))
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u\n",
- md->amount,
- is->ip);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
- if (GNUNET_OK !=
TALER_TESTING_get_trait_denom_sig (coin_command,
0,
&melt_sig))
@@ -946,6 +929,9 @@ refresh_melt_run (void *cls,
TALER_TESTING_interpreter_fail (rms->is);
return;
}
+ /* Melt amount starts with the melt fee of the old coin; we'll add the
+ values and withdraw fees of the fresh coins next */
+ melt_amount = melt_denom_pub->fee_refresh;
for (unsigned int i=0;i<num_fresh_coins;i++)
{
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk;
@@ -969,7 +955,14 @@ refresh_melt_run (void *cls,
TALER_TESTING_interpreter_fail (rms->is);
return;
}
-
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_add (&melt_amount,
+ &melt_amount,
+ &fresh_amount));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_add (&melt_amount,
+ &melt_amount,
+ &fresh_pk->fee_withdraw));
rms->fresh_pks[i] = *fresh_pk;
}
rms->refresh_data = TALER_EXCHANGE_refresh_prepare
@@ -1028,6 +1021,7 @@ refresh_melt_cleanup (void *cls,
GNUNET_free_non_null (rms->refresh_data);
rms->refresh_data = NULL;
rms->refresh_data_length = 0;
+ GNUNET_free_non_null (rms->melt_fresh_amounts);
GNUNET_free (rms);
}
@@ -1070,31 +1064,82 @@ refresh_melt_traits (void *cls,
/**
+ * Parse list of amounts for melt operation.
+ *
+ * @param rms[in,out] where to store the list
+ * @param ap NULL-termianted list of amounts to be melted (one per fresh coin)
+ * @return #GNUNET_OK on success
+ */
+static int
+parse_amounts (struct RefreshMeltState *rms,
+ va_list ap)
+{
+ unsigned int len;
+ unsigned int off;
+ const char *amount;
+
+ len = 0;
+ off = 0;
+ while (NULL != (amount = va_arg (ap, const char *)))
+ {
+ if (len == off)
+ {
+ struct TALER_Amount a;
+
+ GNUNET_array_grow (rms->melt_fresh_amounts,
+ len,
+ off + 16);
+ if (GNUNET_OK !=
+ TALER_string_to_amount (amount, &a))
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to parse amount `%s' at index %u\n",
+ amount, off);
+ GNUNET_free (rms->melt_fresh_amounts);
+ rms->melt_fresh_amounts = NULL;
+ return GNUNET_SYSERR;
+ }
+ rms->melt_fresh_amounts[off++] = amount;
+ }
+ }
+ if (0 == off)
+ return GNUNET_OK; /* no amounts given == use defaults! */
+ /* ensure NULL-termination */
+ GNUNET_array_grow (rms->melt_fresh_amounts,
+ len,
+ off + 1);
+ return GNUNET_OK;
+}
+
+
+/**
* Create a "refresh melt" command.
*
* @param label command label.
- * @param amount amount to be melted.
* @param coin_reference reference to a command
* that will provide a coin to refresh.
* @param expected_response_code expected HTTP code.
- *
+ * @param ... NULL-terminated list of amounts to be melted
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_refresh_melt
(const char *label,
- const char *amount,
const char *coin_reference,
- unsigned int expected_response_code)
+ unsigned int expected_response_code,
+ ...)
{
struct RefreshMeltState *rms;
- struct MeltDetails md;
+ va_list ap;
- md.coin_reference = coin_reference;
- md.amount = amount;
rms = GNUNET_new (struct RefreshMeltState);
- rms->melted_coin = md;
+ rms->coin_reference = coin_reference;
rms->expected_response_code = expected_response_code;
+ va_start (ap, expected_response_code);
+ GNUNET_assert (GNUNET_OK ==
+ parse_amounts (rms, ap));
+ va_end (ap);
{
struct TALER_TESTING_Command cmd = {
.label = label,
@@ -1116,28 +1161,30 @@ TALER_TESTING_cmd_refresh_melt
*
* @param label command label
* @param exchange connection to the exchange
- * @param amount amount to be melted.
* @param coin_reference reference to a command that will provide
* a coin to refresh
* @param expected_response_code expected HTTP code
+ * @param ... NULL-terminated list of amounts to be melted
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_refresh_melt_double
(const char *label,
- const char *amount,
const char *coin_reference,
- unsigned int expected_response_code)
+ unsigned int expected_response_code,
+ ...)
{
struct RefreshMeltState *rms;
- struct MeltDetails md;
+ va_list ap;
- md.coin_reference = coin_reference;
- md.amount = amount;
rms = GNUNET_new (struct RefreshMeltState);
- rms->melted_coin = md;
+ rms->coin_reference = coin_reference;
rms->expected_response_code = expected_response_code;
rms->double_melt = GNUNET_YES;
+ va_start (ap, expected_response_code);
+ GNUNET_assert (GNUNET_OK ==
+ parse_amounts (rms, ap));
+ va_end (ap);
{
struct TALER_TESTING_Command cmd = {
.label = label,