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:
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,