diff options
Diffstat (limited to 'src/lib/testing_api_cmd_refresh.c')
-rw-r--r-- | src/lib/testing_api_cmd_refresh.c | 157 |
1 files changed, 102 insertions, 55 deletions
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, |