commit 0b6b2f3a05fb8fc77182748ed2693ae9fe50070c
parent 33679d241f5f0d25af328a28d6796a41d6c35e4e
Author: Christian Grothoff <christian@grothoff.org>
Date: Fri, 9 Oct 2026 22:11:30 +0200
flush coin-history cache between transactions to avoid looking at a stale one
Diffstat:
1 file changed, 44 insertions(+), 0 deletions(-)
diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c
@@ -169,6 +169,18 @@ struct CoinHistory
static struct CoinHistory coin_histories[MAX_COIN_HISTORIES];
/**
+ * Indices of the entries of #coin_histories that are in use. Used to
+ * flush the cache at the end of a pass without touching the entire
+ * (huge) #coin_histories array.
+ */
+static unsigned int *used_histories;
+
+/**
+ * Length of the #used_histories array.
+ */
+static unsigned int num_used_histories;
+
+/**
* Should we run checks that only work for exchange-internal audits?
*/
static int internal_checks;
@@ -213,12 +225,43 @@ cache_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
if (NULL != coin_histories[i].tl)
TALER_EXCHANGEDB_free_coin_transaction_list (coin_histories[i].tl);
+ else
+ GNUNET_array_append (used_histories,
+ num_used_histories,
+ i);
coin_histories[i].coin_pub = *coin_pub;
coin_histories[i].tl = tl;
}
/**
+ * Drop all cached coin histories.
+ *
+ * Must be called at the end of each pass: within a pass the history we
+ * fetched is complete (we read it from a consistent snapshot), but the
+ * exchange keeps adding transactions to coins we already saw. Keeping
+ * the entry across passes would make us skip the over-spending check
+ * for every coin the process has already looked at.
+ */
+static void
+flush_coin_histories (void)
+{
+ for (unsigned int j = 0; j < num_used_histories; j++)
+ {
+ struct CoinHistory *ch = &coin_histories[used_histories[j]];
+
+ TALER_EXCHANGEDB_free_coin_transaction_list (ch->tl);
+ memset (ch,
+ 0,
+ sizeof (*ch));
+ }
+ GNUNET_array_grow (used_histories,
+ num_used_histories,
+ 0);
+}
+
+
+/**
* Obtain a coin's history from our in-memory cache.
*
* @param coin_pub public key of the coin to cache
@@ -2979,6 +3022,7 @@ analyze_coins (void *cls)
coins_purse_refunds_serial_id));
qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
cleanup:
+ flush_coin_histories ();
GNUNET_CONTAINER_multihashmap_iterate (cc.denom_summaries,
&cleanup_denomination,
&cc);