exchange

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

commit bf816a8ff4f8185f13f99489e6bbcb04bb3b7056
parent 080cc5ac08d98eed92b39ef6ea66c66e6ff4f081
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Sat, 11 Jul 2026 17:24:38 +0200

-fix issues

Diffstat:
Msrc/exchange/taler-exchange-httpd_post-reserves-RESERVE_PUB-attest.c | 7+++++--
Msrc/exchangedb/profit_drains_get_pending.c | 3++-
Msrc/exchangedb/select_kyc_accounts.c | 9+++++++--
Dsrc/exchangedb/test_exchangedb_by_j.c | 232-------------------------------------------------------------------------------
Msrc/include/taler/exchange/get-reserves-RESERVE_PUB-history.h | 2+-
Msrc/include/taler/taler_kyclogic_lib.h | 2+-
Msrc/json/json_helper.c | 4++--
Msrc/kyclogic/kyclogic_api.c | 18+++++-------------
Msrc/lib/exchange_api_get-keys.c | 2+-
Msrc/lib/exchange_api_get-reserves-RESERVE_PUB-history.c | 5+----
Msrc/lib/exchange_api_post-reveal-melt.c | 3+--
Msrc/pq/pq_result_helper.c | 14++++++++------
Msrc/testing/testing_api_cmd_refresh.c | 1-
13 files changed, 34 insertions(+), 268 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_post-reserves-RESERVE_PUB-attest.c b/src/exchange/taler-exchange-httpd_post-reserves-RESERVE_PUB-attest.c @@ -255,8 +255,8 @@ reserve_attest_transaction (void *cls, struct ReserveAttestContext *rsc = cls; enum GNUNET_DB_QueryStatus qs; - rsc->json_attest = json_object (); - GNUNET_assert (NULL != rsc->json_attest); + GNUNET_assert (0 == + json_object_clear (rsc->json_attest)); qs = TALER_EXCHANGEDB_select_kyc_attributes (TEH_pg, &rsc->h_payto, &kyc_process_cb, @@ -373,6 +373,8 @@ TEH_handler_reserves_attest ( GNUNET_free (payto_uri.normalized_payto); } + rsc.json_attest = json_object (); + GNUNET_assert (NULL != rsc.json_attest); if (GNUNET_OK != TEH_DB_run_transaction (rc->connection, "post reserve attest", @@ -381,6 +383,7 @@ TEH_handler_reserves_attest ( &reserve_attest_transaction, &rsc)) { + json_decref (rsc.json_attest); return mhd_ret; } if (rsc.not_found) diff --git a/src/exchangedb/profit_drains_get_pending.c b/src/exchangedb/profit_drains_get_pending.c @@ -67,7 +67,8 @@ TALER_EXCHANGEDB_profit_drains_get_pending ( ",master_sig" " FROM profit_drains" " WHERE NOT executed" - " ORDER BY trigger_date ASC;"); + " ORDER BY trigger_date ASC" + " LIMIT 1;"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "get_ready_profit_drain", params, diff --git a/src/exchangedb/select_kyc_accounts.c b/src/exchangedb/select_kyc_accounts.c @@ -181,8 +181,13 @@ TALER_EXCHANGEDB_select_kyc_accounts ( " FROM kyc_targets kt" " JOIN wire_targets wt" " ON (wt.h_normalized_payto = kt.h_normalized_payto)" - " LEFT JOIN legitimization_outcomes lo" - " ON (lo.h_payto = kt.h_normalized_payto)" + " LEFT JOIN LATERAL (" + " SELECT payto_uri" + " FROM wire_targets" + " WHERE h_normalized_payto = kt.h_normalized_payto" + " ORDER BY wire_target_serial_id DESC" + " LIMIT 1" + " ) wt ON true" " WHERE (kyc_target_serial_id > $1)" // select most recent outcomes only " AND COALESCE (lo.is_active, TRUE)" diff --git a/src/exchangedb/test_exchangedb_by_j.c b/src/exchangedb/test_exchangedb_by_j.c @@ -1,232 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file exchangedb/test_exchangedb_by_j.c - * @brief test cases for DB interaction functions - * @author Joseph Xu - */ -#include "exchangedb_lib.h" -#include "taler/taler_json_lib.h" -#include "exchangedb_lib.h" -#include "math.h" -#define ROUNDS 10 - -/** - * Global result from the testcase. - */ -static int result; - -/** - * Report line of error if @a cond is true, and jump to label "drop". - */ -#define FAILIF(cond) \ - do { \ - if (! (cond)) {break;} \ - GNUNET_break (0); \ - goto drop; \ - } while (0) - - -/** - * Initializes @a ptr with random data. - */ -#define RND_BLK(ptr) \ - GNUNET_CRYPTO_random_block (ptr, sizeof (* \ - ptr)) - -/** - * Initializes @a ptr with zeros. - */ -#define ZR_BLK(ptr) \ - memset (ptr, 0, sizeof (*ptr)) - - -/** - * Currency we use. Must match test-exchange-db-*.conf. - */ -#define CURRENCY "EUR" - -/** - * Database plugin under test. - */ -static struct TALER_EXCHANGEDB_PostgresContext *plugin; - - -/** - * Main function that will be run by the scheduler. - * - * @param cls closure with config - */ -static void -run (struct TALER_EXCHANGEDB_PostgresContext *pg) -{ - static const unsigned int batches[] = {1, 2, 3, 4, 8, 16 }; - struct GNUNET_TIME_Relative times[sizeof (batches) / sizeof(*batches)]; - unsigned long long sqrs[sizeof (batches) / sizeof(*batches)]; - struct GNUNET_CONFIGURATION_Handle *cfg = cls; - const uint32_t num_partitions = 10; - - if (NULL == - (plugin = TALER_EXCHANGEDB_plugin_load (cfg))) - { - GNUNET_break (0); - result = 77; - return; - } - - - if (GNUNET_OK != - plugin->create_tables (plugin->cls, - true, - num_partitions)) - { - GNUNET_break (0); - result = 77; - goto cleanup; - } - - memset (times, 0, sizeof (times)); - memset (sqrs, 0, sizeof (sqrs)); - for (unsigned int r = 0; r < ROUNDS; r++) - { - for (unsigned int i = 0; i< 6; i++) - { - const char *sndr = "payto://x-taler-bank/localhost:8080/1"; - struct TALER_Amount value; - unsigned int batch_size = batches[i]; - unsigned int iterations = 16; // 1024*10; - struct TALER_ReservePublicKeyP reserve_pubs[iterations]; - struct GNUNET_TIME_Absolute now; - struct GNUNET_TIME_Timestamp ts; - struct GNUNET_TIME_Relative duration; - struct TALER_EXCHANGEDB_ReserveInInfo reserves[iterations]; - enum GNUNET_DB_QueryStatus results[iterations]; - unsigned long long duration_sq; - - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount (CURRENCY ":1.000010", - &value)); - now = GNUNET_TIME_absolute_get (); - ts = GNUNET_TIME_timestamp_get (); - for (unsigned int r = 0; r<iterations; r++) - { - RND_BLK (&reserve_pubs[r]); - reserves[r].reserve_pub = &reserve_pubs[r]; - reserves[r].balance = &value; - reserves[r].execution_time = ts; - reserves[r].sender_account_details = sndr; - reserves[r].exchange_account_name = "name"; - reserves[r].wire_reference = r; - } - FAILIF (iterations != - plugin->batch2_reserves_in_insert (plugin->cls, - reserves, - iterations, - batch_size, - results)); - duration = GNUNET_TIME_absolute_get_duration (now); - times[i] = GNUNET_TIME_relative_add (times[i], - duration); - duration_sq = duration.rel_value_us * duration.rel_value_us; - GNUNET_assert (duration_sq / duration.rel_value_us == - duration.rel_value_us); - GNUNET_assert (sqrs[i] + duration_sq >= sqrs[i]); - sqrs[i] += duration_sq; - fprintf (stdout, - "for a batchsize equal to %d it took %s\n", - batch_size, - GNUNET_STRINGS_relative_time_to_string (duration, - GNUNET_NO) ); - - system ("./test.sh"); // DELETE AFTER TIMER - } - } - for (unsigned int i = 0; i< 6; i++) - { - struct GNUNET_TIME_Relative avg; - double avg_dbl; - double variance; - - avg = GNUNET_TIME_relative_divide (times[i], - ROUNDS); - avg_dbl = avg.rel_value_us; - variance = sqrs[i] - (avg_dbl * avg_dbl * ROUNDS); - fprintf (stdout, - "Batch[%2u]: %8llu ± %6.0f\n", - batches[i], - (unsigned long long) avg.rel_value_us, - sqrt (variance / (ROUNDS - 1))); - } - - result = 0; -drop: - GNUNET_break (GNUNET_OK == - plugin->drop_tables (plugin->cls)); -cleanup: - TALER_EXCHANGEDB_plugin_unload (plugin); - plugin = NULL; -} - - -int -main (int argc, - char *const argv[]) -{ - const char *plugin_name; - char *config_filename; - char *testname; - struct GNUNET_CONFIGURATION_Handle *cfg; - (void) argc; - result = -1; - if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) - { - GNUNET_break (0); - return -1; - } - - GNUNET_log_setup (argv[0], - "WARNING", - NULL); - plugin_name++; - (void) GNUNET_asprintf (&testname, - "test-exchange-db-%s", - plugin_name); - (void) GNUNET_asprintf (&config_filename, - "%s.conf", - testname); - fprintf (stdout, - "Using config: %s\n", - config_filename); - cfg = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != - GNUNET_CONFIGURATION_parse (cfg, - config_filename)) - { - GNUNET_break (0); - GNUNET_free (config_filename); - GNUNET_free (testname); - return 2; - } - GNUNET_SCHEDULER_run (&run, - cfg); - GNUNET_CONFIGURATION_destroy (cfg); - GNUNET_free (config_filename); - GNUNET_free (testname); - return result; -} - - -/* end of test_exchangedb_by_j.c */ diff --git a/src/include/taler/exchange/get-reserves-RESERVE_PUB-history.h b/src/include/taler/exchange/get-reserves-RESERVE_PUB-history.h @@ -129,7 +129,7 @@ struct TALER_EXCHANGE_ReserveHistoryEntry /** * Signature authorizing the withdrawal. */ - json_t *out_authorization_sig; + struct TALER_ReserveSignatureP reserve_sig; /** * Running hash over all hashes of blinded planchets of the withdrawal. diff --git a/src/include/taler/taler_kyclogic_lib.h b/src/include/taler/taler_kyclogic_lib.h @@ -304,7 +304,7 @@ TALER_KYCLOGIC_rules_free (struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs); * @param[out] triggered_rule set to NULL if no rule * is triggered, otherwise the rule with measures * that must be satisfied (will be the highest - * applicable rule by display priority) + * applicable rule by threshold magnitude) * @param[out] next_threshold set to the next amount * that may trigger a KYC check (note: only really * useful for the wallet balance right now, as we diff --git a/src/json/json_helper.c b/src/json/json_helper.c @@ -2311,9 +2311,9 @@ cleaner_array_of_blinded_denom_sigs ( struct GNUNET_JSON_Specification *spec) { struct TALER_BlindedDenominationSignature *sigs = spec->ptr; - size_t *num_entries = cls; + size_t num_entries = (size_t) cls; - for (size_t i = 0; i < *num_entries; i++) + for (size_t i = 0; i < num_entries; i++) { if (NULL != sigs[i].blinded_sig) { diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c @@ -2307,7 +2307,7 @@ add_check (const struct GNUNET_CONFIGURATION_Handle *cfg, "TYPE", "valid check type required"); GNUNET_free (type_s); - return GNUNET_SYSERR; + goto fail; } GNUNET_free (type_s); } @@ -2427,10 +2427,7 @@ add_check (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "FORM_NAME"); - GNUNET_free (requires); - GNUNET_free (outputs); - GNUNET_free (kc); - return GNUNET_SYSERR; + goto fail; } if (! ascii_lower (form_name)) { @@ -2456,10 +2453,7 @@ add_check (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "PROVIDER_ID"); - GNUNET_free (requires); - GNUNET_free (outputs); - GNUNET_free (kc); - return GNUNET_SYSERR; + goto fail; } if (! ascii_lower (provider_id)) { @@ -2476,11 +2470,9 @@ add_check (const struct GNUNET_CONFIGURATION_Handle *cfg, "Unknown KYC provider `%s' used in check `%s'\n", provider_id, &section[strlen ("kyc-check-")]); - GNUNET_free (provider_id); - GNUNET_free (requires); - GNUNET_free (outputs); GNUNET_free (kc); - return GNUNET_SYSERR; + GNUNET_free (provider_id); + goto fail; } GNUNET_free (provider_id); } diff --git a/src/lib/exchange_api_get-keys.c b/src/lib/exchange_api_get-keys.c @@ -294,7 +294,7 @@ keys_completed_cb (void *cls, if (NULL == j) { GNUNET_break (0); - response_code = 0; + kresp.hr.http_status = 0; break; } kd = GNUNET_new (struct TALER_EXCHANGE_Keys); diff --git a/src/lib/exchange_api_get-reserves-RESERVE_PUB-history.c b/src/lib/exchange_api_get-reserves-RESERVE_PUB-history.c @@ -328,6 +328,7 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, rh->details.withdraw.selected_h = selected_h; rh->details.withdraw.noreveal_index = noreveal_index; rh->details.withdraw.no_blinding_seed = no_blinding_seed; + rh->details.withdraw.reserve_sig = reserve_sig; if (! no_blinding_seed) rh->details.withdraw.blinding_seed = blinding_seed; @@ -383,10 +384,6 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh, 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"); /* Check check that the same withdraw transaction isn't listed twice by the exchange. We use the "uuid" array to remember the hashes of all diff --git a/src/lib/exchange_api_post-reveal-melt.c b/src/lib/exchange_api_post-reveal-melt.c @@ -179,7 +179,6 @@ reveal_melt_ok ( GNUNET_JSON_parse_free (spec); return GNUNET_SYSERR; } - GNUNET_JSON_parse_free (spec); rci->sig = coin.sig; } @@ -195,8 +194,8 @@ reveal_melt_ok ( struct TALER_EXCHANGE_RevealedCoinInfo *rci = &coins[i]; TALER_denom_sig_free (&rci->sig); - TALER_blinded_denom_sig_free (&blind_sigs[i]); } + GNUNET_JSON_parse_free (spec); } return GNUNET_OK; diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c @@ -1224,6 +1224,12 @@ extract_array_generic ( if (NULL != info->num) *info->num = header.dim; + if (0 == header.dim) + { + if (NULL != dst_size) + *dst_size = 0; + return GNUNET_OK; + } { char *in = data + sizeof(header); @@ -1234,6 +1240,7 @@ extract_array_generic ( case TALER_PQ_array_of_amount: { struct TALER_Amount *amounts; + if (NULL != dst_size) *dst_size = sizeof(struct TALER_Amount) * (header.dim); @@ -1277,6 +1284,7 @@ extract_array_generic ( case TALER_PQ_array_of_amount_currency: { struct TALER_Amount *amounts; + if (NULL != dst_size) *dst_size = sizeof(struct TALER_Amount) * (header.dim); @@ -1431,12 +1439,6 @@ extract_array_generic ( case TALER_PQ_array_of_blinded_denom_sig: { struct TALER_BlindedDenominationSignature *denom_sigs; - if (0 == header.dim) - { - if (NULL != dst_size) - *dst_size = 0; - break; - } denom_sigs = GNUNET_new_array (header.dim, struct TALER_BlindedDenominationSignature); diff --git a/src/testing/testing_api_cmd_refresh.c b/src/testing/testing_api_cmd_refresh.c @@ -720,7 +720,6 @@ melt_cb (struct MeltState *ms, ms->num_blinding_values = mr->details.ok.num_melt_blinding_values; if (NULL != ms->blinding_values) { - GNUNET_break (0); /* can this this happen? Check! */ for (unsigned int i = 0; i < ms->num_blinding_values; i++) TALER_denom_ewv_free (&ms->blinding_values[i]); GNUNET_free (ms->blinding_values);