exchange

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

commit 042f5318b30c410a2fefcc37632bf6f19a8ff506
parent ae67550c27dcec9093be91aab4ba33ecf19540c2
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon, 12 Oct 2026 16:37:10 +0200

fix auditing order: credits before debits

Diffstat:
Msrc/auditor/taler-helper-auditor-coins.c | 57++++++++++++++++++++++++++++++++-------------------------
1 file changed, 32 insertions(+), 25 deletions(-)

diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c @@ -2846,12 +2846,19 @@ analyze_coins (void *cls) qs = cc.qs; goto cleanup; } - /* process refreshes */ + /* Process all operations that credit a denomination balance (refunds, + recoup-refresh, purse refunds) before those that debit it (melts, + deposits, purse deposits): within a pass the tables are processed + one after the other and not in time order, so a coin that spends + a credit it received in the same pass would otherwise make + reduce_denom_balance() see a balance that is too low and report a + false emergency. */ + /* process refunds */ if (0 > - (qs = TALER_EXCHANGEDB_iterate_refreshes_above_serial_id ( + (qs = TALER_EXCHANGEDB_iterate_refunds_above_serial_id ( TALER_ARL_edb, - TALER_ARL_USE_PP (coins_melt_serial_id), - &refresh_session_cb, + TALER_ARL_USE_PP (coins_refund_serial_id), + &refund_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -2862,12 +2869,12 @@ analyze_coins (void *cls) qs = cc.qs; goto cleanup; } - /* process refunds */ + /* process recoups of refreshed coins (credit the old coin) */ if (0 > - (qs = TALER_EXCHANGEDB_iterate_refunds_above_serial_id ( + (qs = TALER_EXCHANGEDB_iterate_recoup_refreshes_above_serial_id ( TALER_ARL_edb, - TALER_ARL_USE_PP (coins_refund_serial_id), - &refund_cb, + TALER_ARL_USE_PP (coins_recoup_refresh_serial_id), + &recoup_refresh_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -2878,12 +2885,13 @@ analyze_coins (void *cls) qs = cc.qs; goto cleanup; } - /* process recoups */ + /* process purse_refunds */ if (0 > - (qs = TALER_EXCHANGEDB_iterate_recoup_refreshes_above_serial_id ( + (qs = TALER_EXCHANGEDB_iterate_purse_decisions_above_serial_id ( TALER_ARL_edb, - TALER_ARL_USE_PP (coins_recoup_refresh_serial_id), - &recoup_refresh_cb, + TALER_ARL_USE_PP (coins_purse_refunds_serial_id), + true, /* only go for refunds! */ + &purse_refund_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -2894,12 +2902,12 @@ analyze_coins (void *cls) qs = cc.qs; goto cleanup; } - /* process deposits */ + /* process refreshes */ if (0 > - (qs = TALER_EXCHANGEDB_iterate_coin_deposits_above_serial_id ( + (qs = TALER_EXCHANGEDB_iterate_refreshes_above_serial_id ( TALER_ARL_edb, - TALER_ARL_USE_PP (coins_deposit_serial_id), - &deposit_cb, + TALER_ARL_USE_PP (coins_melt_serial_id), + &refresh_session_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -2910,12 +2918,12 @@ analyze_coins (void *cls) qs = cc.qs; goto cleanup; } - /* process purse_deposits */ + /* process deposits */ if (0 > - (qs = TALER_EXCHANGEDB_iterate_purse_deposits_above_serial_id ( + (qs = TALER_EXCHANGEDB_iterate_coin_deposits_above_serial_id ( TALER_ARL_edb, - TALER_ARL_USE_PP (coins_purse_deposits_serial_id), - &purse_deposit_cb, + TALER_ARL_USE_PP (coins_deposit_serial_id), + &deposit_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); @@ -2926,13 +2934,12 @@ analyze_coins (void *cls) qs = cc.qs; goto cleanup; } - /* process purse_refunds */ + /* process purse_deposits */ if (0 > - (qs = TALER_EXCHANGEDB_iterate_purse_decisions_above_serial_id ( + (qs = TALER_EXCHANGEDB_iterate_purse_deposits_above_serial_id ( TALER_ARL_edb, - TALER_ARL_USE_PP (coins_purse_refunds_serial_id), - true, /* only go for refunds! */ - &purse_refund_cb, + TALER_ARL_USE_PP (coins_purse_deposits_serial_id), + &purse_deposit_cb, &cc))) { GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);