commit d068ebf661c0cf02cde2107dd5344318d7c8f18d
parent 3afafbe4a33f0a768046c050921f422f28dfd74a
Author: Özgür Kesim <oec@codeblau.de>
Date: Mon, 31 Mar 2025 18:01:20 +0200
[exchange] cleanup withdraw and reserves_history
- simplify code in withdraw
- adapt change to exchangedb struct
Diffstat:
2 files changed, 264 insertions(+), 310 deletions(-)
diff --git a/src/exchange/taler-exchange-httpd_reserves_history.c b/src/exchange/taler-exchange-httpd_reserves_history.c
@@ -165,7 +165,7 @@ compile_reserve_history (
&withdraw->amount_with_fee)
);
- if (withdraw->age_restricted)
+ if (withdraw->age_proof_required)
{
if (0 !=
json_object_update_new (
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -37,6 +37,50 @@
#include "taler_util.h"
/**
+ * This bit will be set on errors of type #WithdrawError
+ * that require a check for idempotency before actually
+ * returning an error.
+ * This value must be outside the range of enum #WithdrawError.
+ */
+#define IDEMPOTENCY_FLAG 1 << 5
+
+/**
+ * The different type of errors that might occur, sorted by name.
+ * Some of them require idempotency checks, which are marked
+ * in array @a needs_idempotency_check_error below.
+ */
+enum WithdrawError
+{
+ WITHDRAW_ERROR_NONE = 0,
+ WITHDRAW_ERROR_AGE_RESTRICTION_NOT_SUPPORTED_BY_DENOMINATION = 1,
+ WITHDRAW_ERROR_AGE_RESTRICTION_REQUIRED = 2,
+ WITHDRAW_ERROR_AMOUNT_OVERFLOW = 3,
+ WITHDRAW_ERROR_AMOUNT_PLUS_FEE_OVERFLOW = 4,
+ WITHDRAW_ERROR_CIPHER_MISMATCH = 5,
+ WITHDRAW_ERROR_CONFIRMATION_SIGN = 6,
+ WITHDRAW_ERROR_DB_FETCH_FAILED = 7,
+ WITHDRAW_ERROR_DB_INVARIANT_FAILURE = 8,
+ WITHDRAW_ERROR_DENOMINATION_EXPIRED = 9 | IDEMPOTENCY_FLAG,
+ WITHDRAW_ERROR_DENOMINATION_KEY_UNKNOWN = 10 | IDEMPOTENCY_FLAG,
+ WITHDRAW_ERROR_DENOMINATION_REVOKED = 11 | IDEMPOTENCY_FLAG,
+ WITHDRAW_ERROR_DENOMINATION_SIGN = 12,
+ WITHDRAW_ERROR_DENOMINATION_VALIDITY_IN_FUTURE = 13,
+ WITHDRAW_ERROR_FEE_OVERFLOW = 14,
+ WITHDRAW_ERROR_IDEMPOTENT_PLANCHET = 15 | IDEMPOTENCY_FLAG,
+ WITHDRAW_ERROR_INSUFFICIENT_FUNDS = 16 | IDEMPOTENCY_FLAG,
+ WITHDRAW_ERROR_INTERNAL_INVARIANT_FAILURE = 17,
+ WITHDRAW_ERROR_KEYS_MISSING = 18 | IDEMPOTENCY_FLAG,
+ WITHDRAW_ERROR_KYC_REQUIRED = 19 | IDEMPOTENCY_FLAG,
+ WITHDRAW_ERROR_LEGITIMIZATION_RESULT = 20,
+ WITHDRAW_ERROR_MAXIMUM_AGE_TOO_LARGE = 21,
+ WITHDRAW_ERROR_NONCE_RESUSE = 22,
+ WITHDRAW_ERROR_REQUEST_PARAMETER_MALFORMED = 23,
+ WITHDRAW_ERROR_RESERVE_CIPHER_UNKNOWN = 24,
+ WITHDRAW_ERROR_RESERVE_SIGNATURE_INVALID = 25,
+ WITHDRAW_ERROR_RESERVE_UNKNOWN = 26,
+};
+
+/**
* Context for a /withdraw requests
*/
struct WithdrawContext
@@ -55,17 +99,17 @@ struct WithdrawContext
*/
enum
{
- PHASE_CHECK_KEYS,
- PHASE_CHECK_RESERVE_SIGNATURE,
- PHASE_RUN_LEGI_CHECK,
- PHASE_SUSPENDED,
- PHASE_CHECK_KYC_RESULT,
- PHASE_PREPARE_TRANSACTION,
- PHASE_RUN_TRANSACTION,
- PHASE_GENERATE_REPLY_SUCCESS,
- PHASE_GENERATE_REPLY_ERROR,
- PHASE_RETURN_NO,
- PHASE_RETURN_YES,
+ WITHDRAW_PHASE_CHECK_KEYS,
+ WITHDRAW_PHASE_CHECK_RESERVE_SIGNATURE,
+ WITHDRAW_PHASE_RUN_LEGI_CHECK,
+ WITHDRAW_PHASE_SUSPENDED,
+ WITHDRAW_PHASE_CHECK_KYC_RESULT,
+ WITHDRAW_PHASE_PREPARE_TRANSACTION,
+ WITHDRAW_PHASE_RUN_TRANSACTION,
+ WITHDRAW_PHASE_GENERATE_REPLY_SUCCESS,
+ WITHDRAW_PHASE_GENERATE_REPLY_ERROR,
+ WITHDRAW_PHASE_RETURN_NO,
+ WITHDRAW_PHASE_RETURN_YES,
} phase;
@@ -135,7 +179,7 @@ struct WithdrawContext
/**
* Array of ``num_planchets`` coin planchets.
* Note that the size depends on the age restriction:
- * If ``age_restricted`` is false, this is an array of length ``num_coins``.
+ * 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.
@@ -156,167 +200,86 @@ struct WithdrawContext
/**
- * Errors occurring during evaluation of the request are captured in this struct.
- * In phase PHASE_GENERATE_REPLY_ERROR an appropriate error message is prepared
- * and sent to the client.
- */
+ * Errors occurring during evaluation of the request are captured in this
+ * struct. In phase WITHDRAW_PHASE_GENERATE_REPLY_ERROR an appropriate error
+ * message is prepared and sent to the client.
+ */
struct
{
- /**
- * The different type of errors that might occur, sorted by name.
- * Some of them require idempotency checks, which are marked
- * in array @a needs_idempotency_check_error below.
- */
- enum
- {
- ERROR_NONE,
-
- ERROR_AGE_RESTRICTION_NOT_SUPPORTED_BY_DENOMINATION,
- ERROR_AGE_RESTRICTION_REQUIRED,
- ERROR_AMOUNT_OVERFLOW,
- ERROR_AMOUNT_PLUS_FEE_OVERFLOW,
- ERROR_CIPHER_MISMATCH,
- ERROR_CONFIRMATION_SIGN,
- ERROR_DB_FETCH_FAILED,
- ERROR_DB_INVARIANT_FAILURE,
- ERROR_DENOMINATION_EXPIRED,
- ERROR_DENOMINATION_KEY_UNKNOWN,
- ERROR_DENOMINATION_REVOKED,
- ERROR_DENOMINATION_SIGN,
- ERROR_DENOMINATION_VALIDITY_IN_FUTURE,
- ERROR_FEE_OVERFLOW,
- ERROR_IDEMPOTENT_PLANCHET,
- ERROR_INSUFFICIENT_FUNDS,
- ERROR_INTERNAL_INVARIANT_FAILURE,
- ERROR_KEYS_MISSING,
- ERROR_KYC_REQUIRED,
- ERROR_LEGITIMIZATION_RESULT,
- ERROR_MAXIMUM_AGE_TOO_LARGE,
- ERROR_NONCE_RESUSE,
- ERROR_REQUEST_PARAMETER_MALFORMED,
- ERROR_RESERVE_CIPHER_UNKNOWN,
- ERROR_RESERVE_SIGNATURE_INVALID,
- ERROR_RESERVE_UNKNOWN,
-
- ERROR_MAX
- } code;
+ /* The (internal) error code */
+ enum WithdrawError code;
/**
* Some errors require details to be sent to the client.
* These are captured in this union.
- * Each field is marked with a comment, referring to the error(s)
- * that is/are using it.
+ * Each field is named according to the error that is using it, except
+ * commented otherwise.
*/
union
{
- /* ERROR_REQUEST_PARAMETER_MALFORMED */
- const char *hint;
-
- /* ERROR_AMOUNT_OVERFLOW */
- /* ERROR_FEE_OVERFLOW */
- /* ERROR_AMOUNT_PLUS_FEE_OVERFLOW */
- const char *which;
+ const char *request_parameter_malformed;
- /* ERROR_RESERVE_CIPHER_UNKNOWN */
- const char *cipher;
+ const char *reserve_cipher_unknown;
- /* ERROR_DENOMINATION_KEY_UNKNOWN */
+ /**
+ * For all errors related to a particular denomination, i.e.
+ * WITHDRAW_ERROR_DENOMINATION_KEY_UNKNOWN,
+ * WITHDRAW_ERROR_DENOMINATION_EXPIRED,
+ * WITHDRAW_ERROR_DENOMINATION_VALIDITY_IN_FUTURE,
+ * WITHDRAW_ERROR_AGE_RESTRICTION_NOT_SUPPORTED_BY_DENOMINATION,
+ * we use this one field.
+ */
const struct TALER_DenominationHashP *denom_h;
- /* ERROR_DB_FETCH_FAILED */
const char *db_fetch_context;
- /* ERROR_MAXIMUM_AGE_TOO_LARGE */
struct
{
- uint16_t max;
+ uint16_t max_allowed;
uint32_t birthday;
- } age;
+ } maximum_age_too_large;
+
+ /* The lowest age required */
+ uint16_t age_restriction_required;
- /* ERROR_AGE_RESTRICTION_REQUIRED */
- uint16_t lowest_age;
+ /* Balance of the reserve */
+ struct TALER_Amount insufficient_funds;
- /* ERROR_INSUFFICIENT_FUNDS */
- struct TALER_Amount reserve_balance;
+ enum TALER_ErrorCode ec_confirmation_sign;
- /* ERROR_CONFIRMATION_SIGN */
- /* ERROR_DENOMINATION_SIGN */
- enum TALER_ErrorCode ec;
+ enum TALER_ErrorCode ec_denomination_sign;
- /* ERROR_LEGITIMIZATION_RESULT */
struct
{
struct MHD_Response *response;
unsigned int http_status;
- } legi;
+ } legitimization_result;
} details;
} error;
};
/**
- * This table marks which @a WithdrawContext.error.code
- * needs a idempotency check prior to actually sending an error message.
- */
-static const bool
- needs_idempotency_check[] = {
- [ERROR_NONE] = false,
-
- [ERROR_MAXIMUM_AGE_TOO_LARGE] = false,
- [ERROR_AGE_RESTRICTION_NOT_SUPPORTED_BY_DENOMINATION] = false,
- [ERROR_AGE_RESTRICTION_REQUIRED] = false,
- [ERROR_AMOUNT_OVERFLOW] = false,
- [ERROR_AMOUNT_PLUS_FEE_OVERFLOW] = false,
- [ERROR_CIPHER_MISMATCH] = false,
- [ERROR_CONFIRMATION_SIGN] = false,
- [ERROR_DB_FETCH_FAILED] = false,
- [ERROR_DB_INVARIANT_FAILURE] = false,
- [ERROR_DENOMINATION_SIGN] = false,
- [ERROR_DENOMINATION_VALIDITY_IN_FUTURE] = false,
- [ERROR_INTERNAL_INVARIANT_FAILURE] = false,
- [ERROR_LEGITIMIZATION_RESULT] = false,
- [ERROR_NONCE_RESUSE] = false,
- [ERROR_REQUEST_PARAMETER_MALFORMED] = false,
- [ERROR_RESERVE_CIPHER_UNKNOWN] = false,
- [ERROR_RESERVE_SIGNATURE_INVALID] = false,
- [ERROR_RESERVE_UNKNOWN] = false,
-
- /* These require idempotency checks */
- [ERROR_INSUFFICIENT_FUNDS] = true,
- [ERROR_IDEMPOTENT_PLANCHET] = true,
- [ERROR_DENOMINATION_EXPIRED] = true,
- [ERROR_DENOMINATION_KEY_UNKNOWN] = true,
- [ERROR_DENOMINATION_REVOKED] = true,
- [ERROR_KEYS_MISSING] = true,
- [ERROR_KYC_REQUIRED] = true,
-};
-
-_Static_assert (
- (sizeof (needs_idempotency_check) ==
- ERROR_MAX),
- "needs_idempotency_check size mismatch with enum for errors");
-
-/**
* The following macros set the given error code,
- * set the phase to PHASE_GENERATE_REPLY_ERROR,
+ * set the phase to WITHDRAW_PHASE_GENERATE_REPLY_ERROR,
* and optionally set the given field (with an optionally given value).
*/
#define SET_ERROR(wc, ec) \
do \
{ (wc)->error.code = (ec); \
- (wc)->phase = PHASE_GENERATE_REPLY_ERROR; } while (0)
+ (wc)->phase = WITHDRAW_PHASE_GENERATE_REPLY_ERROR; } while (0)
#define SET_ERROR_WITH_FIELD(wc, ec, field) \
do \
{ (wc)->error.code = (ec); \
(wc)->error.details.field = (field); \
- (wc)->phase = PHASE_GENERATE_REPLY_ERROR; } while (0)
+ (wc)->phase = WITHDRAW_PHASE_GENERATE_REPLY_ERROR; } while (0)
#define SET_ERROR_WITH_DETAIL(wc, ec, field, value) \
do \
{ (wc)->error.code = (ec); \
(wc)->error.details.field = (value); \
- (wc)->phase = PHASE_GENERATE_REPLY_ERROR; } while (0)
+ (wc)->phase = WITHDRAW_PHASE_GENERATE_REPLY_ERROR; } while (0)
/**
@@ -352,8 +315,8 @@ finish_loop (struct WithdrawContext *wc,
MHD_RESULT mres)
{
wc->phase = (MHD_YES == mres)
- ? PHASE_RETURN_YES
- : PHASE_RETURN_NO;
+ ? WITHDRAW_PHASE_RETURN_YES
+ : WITHDRAW_PHASE_RETURN_NO;
}
@@ -382,7 +345,7 @@ withdraw_is_idempotent (
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
SET_ERROR_WITH_DETAIL (wc,
- ERROR_DB_FETCH_FAILED,
+ WITHDRAW_ERROR_DB_FETCH_FAILED,
db_fetch_context,
"get_withdraw");
return true; /* Well, kind-of. */
@@ -396,7 +359,7 @@ withdraw_is_idempotent (
/* Generate idempotent reply */
TEH_METRICS_num_requests[TEH_MT_REQUEST_IDEMPOTENT_WITHDRAW]++;
- wc->phase = PHASE_GENERATE_REPLY_SUCCESS;
+ wc->phase = WITHDRAW_PHASE_GENERATE_REPLY_SUCCESS;
return true;
}
@@ -423,50 +386,45 @@ withdraw_transaction (
{
struct WithdrawContext *wc = cls;
enum GNUNET_DB_QueryStatus qs;
- bool found = false;
- bool balance_ok = false;
- bool age_ok = false;
- bool conflict = false;
- uint16_t allowed_maximum_age = 0;
- uint32_t reserve_birthday = 0;
- struct TALER_Amount reserve_balance;
-
+ bool balance_ok;
+ bool age_ok;
+ bool conflict;
+ uint16_t allowed_maximum_age;
+ uint32_t reserve_birthday;
+ struct TALER_Amount insufficient_funds;
qs = TEH_plugin->do_withdraw (TEH_plugin->cls,
&wc->request.persist,
wc->now,
- &found,
&balance_ok,
- &reserve_balance,
+ &insufficient_funds,
&age_ok,
&allowed_maximum_age,
&reserve_birthday,
&conflict);
-
if (0 > qs)
{
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
SET_ERROR_WITH_DETAIL (wc,
- ERROR_DB_FETCH_FAILED,
+ WITHDRAW_ERROR_DB_FETCH_FAILED,
db_fetch_context,
"do_withdraw");
return qs;
}
-
- if (! found)
+ if (0 == qs)
{
SET_ERROR (wc,
- ERROR_RESERVE_UNKNOWN);
+ WITHDRAW_ERROR_RESERVE_UNKNOWN);
return GNUNET_DB_STATUS_HARD_ERROR;
}
if (! age_ok)
{
- wc->error.details.age.max = allowed_maximum_age;
- wc->error.details.age.birthday = reserve_birthday;
+ wc->error.details.maximum_age_too_large.max_allowed = allowed_maximum_age;
+ wc->error.details.maximum_age_too_large.birthday = reserve_birthday;
SET_ERROR (wc,
- ERROR_MAXIMUM_AGE_TOO_LARGE);
+ WITHDRAW_ERROR_MAXIMUM_AGE_TOO_LARGE);
return GNUNET_DB_STATUS_HARD_ERROR;
}
@@ -475,8 +433,8 @@ withdraw_transaction (
TEH_plugin->rollback (TEH_plugin->cls);
SET_ERROR_WITH_FIELD (wc,
- ERROR_INSUFFICIENT_FUNDS,
- reserve_balance);
+ WITHDRAW_ERROR_INSUFFICIENT_FUNDS,
+ insufficient_funds);
return GNUNET_DB_STATUS_HARD_ERROR;
}
@@ -510,10 +468,9 @@ phase_run_transaction (
MHD_RESULT mhd_ret;
enum GNUNET_GenericReturnValue qs;
- GNUNET_assert (PHASE_RUN_TRANSACTION ==
+ GNUNET_assert (WITHDRAW_PHASE_RUN_TRANSACTION ==
wc->phase);
-
qs = TEH_DB_run_transaction (wc->rc->connection,
"run withdraw",
TEH_MT_REQUEST_WITHDRAW,
@@ -524,7 +481,7 @@ phase_run_transaction (
if (GNUNET_OK != qs)
{
/* TODO[oec]: Logic still ok with new error handling? */
- if (PHASE_RUN_TRANSACTION == wc->phase)
+ if (WITHDRAW_PHASE_RUN_TRANSACTION == wc->phase)
finish_loop (wc,
mhd_ret);
return;
@@ -556,7 +513,7 @@ phase_prepare_transaction (
struct TALER_BlindedCoinHashP);
/* Pick the challenge in case of age restriction */
- if (wc->request.persist.age_restricted)
+ if (wc->request.persist.age_proof_required)
{
wc->request.persist.noreveal_index =
GNUNET_CRYPTO_random_u32 (
@@ -575,7 +532,7 @@ phase_prepare_transaction (
/* Choose and sign the coins */
{
struct TEH_CoinSignData csds[wc->request.persist.num_coins];
- enum TALER_ErrorCode ec;
+ enum TALER_ErrorCode ec_denomination_sign;
memset (csds,
0,
@@ -588,17 +545,17 @@ phase_prepare_transaction (
csds[i].h_denom_pub = &wc->request.denoms_h[i];
}
- ec = TEH_keys_denomination_batch_sign (
+ ec_denomination_sign = TEH_keys_denomination_batch_sign (
wc->request.persist.num_coins,
csds,
false,
wc->request.persist.denom_sigs);
- if (TALER_EC_NONE != ec)
+ if (TALER_EC_NONE != ec_denomination_sign)
{
GNUNET_break (0);
SET_ERROR_WITH_FIELD (wc,
- ERROR_DENOMINATION_SIGN,
- ec);
+ WITHDRAW_ERROR_DENOMINATION_SIGN,
+ ec_denomination_sign);
return;
}
@@ -627,7 +584,7 @@ phase_check_kyc_result (struct WithdrawContext *wc)
if (! wc->kyc.ok)
{
SET_ERROR (wc,
- ERROR_KYC_REQUIRED);
+ WITHDRAW_ERROR_KYC_REQUIRED);
return;
}
wc->phase++;
@@ -649,7 +606,7 @@ withdraw_legi_cb (
struct WithdrawContext *wc = cls;
wc->lch = NULL;
- GNUNET_assert (PHASE_SUSPENDED ==
+ GNUNET_assert (WITHDRAW_PHASE_SUSPENDED ==
wc->phase);
MHD_resume_connection (wc->rc->connection);
GNUNET_CONTAINER_DLL_remove (wc_head,
@@ -658,14 +615,14 @@ withdraw_legi_cb (
TALER_MHD_daemon_trigger ();
if (NULL != lcr->response)
{
- wc->error.details.legi.response = lcr->response;
- wc->error.details.legi.http_status = lcr->http_status;
+ wc->error.details.legitimization_result.response = lcr->response;
+ wc->error.details.legitimization_result.http_status = lcr->http_status;
SET_ERROR (wc,
- ERROR_LEGITIMIZATION_RESULT);
+ WITHDRAW_ERROR_LEGITIMIZATION_RESULT);
return;
}
wc->kyc = lcr->kyc;
- wc->phase = PHASE_CHECK_KYC_RESULT;
+ wc->phase = WITHDRAW_PHASE_CHECK_KYC_RESULT;
}
@@ -678,7 +635,7 @@ static const char *
typ2str (
const struct WithdrawContext *wc)
{
- return (wc->request.persist.age_restricted) ? "age-withdraw" :
+ return (wc->request.persist.age_proof_required) ? "age-withdraw" :
"batch-withdraw";
}
@@ -762,7 +719,7 @@ phase_run_legi_check (struct WithdrawContext *wc)
if (qs < 0)
{
SET_ERROR_WITH_DETAIL (wc,
- ERROR_DB_FETCH_FAILED,
+ WITHDRAW_ERROR_DB_FETCH_FAILED,
db_fetch_context,
"reserves_get_origin");
return;
@@ -772,7 +729,7 @@ phase_run_legi_check (struct WithdrawContext *wc)
merge already did that. */
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
- wc->phase = PHASE_PREPARE_TRANSACTION;
+ wc->phase = WITHDRAW_PHASE_PREPARE_TRANSACTION;
return;
}
TALER_full_payto_normalize_and_hash (payto_uri,
@@ -793,7 +750,7 @@ phase_run_legi_check (struct WithdrawContext *wc)
wc_tail,
wc);
MHD_suspend_connection (wc->rc->connection);
- wc->phase = PHASE_SUSPENDED;
+ wc->phase = WITHDRAW_PHASE_SUSPENDED;
}
@@ -829,7 +786,7 @@ find_denomination (
if (NULL == dk)
{
SET_ERROR_WITH_FIELD (wc,
- ERROR_DENOMINATION_KEY_UNKNOWN,
+ WITHDRAW_ERROR_DENOMINATION_KEY_UNKNOWN,
denom_h);
return GNUNET_NO;
}
@@ -838,7 +795,7 @@ find_denomination (
dk->meta.expire_withdraw.abs_time))
{
SET_ERROR_WITH_FIELD (wc,
- ERROR_DENOMINATION_EXPIRED,
+ WITHDRAW_ERROR_DENOMINATION_EXPIRED,
denom_h);
return GNUNET_SYSERR;
}
@@ -848,7 +805,7 @@ find_denomination (
{
GNUNET_break_op (0);
SET_ERROR_WITH_FIELD (wc,
- ERROR_DENOMINATION_VALIDITY_IN_FUTURE,
+ WITHDRAW_ERROR_DENOMINATION_VALIDITY_IN_FUTURE,
denom_h);
return GNUNET_SYSERR;
}
@@ -856,18 +813,18 @@ find_denomination (
if (dk->recoup_possible)
{
SET_ERROR (wc,
- ERROR_DENOMINATION_REVOKED);
+ WITHDRAW_ERROR_DENOMINATION_REVOKED);
return GNUNET_SYSERR;
}
/* In case of age withdraw, make sure that the denomitation supports age restriction */
- if (wc->request.persist.age_restricted)
+ if (wc->request.persist.age_proof_required)
{
if (0 == dk->denom_pub.age_mask.bits)
{
GNUNET_break_op (0);
SET_ERROR_WITH_FIELD (wc,
- ERROR_AGE_RESTRICTION_NOT_SUPPORTED_BY_DENOMINATION,
+ WITHDRAW_ERROR_AGE_RESTRICTION_NOT_SUPPORTED_BY_DENOMINATION,
denom_h);
return GNUNET_SYSERR;
}
@@ -898,7 +855,7 @@ phase_check_keys (
{
GNUNET_break (0);
SET_ERROR (wc,
- ERROR_KEYS_MISSING);
+ WITHDRAW_ERROR_KEYS_MISSING);
return;
}
@@ -937,7 +894,7 @@ phase_check_keys (
* a) When age restriction is not applicable, we only have request.persist.num_coins
* to deal with, matching the number of denominations.
*
- * b) However, when request.persist.age_restricted is set, the list of planchets
+ * b) However, when request.persist.age_proof_required is set, the list of planchets
* is kappa*num_coins, and there are kappa many coin candidates per denomination.
* At each index i, the coins at i+j*num_coins (for j from 0 to kappa)
* belong to the same denomination.
@@ -945,7 +902,8 @@ phase_check_keys (
* We try to be smart here and handle both variants in one loop
* that either runs only once or kappa times.
*/
- uint8_t kappa = wc->request.persist.age_restricted ? TALER_CNC_KAPPA : 0;
+ uint8_t kappa = wc->request.persist.age_proof_required ? TALER_CNC_KAPPA :
+ 0;
for (uint8_t k = 0; k < kappa; k++)
{
@@ -956,7 +914,7 @@ phase_check_keys (
{
GNUNET_break_op (0);
SET_ERROR (wc,
- ERROR_CIPHER_MISMATCH);
+ WITHDRAW_ERROR_CIPHER_MISMATCH);
return;
}
}
@@ -968,10 +926,8 @@ phase_check_keys (
&dk->meta.value))
{
GNUNET_break_op (0);
- SET_ERROR_WITH_DETAIL (wc,
- ERROR_AMOUNT_OVERFLOW,
- which,
- "amount");
+ SET_ERROR (wc,
+ WITHDRAW_ERROR_AMOUNT_OVERFLOW);
return;
}
@@ -981,10 +937,8 @@ phase_check_keys (
&dk->meta.fees.withdraw))
{
GNUNET_break_op (0);
- SET_ERROR_WITH_DETAIL (wc,
- ERROR_AMOUNT_OVERFLOW,
- which,
- "fee");
+ SET_ERROR (wc,
+ WITHDRAW_ERROR_FEE_OVERFLOW);
return;
}
wc->request.persist.denom_serials[i] = dk->meta.serial;
@@ -997,10 +951,8 @@ phase_check_keys (
&wc->request.fee))
{
GNUNET_break_op (0);
- SET_ERROR_WITH_DETAIL (wc,
- ERROR_AMOUNT_OVERFLOW,
- which,
- "amount+fee");
+ SET_ERROR (wc,
+ WITHDRAW_ERROR_AMOUNT_PLUS_FEE_OVERFLOW);
return;
}
@@ -1024,16 +976,17 @@ phase_check_reserve_signature (
&wc->request.amount,
&wc->request.fee,
&wc->request.persist.h_planchets,
- (wc->request.persist.age_restricted) ?
+ (wc->request.persist.age_proof_required) ?
&TEH_age_restriction_config.mask :
NULL,
- (wc->request.persist.age_restricted) ? wc->request.persist.max_age : 0,
+ (wc->request.persist.age_proof_required) ? wc->request.persist.max_age :
+ 0,
&wc->request.persist.reserve_pub,
&wc->request.persist.reserve_sig))
{
GNUNET_break_op (0);
SET_ERROR (wc,
- ERROR_RESERVE_SIGNATURE_INVALID);
+ WITHDRAW_ERROR_RESERVE_SIGNATURE_INVALID);
return;
}
@@ -1045,15 +998,14 @@ phase_check_reserve_signature (
&wc->request.amount,
&wc->request.fee,
&wc->request.persist.h_planchets,
- (wc->request.persist.age_restricted) ?
- &TEH_age_restriction_config.mask :
- NULL,
- (wc->request.persist.age_restricted) ?
- wc->request.persist.max_age :
- 0,
+ wc->request.persist.age_proof_required
+ ? &TEH_age_restriction_config.mask
+ : NULL,
+ wc->request.persist.age_proof_required
+ ? wc->request.persist.max_age
+ : 0,
&wc->request.persist.h_commitment);
-
wc->phase++;
}
@@ -1100,11 +1052,11 @@ clean_withdraw_rc (struct TEH_RequestContext *rc)
GNUNET_free (wc->request.idem.denom_serials);
}
- if (ERROR_LEGITIMIZATION_RESULT == wc->error.code &&
- NULL != wc->error.details.legi.response)
+ if (WITHDRAW_ERROR_LEGITIMIZATION_RESULT == wc->error.code &&
+ NULL != wc->error.details.legitimization_result.response)
{
- MHD_destroy_response (wc->error.details.legi.response);
- wc->error.details.legi.response = NULL;
+ MHD_destroy_response (wc->error.details.legitimization_result.response);
+ wc->error.details.legitimization_result.response = NULL;
}
GNUNET_free (wc);
@@ -1121,27 +1073,28 @@ phase_generate_reply_success (struct WithdrawContext *wc)
{
struct TALER_EXCHANGEDB_Withdraw *db_obj;
- db_obj = wc->request.is_idempotent ?
- &wc->request.idem :
- &wc->request.persist;
+ db_obj = wc->request.is_idempotent
+ ? &wc->request.idem
+ : &wc->request.persist;
- if (wc->request.persist.age_restricted)
+ if (wc->request.persist.age_proof_required)
{
struct TALER_ExchangePublicKeyP pub;
struct TALER_ExchangeSignatureP sig;
- enum TALER_ErrorCode ec;
-
- ec = TALER_exchange_online_withdraw_age_confirmation_sign (
- &TEH_keys_exchange_sign_,
- &db_obj->h_commitment,
- db_obj->noreveal_index,
- &pub,
- &sig);
- if (TALER_EC_NONE != ec)
+ enum TALER_ErrorCode ec_confirmation_sign;
+
+ ec_confirmation_sign =
+ TALER_exchange_online_withdraw_age_confirmation_sign (
+ &TEH_keys_exchange_sign_,
+ &db_obj->h_commitment,
+ db_obj->noreveal_index,
+ &pub,
+ &sig);
+ if (TALER_EC_NONE != ec_confirmation_sign)
{
SET_ERROR_WITH_FIELD (wc,
- ERROR_CONFIRMATION_SIGN,
- ec);
+ WITHDRAW_ERROR_CONFIRMATION_SIGN,
+ ec_confirmation_sign);
return;
}
@@ -1196,11 +1149,10 @@ static void
phase_generate_reply_error (
struct WithdrawContext *wc)
{
- GNUNET_assert (PHASE_GENERATE_REPLY_ERROR == wc->phase);
- GNUNET_assert (ERROR_NONE != wc->error.code);
- GNUNET_assert (ERROR_MAX != wc->error.code);
+ GNUNET_assert (WITHDRAW_PHASE_GENERATE_REPLY_ERROR == wc->phase);
+ GNUNET_assert (WITHDRAW_ERROR_NONE != wc->error.code);
- if (needs_idempotency_check[wc->error.code] &&
+ if ((0 != (wc->error.code & IDEMPOTENCY_FLAG)) &&
withdraw_is_idempotent (wc))
{
return;
@@ -1208,23 +1160,22 @@ phase_generate_reply_error (
switch (wc->error.code)
{
- case ERROR_MAX:
- case ERROR_NONE:
+ case WITHDRAW_ERROR_NONE:
{
GNUNET_break (0);
- wc->phase = PHASE_RETURN_YES;
+ wc->phase = WITHDRAW_PHASE_RETURN_YES;
return;
}
- case ERROR_REQUEST_PARAMETER_MALFORMED:
+ case WITHDRAW_ERROR_REQUEST_PARAMETER_MALFORMED:
TALER_MHD_reply_with_error (
wc->rc->connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
- wc->error.details.hint);
+ wc->error.details.request_parameter_malformed);
break;
- case ERROR_KEYS_MISSING:
+ case WITHDRAW_ERROR_KEYS_MISSING:
finish_loop (wc,
TALER_MHD_reply_with_error (
wc->rc->connection,
@@ -1233,7 +1184,7 @@ phase_generate_reply_error (
NULL));
break;
- case ERROR_DB_FETCH_FAILED:
+ case WITHDRAW_ERROR_DB_FETCH_FAILED:
finish_loop (wc,
TALER_MHD_reply_with_error (
wc->rc->connection,
@@ -1242,7 +1193,7 @@ phase_generate_reply_error (
wc->error.details.db_fetch_context));
break;
- case ERROR_DB_INVARIANT_FAILURE:
+ case WITHDRAW_ERROR_DB_INVARIANT_FAILURE:
finish_loop (wc,
TALER_MHD_reply_with_error (
wc->rc->connection,
@@ -1251,7 +1202,7 @@ phase_generate_reply_error (
NULL));
break;
- case ERROR_INTERNAL_INVARIANT_FAILURE:
+ case WITHDRAW_ERROR_INTERNAL_INVARIANT_FAILURE:
finish_loop (wc,
TALER_MHD_reply_with_error (
wc->rc->connection,
@@ -1260,7 +1211,7 @@ phase_generate_reply_error (
NULL));
break;
- case ERROR_RESERVE_UNKNOWN:
+ case WITHDRAW_ERROR_RESERVE_UNKNOWN:
finish_loop (wc,
TALER_MHD_reply_with_ec (
wc->rc->connection,
@@ -1268,15 +1219,15 @@ phase_generate_reply_error (
NULL));
break;
- case ERROR_DENOMINATION_SIGN:
+ case WITHDRAW_ERROR_DENOMINATION_SIGN:
finish_loop (wc,
TALER_MHD_reply_with_ec (
wc->rc->connection,
- wc->error.details.ec,
+ wc->error.details.ec_denomination_sign,
NULL));
break;
- case ERROR_KYC_REQUIRED:
+ case WITHDRAW_ERROR_KYC_REQUIRED:
finish_loop (wc,
TEH_RESPONSE_reply_kyc_required (
wc->rc->connection,
@@ -1285,17 +1236,15 @@ phase_generate_reply_error (
false));
break;
- case ERROR_DENOMINATION_KEY_UNKNOWN:
- {
- GNUNET_break_op (0);
- finish_loop (wc,
- TEH_RESPONSE_reply_unknown_denom_pub_hash (
- wc->rc->connection,
- wc->error.details.denom_h));
- break;
- }
+ case WITHDRAW_ERROR_DENOMINATION_KEY_UNKNOWN:
+ GNUNET_break_op (0);
+ finish_loop (wc,
+ TEH_RESPONSE_reply_unknown_denom_pub_hash (
+ wc->rc->connection,
+ wc->error.details.denom_h));
+ break;
- case ERROR_DENOMINATION_EXPIRED:
+ case WITHDRAW_ERROR_DENOMINATION_EXPIRED:
GNUNET_break_op (0);
finish_loop (wc,
TEH_RESPONSE_reply_expired_denom_pub_hash (
@@ -1305,7 +1254,7 @@ phase_generate_reply_error (
typ2str (wc)));
break;
- case ERROR_DENOMINATION_VALIDITY_IN_FUTURE:
+ case WITHDRAW_ERROR_DENOMINATION_VALIDITY_IN_FUTURE:
finish_loop (wc,
TEH_RESPONSE_reply_expired_denom_pub_hash (
wc->rc->connection,
@@ -1314,7 +1263,7 @@ phase_generate_reply_error (
typ2str (wc)));
break;
- case ERROR_DENOMINATION_REVOKED:
+ case WITHDRAW_ERROR_DENOMINATION_REVOKED:
GNUNET_break_op (0);
finish_loop (wc,
TALER_MHD_reply_with_ec (
@@ -1323,7 +1272,7 @@ phase_generate_reply_error (
typ2str (wc)));
break;
- case ERROR_CIPHER_MISMATCH:
+ case WITHDRAW_ERROR_CIPHER_MISMATCH:
finish_loop (wc,
TALER_MHD_reply_with_ec (
wc->rc->connection,
@@ -1331,7 +1280,7 @@ phase_generate_reply_error (
NULL));
break;
- case ERROR_RESERVE_CIPHER_UNKNOWN:
+ case WITHDRAW_ERROR_RESERVE_CIPHER_UNKNOWN:
finish_loop (wc,
TALER_MHD_reply_with_ec (
wc->rc->connection,
@@ -1339,7 +1288,7 @@ phase_generate_reply_error (
"cipher"));
break;
- case ERROR_AGE_RESTRICTION_NOT_SUPPORTED_BY_DENOMINATION:
+ case WITHDRAW_ERROR_AGE_RESTRICTION_NOT_SUPPORTED_BY_DENOMINATION:
{
char msg[256];
GNUNET_snprintf (msg,
@@ -1354,7 +1303,7 @@ phase_generate_reply_error (
break;
}
- case ERROR_MAXIMUM_AGE_TOO_LARGE:
+ case WITHDRAW_ERROR_MAXIMUM_AGE_TOO_LARGE:
finish_loop (wc,
TALER_MHD_REPLY_JSON_PACK (
wc->rc->connection,
@@ -1363,58 +1312,64 @@ phase_generate_reply_error (
TALER_EC_EXCHANGE_WITHDRAW_MAXIMUM_AGE_TOO_LARGE),
GNUNET_JSON_pack_uint64 (
"allowed_maximum_age",
- wc->error.details.age.max),
+ wc->error.details.maximum_age_too_large.max_allowed),
GNUNET_JSON_pack_uint64 (
"reserve_birthday",
- wc->error.details.age.birthday)));
+ wc->error.details.maximum_age_too_large.birthday)));
break;
- case ERROR_AGE_RESTRICTION_REQUIRED:
+ case WITHDRAW_ERROR_AGE_RESTRICTION_REQUIRED:
finish_loop (wc,
TEH_RESPONSE_reply_reserve_age_restriction_required (
wc->rc->connection,
- wc->error.details.lowest_age));
+ wc->error.details.age_restriction_required));
break;
- case ERROR_AMOUNT_OVERFLOW:
- case ERROR_FEE_OVERFLOW:
+ case WITHDRAW_ERROR_AMOUNT_OVERFLOW:
finish_loop (wc,
TALER_MHD_reply_with_error (
wc->rc->connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_OVERFLOW,
- wc->error.details.which));
+ "amount"));
+ case WITHDRAW_ERROR_FEE_OVERFLOW:
+ finish_loop (wc,
+ TALER_MHD_reply_with_error (
+ wc->rc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_OVERFLOW,
+ "fee"));
break;
- case ERROR_AMOUNT_PLUS_FEE_OVERFLOW:
+ case WITHDRAW_ERROR_AMOUNT_PLUS_FEE_OVERFLOW:
finish_loop (wc,
TALER_MHD_reply_with_error (
wc->rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
- NULL));
+ "amount+fee"));
break;
- case ERROR_CONFIRMATION_SIGN:
+ case WITHDRAW_ERROR_CONFIRMATION_SIGN:
finish_loop (wc,
TALER_MHD_reply_with_ec (
wc->rc->connection,
- wc->error.details.ec,
+ wc->error.details.ec_confirmation_sign,
NULL));
break;
- case ERROR_INSUFFICIENT_FUNDS:
+ case WITHDRAW_ERROR_INSUFFICIENT_FUNDS:
finish_loop (wc,
TEH_RESPONSE_reply_reserve_insufficient_balance (
wc->rc->connection,
TALER_EC_EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS,
- &wc->error.details.reserve_balance,
+ &wc->error.details.insufficient_funds,
&wc->request.persist.amount_with_fee,
&wc->request.persist.reserve_pub));
break;
- case ERROR_IDEMPOTENT_PLANCHET:
+ case WITHDRAW_ERROR_IDEMPOTENT_PLANCHET:
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Idempotent coin in batch, not allowed. Aborting.\n");
@@ -1427,7 +1382,7 @@ phase_generate_reply_error (
break;
}
- case ERROR_NONCE_RESUSE:
+ case WITHDRAW_ERROR_NONCE_RESUSE:
finish_loop (wc,
TALER_MHD_reply_with_error (
wc->rc->connection,
@@ -1436,7 +1391,7 @@ phase_generate_reply_error (
NULL));
break;
- case ERROR_RESERVE_SIGNATURE_INVALID:
+ case WITHDRAW_ERROR_RESERVE_SIGNATURE_INVALID:
finish_loop (wc,
TALER_MHD_reply_with_ec (
wc->rc->connection,
@@ -1444,11 +1399,12 @@ phase_generate_reply_error (
NULL));
break;
- case ERROR_LEGITIMIZATION_RESULT: {
- finish_loop (wc,
- MHD_queue_response (wc->rc->connection,
- wc->error.details.legi.http_status,
- wc->error.details.legi.response));
+ case WITHDRAW_ERROR_LEGITIMIZATION_RESULT: {
+ finish_loop (
+ wc,
+ MHD_queue_response (wc->rc->connection,
+ wc->error.details.legitimization_result.http_status,
+ wc->error.details.legitimization_result.response));
break;
}
}
@@ -1501,18 +1457,20 @@ withdraw_new_request (
return res;
/* For now, we only support cipher "ED25519" for signatures by the reserve */
- if (strcmp ("ED25519", cipher))
+ if (0 != strcmp ("ED25519",
+ cipher))
{
GNUNET_break_op (0);
- SET_ERROR_WITH_FIELD (wc,
- ERROR_RESERVE_CIPHER_UNKNOWN,
- cipher);
+ SET_ERROR_WITH_DETAIL (wc,
+ WITHDRAW_ERROR_RESERVE_CIPHER_UNKNOWN,
+ reserve_cipher_unknown,
+ cipher);
return GNUNET_SYSERR;
}
- wc->request.persist.age_restricted = ! no_max_age;
+ wc->request.persist.age_proof_required = ! no_max_age;
- if (wc->request.persist.age_restricted)
+ if (wc->request.persist.age_proof_required)
{
/* The age value MUST be on the beginning of an age group */
if (wc->request.persist.max_age !=
@@ -1522,8 +1480,8 @@ withdraw_new_request (
GNUNET_break_op (0);
SET_ERROR_WITH_DETAIL (
wc,
- ERROR_REQUEST_PARAMETER_MALFORMED,
- hint,
+ WITHDRAW_ERROR_REQUEST_PARAMETER_MALFORMED,
+ request_parameter_malformed,
"max_age must be the lower edge of an age group");
return GNUNET_SYSERR;
}
@@ -1556,17 +1514,17 @@ withdraw_new_request (
BAIL_IF (num_coins > TALER_MAX_FRESH_COINS,
"maximum number of coins that can be withdrawn has been exceeded")
- BAIL_IF ((! wc->request.persist.age_restricted) &&
+ BAIL_IF ((! wc->request.persist.age_proof_required) &&
(num_coins !=array_size),
"denoms_h and coin_evs must be arrays of the same size")
- BAIL_IF (wc->request.persist.age_restricted &&
+ BAIL_IF (wc->request.persist.age_proof_required &&
((TALER_CNC_KAPPA * num_coins) != array_size),
"coin_evs must be an array of length "
TALER_CNC_KAPPA_STR
"*len(denoms_h)")
- wc->request.persist.num_coins = num_coins;
+ wc->request.persist.num_coins = num_coins;
wc->request.num_planchets = array_size;
} while (0);
@@ -1577,8 +1535,8 @@ withdraw_new_request (
{
GNUNET_break_op (0);
SET_ERROR_WITH_DETAIL (wc,
- ERROR_REQUEST_PARAMETER_MALFORMED,
- hint,
+ WITHDRAW_ERROR_REQUEST_PARAMETER_MALFORMED,
+ request_parameter_malformed,
error);
return GNUNET_SYSERR;
}
@@ -1613,7 +1571,7 @@ withdraw_new_request (
GNUNET_new_array (wc->request.num_planchets,
struct TALER_BlindedPlanchet);
- /* calculate the hash over the blinded coin envelopes */
+ /* Calculate the hash over the blinded coin envelopes */
{
struct GNUNET_HashContext *hash_context;
@@ -1658,7 +1616,7 @@ withdraw_new_request (
/* Check for duplicate planchets. Technically a bug on
* the client side that is harmless for us, but still
* not allowed per protocol */
- for (unsigned int i = 0; i < idx; i++)
+ for (size_t i = 0; i < idx; i++)
{
if (0 ==
TALER_blinded_planchet_cmp (
@@ -1667,8 +1625,8 @@ withdraw_new_request (
{
GNUNET_break_op (0);
SET_ERROR_WITH_DETAIL (wc,
- ERROR_REQUEST_PARAMETER_MALFORMED,
- hint,
+ WITHDRAW_ERROR_REQUEST_PARAMETER_MALFORMED,
+ request_parameter_malformed,
"duplicate planchet");
return GNUNET_SYSERR;
}
@@ -1679,10 +1637,8 @@ withdraw_new_request (
/* Finally, calculate the hash from all blinded envelopes */
GNUNET_CRYPTO_hash_context_finish (hash_context,
&wc->request.persist.h_planchets.hash);
-
} /* scope of hash_context */
} /* scope of j_denoms_h, j_blinded_coin_evs */
-
return GNUNET_OK;
}
@@ -1698,19 +1654,18 @@ TEH_handler_withdraw (
(void) args;
- while (NULL == wc)
+ if (NULL == wc)
{
wc = GNUNET_new (struct WithdrawContext);
rc->rh_ctx = wc;
rc->rh_cleaner = &clean_withdraw_rc;
wc->rc = rc;
wc->now = GNUNET_TIME_timestamp_get ();
-
- r = withdraw_new_request (wc, root);
+ r = withdraw_new_request (wc,
+ root);
if (GNUNET_OK != r)
return (GNUNET_SYSERR == r) ? MHD_NO : MHD_YES;
-
- wc->phase = PHASE_CHECK_KEYS;
+ wc->phase = WITHDRAW_PHASE_CHECK_KEYS;
}
while (true)
@@ -1719,38 +1674,37 @@ TEH_handler_withdraw (
"%s processing in phase %d\n",
typ2str (wc),
wc->phase);
-
switch (wc->phase)
{
- case PHASE_CHECK_KEYS:
+ case WITHDRAW_PHASE_CHECK_KEYS:
phase_check_keys (wc);
break;
- case PHASE_CHECK_RESERVE_SIGNATURE:
+ case WITHDRAW_PHASE_CHECK_RESERVE_SIGNATURE:
phase_check_reserve_signature (wc);
break;
- case PHASE_RUN_LEGI_CHECK:
+ case WITHDRAW_PHASE_RUN_LEGI_CHECK:
phase_run_legi_check (wc);
break;
- case PHASE_SUSPENDED:
+ case WITHDRAW_PHASE_SUSPENDED:
return MHD_YES;
- case PHASE_CHECK_KYC_RESULT:
+ case WITHDRAW_PHASE_CHECK_KYC_RESULT:
phase_check_kyc_result (wc);
break;
- case PHASE_PREPARE_TRANSACTION:
+ case WITHDRAW_PHASE_PREPARE_TRANSACTION:
phase_prepare_transaction (wc);
break;
- case PHASE_RUN_TRANSACTION:
+ case WITHDRAW_PHASE_RUN_TRANSACTION:
phase_run_transaction (wc);
break;
- case PHASE_GENERATE_REPLY_SUCCESS:
+ case WITHDRAW_PHASE_GENERATE_REPLY_SUCCESS:
phase_generate_reply_success (wc);
break;
- case PHASE_GENERATE_REPLY_ERROR:
+ case WITHDRAW_PHASE_GENERATE_REPLY_ERROR:
phase_generate_reply_error (wc);
break;
- case PHASE_RETURN_YES:
+ case WITHDRAW_PHASE_RETURN_YES:
return MHD_YES;
- case PHASE_RETURN_NO:
+ case WITHDRAW_PHASE_RETURN_NO:
return MHD_NO;
}
}