exchange

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

commit ce42b6945114cd4a2518fdd01997aa76e06c98b5
parent 3bdc7c0c70dd1dc457cdb7e900401ba1af7a2318
Author: Özgür Kesim <oec@codeblau.de>
Date:   Mon, 14 Sep 2026 21:32:56 +0200

auditor: re-enable the recoup checks in taler-helper-auditor-coins

Drop the FIXME_9828 guards around recoup_refresh_cb()
and the iteration over recoup_refresh, and give
TALER_EXCHANGEDB_iterate_recoup_refreshes_above_serial_id() a query
that matches the current schema.

test_recoup_refresh now checks that the iterator returns the recoup
it made.  The revocation shell fixture is still skipped, but for the
right reason: taler-wallet-cli does not implement the batch recoup
protocol (vRECOUP) yet.

Fixes issue: https://bugs.taler.net/n/9828

Diffstat:
Msrc/auditor/generate-revoke-basedb.sh | 27+++++++--------------------
Msrc/auditor/meson.build | 7++++---
Msrc/auditor/taler-helper-auditor-coins.c | 8++------
Msrc/auditor/test-revocation.sh | 5+++--
Msrc/exchangedb/iterate_recoup_refreshes_above_serial_id.c | 16+++-------------
Msrc/exchangedb/iterate_recoups_above_serial_id.c | 2--
Msrc/exchangedb/test_recoup_refresh.c | 15++++++++++-----
7 files changed, 29 insertions(+), 51 deletions(-)

diff --git a/src/auditor/generate-revoke-basedb.sh b/src/auditor/generate-revoke-basedb.sh @@ -116,26 +116,13 @@ export rc=$(echo "$COINS" | jq -r '[.coins[] | select((.denomValue == "TESTKUDOS # Find the denom export rd=$(echo "$COINS" | jq -r '[.coins[] | select((.denomValue == "TESTKUDOS:2"))][0] | .denomPubHash') -# This database is all about recoup, which the exchange currently does not -# implement: the recoup handlers are compiled out behind FIXME_9828 (see -# src/exchange/taler-exchange-httpd.c and -# https://bugs.gnunet.org/view.php?id=9828). Without them the wallet can -# never recoup the coins of the revoked denomination and we would spin until -# the test times out, so detect that up front and skip. -echo -n "Checking that the exchange implements recoup ..." -RECOUP_CODE=$(curl -s -X POST \ - -o "${MY_TMP_DIR}/recoup-probe.json" \ - -w "%{http_code}" \ - -H "Content-Type: application/json" \ - -d '{}' \ - "${EXCHANGE_URL}coins/${rc}/recoup") -if [ "$RECOUP_CODE" = "404" ] && - [ "$(jq -r '.code' < "${MY_TMP_DIR}/recoup-probe.json")" = "1001" ] -then - echo " NO" - exit_skip "exchange has no /coins/\$COIN_PUB/recoup endpoint (recoup is disabled, see FIXME_9828)" -fi -echo " YES" +# This database is all about recoup. The exchange implements the batch +# recoup protocol (POST /recoup-withdraw and /recoup-refresh, vRECOUP, see +# https://bugs.gnunet.org/view.php?id=9828), but taler-wallet-cli does not +# yet: after the revocation below the wallet would never recoup the coins of +# the revoked denomination and we would spin until the test times out. +# Remove this skip once wallet-core supports vRECOUP. +exit_skip "taler-wallet-cli does not implement the batch recoup protocol (vRECOUP, #9828) yet" echo -n "Revoking denomination ${rd} (to affect coin ${rc}) ..." # Find all other coins, which will be suspended diff --git a/src/auditor/meson.build b/src/auditor/meson.build @@ -334,9 +334,10 @@ test( timeout: 1800, ) # test-revocation audits denomination revocation, which relies on recoup. -# The exchange's recoup handlers are currently compiled out (FIXME_9828, -# https://bugs.gnunet.org/view.php?id=9828), so the test detects the missing -# endpoint and reports itself as skipped until recoup is reimplemented. +# Its fixture drives the recoup through the wallet CLI, which does not yet +# implement the batch recoup protocol (vRECOUP, see +# https://bugs.gnunet.org/view.php?id=9828), so the test reports itself as +# skipped until the wallet does. test_revocation = configure_file( input: 'test-revocation.sh', output: 'test-revocation.sh', diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c @@ -2311,7 +2311,6 @@ recoup_cb (struct CoinContext *cc, } -#if FIXME_9828 /** * Function called about recoups on refreshed coins the exchange had to * perform. Updates the denomination balance(s). Does not change the @@ -2373,6 +2372,8 @@ recoup_refresh_cb (struct CoinContext *cc, cc->qs = qs; return GNUNET_SYSERR; } + /* nothing to update without the denomination */ + return GNUNET_OK; } { @@ -2445,9 +2446,6 @@ recoup_refresh_cb (struct CoinContext *cc, } -#endif - - /** * Function called with the results of iterate_denomination_info(), * or directly (!). Used to check that we correctly signed the @@ -2823,7 +2821,6 @@ analyze_coins (void *cls) qs = cc.qs; goto cleanup; } -#if FIXME_9828 /* process recoups */ if (0 > (qs = TALER_EXCHANGEDB_iterate_recoup_refreshes_above_serial_id ( @@ -2840,7 +2837,6 @@ analyze_coins (void *cls) qs = cc.qs; goto cleanup; } -#endif /* process deposits */ if (0 > (qs = TALER_EXCHANGEDB_iterate_coin_deposits_above_serial_id ( diff --git a/src/auditor/test-revocation.sh b/src/auditor/test-revocation.sh @@ -732,8 +732,9 @@ then set -e if [ 77 = "$GENSTATUS" ] then - # Prerequisite missing (currently: recoup is not implemented by the - # exchange, see FIXME_9828); report as skipped, not as a failure. + # Prerequisite missing (currently: taler-wallet-cli does not + # implement the batch recoup protocol, see #9828); report as + # skipped, not as a failure. echo "SKIPPING: could not generate the revocation database" exit 77 fi diff --git a/src/exchangedb/iterate_recoup_refreshes_above_serial_id.c b/src/exchangedb/iterate_recoup_refreshes_above_serial_id.c @@ -77,7 +77,6 @@ recoup_refresh_serial_helper_cb (void *cls, struct TALER_DenominationPublicKey denom_pub; struct TALER_DenominationHashP old_denom_pub_hash; struct TALER_Amount amount; - struct TALER_BlindedCoinHashP h_blind_ev; struct GNUNET_TIME_Timestamp timestamp; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid", @@ -96,8 +95,6 @@ recoup_refresh_serial_helper_cb (void *cls, &coin_blind), TALER_PQ_result_spec_denom_pub ("denom_pub", &denom_pub), - GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", - &h_blind_ev), GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &coin.denom_pub_hash), GNUNET_PQ_result_spec_allow_null ( @@ -165,7 +162,6 @@ TALER_EXCHANGEDB_iterate_recoup_refreshes_above_serial_id ( ",rr.coin_sig" ",rr.coin_blind" ",rr.amount" - ",rrc.h_coin_ev AS h_blind_ev" // FIXME:-#9828 r.rc? r.selected_h? Old logic wanted a TALER_BlindedCoinHash, which we now need to derive (from rr.coin_blind) ",new_coins.age_commitment_hash" ",new_coins.coin_pub AS coin_pub" ",new_denoms.denom_pub AS denom_pub" @@ -174,24 +170,18 @@ TALER_EXCHANGEDB_iterate_recoup_refreshes_above_serial_id ( ",old_coins.coin_pub AS old_coin_pub" ",old_denoms.denom_pub_hash AS old_denom_pub_hash" " FROM recoup_refresh rr" - " INNER JOIN refresh_revealed_coins rrc" // FIXME-#9828: no such table anymore! - // but we have 'refresh_id" which is an FK into 'refresh'! - " USING (rrc_serial)" " INNER JOIN refresh r" - // but we have 'refresh_id" which is an FK into 'refresh'! - " USING (refresh_id)" + " ON (r.refresh_id = rr.refresh_id)" " INNER JOIN known_coins old_coins" " ON (r.old_coin_pub = old_coins.coin_pub)" " INNER JOIN known_coins new_coins" " ON (rr.coin_pub = new_coins.coin_pub)" - " INNER JOIN refresh_commitments rfc" - " ON (rrc.melt_serial_id = rfc.melt_serial_id)" " INNER JOIN denominations new_denoms" " ON (new_coins.denominations_serial = new_denoms.denominations_serial)" " INNER JOIN denominations old_denoms" " ON (old_coins.denominations_serial = old_denoms.denominations_serial)" - " WHERE recoup_refresh_uuid>=$1" - " ORDER BY recoup_refresh_uuid ASC;"); + " WHERE rr.recoup_refresh_uuid>=$1" + " ORDER BY rr.recoup_refresh_uuid ASC;"); qs = GNUNET_PQ_eval_prepared_multi_select ( pg->conn, "iterate_recoup_refreshes_above_serial_id", diff --git a/src/exchangedb/iterate_recoups_above_serial_id.c b/src/exchangedb/iterate_recoups_above_serial_id.c @@ -150,8 +150,6 @@ TALER_EXCHANGEDB_iterate_recoups_above_serial_id ( }; enum GNUNET_DB_QueryStatus qs; - /* FIXME-9828: this query joins with table/columns - that no longer exist... */ PREPARE (pg, "iterate_recoups_above_serial_id", "SELECT" diff --git a/src/exchangedb/test_recoup_refresh.c b/src/exchangedb/test_recoup_refresh.c @@ -19,16 +19,12 @@ * `recoup_refresh` * @author Christian Grothoff * - * Covers #TALER_EXCHANGEDB_do_recoup_refresh() and, as far as it can be, + * Covers #TALER_EXCHANGEDB_do_recoup_refresh() and * #TALER_EXCHANGEDB_iterate_recoup_refreshes_above_serial_id(). * * `recoup_refresh` references `known_coins` and `refresh`, so each check * builds a melt first. do_recoup_refresh() moves the fresh coin's whole * remaining balance back to the old coin. - * - * The iterator cannot be checked beyond "does not invent an answer": its - * statement joins `refresh_revealed_coins` and `refresh_commitments`, which - * the schema no longer has (EDB-16 in bugs.txt, in-tree FIXME-#9828). */ #include "test_common.h" #include "exchange-database/do_recoup_refresh.h" @@ -638,6 +634,15 @@ check_iterate (struct TALER_EXCHANGEDB_PostgresContext *pg) { unsigned int total = 0; + /* the one recoup made in check_recoup_refresh() */ + FAILIF (1 != + TALER_EXCHANGEDB_iterate_recoup_refreshes_above_serial_id ( + pg, + 0, + &recoup_refresh_cb, + &total)); + FAILIF (1 != total); + total = 0; FAILIF (0 < TALER_EXCHANGEDB_iterate_recoup_refreshes_above_serial_id ( pg,