exchange

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

commit 375dbd875a7e15ab61bee32820257cf467bf7e59
parent d497589c35d3db41c4988ffd1aba83b0d5569b04
Author: Özgür Kesim <oec@codeblau.de>
Date:   Thu,  1 May 2025 17:09:52 +0200

[exchange,lib] finish reserve history data handling

- added cs_r_values to JSON output
- finished history data verification (withdraw fees) in C-lib

Diffstat:
Msrc/exchange/taler-exchange-httpd_reserves_history.c | 15++++++++++++++-
Msrc/lib/exchange_api_reserves_history.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
2 files changed, 87 insertions(+), 45 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_reserves_history.c b/src/exchange/taler-exchange-httpd_reserves_history.c @@ -171,7 +171,20 @@ compile_reserve_history ( json_decref (json_history); return NULL; } -#pragma message "also pack cs_r_values" + if (0!= + json_object_update_new ( + j_entry, + GNUNET_JSON_PACK ( + TALER_JSON_pack_array_of_data ( + "cs_r_values", + withdraw->num_cs_r_values, + withdraw->cs_r_values, + sizeof(withdraw->cs_r_values[0]))))) + { + GNUNET_break (0); + json_decref (json_history); + return NULL; + } } if (withdraw->age_proof_required) { diff --git a/src/lib/exchange_api_reserves_history.c b/src/lib/exchange_api_reserves_history.c @@ -203,13 +203,15 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, uint16_t num_coins; struct TALER_Amount withdraw_fee; struct TALER_Amount withdraw_amount; + struct TALER_Amount amount_without_fee; uint8_t max_age = 0; uint8_t noreveal_index = 0; struct TALER_HashBlindedPlanchetsP planchets_h; struct TALER_HashBlindedPlanchetsP selected_h; struct TALER_ReserveSignatureP reserve_sig; struct TALER_BlindingMasterSeedP blinding_seed; - const json_t *j_denom_pub_hashes; + struct TALER_DenominationHashP *denom_pub_hashes; + size_t num_denom_pub_hashes; bool no_max_age; bool no_noreveal_index; bool no_blinding_seed; @@ -225,8 +227,9 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, &withdraw_amount), TALER_JSON_spec_amount_any ("withdraw_fee", &withdraw_fee), - GNUNET_JSON_spec_array_const ("denom_pub_hashes", - &j_denom_pub_hashes), + TALER_JSON_spec_array_of_denom_pub_h ("denom_pub_hashes", + &num_denom_pub_hashes, + &denom_pub_hashes), GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_fixed_auto ("selected_h", &selected_h), @@ -264,38 +267,40 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, } rh->details.withdraw.age_restricted = ! no_max_age; - /* Check that the signature is a valid withdraw request */ + if (num_coins != num_denom_pub_hashes) { - struct TALER_Amount amount_without_fee; + GNUNET_break_op (0); + GNUNET_JSON_parse_free (withdraw_spec); + return GNUNET_SYSERR; + } - if (0>TALER_amount_subtract ( - &amount_without_fee, - &withdraw_amount, - &withdraw_fee)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } + /* Check that the signature is a valid withdraw request */ + if (0>TALER_amount_subtract ( + &amount_without_fee, + &withdraw_amount, + &withdraw_fee)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } - if (GNUNET_OK != - TALER_wallet_withdraw_verify ( - &amount_without_fee, - &withdraw_fee, - &planchets_h, - no_blinding_seed ? NULL : &blinding_seed, - no_max_age ? NULL : &uc->keys->age_mask, - no_max_age ? 0 : max_age, - uc->reserve_pub, - &reserve_sig)) - { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (withdraw_spec); - return GNUNET_SYSERR; - } + if (GNUNET_OK != + TALER_wallet_withdraw_verify ( + &amount_without_fee, + &withdraw_fee, + &planchets_h, + no_blinding_seed ? NULL : &blinding_seed, + no_max_age ? NULL : &uc->keys->age_mask, + no_max_age ? 0 : max_age, + uc->reserve_pub, + &reserve_sig)) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (withdraw_spec); + return GNUNET_SYSERR; } rh->details.withdraw.num_coins = num_coins; - rh->details.withdraw.fee = withdraw_fee; rh->details.withdraw.age_restricted = ! no_max_age; rh->details.withdraw.max_age = max_age; rh->details.withdraw.planchets_h = planchets_h; @@ -305,30 +310,56 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, if (! no_blinding_seed) rh->details.withdraw.blinding_seed = blinding_seed; - -#pragma message "finish parsing and verification of withdraw history entry" -#if 0 /* check that withdraw fee matches expectations! */ { const struct TALER_EXCHANGE_Keys *key_state; - const struct TALER_EXCHANGE_DenomPublicKey *dki; + struct TALER_Amount fee_acc; + struct TALER_Amount amount_acc; + + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (withdraw_amount.currency, + &fee_acc)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (withdraw_amount.currency, + &amount_acc)); key_state = uc->keys; - dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, - &h_denom_pub); + + /* accumulate the withdraw fees */ + for (size_t i=0; i < num_coins; i++) + { + const struct TALER_EXCHANGE_DenomPublicKey *dki; + dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state, + &denom_pub_hashes[i]); + if (NULL == dki) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (withdraw_spec); + return GNUNET_SYSERR; + } + TALER_amount_add (&fee_acc, + &fee_acc, + &dki->fees.withdraw); + TALER_amount_add (&amount_acc, + &amount_acc, + &dki->value); + } + if ( (GNUNET_YES != - TALER_amount_cmp_currency (&amount_with_fee, - &dki->fees.withdraw)) || + TALER_amount_cmp_currency (&fee_acc, + &withdraw_fee)) || (0 != - TALER_amount_cmp (&amount_with_fee, - &dki->fees.withdraw)) ) + TALER_amount_cmp (&amount_acc, + &amount_without_fee)) ) { GNUNET_break_op (0); GNUNET_JSON_parse_free (withdraw_spec); return GNUNET_SYSERR; } - rh->details.withdraw.fee = amount_with_fee; + rh->details.withdraw.fee = withdraw_fee; } + + #pragma message "is out_authorization_sig still needed? Not set anywhere" rh->details.withdraw.out_authorization_sig = json_object_get (transaction, "signature"); @@ -337,8 +368,8 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, "uuid" array to remember the hashes of all signatures, and compare the hashes to find duplicates. */ - GNUNET_CRYPTO_hash (&sig, - sizeof (sig), + GNUNET_CRYPTO_hash (&reserve_sig, + sizeof (reserve_sig), &uc->uuids[uc->uuid_off]); for (unsigned int i = 0; i<uc->uuid_off; i++) { @@ -362,8 +393,6 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, GNUNET_JSON_parse_free (withdraw_spec); return GNUNET_SYSERR; } -#endif - return GNUNET_OK; }