commit 4a5e39300957413aeccf695a8d14854d3b6437de
parent c80fe0cca497ae3ce5d27048be0ff3cb1dbe553e
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 30 Apr 2025 23:39:07 +0200
use more portable GNUNET_static_assert(); fix handling of return value from TALER_MHD_parse_json_data, use phase loop more consistently
Diffstat:
1 file changed, 59 insertions(+), 64 deletions(-)
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -80,15 +80,15 @@ enum WithdrawError
*/
static const uint64_t idempotency_check_required =
0
- | (1 << WITHDRAW_ERROR_DENOMINATION_EXPIRED)
- | (1 << WITHDRAW_ERROR_DENOMINATION_KEY_UNKNOWN)
- | (1 << WITHDRAW_ERROR_DENOMINATION_REVOKED)
- | (1 << WITHDRAW_ERROR_INSUFFICIENT_FUNDS)
- | (1 << WITHDRAW_ERROR_KEYS_MISSING)
- | (1 << WITHDRAW_ERROR_KYC_REQUIRED);
+ | (1LLU << WITHDRAW_ERROR_DENOMINATION_EXPIRED)
+ | (1LLU << WITHDRAW_ERROR_DENOMINATION_KEY_UNKNOWN)
+ | (1LLU << WITHDRAW_ERROR_DENOMINATION_REVOKED)
+ | (1LLU << WITHDRAW_ERROR_INSUFFICIENT_FUNDS)
+ | (1LLU << WITHDRAW_ERROR_KEYS_MISSING)
+ | (1LLU << WITHDRAW_ERROR_KYC_REQUIRED);
#define IDEMPOTENCY_CHECK_REQUIRED(ec) \
- (0 != (idempotency_check_required & (1 << (ec))))
+ (0LLU != (idempotency_check_required & (1LLU << (ec))))
/**
@@ -110,6 +110,7 @@ struct WithdrawContext
*/
enum
{
+ WITHDRAW_PHASE_PARSE = 0,
WITHDRAW_PHASE_CHECK_KEYS,
WITHDRAW_PHASE_CHECK_RESERVE_SIGNATURE,
WITHDRAW_PHASE_RUN_LEGI_CHECK,
@@ -150,7 +151,6 @@ struct WithdrawContext
*/
struct TALER_NormalizedPaytoHashP h_normalized_payto;
-
/**
* Captures all parameters provided in the JSON request
*/
@@ -176,30 +176,32 @@ struct WithdrawContext
struct TALER_EXCHANGEDB_Withdraw withdraw_idem;
/**
- * Array ``num_coins`` of hashes of the public keys
+ * Array of ``withdraw.num_coins`` hashes of the public keys
* of the denominations to withdraw.
*/
struct TALER_DenominationHashP *denoms_h;
/**
- * Number of planchets. If ``max_age`` was _not_ set, this is equal to ``num_coins``.
- * Otherwise (``max_age`` was set) it is ``num_coins * kappa``.
+ * Number of planchets. If ``withdraw.max_age`` was _not_ set, this is equal to ``num_coins``.
+ * Otherwise (``withdraw.max_age`` was set) it is ``withdraw.num_coins * kappa``.
*/
size_t num_planchets;
/**
- * Array of ``num_planchets`` coin planchets.
+ * Array of ``withdraw.num_planchets`` coin planchets.
* Note that the size depends on the age restriction:
- * If ``age_proof_required`` is false, this is an array of length ``num_coins``.
- * Otherwise it is an array of length ``kappa*num_coins``, arranged
- * in runs of ``num_coins`` coins, [0..num_coins)..[0..num_coins),
- * one for each kappa value.
+ * If ``withdraw.age_proof_required`` is false,
+ * this is an array of length ``withdraw.num_coins``.
+ * Otherwise it is an array of length ``kappa*withdraw.num_coins``,
+ * arranged in runs of ``num_coins`` coins,
+ * [0..num_coins)..[0..num_coins),
+ * one for each #TALER_CNC_KAPPA value.
*/
struct TALER_BlindedPlanchet *planchets;
/**
* If proof of age-restriction is required, the #TALER_CNC_KAPPA hashes
- * of the batches of n coins.
+ * of the batches of ``withdraw.num_coins`` coins.
*/
struct TALER_HashBlindedPlanchetsP kappa_planchets_h[TALER_CNC_KAPPA];
@@ -214,8 +216,8 @@ struct WithdrawContext
struct TALER_Amount fee;
/**
- * Array @e withdraw.num_r_pubs of indices into @e denoms_h
- * of CS denominations.
+ * Array of length ``withdraw.num_cs_r_values`` of indices into
+ * @e denoms_h of CS denominations.
*/
uint32_t *cs_indices;
@@ -262,10 +264,14 @@ struct WithdrawContext
uint32_t birthday;
} maximum_age_too_large;
- /* The lowest age required */
+ /**
+ * The lowest age required
+ */
uint16_t age_restriction_required;
- /* Balance of the reserve */
+ /**
+ * Balance of the reserve
+ */
struct TALER_Amount insufficient_funds;
enum TALER_ErrorCode ec_confirmation_sign;
@@ -671,10 +677,9 @@ phase_prepare_transaction (
uint8_t bit = sig->blinded_sig->details.blinded_cs_answer.b;
wc->request.withdraw.cs_r_choices |= bit << i;
- _Static_assert (
+ GNUNET_static_assert (
TALER_MAX_REFRESH_COINS <=
- sizeof(wc->request.withdraw.cs_r_choices) * 8,
- "TALER_MAX_REFRESH_COINS too large");
+ sizeof(wc->request.withdraw.cs_r_choices) * 8);
}
}
wc->phase++;
@@ -1556,14 +1561,13 @@ phase_generate_reply_error (
/**
- * Creates a new context for the incoming withdraw request
+ * Initializes the new context for the incoming withdraw request
*
* @param wc withdraw request context
* @param root json body of the request
- * @return GNUNET_OK on success, GNUNET_SYSERR otherwise (response sent)
*/
-static enum GNUNET_GenericReturnValue
-withdraw_new_request (
+static void
+withdraw_phase_parse (
struct WithdrawContext *wc,
const json_t *root)
{
@@ -1598,10 +1602,13 @@ withdraw_new_request (
res = TALER_MHD_parse_json_data (wc->rc->connection,
root,
spec);
- if (GNUNET_OK != res)
+ if (GNUNET_YES != res)
{
GNUNET_break_op (0);
- return GNUNET_NO;
+ wc->phase = (GNUNET_SYSERR == res)
+ ? WITHDRAW_PHASE_RETURN_NO
+ : WITHDRAW_PHASE_RETURN_YES;
+ return;
}
/* For now, we only support cipher "ED25519" for signatures by the reserve */
@@ -1614,7 +1621,7 @@ withdraw_new_request (
WITHDRAW_ERROR_RESERVE_CIPHER_UNKNOWN,
reserve_cipher_unknown,
cipher);
- return GNUNET_NO;
+ return;
}
wc->request.withdraw.age_proof_required = ! no_max_age;
@@ -1633,7 +1640,7 @@ withdraw_new_request (
WITHDRAW_ERROR_REQUEST_PARAMETER_MALFORMED,
request_parameter_malformed,
"max_age must be the lower edge of an age group");
- return GNUNET_NO;
+ return;
}
}
@@ -1643,9 +1650,8 @@ withdraw_new_request (
size_t array_size = json_array_size (j_coin_evs);
const char *error;
- _Static_assert (
- TALER_MAX_REFRESH_COINS < INT_MAX / TALER_CNC_KAPPA,
- "TALER_MAX_REFRESH_COINS too large");
+ GNUNET_static_assert (
+ TALER_MAX_REFRESH_COINS < INT_MAX / TALER_CNC_KAPPA);
#define BAIL_IF(cond, msg) \
if ((cond)) { \
@@ -1689,7 +1695,7 @@ withdraw_new_request (
WITHDRAW_ERROR_REQUEST_PARAMETER_MALFORMED,
request_parameter_malformed,
error);
- return GNUNET_NO;
+ return;
}
}
/* extract the denomination hashes */
@@ -1711,11 +1717,14 @@ withdraw_new_request (
res = TALER_MHD_parse_json_data (wc->rc->connection,
value,
ispec);
- if (GNUNET_OK != res)
+ if (GNUNET_YES != res)
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
- return GNUNET_NO;
+ wc->phase = (GNUNET_SYSERR == res)
+ ? WITHDRAW_PHASE_RETURN_NO
+ : WITHDRAW_PHASE_RETURN_YES;
+ return;
}
}
}
@@ -1727,12 +1736,10 @@ withdraw_new_request (
wc->request.planchets =
GNUNET_new_array (wc->request.num_planchets,
struct TALER_BlindedPlanchet);
-
-
- json_array_foreach (j_coin_evs, idx, j_cev) {
+ json_array_foreach (j_coin_evs, idx, j_cev)
+ {
/* Now parse the individual envelopes and calculate the hash of
* the commitment along the way. */
-
struct GNUNET_JSON_Specification kspec[] = {
TALER_JSON_spec_blinded_planchet (NULL,
&wc->request.planchets[idx]),
@@ -1746,7 +1753,10 @@ withdraw_new_request (
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
- return GNUNET_NO;
+ wc->phase = (GNUNET_SYSERR == res)
+ ? WITHDRAW_PHASE_RETURN_NO
+ : WITHDRAW_PHASE_RETURN_YES;
+ return;
}
/* Check for duplicate planchets. Technically a bug on
@@ -1763,13 +1773,13 @@ withdraw_new_request (
GNUNET_JSON_parse_free (spec);
SET_ERROR (wc,
WITHDRAW_ERROR_IDEMPOTENT_PLANCHET);
- return GNUNET_NO;
+ return;
}
} /* end duplicate check */
} /* json_array_foreach over j_coin_evs */
} /* scope of j_kappa_planchets, idx */
GNUNET_JSON_parse_free (spec);
- return GNUNET_OK;
+ wc->phase = WITHDRAW_PHASE_CHECK_KEYS;
}
@@ -1780,10 +1790,8 @@ TEH_handler_withdraw (
const char *const args[0])
{
struct WithdrawContext *wc = rc->rh_ctx;
- enum GNUNET_GenericReturnValue r;
(void) args;
-
if (NULL == wc)
{
wc = GNUNET_new (struct WithdrawContext);
@@ -1791,24 +1799,7 @@ TEH_handler_withdraw (
rc->rh_cleaner = &clean_withdraw_rc;
wc->rc = rc;
wc->now = GNUNET_TIME_timestamp_get ();
- r = withdraw_new_request (wc,
- root);
- switch (r)
- {
- case GNUNET_SYSERR:
- return MHD_NO;
- case GNUNET_OK:
- wc->phase = WITHDRAW_PHASE_CHECK_KEYS;
- break;
- case GNUNET_NO:
- wc->phase = WITHDRAW_PHASE_GENERATE_REPLY_ERROR;
- break;
- default:
- GNUNET_break (0);
- return MHD_NO;
- }
}
-
while (true)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1819,6 +1810,10 @@ TEH_handler_withdraw (
wc->phase);
switch (wc->phase)
{
+ case WITHDRAW_PHASE_PARSE:
+ withdraw_phase_parse (wc,
+ root);
+ break;
case WITHDRAW_PHASE_CHECK_KEYS:
phase_check_keys (wc);
break;