-more work on AML triggers for P2P transfers
This commit is contained in:
parent
174022907b
commit
6db4bdbe6e
@ -1 +1 @@
|
|||||||
Subproject commit 3a616a04f1cd946bf0641b54cd71f1b858174f74
|
Subproject commit a7abaa856abbd16994132c5596ce04f442b9f4b9
|
@ -147,6 +147,13 @@ struct TALER_EXCHANGEDB_Plugin *TEH_plugin;
|
|||||||
*/
|
*/
|
||||||
char *TEH_currency;
|
char *TEH_currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What is the largest amount we allow a peer to
|
||||||
|
* merge into a reserve before always triggering
|
||||||
|
* an AML check?
|
||||||
|
*/
|
||||||
|
struct TALER_Amount TEH_aml_threshold;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Our base URL.
|
* Our base URL.
|
||||||
*/
|
*/
|
||||||
@ -1860,6 +1867,16 @@ exchange_serve_process_config (void)
|
|||||||
"CURRENCY");
|
"CURRENCY");
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TALER_config_get_amount (TEH_cfg,
|
||||||
|
"taler",
|
||||||
|
"AML_THRESHOLD",
|
||||||
|
&TEH_aml_threshold))
|
||||||
|
{
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"Need amount in section `TALER' under `AML_THRESHOLD'\n");
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
|
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
|
||||||
"exchange",
|
"exchange",
|
||||||
|
@ -97,6 +97,13 @@ extern struct TALER_EXCHANGEDB_Plugin *TEH_plugin;
|
|||||||
*/
|
*/
|
||||||
extern char *TEH_currency;
|
extern char *TEH_currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What is the largest amount we allow a peer to
|
||||||
|
* merge into a reserve before always triggering
|
||||||
|
* an AML check?
|
||||||
|
*/
|
||||||
|
extern struct TALER_Amount TEH_aml_threshold;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Our (externally visible) base URL.
|
* Our (externally visible) base URL.
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014-2022 Taler Systems SA
|
Copyright (C) 2014-2023 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify
|
TALER is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Affero General Public License as
|
it under the terms of the GNU Affero General Public License as
|
||||||
@ -108,6 +108,11 @@ struct BatchWithdrawContext
|
|||||||
*/
|
*/
|
||||||
unsigned int planchets_length;
|
unsigned int planchets_length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AML decision, #TALER_AML_NORMAL if we may proceed.
|
||||||
|
*/
|
||||||
|
enum TALER_AmlDecisionState aml_decision;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -150,6 +155,34 @@ batch_withdraw_amount_cb (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called on each @a amount that was found to
|
||||||
|
* be relevant for the AML check as it was merged into
|
||||||
|
* the reserve.
|
||||||
|
*
|
||||||
|
* @param cls `struct TALER_Amount *` to total up the amounts
|
||||||
|
* @param amount encountered transaction amount
|
||||||
|
* @param date when was the amount encountered
|
||||||
|
* @return #GNUNET_OK to continue to iterate,
|
||||||
|
* #GNUNET_NO to abort iteration
|
||||||
|
* #GNUNET_SYSERR on internal error (also abort itaration)
|
||||||
|
*/
|
||||||
|
static enum GNUNET_GenericReturnValue
|
||||||
|
aml_amount_cb (
|
||||||
|
void *cls,
|
||||||
|
const struct TALER_Amount *amount,
|
||||||
|
struct GNUNET_TIME_Absolute date)
|
||||||
|
{
|
||||||
|
struct TALER_Amount *total = cls;
|
||||||
|
|
||||||
|
GNUNET_assert (0 <=
|
||||||
|
TALER_amount_add (total,
|
||||||
|
total,
|
||||||
|
amount));
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function implementing withdraw transaction. Runs the
|
* Function implementing withdraw transaction. Runs the
|
||||||
* transaction logic; IF it returns a non-error code, the transaction
|
* transaction logic; IF it returns a non-error code, the transaction
|
||||||
@ -178,8 +211,102 @@ batch_withdraw_transaction (void *cls,
|
|||||||
bool balance_ok = false;
|
bool balance_ok = false;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
const char *kyc_required;
|
const char *kyc_required;
|
||||||
|
struct TALER_PaytoHashP reserve_h_payto;
|
||||||
|
|
||||||
wc->now = GNUNET_TIME_timestamp_get ();
|
wc->now = GNUNET_TIME_timestamp_get ();
|
||||||
|
/* Do AML check: compute total merged amount and check
|
||||||
|
against applicable AML threshold */
|
||||||
|
{
|
||||||
|
char *reserve_payto;
|
||||||
|
|
||||||
|
reserve_payto = TALER_reserve_make_payto (TEH_base_url,
|
||||||
|
wc->reserve_pub);
|
||||||
|
TALER_payto_hash (reserve_payto,
|
||||||
|
&reserve_h_payto);
|
||||||
|
GNUNET_free (reserve_payto);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
struct TALER_Amount merge_amount;
|
||||||
|
struct TALER_Amount threshold;
|
||||||
|
struct GNUNET_TIME_Absolute now_minus_one_month;
|
||||||
|
|
||||||
|
now_minus_one_month
|
||||||
|
= GNUNET_TIME_absolute_subtract (wc->now.abs_time,
|
||||||
|
GNUNET_TIME_UNIT_MONTHS);
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_set_zero (TEH_currency,
|
||||||
|
&merge_amount));
|
||||||
|
qs = TEH_plugin->select_merge_amounts_for_kyc_check (TEH_plugin->cls,
|
||||||
|
&reserve_h_payto,
|
||||||
|
now_minus_one_month,
|
||||||
|
&aml_amount_cb,
|
||||||
|
&merge_amount);
|
||||||
|
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,
|
||||||
|
"select_merge_amounts_for_kyc_check");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
qs = TEH_plugin->select_aml_threshold (TEH_plugin->cls,
|
||||||
|
&reserve_h_payto,
|
||||||
|
&wc->aml_decision,
|
||||||
|
&threshold);
|
||||||
|
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,
|
||||||
|
"select_aml_threshold");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||||
|
{
|
||||||
|
threshold = TEH_aml_threshold; /* use default */
|
||||||
|
wc->aml_decision = TALER_AML_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (wc->aml_decision)
|
||||||
|
{
|
||||||
|
case TALER_AML_NORMAL:
|
||||||
|
if (0 >= TALER_amount_cmp (&merge_amount,
|
||||||
|
&threshold))
|
||||||
|
{
|
||||||
|
/* merge_amount <= threshold, continue withdraw below */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wc->aml_decision = TALER_AML_PENDING;
|
||||||
|
qs = TEH_plugin->trigger_aml_process (TEH_plugin->cls,
|
||||||
|
&reserve_h_payto,
|
||||||
|
&merge_amount);
|
||||||
|
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_STORE_FAILED,
|
||||||
|
"trigger_aml_process");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
return qs;
|
||||||
|
case TALER_AML_PENDING:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"AML already pending, doing nothing\n");
|
||||||
|
return qs;
|
||||||
|
case TALER_AML_FROZEN:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Account frozen, doing nothing\n");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the money came from a wire transfer */
|
||||||
qs = TEH_plugin->reserves_get_origin (TEH_plugin->cls,
|
qs = TEH_plugin->reserves_get_origin (TEH_plugin->cls,
|
||||||
wc->reserve_pub,
|
wc->reserve_pub,
|
||||||
&wc->h_payto);
|
&wc->h_payto);
|
||||||
@ -352,6 +479,9 @@ generate_reply_success (const struct TEH_RequestContext *rc,
|
|||||||
&wc->h_payto,
|
&wc->h_payto,
|
||||||
&wc->kyc);
|
&wc->kyc);
|
||||||
}
|
}
|
||||||
|
if (TALER_AML_NORMAL != wc->aml_decision)
|
||||||
|
return TEH_RESPONSE_reply_aml_blocked (rc->connection,
|
||||||
|
wc->aml_decision);
|
||||||
|
|
||||||
sigs = json_array ();
|
sigs = json_array ();
|
||||||
GNUNET_assert (NULL != sigs);
|
GNUNET_assert (NULL != sigs);
|
||||||
|
@ -1142,4 +1142,29 @@ TEH_RESPONSE_reply_kyc_required (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MHD_RESULT
|
||||||
|
TEH_RESPONSE_reply_aml_blocked (struct MHD_Connection *connection,
|
||||||
|
enum TALER_AmlDecisionState status)
|
||||||
|
{
|
||||||
|
enum TALER_ErrorCode ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
|
||||||
|
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case TALER_AML_NORMAL:
|
||||||
|
GNUNET_break (0);
|
||||||
|
return MHD_NO;
|
||||||
|
case TALER_AML_PENDING:
|
||||||
|
ec = TALER_EC_EXCHANGE_GENERIC_AML_PENDING;
|
||||||
|
break;
|
||||||
|
case TALER_AML_FROZEN:
|
||||||
|
ec = TALER_EC_EXCHANGE_GENERIC_AML_FROZEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TALER_MHD_REPLY_JSON_PACK (
|
||||||
|
connection,
|
||||||
|
MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
|
||||||
|
TALER_JSON_pack_ec (ec));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* end of taler-exchange-httpd_responses.c */
|
/* end of taler-exchange-httpd_responses.c */
|
||||||
|
@ -91,6 +91,19 @@ TEH_RESPONSE_reply_kyc_required (struct MHD_Connection *connection,
|
|||||||
const struct TALER_EXCHANGEDB_KycStatus *kyc);
|
const struct TALER_EXCHANGEDB_KycStatus *kyc);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send information that an AML process is blocking
|
||||||
|
* the operation right now.
|
||||||
|
*
|
||||||
|
* @param connection connection to the client
|
||||||
|
* @param status current AML status
|
||||||
|
* @return MHD result code
|
||||||
|
*/
|
||||||
|
MHD_RESULT
|
||||||
|
TEH_RESPONSE_reply_aml_blocked (struct MHD_Connection *connection,
|
||||||
|
enum TALER_AmlDecisionState status);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send assertion that the given denomination key hash
|
* Send assertion that the given denomination key hash
|
||||||
* is not usable (typically expired) at this time.
|
* is not usable (typically expired) at this time.
|
||||||
|
@ -61,16 +61,21 @@ struct WithdrawContext
|
|||||||
struct TALER_EXCHANGEDB_KycStatus kyc;
|
struct TALER_EXCHANGEDB_KycStatus kyc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash of the payto-URI representing the reserve
|
* Hash of the payto-URI representing the account
|
||||||
* from which we are withdrawing.
|
* from which the money was put into the reserve.
|
||||||
*/
|
*/
|
||||||
struct TALER_PaytoHashP h_payto;
|
struct TALER_PaytoHashP h_account_payto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current time for the DB transaction.
|
* Current time for the DB transaction.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_TIME_Timestamp now;
|
struct GNUNET_TIME_Timestamp now;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AML decision, #TALER_AML_NORMAL if we may proceed.
|
||||||
|
*/
|
||||||
|
enum TALER_AmlDecisionState aml_decision;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -108,7 +113,7 @@ withdraw_amount_cb (void *cls,
|
|||||||
return;
|
return;
|
||||||
qs = TEH_plugin->select_withdraw_amounts_for_kyc_check (
|
qs = TEH_plugin->select_withdraw_amounts_for_kyc_check (
|
||||||
TEH_plugin->cls,
|
TEH_plugin->cls,
|
||||||
&wc->h_payto,
|
&wc->h_account_payto,
|
||||||
limit,
|
limit,
|
||||||
cb,
|
cb,
|
||||||
cb_cls);
|
cb_cls);
|
||||||
@ -120,6 +125,34 @@ withdraw_amount_cb (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called on each @a amount that was found to
|
||||||
|
* be relevant for the AML check as it was merged into
|
||||||
|
* the reserve.
|
||||||
|
*
|
||||||
|
* @param cls `struct TALER_Amount *` to total up the amounts
|
||||||
|
* @param amount encountered transaction amount
|
||||||
|
* @param date when was the amount encountered
|
||||||
|
* @return #GNUNET_OK to continue to iterate,
|
||||||
|
* #GNUNET_NO to abort iteration
|
||||||
|
* #GNUNET_SYSERR on internal error (also abort itaration)
|
||||||
|
*/
|
||||||
|
static enum GNUNET_GenericReturnValue
|
||||||
|
aml_amount_cb (
|
||||||
|
void *cls,
|
||||||
|
const struct TALER_Amount *amount,
|
||||||
|
struct GNUNET_TIME_Absolute date)
|
||||||
|
{
|
||||||
|
struct TALER_Amount *total = cls;
|
||||||
|
|
||||||
|
GNUNET_assert (0 <=
|
||||||
|
TALER_amount_add (total,
|
||||||
|
total,
|
||||||
|
amount));
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function implementing withdraw transaction. Runs the
|
* Function implementing withdraw transaction. Runs the
|
||||||
* transaction logic; IF it returns a non-error code, the transaction
|
* transaction logic; IF it returns a non-error code, the transaction
|
||||||
@ -150,23 +183,116 @@ withdraw_transaction (void *cls,
|
|||||||
uint64_t ruuid;
|
uint64_t ruuid;
|
||||||
const struct TALER_CsNonce *nonce;
|
const struct TALER_CsNonce *nonce;
|
||||||
const struct TALER_BlindedPlanchet *bp;
|
const struct TALER_BlindedPlanchet *bp;
|
||||||
|
struct TALER_PaytoHashP reserve_h_payto;
|
||||||
|
|
||||||
wc->now = GNUNET_TIME_timestamp_get ();
|
wc->now = GNUNET_TIME_timestamp_get ();
|
||||||
|
/* Do AML check: compute total merged amount and check
|
||||||
|
against applicable AML threshold */
|
||||||
|
{
|
||||||
|
char *reserve_payto;
|
||||||
|
|
||||||
|
reserve_payto = TALER_reserve_make_payto (TEH_base_url,
|
||||||
|
&wc->collectable.reserve_pub);
|
||||||
|
TALER_payto_hash (reserve_payto,
|
||||||
|
&reserve_h_payto);
|
||||||
|
GNUNET_free (reserve_payto);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
struct TALER_Amount merge_amount;
|
||||||
|
struct TALER_Amount threshold;
|
||||||
|
struct GNUNET_TIME_Absolute now_minus_one_month;
|
||||||
|
|
||||||
|
now_minus_one_month
|
||||||
|
= GNUNET_TIME_absolute_subtract (wc->now.abs_time,
|
||||||
|
GNUNET_TIME_UNIT_MONTHS);
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_set_zero (TEH_currency,
|
||||||
|
&merge_amount));
|
||||||
|
qs = TEH_plugin->select_merge_amounts_for_kyc_check (TEH_plugin->cls,
|
||||||
|
&reserve_h_payto,
|
||||||
|
now_minus_one_month,
|
||||||
|
&aml_amount_cb,
|
||||||
|
&merge_amount);
|
||||||
|
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,
|
||||||
|
"select_merge_amounts_for_kyc_check");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
qs = TEH_plugin->select_aml_threshold (TEH_plugin->cls,
|
||||||
|
&reserve_h_payto,
|
||||||
|
&wc->aml_decision,
|
||||||
|
&threshold);
|
||||||
|
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,
|
||||||
|
"select_aml_threshold");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||||
|
{
|
||||||
|
threshold = TEH_aml_threshold; /* use default */
|
||||||
|
wc->aml_decision = TALER_AML_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (wc->aml_decision)
|
||||||
|
{
|
||||||
|
case TALER_AML_NORMAL:
|
||||||
|
if (0 >= TALER_amount_cmp (&merge_amount,
|
||||||
|
&threshold))
|
||||||
|
{
|
||||||
|
/* merge_amount <= threshold, continue withdraw below */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wc->aml_decision = TALER_AML_PENDING;
|
||||||
|
qs = TEH_plugin->trigger_aml_process (TEH_plugin->cls,
|
||||||
|
&reserve_h_payto,
|
||||||
|
&merge_amount);
|
||||||
|
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_STORE_FAILED,
|
||||||
|
"trigger_aml_process");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
return qs;
|
||||||
|
case TALER_AML_PENDING:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"AML already pending, doing nothing\n");
|
||||||
|
return qs;
|
||||||
|
case TALER_AML_FROZEN:
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Account frozen, doing nothing\n");
|
||||||
|
return qs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the money came from a wire transfer */
|
||||||
qs = TEH_plugin->reserves_get_origin (TEH_plugin->cls,
|
qs = TEH_plugin->reserves_get_origin (TEH_plugin->cls,
|
||||||
&wc->collectable.reserve_pub,
|
&wc->collectable.reserve_pub,
|
||||||
&wc->h_payto);
|
&wc->h_account_payto);
|
||||||
if (qs < 0)
|
if (qs < 0)
|
||||||
return qs;
|
return qs;
|
||||||
/* If no results, reserve was created by merge,
|
/* If no results, reserve was created by merge, in which case no KYC check
|
||||||
in which case no KYC check is required as the
|
is required as the merge already did that. */
|
||||||
merge already did that. */
|
|
||||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
|
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
|
||||||
{
|
{
|
||||||
const char *kyc_required;
|
const char *kyc_required;
|
||||||
|
|
||||||
qs = TALER_KYCLOGIC_kyc_test_required (
|
qs = TALER_KYCLOGIC_kyc_test_required (
|
||||||
TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW,
|
TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW,
|
||||||
&wc->h_payto,
|
&wc->h_account_payto,
|
||||||
TEH_plugin->select_satisfied_kyc_processes,
|
TEH_plugin->select_satisfied_kyc_processes,
|
||||||
TEH_plugin->cls,
|
TEH_plugin->cls,
|
||||||
&withdraw_amount_cb,
|
&withdraw_amount_cb,
|
||||||
@ -191,7 +317,7 @@ withdraw_transaction (void *cls,
|
|||||||
return TEH_plugin->insert_kyc_requirement_for_account (
|
return TEH_plugin->insert_kyc_requirement_for_account (
|
||||||
TEH_plugin->cls,
|
TEH_plugin->cls,
|
||||||
kyc_required,
|
kyc_required,
|
||||||
&wc->h_payto,
|
&wc->h_account_payto,
|
||||||
&wc->kyc.requirement_row);
|
&wc->kyc.requirement_row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -515,8 +641,13 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
|
|||||||
|
|
||||||
if (! wc.kyc.ok)
|
if (! wc.kyc.ok)
|
||||||
return TEH_RESPONSE_reply_kyc_required (rc->connection,
|
return TEH_RESPONSE_reply_kyc_required (rc->connection,
|
||||||
&wc.h_payto,
|
&wc.h_account_payto,
|
||||||
&wc.kyc);
|
&wc.kyc);
|
||||||
|
|
||||||
|
if (TALER_AML_NORMAL != wc.aml_decision)
|
||||||
|
return TEH_RESPONSE_reply_aml_blocked (rc->connection,
|
||||||
|
wc.aml_decision);
|
||||||
|
|
||||||
{
|
{
|
||||||
MHD_RESULT ret;
|
MHD_RESULT ret;
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/
|
|||||||
# Currency supported by the exchange (can only be one)
|
# Currency supported by the exchange (can only be one)
|
||||||
CURRENCY = EUR
|
CURRENCY = EUR
|
||||||
CURRENCY_ROUND_UNIT = EUR:0.01
|
CURRENCY_ROUND_UNIT = EUR:0.01
|
||||||
|
AML_THRESHOLD = EUR:1000000
|
||||||
|
|
||||||
[auditor]
|
[auditor]
|
||||||
TINY_AMOUNT = EUR:0.01
|
TINY_AMOUNT = EUR:0.01
|
||||||
|
@ -54,25 +54,6 @@ compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
notify_on_reserve (struct PostgresClosure *pg,
|
|
||||||
const struct TALER_ReservePublicKeyP *reserve_pub)
|
|
||||||
{
|
|
||||||
struct TALER_ReserveEventP rep = {
|
|
||||||
.header.size = htons (sizeof (rep)),
|
|
||||||
.header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
|
|
||||||
.reserve_pub = *reserve_pub
|
|
||||||
};
|
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Notifying on reserve!\n");
|
|
||||||
TEH_PG_event_notify (pg,
|
|
||||||
&rep.header,
|
|
||||||
NULL,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
static enum GNUNET_DB_QueryStatus
|
||||||
insert1 (struct PostgresClosure *pg,
|
insert1 (struct PostgresClosure *pg,
|
||||||
const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1],
|
const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1],
|
||||||
|
@ -41,7 +41,7 @@ TEH_PG_select_aml_threshold (
|
|||||||
uint32_t status32 = TALER_AML_NORMAL;
|
uint32_t status32 = TALER_AML_NORMAL;
|
||||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||||
TALER_PQ_RESULT_SPEC_AMOUNT ("threshold",
|
TALER_PQ_RESULT_SPEC_AMOUNT ("threshold",
|
||||||
&threshold),
|
threshold),
|
||||||
GNUNET_PQ_result_spec_uint32 ("status",
|
GNUNET_PQ_result_spec_uint32 ("status",
|
||||||
&status32),
|
&status32),
|
||||||
GNUNET_PQ_result_spec_end
|
GNUNET_PQ_result_spec_end
|
||||||
|
Loading…
Reference in New Issue
Block a user