summaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_reserves_purse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange/taler-exchange-httpd_reserves_purse.c')
-rw-r--r--src/exchange/taler-exchange-httpd_reserves_purse.c97
1 files changed, 83 insertions, 14 deletions
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;