exchange

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

commit 6124b69ad557c5e5c97ea564a828b53596626c8b
parent fb25885342d78395295cf834a7571daf054c0b1b
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon, 12 Oct 2026 16:44:03 +0200

better place for h_planchet computation

Diffstat:
Msrc/exchange/taler-exchange-httpd_post-withdraw.c | 89++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 45 insertions(+), 44 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_post-withdraw.c b/src/exchange/taler-exchange-httpd_post-withdraw.c @@ -1080,46 +1080,6 @@ phase_check_keys ( wc->request.withdraw.denom_serials[i] = dk->meta.serial; } - /* Save the hash of the batch of planchets */ - if (! wc->request.withdraw.age_proof_required) - { - TALER_wallet_blinded_planchets_hash ( - wc->request.withdraw.num_coins, - wc->request.planchets, - wc->request.denoms_h, - &wc->request.withdraw.planchets_h); - } - else - { - struct GNUNET_HashContext *ctx; - - /** - * The age-proof-required case is a bit more involved, - * because we need to calculate and remember kappa hashes - * for each batch of coins. - */ - ctx = GNUNET_CRYPTO_hash_context_start (); - GNUNET_assert (NULL != ctx); - - for (uint8_t k = 0; k < TALER_CNC_KAPPA; k++) - { - size_t off = k * wc->request.withdraw.num_coins; - - TALER_wallet_blinded_planchets_hash ( - wc->request.withdraw.num_coins, - &wc->request.planchets[off], - wc->request.denoms_h, - &wc->request.kappa_planchets_h[k]); - GNUNET_CRYPTO_hash_context_read ( - ctx, - &wc->request.kappa_planchets_h[k], - sizeof(wc->request.kappa_planchets_h[k])); - } - GNUNET_CRYPTO_hash_context_finish ( - ctx, - &wc->request.withdraw.planchets_h.hash); - } - /* Save the total amount including fees */ if (0 > TALER_amount_add ( &wc->request.withdraw.amount_with_fee, @@ -1703,10 +1663,10 @@ withdraw_phase_parse ( "denoms_h must not be empty") /** - * The wallet had committed to more than the maximum coins allowed, the - * reserve has been charged, but now the user can not withdraw any money - * from it. Note that the user can't get their money back in this case! - */ + * The wallet had committed to more than the maximum coins allowed, the + * reserve has been charged, but now the user can not withdraw any money + * from it. Note that the user can't get their money back in this case! + */ BAIL_IF (num_coins > TALER_MAX_COINS, "maximum number of coins that can be withdrawn has been exceeded") @@ -1813,6 +1773,47 @@ withdraw_phase_parse ( } /* end duplicate check */ } /* json_array_foreach over j_coin_evs */ } /* scope of j_kappa_planchets, idx */ + + /* Save the hash of the batch of planchets. Needed for idempotency + checks. */ + if (! wc->request.withdraw.age_proof_required) + { + TALER_wallet_blinded_planchets_hash ( + wc->request.withdraw.num_coins, + wc->request.planchets, + wc->request.denoms_h, + &wc->request.withdraw.planchets_h); + } + else + { + struct GNUNET_HashContext *ctx; + + /** + * The age-proof-required case is a bit more involved, + * because we need to calculate and remember kappa hashes + * for each batch of coins. + */ + ctx = GNUNET_CRYPTO_hash_context_start (); + GNUNET_assert (NULL != ctx); + + for (uint8_t k = 0; k < TALER_CNC_KAPPA; k++) + { + size_t off = k * wc->request.withdraw.num_coins; + + TALER_wallet_blinded_planchets_hash ( + wc->request.withdraw.num_coins, + &wc->request.planchets[off], + wc->request.denoms_h, + &wc->request.kappa_planchets_h[k]); + GNUNET_CRYPTO_hash_context_read ( + ctx, + &wc->request.kappa_planchets_h[k], + sizeof(wc->request.kappa_planchets_h[k])); + } + GNUNET_CRYPTO_hash_context_finish ( + ctx, + &wc->request.withdraw.planchets_h.hash); + } wc->phase = WITHDRAW_PHASE_CHECK_KEYS; }