code cleanup and additional error checking logic for #6124, but no actual semantic change

This commit is contained in:
Christian Grothoff 2020-03-14 20:18:47 +01:00
parent 6aca928cf8
commit d292b8edca
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
3 changed files with 56 additions and 24 deletions

View File

@ -433,10 +433,13 @@ TEH_RESPONSE_reply_coin_insufficient_funds (struct MHD_Connection *connection,
history = TEH_RESPONSE_compile_transaction_history (coin_pub, history = TEH_RESPONSE_compile_transaction_history (coin_pub,
tl); tl);
if (NULL == history) if (NULL == history)
{
GNUNET_break (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_COIN_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS, TALER_EC_COIN_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS,
"failed to convert transaction history to JSON"); "failed to convert transaction history to JSON");
}
return TALER_MHD_reply_json_pack (connection, return TALER_MHD_reply_json_pack (connection,
MHD_HTTP_CONFLICT, MHD_HTTP_CONFLICT,
"{s:s, s:I, s:o}", "{s:s, s:I, s:o}",
@ -462,10 +465,17 @@ TEH_RESPONSE_compile_reserve_history (const struct
struct TALER_Amount deposit_total; struct TALER_Amount deposit_total;
struct TALER_Amount withdraw_total; struct TALER_Amount withdraw_total;
json_t *json_history; json_t *json_history;
int ret; enum InitAmounts
{
/** Nothing initialized */
IA_NONE = 0,
/** deposit_total initialized */
IA_DEPOSIT = 1,
/** withdraw_total initialized */
IA_WITHDRAW = 2
} init = IA_NONE;
json_history = json_array (); json_history = json_array ();
ret = 0;
for (const struct TALER_EXCHANGEDB_ReserveHistory *pos = rh; for (const struct TALER_EXCHANGEDB_ReserveHistory *pos = rh;
NULL != pos; NULL != pos;
pos = pos->next) pos = pos->next)
@ -473,8 +483,11 @@ TEH_RESPONSE_compile_reserve_history (const struct
switch (pos->type) switch (pos->type)
{ {
case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE: case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
if (0 == (1 & ret)) if (0 == (IA_DEPOSIT & init))
{
deposit_total = pos->details.bank->amount; deposit_total = pos->details.bank->amount;
init |= IA_DEPOSIT;
}
else if (GNUNET_OK != else if (GNUNET_OK !=
TALER_amount_add (&deposit_total, TALER_amount_add (&deposit_total,
&deposit_total, &deposit_total,
@ -484,7 +497,6 @@ TEH_RESPONSE_compile_reserve_history (const struct
json_decref (json_history); json_decref (json_history);
return NULL; return NULL;
} }
ret |= 1;
if (0 != if (0 !=
json_array_append_new (json_history, json_array_append_new (json_history,
json_pack ("{s:s, s:o, s:s, s:o, s:o}", json_pack ("{s:s, s:o, s:s, s:o, s:o}",
@ -514,9 +526,10 @@ TEH_RESPONSE_compile_reserve_history (const struct
struct TALER_Amount value; struct TALER_Amount value;
value = pos->details.withdraw->amount_with_fee; value = pos->details.withdraw->amount_with_fee;
if (0 == (2 & ret)) if (0 == (IA_WITHDRAW & init))
{ {
withdraw_total = value; withdraw_total = value;
init |= IA_WITHDRAW;
} }
else else
{ {
@ -530,7 +543,6 @@ TEH_RESPONSE_compile_reserve_history (const struct
return NULL; return NULL;
} }
} }
ret |= 2;
if (0 != if (0 !=
json_array_append_new (json_history, json_array_append_new (json_history,
json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}", json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}",
@ -568,8 +580,11 @@ TEH_RESPONSE_compile_reserve_history (const struct
struct TALER_ExchangeSignatureP sig; struct TALER_ExchangeSignatureP sig;
recoup = pos->details.recoup; recoup = pos->details.recoup;
if (0 == (1 & ret)) if (0 == (IA_DEPOSIT & init))
{
deposit_total = recoup->value; deposit_total = recoup->value;
init |= IA_DEPOSIT;
}
else if (GNUNET_OK != else if (GNUNET_OK !=
TALER_amount_add (&deposit_total, TALER_amount_add (&deposit_total,
&deposit_total, &deposit_total,
@ -579,7 +594,6 @@ TEH_RESPONSE_compile_reserve_history (const struct
json_decref (json_history); json_decref (json_history);
return NULL; return NULL;
} }
ret |= 1;
pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP); pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP);
pc.purpose.size = htonl (sizeof (struct TALER_RecoupConfirmationPS)); pc.purpose.size = htonl (sizeof (struct TALER_RecoupConfirmationPS));
pc.timestamp = GNUNET_TIME_absolute_hton (recoup->timestamp); pc.timestamp = GNUNET_TIME_absolute_hton (recoup->timestamp);
@ -628,9 +642,10 @@ TEH_RESPONSE_compile_reserve_history (const struct
struct TALER_Amount value; struct TALER_Amount value;
value = pos->details.closing->amount; value = pos->details.closing->amount;
if (0 == (2 & ret)) if (0 == (IA_WITHDRAW & init))
{ {
withdraw_total = value; withdraw_total = value;
init |= IA_WITHDRAW;
} }
else else
{ {
@ -644,7 +659,6 @@ TEH_RESPONSE_compile_reserve_history (const struct
return NULL; return NULL;
} }
} }
ret |= 2;
rcc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED); rcc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED);
rcc.purpose.size = htonl (sizeof (struct rcc.purpose.size = htonl (sizeof (struct
TALER_ReserveCloseConfirmationPS)); TALER_ReserveCloseConfirmationPS));
@ -703,15 +717,17 @@ TEH_RESPONSE_compile_reserve_history (const struct
} }
} }
if (0 == (1 & ret)) if (0 == (IA_DEPOSIT & init))
{ {
/* We should not have gotten here, without deposits no reserve
should exist! */
GNUNET_break (0); GNUNET_break (0);
json_decref (json_history); json_decref (json_history);
return NULL; return NULL;
} }
if (0 == (2 & ret)) if (0 == (IA_WITHDRAW & init))
{ {
/* did not encounter any withdraw operations, set to zero */ /* did not encounter any withdraw operations, set withdraw_total to zero */
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (deposit_total.currency, TALER_amount_get_zero (deposit_total.currency,
&withdraw_total)); &withdraw_total));

View File

@ -44,33 +44,40 @@
/** /**
* Send reserve status information to client with the * Send reserve status information to client with the
* message that we have insufficient funds for the * message that we have insufficient funds for the
* requested /reserve/withdraw operation. * requested withdraw operation.
* *
* @param connection connection to the client * @param connection connection to the client
* @param ebalance expected balance based on our database
* @param rh reserve history to return * @param rh reserve history to return
* @return MHD result code * @return MHD result code
*/ */
static int static int
reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *connection, reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *connection,
const struct TALER_Amount *ebalance,
const struct const struct
TALER_EXCHANGEDB_ReserveHistory *rh) TALER_EXCHANGEDB_ReserveHistory *rh)
{ {
json_t *json_balance;
json_t *json_history; json_t *json_history;
struct TALER_Amount balance; struct TALER_Amount balance;
json_history = TEH_RESPONSE_compile_reserve_history (rh, json_history = TEH_RESPONSE_compile_reserve_history (rh,
&balance); &balance);
if ((NULL == json_history) if (NULL == json_history)
/* Address the case where the ptr is not null, but
* it fails "internally" to dump as string (= corrupted). */
|| (0 == json_dumpb (json_history, NULL, 0, 0)))
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_WITHDRAW_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS, TALER_EC_WITHDRAW_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS,
"balance calculation failure"); "balance calculation failure");
json_balance = TALER_JSON_from_amount (&balance); if (0 !=
TALER_amount_cmp (&balance,
ebalance))
{
GNUNET_break (0);
json_decref (json_history);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_WITHDRAW_HISTORY_RESERVE_BALANCE_CORRUPT,
"internal balance inconsistency error");
}
return TALER_MHD_reply_json_pack (connection, return TALER_MHD_reply_json_pack (connection,
MHD_HTTP_CONFLICT, MHD_HTTP_CONFLICT,
"{s:s, s:I, s:o, s:o}", "{s:s, s:I, s:o, s:o}",
@ -78,7 +85,8 @@ reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *connection,
"code", "code",
(json_int_t) (json_int_t)
TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS, TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS,
"balance", json_balance, "balance", TALER_JSON_from_amount (
&balance),
"history", json_history); "history", json_history);
} }
@ -285,6 +293,7 @@ withdraw_transaction (void *cls,
return GNUNET_DB_STATUS_HARD_ERROR; return GNUNET_DB_STATUS_HARD_ERROR;
} }
*mhd_ret = reply_reserve_withdraw_insufficient_funds (connection, *mhd_ret = reply_reserve_withdraw_insufficient_funds (connection,
&r.balance,
rh); rh);
TEH_plugin->free_reserve_history (TEH_plugin->cls, TEH_plugin->free_reserve_history (TEH_plugin->cls,
rh); rh);
@ -455,7 +464,7 @@ TEH_RESERVE_handler_reserve_withdraw (const struct TEH_RequestHandler *rh,
&wc.wsrd.reserve_pub.eddsa_pub)) &wc.wsrd.reserve_pub.eddsa_pub))
{ {
TALER_LOG_WARNING ( TALER_LOG_WARNING (
"Client supplied invalid signature for /reserve/withdraw request\n"); "Client supplied invalid signature for withdraw request\n");
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
TEH_KS_release (wc.key_state); TEH_KS_release (wc.key_state);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (connection,
@ -484,7 +493,7 @@ TEH_RESERVE_handler_reserve_withdraw (const struct TEH_RequestHandler *rh,
if (GNUNET_OK != if (GNUNET_OK !=
TEH_DB_run_transaction (connection, TEH_DB_run_transaction (connection,
"run reserve withdraw", "run withdraw",
&mhd_ret, &mhd_ret,
&withdraw_transaction, &withdraw_transaction,
&wc)) &wc))

View File

@ -381,6 +381,13 @@ enum TALER_ErrorCode
*/ */
TALER_EC_DENOMINATION_KEY_LOST = 1116, TALER_EC_DENOMINATION_KEY_LOST = 1116,
/**
* The exchange's database entry with the reserve balance summary
* is inconsistent with its own history of the reserve.
* Returned with an HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
TALER_EC_WITHDRAW_HISTORY_RESERVE_BALANCE_CORRUPT = 1117,
/** /**
* The exchange failed to obtain the transaction history of the given * The exchange failed to obtain the transaction history of the given
* reserve from the database. This response is provided with HTTP * reserve from the database. This response is provided with HTTP