exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit a860cbb1be59263b1e81827158d79092a949d14f
parent a19a146628156a3541f8f46286c03c2e6e1e28d8
Author: Özgür Kesim <oec@codeblau.de>
Date:   Tue,  6 May 2025 12:43:47 +0200

[lib,testing] use new refresh API (melt/reveal-melt); refactoring and fixes

Diffstat:
Msrc/benchmark/taler-aggregator-benchmark.c | 2+-
Msrc/benchmark/taler-exchange-benchmark.c | 15+++++----------
Msrc/exchange/taler-exchange-httpd_blinding-prepare.c | 4+---
Msrc/exchange/taler-exchange-httpd_csr.c | 8++++----
Msrc/exchange/taler-exchange-httpd_link.c | 2+-
Msrc/exchange/taler-exchange-httpd_melt_v27.c | 30+++++++++++++++++++++++++++---
Msrc/exchange/taler-exchange-httpd_recoup-refresh.c | 6+++---
Msrc/exchange/taler-exchange-httpd_recoup.c | 6+++---
Msrc/exchange/taler-exchange-httpd_refreshes_reveal.c | 6+++---
Msrc/exchange/taler-exchange-httpd_reveal-melt.c | 43++++++++++++++++++++-----------------------
Msrc/exchange/taler-exchange-httpd_reveal-withdraw.c | 2+-
Msrc/exchangedb/exchange_do_refresh.sql | 2++
Msrc/exchangedb/perf_deposits_get_ready.c | 2+-
Msrc/exchangedb/perf_get_link_data.c | 2+-
Msrc/exchangedb/perf_select_refunds_by_coin.c | 2+-
Msrc/exchangedb/pg_ensure_coin_known.c | 20++++++++++----------
Msrc/exchangedb/pg_insert_records_by_table.c | 2+-
Msrc/exchangedb/pg_insert_refresh_reveal.c | 2+-
Msrc/exchangedb/test_exchangedb.c | 2+-
Msrc/include/taler_crypto_lib.h | 57+++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/include/taler_exchange_service.h | 223++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/include/taler_exchangedb_plugin.h | 6+++---
Msrc/include/taler_json_lib.h | 29++++++++++++++++++++++-------
Msrc/include/taler_pq_lib.h | 10+++++-----
Msrc/include/taler_testing_lib.h | 34+++++-----------------------------
Msrc/json/json_helper.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Msrc/json/json_pack.c | 4++--
Msrc/lib/exchange_api_blinding_prepare.c | 21++++++++++-----------
Msrc/lib/exchange_api_csr_melt.c | 12++++++------
Msrc/lib/exchange_api_link.c | 14+++++++-------
Msrc/lib/exchange_api_melt.c | 12++++++------
Msrc/lib/exchange_api_melt_v27.c | 170++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/lib/exchange_api_recoup.c | 10+++++-----
Msrc/lib/exchange_api_recoup_refresh.c | 10+++++-----
Msrc/lib/exchange_api_refresh_common.c | 125+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/lib/exchange_api_refresh_common.h | 29+++++++++++++++++++++++------
Msrc/lib/exchange_api_refreshes_reveal.c | 6+++---
Msrc/lib/exchange_api_reveal_melt.c | 155+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/lib/exchange_api_withdraw.c | 39++++++++++++++++++++++++---------------
Msrc/pq/pq_query_helper.c | 14+++++++-------
Msrc/pq/pq_result_helper.c | 4++--
Msrc/pq/test_pq.c | 39++++++++++++++++++++++++++++++++++++++-
Msrc/testing/test_auditor_api.c | 6+++---
Msrc/testing/test_exchange_api.c | 26++++++--------------------
Msrc/testing/test_exchange_api_age_restriction.c | 11++---------
Msrc/testing/test_exchange_api_twisted.c | 6+++++-
Msrc/testing/testing_api_cmd_age_withdraw.c | 12++++++------
Msrc/testing/testing_api_cmd_batch_withdraw.c | 11++++++-----
Msrc/testing/testing_api_cmd_insert_deposit.c | 2+-
Msrc/testing/testing_api_cmd_recoup.c | 8++++----
Msrc/testing/testing_api_cmd_recoup_refresh.c | 8++++----
Msrc/testing/testing_api_cmd_refresh.c | 643+++++++++++++++++++++----------------------------------------------------------
Msrc/testing/testing_api_cmd_withdraw.c | 9+++++----
Msrc/util/age_restriction.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/util/crypto.c | 12++++++------
Msrc/util/denom.c | 18+++++++++---------
Msrc/util/test_crypto.c | 8++++----
Msrc/util/test_helper_cs.c | 8++++----
Msrc/util/test_helper_rsa.c | 6+++---
59 files changed, 1071 insertions(+), 1052 deletions(-)

diff --git a/src/benchmark/taler-aggregator-benchmark.c b/src/benchmark/taler-aggregator-benchmark.c @@ -493,7 +493,7 @@ run (void *cls, struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_AgeCommitmentHash hac; union GNUNET_CRYPTO_BlindingSecretP bks; - const struct TALER_ExchangeWithdrawValues *alg_values; + const struct TALER_ExchangeBlindingValues *alg_values; RANDOMIZE (&coin_pub); GNUNET_assert (GNUNET_OK == diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c @@ -320,16 +320,11 @@ run (void *cls, MHD_HTTP_OK, NULL)); unit[3] = - TALER_TESTING_cmd_refresh_reveal_with_retry ( - TALER_TESTING_cmd_refresh_reveal (rl, - ml, - MHD_HTTP_OK)); - unit[4] = - TALER_TESTING_cmd_refresh_link_with_retry ( - TALER_TESTING_cmd_refresh_link ("link", - rl, - MHD_HTTP_OK)); - unit[5] = TALER_TESTING_cmd_end (); + TALER_TESTING_cmd_melt_reveal_with_retry ( + TALER_TESTING_cmd_melt_reveal (rl, + ml, + MHD_HTTP_OK)); + unit[4] = TALER_TESTING_cmd_end (); } else unit[2] = TALER_TESTING_cmd_end (); diff --git a/src/exchange/taler-exchange-httpd_blinding-prepare.c b/src/exchange/taler-exchange-httpd_blinding-prepare.c @@ -144,8 +144,6 @@ TEH_handler_blinding_prepare (struct TEH_RequestContext *rc, num, cs_indices, nonces); - - { struct TEH_KeyStateHandle *ksh; struct GNUNET_CRYPTO_CSPublicRPairP r_pubs[num]; @@ -164,7 +162,7 @@ TEH_handler_blinding_prepare (struct TEH_RequestContext *rc, num, h_denom_pubs, nonces, - false, + is_melt, r_pubs, &err_idx); switch (ec) diff --git a/src/exchange/taler-exchange-httpd_csr.c b/src/exchange/taler-exchange-httpd_csr.c @@ -203,12 +203,12 @@ TEH_handler_csr_melt (struct TEH_RequestContext *rc, for (unsigned int i = 0; i < csr_requests_num; i++) { json_t *csr_obj; - struct TALER_ExchangeWithdrawValues exw = { + struct TALER_ExchangeBlindingValues exw = { .blinding_inputs = &ewvs[i] }; csr_obj = GNUNET_JSON_PACK ( - TALER_JSON_pack_exchange_withdraw_values ("ewv", + TALER_JSON_pack_exchange_blinding_values ("ewv", &exw)); GNUNET_assert (NULL != csr_obj); GNUNET_assert (0 == @@ -336,14 +336,14 @@ TEH_handler_csr_withdraw (struct TEH_RequestContext *rc, } } { - struct TALER_ExchangeWithdrawValues exw = { + struct TALER_ExchangeBlindingValues exw = { .blinding_inputs = &ewv }; return TALER_MHD_REPLY_JSON_PACK ( rc->connection, MHD_HTTP_OK, - TALER_JSON_pack_exchange_withdraw_values ("ewv", + TALER_JSON_pack_exchange_blinding_values ("ewv", &exw)); } } diff --git a/src/exchange/taler-exchange-httpd_link.c b/src/exchange/taler-exchange-httpd_link.c @@ -88,7 +88,7 @@ handle_link_data (void *cls, &pos->ev_sig), GNUNET_JSON_pack_uint64 ("coin_idx", pos->coin_refresh_offset), - TALER_JSON_pack_exchange_withdraw_values ("ewv", + TALER_JSON_pack_exchange_blinding_values ("ewv", &pos->alg_values), GNUNET_JSON_pack_data_auto ("link_sig", &pos->orig_coin_link_sig), diff --git a/src/exchange/taler-exchange-httpd_melt_v27.c b/src/exchange/taler-exchange-httpd_melt_v27.c @@ -1586,7 +1586,7 @@ phase_run_transaction ( /* first, make sure coin is known */ if (! mc->coin_is_dirty) { - MHD_RESULT mhd_ret = MHD_NO; + MHD_RESULT mhd_ret = -1; enum GNUNET_DB_QueryStatus qs; for (unsigned int tries = 0; tries<MAX_TRANSACTION_COMMIT_RETRIES; tries++) @@ -1601,6 +1601,18 @@ phase_run_transaction ( if (0 > qs) { GNUNET_break (0); + /* Check if an answer has been queued */ + switch (mhd_ret) + { + case MHD_NO: + mc->phase = MELT_PHASE_RETURN_NO; + return; + case MHD_YES: + mc->phase = MELT_PHASE_RETURN_YES; + return; + default: + /* ignore */ + } SET_ERROR (mc, MELT_ERROR_DB_MAKE_COIN_KNOW_FAILURE); return; @@ -1609,7 +1621,7 @@ phase_run_transaction ( /* run main database transaction */ { - MHD_RESULT mhd_ret; + MHD_RESULT mhd_ret = -1; enum GNUNET_GenericReturnValue ret; enum MeltPhase current_phase = mc->phase; @@ -1623,9 +1635,21 @@ phase_run_transaction ( mc); if (GNUNET_OK != ret) { + GNUNET_break (0); + /* Check if an answer has been queued */ + switch (mhd_ret) + { + case MHD_NO: + mc->phase = MELT_PHASE_RETURN_NO; + return; + case MHD_YES: + mc->phase = MELT_PHASE_RETURN_YES; + return; + default: + /* ignore */ + } GNUNET_assert (MELT_ERROR_NONE != mc->error.code); GNUNET_assert (MELT_PHASE_GENERATE_REPLY_ERROR == mc->phase); - GNUNET_break (0); return; } /** diff --git a/src/exchange/taler-exchange-httpd_recoup-refresh.c b/src/exchange/taler-exchange-httpd_recoup-refresh.c @@ -174,7 +174,7 @@ static MHD_RESULT verify_and_execute_recoup_refresh ( struct MHD_Connection *connection, const struct TALER_CoinPublicInfo *coin, - const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_ExchangeBlindingValues *exchange_vals, const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const union GNUNET_CRYPTO_BlindSessionNonce *nonce, const struct TALER_CoinSpendSignatureP *coin_sig) @@ -375,7 +375,7 @@ TEH_handler_recoup_refresh (struct MHD_Connection *connection, struct TALER_CoinPublicInfo coin = {0}; union GNUNET_CRYPTO_BlindingSecretP coin_bks; struct TALER_CoinSpendSignatureP coin_sig; - struct TALER_ExchangeWithdrawValues exchange_vals; + struct TALER_ExchangeBlindingValues exchange_vals; union GNUNET_CRYPTO_BlindSessionNonce nonce; bool no_nonce; struct GNUNET_JSON_Specification spec[] = { @@ -383,7 +383,7 @@ TEH_handler_recoup_refresh (struct MHD_Connection *connection, &coin.denom_pub_hash), TALER_JSON_spec_denom_sig ("denom_sig", &coin.denom_sig), - TALER_JSON_spec_exchange_withdraw_values ("ewv", + TALER_JSON_spec_exchange_blinding_values ("ewv", &exchange_vals), GNUNET_JSON_spec_fixed_auto ("coin_blind_key_secret", &coin_bks), diff --git a/src/exchange/taler-exchange-httpd_recoup.c b/src/exchange/taler-exchange-httpd_recoup.c @@ -178,7 +178,7 @@ static MHD_RESULT verify_and_execute_recoup ( struct MHD_Connection *connection, const struct TALER_CoinPublicInfo *coin, - const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_ExchangeBlindingValues *exchange_vals, const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_HashBlindedPlanchetsP *h_planchets, const union GNUNET_CRYPTO_BlindSessionNonce *nonce, @@ -383,7 +383,7 @@ TEH_handler_recoup (struct MHD_Connection *connection, struct TALER_CoinPublicInfo coin; union GNUNET_CRYPTO_BlindingSecretP coin_bks; struct TALER_CoinSpendSignatureP coin_sig; - struct TALER_ExchangeWithdrawValues exchange_vals; + struct TALER_ExchangeBlindingValues exchange_vals; struct TALER_HashBlindedPlanchetsP h_planchets; union GNUNET_CRYPTO_BlindSessionNonce nonce; bool no_nonce; @@ -394,7 +394,7 @@ TEH_handler_recoup (struct MHD_Connection *connection, &coin.denom_sig), GNUNET_JSON_spec_fixed_auto ("h_planchets", &h_planchets), - TALER_JSON_spec_exchange_withdraw_values ("ewv", + TALER_JSON_spec_exchange_blinding_values ("ewv", &exchange_vals), GNUNET_JSON_spec_fixed_auto ("coin_blind_key_secret", &coin_bks), diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c b/src/exchange/taler-exchange-httpd_refreshes_reveal.c @@ -201,7 +201,7 @@ check_commitment (struct RevealContext *rctx, for (unsigned int j = 0; j<rctx->num_fresh_coins; j++) { const struct TALER_DenominationPublicKey *dk = &rctx->dks[j]->denom_pub; - struct TALER_ExchangeWithdrawValues *alg_values + struct TALER_ExchangeBlindingValues *alg_values = &rctx->rrcs[j].exchange_vals; struct GNUNET_CRYPTO_BlindingInputValues *bi; @@ -282,7 +282,7 @@ check_commitment (struct RevealContext *rctx, struct TALER_RefreshCoinData *rcd = &rce->new_coins[j]; struct TALER_CoinSpendPrivateKeyP coin_priv; union GNUNET_CRYPTO_BlindingSecretP bks; - const struct TALER_ExchangeWithdrawValues *alg_value + const struct TALER_ExchangeBlindingValues *alg_value = &rctx->rrcs[j].exchange_vals; struct TALER_PlanchetDetail pd = {0}; struct TALER_CoinPubHashP c_hash; @@ -865,7 +865,7 @@ cleanup: for (unsigned int i = 0; i<num_fresh_coins; i++) { struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i]; - struct TALER_ExchangeWithdrawValues *alg_values + struct TALER_ExchangeBlindingValues *alg_values = &rrcs[i].exchange_vals; GNUNET_free (alg_values->blinding_inputs); diff --git a/src/exchange/taler-exchange-httpd_reveal-melt.c b/src/exchange/taler-exchange-httpd_reveal-melt.c @@ -209,20 +209,11 @@ calculate_blinded_detail ( /* calculate age commitment hash */ if (! no_age_commitment) { - struct GNUNET_HashCode salt; struct TALER_AgeCommitment nac; - GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_kdf (&salt, - sizeof (salt), - "age commitment", - strlen ("age commitment"), - secret, - sizeof(*secret), - NULL, 0)); - TALER_age_commitment_derive (old_age_commitment, - &salt, - &nac); + TALER_age_commitment_derive_from_secret (old_age_commitment, + secret, + &nac); TALER_age_commitment_hash (&nac, &ach); TALER_age_commitment_free (&nac); @@ -236,24 +227,31 @@ calculate_blinded_detail ( struct GNUNET_CRYPTO_BlindingInputValues bi = { .cipher = denom_key->denom_pub.bsign_pub_key->cipher }; - struct TALER_ExchangeWithdrawValues alg_values = { + struct TALER_ExchangeBlindingValues blinding_values = { .blinding_inputs = &bi }; - if (GNUNET_CRYPTO_BSA_CS == bi.cipher) + switch (bi.cipher) { + case GNUNET_CRYPTO_BSA_CS: GNUNET_assert (NULL != r_pub); GNUNET_assert (NULL != nonce); bi.details.cs_values = *r_pub; + break; + case GNUNET_CRYPTO_BSA_RSA: + break; + default: + GNUNET_assert (0); } + TALER_planchet_blinding_secret_create (secret, - &alg_values, + &blinding_values, &bks); TALER_planchet_setup_coin_priv (secret, - &alg_values, + &blinding_values, &coin_priv); ret = TALER_planchet_prepare (&denom_key->denom_pub, - &alg_values, + &blinding_values, &bks, nonce, &coin_priv, @@ -412,17 +410,17 @@ verify_commitment ( { size_t sig_idx = 0; - for (uint8_t gamma=0; gamma < TALER_CNC_KAPPA; gamma++) + for (uint8_t k=0; k < TALER_CNC_KAPPA; k++) { - if (rf->noreveal_index == gamma) + if (rf->noreveal_index == k) continue; if (GNUNET_OK != TALER_wallet_refresh_nonce_verify ( &rf->coin.coin_pub, - &kappa_nonces.tuple[gamma], + &kappa_nonces.tuple[k], rf->num_coins, denoms_h, - gamma, + k, &signatures[sig_idx++])) { GNUNET_break_op (0); @@ -434,7 +432,6 @@ verify_commitment ( } } - /** * In the following scope, we start collecting blinded coin planchet hashes, * either those persisted from the original request to /melt, or we @@ -447,7 +444,7 @@ verify_commitment ( */ { struct TALER_KappaHashBlindedPlanchetsP kappa_planchets_h; - union GNUNET_CRYPTO_BlindSessionNonce b_nonces[0 < cs_count ?cs_count : 1]; + union GNUNET_CRYPTO_BlindSessionNonce b_nonces[GNUNET_NZL (cs_count)]; size_t cs_idx = 0; /* [0...cs_count) */ uint8_t sig_idx = 0; /* [0..KAPPA_MINUS_1) */ diff --git a/src/exchange/taler-exchange-httpd_reveal-withdraw.c b/src/exchange/taler-exchange-httpd_reveal-withdraw.c @@ -239,7 +239,7 @@ calculate_blinded_hash ( struct GNUNET_CRYPTO_BlindingInputValues bi = { .cipher = denom_key->denom_pub.bsign_pub_key->cipher }; - struct TALER_ExchangeWithdrawValues alg_values = { + struct TALER_ExchangeBlindingValues alg_values = { .blinding_inputs = &bi }; diff --git a/src/exchangedb/exchange_do_refresh.sql b/src/exchangedb/exchange_do_refresh.sql @@ -125,6 +125,7 @@ INSERT INTO exchange.refresh ,amount_with_fee ,noreveal_index ,refresh_seed + ,blinding_seed ,cs_r_values ,cs_r_choices ,selected_h @@ -140,6 +141,7 @@ INSERT INTO exchange.refresh ,in_amount_with_fee ,in_noreveal_index ,in_refresh_seed + ,in_blinding_seed ,in_cs_r_values ,in_cs_r_choices ,in_selected_h diff --git a/src/exchangedb/perf_deposits_get_ready.c b/src/exchangedb/perf_deposits_get_ready.c @@ -207,7 +207,7 @@ run (void *cls) .cipher = GNUNET_CRYPTO_BSA_RSA, .rc = 0 }; - struct TALER_ExchangeWithdrawValues alg_values = { + struct TALER_ExchangeBlindingValues alg_values = { .blinding_inputs = &bi }; diff --git a/src/exchangedb/perf_get_link_data.c b/src/exchangedb/perf_get_link_data.c @@ -213,7 +213,7 @@ run (void *cls) .cipher = GNUNET_CRYPTO_BSA_RSA, .rc = 0 }; - struct TALER_ExchangeWithdrawValues alg_values = { + struct TALER_ExchangeBlindingValues alg_values = { .blinding_inputs = &bi }; struct TALER_DenomFeeSet fees; diff --git a/src/exchangedb/perf_select_refunds_by_coin.c b/src/exchangedb/perf_select_refunds_by_coin.c @@ -221,7 +221,7 @@ run (void *cls) .cipher = GNUNET_CRYPTO_BSA_RSA, .rc = 0 }; - struct TALER_ExchangeWithdrawValues alg_values = { + struct TALER_ExchangeBlindingValues alg_values = { .blinding_inputs = &bi }; struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO; diff --git a/src/exchangedb/pg_ensure_coin_known.c b/src/exchangedb/pg_ensure_coin_known.c @@ -37,8 +37,8 @@ TEH_PG_ensure_coin_known (void *cls, struct PostgresClosure *pg = cls; enum GNUNET_DB_QueryStatus qs; bool existed; - bool is_denom_pub_hash_null = false; - bool is_age_hash_null = false; + bool no_denom_pub_hash; + bool no_age_commitment_hash; struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub), GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash), @@ -56,11 +56,11 @@ TEH_PG_ensure_coin_known (void *cls, GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", denom_hash), - &is_denom_pub_hash_null), + &no_denom_pub_hash), GNUNET_PQ_result_spec_allow_null ( GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", h_age_commitment), - &is_age_hash_null), + &no_age_commitment_hash), GNUNET_PQ_result_spec_end }; @@ -136,17 +136,17 @@ TEH_PG_ensure_coin_known (void *cls, break; /* continued below */ } - if ( (! is_denom_pub_hash_null) && - (0 != GNUNET_memcmp (&denom_hash->hash, - &coin->denom_pub_hash.hash)) ) + if ( (! no_denom_pub_hash) && + (0 != GNUNET_memcmp (denom_hash, + &coin->denom_pub_hash)) ) { GNUNET_break_op (0); return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT; } - if (is_age_hash_null != coin->no_age_commitment) + if (no_age_commitment_hash != coin->no_age_commitment) { - if (is_age_hash_null) + if (no_age_commitment_hash) { GNUNET_break_op (0); return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL; @@ -157,7 +157,7 @@ TEH_PG_ensure_coin_known (void *cls, return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL; } } - else if ( (! is_age_hash_null) && + else if ( (! no_age_commitment_hash) && (0 != GNUNET_memcmp (h_age_commitment, &coin->h_age_commitment)) ) { diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c @@ -900,7 +900,7 @@ irbt_cb_table_refresh_revealed_coins ( GNUNET_PQ_query_param_auto_from_type (&h_coin_ev), TALER_PQ_query_param_blinded_denom_sig ( &td->details.refresh_revealed_coins.ev_sig), - TALER_PQ_query_param_exchange_withdraw_values ( + TALER_PQ_query_param_exchange_blinding_values ( &td->details.refresh_revealed_coins.ewv), GNUNET_PQ_query_param_uint64 ( &td->details.refresh_revealed_coins.denominations_serial), diff --git a/src/exchangedb/pg_insert_refresh_reveal.c b/src/exchangedb/pg_insert_refresh_reveal.c @@ -68,7 +68,7 @@ TEH_PG_insert_refresh_reveal ( GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig), GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub), TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet), - TALER_PQ_query_param_exchange_withdraw_values (&rrc->exchange_vals), + TALER_PQ_query_param_exchange_blinding_values (&rrc->exchange_vals), GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash), TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig), GNUNET_PQ_query_param_end diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c @@ -1236,7 +1236,7 @@ run (void *cls) struct TALER_PlanchetMasterSecretP ps; union GNUNET_CRYPTO_BlindingSecretP bks; struct TALER_Amount amount_with_fee; - const struct TALER_ExchangeWithdrawValues *alg_values + const struct TALER_ExchangeBlindingValues *alg_values = TALER_denom_ewv_rsa_singleton (); memset (&deposit, diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h @@ -1555,7 +1555,7 @@ struct TALER_TrackTransferDetails /** * @brief Inputs needed from the exchange for blind signing. */ -struct TALER_ExchangeWithdrawValues +struct TALER_ExchangeBlindingValues { /** @@ -1600,7 +1600,7 @@ struct TALER_BlindingPrepareResponse * * @return singleton to use for RSA blinding */ -const struct TALER_ExchangeWithdrawValues * +const struct TALER_ExchangeBlindingValues * TALER_denom_ewv_rsa_singleton (void); @@ -1613,8 +1613,8 @@ TALER_denom_ewv_rsa_singleton (void); */ void TALER_denom_ewv_copy ( - struct TALER_ExchangeWithdrawValues *bi_dst, - const struct TALER_ExchangeWithdrawValues *bi_src); + struct TALER_ExchangeBlindingValues *bi_dst, + const struct TALER_ExchangeBlindingValues *bi_src); /** @@ -1626,7 +1626,7 @@ TALER_denom_ewv_copy ( void TALER_planchet_setup_coin_priv ( const struct TALER_PlanchetMasterSecretP *ps, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, struct TALER_CoinSpendPrivateKeyP *coin_priv); @@ -1799,7 +1799,7 @@ TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub); * @param[in] ewv input values to free */ void -TALER_denom_ewv_free (struct TALER_ExchangeWithdrawValues *ewv); +TALER_denom_ewv_free (struct TALER_ExchangeBlindingValues *ewv); /** @@ -1844,7 +1844,7 @@ TALER_denom_blind (const struct TALER_DenominationPublicKey *dk, const union GNUNET_CRYPTO_BlindSessionNonce *nonce, const struct TALER_AgeCommitmentHash *age_commitment_hash, const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, struct TALER_CoinPubHashP *c_hash, struct TALER_BlindedPlanchet *blinded_planchet); @@ -1882,7 +1882,7 @@ TALER_denom_sig_unblind ( const struct TALER_BlindedDenominationSignature *bdenom_sig, const union GNUNET_CRYPTO_BlindingSecretP *bks, const struct TALER_CoinPubHashP *c_hash, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, const struct TALER_DenominationPublicKey *denom_pub); @@ -2489,7 +2489,7 @@ TALER_refresh_expand_kappa_nonces ( void TALER_planchet_blinding_secret_create ( const struct TALER_PlanchetMasterSecretP *ps, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, union GNUNET_CRYPTO_BlindingSecretP *bks); @@ -2511,7 +2511,7 @@ TALER_planchet_blinding_secret_create ( enum GNUNET_GenericReturnValue TALER_planchet_prepare ( const struct TALER_DenominationPublicKey *dk, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, const union GNUNET_CRYPTO_BlindingSecretP *bks, const union GNUNET_CRYPTO_BlindSessionNonce *nonce, const struct TALER_CoinSpendPrivateKeyP *coin_priv, @@ -2561,7 +2561,7 @@ TALER_planchet_to_coin ( const struct TALER_CoinSpendPrivateKeyP *coin_priv, const struct TALER_AgeCommitmentHash *ach, const struct TALER_CoinPubHashP *c_hash, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, struct TALER_FreshCoin *coin); @@ -6773,11 +6773,27 @@ TALER_age_commitment_proof_derive ( /** + * @brief Derives another, equivalent age commitment with proof for a given one, + * for a given planchet secret of a new coin. + * + * @param orig Original age commitment with proof + * @param secret Planchet secret for the new coin from which the new age commitment with proof is derived from + * @param[out] derived The resulting age commitment, ->priv and ->pub allocated via GNUNET_malloc() on success. + * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_age_commitment_proof_derive_from_secret ( + const struct TALER_AgeCommitmentProof *orig, + const struct TALER_PlanchetMasterSecretP *secret, + struct TALER_AgeCommitmentProof *derived); + + +/** * @brief Derives another, equivalent age commitment (without proof) for a given one. * * @param orig Original age commitment * @param salt Salt to randomly move the points on the elliptic curve in order to generate another, equivalent commitment. - * @param[out] derived The resulting age commitment, ->priv and ->pub allocated via GNUNET_malloc() on success. + * @param[out] derived The resulting age commitment, ->pub allocated via GNUNET_malloc() on success. * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ enum GNUNET_GenericReturnValue @@ -6786,6 +6802,23 @@ TALER_age_commitment_derive ( const struct GNUNET_HashCode *salt, struct TALER_AgeCommitment *derived); + +/** + * @brief Derives another, equivalent age commitment (without proof) for a given one, + * from the planchet secret. + * + * @param orig Original age commitment + * @param secret Planchet secret for the new coin from which the new age commitment is derived from + * @param[out] derived The resulting age commitment, ->pub allocated via GNUNET_malloc() on success. + * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_age_commitment_derive_from_secret ( + const struct TALER_AgeCommitment *orig, + const struct TALER_PlanchetMasterSecretP *secret, + struct TALER_AgeCommitment *derived); + + /** * @brief Provide attestation for a given age, from a given age commitment, if possible. * diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h @@ -1628,15 +1628,15 @@ struct TALER_EXCHANGE_CsRMeltResponse struct { /** - * Length of the @e alg_values array. + * Length of the @e blinding_values array. */ - unsigned int alg_values_len; + unsigned int blinding_values_len; /** * Values contributed by the exchange for the * respective coin's withdraw operation. */ - const struct TALER_ExchangeWithdrawValues *alg_values; + const struct TALER_ExchangeBlindingValues *blinding_values; } ok; /** @@ -2669,14 +2669,14 @@ struct TALER_EXCHANGE_BlindingPrepareResponse struct { /** - * Number of entries in @e alg_values, etc. + * Number of entries in @e blinding_values, etc. */ - size_t num; + size_t num_blinding_values; /** * Array @a num withdraw values form the exchange. */ - const struct TALER_ExchangeWithdrawValues *alg_values; + const struct TALER_ExchangeBlindingValues *blinding_values; } ok; @@ -2861,7 +2861,7 @@ struct TALER_EXCHANGE_WithdrawCoinPrivateDetails * Values contributed from the exchange during the * withdraw protocol. */ - struct TALER_ExchangeWithdrawValues alg_values; + struct TALER_ExchangeBlindingValues blinding_values; /** * The planchet constructed @@ -3452,18 +3452,17 @@ struct TALER_EXCHANGE_RevealMeltResponse struct { /** - * Number of signatures returned. + * Array of @e num_coins values about the coins obtained via the refresh + * operation. The array give the coins in the same order (and should + * have the same length) in which the original melt request specified the + * respective denomination keys. */ - unsigned int num_sigs; + const struct TALER_EXCHANGE_RevealedCoinInfo *coins; /** - * Array of @e num_coins blinded denomination signatures, giving each - * coin its value and validity. The array give these coins in the same - * order (and should have the same length) in which the original - * melt request specified the respective denomination keys. + * Number of coins returned. */ - const struct TALER_BlindedDenominationSignature *blinded_denom_sigs; - + unsigned int num_coins; } ok; /** @@ -3491,6 +3490,103 @@ struct TALER_RevealPrivateRefreshNonceSignaturesP struct TALER_PrivateRefreshNonceSignatureP tuple[TALER_CNC_KAPPA - 1]; }; + +/** + * Information needed to melt (partially spent) coins to obtain fresh coins + * that are unlinkable to the original coin(s). Note that melting more than + * one coin in a single request will make those coins linkable, so we only melt + * one coin at a time. + */ +struct TALER_EXCHANGE_MeltInput +{ + /** + * private key of the coin to melt + */ + struct TALER_CoinSpendPrivateKeyP melt_priv; + + /** + * age commitment and proof that went into the original coin, + * might be NULL. + */ + const struct TALER_AgeCommitmentProof *melt_age_commitment_proof; + + /** + * Hash of age commitment and proof that went into the original coin, + * might be NULL. + */ + const struct TALER_AgeCommitmentHash *melt_h_age_commitment; + + /** + * amount specifying how much the coin will contribute to the melt + * (including fee) + */ + struct TALER_Amount melt_amount; + + /** + * signatures affirming the validity of the public keys corresponding to the + * @e melt_priv private key + */ + struct TALER_DenominationSignature melt_sig; + + /** + * denomination key information record corresponding to the @e melt_sig + * validity of the keys + */ + struct TALER_EXCHANGE_DenomPublicKey melt_pk; + + /** + * length of the @e fresh_denom_pubs array + */ + size_t num_fresh_denom_pubs; + + /** + * array of @e num_fresh_coins denominations of fresh coins to create + */ + const struct TALER_EXCHANGE_DenomPublicKey *fresh_denom_pubs; + +}; + + +/** + * The necessary data of the /reveal-melt request, containing the input data + * from the prior call to /melt and the information returned from it. + */ +struct TALER_EXCHANGE_RevealMeltInput +{ + /** + * The master secret for the melt/reveal, from which all other + * secret material is derived from + */ + const struct TALER_RefreshMasterSecretP *rms; + + /* The input data from the prior call to /melt */ + const struct TALER_EXCHANGE_MeltInput *melt_input; + + /** + * The blinding seed that was used during the call to /melt + * Maybe NULL + */ + const struct TALER_BlindingMasterSeedP *blinding_seed; + + /** + * Length of the @a blinding_values array with the exchange values + * and blinding keys we are using. + * MUST be the same as @e melt_input.num_fresh_denom_pubs. + */ + unsigned int num_blinding_values; + + /** + * Blinding values returned per coin. + */ + const struct TALER_ExchangeBlindingValues *blinding_values; + + /** + * Gamma value chosen by the exchange. + */ + uint32_t noreveal_index; + +}; + /** * Submit an reveal-melt request to the exchange and get the exchange's * response. This is the second step in the refresh protocol, after the first @@ -3503,10 +3599,7 @@ struct TALER_RevealPrivateRefreshNonceSignaturesP * * @param curl_ctx The curl context * @param exchange_url The base url of the exchange - * @param num_coins Number of coin signatures to expect from the reveal - * @param rc The commitment from the previous call to melt - * @param signatures TALER_CNC_KAPPA-1 tuple of signatures to reveal - * @param age_commitment The age commitment of the old coin, might be NULL + * @param reveal_melt_input The input data for the reveal * @param reveal_cb A callback for the result, maybe NULL * @param reveal_cb_cls A closure for @e reveal_cb, maybe NULL * @return a handle for this request; NULL if the argument was invalid. @@ -3516,10 +3609,7 @@ struct TALER_EXCHANGE_RevealMeltHandle * TALER_EXCHANGE_reveal_melt ( struct GNUNET_CURL_Context *curl_ctx, const char *exchange_url, - size_t num_coins, - const struct TALER_RefreshCommitmentP *rc, - const struct TALER_RevealPrivateRefreshNonceSignaturesP *signatures, - const struct TALER_AgeCommitment *age_commitment, + const struct TALER_EXCHANGE_RevealMeltInput *reveal_melt_input, TALER_EXCHANGE_RevealMeltCallback reveal_cb, void *reveal_cb_cls); @@ -3608,7 +3698,7 @@ struct TALER_EXCHANGE_MeltBlindingDetail /** * Exchange values contributed to the refresh operation */ - struct TALER_ExchangeWithdrawValues alg_value; + struct TALER_ExchangeBlindingValues alg_value; }; @@ -3744,22 +3834,27 @@ struct TALER_EXCHANGE_MeltResponse_v27 */ struct { + /** + * Length of the @a melt_blinding_values array with the exchange values + * and blinding keys we are using. + */ + unsigned int num_melt_blinding_values; /** * Information returned per coin. */ - const struct TALER_EXCHANGE_MeltBlindingDetail *mbds; + const struct TALER_ExchangeBlindingValues *melt_blinding_values; /** - * Key used by the exchange to sign the response. + * The blinding seed that was used to get the blinding values. + * Might be NULL. */ - struct TALER_ExchangePublicKeyP sign_key; + const struct TALER_BlindingMasterSeedP *blinding_seed; /** - * Length of the @a mbds array with the exchange values - * and blinding keys we are using. + * Key used by the exchange to sign the response. */ - unsigned int num_mbds; + struct TALER_ExchangePublicKeyP sign_key; /** * Gamma value chosen by the exchange. @@ -3784,62 +3879,6 @@ typedef void void *cls, const struct TALER_EXCHANGE_MeltResponse_v27 *mr); - -/** - * Information needed to melt (partially spent) coins to obtain fresh coins - * that are unlinkable to the original coin(s). Note that melting more than - * one coin in a single request will make those coins linkable, so we only melt - * one coin at a time. - */ -struct TALER_EXCHANGE_RefreshData_v27 -{ - /** - * private key of the coin to melt - */ - struct TALER_CoinSpendPrivateKeyP melt_priv; - - /** - * age commitment and proof that went into the original coin, - * might be NULL. - */ - const struct TALER_AgeCommitmentProof *melt_age_commitment_proof; - - /** - * Hash of age commitment and proof that went into the original coin, - * might be NULL. - */ - const struct TALER_AgeCommitmentHash *melt_h_age_commitment; - - /** - * amount specifying how much the coin will contribute to the melt - * (including fee) - */ - struct TALER_Amount melt_amount; - - /** - * signatures affirming the validity of the public keys corresponding to the - * @e melt_priv private key - */ - struct TALER_DenominationSignature melt_sig; - - /** - * denomination key information record corresponding to the @e melt_sig - * validity of the keys - */ - struct TALER_EXCHANGE_DenomPublicKey melt_pk; - - /** - * array of @e pks_len denominations of fresh coins to create - */ - const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks; - - /** - * length of the @e pks array - */ - unsigned int fresh_pks_len; -}; - - /** * Submit a melt request to the exchange and get the exchange's * response. @@ -3853,7 +3892,7 @@ struct TALER_EXCHANGE_RefreshData_v27 * @param url exchange base URL * @param keys exchange keys * @param rms the fresh seed that defines the refresh operation - * @param rd the refresh data specifying the characteristics of the operation + * @param melt_input the refresh data specifying the characteristics of the operation * @param melt_cb the callback to call with the result * @param melt_cb_cls closure for @a melt_cb * @return a handle for this request; NULL if the argument was invalid. @@ -3865,7 +3904,7 @@ TALER_EXCHANGE_melt_v27 ( const char *url, struct TALER_EXCHANGE_Keys *keys, const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData_v27 *rd, + const struct TALER_EXCHANGE_MeltInput *melt_input, TALER_EXCHANGE_MeltCallback_v27 melt_cb, void *melt_cb_cls); @@ -3992,7 +4031,7 @@ struct TALER_EXCHANGE_RefreshesRevealHandle; * @param rms the fresh secret that defines the refresh operation * @param rd the refresh data that characterizes the refresh operation * @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, must match value in @a rd - * @param alg_values array @a num_coins of exchange values contributed to the refresh operation + * @param blinding_values array @a num_coins of exchange values contributed to the refresh operation * @param noreveal_index response from the exchange to the * #TALER_EXCHANGE_melt() invocation * @param reveal_cb the callback to call with the final result of the @@ -4008,7 +4047,7 @@ TALER_EXCHANGE_refreshes_reveal ( const struct TALER_RefreshMasterSecretP *rms, const struct TALER_EXCHANGE_RefreshData *rd, unsigned int num_coins, - const struct TALER_ExchangeWithdrawValues alg_values[static num_coins], + const struct TALER_ExchangeBlindingValues blinding_values[static num_coins], uint32_t noreveal_index, TALER_EXCHANGE_RefreshesRevealCallback reveal_cb, void *reveal_cb_cls); @@ -4520,7 +4559,7 @@ TALER_EXCHANGE_recoup ( struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_DenomPublicKey *pk, const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_ExchangeBlindingValues *exchange_vals, const struct TALER_PlanchetMasterSecretP *ps, const struct TALER_HashBlindedPlanchetsP *h_planchets, TALER_EXCHANGE_RecoupResultCallback recoup_cb, @@ -4619,7 +4658,7 @@ TALER_EXCHANGE_recoup_refresh ( struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_DenomPublicKey *pk, const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_ExchangeBlindingValues *exchange_vals, const struct TALER_RefreshMasterSecretP *rms, const struct TALER_PlanchetMasterSecretP *ps, unsigned int idx, diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h @@ -593,7 +593,7 @@ struct TALER_EXCHANGEDB_TableData uint64_t denominations_serial; void *coin_ev; size_t coin_ev_size; - struct TALER_ExchangeWithdrawValues ewv; + struct TALER_ExchangeBlindingValues ewv; // h_coin_ev omitted, to be recomputed! struct TALER_BlindedDenominationSignature ev_sig; } refresh_revealed_coins; @@ -2679,7 +2679,7 @@ struct TALER_EXCHANGEDB_LinkList /** * Exchange-provided values during the coin generation. */ - struct TALER_ExchangeWithdrawValues alg_values; + struct TALER_ExchangeBlindingValues alg_values; /** * Signature of the original coin being refreshed over the @@ -3153,7 +3153,7 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin * Values contributed from the exchange to the * coin generation (see /csr). */ - struct TALER_ExchangeWithdrawValues exchange_vals; + struct TALER_ExchangeBlindingValues exchange_vals; /** * Blinded message to be signed (in envelope). diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h @@ -169,16 +169,16 @@ TALER_JSON_pack_token_envelope ( /** * Generate packer instruction for a JSON field of type - * exchange withdraw values (/csr). + * exchange blinding values (/blinding-prepare). * * @param name name of the field to add to the object * @param ewv values to transmit * @return json pack specification */ struct GNUNET_JSON_PackSpec -TALER_JSON_pack_exchange_withdraw_values ( +TALER_JSON_pack_exchange_blinding_values ( const char *name, - const struct TALER_ExchangeWithdrawValues *ewv); + const struct TALER_ExchangeBlindingValues *ewv); /** * Generate packer instruction for a JSON field of type @@ -655,16 +655,16 @@ TALER_JSON_spec_blinded_denom_sig ( /** * Generate line in parser specification for - * exchange withdraw values (/csr). + * exchange blinding values (/blinding-prepare). * * @param field name of the field - * @param[out] ewv the exchange withdraw values to initialize + * @param[out] ewv the exchange blinding values to initialize * @return corresponding field spec */ struct GNUNET_JSON_Specification -TALER_JSON_spec_exchange_withdraw_values ( +TALER_JSON_spec_exchange_blinding_values ( const char *field, - struct TALER_ExchangeWithdrawValues *ewv); + struct TALER_ExchangeBlindingValues *ewv); /** @@ -794,6 +794,21 @@ TALER_JSON_spec_array_of_data ( /** + * Generate a parser for an array of known length of + * blinded signatures of denomination public keys. + * + * @param field name of the field for the array, might be NULL + * @param[out] num_entries number of entries found in the array + * @param[out] entries pointer to write where the allocated array of @e num_entries entries is + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_array_of_blinded_denom_sigs ( + const char *field, + size_t num_entries, + struct TALER_BlindedDenominationSignature *entries); + + +/** * Generate a parser for an array of unknown length of * hashes of denomination public keys. * diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h @@ -117,14 +117,14 @@ TALER_PQ_query_param_blinded_denom_sig ( /** * Generate query parameter for the exchange's contribution during a - * withdraw. Internally, the various attributes of the @a alg_values will be + * withdraw. Internally, the various attributes of the @a blinding_values will be * serialized into on variable-size BLOB. * - * @param alg_values pointer to the query parameter to pass + * @param blinding_values pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_exchange_withdraw_values ( - const struct TALER_ExchangeWithdrawValues *alg_values); +TALER_PQ_query_param_exchange_blinding_values ( + const struct TALER_ExchangeBlindingValues *blinding_values); /** @@ -340,7 +340,7 @@ TALER_PQ_result_spec_blinded_denom_sig ( struct GNUNET_PQ_ResultSpec TALER_PQ_result_spec_exchange_withdraw_values ( const char *name, - struct TALER_ExchangeWithdrawValues *ewv); + struct TALER_ExchangeBlindingValues *ewv); /** diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h @@ -1569,9 +1569,9 @@ TALER_TESTING_cmd_melt_with_retry (struct TALER_TESTING_Command cmd); * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_refresh_reveal (const char *label, - const char *melt_reference, - unsigned int expected_response_code); +TALER_TESTING_cmd_melt_reveal (const char *label, + const char *melt_reference, + unsigned int expected_response_code); /** @@ -1581,31 +1581,7 @@ TALER_TESTING_cmd_refresh_reveal (const char *label, * @return modified command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_refresh_reveal_with_retry (struct TALER_TESTING_Command cmd); - - -/** - * Create a "refresh link" command. - * - * @param label command label. - * @param reveal_reference reference to a "refresh reveal" CMD. - * @param expected_response_code expected HTTP response code - * @return the "refresh link" command - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_refresh_link (const char *label, - const char *reveal_reference, - unsigned int expected_response_code); - - -/** - * Modify a "refresh link" command to enable retries. - * - * @param cmd command - * @return modified command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_refresh_link_with_retry (struct TALER_TESTING_Command cmd); +TALER_TESTING_cmd_melt_reveal_with_retry (struct TALER_TESTING_Command cmd); /** @@ -2828,7 +2804,7 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, op (coin_history, const struct TALER_EXCHANGE_CoinHistoryEntry) \ op (planchet_secrets, const struct TALER_PlanchetMasterSecretP) \ op (kappa_seeds, const struct TALER_KappaWithdrawMasterSeedP) \ - op (exchange_wd_value, const struct TALER_ExchangeWithdrawValues) \ + op (exchange_blinding_values, const struct TALER_ExchangeBlindingValues) \ op (coin_priv, const struct TALER_CoinSpendPrivateKeyP) \ op (coin_pub, const struct TALER_CoinSpendPublicKeyP) \ op (coin_sig, const struct TALER_CoinSpendSignatureP) \ diff --git a/src/json/json_helper.c b/src/json/json_helper.c @@ -967,11 +967,11 @@ TALER_JSON_spec_blinded_planchet ( * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error */ static enum GNUNET_GenericReturnValue -parse_exchange_withdraw_values (void *cls, +parse_exchange_blinding_values (void *cls, json_t *root, struct GNUNET_JSON_Specification *spec) { - struct TALER_ExchangeWithdrawValues *ewv = spec->ptr; + struct TALER_ExchangeBlindingValues *ewv = spec->ptr; struct GNUNET_CRYPTO_BlindingInputValues *bi; const char *cipher; struct GNUNET_JSON_Specification dspec[] = { @@ -1044,11 +1044,11 @@ parse_exchange_withdraw_values (void *cls, * @param[out] spec where to free the data */ static void -clean_exchange_withdraw_values ( +clean_exchange_blinding_values ( void *cls, struct GNUNET_JSON_Specification *spec) { - struct TALER_ExchangeWithdrawValues *ewv = spec->ptr; + struct TALER_ExchangeBlindingValues *ewv = spec->ptr; (void) cls; TALER_denom_ewv_free (ewv); @@ -1056,13 +1056,13 @@ clean_exchange_withdraw_values ( struct GNUNET_JSON_Specification -TALER_JSON_spec_exchange_withdraw_values ( +TALER_JSON_spec_exchange_blinding_values ( const char *field, - struct TALER_ExchangeWithdrawValues *ewv) + struct TALER_ExchangeBlindingValues *ewv) { struct GNUNET_JSON_Specification ret = { - .parser = &parse_exchange_withdraw_values, - .cleaner = &clean_exchange_withdraw_values, + .parser = &parse_exchange_blinding_values, + .cleaner = &clean_exchange_blinding_values, .field = field, .ptr = ewv }; @@ -1833,7 +1833,6 @@ parse_array_fixed (void *cls, size_t num_entries; GNUNET_assert (0< entry_size); - GNUNET_assert (0<spec->ptr_size); num_entries = spec->ptr_size / entry_size; GNUNET_assert (0 < num_entries); @@ -1894,8 +1893,8 @@ TALER_JSON_spec_array_fixed ( .cls = (void *) entry_size, }; - GNUNET_assert (entry_size * num_entries > entry_size); - + GNUNET_assert ((num_entries <= 1) || + (entry_size * num_entries > entry_size)); return ret; } @@ -2033,4 +2032,73 @@ TALER_JSON_spec_array_of_denom_pub_h ( } +/** + * Parser for an array of blinded denomination signatures, + * of unknown array length + */ +static enum GNUNET_GenericReturnValue +parse_array_of_blinded_denom_sigs (void *cls, + json_t *root, + struct GNUNET_JSON_Specification *spec) +{ + enum GNUNET_GenericReturnValue ret; + struct TALER_BlindedDenominationSignature *sigs = spec->ptr; + size_t expected_num_entries = (size_t) cls; + size_t num_entries; + + if (! json_is_array (root)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + num_entries = json_array_size (root); + if (num_entries != expected_num_entries) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + { + json_t *j_entry; + size_t idx; + struct TALER_BlindedDenominationSignature *ptr = sigs; + + json_array_foreach (root, idx, j_entry) { + struct GNUNET_JSON_Specification esp[] = { + TALER_JSON_spec_blinded_denom_sig (NULL, + ptr), + GNUNET_JSON_spec_end () + }; + ret = GNUNET_JSON_parse (j_entry, + esp, + NULL, + NULL); + if (GNUNET_OK != ret) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + ptr++; + } + } + return GNUNET_OK; +} + + +struct GNUNET_JSON_Specification +TALER_JSON_spec_array_of_blinded_denom_sigs ( + const char *field, + size_t num_entries, + struct TALER_BlindedDenominationSignature *entries) +{ + struct GNUNET_JSON_Specification ret = { + .parser = &parse_array_of_blinded_denom_sigs, + .ptr = entries, + .field = field, + .cls = (void *) num_entries, + }; + return ret; +} + + /* end of json/json_helper.c */ diff --git a/src/json/json_pack.c b/src/json/json_pack.c @@ -269,9 +269,9 @@ TALER_JSON_pack_token_envelope ( struct GNUNET_JSON_PackSpec -TALER_JSON_pack_exchange_withdraw_values ( +TALER_JSON_pack_exchange_blinding_values ( const char *name, - const struct TALER_ExchangeWithdrawValues *ewv) + const struct TALER_ExchangeBlindingValues *ewv) { const struct GNUNET_CRYPTO_BlindingInputValues *biv; struct GNUNET_JSON_PackSpec ps = { diff --git a/src/lib/exchange_api_blinding_prepare.c b/src/lib/exchange_api_blinding_prepare.c @@ -139,17 +139,16 @@ blinding_prepare_ok (struct TALER_EXCHANGE_BlindingPrepareHandle *handle, size_t num = handle->num; const json_t *j_pair; size_t idx; - struct TALER_ExchangeWithdrawValues alg_values[GNUNET_NZL (num)]; + struct TALER_ExchangeBlindingValues blinding_values[GNUNET_NZL (num)]; - memset (alg_values, + memset (blinding_values, 0, - sizeof(alg_values)); + sizeof(blinding_values)); json_array_foreach (j_r_pubs, idx, j_pair) { struct GNUNET_CRYPTO_BlindingInputValues *bi = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues); struct GNUNET_CRYPTO_CSPublicRPairP *csv = &bi->details.cs_values; - struct GNUNET_JSON_Specification tuple[] = { GNUNET_JSON_spec_fixed (NULL, &csv->r_pub[0], @@ -175,7 +174,7 @@ blinding_prepare_ok (struct TALER_EXCHANGE_BlindingPrepareHandle *handle, GNUNET_break_op (0); GNUNET_free (bi); for (size_t i=0; i < idx; i++) - TALER_denom_ewv_free (&alg_values[i]); + TALER_denom_ewv_free (&blinding_values[i]); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error while parsing response: in line %d: %s", err_line, @@ -185,18 +184,18 @@ blinding_prepare_ok (struct TALER_EXCHANGE_BlindingPrepareHandle *handle, bi->cipher = GNUNET_CRYPTO_BSA_CS; bi->rc = 1; - alg_values[idx].blinding_inputs = bi; + blinding_values[idx].blinding_inputs = bi; } - response->details.ok.alg_values = alg_values; - response->details.ok.num = num; + response->details.ok.blinding_values = blinding_values; + response->details.ok.num_blinding_values = num; handle->callback ( handle->callback_cls, response); for (size_t i = 0; i < num; i++) - TALER_denom_ewv_free (&alg_values[i]); + TALER_denom_ewv_free (&blinding_values[i]); } return GNUNET_OK; } @@ -326,6 +325,7 @@ TALER_EXCHANGE_blinding_prepare ( bph = GNUNET_new (struct TALER_EXCHANGE_BlindingPrepareHandle); bph->num = num; bph->callback = callback; + bph->for_melt = for_melt; bph->callback_cls = callback_cls; bph->url = TALER_url_join (exchange_url, "blinding-prepare", @@ -343,7 +343,7 @@ TALER_EXCHANGE_blinding_prepare ( GNUNET_JSON_pack_string ("cipher", "CS"), GNUNET_JSON_pack_string ("operation", - for_melt ? "refresh" : "withdraw"), + for_melt ? "melt" : "withdraw"), GNUNET_JSON_pack_data_auto ("seed", seed)); GNUNET_assert (NULL != j_request); @@ -369,7 +369,6 @@ TALER_EXCHANGE_blinding_prepare ( json_object_set_new (j_request, "nks", j_nks)); - eh = TALER_EXCHANGE_curl_easy_get_ (bph->url); if ( (NULL == eh) || (GNUNET_OK != diff --git a/src/lib/exchange_api_csr_melt.c b/src/lib/exchange_api_csr_melt.c @@ -87,11 +87,11 @@ csr_ok (struct TALER_EXCHANGE_CsRMeltHandle *csrh, struct TALER_EXCHANGE_HttpResponse *hr) { size_t alen = json_array_size (arr); - struct TALER_ExchangeWithdrawValues alg_values[GNUNET_NZL (alen)]; + struct TALER_ExchangeBlindingValues blinding_values[GNUNET_NZL (alen)]; struct TALER_EXCHANGE_CsRMeltResponse csrr = { .hr = *hr, - .details.ok.alg_values_len = alen, - .details.ok.alg_values = alg_values + .details.ok.blinding_values_len = alen, + .details.ok.blinding_values = blinding_values }; for (size_t i = 0; i<alen; i++) @@ -99,9 +99,9 @@ csr_ok (struct TALER_EXCHANGE_CsRMeltHandle *csrh, json_t *av = json_array_get (arr, i); struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_exchange_withdraw_values ( + TALER_JSON_spec_exchange_blinding_values ( "ewv", - &alg_values[i]), + &blinding_values[i]), GNUNET_JSON_spec_end () }; @@ -117,7 +117,7 @@ csr_ok (struct TALER_EXCHANGE_CsRMeltHandle *csrh, csrh->cb (csrh->cb_cls, &csrr); for (size_t i = 0; i<alen; i++) - TALER_denom_ewv_free (&alg_values[i]); + TALER_denom_ewv_free (&blinding_values[i]); return GNUNET_OK; } diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c @@ -90,7 +90,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh, struct TALER_DenominationPublicKey rpub; struct TALER_CoinSpendSignatureP link_sig; union GNUNET_CRYPTO_BlindingSecretP bks; - struct TALER_ExchangeWithdrawValues alg_values; + struct TALER_ExchangeBlindingValues blinding_values; union GNUNET_CRYPTO_BlindSessionNonce nonce; bool no_nonce; uint32_t coin_idx; @@ -99,8 +99,8 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh, &rpub), TALER_JSON_spec_blinded_denom_sig ("ev_sig", &bsig), - TALER_JSON_spec_exchange_withdraw_values ("ewv", - &alg_values), + TALER_JSON_spec_exchange_blinding_values ("ewv", + &blinding_values), GNUNET_JSON_spec_fixed_auto ("link_sig", &link_sig), GNUNET_JSON_spec_uint32 ("coin_idx", @@ -132,10 +132,10 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh, coin_idx, &lci->ps); TALER_planchet_setup_coin_priv (&lci->ps, - &alg_values, + &blinding_values, &lci->coin_priv); TALER_planchet_blinding_secret_create (&lci->ps, - &alg_values, + &blinding_values, &bks); lci->has_age_commitment = false; @@ -161,7 +161,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh, if (GNUNET_OK != TALER_planchet_prepare ( &rpub, - &alg_values, + &blinding_values, &bks, no_nonce ? NULL @@ -181,7 +181,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh, &bsig, &bks, &c_hash, - &alg_values, + &blinding_values, &rpub)) { GNUNET_break_op (0); diff --git a/src/lib/exchange_api_melt.c b/src/lib/exchange_api_melt.c @@ -305,20 +305,20 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh) CURL *eh; char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; struct TALER_DenominationHashP h_denom_pub; - struct TALER_ExchangeWithdrawValues alg_values[mh->rd->fresh_pks_len]; + struct TALER_ExchangeBlindingValues blinding_values[mh->rd->fresh_pks_len]; for (unsigned int i = 0; i<mh->rd->fresh_pks_len; i++) { if (GNUNET_CRYPTO_BSA_RSA == mh->rd->fresh_pks[i].key.bsign_pub_key->cipher) - alg_values[i] = *TALER_denom_ewv_rsa_singleton (); + blinding_values[i] = *TALER_denom_ewv_rsa_singleton (); else - alg_values[i] = mh->mbds[i].alg_value; + blinding_values[i] = mh->mbds[i].alg_value; } if (GNUNET_OK != TALER_EXCHANGE_get_melt_data_ (&mh->rms, mh->rd, - alg_values, + blinding_values, &mh->md)) { GNUNET_break (0); @@ -464,7 +464,7 @@ csr_cb (void *cls, { const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = &mh->rd->fresh_pks[i]; - struct TALER_ExchangeWithdrawValues *wv = &mh->mbds[i].alg_value; + struct TALER_ExchangeBlindingValues *wv = &mh->mbds[i].alg_value; switch (fresh_pk->key.bsign_pub_key->cipher) { @@ -477,7 +477,7 @@ csr_cb (void *cls, break; case GNUNET_CRYPTO_BSA_CS: TALER_denom_ewv_copy (wv, - &csrr->details.ok.alg_values[nks_off]); + &csrr->details.ok.blinding_values[nks_off]); nks_off++; break; } diff --git a/src/lib/exchange_api_melt_v27.c b/src/lib/exchange_api_melt_v27.c @@ -94,13 +94,25 @@ struct TALER_EXCHANGE_MeltHandle_v27 /** * Details about the characteristics of the requested melt operation. */ - const struct TALER_EXCHANGE_RefreshData_v27 *rd; + const struct TALER_EXCHANGE_MeltInput *rd; /** - * Array of `num_fresh_coins` per-coin values + * True, if no blinding_seed is needed (no CS denominations involved) + */ + bool no_blinding_seed; + + /** + * If @e no_blinding_seed is false, the blinding seed for the intermediate + * call to /blinding-prepare, in order to retrieve the R-values from the + * exchange for the blind Clause-Schnorr signature. + */ + struct TALER_BlindingMasterSeedP blinding_seed; + + /** + * Array of `num_fresh_denom_pubs` per-coin values * returned from melt operation. */ - struct TALER_EXCHANGE_MeltBlindingDetail *mbds; + struct TALER_ExchangeBlindingValues *melt_blinding_values; /** * Handle for the preflight request, or NULL. @@ -127,10 +139,6 @@ struct TALER_EXCHANGE_MeltHandle_v27 */ uint32_t noreveal_index; - /** - * True if we need to include @e rms in our melt request. - */ - bool send_rms; }; @@ -149,7 +157,6 @@ verify_melt_v27_signature_ok (struct TALER_EXCHANGE_MeltHandle_v27 *mh, struct TALER_ExchangePublicKeyP *exchange_pub) { struct TALER_ExchangeSignatureP exchange_sig; - const struct TALER_EXCHANGE_Keys *key_state; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig), @@ -169,9 +176,8 @@ verify_melt_v27_signature_ok (struct TALER_EXCHANGE_MeltHandle_v27 *mh, return GNUNET_SYSERR; } /* check that exchange signing key is permitted */ - key_state = mh->keys; if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, + TALER_EXCHANGE_test_signing_key (mh->keys, exchange_pub)) { GNUNET_break_op (0); @@ -237,8 +243,11 @@ handle_melt_v27_finished (void *cls, break; } mr.details.ok.noreveal_index = mh->noreveal_index; - mr.details.ok.num_mbds = mh->rd->fresh_pks_len; - mr.details.ok.mbds = mh->mbds; + mr.details.ok.num_melt_blinding_values = mh->rd->num_fresh_denom_pubs; + mr.details.ok.melt_blinding_values = mh->melt_blinding_values; + mr.details.ok.blinding_seed = mh->no_blinding_seed + ? NULL + : &mh->blinding_seed; mh->melt_cb (mh->melt_cb_cls, &mr); mh->melt_cb = NULL; @@ -300,24 +309,18 @@ handle_melt_v27_finished (void *cls, static enum GNUNET_GenericReturnValue start_melt (struct TALER_EXCHANGE_MeltHandle_v27 *mh) { - const struct TALER_EXCHANGE_Keys *key_state; - json_t *melt_obj; + json_t *j_request_body; + json_t *j_coin_evs; CURL *eh; struct TALER_DenominationHashP h_denom_pub; - struct TALER_ExchangeWithdrawValues alg_values[mh->rd->fresh_pks_len]; - for (unsigned int i = 0; i<mh->rd->fresh_pks_len; i++) - { - if (GNUNET_CRYPTO_BSA_RSA == - mh->rd->fresh_pks[i].key.bsign_pub_key->cipher) - alg_values[i] = *TALER_denom_ewv_rsa_singleton (); - else - alg_values[i] = mh->mbds[i].alg_value; - } if (GNUNET_OK != TALER_EXCHANGE_get_melt_data_v27 (&mh->rms, mh->rd, - alg_values, + mh->no_blinding_seed + ? NULL + : &mh->blinding_seed, + mh->melt_blinding_values, &mh->md)) { GNUNET_break (0); @@ -336,42 +339,71 @@ start_melt (struct TALER_EXCHANGE_MeltHandle_v27 *mh) GNUNET_CRYPTO_eddsa_key_get_public ( &mh->md.melted_coin.coin_priv.eddsa_priv, &mh->coin_pub.eddsa_pub); - melt_obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("denom_pub_hash", + mh->dki = TALER_EXCHANGE_get_denomination_key (mh->keys, + &mh->md.melted_coin.pub_key); + j_request_body = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_data_auto ("old_coin_pub", + &mh->coin_pub), + GNUNET_JSON_pack_data_auto ("old_denom_pub_h", &h_denom_pub), - TALER_JSON_pack_denom_sig ("denom_sig", + TALER_JSON_pack_denom_sig ("old_denom_sig", &mh->md.melted_coin.sig), GNUNET_JSON_pack_data_auto ("confirm_sig", &mh->coin_sig), TALER_JSON_pack_amount ("value_with_fee", &mh->md.melted_coin.melt_amount_with_fee), - GNUNET_JSON_pack_data_auto ("rc", - &mh->md.rc), GNUNET_JSON_pack_allow_null ( (NULL != mh->md.melted_coin.h_age_commitment) - ? GNUNET_JSON_pack_data_auto ("age_commitment_hash", + ? GNUNET_JSON_pack_data_auto ("old_age_commitment_h", mh->md.melted_coin.h_age_commitment) - : GNUNET_JSON_pack_string ("age_commitment_hash", + : GNUNET_JSON_pack_string ("old_age_commitment_h", NULL)), + GNUNET_JSON_pack_data_auto ("refresh_seed", + &mh->md.refresh_seed), GNUNET_JSON_pack_allow_null ( - mh->send_rms - ? GNUNET_JSON_pack_data_auto ("rms", - &mh->rms) - : GNUNET_JSON_pack_string ("rms", - NULL))); - - key_state = mh->keys; - mh->dki = TALER_EXCHANGE_get_denomination_key (key_state, - &mh->md.melted_coin.pub_key); - + (mh->md.no_blinding_seed) + ? GNUNET_JSON_pack_string ("blinding_seed", + NULL) + : GNUNET_JSON_pack_data_auto ("blinding_seed", + &mh->md.blinding_seed)), + TALER_JSON_pack_array_of_data ("denoms_h", + mh->md.num_fresh_coins, + mh->md.denoms_h, + sizeof(*mh->md.denoms_h)) + ); + GNUNET_assert (NULL != j_request_body); + j_coin_evs = json_array (); + GNUNET_assert (NULL != j_coin_evs); + /** + * Fill the kappa array of coin envelopes + */ + for (uint8_t k=0; k<TALER_CNC_KAPPA; k++) + { + json_t *j_envs = json_array (); + GNUNET_assert (NULL != j_envs); + for (size_t i = 0; i < mh->md.num_fresh_coins; i++) + { + json_t *j_coin = GNUNET_JSON_PACK ( + TALER_JSON_pack_blinded_planchet (NULL, + &mh->md.kappa_blinded_planchets[k][i])); + GNUNET_assert (NULL != j_coin); + GNUNET_assert (0 == + json_array_append_new (j_envs, j_coin)); + } + GNUNET_assert (0 == + json_array_append_new (j_coin_evs, j_envs)); + } + GNUNET_assert (0 == + json_object_set_new (j_request_body, + "coin_evs", + j_coin_evs)); /* and now we can at last begin the actual request handling */ - mh->url = TALER_url_join (mh->exchange_url, - "/melt", + "melt", NULL); if (NULL == mh->url) { - json_decref (melt_obj); + json_decref (j_request_body); return GNUNET_SYSERR; } eh = TALER_EXCHANGE_curl_easy_get_ (mh->url); @@ -379,15 +411,15 @@ start_melt (struct TALER_EXCHANGE_MeltHandle_v27 *mh) (GNUNET_OK != TALER_curl_easy_post (&mh->ctx, eh, - melt_obj)) ) + j_request_body)) ) { GNUNET_break (0); if (NULL != eh) curl_easy_cleanup (eh); - json_decref (melt_obj); + json_decref (j_request_body); return GNUNET_SYSERR; } - json_decref (melt_obj); + json_decref (j_request_body); mh->job = GNUNET_CURL_job_add2 (mh->cctx, eh, mh->ctx.headers, @@ -445,11 +477,11 @@ blinding_prepare_cb (void *cls, TALER_EXCHANGE_melt_v27_cancel (mh); return; } - for (unsigned int i = 0; i<mh->rd->fresh_pks_len; i++) + for (unsigned int i = 0; i<mh->rd->num_fresh_denom_pubs; i++) { const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = - &mh->rd->fresh_pks[i]; - struct TALER_ExchangeWithdrawValues *wv = &mh->mbds[i].alg_value; + &mh->rd->fresh_denom_pubs[i]; + struct TALER_ExchangeBlindingValues *wv = &mh->melt_blinding_values[i]; switch (fresh_pk->key.bsign_pub_key->cipher) { @@ -462,12 +494,11 @@ blinding_prepare_cb (void *cls, break; case GNUNET_CRYPTO_BSA_CS: TALER_denom_ewv_copy (wv, - &bpr->details.ok.alg_values[nks_off]); + &bpr->details.ok.blinding_values[nks_off]); nks_off++; break; } } - mh->send_rms = true; if (GNUNET_OK != start_melt (mh)) { @@ -485,15 +516,15 @@ TALER_EXCHANGE_melt_v27 ( const char *url, struct TALER_EXCHANGE_Keys *keys, const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData_v27 *rd, + const struct TALER_EXCHANGE_MeltInput *rd, TALER_EXCHANGE_MeltCallback_v27 melt_cb, void *melt_cb_cls) { - struct TALER_EXCHANGE_NonceKey nks[GNUNET_NZL (rd->fresh_pks_len)]; + struct TALER_EXCHANGE_NonceKey nks[GNUNET_NZL (rd->num_fresh_denom_pubs)]; unsigned int nks_off = 0; struct TALER_EXCHANGE_MeltHandle_v27 *mh; - if (0 == rd->fresh_pks_len) + if (0 == rd->num_fresh_denom_pubs) { GNUNET_break (0); return NULL; @@ -506,26 +537,29 @@ TALER_EXCHANGE_melt_v27 ( mh->rms = *rms; mh->melt_cb = melt_cb; mh->melt_cb_cls = melt_cb_cls; - mh->mbds = GNUNET_new_array (rd->fresh_pks_len, - struct TALER_EXCHANGE_MeltBlindingDetail); - for (unsigned int i = 0; i<rd->fresh_pks_len; i++) + mh->no_blinding_seed = true; + mh->melt_blinding_values = + GNUNET_new_array (rd->num_fresh_denom_pubs, + struct TALER_ExchangeBlindingValues); + for (unsigned int i = 0; i<rd->num_fresh_denom_pubs; i++) { - const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = &rd->fresh_pks[i]; + const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = + &rd->fresh_denom_pubs[i]; switch (fresh_pk->key.bsign_pub_key->cipher) { case GNUNET_CRYPTO_BSA_INVALID: GNUNET_break (0); - GNUNET_free (mh->mbds); + GNUNET_free (mh->melt_blinding_values); GNUNET_free (mh); return NULL; case GNUNET_CRYPTO_BSA_RSA: - TALER_denom_ewv_copy (&mh->mbds[i].alg_value, + TALER_denom_ewv_copy (&mh->melt_blinding_values[i], TALER_denom_ewv_rsa_singleton ()); break; case GNUNET_CRYPTO_BSA_CS: nks[nks_off].pk = fresh_pk; - nks[nks_off].cnc_num = nks_off; + nks[nks_off].cnc_num = i; nks_off++; break; } @@ -533,9 +567,13 @@ TALER_EXCHANGE_melt_v27 ( mh->keys = TALER_EXCHANGE_keys_incref (keys); if (0 != nks_off) { + mh->no_blinding_seed = false; + TALER_cs_refresh_secret_to_blinding_seed ( + rms, + &mh->blinding_seed); mh->bpr = TALER_EXCHANGE_blinding_prepare_for_melt (ctx, url, - &mh->md.blinding_seed, + &mh->blinding_seed, nks_off, nks, &blinding_prepare_cb, @@ -562,8 +600,8 @@ TALER_EXCHANGE_melt_v27 ( void TALER_EXCHANGE_melt_v27_cancel (struct TALER_EXCHANGE_MeltHandle_v27 *mh) { - for (unsigned int i = 0; i<mh->rd->fresh_pks_len; i++) - TALER_denom_ewv_free (&mh->mbds[i].alg_value); + for (unsigned int i = 0; i<mh->rd->num_fresh_denom_pubs; i++) + TALER_denom_ewv_free (&mh->melt_blinding_values[i]); if (NULL != mh->job) { GNUNET_CURL_job_cancel (mh->job); @@ -575,7 +613,7 @@ TALER_EXCHANGE_melt_v27_cancel (struct TALER_EXCHANGE_MeltHandle_v27 *mh) mh->bpr = NULL; } TALER_EXCHANGE_free_melt_data_v27 (&mh->md); /* does not free 'md' itself */ - GNUNET_free (mh->mbds); + GNUNET_free (mh->melt_blinding_values); GNUNET_free (mh->url); GNUNET_free (mh->exchange_url); TALER_curl_easy_post_finished (&mh->ctx); diff --git a/src/lib/exchange_api_recoup.c b/src/lib/exchange_api_recoup.c @@ -234,7 +234,7 @@ TALER_EXCHANGE_recoup ( struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_DenomPublicKey *pk, const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_ExchangeBlindingValues *blinding_values, const struct TALER_PlanchetMasterSecretP *ps, const struct TALER_HashBlindedPlanchetsP *h_planchets, TALER_EXCHANGE_RecoupResultCallback recoup_cb, @@ -250,10 +250,10 @@ TALER_EXCHANGE_recoup ( ph = GNUNET_new (struct TALER_EXCHANGE_RecoupHandle); TALER_planchet_setup_coin_priv (ps, - exchange_vals, + blinding_values, &coin_priv); TALER_planchet_blinding_secret_create (ps, - exchange_vals, + blinding_values, &bks); GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv, &ph->coin_pub.eddsa_pub); @@ -268,8 +268,8 @@ TALER_EXCHANGE_recoup ( &h_denom_pub), TALER_JSON_pack_denom_sig ("denom_sig", denom_sig), - TALER_JSON_pack_exchange_withdraw_values ("ewv", - exchange_vals), + TALER_JSON_pack_exchange_blinding_values ("ewv", + blinding_values), GNUNET_JSON_pack_data_auto ("coin_sig", &ph->coin_sig), GNUNET_JSON_pack_data_auto ("h_planchets", diff --git a/src/lib/exchange_api_recoup_refresh.c b/src/lib/exchange_api_recoup_refresh.c @@ -222,7 +222,7 @@ TALER_EXCHANGE_recoup_refresh ( struct TALER_EXCHANGE_Keys *keys, const struct TALER_EXCHANGE_DenomPublicKey *pk, const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_ExchangeBlindingValues *blinding_values, const struct TALER_RefreshMasterSecretP *rms, const struct TALER_PlanchetMasterSecretP *ps, unsigned int idx, @@ -246,10 +246,10 @@ TALER_EXCHANGE_recoup_refresh ( ph->cb = recoup_cb; ph->cb_cls = recoup_cb_cls; TALER_planchet_setup_coin_priv (ps, - exchange_vals, + blinding_values, &coin_priv); TALER_planchet_blinding_secret_create (ps, - exchange_vals, + blinding_values, &bks); GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv, &ph->coin_pub.eddsa_pub); @@ -264,8 +264,8 @@ TALER_EXCHANGE_recoup_refresh ( &h_denom_pub), TALER_JSON_pack_denom_sig ("denom_sig", denom_sig), - TALER_JSON_pack_exchange_withdraw_values ("ewv", - exchange_vals), + TALER_JSON_pack_exchange_blinding_values ("ewv", + blinding_values), GNUNET_JSON_pack_data_auto ("coin_sig", &ph->coin_sig), GNUNET_JSON_pack_data_auto ("coin_blind_key_secret", diff --git a/src/lib/exchange_api_refresh_common.c b/src/lib/exchange_api_refresh_common.c @@ -64,7 +64,7 @@ enum GNUNET_GenericReturnValue TALER_EXCHANGE_get_melt_data_ ( const struct TALER_RefreshMasterSecretP *rms, const struct TALER_EXCHANGE_RefreshData *rd, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, struct MeltData *md) { struct TALER_Amount total; @@ -260,16 +260,13 @@ TALER_EXCHANGE_get_melt_data_ ( void TALER_EXCHANGE_free_melt_data_v27 (struct MeltData_v27 *md) { - for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++) + for (unsigned int k = 0; k < TALER_CNC_KAPPA; k++) { - struct TALER_RefreshCoinData *rcds = md->rcd[i]; - - if (NULL == rcds) - continue; - for (unsigned int j = 0; j < md->num_fresh_coins; j++) - TALER_blinded_planchet_free (&rcds[j].blinded_planchet); - GNUNET_free (rcds); + for (unsigned int i = 0; i < md->num_fresh_coins; i++) + TALER_blinded_planchet_free (&md->kappa_blinded_planchets[k][i]); } + GNUNET_free (md->denoms_h); + GNUNET_free (md->denom_pubs); TALER_denom_pub_free (&md->melted_coin.pub_key); TALER_denom_sig_free (&md->melted_coin.sig); if (NULL != md->fcds) @@ -296,25 +293,26 @@ TALER_EXCHANGE_free_melt_data_v27 (struct MeltData_v27 *md) enum GNUNET_GenericReturnValue TALER_EXCHANGE_get_melt_data_v27 ( const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData_v27 *rd, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_EXCHANGE_MeltInput *rd, + const struct TALER_BlindingMasterSeedP *blinding_seed, + const struct TALER_ExchangeBlindingValues *blinding_values, struct MeltData_v27 *md) { struct TALER_Amount total; struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_KappaHashBlindedPlanchetsP k_h_bps; - union GNUNET_CRYPTO_BlindSessionNonce nonces[rd->fresh_pks_len]; - const struct TALER_DenominationHashP *denoms_h[rd->fresh_pks_len]; - bool is_cs[rd->fresh_pks_len]; + union GNUNET_CRYPTO_BlindSessionNonce nonces[rd->num_fresh_denom_pubs]; + const struct TALER_DenominationHashP *denoms_h[rd->num_fresh_denom_pubs]; + bool is_cs[rd->num_fresh_denom_pubs]; bool uses_cs = false; GNUNET_CRYPTO_eddsa_key_get_public (&rd->melt_priv.eddsa_priv, &coin_pub.eddsa_pub); - /* build up melt data structure */ memset (md, 0, sizeof (*md)); - md->num_fresh_coins = rd->fresh_pks_len; + /* build up melt data structure */ + md->num_fresh_coins = rd->num_fresh_denom_pubs; md->melted_coin.coin_priv = rd->melt_priv; md->melted_coin.melt_amount_with_fee = rd->melt_amount; md->melted_coin.fee_melt = rd->melt_pk.fees.refresh; @@ -322,6 +320,9 @@ TALER_EXCHANGE_get_melt_data_v27 ( md->melted_coin.expire_deposit = rd->melt_pk.expire_deposit; md->melted_coin.age_commitment_proof = rd->melt_age_commitment_proof; md->melted_coin.h_age_commitment = rd->melt_h_age_commitment; + md->no_blinding_seed = (NULL == blinding_seed); + if (NULL != blinding_seed) + md->blinding_seed = *blinding_seed; GNUNET_assert (GNUNET_OK == TALER_amount_set_zero (rd->melt_amount.currency, @@ -332,15 +333,25 @@ TALER_EXCHANGE_get_melt_data_v27 ( &rd->melt_sig); md->fcds = GNUNET_new_array (md->num_fresh_coins, struct FreshCoinData); - for (unsigned int j = 0; j<rd->fresh_pks_len; j++) + md->denoms_h = + GNUNET_new_array (md->num_fresh_coins, + struct TALER_DenominationHashP); + md->denom_pubs = + GNUNET_new_array (md->num_fresh_coins, + const struct TALER_DenominationPublicKey*); + + for (unsigned int j = 0; j<rd->num_fresh_denom_pubs; j++) { struct FreshCoinData *fcd = &md->fcds[j]; - denoms_h[j] = &rd->fresh_pks[j].h_key; + denoms_h[j] = &rd->fresh_denom_pubs[j].h_key; + md->denoms_h[j] = rd->fresh_denom_pubs[j].h_key; + md->denom_pubs[j] = &rd->fresh_denom_pubs[j].key; + TALER_denom_pub_copy (&fcd->fresh_pk, - &rd->fresh_pks[j].key); + &rd->fresh_denom_pubs[j].key); GNUNET_assert (NULL != fcd->fresh_pk.bsign_pub_key); - if (alg_values[j].blinding_inputs->cipher != + if (blinding_values[j].blinding_inputs->cipher != fcd->fresh_pk.bsign_pub_key->cipher) { GNUNET_break (0); @@ -364,11 +375,11 @@ TALER_EXCHANGE_get_melt_data_v27 ( if ( (0 > TALER_amount_add (&total, &total, - &rd->fresh_pks[j].value)) || + &rd->fresh_denom_pubs[j].value)) || (0 > TALER_amount_add (&total, &total, - &rd->fresh_pks[j].fees.withdraw)) ) + &rd->fresh_denom_pubs[j].fees.withdraw)) ) { GNUNET_break (0); TALER_EXCHANGE_free_melt_data_v27 (md); @@ -393,12 +404,16 @@ TALER_EXCHANGE_get_melt_data_v27 ( * in TALER_EXCHANGE_melt_v27(), as preparation for * the request to `/blinding-prepare`. */ + memset (nonces, + 0, + sizeof(*nonces)); if (uses_cs) { + GNUNET_assert (! md->no_blinding_seed); TALER_cs_derive_blind_nonces_from_seed ( - &md->blinding_seed, + blinding_seed, true, /* for melt */ - rd->fresh_pks_len, + rd->num_fresh_denom_pubs, is_cs, nonces); } @@ -412,80 +427,71 @@ TALER_EXCHANGE_get_melt_data_v27 ( TALER_refresh_expand_kappa_nonces ( &md->refresh_seed, &md->kappa_nonces); - - /* build up coins */ + /** + * Build up all candidates for coin planchets + */ for (unsigned int k = 0; k<TALER_CNC_KAPPA; k++) { - struct TALER_PlanchetMasterSecretP planchet_secrets[rd->fresh_pks_len]; - struct TALER_PlanchetDetail planchet_details[rd->fresh_pks_len]; + struct TALER_PlanchetMasterSecretP + planchet_secrets[rd->num_fresh_denom_pubs]; + struct TALER_PlanchetDetail planchet_details[rd->num_fresh_denom_pubs]; TALER_wallet_refresh_nonce_sign ( &rd->melt_priv, &md->kappa_nonces.tuple[k], - rd->fresh_pks_len, + rd->num_fresh_denom_pubs, denoms_h, k, &md->signatures[k]); TALER_refresh_signature_to_secrets ( &md->signatures[k], - rd->fresh_pks_len, + rd->num_fresh_denom_pubs, planchet_secrets); - md->rcd[k] = GNUNET_new_array (rd->fresh_pks_len, - struct TALER_RefreshCoinData); + md->kappa_blinded_planchets[k] = + GNUNET_new_array (rd->num_fresh_denom_pubs, + struct TALER_BlindedPlanchet); - for (unsigned int j = 0; j<rd->fresh_pks_len; j++) + for (unsigned int j = 0; j<rd->num_fresh_denom_pubs; j++) { struct FreshCoinData *fcd = &md->fcds[j]; struct TALER_CoinSpendPrivateKeyP *coin_priv = &fcd->coin_priv; - struct TALER_RefreshCoinData *rcd = &md->rcd[k][j]; union GNUNET_CRYPTO_BlindingSecretP *bks = &fcd->bks[k]; struct TALER_CoinPubHashP c_hash; struct TALER_AgeCommitmentHash ach; - struct TALER_AgeCommitmentHash *pah = NULL; + struct TALER_AgeCommitmentHash *pah; fcd->ps[k] = planchet_secrets[j]; TALER_planchet_setup_coin_priv (&planchet_secrets[j], - &alg_values[j], + &blinding_values[j], coin_priv); - TALER_planchet_blinding_secret_create (&planchet_secrets[j], - &alg_values[j], + &blinding_values[j], bks); - if (NULL != rd->melt_age_commitment_proof) { - struct GNUNET_HashCode salt; - - GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_kdf (&salt, - sizeof (salt), - &planchet_secrets[j], - sizeof(planchet_secrets[j]), - "age commitment", - strlen ("age commitment"), - NULL, 0)); - fcd->age_commitment_proofs[k] = GNUNET_new (struct TALER_AgeCommitmentProof); - GNUNET_assert (GNUNET_OK == - TALER_age_commitment_proof_derive ( + TALER_age_commitment_proof_derive_from_secret ( md->melted_coin.age_commitment_proof, - &salt, + &planchet_secrets[j], fcd->age_commitment_proofs[k])); - TALER_age_commitment_hash ( &fcd->age_commitment_proofs[k]->commitment, &ach); pah = &ach; } + else + { + pah = NULL; + } if (GNUNET_OK != TALER_planchet_prepare (&fcd->fresh_pk, - &alg_values[j], + &blinding_values[j], bks, - &nonces[j], + is_cs[j] ? &nonces[j] : NULL, coin_priv, pah, &c_hash, @@ -495,15 +501,14 @@ TALER_EXCHANGE_get_melt_data_v27 ( TALER_EXCHANGE_free_melt_data_v27 (md); return GNUNET_SYSERR; } - rcd->blinded_planchet = planchet_details[j].blinded_planchet; - rcd->dk = &fcd->fresh_pk; + md->kappa_blinded_planchets[k][j] = + planchet_details[j].blinded_planchet; } - /** * Compute the hash of this batch of blinded planchets */ TALER_wallet_blinded_planchet_details_hash ( - rd->fresh_pks_len, + rd->num_fresh_denom_pubs, planchet_details, &k_h_bps.tuple[k]); } diff --git a/src/lib/exchange_api_refresh_common.h b/src/lib/exchange_api_refresh_common.h @@ -192,6 +192,11 @@ struct MeltData_v27 uint16_t num_fresh_coins; /** + * If true, no blinding seed is used in the melt request + */ + bool no_blinding_seed; + + /** * The seed for blinding, derived from the refresh master secret; */ struct TALER_BlindingMasterSeedP blinding_seed; @@ -223,10 +228,20 @@ struct MeltData_v27 struct FreshCoinData *fcds; /** - * Blinded planchets and denominations of the fresh coins, depending on the cut-and-choose. + * Array of @e num_fresh_coins denominations of the fresh coins. + */ + const struct TALER_DenominationPublicKey **denom_pubs; + + /** + * Array of @e num_fresh_coins of hashes of the public key of the denominations. + */ + struct TALER_DenominationHashP *denoms_h; + + /** + * Blinded planchets of the fresh coins, depending on the cut-and-choose. * Array of length @e num_fresh_coins. */ - struct TALER_RefreshCoinData *rcd[TALER_CNC_KAPPA]; + struct TALER_BlindedPlanchet *kappa_blinded_planchets[TALER_CNC_KAPPA]; }; /** @@ -241,23 +256,25 @@ enum GNUNET_GenericReturnValue TALER_EXCHANGE_get_melt_data_ ( const struct TALER_RefreshMasterSecretP *rms, const struct TALER_EXCHANGE_RefreshData *rd, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, struct MeltData *md); /** * Compute the melt data from the refresh data and secret - * for v26 of the protocol. + * for v27 of the protocol. * * @param rms secret internals of the refresh-reveal operation * @param rd refresh data with the characteristics of the operation + * @param blinding_seed seed for blinding in case of CS denominations, can be NULL * @param alg_values contributions from the exchange into the melt * @param[out] md where to write the derived melt data */ enum GNUNET_GenericReturnValue TALER_EXCHANGE_get_melt_data_v27 ( const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData_v27 *rd, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_EXCHANGE_MeltInput *rd, + const struct TALER_BlindingMasterSeedP *blinding_seed, + const struct TALER_ExchangeBlindingValues *alg_values, struct MeltData_v27 *md); diff --git a/src/lib/exchange_api_refreshes_reveal.c b/src/lib/exchange_api_refreshes_reveal.c @@ -58,7 +58,7 @@ struct TALER_EXCHANGE_RefreshesRevealHandle /** * Exchange-contributed values to the operation. */ - struct TALER_ExchangeWithdrawValues *alg_values; + struct TALER_ExchangeBlindingValues *alg_values; /** * Function to call with the result. @@ -310,7 +310,7 @@ TALER_EXCHANGE_refreshes_reveal ( const struct TALER_RefreshMasterSecretP *rms, const struct TALER_EXCHANGE_RefreshData *rd, unsigned int num_coins, - const struct TALER_ExchangeWithdrawValues alg_values[static num_coins], + const struct TALER_ExchangeBlindingValues alg_values[static num_coins], uint32_t noreveal_index, TALER_EXCHANGE_RefreshesRevealCallback reveal_cb, void *reveal_cb_cls) @@ -468,7 +468,7 @@ TALER_EXCHANGE_refreshes_reveal ( rrh->md = md; rrh->alg_values = GNUNET_new_array (md.num_fresh_coins, - struct TALER_ExchangeWithdrawValues); + struct TALER_ExchangeBlindingValues); for (unsigned int i = 0; i<md.num_fresh_coins; i++) TALER_denom_ewv_copy (&rrh->alg_values[i], &alg_values[i]); diff --git a/src/lib/exchange_api_reveal_melt.c b/src/lib/exchange_api_reveal_melt.c @@ -57,27 +57,17 @@ struct TALER_EXCHANGE_RevealMeltHandle /** * Number of coins to expect */ - size_t num_coins; + size_t num_expected_coins; /** - * The commitment from the previous call to /melt + * The input provided */ - struct TALER_RefreshCommitmentP rc; + const struct TALER_EXCHANGE_RevealMeltInput *reveal_input; /** - * The signatures to reveal + * The melt data */ - struct TALER_RevealPrivateRefreshNonceSignaturesP signatures; - - /** - * False if an age commitment was provided - */ - bool no_age_commitment; - - /** - * The age commitment of the previous coin, if @e no_age_commitment is false - */ - struct TALER_AgeCommitment age_commitment; + struct MeltData_v27 md; /** * Callback to pass the result onto @@ -108,13 +98,13 @@ reveal_melt_ok ( .hr.reply = j_response, .hr.http_status = MHD_HTTP_OK, }; - const json_t *j_sigs; + struct TALER_BlindedDenominationSignature blind_sigs[mrh->num_expected_coins]; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_array_const ("ev_sigs", - &j_sigs), + TALER_JSON_spec_array_of_blinded_denom_sigs ("ev_sigs", + mrh->num_expected_coins, + blind_sigs), GNUNET_JSON_spec_end () }; - if (GNUNET_OK != GNUNET_JSON_parse (j_response, spec, @@ -124,46 +114,76 @@ reveal_melt_ok ( return GNUNET_SYSERR; } - if (mrh->num_coins != json_array_size (j_sigs)) - { - /* Number of coins generated does not match our expectation */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - { - struct TALER_BlindedDenominationSignature denom_sigs[mrh->num_coins]; - json_t *j_sig; - size_t n; + struct TALER_EXCHANGE_RevealedCoinInfo coins[mrh->num_expected_coins]; /* Reconstruct the coins and unblind the signatures */ - json_array_foreach (j_sigs, n, j_sig) + for (unsigned int i = 0; i<mrh->num_expected_coins; i++) { - struct GNUNET_JSON_Specification ispec[] = { - TALER_JSON_spec_blinded_denom_sig (NULL, - &denom_sigs[n]), - GNUNET_JSON_spec_end () - }; + struct TALER_EXCHANGE_RevealedCoinInfo *rci = &coins[i]; + const struct FreshCoinData *fcd = &mrh->md.fcds[i]; + const struct TALER_DenominationPublicKey *pk; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinPubHashP coin_hash; + struct TALER_FreshCoin coin; + union GNUNET_CRYPTO_BlindingSecretP bks; + const struct TALER_AgeCommitmentHash *pah = NULL; + + rci->ps = fcd->ps[mrh->reveal_input->noreveal_index]; + rci->bks = fcd->bks[mrh->reveal_input->noreveal_index]; + rci->age_commitment_proof = NULL; + pk = &fcd->fresh_pk; + if (NULL != mrh->md.melted_coin.age_commitment_proof) + { + rci->age_commitment_proof + = fcd->age_commitment_proofs[mrh->reveal_input->noreveal_index]; + TALER_age_commitment_hash ( + &rci->age_commitment_proof->commitment, + &rci->h_age_commitment); + pah = &rci->h_age_commitment; + } + TALER_planchet_setup_coin_priv (&rci->ps, + &mrh->reveal_input->blinding_values[i], + &rci->coin_priv); + TALER_planchet_blinding_secret_create (&rci->ps, + &mrh->reveal_input->blinding_values + [i], + &bks); + /* needed to verify the signature, and we didn't store it earlier, + hence recomputing it here... */ + GNUNET_CRYPTO_eddsa_key_get_public (&rci->coin_priv.eddsa_priv, + &coin_pub.eddsa_pub); + TALER_coin_pub_hash (&coin_pub, + pah, + &coin_hash); if (GNUNET_OK != - GNUNET_JSON_parse (j_sig, - ispec, - NULL, NULL)) + TALER_planchet_to_coin (pk, + &blind_sigs[i], + &bks, + &rci->coin_priv, + pah, + &coin_hash, + &mrh->reveal_input->blinding_values[i], + &coin)) { GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } + GNUNET_JSON_parse_free (spec); + rci->sig = coin.sig; } - response.details.ok.num_sigs = mrh->num_coins; - response.details.ok.blinded_denom_sigs = denom_sigs; + response.details.ok.num_coins = mrh->num_expected_coins; + response.details.ok.coins = coins; mrh->callback (mrh->callback_cls, &response); /* Make sure the callback isn't called again */ mrh->callback = NULL; /* Free resources */ - for (size_t i = 0; i < mrh->num_coins; i++) - TALER_blinded_denom_sig_free (&denom_sigs[i]); + for (size_t i = 0; i < mrh->num_expected_coins; i++) + TALER_blinded_denom_sig_free (&blind_sigs[i]); } return GNUNET_OK; @@ -273,39 +293,40 @@ perform_protocol ( CURL *curlh; json_t *j_array_of_signatures; + j_array_of_signatures = json_array (); GNUNET_assert (NULL != j_array_of_signatures); - for (uint8_t k = 0; k < TALER_CNC_KAPPA - 1; k++) + for (uint8_t k = 0; k < TALER_CNC_KAPPA; k++) { - json_t *j_sig = - GNUNET_JSON_from_data_auto (&mrh->signatures.tuple[k]); - GNUNET_assert (NULL != j_sig); + if (mrh->reveal_input->noreveal_index == k) + continue; + GNUNET_assert (0 == json_array_append_new ( j_array_of_signatures, - j_sig)); + GNUNET_JSON_from_data_auto (&mrh->md.signatures[k]))); } { json_t *j_request_body; j_request_body = GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("rc", - &mrh->rc), + &mrh->md.rc), GNUNET_JSON_pack_array_steal ("signatures", j_array_of_signatures)); GNUNET_assert (NULL != j_request_body); - if (! mrh->no_age_commitment) + if (NULL != mrh->reveal_input->melt_input->melt_age_commitment_proof) { json_t *j_age = GNUNET_JSON_PACK ( - TALER_JSON_pack_age_commitment ("age_commitment", - &mrh->age_commitment)); + TALER_JSON_pack_age_commitment ( + "age_commitment", + &mrh->reveal_input->melt_input->melt_age_commitment_proof->commitment)); GNUNET_assert (NULL != j_age); GNUNET_assert (0 == json_object_update_new (j_request_body, j_age)); } - curlh = TALER_EXCHANGE_curl_easy_get_ (mrh->request_url); GNUNET_assert (NULL != curlh); GNUNET_assert (GNUNET_OK == @@ -337,27 +358,16 @@ struct TALER_EXCHANGE_RevealMeltHandle * TALER_EXCHANGE_reveal_melt ( struct GNUNET_CURL_Context *curl_ctx, const char *exchange_url, - size_t num_coins, - const struct TALER_RefreshCommitmentP *rc, - const struct TALER_RevealPrivateRefreshNonceSignaturesP *signatures, - const struct TALER_AgeCommitment *age_commitment, + const struct TALER_EXCHANGE_RevealMeltInput *reveal_melt_input, TALER_EXCHANGE_RevealMeltCallback reveal_cb, void *reveal_cb_cls) { struct TALER_EXCHANGE_RevealMeltHandle *mrh = GNUNET_new (struct TALER_EXCHANGE_RevealMeltHandle); - mrh->rc = *rc; - mrh->num_coins = num_coins; - mrh->signatures = *signatures; - mrh->no_age_commitment = (NULL == age_commitment); - if (NULL != age_commitment) - { - TALER_age_commitment_deep_copy ( - &mrh->age_commitment, - age_commitment); - } mrh->callback = reveal_cb; mrh->callback_cls = reveal_cb_cls; + mrh->reveal_input = reveal_melt_input; + mrh->num_expected_coins = reveal_melt_input->melt_input->num_fresh_denom_pubs; mrh->request_url = TALER_url_join (exchange_url, "reveal-melt", NULL); @@ -367,6 +377,19 @@ TALER_EXCHANGE_reveal_melt ( GNUNET_free (mrh); return NULL; } + if (reveal_melt_input->num_blinding_values != + reveal_melt_input->melt_input->num_fresh_denom_pubs) + { + GNUNET_break (0); + GNUNET_free (mrh); + return NULL; + } + TALER_EXCHANGE_get_melt_data_v27 ( + reveal_melt_input->rms, + reveal_melt_input->melt_input, + reveal_melt_input->blinding_seed, + reveal_melt_input->blinding_values, + &mrh->md); perform_protocol (curl_ctx, mrh); diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c @@ -95,6 +95,11 @@ struct BlindingPrepareClosure const struct TALER_DenominationPublicKey *denom_pub; /** + * True, if denomination supports age restriction + */ + bool age_denom; + + /** * The index into the array of returned values from the call to * /blinding-prepare that are to be used for this coin. */ @@ -1008,7 +1013,7 @@ copy_results ( &coin->coin_priv, &coin->h_age_commitment, &coin->h_coin_pub, - &coin->alg_values, + &coin->blinding_values, &fresh_coin)) { resp.hr.http_status = 0; @@ -1206,7 +1211,7 @@ blinding_prepare_done ( case MHD_HTTP_OK: { bool success = false; - size_t num = bpr->details.ok.num; + size_t num = bpr->details.ok.num_blinding_values; GNUNET_assert (0 != num); GNUNET_assert (num == bpcls->num_nonces); @@ -1222,20 +1227,20 @@ blinding_prepare_done ( /* Complete the initialization of the coin with CS denomination */ TALER_denom_ewv_copy ( - &can->details.alg_values, - &bpr->details.ok.alg_values[cs_idx]); + &can->details.blinding_values, + &bpr->details.ok.blinding_values[cs_idx]); GNUNET_assert (GNUNET_CRYPTO_BSA_CS == - can->details.alg_values.blinding_inputs->cipher); + can->details.blinding_values.blinding_inputs->cipher); TALER_planchet_setup_coin_priv ( &can->details.secret, - &can->details.alg_values, + &can->details.blinding_values, &can->details.coin_priv); TALER_planchet_blinding_secret_create ( &can->details.secret, - &can->details.alg_values, + &can->details.blinding_values, &can->details.blinding_key); /* This initializes the 2nd half of the @@ -1243,7 +1248,7 @@ blinding_prepare_done ( if (GNUNET_OK != TALER_planchet_prepare ( bpcls->coins[i].denom_pub, - &can->details.alg_values, + &can->details.blinding_values, &can->details.blinding_key, &bpcls->nonces[cs_idx], &can->details.coin_priv, @@ -1406,6 +1411,7 @@ prepare_coins ( for (uint32_t i = 0; i < wh->num_coins; i++) { struct CoinData *cd = &wh->coin_data[i]; + bool age_denom = (0 != denoms_pub[i].key.age_mask.bits); cd->denom_pub = denoms_pub[i]; /* The age mask must be the same for all coins */ @@ -1444,7 +1450,7 @@ prepare_coins ( * support age restriction. Note that his is regardless of weither * with_age_proof is set or not. */ - if (0 != wh->age_mask.bits) + if (age_denom) { /* Derive the age restriction from the given secret and * the maximum age */ @@ -1462,21 +1468,23 @@ prepare_coins ( switch (cd->denom_pub.key.bsign_pub_key->cipher) { case GNUNET_CRYPTO_BSA_RSA: - TALER_denom_ewv_copy (&can->details.alg_values, + TALER_denom_ewv_copy (&can->details.blinding_values, TALER_denom_ewv_rsa_singleton ()); TALER_planchet_setup_coin_priv (&can->details.secret, - &can->details.alg_values, + &can->details.blinding_values, &can->details.coin_priv); TALER_planchet_blinding_secret_create (&can->details.secret, - &can->details.alg_values, + &can->details.blinding_values, &can->details.blinding_key); FAIL_IF (GNUNET_OK != TALER_planchet_prepare (&cd->denom_pub.key, - &can->details.alg_values, + &can->details.blinding_values, &can->details.blinding_key, NULL, &can->details.coin_priv, - &can->details.h_age_commitment, + (age_denom) + ? &can->details.h_age_commitment + : NULL, &can->details.h_coin_pub, planchet)); TALER_coin_ev_hash (&planchet->blinded_planchet, @@ -1495,6 +1503,7 @@ prepare_coins ( cs_closure->coins[cs_coin_idx].planchet = planchet; cs_closure->coins[cs_coin_idx].denom_pub = &cd->denom_pub.key; cs_closure->coins[cs_coin_idx].cs_idx = i; + cs_closure->coins[cs_coin_idx].age_denom = age_denom; cs_coin_idx++; break; } @@ -1759,7 +1768,7 @@ TALER_EXCHANGE_withdraw_cancel ( struct CoinCandidate *can = &cd->candidates[k]; TALER_blinded_planchet_free (&planchet->blinded_planchet); - TALER_denom_ewv_free (&can->details.alg_values); + TALER_denom_ewv_free (&can->details.blinding_values); TALER_age_commitment_proof_free (&can->details.age_commitment_proof); } TALER_denom_pub_free (&cd->denom_pub.key); diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c @@ -428,7 +428,7 @@ TALER_PQ_query_param_blinded_planchet ( * @return -1 on error, number of offsets used in @a scratch otherwise */ static int -qconv_exchange_withdraw_values (void *cls, +qconv_exchange_blinding_values (void *cls, const void *data, size_t data_len, void *param_values[], @@ -438,9 +438,9 @@ qconv_exchange_withdraw_values (void *cls, void *scratch[], unsigned int scratch_length) { - const struct TALER_ExchangeWithdrawValues *alg_values = data; + const struct TALER_ExchangeBlindingValues *blinding_values = data; const struct GNUNET_CRYPTO_BlindingInputValues *bi = - alg_values->blinding_inputs; + blinding_values->blinding_inputs; size_t tlen; size_t len; uint32_t be[2]; @@ -490,12 +490,12 @@ qconv_exchange_withdraw_values (void *cls, struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_exchange_withdraw_values ( - const struct TALER_ExchangeWithdrawValues *alg_values) +TALER_PQ_query_param_exchange_blinding_values ( + const struct TALER_ExchangeBlindingValues *blinding_values) { struct GNUNET_PQ_QueryParam res = { - .conv = &qconv_exchange_withdraw_values, - .data = alg_values, + .conv = &qconv_exchange_blinding_values, + .data = blinding_values, .num_params = 1 }; diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c @@ -989,7 +989,7 @@ extract_exchange_withdraw_values (void *cls, size_t *dst_size, void *dst) { - struct TALER_ExchangeWithdrawValues *alg_values = dst; + struct TALER_ExchangeBlindingValues *alg_values = dst; struct GNUNET_CRYPTO_BlindingInputValues *bi; size_t len; const char *res; @@ -1071,7 +1071,7 @@ extract_exchange_withdraw_values (void *cls, struct GNUNET_PQ_ResultSpec TALER_PQ_result_spec_exchange_withdraw_values ( const char *name, - struct TALER_ExchangeWithdrawValues *ewv) + struct TALER_ExchangeBlindingValues *ewv) { struct GNUNET_PQ_ResultSpec res = { .conv = &extract_exchange_withdraw_values, diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c @@ -42,8 +42,9 @@ postgres_prepare (struct GNUNET_PQ_Context *db) ",tamountc" ",hash" ",hashes" + ",cs_r_pubs" ") VALUES " - "($1, $2, $3, $4, $5, $6);"), + "($1, $2, $3, $4, $5, $6, $7);"), GNUNET_PQ_make_prepare ("test_select", "SELECT" " tamount" @@ -52,6 +53,7 @@ postgres_prepare (struct GNUNET_PQ_Context *db) ",tamountc" ",hash" ",hashes" + ",cs_r_pubs" " FROM test_pq;"), GNUNET_PQ_PREPARED_STATEMENT_END }; @@ -86,6 +88,7 @@ run_queries (struct GNUNET_PQ_Context *conn) 0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf, 0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf, 0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,0xdeadbeaf,}}}; + struct GNUNET_CRYPTO_CSPublicRPairP in_cs_r_pubs[5]; json_t *json; GNUNET_assert (GNUNET_OK == @@ -109,6 +112,9 @@ run_queries (struct GNUNET_PQ_Context *conn) json_object_set_new (json, "foo", json_integer (42))); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + in_cs_r_pubs, + sizeof(struct GNUNET_CRYPTO_CSPublicRPairP) * 5); { struct GNUNET_PQ_QueryParam params_insert[] = { TALER_PQ_query_param_amount (conn, @@ -124,6 +130,9 @@ run_queries (struct GNUNET_PQ_Context *conn) TALER_PQ_query_param_array_hash_code (2, hcs, conn), + TALER_PQ_query_param_array_cs_r_pub (5, + in_cs_r_pubs, + conn), GNUNET_PQ_query_param_end }; PGresult *result; @@ -131,6 +140,15 @@ run_queries (struct GNUNET_PQ_Context *conn) result = GNUNET_PQ_exec_prepared (conn, "test_insert", params_insert); + for (uint8_t i = 0; i < 5; i++) + { + printf (" in_cs_r_pubs[%d]=%s\n", + i, + GNUNET_STRINGS_data_to_string_alloc ( + &in_cs_r_pubs[i], + sizeof(in_cs_r_pubs[i]))); + } + if (PGRES_COMMAND_OK != PQresultStatus (result)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -148,8 +166,10 @@ run_queries (struct GNUNET_PQ_Context *conn) struct TALER_Amount *pamount; struct GNUNET_HashCode hc2; struct GNUNET_HashCode *hcs2; + struct GNUNET_CRYPTO_CSPublicRPairP *out_cs_r_pubs; size_t npamount; size_t nhcs; + size_t n_rpubs; json_t *json2; struct GNUNET_PQ_QueryParam params_select[] = { GNUNET_PQ_query_param_end @@ -173,6 +193,10 @@ run_queries (struct GNUNET_PQ_Context *conn) "hashes", &nhcs, &hcs2), + TALER_PQ_result_spec_array_cs_r_pub (conn, + "cs_r_pubs", + &n_rpubs, + &out_cs_r_pubs), GNUNET_PQ_result_spec_end }; @@ -208,6 +232,18 @@ run_queries (struct GNUNET_PQ_Context *conn) GNUNET_memcmp (&hcs[i], &hcs2[i])); } + GNUNET_break (5 == n_rpubs); + for (uint8_t i = 0; i < 5; i++) + { + GNUNET_break (0 == + GNUNET_memcmp (&in_cs_r_pubs[i], + &out_cs_r_pubs[i])); + printf ("out_cs_r_pubs[%d]=%s\n", + i, + GNUNET_STRINGS_data_to_string_alloc ( + &out_cs_r_pubs[i], + sizeof(out_cs_r_pubs[i]))); + } GNUNET_PQ_cleanup_result (results_select); } return 0; @@ -250,6 +286,7 @@ main (int argc, ",tamountc taler_amount_currency" ",hash gnunet_hashcode" ",hashes gnunet_hashcode[]" + ",cs_r_pubs BYTEA[]" ")"), GNUNET_PQ_EXECUTE_STATEMENT_END }; diff --git a/src/testing/test_auditor_api.c b/src/testing/test_auditor_api.c @@ -190,9 +190,9 @@ run (void *cls, /** * Complete (successful) melt operation, and withdraw the coins */ - TALER_TESTING_cmd_refresh_reveal ("refresh-reveal-1", - "refresh-melt-1", - MHD_HTTP_OK), + TALER_TESTING_cmd_melt_reveal ("refresh-reveal-1", + "refresh-melt-1", + MHD_HTTP_OK), /** * Try to spend a refreshed EUR:0.1 coin */ diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c @@ -344,25 +344,18 @@ run (void *cls, * Complete (successful) melt operation, and * withdraw the coins */ - TALER_TESTING_cmd_refresh_reveal ( + TALER_TESTING_cmd_melt_reveal ( "refresh-reveal-1", "refresh-melt-1", MHD_HTTP_OK), /** * Do it again to check idempotency */ - TALER_TESTING_cmd_refresh_reveal ( + TALER_TESTING_cmd_melt_reveal ( "refresh-reveal-1-idempotency", "refresh-melt-1", MHD_HTTP_OK), /** - * Test that /refresh/link works - */ - TALER_TESTING_cmd_refresh_link ( - "refresh-link-1", - "refresh-reveal-1", - MHD_HTTP_OK), - /** * Try to spend a refreshed EUR:1 coin */ TALER_TESTING_cmd_deposit ( @@ -636,25 +629,18 @@ run (void *cls, * Complete (successful) melt operation, and * withdraw the coins */ - TALER_TESTING_cmd_refresh_reveal ( + TALER_TESTING_cmd_melt_reveal ( "refresh-reveal-age-1", "refresh-melt-age-1", MHD_HTTP_OK), /** * Do it again to check idempotency */ - TALER_TESTING_cmd_refresh_reveal ( + TALER_TESTING_cmd_melt_reveal ( "refresh-reveal-age-1-idempotency", "refresh-melt-age-1", MHD_HTTP_OK), /** - * Test that /refresh/link works - */ - TALER_TESTING_cmd_refresh_link ( - "refresh-link-age-1", - "refresh-reveal-age-1", - MHD_HTTP_OK), - /** * Try to spend a refreshed EUR:1 coin */ TALER_TESTING_cmd_deposit ( @@ -953,7 +939,7 @@ run (void *cls, MHD_HTTP_OK, "EUR:5", NULL), - TALER_TESTING_cmd_refresh_reveal ( + TALER_TESTING_cmd_melt_reveal ( "recoup-reveal-coin-1b", "recoup-melt-coin-1b", MHD_HTTP_OK), @@ -989,7 +975,7 @@ run (void *cls, MHD_HTTP_OK, "EUR:1", NULL), - TALER_TESTING_cmd_refresh_reveal ( + TALER_TESTING_cmd_melt_reveal ( "recoup-reveal-coin-1a", "recoup-remelt-coin-1a", MHD_HTTP_OK), diff --git a/src/testing/test_exchange_api_age_restriction.c b/src/testing/test_exchange_api_age_restriction.c @@ -235,25 +235,18 @@ run (void *cls, * Complete (successful) melt operation, and * withdraw the coins */ - TALER_TESTING_cmd_refresh_reveal ( + TALER_TESTING_cmd_melt_reveal ( "refresh-reveal-age-1", "refresh-melt-age-1", MHD_HTTP_OK), /** * Do it again to check idempotency */ - TALER_TESTING_cmd_refresh_reveal ( + TALER_TESTING_cmd_melt_reveal ( "refresh-reveal-age-1-idempotency", "refresh-melt-age-1", MHD_HTTP_OK), /** - * Test that /refresh/link works - */ - TALER_TESTING_cmd_refresh_link ( - "refresh-link-age-1", - "refresh-reveal-age-1", - MHD_HTTP_OK), - /** * Try to spend a refreshed EUR:1 coin */ TALER_TESTING_cmd_deposit ( diff --git a/src/testing/test_exchange_api_twisted.c b/src/testing/test_exchange_api_twisted.c @@ -160,15 +160,19 @@ run (void *cls, "refresh-withdraw-coin", MHD_HTTP_OK, NULL), +#pragma message "conflict test must be adjusted to new melt/reveal API" +#if 0 /* Trigger 409 Conflict. */ TALER_TESTING_cmd_flip_upload ( "flip-upload", config_file, "transfer_privs.0"), - TALER_TESTING_cmd_refresh_reveal ( + + TALER_TESTING_cmd_melt_reveal ( "refresh-(flipped-)reveal", "refresh-melt", MHD_HTTP_CONFLICT), +#endif TALER_TESTING_cmd_end () }; diff --git a/src/testing/testing_api_cmd_age_withdraw.c b/src/testing/testing_api_cmd_age_withdraw.c @@ -219,8 +219,8 @@ age_withdraw_cb ( &aws->coin_outputs[n].details.age_commitment_proof, &response->details.created.coin_details[n].age_commitment_proof); TALER_denom_ewv_copy ( - &aws->coin_outputs[n].details.alg_values, - &response->details.created.coin_details[n].alg_values); + &aws->coin_outputs[n].details.blinding_values, + &response->details.created.coin_details[n].blinding_values); } break; case MHD_HTTP_FORBIDDEN: @@ -410,7 +410,7 @@ age_withdraw_cleanup ( { struct CoinOutputState *out = &aws->coin_outputs[n]; TALER_age_commitment_proof_free (&out->details.age_commitment_proof); - TALER_denom_ewv_free (&out->details.alg_values); + TALER_denom_ewv_free (&out->details.blinding_values); } GNUNET_free (aws->coin_outputs); aws->coin_outputs = NULL; @@ -470,8 +470,8 @@ age_withdraw_traits ( */ TALER_TESTING_make_trait_blinding_key (idx, &details->blinding_key), - TALER_TESTING_make_trait_exchange_wd_value (idx, - &details->alg_values), + TALER_TESTING_make_trait_exchange_blinding_values (idx, + &details->blinding_values), TALER_TESTING_make_trait_age_commitment_proof ( idx, &details->age_commitment_proof), @@ -640,7 +640,7 @@ age_reveal_withdraw_cb ( &response->details.ok.blinded_denom_sigs[n], &aws->coin_outputs[n].details.blinding_key, &aws->coin_outputs[n].details.h_coin_pub, - &aws->coin_outputs[n].details.alg_values, + &aws->coin_outputs[n].details.blinding_values, &aws->denoms_pub[n].key)); TALER_denom_sig_free (&awrs->denom_sigs[n]); } diff --git a/src/testing/testing_api_cmd_batch_withdraw.c b/src/testing/testing_api_cmd_batch_withdraw.c @@ -202,8 +202,8 @@ batch_withdraw_cb (void *cls, cs->details = wr->details.ok.coin_details[i]; TALER_denom_sig_copy (&cs->details.denom_sig, &wr->details.ok.coin_details[i].denom_sig); - TALER_denom_ewv_copy (&cs->details.alg_values, - &wr->details.ok.coin_details[i].alg_values); + TALER_denom_ewv_copy (&cs->details.blinding_values, + &wr->details.ok.coin_details[i].blinding_values); } ws->planchets_h = wr->details.ok.planchets_h; break; @@ -404,7 +404,7 @@ batch_withdraw_cleanup (void *cls, for (unsigned int i = 0; i<ws->num_coins; i++) { struct CoinState *cs = &ws->coins[i]; - TALER_denom_ewv_free (&cs->details.alg_values); + TALER_denom_ewv_free (&cs->details.blinding_values); TALER_denom_sig_free (&cs->details.denom_sig); if (NULL != cs->pk) { @@ -449,8 +449,9 @@ batch_withdraw_traits (void *cls, &cs->secret), TALER_TESTING_make_trait_blinding_key (index, &cs->details.blinding_key), - TALER_TESTING_make_trait_exchange_wd_value (index, - &cs->details.alg_values), + TALER_TESTING_make_trait_exchange_blinding_values (index, + &cs->details. + blinding_values), TALER_TESTING_make_trait_denom_pub (index, cs->pk), TALER_TESTING_make_trait_denom_sig (index, diff --git a/src/testing/testing_api_cmd_insert_deposit.c b/src/testing/testing_api_cmd_insert_deposit.c @@ -224,7 +224,7 @@ insert_deposit_run (void *cls, struct TALER_BlindedDenominationSignature bds; struct TALER_PlanchetMasterSecretP ps; union GNUNET_CRYPTO_BlindingSecretP bks; - const struct TALER_ExchangeWithdrawValues *alg_values; + const struct TALER_ExchangeBlindingValues *alg_values; alg_values = TALER_denom_ewv_rsa_singleton (); TALER_planchet_blinding_secret_create (&ps, diff --git a/src/testing/testing_api_cmd_recoup.c b/src/testing/testing_api_cmd_recoup.c @@ -195,7 +195,7 @@ recoup_run (void *cls, struct TALER_PlanchetMasterSecretP secret; char *cref; unsigned int idx; - const struct TALER_ExchangeWithdrawValues *ewv; + const struct TALER_ExchangeBlindingValues *ewv; struct TALER_DenominationHashP h_denom_pub; ps->is = is; @@ -231,9 +231,9 @@ recoup_run (void *cls, GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, &ps->coin.eddsa_pub); if (GNUNET_OK != - TALER_TESTING_get_trait_exchange_wd_value (coin_cmd, - idx, - &ewv)) + TALER_TESTING_get_trait_exchange_blinding_values (coin_cmd, + idx, + &ewv)) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); diff --git a/src/testing/testing_api_cmd_recoup_refresh.c b/src/testing/testing_api_cmd_recoup_refresh.c @@ -203,7 +203,7 @@ recoup_refresh_run (void *cls, const struct TALER_DenominationSignature *coin_sig; const struct TALER_RefreshMasterSecretP *rplanchet; const struct TALER_PlanchetMasterSecretP *planchet; - const struct TALER_ExchangeWithdrawValues *ewv; + const struct TALER_ExchangeBlindingValues *ewv; char *cref; unsigned int idx; struct TALER_DenominationHashP h_denom_pub; @@ -262,9 +262,9 @@ recoup_refresh_run (void *cls, &rrs->coin_pub_old.eddsa_pub); if (GNUNET_OK != - TALER_TESTING_get_trait_exchange_wd_value (melt_cmd, - idx, - &ewv)) + TALER_TESTING_get_trait_exchange_blinding_values (melt_cmd, + idx, + &ewv)) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); diff --git a/src/testing/testing_api_cmd_refresh.c b/src/testing/testing_api_cmd_refresh.c @@ -20,6 +20,7 @@ * @file testing/testing_api_cmd_refresh.c * @brief commands for testing all "refresh" features. * @author Marcello Stanisci + * @author Özgür Kesim */ #include "platform.h" #include "taler_json_lib.h" @@ -88,7 +89,7 @@ struct TALER_TESTING_FreshCoinData /** * State for a "refresh melt" command. */ -struct RefreshMeltState +struct MeltState { /** @@ -98,11 +99,6 @@ struct RefreshMeltState const char *coin_reference; /** - * Data used in the refresh operation. - */ - struct TALER_EXCHANGE_RefreshData refresh_data; - - /** * Our command. */ const struct TALER_TESTING_Command *cmd; @@ -115,7 +111,7 @@ struct RefreshMeltState /** * Melt handle while operation is running. */ - struct TALER_EXCHANGE_MeltHandle *rmh; + struct TALER_EXCHANGE_MeltHandle_v27 *mh; /** * Expected entry in the coin history created by this @@ -129,16 +125,41 @@ struct RefreshMeltState struct TALER_TESTING_Interpreter *is; /** + * The input for the call to /melt + */ + struct TALER_EXCHANGE_MeltInput melt_input; + + /** + * Length of the @a blinding_values array with the exchange values + * and blinding keys we are using. + */ + unsigned int num_blinding_values; + + /** + * Blinding values returned per coin. + */ + struct TALER_ExchangeBlindingValues *blinding_values; + + /** + * The input for the call to /reveal-melt + */ + struct TALER_EXCHANGE_RevealMeltInput reveal_melt_input; + + /** * Array of the denomination public keys * corresponding to the @e num_fresh_coins; */ struct TALER_EXCHANGE_DenomPublicKey *fresh_pks; /** - * Array of @e num_fresh_coins of results from - * the melt operation. + * Private key of the dirty coin being melted. + */ + const struct TALER_CoinSpendPrivateKeyP *melt_priv; + + /** + * Public key of the dirty coin being melted. */ - struct TALER_EXCHANGE_MeltBlindingDetail *mbds; + struct TALER_CoinSpendPublicKeyP melt_pub; /** * Entropy seed for the refresh-melt operation. @@ -146,14 +167,31 @@ struct RefreshMeltState struct TALER_RefreshMasterSecretP rms; /** - * Private key of the dirty coin being melted. + * The master seed to derive the nonces from */ - const struct TALER_CoinSpendPrivateKeyP *melt_priv; + struct TALER_PublicRefreshMasterSeedP refresh_seed; /** - * Public key of the dirty coin being melted. + * If false, @e blinding_seed contains the seed for the + * blinding values for CS signatures */ - struct TALER_CoinSpendPublicKeyP melt_pub; + bool no_blinding_seed; + + /** + * If @e no_blinding_seed is fals, contains the blinding + * seed from which the nonces were derived for CS signatures + */ + struct TALER_BlindingMasterSeedP blinding_seed; + + /** + * The refresh commitment we calculated + */ + struct TALER_RefreshCommitmentP rc; + + /** + * The kappa refresh nonces for signing with the old coin. + */ + struct TALER_KappaPublicRefreshNoncesP kappa_nonces; /** * Task scheduled to try later. @@ -207,13 +245,19 @@ struct RefreshMeltState * Set by the melt callback as it comes from the exchange. */ uint16_t noreveal_index; + + /** + * The signatures over the nonces we need to reveal + */ + struct TALER_RevealPrivateRefreshNonceSignaturesP revealed_signatures; + }; /** * State for a "refresh reveal" CMD. */ -struct RefreshRevealState +struct RevealMeltState { /** * Link to a "refresh melt" command. @@ -223,7 +267,7 @@ struct RefreshRevealState /** * Reveal handle while operation is running. */ - struct TALER_EXCHANGE_RefreshesRevealHandle *rrh; + struct TALER_EXCHANGE_RevealMeltHandle *rmh; /** * Our command. @@ -344,26 +388,26 @@ struct RefreshLinkState * @param is the interpreter state. */ static void -refresh_reveal_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is); +melt_reveal_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is); /** - * Task scheduled to re-try #refresh_reveal_run. + * Task scheduled to re-try #melt_reveal_run. * * @param cls a `struct RefreshRevealState` */ static void do_reveal_retry (void *cls) { - struct RefreshRevealState *rrs = cls; + struct RevealMeltState *rrs = cls; rrs->retry_task = NULL; TALER_TESTING_touch_cmd (rrs->is); - refresh_reveal_run (rrs, - NULL, - rrs->is); + melt_reveal_run (rrs, + NULL, + rrs->is); } @@ -372,18 +416,18 @@ do_reveal_retry (void *cls) * code is expected and copies into its command's state the data * coming from the exchange, namely the fresh coins. * - * @param cls closure, a `struct RefreshRevealState` - * @param rr HTTP response details + * @param cls closure, a `struct RevealMeltState` + * @param rmr HTTP response details */ static void reveal_cb (void *cls, - const struct TALER_EXCHANGE_RevealResult *rr) + const struct TALER_EXCHANGE_RevealMeltResponse *rmr) { - struct RefreshRevealState *rrs = cls; - const struct TALER_EXCHANGE_HttpResponse *hr = &rr->hr; + struct RevealMeltState *rrs = cls; + const struct TALER_EXCHANGE_HttpResponse *hr = &rmr->hr; const struct TALER_TESTING_Command *melt_cmd; - rrs->rrh = NULL; + rrs->rmh = NULL; if (rrs->expected_response_code != hr->http_status) { if (0 != rrs->do_retry) @@ -428,7 +472,7 @@ reveal_cb (void *cls, switch (hr->http_status) { case MHD_HTTP_OK: - rrs->num_fresh_coins = rr->details.ok.num_coins; + rrs->num_fresh_coins = rmr->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, @@ -436,7 +480,7 @@ reveal_cb (void *cls, for (unsigned int i = 0; i<rrs->num_fresh_coins; i++) { const struct TALER_EXCHANGE_RevealedCoinInfo *coin - = &rr->details.ok.coins[i]; + = &rmr->details.ok.coins[i]; struct TALER_TESTING_FreshCoinData *fc = &rrs->fresh_coins[i]; rrs->psa[i] = coin->ps; @@ -502,12 +546,12 @@ melt_run (void *cls, * @param is the interpreter state. */ static void -refresh_reveal_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is) +melt_reveal_run (void *cls, + const struct TALER_TESTING_Command *cmd, + struct TALER_TESTING_Interpreter *is) { - struct RefreshRevealState *rrs = cls; - struct RefreshMeltState *rms; + struct RevealMeltState *rrs = cls; + struct MeltState *rms; const struct TALER_TESTING_Command *melt_cmd; rrs->cmd = cmd; @@ -522,24 +566,22 @@ refresh_reveal_run (void *cls, } GNUNET_assert (melt_cmd->run == &melt_run); rms = melt_cmd->cls; - { - 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; -#pragma message "use TALER_EXCHANGE_reveal_melt" - 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) + rms->reveal_melt_input.rms = &rms->rms; + rms->reveal_melt_input.melt_input = &rms->melt_input; + rms->reveal_melt_input.blinding_seed = rms->no_blinding_seed + ? NULL + : &rms-> + blinding_seed; + rms->reveal_melt_input.num_blinding_values = rms->num_blinding_values; + rms->reveal_melt_input.blinding_values = rms->blinding_values; + rms->reveal_melt_input.noreveal_index = rms->noreveal_index; + rrs->rmh = TALER_EXCHANGE_reveal_melt ( + TALER_TESTING_interpreter_get_context (is), + TALER_TESTING_get_exchange_url (is), + &rms->reveal_melt_input, + &reveal_cb, + rrs); + if (NULL == rrs->rmh) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); @@ -556,18 +598,18 @@ refresh_reveal_run (void *cls, * @param cmd the command which is being cleaned up. */ static void -refresh_reveal_cleanup (void *cls, - const struct TALER_TESTING_Command *cmd) +melt_reveal_cleanup (void *cls, + const struct TALER_TESTING_Command *cmd) { - struct RefreshRevealState *rrs = cls; + struct RevealMeltState *rrs = cls; (void) cmd; - if (NULL != rrs->rrh) + if (NULL != rrs->rmh) { TALER_TESTING_command_incomplete (rrs->is, cmd->label); - TALER_EXCHANGE_refreshes_reveal_cancel (rrs->rrh); - rrs->rrh = NULL; + TALER_EXCHANGE_reveal_melt_cancel (rrs->rmh); + rrs->rmh = NULL; } if (NULL != rrs->retry_task) { @@ -581,7 +623,6 @@ refresh_reveal_cleanup (void *cls, 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); GNUNET_free (rrs->psa); rrs->num_fresh_coins = 0; @@ -590,315 +631,6 @@ refresh_reveal_cleanup (void *cls, /** - * Run the command. - * - * @param cls closure. - * @param cmd the command to execute. - * @param is the interpreter state. - */ -static void -refresh_link_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is); - - -/** - * Task scheduled to re-try #refresh_link_run. - * - * @param cls a `struct RefreshLinkState` - */ -static void -do_link_retry (void *cls) -{ - struct RefreshLinkState *rls = cls; - - rls->retry_task = NULL; - TALER_TESTING_touch_cmd (rls->is); - refresh_link_run (rls, - NULL, - rls->is); -} - - -/** - * "refresh link" operation callback, checks that HTTP response - * code is expected _and_ that all the linked coins were actually - * withdrawn by the "refresh reveal" CMD. - * - * @param cls closure. - * @param lr HTTP response details - */ -static void -link_cb (void *cls, - 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; - unsigned int found; - const unsigned int *num_fresh_coins; - - rls->rlh = NULL; - if (rls->expected_response_code != hr->http_status) - { - if (0 != rls->do_retry) - { - rls->do_retry--; - if ( (0 == hr->http_status) || - (TALER_EC_GENERIC_DB_SOFT_FAILURE == hr->ec) || - (MHD_HTTP_INTERNAL_SERVER_ERROR == hr->http_status) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Retrying refresh link failed with %u/%d\n", - hr->http_status, - (int) hr->ec); - /* on DB conflicts, do not use backoff */ - if (TALER_EC_GENERIC_DB_SOFT_FAILURE == hr->ec) - rls->backoff = GNUNET_TIME_UNIT_ZERO; - else - rls->backoff = GNUNET_TIME_randomized_backoff (rls->backoff, - MAX_BACKOFF); - rls->total_backoff = GNUNET_TIME_relative_add (rls->total_backoff, - rls->backoff); - TALER_TESTING_inc_tries (rls->is); - rls->retry_task = GNUNET_SCHEDULER_add_delayed (rls->backoff, - &do_link_retry, - rls); - return; - } - } - TALER_TESTING_unexpected_status (rls->is, - hr->http_status, - rls->expected_response_code); - return; - } - reveal_cmd = TALER_TESTING_interpreter_lookup_command (rls->is, - rls->reveal_reference); - if (NULL == reveal_cmd) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } - - switch (hr->http_status) - { - case MHD_HTTP_OK: - /* check that number of coins returned matches */ - if (GNUNET_OK != - TALER_TESTING_get_trait_array_length (reveal_cmd, - &num_fresh_coins)) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } - 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", - lr->details.ok.num_coins, - *num_fresh_coins, - __FILE__, - __LINE__); - TALER_TESTING_interpreter_fail (rls->is); - return; - } - /* check that the coins match */ - 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 (&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; - - /* Will point to the pointer inside the cmd state. */ - { - const struct TALER_TESTING_FreshCoinData **fc = NULL; - - if (GNUNET_OK != - TALER_TESTING_get_trait_fresh_coins (reveal_cmd, - &fc)) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } - - 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 (&fcj->coin_priv, - &lci_i->coin_priv)) && - (0 == - TALER_denom_sig_cmp (&fcj->sig, - &lci_i->sig)) && - (0 == - TALER_denom_pub_cmp (&fcj->pk->key, - &lci_i->pub)) ) - { - found++; - break; - } - } /* for j*/ - } /* for i */ - } - if (found != lr->details.ok.num_coins) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Only %u/%u coins match expectations\n", - found, - lr->details.ok.num_coins); - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } - if (0 != rls->total_backoff.rel_value_us) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Total link backoff for %s was %s\n", - rls->cmd->label, - GNUNET_STRINGS_relative_time_to_string (rls->total_backoff, - true)); - } - break; - default: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unknown HTTP response code %u/%d.\n", - hr->http_status, - hr->ec); - } - TALER_TESTING_interpreter_next (rls->is); -} - - -/** - * Run the command. - * - * @param cls closure. - * @param cmd the command to execute. - * @param is the interpreter state. - */ -static void -refresh_link_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is) -{ - struct RefreshLinkState *rls = cls; - struct RefreshRevealState *rrs; - struct RefreshMeltState *rms; - 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; - const struct TALER_CoinSpendPrivateKeyP *coin_priv; - - 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) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } - rrs = reveal_cmd->cls; - melt_cmd = TALER_TESTING_interpreter_lookup_command (rls->is, - rrs->melt_reference); - if (NULL == melt_cmd) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } - - /* 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) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } - - if (GNUNET_OK != - TALER_TESTING_get_trait_coin_priv (coin_cmd, - 0, - &coin_priv)) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } - - /* finally, use private key from withdraw sign command */ - 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) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (rls->is); - return; - } -} - - -/** - * Free the state of the "refresh link" CMD, and possibly - * cancel a operation thereof. - * - * @param cls closure - * @param cmd the command which is being cleaned up. - */ -static void -refresh_link_cleanup (void *cls, - const struct TALER_TESTING_Command *cmd) -{ - struct RefreshLinkState *rls = cls; - - if (NULL != rls->rlh) - { - TALER_TESTING_command_incomplete (rls->is, - cmd->label); - TALER_EXCHANGE_link_cancel (rls->rlh); - rls->rlh = NULL; - } - if (NULL != rls->retry_task) - { - GNUNET_SCHEDULER_cancel (rls->retry_task); - rls->retry_task = NULL; - } - GNUNET_free (rls); -} - - -/** * Task scheduled to re-try #melt_run. * * @param cls a `struct RefreshMeltState` @@ -906,7 +638,7 @@ refresh_link_cleanup (void *cls, static void do_melt_retry (void *cls) { - struct RefreshMeltState *rms = cls; + struct MeltState *rms = cls; rms->retry_task = NULL; TALER_TESTING_touch_cmd (rms->is); @@ -917,7 +649,7 @@ do_melt_retry (void *cls) /** - * Callback for a "refresh melt" operation; checks if the HTTP + * Callback for a " /melt" operation; checks if the HTTP * response code is okay and re-run the melt operation if the * CMD was set to do so. * @@ -926,12 +658,12 @@ do_melt_retry (void *cls) */ static void melt_cb (void *cls, - const struct TALER_EXCHANGE_MeltResponse *mr) + const struct TALER_EXCHANGE_MeltResponse_v27 *mr) { - struct RefreshMeltState *rms = cls; + struct MeltState *rms = cls; const struct TALER_EXCHANGE_HttpResponse *hr = &mr->hr; - rms->rmh = NULL; + rms->mh = NULL; if (rms->expected_response_code != hr->http_status) { if (0 != rms->do_retry) @@ -969,19 +701,24 @@ melt_cb (void *cls, 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) + if (mr->details.ok.num_melt_blinding_values != 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); + rms->no_blinding_seed = (NULL == mr->details.ok.blinding_seed); + if (NULL != mr->details.ok.blinding_seed) + rms->blinding_seed = *mr->details.ok.blinding_seed; + rms->num_blinding_values = mr->details.ok.num_melt_blinding_values; + rms->blinding_values = GNUNET_new_array ( + rms->num_blinding_values, + struct TALER_ExchangeBlindingValues); + for (unsigned int i = 0; i<rms->num_blinding_values; i++) + { + TALER_denom_ewv_copy (&rms->blinding_values[i], + &mr->details.ok.melt_blinding_values[i]); + } } if (0 != rms->total_backoff.rel_value_us) { @@ -995,13 +732,12 @@ melt_cb (void *cls, { TALER_LOG_DEBUG ("Doubling the melt (%s)\n", rms->cmd->label); -#pragma message "use TALER_EXCHANGE_melt_v27" - rms->rmh = TALER_EXCHANGE_melt ( + rms->mh = TALER_EXCHANGE_melt_v27 ( 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, + &rms->melt_input, &melt_cb, rms); rms->double_melt = false; @@ -1027,7 +763,7 @@ melt_run (void *cls, "EUR:1", "EUR:1", "EUR:1", "EUR:0.1", NULL }; - struct RefreshMeltState *rms = cls; + struct MeltState *rms = cls; unsigned int num_fresh_coins; const char **melt_fresh_amounts; @@ -1159,21 +895,21 @@ melt_run (void *cls, &fresh_pk->key); } /* end for */ - rms->refresh_data.melt_priv = *rms->melt_priv; + rms->melt_input.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; + rms->melt_input.melt_amount = melt_amount; + rms->melt_input.melt_sig = *melt_sig; + rms->melt_input.melt_pk = *melt_denom_pub; if (NULL != age_commitment_proof) { 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->melt_input.melt_age_commitment_proof = age_commitment_proof; + rms->melt_input.melt_h_age_commitment = h_age_commitment; } - rms->refresh_data.fresh_pks = rms->fresh_pks; - rms->refresh_data.fresh_pks_len = num_fresh_coins; + rms->melt_input.fresh_denom_pubs = rms->fresh_pks; + rms->melt_input.num_fresh_denom_pubs = num_fresh_coins; GNUNET_assert (age_restricted_denom == (NULL != age_commitment_proof)); @@ -1187,17 +923,16 @@ melt_run (void *cls, else rms->che.details.melt.no_hac = true; -#pragma message "use TALER_EXCHANGE_melt_v27" - rms->rmh = TALER_EXCHANGE_melt ( + rms->mh = TALER_EXCHANGE_melt_v27 ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_exchange_url (is), TALER_TESTING_get_keys (is), &rms->rms, - &rms->refresh_data, + &rms->melt_input, &melt_cb, rms); - if (NULL == rms->rmh) + if (NULL == rms->mh) { GNUNET_break (0); TALER_TESTING_interpreter_fail (rms->is); @@ -1218,15 +953,15 @@ static void melt_cleanup (void *cls, const struct TALER_TESTING_Command *cmd) { - struct RefreshMeltState *rms = cls; + struct MeltState *rms = cls; (void) cmd; - if (NULL != rms->rmh) + if (NULL != rms->mh) { TALER_TESTING_command_incomplete (rms->is, cmd->label); - TALER_EXCHANGE_melt_cancel (rms->rmh); - rms->rmh = NULL; + TALER_EXCHANGE_melt_v27_cancel (rms->mh); + rms->mh = NULL; } if (NULL != rms->retry_task) { @@ -1239,11 +974,11 @@ melt_cleanup (void *cls, TALER_denom_pub_free (&rms->fresh_pks[i].key); GNUNET_free (rms->fresh_pks); } - if (NULL != rms->mbds) + if (NULL != rms->blinding_values) { - for (unsigned int i = 0; i < rms->num_fresh_coins; i++) - TALER_denom_ewv_free (&rms->mbds[i].alg_value); - GNUNET_free (rms->mbds); + for (unsigned int i = 0; i < rms->num_blinding_values; i++) + TALER_denom_ewv_free (&rms->blinding_values[i]); + GNUNET_free (rms->blinding_values); } GNUNET_free (rms->melt_fresh_amounts); GNUNET_free (rms); @@ -1265,7 +1000,7 @@ melt_traits (void *cls, const char *trait, unsigned int index) { - struct RefreshMeltState *rms = cls; + struct MeltState *rms = cls; if (index >= rms->num_fresh_coins) { @@ -1284,14 +1019,15 @@ melt_traits (void *cls, &rms->che), TALER_TESTING_make_trait_age_commitment_proof ( index, - rms->refresh_data.melt_age_commitment_proof), + rms->melt_input.melt_age_commitment_proof), TALER_TESTING_make_trait_h_age_commitment ( index, - rms->refresh_data.melt_h_age_commitment), + rms->melt_input.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) + (NULL != rms->reveal_melt_input.blinding_values) + ? TALER_TESTING_make_trait_exchange_blinding_values ( + index, + &rms->reveal_melt_input.blinding_values[index ]) : TALER_TESTING_trait_end (), TALER_TESTING_trait_end () }; @@ -1312,7 +1048,7 @@ melt_traits (void *cls, * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -parse_amounts (struct RefreshMeltState *rms, +parse_amounts (struct MeltState *rms, va_list ap) { unsigned int len; @@ -1360,10 +1096,10 @@ TALER_TESTING_cmd_melt (const char *label, unsigned int expected_response_code, ...) { - struct RefreshMeltState *rms; + struct MeltState *rms; va_list ap; - rms = GNUNET_new (struct RefreshMeltState); + rms = GNUNET_new (struct MeltState); rms->coin_reference = coin_reference; rms->expected_response_code = expected_response_code; va_start (ap, @@ -1391,10 +1127,10 @@ TALER_TESTING_cmd_melt_double (const char *label, unsigned int expected_response_code, ...) { - struct RefreshMeltState *rms; + struct MeltState *rms; va_list ap; - rms = GNUNET_new (struct RefreshMeltState); + rms = GNUNET_new (struct MeltState); rms->coin_reference = coin_reference; rms->expected_response_code = expected_response_code; rms->double_melt = true; @@ -1420,7 +1156,7 @@ TALER_TESTING_cmd_melt_double (const char *label, struct TALER_TESTING_Command TALER_TESTING_cmd_melt_with_retry (struct TALER_TESTING_Command cmd) { - struct RefreshMeltState *rms; + struct MeltState *rms; GNUNET_assert (&melt_run == cmd.run); rms = cmd.cls; @@ -1439,12 +1175,12 @@ TALER_TESTING_cmd_melt_with_retry (struct TALER_TESTING_Command cmd) * @return #GNUNET_OK on success. */ static enum GNUNET_GenericReturnValue -refresh_reveal_traits (void *cls, - const void **ret, - const char *trait, - unsigned int index) +melt_reveal_traits (void *cls, + const void **ret, + const char *trait, + unsigned int index) { - struct RefreshRevealState *rrs = cls; + struct RevealMeltState *rrs = cls; if (index >= rrs->num_fresh_coins) return GNUNET_SYSERR; @@ -1487,22 +1223,22 @@ refresh_reveal_traits (void *cls, struct TALER_TESTING_Command -TALER_TESTING_cmd_refresh_reveal (const char *label, - const char *melt_reference, - unsigned int expected_response_code) +TALER_TESTING_cmd_melt_reveal (const char *label, + const char *melt_reference, + unsigned int expected_response_code) { - struct RefreshRevealState *rrs; + struct RevealMeltState *rrs; - rrs = GNUNET_new (struct RefreshRevealState); + rrs = GNUNET_new (struct RevealMeltState); rrs->melt_reference = melt_reference; rrs->expected_response_code = expected_response_code; { struct TALER_TESTING_Command cmd = { .cls = rrs, .label = label, - .run = &refresh_reveal_run, - .cleanup = &refresh_reveal_cleanup, - .traits = &refresh_reveal_traits + .run = &melt_reveal_run, + .cleanup = &melt_reveal_cleanup, + .traits = &melt_reveal_traits }; return cmd; @@ -1511,47 +1247,12 @@ TALER_TESTING_cmd_refresh_reveal (const char *label, struct TALER_TESTING_Command -TALER_TESTING_cmd_refresh_reveal_with_retry (struct TALER_TESTING_Command cmd) +TALER_TESTING_cmd_melt_reveal_with_retry (struct TALER_TESTING_Command cmd) { - struct RefreshRevealState *rrs; + struct RevealMeltState *rrs; - GNUNET_assert (&refresh_reveal_run == cmd.run); + GNUNET_assert (&melt_reveal_run == cmd.run); rrs = cmd.cls; rrs->do_retry = NUM_RETRIES; return cmd; } - - -struct TALER_TESTING_Command -TALER_TESTING_cmd_refresh_link (const char *label, - const char *reveal_reference, - unsigned int expected_response_code) -{ - struct RefreshLinkState *rrs; - - rrs = GNUNET_new (struct RefreshLinkState); - rrs->reveal_reference = reveal_reference; - rrs->expected_response_code = expected_response_code; - { - struct TALER_TESTING_Command cmd = { - .cls = rrs, - .label = label, - .run = &refresh_link_run, - .cleanup = &refresh_link_cleanup - }; - - return cmd; - } -} - - -struct TALER_TESTING_Command -TALER_TESTING_cmd_refresh_link_with_retry (struct TALER_TESTING_Command cmd) -{ - struct RefreshLinkState *rls; - - GNUNET_assert (&refresh_link_run == cmd.run); - rls = cmd.cls; - rls->do_retry = NUM_RETRIES; - return cmd; -} diff --git a/src/testing/testing_api_cmd_withdraw.c b/src/testing/testing_api_cmd_withdraw.c @@ -21,6 +21,7 @@ * @brief main interpreter loop for testcases * @author Christian Grothoff * @author Marcello Stanisci + * @author Özgür Kesim */ #include "platform.h" #include "taler_json_lib.h" @@ -119,7 +120,7 @@ struct WithdrawState * Values contributed from the exchange during the * withdraw protocol. */ - struct TALER_ExchangeWithdrawValues exchange_vals; + struct TALER_ExchangeBlindingValues exchange_vals; /** * Interpreter state (during command). @@ -308,7 +309,7 @@ withdraw_cb (void *cls, ws->coin_priv = wr->details.ok.coin_details[0].coin_priv; ws->bks = wr->details.ok.coin_details[0].blinding_key; TALER_denom_ewv_copy (&ws->exchange_vals, - &wr->details.ok.coin_details[0].alg_values); + &wr->details.ok.coin_details[0].blinding_values); ws->planchets_h = wr->details.ok.planchets_h; if (0<ws->age) { @@ -551,8 +552,8 @@ withdraw_traits (void *cls, TALER_TESTING_make_trait_withdraw_commitment (&ws->planchets_h), TALER_TESTING_make_trait_blinding_key (0 /* only one coin */, &ws->bks), - TALER_TESTING_make_trait_exchange_wd_value (0 /* only one coin */, - &ws->exchange_vals), + TALER_TESTING_make_trait_exchange_blinding_values (0 /* only one coin */, + &ws->exchange_vals), TALER_TESTING_make_trait_denom_pub (0 /* only one coin */, ws->pk), TALER_TESTING_make_trait_denom_sig (0 /* only one coin */, diff --git a/src/util/age_restriction.c b/src/util/age_restriction.c @@ -269,6 +269,35 @@ TALER_age_commitment_derive ( enum GNUNET_GenericReturnValue +TALER_age_commitment_derive_from_secret ( + const struct TALER_AgeCommitment *orig, + const struct TALER_PlanchetMasterSecretP *secret, + struct TALER_AgeCommitment *newac) +{ + struct GNUNET_HashCode salt; + enum GNUNET_GenericReturnValue ret; + + ret = GNUNET_CRYPTO_kdf (&salt, + sizeof (salt), + "age commitment", + strlen ("age commitment"), + secret, + sizeof(*secret), + NULL, 0); + if (GNUNET_OK != ret) + { + GNUNET_break (0); + return ret; + } + + return TALER_age_commitment_derive ( + orig, + &salt, + newac); +} + + +enum GNUNET_GenericReturnValue TALER_age_commitment_proof_derive ( const struct TALER_AgeCommitmentProof *orig, const struct GNUNET_HashCode *salt, @@ -330,6 +359,35 @@ TALER_age_commitment_proof_derive ( } +enum GNUNET_GenericReturnValue +TALER_age_commitment_proof_derive_from_secret ( + const struct TALER_AgeCommitmentProof *orig, + const struct TALER_PlanchetMasterSecretP *secret, + struct TALER_AgeCommitmentProof *newacp) +{ + struct GNUNET_HashCode salt; + enum GNUNET_GenericReturnValue ret; + + ret = GNUNET_CRYPTO_kdf (&salt, + sizeof (salt), + "age commitment", + strlen ("age commitment"), + secret, + sizeof(*secret), + NULL, 0); + if (GNUNET_OK != ret) + { + GNUNET_break (0); + return ret; + } + + return TALER_age_commitment_proof_derive ( + orig, + &salt, + newacp); +} + + GNUNET_NETWORK_STRUCT_BEGIN /** diff --git a/src/util/crypto.c b/src/util/crypto.c @@ -476,18 +476,18 @@ TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs, enum GNUNET_GenericReturnValue TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct + TALER_ExchangeBlindingValues *blinding_values, const union GNUNET_CRYPTO_BlindingSecretP *bks, const union GNUNET_CRYPTO_BlindSessionNonce *nonce, const struct TALER_CoinSpendPrivateKeyP *coin_priv, const struct TALER_AgeCommitmentHash *ach, struct TALER_CoinPubHashP *c_hash, - struct TALER_PlanchetDetail *pd - ) + struct TALER_PlanchetDetail *pd) { struct TALER_CoinSpendPublicKeyP coin_pub; - GNUNET_assert (alg_values->blinding_inputs->cipher == + GNUNET_assert (blinding_values->blinding_inputs->cipher == dk->bsign_pub_key->cipher); GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, &coin_pub.eddsa_pub); @@ -497,7 +497,7 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, nonce, ach, &coin_pub, - alg_values, + blinding_values, c_hash, &pd->blinded_planchet)) { @@ -525,7 +525,7 @@ TALER_planchet_to_coin ( const struct TALER_CoinSpendPrivateKeyP *coin_priv, const struct TALER_AgeCommitmentHash *ach, const struct TALER_CoinPubHashP *c_hash, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, struct TALER_FreshCoin *coin) { if (dk->bsign_pub_key->cipher != diff --git a/src/util/denom.c b/src/util/denom.c @@ -71,7 +71,7 @@ TALER_denom_sig_unblind ( const struct TALER_BlindedDenominationSignature *bdenom_sig, const union GNUNET_CRYPTO_BlindingSecretP *bks, const struct TALER_CoinPubHashP *c_hash, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, const struct TALER_DenominationPublicKey *denom_pub) { denom_sig->unblinded_sig @@ -135,13 +135,13 @@ TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub, } -const struct TALER_ExchangeWithdrawValues * +const struct TALER_ExchangeBlindingValues * TALER_denom_ewv_rsa_singleton () { static struct GNUNET_CRYPTO_BlindingInputValues bi = { .cipher = GNUNET_CRYPTO_BSA_RSA }; - static struct TALER_ExchangeWithdrawValues alg_values = { + static struct TALER_ExchangeBlindingValues alg_values = { .blinding_inputs = &bi }; return &alg_values; @@ -155,7 +155,7 @@ TALER_denom_blind ( const union GNUNET_CRYPTO_BlindSessionNonce *nonce, const struct TALER_AgeCommitmentHash *ach, const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, struct TALER_CoinPubHashP *c_hash, struct TALER_BlindedPlanchet *blinded_planchet) { @@ -233,7 +233,7 @@ TALER_blinded_denom_sig_free ( void -TALER_denom_ewv_free (struct TALER_ExchangeWithdrawValues *ewv) +TALER_denom_ewv_free (struct TALER_ExchangeBlindingValues *ewv) { if (ewv == TALER_denom_ewv_rsa_singleton ()) return; @@ -252,8 +252,8 @@ TALER_denom_ewv_free (struct TALER_ExchangeWithdrawValues *ewv) void -TALER_denom_ewv_copy (struct TALER_ExchangeWithdrawValues *bi_dst, - const struct TALER_ExchangeWithdrawValues *bi_src) +TALER_denom_ewv_copy (struct TALER_ExchangeBlindingValues *bi_dst, + const struct TALER_ExchangeBlindingValues *bi_src) { if (bi_src == TALER_denom_ewv_rsa_singleton ()) { @@ -373,7 +373,7 @@ TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp, void TALER_planchet_blinding_secret_create ( const struct TALER_PlanchetMasterSecretP *ps, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, union GNUNET_CRYPTO_BlindingSecretP *bks) { const struct GNUNET_CRYPTO_BlindingInputValues *bi = @@ -416,7 +416,7 @@ TALER_planchet_blinding_secret_create ( void TALER_planchet_setup_coin_priv ( const struct TALER_PlanchetMasterSecretP *ps, - const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_ExchangeBlindingValues *alg_values, struct TALER_CoinSpendPrivateKeyP *coin_priv) { const struct GNUNET_CRYPTO_BlindingInputValues *bi diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c @@ -46,10 +46,10 @@ test_high_level (void) struct GNUNET_CRYPTO_BlindingInputValues bi = { .cipher = GNUNET_CRYPTO_BSA_RSA }; - struct TALER_ExchangeWithdrawValues alg1 = { + struct TALER_ExchangeBlindingValues alg1 = { .blinding_inputs = &bi }; - struct TALER_ExchangeWithdrawValues alg2 = { + struct TALER_ExchangeBlindingValues alg2 = { .blinding_inputs = &bi }; @@ -124,7 +124,7 @@ test_planchets_rsa (uint8_t age) union GNUNET_CRYPTO_BlindingSecretP bks; struct TALER_DenominationPrivateKey dk_priv; struct TALER_DenominationPublicKey dk_pub; - const struct TALER_ExchangeWithdrawValues *alg_values; + const struct TALER_ExchangeBlindingValues *alg_values; struct TALER_PlanchetDetail pd; struct TALER_BlindedDenominationSignature blind_sig; struct TALER_FreshCoin coin; @@ -227,7 +227,7 @@ test_planchets_cs (uint8_t age) union GNUNET_CRYPTO_BlindSessionNonce nonce; struct TALER_BlindedDenominationSignature blind_sig; struct TALER_FreshCoin coin; - struct TALER_ExchangeWithdrawValues alg_values; + struct TALER_ExchangeBlindingValues alg_values; struct TALER_AgeCommitmentHash *ach = NULL; struct TALER_AgeCommitmentHash ah = {0}; diff --git a/src/util/test_helper_cs.c b/src/util/test_helper_cs.c @@ -273,7 +273,7 @@ test_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh) struct GNUNET_CRYPTO_BlindingInputValues bi = { .cipher = GNUNET_CRYPTO_BSA_CS }; - struct TALER_ExchangeWithdrawValues alg_values = { + struct TALER_ExchangeBlindingValues alg_values = { .blinding_inputs = &bi }; union GNUNET_CRYPTO_BlindSessionNonce nonce; @@ -434,7 +434,7 @@ test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh) struct GNUNET_CRYPTO_BlindingInputValues bi = { .cipher = GNUNET_CRYPTO_BSA_CS }; - struct TALER_ExchangeWithdrawValues alg_values = { + struct TALER_ExchangeBlindingValues alg_values = { .blinding_inputs = &bi }; union GNUNET_CRYPTO_BlindSessionNonce nonce; @@ -632,7 +632,7 @@ test_batch_signing (struct TALER_CRYPTO_CsDenominationHelper *dh, union GNUNET_CRYPTO_BlindingSecretP bks[batch_size]; struct TALER_CoinPubHashP c_hash[batch_size]; struct GNUNET_CRYPTO_BlindingInputValues bi[batch_size]; - struct TALER_ExchangeWithdrawValues alg_values[batch_size]; + struct TALER_ExchangeBlindingValues alg_values[batch_size]; union GNUNET_CRYPTO_BlindSessionNonce nonces[batch_size]; for (unsigned int i = 0; i<batch_size; i++) @@ -850,7 +850,7 @@ perf_signing (struct TALER_CRYPTO_CsDenominationHelper *dh, struct GNUNET_CRYPTO_BlindingInputValues bv = { .cipher = GNUNET_CRYPTO_BSA_CS }; - struct TALER_ExchangeWithdrawValues alg_values = { + struct TALER_ExchangeBlindingValues alg_values = { .blinding_inputs = &bv }; diff --git a/src/util/test_helper_rsa.c b/src/util/test_helper_rsa.c @@ -268,7 +268,7 @@ test_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh) enum TALER_ErrorCode ec; bool success = false; struct TALER_PlanchetMasterSecretP ps; - const struct TALER_ExchangeWithdrawValues *alg_values + const struct TALER_ExchangeBlindingValues *alg_values = TALER_denom_ewv_rsa_singleton (); struct TALER_AgeCommitmentHash ach; struct TALER_CoinPubHashP c_hash; @@ -462,7 +462,7 @@ test_batch_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh, enum TALER_ErrorCode ec; bool success = false; struct TALER_PlanchetMasterSecretP ps[batch_size]; - const struct TALER_ExchangeWithdrawValues *alg_values; + const struct TALER_ExchangeBlindingValues *alg_values; struct TALER_AgeCommitmentHash ach[batch_size]; struct TALER_CoinPubHashP c_hash[batch_size]; struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size]; @@ -683,7 +683,7 @@ perf_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh, struct TALER_CoinSpendPrivateKeyP coin_priv; struct TALER_AgeCommitmentHash ach; union GNUNET_CRYPTO_BlindingSecretP bks; - const struct TALER_ExchangeWithdrawValues *alg_values + const struct TALER_ExchangeBlindingValues *alg_values = TALER_denom_ewv_rsa_singleton (); TALER_planchet_master_setup_random (&ps);