commit af660c11f94d80edd8f89ccaca9da2195e23ffcc
parent 04ba57964684d50087462df2ec4cace1c8e5dbec
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 3 Nov 2026 22:48:58 +0100
keep checking the rest even if one denomination is missing
Diffstat:
2 files changed, 59 insertions(+), 5 deletions(-)
diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c
@@ -1472,7 +1472,9 @@ withdraw_cb (
cc->qs = qs;
return GNUNET_SYSERR;
}
- return GNUNET_OK;
+ /* We cannot account for this planchet, but the other planchets
+ of the batch must still be processed. */
+ continue;
}
ds = get_denomination_summary (cc,
issue);
diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c
@@ -582,10 +582,12 @@ handle_withdrawals (
const struct TALER_Amount *amount_with_fee)
{
struct ReserveSummary *rs;
- const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
struct TALER_Amount auditor_amount;
struct TALER_Amount auditor_fee;
struct TALER_Amount auditor_amount_with_fee;
+ struct TALER_AgeMask age_mask = { 0 };
+ bool have_age_mask = false;
+ bool missing_denom = false;
enum GNUNET_DB_QueryStatus qs;
/* should be monotonically increasing */
@@ -613,6 +615,8 @@ handle_withdrawals (
}
for (size_t i = 0; i < num_denom_serials; i++)
{
+ const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
+
/* lookup denomination pub data (make sure denom_pub is valid, establish fees);
initializes wsrd.h_denomination_pub! */
qs = TALER_ARL_get_denomination_info_by_serial (denom_serials[i],
@@ -638,12 +642,33 @@ handle_withdrawals (
"denomination key not found");
if (global_qs < 0)
return GNUNET_SYSERR;
- return GNUNET_OK;
+ /* We cannot account for this planchet, but the other planchets
+ of the batch must still be processed. */
+ missing_denom = true;
+ continue;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Analyzing withdrawn denomination #%llu (%s)\n",
(unsigned long long) denom_serials[i],
TALER_amount2s (&issue->value));
+ if (! have_age_mask)
+ {
+ age_mask = issue->age_mask;
+ have_age_mask = true;
+ }
+ else if (age_mask.bits != issue->age_mask.bits)
+ {
+ /* All denominations of one batch must share the age mask, as the
+ reserve signature is made over a single age mask. */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Denominations of withdraw row %llu disagree on the age mask\n",
+ (unsigned long long) rowid);
+ report_row_inconsistency ("withdraw",
+ rowid,
+ "denominations of the batch disagree on the age mask");
+ if (global_qs < 0)
+ return GNUNET_SYSERR;
+ }
/* check that execution date is within withdraw range for denom_pub */
GNUNET_log (
@@ -710,6 +735,33 @@ handle_withdrawals (
&issue->fees.withdraw);
} /* end for all coins in batch */
+ if (missing_denom)
+ {
+ /* We do not know the value of the entire batch, so we can check
+ neither the reserve signature nor the total; still debit the
+ reserve by the amount the exchange claims. The row inconsistency
+ reported above states that we could not verify it. */
+ TALER_ARL_amount_add (&rs->total_out,
+ &rs->total_out,
+ amount_with_fee);
+ return GNUNET_OK;
+ }
+ if (age_proof_required &&
+ (! have_age_mask))
+ {
+ /* Without a denomination we do not know the age mask the reserve
+ signature was made over. */
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Age-restricted withdraw row %llu has no denominations\n",
+ (unsigned long long) rowid);
+ report_row_inconsistency ("withdraw",
+ rowid,
+ "no denomination given for age-restricted withdraw");
+ if (global_qs < 0)
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
+ }
+
/* check reserve_sig (first: setup remaining members of wsrd) */
if (GNUNET_OK !=
TALER_wallet_withdraw_verify (
@@ -718,7 +770,7 @@ handle_withdrawals (
h_planchets,
blinding_seed,
age_proof_required
- ? &issue->age_mask
+ ? &age_mask
: NULL,
age_proof_required
? max_age
@@ -773,7 +825,7 @@ handle_withdrawals (
TALER_amount2s (&auditor_amount_with_fee));
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Increasing withdraw profits by fee %s\n",
- TALER_amount2s (&issue->fees.withdraw));
+ TALER_amount2s (&auditor_fee));
TALER_ARL_amount_add (&rs->total_out,
&rs->total_out,
&auditor_amount_with_fee);