From c239ba6f18ee7d62b249c7204dbe50dab37912b8 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 27 Jan 2023 14:10:27 +0100 Subject: [PATCH] address DB failure error handling in KYC check --- src/exchange/taler-exchange-aggregator.c | 10 ++++- .../taler-exchange-httpd_batch-withdraw.c | 25 +++++++++++- .../taler-exchange-httpd_kyc-wallet.c | 24 ++++++++--- .../taler-exchange-httpd_purses_merge.c | 20 ++++++++-- .../taler-exchange-httpd_reserves_close.c | 28 +++++++++---- .../taler-exchange-httpd_reserves_purse.c | 20 ++++++++-- src/exchange/taler-exchange-httpd_withdraw.c | 20 +++++++++- src/include/taler_kyclogic_lib.h | 8 ++-- src/kyclogic/kyclogic_api.c | 40 ++++++++++++++----- 9 files changed, 155 insertions(+), 40 deletions(-) diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index dce6b2df4..823326d07 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -484,13 +484,19 @@ kyc_satisfied (struct AggregationUnit *au_active) const char *requirement; enum GNUNET_DB_QueryStatus qs; - requirement = TALER_KYCLOGIC_kyc_test_required ( + qs = TALER_KYCLOGIC_kyc_test_required ( TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT, &au_active->h_payto, db_plugin->select_satisfied_kyc_processes, db_plugin->cls, &return_relevant_amounts, - (void *) au_active); + (void *) au_active, + &requirement); + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + return false; + } if (NULL == requirement) return true; GNUNET_log (GNUNET_ERROR_TYPE_INFO, diff --git a/src/exchange/taler-exchange-httpd_batch-withdraw.c b/src/exchange/taler-exchange-httpd_batch-withdraw.c index a923784bf..b2f35b568 100644 --- a/src/exchange/taler-exchange-httpd_batch-withdraw.c +++ b/src/exchange/taler-exchange-httpd_batch-withdraw.c @@ -184,7 +184,14 @@ batch_withdraw_transaction (void *cls, wc->reserve_pub, &wc->h_payto); if (qs < 0) + { + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "reserves_get_origin"); return qs; + } if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) { *mhd_ret = TALER_MHD_reply_with_error (connection, @@ -193,13 +200,24 @@ batch_withdraw_transaction (void *cls, NULL); return GNUNET_DB_STATUS_HARD_ERROR; } - kyc_required = TALER_KYCLOGIC_kyc_test_required ( + qs = TALER_KYCLOGIC_kyc_test_required ( TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW, &wc->h_payto, TEH_plugin->select_satisfied_kyc_processes, TEH_plugin->cls, &batch_withdraw_amount_cb, - wc); + wc, + &kyc_required); + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "kyc_test_required"); + return qs; + } if (NULL != kyc_required) { /* insert KYC requirement into DB! */ @@ -221,10 +239,13 @@ batch_withdraw_transaction (void *cls, if (0 > qs) { if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); *mhd_ret = TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, "update_reserve_batch_withdraw"); + } return qs; } if (! found) diff --git a/src/exchange/taler-exchange-httpd_kyc-wallet.c b/src/exchange/taler-exchange-httpd_kyc-wallet.c index 1111b6788..515d84b69 100644 --- a/src/exchange/taler-exchange-httpd_kyc-wallet.c +++ b/src/exchange/taler-exchange-httpd_kyc-wallet.c @@ -109,22 +109,34 @@ wallet_kyc_check (void *cls, struct KycRequestContext *krc = cls; enum GNUNET_DB_QueryStatus qs; - krc->required = TALER_KYCLOGIC_kyc_test_required ( + qs = TALER_KYCLOGIC_kyc_test_required ( TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE, &krc->h_payto, TEH_plugin->select_satisfied_kyc_processes, TEH_plugin->cls, &balance_iterator, - krc); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "KYC check required at %s is `%s'\n", - TALER_amount2s (&krc->balance), - krc->required); + krc, + &krc->required); + if (qs < 0) + { + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + return qs; + GNUNET_break (0); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "kyc_test_required"); + return qs; + } if (NULL == krc->required) { krc->kyc.ok = true; return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "KYC check required at %s is `%s'\n", + TALER_amount2s (&krc->balance), + krc->required); krc->kyc.ok = false; qs = TEH_plugin->insert_kyc_requirement_for_account (TEH_plugin->cls, krc->required, diff --git a/src/exchange/taler-exchange-httpd_purses_merge.c b/src/exchange/taler-exchange-httpd_purses_merge.c index d3bded6e0..174131a3b 100644 --- a/src/exchange/taler-exchange-httpd_purses_merge.c +++ b/src/exchange/taler-exchange-httpd_purses_merge.c @@ -282,13 +282,26 @@ merge_transaction (void *cls, bool no_partner = true; const char *required; - required = TALER_KYCLOGIC_kyc_test_required ( + qs = TALER_KYCLOGIC_kyc_test_required ( TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE, &pcc->h_payto, TEH_plugin->select_satisfied_kyc_processes, TEH_plugin->cls, &amount_iterator, - pcc); + pcc, + &required); + if (qs < 0) + { + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + return qs; + GNUNET_break (0); + *mhd_ret = + TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "kyc_test_required"); + return qs; + } if (NULL != required) { pcc->kyc.ok = false; @@ -314,8 +327,7 @@ merge_transaction (void *cls, { if (GNUNET_DB_STATUS_SOFT_ERROR == qs) return qs; - TALER_LOG_WARNING ( - "Failed to store merge purse information in database\n"); + GNUNET_break (0); *mhd_ret = TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, diff --git a/src/exchange/taler-exchange-httpd_reserves_close.c b/src/exchange/taler-exchange-httpd_reserves_close.c index be36f1e73..6ace75fe6 100644 --- a/src/exchange/taler-exchange-httpd_reserves_close.c +++ b/src/exchange/taler-exchange-httpd_reserves_close.c @@ -231,14 +231,26 @@ reserve_close_transaction (void *cls, TALER_payto_hash (rcc->payto_uri, &rcc->kyc_payto); rcc->qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - kyc_needed - = TALER_KYCLOGIC_kyc_test_required ( - TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE, - &rcc->kyc_payto, - TEH_plugin->select_satisfied_kyc_processes, - TEH_plugin->cls, - &amount_it, - rcc); + qs = TALER_KYCLOGIC_kyc_test_required ( + TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE, + &rcc->kyc_payto, + TEH_plugin->select_satisfied_kyc_processes, + TEH_plugin->cls, + &amount_it, + rcc, + &kyc_needed); + if (qs < 0) + { + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + return qs; + GNUNET_break (0); + *mhd_ret + = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "iterate_reserve_close_info"); + return qs; + } if (rcc->qs < 0) { if (GNUNET_DB_STATUS_SOFT_ERROR == rcc->qs) diff --git a/src/exchange/taler-exchange-httpd_reserves_purse.c b/src/exchange/taler-exchange-httpd_reserves_purse.c index cc3ffeb15..d62c1db9b 100644 --- a/src/exchange/taler-exchange-httpd_reserves_purse.c +++ b/src/exchange/taler-exchange-httpd_reserves_purse.c @@ -192,13 +192,26 @@ purse_transaction (void *cls, const char *required; - required = TALER_KYCLOGIC_kyc_test_required ( + qs = TALER_KYCLOGIC_kyc_test_required ( TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE, &rpc->h_payto, TEH_plugin->select_satisfied_kyc_processes, TEH_plugin->cls, &amount_iterator, - rpc); + rpc, + &required); + if (qs < 0) + { + if (GNUNET_DB_STATUS_SOFT_ERROR == qs) + return qs; + GNUNET_break (0); + *mhd_ret = + TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "kyc_test_required"); + return GNUNET_DB_STATUS_HARD_ERROR; + } if (NULL != required) { rpc->kyc.ok = false; @@ -230,8 +243,7 @@ purse_transaction (void *cls, { if (GNUNET_DB_STATUS_SOFT_ERROR == qs) return qs; - TALER_LOG_WARNING ( - "Failed to store purse purse information in database\n"); + GNUNET_break (0); *mhd_ret = TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c index 05153bfc4..567cad5a9 100644 --- a/src/exchange/taler-exchange-httpd_withdraw.c +++ b/src/exchange/taler-exchange-httpd_withdraw.c @@ -164,13 +164,26 @@ withdraw_transaction (void *cls, { const char *kyc_required; - kyc_required = TALER_KYCLOGIC_kyc_test_required ( + qs = TALER_KYCLOGIC_kyc_test_required ( TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW, &wc->h_payto, TEH_plugin->select_satisfied_kyc_processes, TEH_plugin->cls, &withdraw_amount_cb, - wc); + wc, + &kyc_required); + if (qs < 0) + { + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); + *mhd_ret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "kyc_test_required"); + } + return qs; + } if (NULL != kyc_required) { /* insert KYC requirement into DB! */ @@ -198,10 +211,13 @@ withdraw_transaction (void *cls, if (0 > qs) { if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); *mhd_ret = TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, "do_withdraw"); + } return qs; } if (! found) diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h index 60a7c23d2..3acc78df2 100644 --- a/src/include/taler_kyclogic_lib.h +++ b/src/include/taler_kyclogic_lib.h @@ -214,16 +214,18 @@ typedef enum GNUNET_DB_QueryStatus * amounts involved in this type of operation * at the given account * @param ai_cls closure for @a ai - * @return NULL if no check is needed, + * @param[out] set to NULL if no check is needed, * otherwise space-separated list of required checks + * @return transaction status */ -const char * +enum GNUNET_DB_QueryStatus TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event, const struct TALER_PaytoHashP *h_payto, TALER_KYCLOGIC_KycSatisfiedIterator ki, void *ki_cls, TALER_KYCLOGIC_KycAmountIterator ai, - void *ai_cls); + void *ai_cls, + const char **required); /** diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c index 3954ae4ce..fdd814ae0 100644 --- a/src/kyclogic/kyclogic_api.c +++ b/src/kyclogic/kyclogic_api.c @@ -996,13 +996,14 @@ remove_satisfied (void *cls, } -const char * +enum GNUNET_DB_QueryStatus TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event, const struct TALER_PaytoHashP *h_payto, TALER_KYCLOGIC_KycSatisfiedIterator ki, void *ki_cls, TALER_KYCLOGIC_KycAmountIterator ai, - void *ai_cls) + void *ai_cls, + const char **required) { struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks]; unsigned int needed_cnt = 0; @@ -1035,7 +1036,10 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event, &ttc); } if (0 == needed_cnt) - return NULL; + { + *required = NULL; + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } timeframe = GNUNET_TIME_UNIT_ZERO; for (unsigned int i = 0; i= 0); // FIXME: handle DB failure more nicely? + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + return qs; + } } if (0 == needed_cnt) - return NULL; + { + *required = NULL; + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } { struct RemoveContext rc = { .needed = needed, @@ -1093,10 +1107,17 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event, h_payto, &remove_satisfied, &rc); - GNUNET_break (qs >= 0); // FIXME: handle DB failure more nicely? + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + return qs; + } } if (0 == needed_cnt) - return NULL; + { + *required = NULL; + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + } ret = NULL; for (unsigned int k = 0; k