diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-08-14 18:04:09 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-08-14 18:04:09 +0200 |
commit | 74ba46db39d3a906e819cd0ed48f1d46dffe9e38 (patch) | |
tree | 53f050bacd2e634dc5e746a257b10be9294afa71 /src/exchange | |
parent | 913eacf506860a73043be09425d1c143b786e871 (diff) | |
download | exchange-74ba46db39d3a906e819cd0ed48f1d46dffe9e38.tar.gz exchange-74ba46db39d3a906e819cd0ed48f1d46dffe9e38.tar.bz2 exchange-74ba46db39d3a906e819cd0ed48f1d46dffe9e38.zip |
-work on new KYC logic: tests pass again
Diffstat (limited to 'src/exchange')
-rw-r--r-- | src/exchange/taler-exchange-httpd_batch-withdraw.c | 7 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_deposits_get.c | 2 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-wallet.c | 2 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_purses_merge.c | 96 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_get.c | 2 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_purse.c | 97 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_status.c | 21 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_responses.c | 12 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_responses.h | 13 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_withdraw.c | 9 |
10 files changed, 194 insertions, 67 deletions
diff --git a/src/exchange/taler-exchange-httpd_batch-withdraw.c b/src/exchange/taler-exchange-httpd_batch-withdraw.c index 9e24ff4c3..635a968d3 100644 --- a/src/exchange/taler-exchange-httpd_batch-withdraw.c +++ b/src/exchange/taler-exchange-httpd_batch-withdraw.c @@ -327,11 +327,8 @@ generate_reply_success (const struct TEH_RequestContext *rc, if (! wc->kyc.ok) { /* KYC required */ - return TALER_MHD_REPLY_JSON_PACK ( - rc->connection, - MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, - GNUNET_JSON_pack_uint64 ("payment_target_uuid", - wc->kyc.payment_target_uuid)); + return TEH_RESPONSE_reply_kyc_required (rc->connection, + &wc->kyc); } sigs = json_array (); diff --git a/src/exchange/taler-exchange-httpd_deposits_get.c b/src/exchange/taler-exchange-httpd_deposits_get.c index eec815690..682cb6ecd 100644 --- a/src/exchange/taler-exchange-httpd_deposits_get.c +++ b/src/exchange/taler-exchange-httpd_deposits_get.c @@ -247,7 +247,7 @@ handle_track_transaction_request ( MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_INVARIANT_FAILURE, "wire fees exceed aggregate in database"); - if (GNUNET_YES == ctx->pending) + if (ctx->pending) return TALER_MHD_REPLY_JSON_PACK ( connection, MHD_HTTP_ACCEPTED, diff --git a/src/exchange/taler-exchange-httpd_kyc-wallet.c b/src/exchange/taler-exchange-httpd_kyc-wallet.c index a043de6ff..9a1133c7f 100644 --- a/src/exchange/taler-exchange-httpd_kyc-wallet.c +++ b/src/exchange/taler-exchange-httpd_kyc-wallet.c @@ -227,7 +227,7 @@ TEH_handler_kyc_wallet ( return TALER_MHD_REPLY_JSON_PACK ( rc->connection, MHD_HTTP_OK, - GNUNET_JSON_pack_uint64 ("payment_target_uuid", + GNUNET_JSON_pack_uint64 ("legitimization_uuid", krc.legi_row)); } diff --git a/src/exchange/taler-exchange-httpd_purses_merge.c b/src/exchange/taler-exchange-httpd_purses_merge.c index 25d91e1be..c1db6cf39 100644 --- a/src/exchange/taler-exchange-httpd_purses_merge.c +++ b/src/exchange/taler-exchange-httpd_purses_merge.c @@ -28,6 +28,7 @@ #include <pthread.h> #include "taler_dbevents.h" #include "taler_json_lib.h" +#include "taler_kyclogic_lib.h" #include "taler_mhd_lib.h" #include "taler-exchange-httpd_purses_merge.h" #include "taler-exchange-httpd_responses.h" @@ -103,11 +104,21 @@ struct PurseMergeContext /** * URI of the account the purse is to be merged into. - * Must be of the form 'payto://taler/$EXCHANGE_URL/RESERVE_PUB'. + * Must be of the form 'payto://taler-reserve/$EXCHANGE_URL/RESERVE_PUB'. */ const char *payto_uri; /** + * Hash of the @e payto_uri. + */ + struct TALER_PaytoHashP h_payto; + + /** + * KYC status of the operation. + */ + struct TALER_EXCHANGEDB_KycStatus kyc; + + /** * Base URL of the exchange provider hosting the reserve. */ char *provider_url; @@ -202,6 +213,46 @@ reply_merge_success (struct MHD_Connection *connection, /** + * Function called to iterate over KYC-relevant + * transaction amounts for a particular time range. + * Called within a database transaction, so must + * not start a new one. + * + * @param cls a `struct PurseMergeContext` + * @param limit maximum time-range for which events + * should be fetched (timestamp in the past) + * @param cb function to call on each event found, + * events must be returned in reverse chronological + * order + * @param cb_cls closure for @a cb + */ +static void +amount_iterator (void *cls, + struct GNUNET_TIME_Absolute limit, + TALER_EXCHANGEDB_KycAmountCallback cb, + void *cb_cls) +{ + struct PurseMergeContext *pcc = cls; + enum GNUNET_DB_QueryStatus qs; + + cb (cb_cls, + &pcc->target_amount, + GNUNET_TIME_absolute_get ()); + qs = TEH_plugin->select_merge_amounts_for_kyc_check ( + TEH_plugin->cls, + &pcc->h_payto, + limit, + cb, + cb_cls); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got %d additional transactions for this merge and limit %llu\n", + qs, + (unsigned long long) limit.abs_value_us); + GNUNET_break (qs >= 0); +} + + +/** * Execute database transaction for /purses/$PID/merge. Runs the transaction * logic; IF it returns a non-error code, the transaction logic MUST NOT queue * a MHD response. IF it returns an hard error, the transaction logic MUST @@ -224,9 +275,26 @@ merge_transaction (void *cls, bool in_conflict = true; bool no_balance = true; bool no_partner = true; - bool no_kyc = true; bool no_reserve = true; + const char *required; + required = 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); + if (NULL != required) + { + pcc->kyc.ok = false; + return TEH_plugin->insert_kyc_requirement_for_account ( + TEH_plugin->cls, + required, + &pcc->h_payto, + &pcc->kyc.payment_target_uuid); + } + pcc->kyc.ok = true; qs = TEH_plugin->do_purse_merge ( TEH_plugin->cls, pcc->purse_pub, @@ -235,11 +303,9 @@ merge_transaction (void *cls, &pcc->reserve_sig, pcc->provider_url, &pcc->reserve_pub, - TEH_KYC_NONE != TEH_kyc_config.mode, &no_partner, &no_balance, &no_reserve, - &no_kyc, &in_conflict); if (qs < 0) { @@ -272,17 +338,6 @@ merge_transaction (void *cls, NULL); return GNUNET_DB_STATUS_HARD_ERROR; } - if ( (no_kyc) && - (TEH_KYC_NONE != TEH_kyc_config.mode) ) - { - *mhd_ret - = TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, - TALER_JSON_pack_ec ( - TALER_EC_EXCHANGE_GENERIC_KYC_REQUIRED)); - return GNUNET_DB_STATUS_HARD_ERROR; - } if (no_balance) { *mhd_ret = @@ -333,6 +388,7 @@ merge_transaction (void *cls, GNUNET_free (partner_url); return GNUNET_DB_STATUS_HARD_ERROR; } + return qs; } @@ -434,7 +490,6 @@ TEH_handler_purses_merge ( TALER_EC_GENERIC_PARAMETER_MALFORMED, "payto_uri"); } - http = (0 == strncmp (pcc.payto_uri, "payto://taler-reserve+http/", strlen ("payto://taler-reserve+http/"))); @@ -477,6 +532,8 @@ TEH_handler_purses_merge ( } slash++; } + TALER_payto_hash (pcc.payto_uri, + &pcc.h_payto); if (0 == strcmp (pcc.provider_url, TEH_base_url)) { @@ -615,6 +672,12 @@ TEH_handler_purses_merge ( } } + + GNUNET_free (pcc.provider_url); + if (! pcc.kyc.ok) + return TEH_RESPONSE_reply_kyc_required (connection, + &pcc.kyc); + { struct TALER_PurseEventP rep = { .header.size = htons (sizeof (rep)), @@ -630,7 +693,6 @@ TEH_handler_purses_merge ( 0); } - GNUNET_free (pcc.provider_url); /* generate regular response */ return reply_merge_success (connection, &pcc); diff --git a/src/exchange/taler-exchange-httpd_reserves_get.c b/src/exchange/taler-exchange-httpd_reserves_get.c index 27f8faecd..19fb7df8e 100644 --- a/src/exchange/taler-exchange-httpd_reserves_get.c +++ b/src/exchange/taler-exchange-httpd_reserves_get.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2022 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software diff --git a/src/exchange/taler-exchange-httpd_reserves_purse.c b/src/exchange/taler-exchange-httpd_reserves_purse.c index d377323e4..4730a5791 100644 --- a/src/exchange/taler-exchange-httpd_reserves_purse.c +++ b/src/exchange/taler-exchange-httpd_reserves_purse.c @@ -27,6 +27,7 @@ #include <microhttpd.h> #include <pthread.h> #include "taler_json_lib.h" +#include "taler_kyclogic_lib.h" #include "taler_mhd_lib.h" #include "taler-exchange-httpd_reserves_purse.h" #include "taler-exchange-httpd_responses.h" @@ -101,6 +102,16 @@ struct ReservePurseContext struct TEH_PurseDetails pd; /** + * Hash of the @e payto_uri. + */ + struct TALER_PaytoHashP h_payto; + + /** + * KYC status of the operation. + */ + struct TALER_EXCHANGEDB_KycStatus kyc; + + /** * Minimum age for deposits into this purse. */ uint32_t min_age; @@ -119,6 +130,46 @@ struct ReservePurseContext /** + * Function called to iterate over KYC-relevant + * transaction amounts for a particular time range. + * Called within a database transaction, so must + * not start a new one. + * + * @param cls a `struct ReservePurseContext` + * @param limit maximum time-range for which events + * should be fetched (timestamp in the past) + * @param cb function to call on each event found, + * events must be returned in reverse chronological + * order + * @param cb_cls closure for @a cb + */ +static void +amount_iterator (void *cls, + struct GNUNET_TIME_Absolute limit, + TALER_EXCHANGEDB_KycAmountCallback cb, + void *cb_cls) +{ + struct ReservePurseContext *rpc = cls; + enum GNUNET_DB_QueryStatus qs; + + cb (cb_cls, + &rpc->deposit_total, + GNUNET_TIME_absolute_get ()); + qs = TEH_plugin->select_merge_amounts_for_kyc_check ( + TEH_plugin->cls, + &rpc->h_payto, + limit, + cb, + cb_cls); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got %d additional transactions for this merge and limit %llu\n", + qs, + (unsigned long long) limit.abs_value_us); + GNUNET_break (qs >= 0); +} + + +/** * Execute database transaction for /reserves/$PID/purse. Runs the transaction * logic; IF it returns a non-error code, the transaction logic MUST NOT queue * a MHD response. IF it returns an hard error, the transaction logic MUST @@ -139,6 +190,26 @@ purse_transaction (void *cls, struct ReservePurseContext *rpc = cls; enum GNUNET_DB_QueryStatus qs; + const char *required; + + required = 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); + if (NULL != required) + { + rpc->kyc.ok = false; + return TEH_plugin->insert_kyc_requirement_for_account ( + TEH_plugin->cls, + required, + &rpc->h_payto, + &rpc->kyc.payment_target_uuid); + } + rpc->kyc.ok = true; + { bool in_conflict = true; @@ -230,7 +301,6 @@ purse_transaction (void *cls, bool in_conflict = true; bool insufficient_funds = true; bool no_reserve = true; - bool no_kyc = true; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Creating purse with flags %d\n", @@ -246,10 +316,8 @@ purse_transaction (void *cls, ? NULL : &rpc->gf->fees.purse, rpc->reserve_pub, - TEH_KYC_NONE != TEH_kyc_config.mode, &in_conflict, &no_reserve, - &no_kyc, &insufficient_funds); if (qs < 0) { @@ -322,17 +390,6 @@ purse_transaction (void *cls, TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN)); return GNUNET_DB_STATUS_HARD_ERROR; } - if ( (no_kyc) && - (TEH_KYC_NONE != TEH_kyc_config.mode) ) - { - *mhd_ret - = TALER_MHD_REPLY_JSON_PACK ( - connection, - MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, - TALER_JSON_pack_ec ( - TALER_EC_EXCHANGE_GENERIC_KYC_REQUIRED)); - return GNUNET_DB_STATUS_HARD_ERROR; - } if (insufficient_funds) { *mhd_ret @@ -472,6 +529,15 @@ TEH_handler_reserves_purse ( return MHD_YES; /* failure */ } } + { + char *payto_uri; + + payto_uri = TALER_reserve_make_payto (TEH_base_url, + reserve_pub); + TALER_payto_hash (payto_uri, + &rpc.h_payto); + GNUNET_free (payto_uri); + } GNUNET_assert (GNUNET_OK == TALER_amount_set_zero (TEH_currency, &rpc.deposit_total)); @@ -641,6 +707,9 @@ TEH_handler_reserves_purse ( } } + if (! rpc.kyc.ok) + return TEH_RESPONSE_reply_kyc_required (connection, + &rpc.kyc); /* generate regular response */ { MHD_RESULT res; diff --git a/src/exchange/taler-exchange-httpd_reserves_status.c b/src/exchange/taler-exchange-httpd_reserves_status.c index ff8a65c23..4e7b4f47c 100644 --- a/src/exchange/taler-exchange-httpd_reserves_status.c +++ b/src/exchange/taler-exchange-httpd_reserves_status.c @@ -54,11 +54,6 @@ struct ReserveStatusContext struct TALER_EXCHANGEDB_ReserveHistory *rh; /** - * Current KYC status. - */ - struct TALER_EXCHANGEDB_KycStatus kyc; - - /** * Sum of incoming transactions within the returned history. * (currently not used). */ @@ -102,8 +97,6 @@ reply_reserve_status_success (struct MHD_Connection *connection, MHD_HTTP_OK, TALER_JSON_pack_amount ("balance", &rhc->balance), - GNUNET_JSON_pack_bool ("kyc_passed", - rhc->kyc.ok), GNUNET_JSON_pack_array_steal ("history", json_history)); } @@ -133,20 +126,6 @@ reserve_status_transaction (void *cls, struct ReserveStatusContext *rsc = cls; enum GNUNET_DB_QueryStatus qs; - qs = TEH_plugin->inselect_wallet_kyc_status (TEH_plugin->cls, - rsc->reserve_pub, - &rsc->kyc); - 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, - "inselect_wallet_status"); - return qs; - } qs = TEH_plugin->get_reserve_status (TEH_plugin->cls, rsc->reserve_pub, &rsc->balance_in, diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 2642f433a..0320a07b3 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -977,4 +977,16 @@ TEH_RESPONSE_reply_purse_created ( } +MHD_RESULT +TEH_RESPONSE_reply_kyc_required (struct MHD_Connection *connection, + const struct TALER_EXCHANGEDB_KycStatus *kyc) +{ + return TALER_MHD_REPLY_JSON_PACK ( + connection, + MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, + GNUNET_JSON_pack_uint64 ("legitimization_uuid", + kyc->payment_target_uuid)); +} + + /* end of taler-exchange-httpd_responses.c */ diff --git a/src/exchange/taler-exchange-httpd_responses.h b/src/exchange/taler-exchange-httpd_responses.h index 6cd672414..9243960d8 100644 --- a/src/exchange/taler-exchange-httpd_responses.h +++ b/src/exchange/taler-exchange-httpd_responses.h @@ -75,6 +75,19 @@ TEH_RESPONSE_reply_reserve_insufficient_balance ( /** + * Send information that a KYC check must be + * satisfied to proceed to client. + * + * @param connection connection to the client + * @param pcc details about the request that succeeded + * @return MHD result code + */ +MHD_RESULT +TEH_RESPONSE_reply_kyc_required (struct MHD_Connection *connection, + const struct TALER_EXCHANGEDB_KycStatus *kyc); + + +/** * Send assertion that the given denomination key hash * is not usable (typically expired) at this time. * diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c index 255f7d948..920147d4a 100644 --- a/src/exchange/taler-exchange-httpd_withdraw.c +++ b/src/exchange/taler-exchange-httpd_withdraw.c @@ -490,13 +490,8 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc, GNUNET_JSON_parse_free (spec); if (! wc.kyc.ok) - { - return TALER_MHD_REPLY_JSON_PACK ( - rc->connection, - MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS, - GNUNET_JSON_pack_uint64 ("payment_target_uuid", - wc.kyc.payment_target_uuid)); - } + return TEH_RESPONSE_reply_kyc_required (rc->connection, + &wc.kyc); { MHD_RESULT ret; |