diff options
Diffstat (limited to 'src/testing/testing_api_cmd_refresh.c')
-rw-r--r-- | src/testing/testing_api_cmd_refresh.c | 554 |
1 files changed, 343 insertions, 211 deletions
diff --git a/src/testing/testing_api_cmd_refresh.c b/src/testing/testing_api_cmd_refresh.c index dc0392b9e..111e9118f 100644 --- a/src/testing/testing_api_cmd_refresh.c +++ b/src/testing/testing_api_cmd_refresh.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2018-2020 Taler Systems SA + Copyright (C) 2018-2022 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 @@ -70,10 +70,17 @@ struct TALER_TESTING_FreshCoinData */ struct TALER_CoinSpendPrivateKeyP coin_priv; + /* + * Fresh age commitment for the coin with proof and its hash, NULL if not + * applicable. + */ + struct TALER_AgeCommitmentProof *age_commitment_proof; + struct TALER_AgeCommitmentHash h_age_commitment; + /** * The blinding key (needed for recoup operations). */ - union TALER_DenominationBlindingKeyP blinding_key; + union GNUNET_CRYPTO_BlindingSecretP blinding_key; }; @@ -91,9 +98,14 @@ struct RefreshMeltState const char *coin_reference; /** - * "Crypto data" used in the refresh operation. + * Data used in the refresh operation. + */ + struct TALER_EXCHANGE_RefreshData refresh_data; + + /** + * Our command. */ - json_t *refresh_data; + const struct TALER_TESTING_Command *cmd; /** * Reference to a previous melt command. @@ -106,6 +118,12 @@ struct RefreshMeltState struct TALER_EXCHANGE_MeltHandle *rmh; /** + * Expected entry in the coin history created by this + * operation. + */ + struct TALER_EXCHANGE_CoinHistoryEntry che; + + /** * Interpreter state. */ struct TALER_TESTING_Interpreter *is; @@ -117,11 +135,27 @@ struct RefreshMeltState struct TALER_EXCHANGE_DenomPublicKey *fresh_pks; /** + * Array of @e num_fresh_coins of results from + * the melt operation. + */ + struct TALER_EXCHANGE_MeltBlindingDetail *mbds; + + /** + * Entropy seed for the refresh-melt operation. + */ + struct TALER_RefreshMasterSecretP rms; + + /** * Private key of the dirty coin being melted. */ const struct TALER_CoinSpendPrivateKeyP *melt_priv; /** + * Public key of the dirty coin being melted. + */ + struct TALER_CoinSpendPublicKeyP melt_pub; + + /** * Task scheduled to try later. */ struct GNUNET_SCHEDULER_Task *retry_task; @@ -162,7 +196,7 @@ struct RefreshMeltState * exchange to pick any previous /rerfesh/melt operation from * the database. */ - unsigned int double_melt; + bool double_melt; /** * How often should we retry on (transient) failures? @@ -192,6 +226,11 @@ struct RefreshRevealState struct TALER_EXCHANGE_RefreshesRevealHandle *rrh; /** + * Our command. + */ + const struct TALER_TESTING_Command *cmd; + + /** * Convenience struct to keep in one place all the * data related to one fresh coin, set by the reveal callback * as it comes from the exchange. @@ -199,6 +238,12 @@ struct RefreshRevealState struct TALER_TESTING_FreshCoinData *fresh_coins; /** + * Array of @e num_fresh_coins planchet secrets derived + * from the transfer secret per fresh coin. + */ + struct TALER_PlanchetMasterSecretP *psa; + + /** * Interpreter state. */ struct TALER_TESTING_Interpreter *is; @@ -249,6 +294,11 @@ struct RefreshLinkState const char *reveal_reference; /** + * Our command. + */ + const struct TALER_TESTING_Command *cmd; + + /** * Handle to the ongoing operation. */ struct TALER_EXCHANGE_LinkHandle *rlh; @@ -310,8 +360,7 @@ do_reveal_retry (void *cls) struct RefreshRevealState *rrs = cls; rrs->retry_task = NULL; - rrs->is->commands[rrs->is->ip].last_req_time - = GNUNET_TIME_absolute_get (); + TALER_TESTING_touch_cmd (rrs->is); refresh_reveal_run (rrs, NULL, rrs->is); @@ -324,23 +373,14 @@ do_reveal_retry (void *cls) * coming from the exchange, namely the fresh coins. * * @param cls closure, a `struct RefreshRevealState` - * @param hr HTTP response details - * @param num_coins number of fresh coins created, length of the - * @a sigs and @a coin_privs arrays, 0 if the operation - * failed. - * @param coin_privs array of @a num_coins private keys for the - * coins that were created, NULL on error. - * @param sigs array of signature over @a num_coins coins, - * NULL on error. + * @param rr HTTP response details */ static void reveal_cb (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - unsigned int num_coins, - const struct TALER_PlanchetSecretsP *coin_privs, - const struct TALER_DenominationSignature *sigs) + const struct TALER_EXCHANGE_RevealResult *rr) { struct RefreshRevealState *rrs = cls; + const struct TALER_EXCHANGE_HttpResponse *hr = &rr->hr; const struct TALER_TESTING_Command *melt_cmd; rrs->rrh = NULL; @@ -365,24 +405,16 @@ reveal_cb (void *cls, MAX_BACKOFF); rrs->total_backoff = GNUNET_TIME_relative_add (rrs->total_backoff, rrs->backoff); - rrs->is->commands[rrs->is->ip].num_tries++; + TALER_TESTING_inc_tries (rrs->is); rrs->retry_task = GNUNET_SCHEDULER_add_delayed (rrs->backoff, &do_reveal_retry, rrs); return; } } - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d to command %s in %s:%u\n", - hr->http_status, - (int) hr->ec, - rrs->is->commands[rrs->is->ip].label, - __FILE__, - __LINE__); - json_dumpf (hr->reply, - stderr, - 0); - TALER_TESTING_interpreter_fail (rrs->is); + TALER_TESTING_unexpected_status (rrs->is, + hr->http_status, + rrs->expected_response_code); return; } melt_cmd = TALER_TESTING_interpreter_lookup_command (rrs->is, @@ -393,16 +425,22 @@ reveal_cb (void *cls, TALER_TESTING_interpreter_fail (rrs->is); return; } - rrs->num_fresh_coins = num_coins; switch (hr->http_status) { case MHD_HTTP_OK: - rrs->fresh_coins = GNUNET_new_array (num_coins, + rrs->num_fresh_coins = rr->details.ok.num_coins; + rrs->psa = GNUNET_new_array (rrs->num_fresh_coins, + struct TALER_PlanchetMasterSecretP); + rrs->fresh_coins = GNUNET_new_array (rrs->num_fresh_coins, struct TALER_TESTING_FreshCoinData); - for (unsigned int i = 0; i<num_coins; i++) + for (unsigned int i = 0; i<rrs->num_fresh_coins; i++) { + const struct TALER_EXCHANGE_RevealedCoinInfo *coin + = &rr->details.ok.coins[i]; struct TALER_TESTING_FreshCoinData *fc = &rrs->fresh_coins[i]; + rrs->psa[i] = coin->ps; + fc->blinding_key = coin->bks; if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub (melt_cmd, i, @@ -412,18 +450,25 @@ reveal_cb (void *cls, TALER_TESTING_interpreter_fail (rrs->is); return; } - fc->coin_priv = coin_privs[i].coin_priv; - fc->blinding_key = coin_privs[i].blinding_key; - TALER_denom_sig_deep_copy (&fc->sig, - &sigs[i]); + fc->coin_priv = coin->coin_priv; + + if (NULL != coin->age_commitment_proof) + { + fc->age_commitment_proof = + TALER_age_commitment_proof_duplicate (coin->age_commitment_proof); + fc->h_age_commitment = coin->h_age_commitment; + } + + TALER_denom_sig_copy (&fc->sig, + &coin->sig); } if (0 != rrs->total_backoff.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Total reveal backoff for %s was %s\n", - rrs->is->commands[rrs->is->ip].label, + rrs->cmd->label, GNUNET_STRINGS_relative_time_to_string (rrs->total_backoff, - GNUNET_YES)); + true)); } break; default: @@ -444,6 +489,19 @@ reveal_cb (void *cls, * @param is the interpreter state. */ static void +melt_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is); + + +/** + * Run the command. + * + * @param cls closure. + * @param cmd the command to execute. + * @param is the interpreter state. + */ +static void refresh_reveal_run (void *cls, const struct TALER_TESTING_Command *cmd, struct TALER_TESTING_Interpreter *is) @@ -452,6 +510,7 @@ refresh_reveal_run (void *cls, struct RefreshMeltState *rms; const struct TALER_TESTING_Command *melt_cmd; + rrs->cmd = cmd; rrs->is = is; melt_cmd = TALER_TESTING_interpreter_lookup_command (is, rrs->melt_reference); @@ -461,13 +520,24 @@ refresh_reveal_run (void *cls, TALER_TESTING_interpreter_fail (rrs->is); return; } + GNUNET_assert (melt_cmd->run == &melt_run); rms = melt_cmd->cls; - rrs->rrh = TALER_EXCHANGE_refreshes_reveal (is->exchange, - rms->refresh_data, - rms->noreveal_index, - &reveal_cb, - rrs); - + { + struct TALER_ExchangeWithdrawValues alg_values[rms->num_fresh_coins]; + + for (unsigned int i = 0; i<rms->num_fresh_coins; i++) + alg_values[i] = rms->mbds[i].alg_value; + rrs->rrh = TALER_EXCHANGE_refreshes_reveal ( + TALER_TESTING_interpreter_get_context (is), + TALER_TESTING_get_exchange_url (is), + &rms->rms, + &rms->refresh_data, + rms->num_fresh_coins, + alg_values, + rms->noreveal_index, + &reveal_cb, + rrs); + } if (NULL == rrs->rrh) { GNUNET_break (0); @@ -493,10 +563,8 @@ refresh_reveal_cleanup (void *cls, (void) cmd; if (NULL != rrs->rrh) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Command %u (%s) did not complete\n", - rrs->is->ip, - cmd->label); + TALER_TESTING_command_incomplete (rrs->is, + cmd->label); TALER_EXCHANGE_refreshes_reveal_cancel (rrs->rrh); rrs->rrh = NULL; } @@ -507,10 +575,14 @@ refresh_reveal_cleanup (void *cls, } for (unsigned int j = 0; j < rrs->num_fresh_coins; j++) + { TALER_denom_sig_free (&rrs->fresh_coins[j].sig); + TALER_age_commitment_proof_free (rrs->fresh_coins[j].age_commitment_proof); + GNUNET_free (rrs->fresh_coins[j].age_commitment_proof); + } GNUNET_free (rrs->fresh_coins); - rrs->fresh_coins = NULL; + GNUNET_free (rrs->psa); rrs->num_fresh_coins = 0; GNUNET_free (rrs); } @@ -540,8 +612,7 @@ do_link_retry (void *cls) struct RefreshLinkState *rls = cls; rls->retry_task = NULL; - rls->is->commands[rls->is->ip].last_req_time - = GNUNET_TIME_absolute_get (); + TALER_TESTING_touch_cmd (rls->is); refresh_link_run (rls, NULL, rls->is); @@ -554,29 +625,15 @@ do_link_retry (void *cls) * withdrawn by the "refresh reveal" CMD. * * @param cls closure. - * @param hr HTTP response details - * @param num_coins number of fresh coins created, length of the - * @a sigs and @a coin_privs arrays, 0 if the operation - * failed. - * @param coin_privs array of @a num_coins private keys for the - * coins that were created, NULL on error. - * @param sigs array of signature over @a num_coins coins, NULL on - * error. - * @param pubs array of public keys for the @a sigs, - * NULL on error. + * @param lr HTTP response details */ static void link_cb (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - unsigned int num_coins, - const struct TALER_CoinSpendPrivateKeyP *coin_privs, - const struct TALER_DenominationSignature *sigs, - const struct TALER_DenominationPublicKey *pubs) + const struct TALER_EXCHANGE_LinkResult *lr) { - struct RefreshLinkState *rls = cls; + const struct TALER_EXCHANGE_HttpResponse *hr = &lr->hr; const struct TALER_TESTING_Command *reveal_cmd; - struct TALER_TESTING_Command *link_cmd = &rls->is->commands[rls->is->ip]; unsigned int found; const unsigned int *num_fresh_coins; @@ -602,24 +659,16 @@ link_cb (void *cls, MAX_BACKOFF); rls->total_backoff = GNUNET_TIME_relative_add (rls->total_backoff, rls->backoff); - rls->is->commands[rls->is->ip].num_tries++; + TALER_TESTING_inc_tries (rls->is); rls->retry_task = GNUNET_SCHEDULER_add_delayed (rls->backoff, &do_link_retry, rls); return; } } - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d to command %s in %s:%u\n", - hr->http_status, - (int) hr->ec, - link_cmd->label, - __FILE__, - __LINE__); - json_dumpf (hr->reply, - stderr, - 0); - TALER_TESTING_interpreter_fail (rls->is); + TALER_TESTING_unexpected_status (rls->is, + hr->http_status, + rls->expected_response_code); return; } reveal_cmd = TALER_TESTING_interpreter_lookup_command (rls->is, @@ -643,11 +692,11 @@ link_cb (void *cls, TALER_TESTING_interpreter_fail (rls->is); return; } - if (num_coins != *num_fresh_coins) + if (lr->details.ok.num_coins != *num_fresh_coins) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected number of fresh coins: %d vs %d in %s:%u\n", - num_coins, + lr->details.ok.num_coins, *num_fresh_coins, __FILE__, __LINE__); @@ -655,11 +704,11 @@ link_cb (void *cls, return; } /* check that the coins match */ - for (unsigned int i = 0; i<num_coins; i++) - for (unsigned int j = i + 1; j<num_coins; j++) + for (unsigned int i = 0; i<lr->details.ok.num_coins; i++) + for (unsigned int j = i + 1; j<lr->details.ok.num_coins; j++) if (0 == - GNUNET_memcmp (&coin_privs[i], - &coin_privs[j])) + GNUNET_memcmp (&lr->details.ok.coins[i].coin_priv, + &lr->details.ok.coins[j].coin_priv)) GNUNET_break (0); /* Note: coins might be legitimately permutated in here... */ found = 0; @@ -677,29 +726,38 @@ link_cb (void *cls, return; } - for (unsigned int i = 0; i<num_coins; i++) - for (unsigned int j = 0; j<num_coins; j++) + for (unsigned int i = 0; i<lr->details.ok.num_coins; i++) + { + const struct TALER_EXCHANGE_LinkedCoinInfo *lci_i + = &lr->details.ok.coins[i]; + + for (unsigned int j = 0; j<lr->details.ok.num_coins; j++) { + const struct TALER_TESTING_FreshCoinData *fcj + = &(*fc)[j]; + if ( (0 == - GNUNET_memcmp (&coin_privs[i], - &(*fc)[j].coin_priv)) && + GNUNET_memcmp (&fcj->coin_priv, + &lci_i->coin_priv)) && (0 == - TALER_denom_sig_cmp (&(*fc)[i].sig, - &sigs[j])) && + TALER_denom_sig_cmp (&fcj->sig, + &lci_i->sig)) && (0 == - TALER_denom_pub_cmp (&(*fc)[i].pk->key, - &pubs[j])) ) + TALER_denom_pub_cmp (&fcj->pk->key, + &lci_i->pub)) ) { found++; break; } - } + } /* for j*/ + } /* for i */ } - if (found != num_coins) + if (found != lr->details.ok.num_coins) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Only %u/%u coins match expectations\n", - found, num_coins); + found, + lr->details.ok.num_coins); GNUNET_break (0); TALER_TESTING_interpreter_fail (rls->is); return; @@ -708,9 +766,9 @@ link_cb (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Total link backoff for %s was %s\n", - rls->is->commands[rls->is->ip].label, + rls->cmd->label, GNUNET_STRINGS_relative_time_to_string (rls->total_backoff, - GNUNET_YES)); + true)); } break; default: @@ -741,9 +799,16 @@ refresh_link_run (void *cls, const struct TALER_TESTING_Command *reveal_cmd; const struct TALER_TESTING_Command *melt_cmd; const struct TALER_TESTING_Command *coin_cmd; + const char *exchange_url; - (void) cmd; + rls->cmd = cmd; rls->is = is; + exchange_url = TALER_TESTING_get_exchange_url (is); + if (NULL == exchange_url) + { + GNUNET_break (0); + return; + } reveal_cmd = TALER_TESTING_interpreter_lookup_command (rls->is, rls->reveal_reference); if (NULL == reveal_cmd) @@ -763,21 +828,22 @@ refresh_link_run (void *cls, } /* find reserve_withdraw command */ + GNUNET_assert (melt_cmd->run == &melt_run); + rms = melt_cmd->cls; + coin_cmd = TALER_TESTING_interpreter_lookup_command (rls->is, + rms->coin_reference); + if (NULL == coin_cmd) { - rms = melt_cmd->cls; - coin_cmd = TALER_TESTING_interpreter_lookup_command (rls->is, - rms->coin_reference); - if (NULL == coin_cmd) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rls->is); + return; } const struct TALER_CoinSpendPrivateKeyP *coin_priv; - if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv - (coin_cmd, 0, &coin_priv)) + if (GNUNET_OK != + TALER_TESTING_get_trait_coin_priv (coin_cmd, + 0, + &coin_priv)) { GNUNET_break (0); TALER_TESTING_interpreter_fail (rls->is); @@ -785,10 +851,13 @@ refresh_link_run (void *cls, } /* finally, use private key from withdraw sign command */ - rls->rlh = TALER_EXCHANGE_link (is->exchange, - coin_priv, - &link_cb, - rls); + rls->rlh = TALER_EXCHANGE_link ( + TALER_TESTING_interpreter_get_context (is), + exchange_url, + coin_priv, + rms->refresh_data.melt_age_commitment_proof, + &link_cb, + rls); if (NULL == rls->rlh) { @@ -814,11 +883,8 @@ refresh_link_cleanup (void *cls, if (NULL != rls->rlh) { - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Command %u (%s) did not complete\n", - rls->is->ip, - cmd->label); + TALER_TESTING_command_incomplete (rls->is, + cmd->label); TALER_EXCHANGE_link_cancel (rls->rlh); rls->rlh = NULL; } @@ -832,19 +898,6 @@ refresh_link_cleanup (void *cls, /** - * Run the command. - * - * @param cls closure. - * @param cmd the command to execute. - * @param is the interpreter state. - */ -static void -melt_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is); - - -/** * Task scheduled to re-try #melt_run. * * @param cls a `struct RefreshMeltState` @@ -855,13 +908,7 @@ do_melt_retry (void *cls) struct RefreshMeltState *rms = cls; rms->retry_task = NULL; - rms->is->commands[rms->is->ip].last_req_time - = GNUNET_TIME_absolute_get (); - if (NULL != rms->refresh_data) - { - json_decref (rms->refresh_data); - rms->refresh_data = NULL; - } + TALER_TESTING_touch_cmd (rms->is); melt_run (rms, NULL, rms->is); @@ -874,20 +921,15 @@ do_melt_retry (void *cls) * CMD was set to do so. * * @param cls closure. - * @param hr HTTP response details - * @param noreveal_index choice by the exchange in the - * cut-and-choose protocol, UINT16_MAX on error. - * @param exchange_pub public key the exchange used for signing. + * @param mr melt response details */ static void melt_cb (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - uint32_t noreveal_index, - const struct TALER_ExchangePublicKeyP *exchange_pub) + const struct TALER_EXCHANGE_MeltResponse *mr) { struct RefreshMeltState *rms = cls; + const struct TALER_EXCHANGE_HttpResponse *hr = &mr->hr; - (void) exchange_pub; rms->rmh = NULL; if (rms->expected_response_code != hr->http_status) { @@ -910,44 +952,57 @@ melt_cb (void *cls, MAX_BACKOFF); rms->total_backoff = GNUNET_TIME_relative_add (rms->total_backoff, rms->backoff); - rms->is->commands[rms->is->ip].num_tries++; + TALER_TESTING_inc_tries (rms->is); rms->retry_task = GNUNET_SCHEDULER_add_delayed (rms->backoff, &do_melt_retry, rms); return; } } - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d to command %s in %s:%u\n", - hr->http_status, - (int) hr->ec, - rms->is->commands[rms->is->ip].label, - __FILE__, - __LINE__); - json_dumpf (hr->reply, - stderr, - 0); - TALER_TESTING_interpreter_fail (rms->is); + TALER_TESTING_unexpected_status_with_body (rms->is, + hr->http_status, + rms->expected_response_code, + hr->reply); return; } - rms->noreveal_index = noreveal_index; + if (MHD_HTTP_OK == hr->http_status) + { + rms->noreveal_index = mr->details.ok.noreveal_index; + if (mr->details.ok.num_mbds != rms->num_fresh_coins) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rms->is); + return; + } + GNUNET_free (rms->mbds); + rms->mbds = GNUNET_new_array ( + mr->details.ok.num_mbds, + struct TALER_EXCHANGE_MeltBlindingDetail); + for (unsigned int i = 0; i<mr->details.ok.num_mbds; i++) + TALER_denom_ewv_copy (&rms->mbds[i].alg_value, + &mr->details.ok.mbds[i].alg_value); + } if (0 != rms->total_backoff.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Total melt backoff for %s was %s\n", - rms->is->commands[rms->is->ip].label, + rms->cmd->label, GNUNET_STRINGS_relative_time_to_string (rms->total_backoff, - GNUNET_YES)); + true)); } - if (GNUNET_YES == rms->double_melt) + if (rms->double_melt) { TALER_LOG_DEBUG ("Doubling the melt (%s)\n", - rms->is->commands[rms->is->ip].label); - rms->rmh = TALER_EXCHANGE_melt (rms->is->exchange, - rms->refresh_data, - &melt_cb, - rms); - rms->double_melt = GNUNET_NO; + rms->cmd->label); + rms->rmh = TALER_EXCHANGE_melt ( + TALER_TESTING_interpreter_get_context (rms->is), + TALER_TESTING_get_exchange_url (rms->is), + TALER_TESTING_get_keys (rms->is), + &rms->rms, + &rms->refresh_data, + &melt_cb, + rms); + rms->double_melt = false; return; } TALER_TESTING_interpreter_next (rms->is); @@ -974,29 +1029,34 @@ melt_run (void *cls, }; const char **melt_fresh_amounts; - (void) cmd; + rms->cmd = cmd; if (NULL == (melt_fresh_amounts = rms->melt_fresh_amounts)) melt_fresh_amounts = default_melt_fresh_amounts; rms->is = is; rms->noreveal_index = UINT16_MAX; + TALER_refresh_master_setup_random (&rms->rms); for (num_fresh_coins = 0; NULL != melt_fresh_amounts[num_fresh_coins]; num_fresh_coins++) ; rms->num_fresh_coins = num_fresh_coins; - rms->fresh_pks = GNUNET_new_array - (num_fresh_coins, - struct TALER_EXCHANGE_DenomPublicKey); + rms->fresh_pks = GNUNET_new_array ( + num_fresh_coins, + struct TALER_EXCHANGE_DenomPublicKey); { struct TALER_Amount melt_amount; struct TALER_Amount fresh_amount; + const struct TALER_AgeCommitmentProof *age_commitment_proof = NULL; + const struct TALER_AgeCommitmentHash *h_age_commitment = NULL; const struct TALER_DenominationSignature *melt_sig; const struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub; const struct TALER_TESTING_Command *coin_command; + bool age_restricted_denom; if (NULL == (coin_command - = TALER_TESTING_interpreter_lookup_command - (is, rms->coin_reference))) + = TALER_TESTING_interpreter_lookup_command ( + is, + rms->coin_reference))) { GNUNET_break (0); TALER_TESTING_interpreter_fail (rms->is); @@ -1012,8 +1072,26 @@ melt_run (void *cls, TALER_TESTING_interpreter_fail (rms->is); return; } + if (GNUNET_OK != + TALER_TESTING_get_trait_age_commitment_proof (coin_command, + 0, + &age_commitment_proof)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rms->is); + return; + } if (GNUNET_OK != + TALER_TESTING_get_trait_h_age_commitment (coin_command, + 0, + &h_age_commitment)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (rms->is); + return; + } + if (GNUNET_OK != TALER_TESTING_get_trait_denom_sig (coin_command, 0, &melt_sig)) @@ -1031,9 +1109,14 @@ 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; + melt_amount = melt_denom_pub->fees.refresh; + age_restricted_denom = melt_denom_pub->key.age_mask.bits != 0; + GNUNET_assert (age_restricted_denom == (NULL != age_commitment_proof)); + GNUNET_assert ((NULL == age_commitment_proof) || + (0 < age_commitment_proof->commitment.num)); for (unsigned int i = 0; i<num_fresh_coins; i++) { const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk; @@ -1045,12 +1128,14 @@ melt_run (void *cls, GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to parse amount `%s' at index %u\n", - melt_fresh_amounts[i], i); + melt_fresh_amounts[i], + i); TALER_TESTING_interpreter_fail (rms->is); return; } - fresh_pk = TALER_TESTING_find_pk - (TALER_EXCHANGE_get_keys (is->exchange), &fresh_amount); + fresh_pk = TALER_TESTING_find_pk (TALER_TESTING_get_keys (rms->is), + &fresh_amount, + age_restricted_denom); if (NULL == fresh_pk) { GNUNET_break (0); @@ -1065,30 +1150,49 @@ melt_run (void *cls, GNUNET_assert (0 <= TALER_amount_add (&melt_amount, &melt_amount, - &fresh_pk->fee_withdraw)); + &fresh_pk->fees.withdraw)); rms->fresh_pks[i] = *fresh_pk; /* Make a deep copy of the RSA key */ - TALER_denom_pub_deep_copy (&rms->fresh_pks[i].key, - &fresh_pk->key); + TALER_denom_pub_copy (&rms->fresh_pks[i].key, + &fresh_pk->key); } /* end for */ - GNUNET_assert (NULL == rms->refresh_data); - rms->refresh_data - = TALER_EXCHANGE_refresh_prepare (rms->melt_priv, - &melt_amount, - melt_sig, - melt_denom_pub, - num_fresh_coins, - rms->fresh_pks); - if (NULL == rms->refresh_data) + + rms->refresh_data.melt_priv = *rms->melt_priv; + GNUNET_CRYPTO_eddsa_key_get_public (&rms->melt_priv->eddsa_priv, + &rms->melt_pub.eddsa_pub); + rms->refresh_data.melt_amount = melt_amount; + rms->refresh_data.melt_sig = *melt_sig; + rms->refresh_data.melt_pk = *melt_denom_pub; + + if (NULL != age_commitment_proof) { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rms->is); - return; + GNUNET_assert (NULL != h_age_commitment); + rms->refresh_data.melt_age_commitment_proof = age_commitment_proof; + rms->refresh_data.melt_h_age_commitment = h_age_commitment; } - rms->rmh = TALER_EXCHANGE_melt (is->exchange, - rms->refresh_data, - &melt_cb, - rms); + rms->refresh_data.fresh_pks = rms->fresh_pks; + rms->refresh_data.fresh_pks_len = num_fresh_coins; + + GNUNET_assert (age_restricted_denom == + (NULL != age_commitment_proof)); + GNUNET_assert ((NULL == age_commitment_proof) || + (0 < age_commitment_proof->commitment.num)); + + rms->che.type = TALER_EXCHANGE_CTT_MELT; + rms->che.amount = melt_amount; + if (NULL != age_commitment_proof) + rms->che.details.melt.h_age_commitment = *h_age_commitment; + else + rms->che.details.melt.no_hac = true; + + rms->rmh = TALER_EXCHANGE_melt ( + TALER_TESTING_interpreter_get_context (is), + TALER_TESTING_get_exchange_url (is), + TALER_TESTING_get_keys (is), + &rms->rms, + &rms->refresh_data, + &melt_cb, + rms); if (NULL == rms->rmh) { @@ -1116,9 +1220,8 @@ melt_cleanup (void *cls, (void) cmd; if (NULL != rms->rmh) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Command %u (%s) did not complete\n", - rms->is->ip, rms->is->commands[rms->is->ip].label); + TALER_TESTING_command_incomplete (rms->is, + cmd->label); TALER_EXCHANGE_melt_cancel (rms->rmh); rms->rmh = NULL; } @@ -1131,11 +1234,14 @@ melt_cleanup (void *cls, { for (unsigned int i = 0; i < rms->num_fresh_coins; i++) TALER_denom_pub_free (&rms->fresh_pks[i].key); + GNUNET_free (rms->fresh_pks); + } + if (NULL != rms->mbds) + { + for (unsigned int i = 0; i < rms->num_fresh_coins; i++) + TALER_denom_ewv_free (&rms->mbds[i].alg_value); + GNUNET_free (rms->mbds); } - GNUNET_free (rms->fresh_pks); - rms->fresh_pks = NULL; - json_decref (rms->refresh_data); - rms->refresh_data = NULL; GNUNET_free (rms->melt_fresh_amounts); GNUNET_free (rms); } @@ -1169,6 +1275,21 @@ melt_traits (void *cls, &rms->fresh_pks[index]), TALER_TESTING_make_trait_coin_priv (0, rms->melt_priv), + TALER_TESTING_make_trait_coin_pub (0, + &rms->melt_pub), + TALER_TESTING_make_trait_coin_history (0, + &rms->che), + TALER_TESTING_make_trait_age_commitment_proof ( + index, + rms->refresh_data.melt_age_commitment_proof), + TALER_TESTING_make_trait_h_age_commitment ( + index, + rms->refresh_data.melt_h_age_commitment), + TALER_TESTING_make_trait_refresh_secret (&rms->rms), + (NULL != rms->mbds) + ? TALER_TESTING_make_trait_exchange_wd_value (index, + &rms->mbds[index].alg_value) + : TALER_TESTING_trait_end (), TALER_TESTING_trait_end () }; @@ -1242,7 +1363,8 @@ TALER_TESTING_cmd_melt (const char *label, rms = GNUNET_new (struct RefreshMeltState); rms->coin_reference = coin_reference; rms->expected_response_code = expected_response_code; - va_start (ap, expected_response_code); + va_start (ap, + expected_response_code); GNUNET_assert (GNUNET_OK == parse_amounts (rms, ap)); va_end (ap); @@ -1272,8 +1394,9 @@ TALER_TESTING_cmd_melt_double (const char *label, rms = GNUNET_new (struct RefreshMeltState); rms->coin_reference = coin_reference; rms->expected_response_code = expected_response_code; - rms->double_melt = GNUNET_YES; - va_start (ap, expected_response_code); + rms->double_melt = true; + va_start (ap, + expected_response_code); GNUNET_assert (GNUNET_OK == parse_amounts (rms, ap)); va_end (ap); @@ -1322,11 +1445,18 @@ refresh_reveal_traits (void *cls, if (index >= rrs->num_fresh_coins) return GNUNET_SYSERR; + { struct TALER_TESTING_Trait traits[] = { TALER_TESTING_make_trait_coin_priv ( index, &rrs->fresh_coins[index].coin_priv), + TALER_TESTING_make_trait_age_commitment_proof ( + index, + rrs->fresh_coins[index].age_commitment_proof), + TALER_TESTING_make_trait_h_age_commitment ( + index, + &rrs->fresh_coins[index].h_age_commitment), TALER_TESTING_make_trait_denom_pub ( index, rrs->fresh_coins[index].pk), @@ -1340,6 +1470,8 @@ refresh_reveal_traits (void *cls, &rrs->num_fresh_coins), TALER_TESTING_make_trait_fresh_coins ( (const struct TALER_TESTING_FreshCoinData **) &rrs->fresh_coins), + TALER_TESTING_make_trait_planchet_secrets (index, + &rrs->psa[index]), TALER_TESTING_trait_end () }; |