work on AML notification logic

This commit is contained in:
Christian Grothoff 2023-02-13 16:00:37 +01:00
parent 3760d43097
commit dc40f6c679
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
8 changed files with 74 additions and 14 deletions

View File

@ -90,6 +90,11 @@ struct DepositWtidContext
*/
struct TALER_EXCHANGEDB_KycStatus kyc;
/**
* AML status information for the receiving account.
*/
enum TALER_AmlDecisionState aml_decision;
/**
* Set to #GNUNET_YES by #handle_wtid if the wire transfer is still pending
* (and the above were not set).
@ -128,6 +133,7 @@ reply_deposit_details (
&pub,
&sig)))
{
GNUNET_break (0);
return TALER_MHD_reply_with_ec (connection,
ec,
NULL);
@ -184,7 +190,8 @@ deposits_get_transaction (void *cls,
&ctx->execution_time,
&ctx->coin_contribution,
&fee,
&ctx->kyc);
&ctx->kyc,
&ctx->aml_decision);
if (0 > qs)
{
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
@ -257,6 +264,8 @@ handle_track_transaction_request (
NULL)
: GNUNET_JSON_pack_uint64 ("requirement_row",
ctx->kyc.requirement_row)),
GNUNET_JSON_pack_uint64 ("aml_decision",
(uint32_t) ctx->aml_decision),
GNUNET_JSON_pack_bool ("kyc_ok",
ctx->kyc.ok),
GNUNET_JSON_pack_timestamp ("execution_time",

View File

@ -23,6 +23,7 @@ CREATE OR REPLACE FUNCTION exchange_do_insert_aml_decision(
IN in_justification VARCHAR,
IN in_decider_pub BYTEA,
IN in_decider_sig BYTEA,
IN in_notify_s VARCHAR,
OUT out_invalid_officer BOOLEAN,
OUT out_last_date INT8)
LANGUAGE plpgsql
@ -95,8 +96,25 @@ INSERT INTO exchange.aml_history
,in_decider_pub
,in_decider_sig);
-- wake up taler-exchange-aggregator
IF 0 = in_new_status
THEN
INSERT INTO kyc_alerts
(h_payto
,trigger_type)
VALUES
(in_h_payto,1);
EXECUTE FORMAT (
'NOTIFY %s'
,in_notify_s);
END IF;
END $$;
COMMENT ON FUNCTION exchange_do_insert_aml_decision(BYTEA, INT8, INT4, INT4, INT8, VARCHAR, BYTEA, BYTEA)
COMMENT ON FUNCTION exchange_do_insert_aml_decision(BYTEA, INT8, INT4, INT4, INT8, VARCHAR, BYTEA, BYTEA, VARCHAR)
IS 'Checks whether the AML officer is eligible to make AML decisions and if so inserts the decision into the table';

View File

@ -24,6 +24,7 @@
#include "taler_pq_lib.h"
#include "pg_insert_aml_decision.h"
#include "pg_helper.h"
#include <gnunet/gnunet_pq_lib.h>
enum GNUNET_DB_QueryStatus
@ -41,6 +42,12 @@ TEH_PG_insert_aml_decision (
{
struct PostgresClosure *pg = cls;
uint32_t ns = (uint32_t) new_status;
struct TALER_KycCompletedEventP rep = {
.header.size = htons (sizeof (rep)),
.header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
.h_payto = *h_payto
};
char *notify_s = GNUNET_PG_get_event_notify_channel (&rep.header);
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (h_payto),
TALER_PQ_query_param_amount (new_threshold),
@ -49,6 +56,7 @@ TEH_PG_insert_aml_decision (
GNUNET_PQ_query_param_string (justification),
GNUNET_PQ_query_param_auto_from_type (decider_pub),
GNUNET_PQ_query_param_auto_from_type (decider_sig),
GNUNET_PQ_query_param_string (notify_s),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
@ -58,6 +66,7 @@ TEH_PG_insert_aml_decision (
last_date),
GNUNET_PQ_result_spec_end
};
enum GNUNET_DB_QueryStatus qs;
PREPARE (pg,
"do_insert_aml_decision",
@ -66,8 +75,10 @@ TEH_PG_insert_aml_decision (
",out_last_date"
" FROM exchange_do_insert_aml_decision"
"($1, $2, $3, $4, $5, $6, $7, $8);");
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"do_insert_aml_decision",
params,
rs);
GNUNET_free (notify_s);
return qs;
}

View File

@ -26,7 +26,6 @@
#include "pg_helper.h"
enum GNUNET_DB_QueryStatus
TEH_PG_lookup_transfer_by_deposit (
void *cls,
@ -39,7 +38,8 @@ TEH_PG_lookup_transfer_by_deposit (
struct GNUNET_TIME_Timestamp *exec_time,
struct TALER_Amount *amount_with_fee,
struct TALER_Amount *deposit_fee,
struct TALER_EXCHANGEDB_KycStatus *kyc)
struct TALER_EXCHANGEDB_KycStatus *kyc,
enum TALER_AmlDecisionState *aml_decision)
{
struct PostgresClosure *pg = cls;
enum GNUNET_DB_QueryStatus qs;
@ -71,8 +71,6 @@ TEH_PG_lookup_transfer_by_deposit (
0,
sizeof (*kyc));
/* check if the aggregation record exists and get it */
/* Used in #postgres_lookup_transfer_by_deposit */
PREPARE (pg,
"lookup_deposit_wtid",
"SELECT"
@ -117,6 +115,7 @@ TEH_PG_lookup_transfer_by_deposit (
{
*pending = false;
kyc->ok = true;
*aml_decision = TALER_AML_NORMAL;
return qs;
}
qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
@ -134,6 +133,7 @@ TEH_PG_lookup_transfer_by_deposit (
/* Check if transaction exists in deposits, so that we just
do not have a WTID yet. In that case, return without wtid
(by setting 'pending' true). */
uint32_t status32 = TALER_AML_NORMAL;
struct GNUNET_PQ_ResultSpec rs2[] = {
GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
&wire_salt),
@ -149,11 +149,13 @@ TEH_PG_lookup_transfer_by_deposit (
deposit_fee),
GNUNET_PQ_result_spec_timestamp ("wire_deadline",
exec_time),
GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_uint32 ("status",
&status32),
NULL),
GNUNET_PQ_result_spec_end
};
/* Fetch an existing deposit request.
Used in #postgres_lookup_transfer_by_deposit(). */
PREPARE (pg,
"get_deposit_without_wtid",
"SELECT"
@ -165,6 +167,7 @@ TEH_PG_lookup_transfer_by_deposit (
",denom.fee_deposit_val"
",denom.fee_deposit_frac"
",dep.wire_deadline"
",aml.status"
" FROM deposits dep"
" JOIN wire_targets wt"
" USING (wire_target_h_payto)"
@ -175,6 +178,8 @@ TEH_PG_lookup_transfer_by_deposit (
" LEFT JOIN aggregation_transient agt "
" ON ( (dep.wire_target_h_payto = agt.wire_target_h_payto) AND"
" (dep.merchant_pub = agt.merchant_pub) )"
" LEFT JOIN aml_status aml"
" ON (wt.wire_target_h_payto = aml.h_payto)"
" WHERE dep.coin_pub=$1"
" AND dep.merchant_pub=$3"
" AND dep.h_contract_terms=$2"
@ -187,6 +192,7 @@ TEH_PG_lookup_transfer_by_deposit (
{
struct TALER_MerchantWireHashP wh;
*aml_decision = (enum TALER_AmlDecisionState) status32;
if (0 == kyc->requirement_row)
kyc->ok = true; /* technically: unknown */
TALER_merchant_wire_signature_hash (payto_uri,
@ -198,6 +204,7 @@ TEH_PG_lookup_transfer_by_deposit (
h_wire))
return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}
*aml_decision = TALER_AML_NORMAL;
return qs;
}
}

View File

@ -42,6 +42,7 @@
* @param[out] amount_with_fee set to the total deposited amount
* @param[out] deposit_fee set to how much the exchange did charge for the deposit
* @param[out] kyc set to the kyc status of the receiver (if @a pending)
* @param[out[ aml_decision set to the AML status of the receiver
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
@ -56,6 +57,7 @@ TEH_PG_lookup_transfer_by_deposit (
struct GNUNET_TIME_Timestamp *exec_time,
struct TALER_Amount *amount_with_fee,
struct TALER_Amount *deposit_fee,
struct TALER_EXCHANGEDB_KycStatus *kyc);
struct TALER_EXCHANGEDB_KycStatus *kyc,
enum TALER_AmlDecisionState *aml_decision);
#endif

View File

@ -3182,6 +3182,12 @@ struct TALER_EXCHANGE_GetDepositResponse
*/
uint64_t requirement_row;
/**
* Current AML state for the account. May explain why transfers are
* not happening.
*/
enum TALER_AmlDecisionState aml_decision;
/**
* Set to 'true' if the KYC check is already finished and
* the exchange is merely waiting for the @e execution_time.

View File

@ -4319,6 +4319,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param[out] execution_time when was the transaction done, or
* when we expect it to be done (if @a pending is false)
* @param[out] kyc set to the kyc status of the receiver (if @a pending)
* @param[out] aml_decision set to the current AML status for the target account
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
@ -4333,7 +4334,8 @@ struct TALER_EXCHANGEDB_Plugin
struct GNUNET_TIME_Timestamp *exec_time,
struct TALER_Amount *amount_with_fee,
struct TALER_Amount *deposit_fee,
struct TALER_EXCHANGEDB_KycStatus *kyc);
struct TALER_EXCHANGEDB_KycStatus *kyc,
enum TALER_AmlDecisionState *aml_decision);
/**

View File

@ -177,6 +177,7 @@ handle_deposit_wtid_finished (void *cls,
{
/* Transaction known, but not executed yet */
bool no_legi = false;
uint32_t state32;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_timestamp ("execution_time",
&dr.details.accepted.execution_time),
@ -184,6 +185,8 @@ handle_deposit_wtid_finished (void *cls,
GNUNET_JSON_spec_uint64 ("requirement_row",
&dr.details.accepted.requirement_row),
&no_legi),
GNUNET_JSON_spec_uint32 ("aml_decision",
&state32),
GNUNET_JSON_spec_bool ("kyc_ok",
&dr.details.accepted.kyc_ok),
GNUNET_JSON_spec_end ()
@ -199,6 +202,8 @@ handle_deposit_wtid_finished (void *cls,
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
dr.details.accepted.aml_decision
= (enum TALER_AmlDecisionState) state32;
if (no_legi)
dr.details.accepted.requirement_row = 0;
dwh->cb (dwh->cb_cls,