commit bde075f640cda8c5df6fcb60df15be0cb4f9121d
parent 41b10090a3443f77f6f6a76c6a04132229d398c8
Author: Christian Grothoff <christian@grothoff.org>
Date: Sat, 12 Apr 2025 16:05:45 +0200
enable long-polling kyc-status by decision row ID
Diffstat:
10 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c
@@ -630,14 +630,14 @@ handle_withdrawals (
&auditor_fee,
&issue->fees.withdraw);
{
- struct TALER_Amount amount_with_fee;
+ struct TALER_Amount issue_amount_with_fee;
- TALER_ARL_amount_add (&amount_with_fee,
+ TALER_ARL_amount_add (&issue_amount_with_fee,
&issue->value,
&issue->fees.withdraw);
TALER_ARL_amount_add (&auditor_amount_with_fee,
&auditor_amount_with_fee,
- &amount_with_fee);
+ &issue_amount_with_fee);
}
}
diff --git a/src/exchange-tools/taler-exchange-kyc-trigger.c b/src/exchange-tools/taler-exchange-kyc-trigger.c
@@ -188,6 +188,7 @@ kyc_wallet_cb (
CFG_exchange_url,
&h_payto,
&pk,
+ 0,
TALER_EXCHANGE_KLPT_NONE,
GNUNET_TIME_UNIT_ZERO,
&kyc_status_cb,
diff --git a/src/exchange/taler-exchange-httpd_kyc-check.c b/src/exchange/taler-exchange-httpd_kyc-check.c
@@ -77,6 +77,12 @@ struct KycPoller
union TALER_AccountSignatureP account_sig;
/**
+ * Generation of KYC rules already known to the client
+ * (when long-polling). Do not send these rules again.
+ */
+ uint64_t min_rule;
+
+ /**
* What are we long-polling for (if anything)?
*/
enum TALER_EXCHANGE_KycLongPollTarget lpt;
@@ -197,6 +203,7 @@ TEH_handler_kyc_check (
bool aml_review;
bool kyc_required;
bool access_ok = false;
+ uint64_t rule_gen = 0;
if (NULL == kyp)
{
@@ -255,6 +262,9 @@ TEH_handler_kyc_check (
kyp->timeout),
true));
}
+ TALER_MHD_parse_request_number (rc->connection,
+ "min_rule",
+ &kyp->min_rule);
/* long polling needed? */
if (GNUNET_TIME_absolute_is_future (kyp->timeout))
{
@@ -300,6 +310,7 @@ TEH_handler_kyc_check (
&account_pub,
&reserve_pub.reserve_pub,
&access_token,
+ &rule_gen,
&jrules,
&aml_review,
&kyc_required);
@@ -336,7 +347,8 @@ TEH_handler_kyc_check (
(GNUNET_OK ==
TALER_account_kyc_auth_verify (&reserve_pub,
&kyp->account_sig)) ) );
- if (GNUNET_TIME_absolute_is_future (kyp->timeout))
+ if (GNUNET_TIME_absolute_is_future (kyp->timeout) &&
+ (rule_gen <= kyp->min_rule) )
{
switch (kyp->lpt)
{
@@ -437,6 +449,8 @@ TEH_handler_kyc_check (
: MHD_HTTP_OK,
GNUNET_JSON_pack_bool ("aml_review",
aml_review),
+ GNUNET_JSON_pack_uint64 ("rule_gen",
+ rule_gen),
GNUNET_JSON_pack_data_auto ("access_token",
&access_token),
GNUNET_JSON_pack_allow_null (
diff --git a/src/exchangedb/exchange_do_lookup_kyc_requirement_by_row.sql b/src/exchangedb/exchange_do_lookup_kyc_requirement_by_row.sql
@@ -24,6 +24,7 @@ CREATE FUNCTION exchange_do_lookup_kyc_requirement_by_row(
OUT out_access_token BYTEA, -- NULL if 'out_not_found'
OUT out_jrules TEXT, -- NULL allowed
OUT out_not_found BOOLEAN,
+ OUT out_rule_gen INT8, -- NULL allowed
OUT out_aml_review BOOLEAN, -- NULL allowed
OUT out_kyc_required BOOLEAN)
LANGUAGE plpgsql
@@ -64,6 +65,7 @@ out_kyc_required = FOUND;
-- Only one should ever be active per account.
SELECT jnew_rules
,to_investigate
+ ,outcome_serial_id
INTO my_lorec
FROM legitimization_outcomes
WHERE h_payto=in_h_normalized_payto
@@ -73,6 +75,7 @@ IF FOUND
THEN
out_jrules=my_lorec.jnew_rules;
out_aml_review=my_lorec.to_investigate;
+ out_rule_gen=my_lorec.outcome_serial_id;
END IF;
-- Check most recent reserve_in wire transfer, we also
diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c
@@ -33,6 +33,7 @@ TEH_PG_lookup_kyc_requirement_by_row (
union TALER_AccountPublicKeyP *account_pub,
struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_AccountAccessTokenP *access_token,
+ uint64_t *rule_gen,
json_t **jrules,
bool *aml_review,
bool *kyc_required)
@@ -66,6 +67,10 @@ TEH_PG_lookup_kyc_requirement_by_row (
GNUNET_PQ_result_spec_bool ("aml_review",
aml_review),
NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("rule_gen",
+ rule_gen),
+ NULL),
GNUNET_PQ_result_spec_bool ("kyc_required",
kyc_required),
GNUNET_PQ_result_spec_bool ("not_found",
@@ -76,6 +81,7 @@ TEH_PG_lookup_kyc_requirement_by_row (
*jrules = NULL;
*aml_review = false;
+ *rule_gen = 0;
memset (account_pub,
0,
sizeof (*account_pub));
@@ -95,6 +101,7 @@ TEH_PG_lookup_kyc_requirement_by_row (
",out_not_found AS not_found"
",out_aml_review AS aml_review"
",out_kyc_required AS kyc_required"
+ ",out_rule_gen AS rule_gen"
" FROM exchange_do_lookup_kyc_requirement_by_row"
" ($1);");
qs = GNUNET_PQ_eval_prepared_singleton_select (
diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.h b/src/exchangedb/pg_lookup_kyc_requirement_by_row.h
@@ -39,6 +39,8 @@
* all zeros if not known
* @param[out] access_token set to the access token to begin
* work on KYC processes for this account
+ * @param[out] rule_gen row ID of the last decision this
+ * response is based on (for long-polling by clients)
* @param[out] jrules set to active ``LegitimizationRuleSet``
* of the account impacted by the requirement
* @param[out] aml_review set to true if the account is under
@@ -54,6 +56,7 @@ TEH_PG_lookup_kyc_requirement_by_row (
union TALER_AccountPublicKeyP *account_pub,
struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_AccountAccessTokenP *access_token,
+ uint64_t *rule_gen,
json_t **jrules,
bool *aml_review,
bool *kyc_required);
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
@@ -4313,6 +4313,12 @@ struct TALER_EXCHANGE_AccountKycStatus
unsigned int limits_length;
/**
+ * Generation of this rule, matches a monotonically increasing
+ * table row in the exchange with KYC rules for this account.
+ */
+ uint64_t rule_gen;
+
+ /**
* Array of length @e limits_array with (exposed) limits that apply to the
* account.
*/
@@ -4389,6 +4395,7 @@ typedef void
* @param url exchange base URL
* @param h_payto hash of the account the KYC check is about
* @param pk private key to authorize the request with
+ * @param known_rule_gen latest known AML decision, for long polling
* @param lpt target for long polling
* @param timeout how long to wait for an answer, including possibly long polling for the desired @a lpt status
* @param cb function to call with the result
@@ -4401,6 +4408,7 @@ TALER_EXCHANGE_kyc_check (
const char *url,
const struct TALER_NormalizedPaytoHashP *h_payto,
const union TALER_AccountPrivateKeyP *pk,
+ uint64_t known_rule_gen,
enum TALER_EXCHANGE_KycLongPollTarget lpt,
struct GNUNET_TIME_Relative timeout,
TALER_EXCHANGE_KycStatusCallback cb,
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
@@ -7356,6 +7356,8 @@ struct TALER_EXCHANGEDB_Plugin
* all zeros if not known
* @param[out] access_token set to the access token to begin
* work on KYC processes for this account
+ * @param[out] rule_gen row ID of the last decision this
+ * response is based on (for long-polling by clients)
* @param[out] jrules set to active ``LegitimizationRuleSet``
* of the account impacted by the requirement
* @param[out] aml_review set to true if the account is under
@@ -7371,6 +7373,7 @@ struct TALER_EXCHANGEDB_Plugin
union TALER_AccountPublicKeyP *account_pub,
struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_AccountAccessTokenP *access_token,
+ uint64_t *rule_gen,
json_t **jrules,
bool *aml_review,
bool *kyc_required);
diff --git a/src/lib/exchange_api_kyc_check.c b/src/lib/exchange_api_kyc_check.c
@@ -70,6 +70,8 @@ parse_account_status (
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_bool ("aml_review",
&status->aml_review),
+ GNUNET_JSON_spec_uint64 ("rule_gen",
+ &status->rule_gen),
GNUNET_JSON_spec_fixed_auto ("access_token",
&status->access_token),
GNUNET_JSON_spec_mark_optional (
@@ -258,6 +260,7 @@ TALER_EXCHANGE_kyc_check (
const char *url,
const struct TALER_NormalizedPaytoHashP *h_payto,
const union TALER_AccountPrivateKeyP *account_priv,
+ uint64_t known_rule_gen,
enum TALER_EXCHANGE_KycLongPollTarget lpt,
struct GNUNET_TIME_Relative timeout,
TALER_EXCHANGE_KycStatusCallback cb,
@@ -268,6 +271,7 @@ TALER_EXCHANGE_kyc_check (
char arg_str[128];
char timeout_ms[32];
char lpt_str[32];
+ char krg_str[32];
struct curl_slist *job_headers = NULL;
unsigned long long tms;
@@ -289,6 +293,10 @@ TALER_EXCHANGE_kyc_check (
sizeof (timeout_ms),
"%llu",
tms);
+ GNUNET_snprintf (krg_str,
+ sizeof (krg_str),
+ "%llu",
+ (unsigned long long) known_rule_gen);
GNUNET_snprintf (lpt_str,
sizeof (lpt_str),
"%d",
@@ -304,6 +312,10 @@ TALER_EXCHANGE_kyc_check (
GNUNET_TIME_relative_is_zero (timeout)
? NULL
: timeout_ms,
+ "min_rule",
+ 0 == known_rule_gen
+ ? NULL
+ : krg_str,
"lpt",
TALER_EXCHANGE_KLPT_NONE == lpt
? NULL
diff --git a/src/testing/testing_api_cmd_kyc_check_get.c b/src/testing/testing_api_cmd_kyc_check_get.c
@@ -178,6 +178,7 @@ check_kyc_run (void *cls,
h_payto,
account_priv,
kcg->lpt,
+ 0,
TALER_EXCHANGE_KLPT_NONE == kcg->lpt
? GNUNET_TIME_UNIT_ZERO
: GNUNET_TIME_UNIT_MINUTES,