commit 08387dd6adfd7abb4db184c2f7d663fcaab78eb2
parent 4d22b01dd79434c94301e71697a1d5c9ab5a8d6d
Author: Christian Grothoff <christian@grothoff.org>
Date: Thu, 26 Feb 2026 23:24:02 +0100
work a bit on API modernization
Diffstat:
35 files changed, 2472 insertions(+), 2193 deletions(-)
diff --git a/src/exchange-tools/taler-exchange-kyc-trigger.c b/src/exchange-tools/taler-exchange-kyc-trigger.c
@@ -23,6 +23,7 @@
#include <gnunet/gnunet_util_lib.h>
#include <microhttpd.h>
#include "taler/taler_json_lib.h"
+#include "taler/taler-exchange/get-kyc-check-H_NORMALIZED_PAYTO.h"
#include "taler/taler_exchange_service.h"
@@ -54,12 +55,12 @@ static const struct GNUNET_CONFIGURATION_Handle *kcfg;
/**
* Handle for exchange interaction.
*/
-static struct TALER_EXCHANGE_KycWalletHandle *kwh;
+static struct TALER_EXCHANGE_PostKycWalletHandle *kwh;
/**
* Handle for exchange kyc-check interaction.
*/
-static struct TALER_EXCHANGE_KycCheckHandle *kc;
+static struct TALER_EXCHANGE_GetKycCheckHandle *kc;
/**
* Balance threshold to report to the exchange.
@@ -92,7 +93,7 @@ static char *CFG_exchange_url;
static void
kyc_status_cb (
void *cls,
- const struct TALER_EXCHANGE_KycStatus *ks)
+ const struct TALER_EXCHANGE_GetKycCheckResponse *ks)
{
kc = NULL;
switch (ks->hr.http_status)
@@ -144,7 +145,7 @@ kyc_status_cb (
static void
kyc_wallet_cb (
void *cls,
- const struct TALER_EXCHANGE_WalletKycResponse *ks)
+ const struct TALER_EXCHANGE_PostKycWalletResponse *ks)
{
kwh = NULL;
switch (ks->hr.http_status)
@@ -184,18 +185,19 @@ kyc_wallet_cb (
pk.reserve_priv = reserve_priv;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Requesting /kyc-check to determine KYC entrypoint\n");
- kc = TALER_EXCHANGE_kyc_check (ctx,
- CFG_exchange_url,
- &h_payto,
- &pk,
- 0,
- TALER_EXCHANGE_KLPT_NONE,
- GNUNET_TIME_UNIT_ZERO,
- &kyc_status_cb,
- NULL);
+ kc = TALER_EXCHANGE_get_kyc_check_create (ctx,
+ CFG_exchange_url,
+ &h_payto,
+ &pk);
GNUNET_break (NULL != kc);
- if (NULL != kc)
- return;
+ if (NULL == kc)
+ break;
+ GNUNET_assert (TALER_EC_NONE ==
+ TALER_EXCHANGE_get_kyc_check_start (
+ kc,
+ &kyc_status_cb,
+ NULL));
+ return;
}
}
break;
@@ -220,12 +222,12 @@ do_shutdown (void *cls)
(void) cls;
if (NULL != kwh)
{
- TALER_EXCHANGE_kyc_wallet_cancel (kwh);
+ TALER_EXCHANGE_post_kyc_wallet_cancel (kwh);
kwh = NULL;
}
if (NULL != kc)
{
- TALER_EXCHANGE_kyc_check_cancel (kc);
+ TALER_EXCHANGE_get_kyc_check_cancel (kc);
kc = NULL;
}
if (NULL != ctx)
@@ -355,17 +357,19 @@ run (void *cls,
rc = GNUNET_CURL_gnunet_rc_create (ctx);
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
- kwh = TALER_EXCHANGE_kyc_wallet (ctx,
- CFG_exchange_url,
- &reserve_priv,
- &balance,
- &kyc_wallet_cb,
- NULL);
+ kwh = TALER_EXCHANGE_post_kyc_wallet_create (ctx,
+ CFG_exchange_url,
+ &reserve_priv,
+ &balance);
if (NULL == kwh)
{
GNUNET_break (0);
GNUNET_SCHEDULER_shutdown ();
}
+ GNUNET_assert (TALER_EC_NONE ==
+ TALER_EXCHANGE_post_kyc_wallet_start (kwh,
+ &kyc_wallet_cb,
+ NULL));
}
diff --git a/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-decisions.h b/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-decisions.h
@@ -201,9 +201,9 @@ struct TALER_EXCHANGE_GetAmlDecisionsLegitimizationRuleSet
size_t rules_length;
/**
- * Array of KYC rules.
+ * Array of KYC rules. NOT allocated here!
*/
- struct TALER_EXCHANGE_GetAmlDecisionsKycRule *rules;
+ const struct TALER_EXCHANGE_GetAmlDecisionsKycRule *rules;
/**
* Custom measures.
@@ -422,8 +422,7 @@ enum GNUNET_GenericReturnValue
TALER_EXCHANGE_get_aml_decisions_set_options_ (
struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh,
unsigned int num_options,
- struct TALER_EXCHANGE_GetAmlDecisionsOptionValue options[
- static num_options]);
+ const struct TALER_EXCHANGE_GetAmlDecisionsOptionValue options[]);
/**
@@ -503,260 +502,4 @@ TALER_EXCHANGE_get_aml_decisions_cancel (
struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh);
-/* **************** deprecated legacy API ***************** */
-
-
-/**
- * KYC rule that determines limits for an account.
- */
-struct TALER_EXCHANGE_KycRule
-{
- /**
- * Type of operation to which the rule applies.
- */
- enum TALER_KYCLOGIC_KycTriggerEvent operation_type;
-
- /**
- * The measures will be taken if the given
- * threshold is crossed over the given timeframe.
- */
- struct TALER_Amount threshold;
-
- /**
- * Over which duration should the @e threshold be
- * computed. All amounts of the respective
- * @e operation_type will be added up for this
- * duration and the sum compared to the @e threshold.
- */
- struct GNUNET_TIME_Relative timeframe;
-
- /**
- * Array of names of measures to apply.
- * Names listed can be original measures or
- * custom measures from the `AmlOutcome`.
- */
- const char **measures;
-
- /**
- * Length of the measures array.
- */
- unsigned int measures_length;
-
- /**
- * True if crossing these limits is simply categorically
- * forbidden (no measure will be triggered, the request
- * will just be always denied).
- */
- bool verboten;
-
- /**
- * True if the rule (specifically, @e operation_type,
- * @e threshold and @e timeframe) and the general nature of
- * the measures (@e verboten)
- * should be exposed to the client.
- */
- bool exposed;
-
- /**
- * True if all the measures will eventually need to
- * be satisfied, false if any of the measures should
- * do. Primarily used by the SPA to indicate how
- * the measures apply when showing them to the user;
- * in the end, AML programs will decide after each
- * measure what to do next.
- */
- bool is_and_combinator;
-
- /**
- * If multiple rules apply to the same account
- * at the same time, the number with the highest
- * rule determines which set of measures will
- * be activated and thus become visible for the
- * user.
- */
- uint32_t display_priority;
-};
-
-
-/**
- * Set of legitimization rules with expiration data.
- */
-struct TALER_EXCHANGE_LegitimizationRuleSet
-{
-
- /**
- * What successor measure applies to the account?
- */
- const char *successor_measure;
-
- /**
- * What are the current rules for the account?
- */
- const struct TALER_EXCHANGE_KycRule *rules;
-
- /**
- * What are custom measures that @e rules may refer to?
- */
- const struct TALER_EXCHANGE_MeasureInformation *measures;
-
- /**
- * When will this decision expire?
- */
- struct GNUNET_TIME_Timestamp expiration_time;
-
- /**
- * Length of the @e rules array.
- */
- unsigned int rules_length;
-
- /**
- * Length of the @e measures array.
- */
- unsigned int measures_length;
-};
-
-
-/**
- * Data about an AML decision.
- */
-struct TALER_EXCHANGE_AmlDecision
-{
- /**
- * Account the decision was made for.
- */
- struct TALER_NormalizedPaytoHashP h_payto;
-
- /**
- * RowID of this decision.
- */
- uint64_t rowid;
-
- /**
- * When was the decision made?
- */
- struct GNUNET_TIME_Timestamp decision_time;
-
- /**
- * What are the new rules?
- */
- struct TALER_EXCHANGE_LegitimizationRuleSet limits;
-
- /**
- * Justification given for the decision.
- */
- const char *justification;
-
- /**
- * Properties set for the account.
- */
- const json_t *jproperties;
-
- /**
- * Should AML staff investigate this account?
- */
- bool to_investigate;
-
- /**
- * Is this the currently active decision?
- */
- bool is_active;
-
-};
-
-
-/**
- * Information about AML decisions returned by the exchange.
- */
-struct TALER_EXCHANGE_AmlDecisionsResponse
-{
- /**
- * HTTP response details.
- */
- struct TALER_EXCHANGE_HttpResponse hr;
-
- /**
- * Details depending on the HTTP response code.
- */
- union
- {
-
- /**
- * Information returned on success (#MHD_HTTP_OK).
- */
- struct
- {
-
- /**
- * Array of AML decision summaries returned by the exchange.
- */
- const struct TALER_EXCHANGE_AmlDecision *decisions;
-
- /**
- * Length of the @e decisions array.
- */
- unsigned int decisions_length;
-
- } ok;
-
- } details;
-};
-
-
-/**
- * Function called with information about AML decisions.
- *
- * @param cls closure
- * @param adr response data
- */
-typedef void
-(*TALER_EXCHANGE_LookupAmlDecisionsCallback) (
- void *cls,
- const struct TALER_EXCHANGE_AmlDecisionsResponse *adr);
-
-
-/**
- * @brief Handle for a POST /aml/$OFFICER_PUB/decisions request.
- */
-struct TALER_EXCHANGE_LookupAmlDecisions;
-
-
-/**
- * Inform AML SPA client about AML decisions that were been taken.
- *
- * @param ctx the context
- * @param exchange_url HTTP base URL for the exchange
- * @param h_payto which account should we return the AML decision history for, NULL to return all accounts
- * @param investigation_only filter by investigation state
- * @param active_only filter for only active states
- * @param offset row number starting point (exclusive rowid)
- * @param limit number of records to return, negative for descending, positive for ascending from start
- * @param officer_priv private key of the deciding AML officer
- * @param cb function to call with the exchange's result
- * @param cb_cls closure for @a cb
- * @return the request handle; NULL upon error
- */
-struct TALER_EXCHANGE_LookupAmlDecisions *
-TALER_EXCHANGE_lookup_aml_decisions (
- struct GNUNET_CURL_Context *ctx,
- const char *exchange_url,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- enum TALER_EXCHANGE_YesNoAll investigation_only,
- enum TALER_EXCHANGE_YesNoAll active_only,
- uint64_t offset,
- int64_t limit,
- const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
- TALER_EXCHANGE_LookupAmlDecisionsCallback cb,
- void *cb_cls);
-
-
-/**
- * Cancel #TALER_EXCHANGE_lookup_aml_decisions() operation.
- *
- * @param lh handle of the operation to cancel
- */
-void
-TALER_EXCHANGE_lookup_aml_decisions_cancel (
- struct TALER_EXCHANGE_LookupAmlDecisions *lh);
-
-
#endif /* _TALER_EXCHANGE__GET_AML_OFFICER_PUB_DECISIONS_H */
diff --git a/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-kyc-statistics-NAMES.h b/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-kyc-statistics-NAMES.h
@@ -296,59 +296,4 @@ TALER_EXCHANGE_get_aml_kyc_statistics_cancel (
struct TALER_EXCHANGE_GetAmlKycStatisticsHandle *aksh);
-/* **************** deprecated legacy API ***************** */
-
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetAmlKycStatisticsResponse instead.
- * Note: the legacy API accepted only a single name and returned only
- * a single counter; use the new API for multi-name queries.
- */
-struct TALER_EXCHANGE_KycGetStatisticsResponse
-{
- struct TALER_EXCHANGE_HttpResponse hr;
- union
- {
- struct
- {
- unsigned long long counter;
- } ok;
- } details;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetAmlKycStatisticsCallback instead.
- */
-typedef void
-(*TALER_EXCHANGE_KycStatisticsCallback) (
- void *cls,
- const struct TALER_EXCHANGE_KycGetStatisticsResponse *hr);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetAmlKycStatisticsHandle instead.
- */
-struct TALER_EXCHANGE_KycGetStatisticsHandle;
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_aml_kyc_statistics_create() and
- * the new API instead.
- */
-struct TALER_EXCHANGE_KycGetStatisticsHandle *
-TALER_EXCHANGE_kyc_get_statistics (
- struct GNUNET_CURL_Context *ctx,
- const char *exchange_url,
- const char *name,
- struct GNUNET_TIME_Timestamp start_date,
- struct GNUNET_TIME_Timestamp end_date,
- const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
- TALER_EXCHANGE_KycStatisticsCallback cb,
- void *cb_cls);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_aml_kyc_statistics_cancel() instead.
- */
-void
-TALER_EXCHANGE_kyc_get_statistics_cancel (
- struct TALER_EXCHANGE_KycGetStatisticsHandle *kgs);
-
#endif /* _TALER_EXCHANGE__GET_AML_OFFICER_PUB_KYC_STATISTICS_NAMES_H */
diff --git a/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-legitimizations.h b/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-legitimizations.h
@@ -211,7 +211,7 @@ enum GNUNET_GenericReturnValue
TALER_EXCHANGE_get_aml_legitimizations_set_options_ (
struct TALER_EXCHANGE_GetAmlLegitimizationsHandle *algh,
unsigned int num_options,
- const struct TALER_EXCHANGE_GetAmlLegitimizationsOptionValue *options);
+ const struct TALER_EXCHANGE_GetAmlLegitimizationsOptionValue options[]);
/**
@@ -340,27 +340,13 @@ typedef void
* @param[in,out] algh operation to start
* @param cb function to call with the exchange's result
* @param cb_cls closure for @a cb
- * @return status code, #TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_START_OK on success
+ * @return status code, #TALER_EC_NONE on success
*/
-enum TALER_EXCHANGE_AmlLegitimizationsGetStartError
-{
- /**
- * Success.
- */
- TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_START_OK = 0,
- /**
- * Only allowed to be started once.
- */
- TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_START_E_AGAIN = 1,
- /**
- * Internal logic failure.
- */
- TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_START_E_INTERNAL = 2,
-}
+enum TALER_ErrorCode
TALER_EXCHANGE_get_aml_legitimizations_start (
struct TALER_EXCHANGE_GetAmlLegitimizationsHandle *algh,
TALER_EXCHANGE_GetAmlLegitimizationsCallback cb,
- TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_RESULT_CLOSURE * cb_cls);
+ TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_RESULT_CLOSURE *cb_cls);
/**
diff --git a/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-measures.h b/src/include/taler/taler-exchange/get-aml-OFFICER_PUB-measures.h
@@ -346,98 +346,4 @@ TALER_EXCHANGE_get_aml_measures_cancel (
struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh);
-/* **************** deprecated legacy API ***************** */
-
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetAmlMeasuresMeasureInfo instead.
- */
-struct TALER_EXCHANGE_AvailableAmlMeasures
-{
- const char *measure_name;
- const char *check_name;
- const char *prog_name;
- const json_t *context;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetAmlMeasuresProgramRequirement instead.
- */
-struct TALER_EXCHANGE_AvailableAmlPrograms
-{
- const char *prog_name;
- const char *description;
- const char **contexts;
- const char **inputs;
- unsigned int contexts_length;
- unsigned int inputs_length;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetAmlMeasuresCheckInfo instead.
- */
-struct TALER_EXCHANGE_AvailableKycChecks
-{
- const char *check_name;
- const char *description;
- const json_t *description_i18n;
- const char *fallback;
- const char **requires;
- const char **outputs;
- unsigned int requires_length;
- unsigned int outputs_length;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetAmlMeasuresResponse instead.
- */
-struct TALER_EXCHANGE_AmlGetMeasuresResponse
-{
- struct TALER_EXCHANGE_HttpResponse hr;
- union
- {
- struct
- {
- const struct TALER_EXCHANGE_AvailableAmlMeasures *roots;
- const struct TALER_EXCHANGE_AvailableAmlPrograms *programs;
- const struct TALER_EXCHANGE_AvailableKycChecks *checks;
- unsigned int roots_length;
- unsigned int programs_length;
- unsigned int checks_length;
- } ok;
- } details;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetAmlMeasuresCallback instead.
- */
-typedef void
-(*TALER_EXCHANGE_AmlMeasuresCallback) (
- void *cls,
- const struct TALER_EXCHANGE_AmlGetMeasuresResponse *hr);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetAmlMeasuresHandle instead.
- */
-struct TALER_EXCHANGE_AmlGetMeasuresHandle;
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_aml_measures_create() and
- * the new API instead.
- */
-struct TALER_EXCHANGE_AmlGetMeasuresHandle *
-TALER_EXCHANGE_aml_get_measures (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
- TALER_EXCHANGE_AmlMeasuresCallback cb,
- void *cb_cls);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_aml_measures_cancel() instead.
- */
-void
-TALER_EXCHANGE_aml_get_measures_cancel (
- struct TALER_EXCHANGE_AmlGetMeasuresHandle *agml);
-
#endif /* _TALER_EXCHANGE__GET_AML_OFFICER_PUB_MEASURES_H */
diff --git a/src/include/taler/taler-exchange/get-kyc-check-H_NORMALIZED_PAYTO.h b/src/include/taler/taler-exchange/get-kyc-check-H_NORMALIZED_PAYTO.h
@@ -345,61 +345,4 @@ TALER_EXCHANGE_get_kyc_check_cancel (
struct TALER_EXCHANGE_GetKycCheckHandle *gkch);
-/* **************** deprecated legacy API ***************** */
-
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetKycCheckResponse instead.
- */
-struct TALER_EXCHANGE_KycStatus
-{
- struct TALER_EXCHANGE_HttpResponse hr;
- union
- {
- struct TALER_EXCHANGE_AccountKycStatus ok;
- struct TALER_EXCHANGE_AccountKycStatus accepted;
- struct
- {
- union TALER_AccountPublicKeyP expected_account_pub;
- } forbidden;
- } details;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetKycCheckCallback instead.
- */
-typedef void
-(*TALER_EXCHANGE_KycStatusCallback)(
- void *cls,
- const struct TALER_EXCHANGE_KycStatus *ks);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetKycCheckHandle instead.
- */
-struct TALER_EXCHANGE_KycCheckHandle;
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_kyc_check_create() and
- * the new API instead.
- */
-struct TALER_EXCHANGE_KycCheckHandle *
-TALER_EXCHANGE_kyc_check (
- struct GNUNET_CURL_Context *ctx,
- 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,
- void *cb_cls);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_kyc_check_cancel() instead.
- */
-void
-TALER_EXCHANGE_kyc_check_cancel (
- struct TALER_EXCHANGE_KycCheckHandle *kyc);
-
-
#endif /* _TALER_EXCHANGE__GET_KYC_CHECK_H_NORMALIZED_PAYTO_H */
diff --git a/src/include/taler/taler-exchange/get-kyc-info-ACCESS_TOKEN.h b/src/include/taler/taler-exchange/get-kyc-info-ACCESS_TOKEN.h
@@ -347,61 +347,4 @@ TALER_EXCHANGE_get_kyc_info_cancel (
struct TALER_EXCHANGE_GetKycInfoHandle *gkih);
-/* **************** deprecated legacy API ***************** */
-
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetKycInfoResponse instead.
- */
-struct TALER_EXCHANGE_KycProcessClientInformation
-{
- struct TALER_EXCHANGE_HttpResponse hr;
- union
- {
- struct
- {
- const struct TALER_EXCHANGE_RequirementInformation *requirements;
- const struct TALER_EXCHANGE_VoluntaryCheckInformation *vci;
- unsigned int requirements_length;
- unsigned int vci_length;
- bool is_and_combinator;
- } ok;
- } details;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetKycInfoCallback instead.
- */
-typedef void
-(*TALER_EXCHANGE_KycInfoCallback)(
- void *cls,
- const struct TALER_EXCHANGE_KycProcessClientInformation *kpci);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetKycInfoHandle instead.
- */
-struct TALER_EXCHANGE_KycInfoHandle;
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_kyc_info_create() and
- * the new API instead.
- */
-struct TALER_EXCHANGE_KycInfoHandle *
-TALER_EXCHANGE_kyc_info (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const struct TALER_AccountAccessTokenP *token,
- const char *if_none_match,
- struct GNUNET_TIME_Relative timeout,
- TALER_EXCHANGE_KycInfoCallback cb,
- void *cb_cls);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_kyc_info_cancel() instead.
- */
-void
-TALER_EXCHANGE_kyc_info_cancel (
- struct TALER_EXCHANGE_KycInfoHandle *kih);
-
-
#endif /* _TALER_EXCHANGE__GET_KYC_INFO_ACCESS_TOKEN_H */
diff --git a/src/include/taler/taler-exchange/get-kyc-proof-PROVIDER_NAME.h b/src/include/taler/taler-exchange/get-kyc-proof-PROVIDER_NAME.h
@@ -247,57 +247,4 @@ TALER_EXCHANGE_get_kyc_proof_cancel (
struct TALER_EXCHANGE_GetKycProofHandle *gkph);
-/* **************** deprecated legacy API ***************** */
-
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetKycProofResponse instead.
- */
-struct TALER_EXCHANGE_KycProofResponse
-{
- struct TALER_EXCHANGE_HttpResponse hr;
- union
- {
- struct
- {
- const char *redirect_url;
- } found;
- } details;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetKycProofCallback instead.
- */
-typedef void
-(*TALER_EXCHANGE_KycProofCallback)(
- void *cls,
- const struct TALER_EXCHANGE_KycProofResponse *kpr);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_GetKycProofHandle instead.
- */
-struct TALER_EXCHANGE_KycProofHandle;
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_kyc_proof_create() and
- * the new API instead.
- */
-struct TALER_EXCHANGE_KycProofHandle *
-TALER_EXCHANGE_kyc_proof (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const char *logic,
- const char *args,
- TALER_EXCHANGE_KycProofCallback cb,
- void *cb_cls);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_get_kyc_proof_cancel() instead.
- */
-void
-TALER_EXCHANGE_kyc_proof_cancel (
- struct TALER_EXCHANGE_KycProofHandle *kph);
-
-
#endif /* _TALER_EXCHANGE__GET_KYC_PROOF_PROVIDER_NAME_H */
diff --git a/src/include/taler/taler-exchange/post-aml-OFFICER_PUB-decision.h b/src/include/taler/taler-exchange/post-aml-OFFICER_PUB-decision.h
@@ -195,8 +195,6 @@ struct TALER_EXCHANGE_PostAmlDecisionOptionValue
*/
struct TALER_EXCHANGE_PostAmlDecisionHandle;
-#if NEW_API
-
/**
* Set up POST /aml/$OFFICER_PUB/decision operation.
@@ -317,8 +315,7 @@ enum GNUNET_GenericReturnValue
TALER_EXCHANGE_post_aml_decision_set_options_ (
struct TALER_EXCHANGE_PostAmlDecisionHandle *padh,
unsigned int num_options,
- struct TALER_EXCHANGE_PostAmlDecisionOptionValue options[
- static num_options]);
+ const struct TALER_EXCHANGE_PostAmlDecisionOptionValue options[]);
/**
@@ -403,70 +400,5 @@ void
TALER_EXCHANGE_post_aml_decision_cancel (
struct TALER_EXCHANGE_PostAmlDecisionHandle *padh);
-#endif
-
-/* **************** deprecated legacy API ***************** */
-
-
-/**
- * @deprecated
- */
-struct TALER_EXCHANGE_AddAmlDecision;
-
-
-/**
- * @deprecated
- */
-struct TALER_EXCHANGE_AddAmlDecisionResponse
-{
- struct TALER_EXCHANGE_HttpResponse hr;
-};
-
-/**
- * @deprecated
- */
-typedef void
-(*TALER_EXCHANGE_AddAmlDecisionCallback) (
- void *cls,
- const struct TALER_EXCHANGE_AddAmlDecisionResponse *adr);
-
-/**
- * @deprecated
- */
-struct TALER_EXCHANGE_AddAmlDecision *
-TALER_EXCHANGE_post_aml_decision (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const struct TALER_FullPayto payto_uri,
- struct GNUNET_TIME_Timestamp decision_time,
- const char *successor_measure,
- const char *new_measures,
- struct GNUNET_TIME_Timestamp expiration_time,
- unsigned int num_rules,
- const struct TALER_EXCHANGE_AccountRule *rules,
- unsigned int num_measures,
- const struct TALER_EXCHANGE_MeasureInformation *measures,
- const json_t *properties,
- bool keep_investigating,
- const char *justification,
- const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
- unsigned int num_events,
- const char **events,
- TALER_EXCHANGE_AddAmlDecisionCallback cb,
- void *cb_cls);
-
-/**
- * Cancel POST /aml/$OFFICER_PUB/decision operation. This function must not
- * be called by clients after the TALER_EXCHANGE_PostAmlDecisionCallback has
- * been invoked (as in those cases it'll be called internally by the
- * implementation already).
- *
- * @param[in] padh operation to cancel
- */
-void
-TALER_EXCHANGE_post_aml_decision_cancel (
- struct TALER_EXCHANGE_AddAmlDecision *padh);
-
#endif /* _TALER_EXCHANGE__POST_AML_OFFICER_PUB_DECISION_H */
diff --git a/src/include/taler/taler-exchange/post-kyc-start-ID.h b/src/include/taler/taler-exchange/post-kyc-start-ID.h
@@ -125,54 +125,4 @@ TALER_EXCHANGE_post_kyc_start_cancel (
struct TALER_EXCHANGE_PostKycStartHandle *pksh);
-/* **************** deprecated legacy API ***************** */
-
-
-/**
- * @deprecated Use #TALER_EXCHANGE_PostKycStartResponse instead.
- */
-struct TALER_EXCHANGE_KycStartResponse
-{
- struct TALER_EXCHANGE_HttpResponse hr;
- union
- {
- struct
- {
- const char *redirect_url;
- } ok;
- } details;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_PostKycStartCallback instead.
- */
-typedef void
-(*TALER_EXCHANGE_KycStartCallback)(
- void *cls,
- const struct TALER_EXCHANGE_KycStartResponse *ksr);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_PostKycStartHandle instead.
- */
-struct TALER_EXCHANGE_KycStartHandle;
-
-/**
- * @deprecated Use #TALER_EXCHANGE_post_kyc_start_create() and
- * the new API instead.
- */
-struct TALER_EXCHANGE_KycStartHandle *
-TALER_EXCHANGE_kyc_start (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const char *id,
- TALER_EXCHANGE_KycStartCallback cb,
- void *cb_cls);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_post_kyc_start_cancel() instead.
- */
-void
-TALER_EXCHANGE_kyc_start_cancel (struct TALER_EXCHANGE_KycStartHandle *ksh);
-
-
#endif /* _TALER_EXCHANGE__POST_KYC_START_ID_H */
diff --git a/src/include/taler/taler-exchange/post-kyc-wallet.h b/src/include/taler/taler-exchange/post-kyc-wallet.h
@@ -138,57 +138,4 @@ TALER_EXCHANGE_post_kyc_wallet_cancel (
struct TALER_EXCHANGE_PostKycWalletHandle *pkwh);
-/* **************** deprecated legacy API ***************** */
-
-
-/**
- * @deprecated Use #TALER_EXCHANGE_PostKycWalletResponse instead.
- */
-struct TALER_EXCHANGE_WalletKycResponse
-{
- struct TALER_EXCHANGE_HttpResponse hr;
- union
- {
- struct
- {
- struct TALER_Amount next_threshold;
- struct GNUNET_TIME_Timestamp expiration_time;
- } ok;
- struct TALER_EXCHANGE_KycNeededRedirect unavailable_for_legal_reasons;
- } details;
-};
-
-/**
- * @deprecated Use #TALER_EXCHANGE_PostKycWalletCallback instead.
- */
-typedef void
-(*TALER_EXCHANGE_KycWalletCallback)(
- void *cls,
- const struct TALER_EXCHANGE_WalletKycResponse *ks);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_PostKycWalletHandle instead.
- */
-struct TALER_EXCHANGE_KycWalletHandle;
-
-/**
- * @deprecated Use #TALER_EXCHANGE_post_kyc_wallet_create() and
- * the new API instead.
- */
-struct TALER_EXCHANGE_KycWalletHandle *
-TALER_EXCHANGE_kyc_wallet (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_Amount *balance,
- TALER_EXCHANGE_KycWalletCallback cb,
- void *cb_cls);
-
-/**
- * @deprecated Use #TALER_EXCHANGE_post_kyc_wallet_cancel() instead.
- */
-void
-TALER_EXCHANGE_kyc_wallet_cancel (struct TALER_EXCHANGE_KycWalletHandle *kwh);
-
-
#endif /* _TALER_EXCHANGE__POST_KYC_WALLET_H */
diff --git a/src/include/taler/taler-exchange/post-purses-PURSE_PUB-create.h b/src/include/taler/taler-exchange/post-purses-PURSE_PUB-create.h
@@ -146,8 +146,7 @@ enum GNUNET_GenericReturnValue
TALER_EXCHANGE_post_purses_create_set_options_ (
struct TALER_EXCHANGE_PostPursesCreateHandle *ppch,
unsigned int num_options,
- struct TALER_EXCHANGE_PostPursesCreateOptionValue options[
- static num_options]);
+ const struct TALER_EXCHANGE_PostPursesCreateOptionValue options[]);
/**
diff --git a/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-close.h b/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-close.h
@@ -132,8 +132,7 @@ enum GNUNET_GenericReturnValue
TALER_EXCHANGE_post_reserves_close_set_options_ (
struct TALER_EXCHANGE_PostReservesCloseHandle *prch,
unsigned int num_options,
- struct TALER_EXCHANGE_PostReservesCloseOptionValue options[
- static num_options]);
+ const struct TALER_EXCHANGE_PostReservesCloseOptionValue options[]);
/**
diff --git a/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-purse.h b/src/include/taler/taler-exchange/post-reserves-RESERVE_PUB-purse.h
@@ -146,8 +146,7 @@ enum GNUNET_GenericReturnValue
TALER_EXCHANGE_post_reserves_purse_set_options_ (
struct TALER_EXCHANGE_PostReservesPurseHandle *prph,
unsigned int num_options,
- struct TALER_EXCHANGE_PostReservesPurseOptionValue options[
- static num_options]);
+ const struct TALER_EXCHANGE_PostReservesPurseOptionValue options[]);
/**
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
@@ -18,7 +18,7 @@ lib_LTLIBRARIES = \
libtalerexchange.la
libtalerexchange_la_LDFLAGS = \
- -version-info 18:0:0 \
+ -version-info 19:0:0 \
-no-undefined
libtalerexchange_la_SOURCES = \
exchange_api_delete-purses-PURSE_PUB.c \
diff --git a/src/lib/exchange_api_get-aml-OFFICER_PUB-attributes-H_NORMALIZED_PAYTO.c b/src/lib/exchange_api_get-aml-OFFICER_PUB-attributes-H_NORMALIZED_PAYTO.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023, 2024 Taler Systems SA
+ Copyright (C) 2023, 2024, 2025, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -28,15 +28,22 @@
#include "exchange_api_handle.h"
#include "taler/taler_signatures.h"
#include "exchange_api_curl_defaults.h"
+#include \
+ "taler/taler-exchange/get-aml-OFFICER_PUB-attributes-H_NORMALIZED_PAYTO.h"
/**
- * @brief A GET /aml/$OFFICER_PUB/attributes Handle
+ * @brief A GET /aml/$OFFICER_PUB/attributes/$H_NORMALIZED_PAYTO Handle
*/
-struct TALER_EXCHANGE_LookupKycAttributes
+struct TALER_EXCHANGE_GetAmlAttributesHandle
{
/**
+ * Base URL of the exchange.
+ */
+ char *base_url;
+
+ /**
* The url for this request.
*/
char *url;
@@ -49,56 +56,91 @@ struct TALER_EXCHANGE_LookupKycAttributes
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_LookupKycAttributesCallback attributes_cb;
+ TALER_EXCHANGE_GetAmlAttributesCallback cb;
/**
* Closure for @e cb.
*/
- void *attributes_cb_cls;
+ TALER_EXCHANGE_GET_AML_ATTRIBUTES_RESULT_CLOSURE *cb_cls;
+
+ /**
+ * CURL context to use.
+ */
+ struct GNUNET_CURL_Context *ctx;
/**
- * HTTP headers for the job.
+ * Public key of the AML officer (computed from officer_priv in _create).
*/
- struct curl_slist *job_headers;
+ struct TALER_AmlOfficerPublicKeyP officer_pub;
+
+ /**
+ * Private key of the AML officer (stored for signing in _start).
+ */
+ struct TALER_AmlOfficerPrivateKeyP officer_priv;
+
+ /**
+ * Hash of the normalized payto URI for the account.
+ */
+ struct TALER_NormalizedPaytoHashP h_payto;
+
+ /**
+ * Options set for this request.
+ */
+ struct
+ {
+ /**
+ * Limit on the number of results (negative = before offset, positive = after).
+ * Default: -20.
+ */
+ int64_t limit;
+
+ /**
+ * Row offset threshold. Default: UINT64_MAX.
+ */
+ uint64_t offset;
+ } options;
};
/**
- * Parse AML decision summary array.
+ * Parse AML attribute collection events from a JSON array.
*
- * @param[in,out] lh handle to use for allocations
- * @param jdetails JSON array with AML decision summaries
- * @param[out] detail_ar where to write the result
+ * @param jdetails JSON array with AML attribute collection events
+ * @param[out] detail_ar where to write the results
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
-parse_kyc_attributes (
- struct TALER_EXCHANGE_LookupKycAttributes *lh,
+parse_attributes_new (
const json_t *jdetails,
- struct TALER_EXCHANGE_KycAttributeDetail *detail_ar)
+ struct TALER_EXCHANGE_GetAmlAttributesCollectionEvent *detail_ar)
{
json_t *obj;
size_t idx;
json_array_foreach (jdetails, idx, obj)
{
- struct TALER_EXCHANGE_KycAttributeDetail *detail
+ struct TALER_EXCHANGE_GetAmlAttributesCollectionEvent *detail
= &detail_ar[idx];
+ bool by_aml_officer = false;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_uint64 ("rowid",
- &detail->row_id),
+ &detail->rowid),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_bool ("by_aml_officer",
+ &by_aml_officer),
+ NULL),
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("provider_name",
- &detail->provider_name),
+ GNUNET_JSON_spec_object_const ("attributes",
+ &detail->attributes),
NULL),
- GNUNET_JSON_spec_object_const ("attributes",
- &detail->attributes),
GNUNET_JSON_spec_timestamp ("collection_time",
&detail->collection_time),
GNUNET_JSON_spec_end ()
};
+ detail->by_aml_officer = false;
+ detail->attributes = NULL;
if (GNUNET_OK !=
GNUNET_JSON_parse (obj,
spec,
@@ -108,23 +150,25 @@ parse_kyc_attributes (
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
+ detail->by_aml_officer = by_aml_officer;
}
return GNUNET_OK;
}
/**
- * Parse the provided decision data from the "200 OK" response.
+ * Parse the provided data from the "200 OK" response.
*
- * @param[in,out] lh handle (callback may be zero'ed out)
- * @param json json reply with the data for one coin
+ * @param[in,out] aagh handle (callback may be zero'ed out)
+ * @param json json reply with the data
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static enum GNUNET_GenericReturnValue
-parse_attributes_ok (struct TALER_EXCHANGE_LookupKycAttributes *lh,
- const json_t *json)
+parse_get_aml_attributes_ok_new (
+ struct TALER_EXCHANGE_GetAmlAttributesHandle *aagh,
+ const json_t *json)
{
- struct TALER_EXCHANGE_KycAttributesResponse lr = {
+ struct TALER_EXCHANGE_GetAmlAttributesResponse lr = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
@@ -144,52 +188,51 @@ parse_attributes_ok (struct TALER_EXCHANGE_LookupKycAttributes *lh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- lr.details.ok.kyc_attributes_length
- = json_array_size (jdetails);
+ lr.details.ok.details_length = json_array_size (jdetails);
{
- struct TALER_EXCHANGE_KycAttributeDetail details[
- GNUNET_NZL (lr.details.ok.kyc_attributes_length)];
- enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
+ struct TALER_EXCHANGE_GetAmlAttributesCollectionEvent details[
+ GNUNET_NZL (lr.details.ok.details_length)];
memset (details,
0,
sizeof (details));
- lr.details.ok.kyc_attributes = details;
- ret = parse_kyc_attributes (lh,
- jdetails,
- details);
- if (GNUNET_OK == ret)
+ lr.details.ok.details = details;
+ if (GNUNET_OK !=
+ parse_attributes_new (jdetails,
+ details))
{
- lh->attributes_cb (lh->attributes_cb_cls,
- &lr);
- lh->attributes_cb = NULL;
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
}
- return ret;
+ aagh->cb (aagh->cb_cls,
+ &lr);
+ aagh->cb = NULL;
}
+ return GNUNET_OK;
}
/**
* Function called when we're done processing the
- * HTTP /aml/$OFFICER_PUB/attributes request.
+ * HTTP GET /aml/$OFFICER_PUB/attributes/$H_NORMALIZED_PAYTO request (new API).
*
- * @param cls the `struct TALER_EXCHANGE_LookupKycAttributes`
+ * @param cls the `struct TALER_EXCHANGE_GetAmlAttributesHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
static void
-handle_lookup_finished (void *cls,
- long response_code,
- const void *response)
+handle_get_aml_attributes_finished (void *cls,
+ long response_code,
+ const void *response)
{
- struct TALER_EXCHANGE_LookupKycAttributes *lh = cls;
+ struct TALER_EXCHANGE_GetAmlAttributesHandle *aagh = cls;
const json_t *j = response;
- struct TALER_EXCHANGE_KycAttributesResponse lr = {
+ struct TALER_EXCHANGE_GetAmlAttributesResponse lr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
- lh->job = NULL;
+ aagh->job = NULL;
switch (response_code)
{
case 0:
@@ -197,19 +240,23 @@ handle_lookup_finished (void *cls,
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
- parse_attributes_ok (lh,
- j))
+ parse_get_aml_attributes_ok_new (aagh,
+ j))
{
GNUNET_break_op (0);
lr.hr.http_status = 0;
lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
- GNUNET_assert (NULL == lh->attributes_cb);
- TALER_EXCHANGE_lookup_kyc_attributes_cancel (lh);
+ GNUNET_assert (NULL == aagh->cb);
+ TALER_EXCHANGE_get_aml_attributes_cancel (aagh);
return;
case MHD_HTTP_NO_CONTENT:
break;
+ case MHD_HTTP_NOT_IMPLEMENTED:
+ lr.hr.ec = TALER_JSON_get_error_code (j);
+ lr.hr.hint = TALER_JSON_get_error_hint (j);
+ break;
case MHD_HTTP_BAD_REQUEST:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
@@ -219,14 +266,10 @@ handle_lookup_finished (void *cls,
case MHD_HTTP_FORBIDDEN:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, exchange says this coin was not melted; we
- should pass the JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, exchange says this coin was not melted; we
- should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
lr.hr.ec = TALER_JSON_get_error_code (j);
@@ -240,56 +283,101 @@ handle_lookup_finished (void *cls,
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for lookup AML attributes\n",
+ "Unexpected response code %u/%d for get AML attributes\n",
(unsigned int) response_code,
(int) lr.hr.ec);
break;
}
- if (NULL != lh->attributes_cb)
- lh->attributes_cb (lh->attributes_cb_cls,
- &lr);
- TALER_EXCHANGE_lookup_kyc_attributes_cancel (lh);
+ if (NULL != aagh->cb)
+ aagh->cb (aagh->cb_cls,
+ &lr);
+ TALER_EXCHANGE_get_aml_attributes_cancel (aagh);
}
-struct TALER_EXCHANGE_LookupKycAttributes *
-TALER_EXCHANGE_lookup_kyc_attributes (
+struct TALER_EXCHANGE_GetAmlAttributesHandle *
+TALER_EXCHANGE_get_aml_attributes_create (
struct GNUNET_CURL_Context *ctx,
- const char *exchange_url,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- uint64_t offset,
- int64_t limit,
+ const char *url,
const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
- TALER_EXCHANGE_LookupKycAttributesCallback cb,
- void *cb_cls)
+ const struct TALER_NormalizedPaytoHashP *h_payto)
+{
+ struct TALER_EXCHANGE_GetAmlAttributesHandle *aagh;
+
+ aagh = GNUNET_new (struct TALER_EXCHANGE_GetAmlAttributesHandle);
+ aagh->ctx = ctx;
+ aagh->base_url = GNUNET_strdup (url);
+ aagh->h_payto = *h_payto;
+ aagh->officer_priv = *officer_priv;
+ GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
+ &aagh->officer_pub.eddsa_pub);
+ aagh->options.limit = -20;
+ aagh->options.offset = UINT64_MAX;
+ return aagh;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_get_aml_attributes_set_options_ (
+ struct TALER_EXCHANGE_GetAmlAttributesHandle *aagh,
+ unsigned int num_options,
+ const struct TALER_EXCHANGE_GetAmlAttributesOptionValue *options)
+{
+ for (unsigned int i = 0; i < num_options; i++)
+ {
+ const struct TALER_EXCHANGE_GetAmlAttributesOptionValue *opt = &options[i];
+
+ switch (opt->option)
+ {
+ case TALER_EXCHANGE_GET_AML_ATTRIBUTES_OPTION_END:
+ return GNUNET_OK;
+ case TALER_EXCHANGE_GET_AML_ATTRIBUTES_OPTION_LIMIT:
+ aagh->options.limit = opt->details.limit;
+ break;
+ case TALER_EXCHANGE_GET_AML_ATTRIBUTES_OPTION_OFFSET:
+ aagh->options.offset = opt->details.offset;
+ break;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_get_aml_attributes_start (
+ struct TALER_EXCHANGE_GetAmlAttributesHandle *aagh,
+ TALER_EXCHANGE_GetAmlAttributesCallback cb,
+ TALER_EXCHANGE_GET_AML_ATTRIBUTES_RESULT_CLOSURE *cb_cls)
{
- struct TALER_EXCHANGE_LookupKycAttributes *lh;
- CURL *eh;
- struct TALER_AmlOfficerPublicKeyP officer_pub;
struct TALER_AmlOfficerSignatureP officer_sig;
- char arg_str[sizeof (officer_pub) * 2
- + sizeof (*h_payto) * 2
+ char arg_str[sizeof (aagh->officer_pub) * 2
+ + sizeof (aagh->h_payto) * 2
+ 32];
+ CURL *eh;
- GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
- &officer_pub.eddsa_pub);
- TALER_officer_aml_query_sign (officer_priv,
+ if (NULL != aagh->job)
+ {
+ GNUNET_break (0);
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ }
+ aagh->cb = cb;
+ aagh->cb_cls = cb_cls;
+ TALER_officer_aml_query_sign (&aagh->officer_priv,
&officer_sig);
-
{
- char payto_s[sizeof (*h_payto) * 2];
- char pub_str[sizeof (officer_pub) * 2];
+ char payto_s[sizeof (aagh->h_payto) * 2];
+ char pub_str[sizeof (aagh->officer_pub) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (
- h_payto,
- sizeof (*h_payto),
+ &aagh->h_payto,
+ sizeof (aagh->h_payto),
payto_s,
sizeof (payto_s));
*end = '\0';
end = GNUNET_STRINGS_data_to_string (
- &officer_pub,
- sizeof (officer_pub),
+ &aagh->officer_pub,
+ sizeof (aagh->officer_pub),
pub_str,
sizeof (pub_str));
*end = '\0';
@@ -299,9 +387,6 @@ TALER_EXCHANGE_lookup_kyc_attributes (
pub_str,
payto_s);
}
- lh = GNUNET_new (struct TALER_EXCHANGE_LookupKycAttributes);
- lh->attributes_cb = cb;
- lh->attributes_cb_cls = cb_cls;
{
char limit_s[24];
char offset_s[24];
@@ -309,35 +394,30 @@ TALER_EXCHANGE_lookup_kyc_attributes (
GNUNET_snprintf (limit_s,
sizeof (limit_s),
"%lld",
- (long long) limit);
+ (long long) aagh->options.limit);
GNUNET_snprintf (offset_s,
sizeof (offset_s),
"%llu",
- (unsigned long long) offset);
- lh->url = TALER_url_join (
- exchange_url,
- arg_str,
- "limit",
- limit_s,
- "offset",
- offset_s,
- "h_payto",
- NULL);
- }
- if (NULL == lh->url)
- {
- GNUNET_free (lh);
- return NULL;
+ (unsigned long long) aagh->options.offset);
+ aagh->url = TALER_url_join (aagh->base_url,
+ arg_str,
+ "limit",
+ limit_s,
+ "offset",
+ offset_s,
+ NULL);
}
- eh = TALER_EXCHANGE_curl_easy_get_ (lh->url);
+ if (NULL == aagh->url)
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
+ eh = TALER_EXCHANGE_curl_easy_get_ (aagh->url);
if (NULL == eh)
{
- GNUNET_break (0);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
- return NULL;
+ GNUNET_free (aagh->url);
+ aagh->url = NULL;
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
}
{
+ struct curl_slist *job_headers = NULL;
char *hdr;
char sig_str[sizeof (officer_sig) * 2];
char *end;
@@ -348,38 +428,44 @@ TALER_EXCHANGE_lookup_kyc_attributes (
sig_str,
sizeof (sig_str));
*end = '\0';
-
GNUNET_asprintf (&hdr,
"%s: %s",
TALER_AML_OFFICER_SIGNATURE_HEADER,
sig_str);
- lh->job_headers = curl_slist_append (NULL,
- hdr);
+ job_headers = curl_slist_append (NULL,
+ hdr);
GNUNET_free (hdr);
- lh->job_headers = curl_slist_append (lh->job_headers,
- "Content-type: application/json");
- lh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- lh->job_headers,
- &handle_lookup_finished,
- lh);
+ job_headers = curl_slist_append (job_headers,
+ "Content-type: application/json");
+ aagh->job = GNUNET_CURL_job_add2 (aagh->ctx,
+ eh,
+ job_headers,
+ &handle_get_aml_attributes_finished,
+ aagh);
+ curl_slist_free_all (job_headers);
+ }
+ if (NULL == aagh->job)
+ {
+ GNUNET_free (aagh->url);
+ aagh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
- return lh;
+ return TALER_EC_NONE;
}
void
-TALER_EXCHANGE_lookup_kyc_attributes_cancel (
- struct TALER_EXCHANGE_LookupKycAttributes *lh)
+TALER_EXCHANGE_get_aml_attributes_cancel (
+ struct TALER_EXCHANGE_GetAmlAttributesHandle *aagh)
{
- if (NULL != lh->job)
+ if (NULL != aagh->job)
{
- GNUNET_CURL_job_cancel (lh->job);
- lh->job = NULL;
+ GNUNET_CURL_job_cancel (aagh->job);
+ aagh->job = NULL;
}
- curl_slist_free_all (lh->job_headers);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
+ GNUNET_free (aagh->url);
+ GNUNET_free (aagh->base_url);
+ GNUNET_free (aagh);
}
diff --git a/src/lib/exchange_api_get-aml-OFFICER_PUB-decisions.c b/src/lib/exchange_api_get-aml-OFFICER_PUB-decisions.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023, 2024 Taler Systems SA
+ Copyright (C) 2023, 2024, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -25,6 +25,7 @@
#include <gnunet/gnunet_curl_lib.h>
#include "taler/taler_exchange_service.h"
#include "taler/taler_json_lib.h"
+#include "taler/taler-exchange/get-aml-OFFICER_PUB-decisions.h"
#include "exchange_api_handle.h"
#include "taler/taler_signatures.h"
#include "exchange_api_curl_defaults.h"
@@ -33,11 +34,16 @@
/**
* @brief A GET /aml/$OFFICER_PUB/decisions Handle
*/
-struct TALER_EXCHANGE_LookupAmlDecisions
+struct TALER_EXCHANGE_GetAmlDecisionsHandle
{
/**
- * The url for this request.
+ * The base URL of the exchange.
+ */
+ char *base_url;
+
+ /**
+ * The full URL for this request, set during _start.
*/
char *url;
@@ -49,55 +55,97 @@ struct TALER_EXCHANGE_LookupAmlDecisions
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_LookupAmlDecisionsCallback decisions_cb;
+ TALER_EXCHANGE_GetAmlDecisionsCallback cb;
/**
* Closure for @e cb.
*/
- void *decisions_cb_cls;
+ TALER_EXCHANGE_GET_AML_DECISIONS_RESULT_CLOSURE *cb_cls;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
/**
- * HTTP headers for the job.
+ * Public key of the AML officer.
*/
- struct curl_slist *job_headers;
+ struct TALER_AmlOfficerPublicKeyP officer_pub;
/**
- * Array with measure information.
+ * Private key of the AML officer (for signing).
*/
- struct TALER_EXCHANGE_MeasureInformation *mip;
+ struct TALER_AmlOfficerPrivateKeyP officer_priv;
+
+ /**
+ * Signature of the AML officer.
+ */
+ struct TALER_AmlOfficerSignatureP officer_sig;
+
+ /**
+ * Options for the request.
+ */
+ struct
+ {
+ /**
+ * Limit on number of results (-20 by default).
+ */
+ int64_t limit;
+
+ /**
+ * Row offset threshold (INT64_MAX by default).
+ */
+ uint64_t offset;
+
+ /**
+ * Optional account filter; NULL if not set.
+ */
+ const struct TALER_NormalizedPaytoHashP *h_payto;
+
+ /**
+ * Filter for active decisions (YNA_ALL by default).
+ */
+ enum TALER_EXCHANGE_YesNoAll active;
+
+ /**
+ * Filter for investigation status (YNA_ALL by default).
+ */
+ enum TALER_EXCHANGE_YesNoAll investigation;
+ } options;
/**
- * Array with rule information.
+ * Flat array of all KYC rules across all decisions (allocated during parse).
*/
- struct TALER_EXCHANGE_KycRule *rp;
+ struct TALER_EXCHANGE_GetAmlDecisionsKycRule *all_rules;
/**
- * Array with all the measures (of all the rules!).
+ * Flat array of all measure string pointers across all rules (allocated during parse).
*/
- const char **mp;
+ const char **all_mp;
+
};
/**
- * Parse AML limits array.
+ * Parse the limits/rules object.
*
- * @param[in,out] lh handle to use for allocations
- * @param jlimits JSON array with AML rules
- * @param[out] ds where to write the result
+ * @param[in,out] adgh handle (used for allocation tracking)
+ * @param jlimits JSON object with legitimization rule set data
+ * @param[out] limits where to write the parsed rule set
+ * @param[in,out] rule_off current offset into adgh->all_rules (advanced)
+ * @param[in,out] mp_off current offset into adgh->all_mp (advanced)
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
-parse_limits (struct TALER_EXCHANGE_LookupAmlDecisions *lh,
- const json_t *jlimits,
- struct TALER_EXCHANGE_AmlDecision *ds)
+parse_limits (
+ struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh,
+ const json_t *jlimits,
+ struct TALER_EXCHANGE_GetAmlDecisionsLegitimizationRuleSet *limits,
+ size_t *rule_off,
+ size_t *mp_off)
{
- struct TALER_EXCHANGE_LegitimizationRuleSet *limits
- = &ds->limits;
const json_t *jrules;
- const json_t *jmeasures;
- size_t mip_len;
- size_t rule_len;
- size_t total;
+ const json_t *jcustom_measures;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_timestamp ("expiration_time",
&limits->expiration_time),
@@ -107,8 +155,10 @@ parse_limits (struct TALER_EXCHANGE_LookupAmlDecisions *lh,
NULL),
GNUNET_JSON_spec_array_const ("rules",
&jrules),
- GNUNET_JSON_spec_object_const ("custom_measures",
- &jmeasures),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_object_const ("custom_measures",
+ &jcustom_measures),
+ NULL),
GNUNET_JSON_spec_end ()
};
@@ -121,172 +171,131 @@ parse_limits (struct TALER_EXCHANGE_LookupAmlDecisions *lh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
-
- mip_len = json_object_size (jmeasures);
- lh->mip = GNUNET_new_array (mip_len,
- struct TALER_EXCHANGE_MeasureInformation);
- limits->measures = lh->mip;
- limits->measures_length = mip_len;
+ limits->custom_measures = jcustom_measures;
{
- const char *measure_name;
- const json_t *jmeasure;
-
- json_object_foreach ((json_t*) jmeasures,
- measure_name,
- jmeasure)
- {
- struct TALER_EXCHANGE_MeasureInformation *mi
- = &lh->mip[--mip_len];
- struct GNUNET_JSON_Specification ispec[] = {
- GNUNET_JSON_spec_string ("check_name",
- &mi->check_name),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("prog_name",
- &mi->prog_name),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_object_const ("context",
- &mi->context),
- NULL),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (jmeasure,
- ispec,
- NULL,
- NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- mi->measure_name = measure_name;
- }
- }
-
- total = 0;
-
- {
- const json_t *rule;
- size_t idx;
-
- json_array_foreach ((json_t *) jrules,
- idx,
- rule)
- {
- total += json_array_size (json_object_get (rule,
- "measures"));
- }
- }
-
- rule_len = json_array_size (jrules);
- lh->rp = GNUNET_new_array (rule_len,
- struct TALER_EXCHANGE_KycRule);
- lh->mp = GNUNET_new_array (total,
- const char *);
+ size_t rule_count = json_array_size (jrules);
+ size_t rule_start = *rule_off;
- {
- const json_t *rule;
- size_t idx;
+ limits->rules = &adgh->all_rules[rule_start];
+ limits->rules_length = rule_count;
- json_array_foreach ((json_t *) jrules,
- idx,
- rule)
{
- const json_t *smeasures;
- struct TALER_EXCHANGE_KycRule *r
- = &lh->rp[--rule_len];
- struct GNUNET_JSON_Specification ispec[] = {
- TALER_JSON_spec_kycte ("operation_type",
- &r->operation_type),
- TALER_JSON_spec_amount_any ("threshold",
- &r->threshold),
- GNUNET_JSON_spec_relative_time ("timeframe",
- &r->timeframe),
- GNUNET_JSON_spec_array_const ("measures",
- &smeasures),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool ("exposed",
- &r->exposed),
- NULL),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_bool ("is_and_combinator",
- &r->is_and_combinator),
- NULL),
- GNUNET_JSON_spec_uint32 ("display_priority",
- &r->display_priority),
- GNUNET_JSON_spec_end ()
- };
- size_t mlen;
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (rule,
- ispec,
- NULL,
- NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- mlen = json_array_size (smeasures);
- GNUNET_assert (mlen <= total);
- total -= mlen;
+ const json_t *jrule;
+ size_t ridx;
+ json_array_foreach ((json_t *) jrules, ridx, jrule)
{
- size_t midx;
- const json_t *smeasure;
+ struct TALER_EXCHANGE_GetAmlDecisionsKycRule *r
+ = &adgh->all_rules[*rule_off];
+ const json_t *jsmeasures;
+ struct GNUNET_JSON_Specification rspec[] = {
+ TALER_JSON_spec_kycte ("operation_type",
+ &r->operation_type),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("rule_name",
+ &r->rule_name),
+ NULL),
+ TALER_JSON_spec_amount_any ("threshold",
+ &r->threshold),
+ GNUNET_JSON_spec_relative_time ("timeframe",
+ &r->timeframe),
+ GNUNET_JSON_spec_array_const ("measures",
+ &jsmeasures),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_bool ("exposed",
+ &r->exposed),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_bool ("is_and_combinator",
+ &r->is_and_combinator),
+ NULL),
+ GNUNET_JSON_spec_int64 ("display_priority",
+ &r->display_priority),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (jrule,
+ rspec,
+ NULL,
+ NULL))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
- json_array_foreach (smeasures,
- midx,
- smeasure)
{
- const char *sval = json_string_value (smeasure);
+ size_t mlen = json_array_size (jsmeasures);
+ size_t mp_start = *mp_off;
+
+ r->measures = &adgh->all_mp[mp_start];
+ r->measures_length = mlen;
- if (NULL == sval)
{
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
+ size_t midx;
+ const json_t *jm;
+
+ json_array_foreach (jsmeasures, midx, jm)
+ {
+ const char *sval = json_string_value (jm);
+
+ if (NULL == sval)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ adgh->all_mp[*mp_off] = sval;
+ (*mp_off)++;
+ }
}
- lh->mp[total + midx] = sval;
- if (0 == strcasecmp (sval,
- "verboten"))
- r->verboten = true;
}
+
+ (*rule_off)++;
}
- r->measures = &lh->mp[total];
- r->measures_length = r->verboten ? 0 : total;
}
}
+
return GNUNET_OK;
}
/**
- * Parse AML decision summary array.
+ * Parse AML decision records.
*
- * @param[in,out] lh handle to use for allocations
- * @param decisions JSON array with AML decision summaries
- * @param[out] decision_ar where to write the result
+ * @param[in,out] adgh handle (for allocations)
+ * @param jrecords JSON array of decision records
+ * @param records_ar_length length of @a records_ar
+ * @param[out] records_ar caller-allocated array to fill
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
parse_aml_decisions (
- struct TALER_EXCHANGE_LookupAmlDecisions *lh,
- const json_t *decisions,
- struct TALER_EXCHANGE_AmlDecision *decision_ar)
+ struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh,
+ const json_t *jrecords,
+ size_t records_ar_length,
+ struct TALER_EXCHANGE_GetAmlDecisionsDecision *records_ar)
{
- json_t *obj;
+ size_t rule_off = 0;
+ size_t mp_off = 0;
+ const json_t *obj;
size_t idx;
- json_array_foreach (decisions, idx, obj)
+ json_array_foreach ((json_t *) jrecords, idx, obj)
{
- struct TALER_EXCHANGE_AmlDecision *decision = &decision_ar[idx];
+ struct TALER_EXCHANGE_GetAmlDecisionsDecision *decision = &records_ar[idx];
const json_t *jlimits;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("h_payto",
&decision->h_payto),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("full_payto",
+ &decision->full_payto),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_bool ("is_wallet",
+ &decision->is_wallet),
+ NULL),
GNUNET_JSON_spec_uint64 ("rowid",
&decision->rowid),
GNUNET_JSON_spec_mark_optional (
@@ -297,7 +306,7 @@ parse_aml_decisions (
&decision->decision_time),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_object_const ("properties",
- &decision->jproperties),
+ &decision->properties),
NULL),
GNUNET_JSON_spec_object_const ("limits",
&jlimits),
@@ -308,6 +317,7 @@ parse_aml_decisions (
GNUNET_JSON_spec_end ()
};
+ GNUNET_assert (idx < records_ar_length);
if (GNUNET_OK !=
GNUNET_JSON_parse (obj,
spec,
@@ -317,10 +327,13 @@ parse_aml_decisions (
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
+
if (GNUNET_OK !=
- parse_limits (lh,
+ parse_limits (adgh,
jlimits,
- decision))
+ &decision->limits,
+ &rule_off,
+ &mp_off))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
@@ -333,22 +346,22 @@ parse_aml_decisions (
/**
* Parse the provided decision data from the "200 OK" response.
*
- * @param[in,out] lh handle (callback may be zero'ed out)
- * @param json json reply with the data for one coin
+ * @param[in,out] adgh handle (callback may be zero'ed out)
+ * @param json json reply with the data
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static enum GNUNET_GenericReturnValue
-parse_decisions_ok (struct TALER_EXCHANGE_LookupAmlDecisions *lh,
- const json_t *json)
+parse_get_aml_decisions_ok (struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh,
+ const json_t *json)
{
- struct TALER_EXCHANGE_AmlDecisionsResponse lr = {
+ struct TALER_EXCHANGE_GetAmlDecisionsResponse lr = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
- const json_t *records;
+ const json_t *jrecords;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_array_const ("records",
- &records),
+ &jrecords),
GNUNET_JSON_spec_end ()
};
@@ -361,29 +374,73 @@ parse_decisions_ok (struct TALER_EXCHANGE_LookupAmlDecisions *lh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- lr.details.ok.decisions_length
- = json_array_size (records);
+
+ lr.details.ok.records_length = json_array_size (jrecords);
+
+ /* First pass: count total rules and measures across all records */
{
- struct TALER_EXCHANGE_AmlDecision decisions[
- GNUNET_NZL (lr.details.ok.decisions_length)];
- enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
+ size_t total_rules = 0;
+ size_t total_measures = 0;
+ const json_t *obj;
+ size_t idx;
- memset (decisions,
+ json_array_foreach ((json_t *) jrecords, idx, obj)
+ {
+ const json_t *jlimits = json_object_get (obj, "limits");
+ const json_t *jrules;
+
+ if (NULL == jlimits)
+ continue;
+ jrules = json_object_get (jlimits, "rules");
+ if (NULL == jrules)
+ continue;
+ total_rules += json_array_size (jrules);
+
+ {
+ const json_t *jrule;
+ size_t ridx;
+
+ json_array_foreach ((json_t *) jrules, ridx, jrule)
+ {
+ const json_t *jmeasures = json_object_get (jrule, "measures");
+
+ if (NULL != jmeasures)
+ total_measures += json_array_size (jmeasures);
+ }
+ }
+ }
+
+ adgh->all_rules = GNUNET_new_array (
+ GNUNET_NZL (total_rules),
+ struct TALER_EXCHANGE_GetAmlDecisionsKycRule);
+ adgh->all_mp = GNUNET_new_array (
+ GNUNET_NZL (total_measures),
+ const char *);
+ }
+
+ {
+ struct TALER_EXCHANGE_GetAmlDecisionsDecision records[
+ GNUNET_NZL (lr.details.ok.records_length)];
+ enum GNUNET_GenericReturnValue ret;
+
+ memset (records,
0,
- sizeof (decisions));
- lr.details.ok.decisions = decisions;
- ret = parse_aml_decisions (lh,
- records,
- decisions);
+ sizeof (records));
+ lr.details.ok.records = records;
+ ret = parse_aml_decisions (adgh,
+ jrecords,
+ lr.details.ok.records_length,
+ records);
if (GNUNET_OK == ret)
{
- lh->decisions_cb (lh->decisions_cb_cls,
- &lr);
- lh->decisions_cb = NULL;
+ adgh->cb (adgh->cb_cls,
+ &lr);
+ adgh->cb = NULL;
}
- GNUNET_free (lh->mip);
- GNUNET_free (lh->rp);
- GNUNET_free (lh->mp);
+ GNUNET_free (adgh->all_rules);
+ adgh->all_rules = NULL;
+ GNUNET_free (adgh->all_mp);
+ adgh->all_mp = NULL;
return ret;
}
}
@@ -393,23 +450,23 @@ parse_decisions_ok (struct TALER_EXCHANGE_LookupAmlDecisions *lh,
* Function called when we're done processing the
* HTTP /aml/$OFFICER_PUB/decisions request.
*
- * @param cls the `struct TALER_EXCHANGE_LookupAmlDecisions`
+ * @param cls the `struct TALER_EXCHANGE_GetAmlDecisionsHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
static void
-handle_lookup_finished (void *cls,
- long response_code,
- const void *response)
+handle_get_aml_decisions_finished (void *cls,
+ long response_code,
+ const void *response)
{
- struct TALER_EXCHANGE_LookupAmlDecisions *lh = cls;
+ struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh = cls;
const json_t *j = response;
- struct TALER_EXCHANGE_AmlDecisionsResponse lr = {
+ struct TALER_EXCHANGE_GetAmlDecisionsResponse lr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
- lh->job = NULL;
+ adgh->job = NULL;
switch (response_code)
{
case 0:
@@ -417,16 +474,16 @@ handle_lookup_finished (void *cls,
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
- parse_decisions_ok (lh,
- j))
+ parse_get_aml_decisions_ok (adgh,
+ j))
{
GNUNET_break_op (0);
lr.hr.http_status = 0;
lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
- GNUNET_assert (NULL == lh->decisions_cb);
- TALER_EXCHANGE_lookup_aml_decisions_cancel (lh);
+ GNUNET_assert (NULL == adgh->cb);
+ TALER_EXCHANGE_get_aml_decisions_cancel (adgh);
return;
case MHD_HTTP_NO_CONTENT:
break;
@@ -436,26 +493,18 @@ handle_lookup_finished (void *cls,
JSON_INDENT (2));
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
break;
case MHD_HTTP_FORBIDDEN:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, exchange says this coin was not melted; we
- should pass the JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, exchange says this coin was not melted; we
- should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
break;
default:
/* unexpected response code */
@@ -463,49 +512,103 @@ handle_lookup_finished (void *cls,
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for lookup AML decisions\n",
+ "Unexpected response code %u/%d for GET AML decisions\n",
(unsigned int) response_code,
(int) lr.hr.ec);
break;
}
- if (NULL != lh->decisions_cb)
- lh->decisions_cb (lh->decisions_cb_cls,
- &lr);
- TALER_EXCHANGE_lookup_aml_decisions_cancel (lh);
+ if (NULL != adgh->cb)
+ adgh->cb (adgh->cb_cls,
+ &lr);
+ TALER_EXCHANGE_get_aml_decisions_cancel (adgh);
}
-struct TALER_EXCHANGE_LookupAmlDecisions *
-TALER_EXCHANGE_lookup_aml_decisions (
+struct TALER_EXCHANGE_GetAmlDecisionsHandle *
+TALER_EXCHANGE_get_aml_decisions_create (
struct GNUNET_CURL_Context *ctx,
- const char *exchange_url,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- enum TALER_EXCHANGE_YesNoAll investigation_only,
- enum TALER_EXCHANGE_YesNoAll active_only,
- uint64_t offset,
- int64_t limit,
- const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
- TALER_EXCHANGE_LookupAmlDecisionsCallback cb,
- void *cb_cls)
+ const char *url,
+ const struct TALER_AmlOfficerPrivateKeyP *officer_priv)
{
- struct TALER_EXCHANGE_LookupAmlDecisions *lh;
- CURL *eh;
- struct TALER_AmlOfficerPublicKeyP officer_pub;
- struct TALER_AmlOfficerSignatureP officer_sig;
- char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2
- + 32];
+ struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh;
+ adgh = GNUNET_new (struct TALER_EXCHANGE_GetAmlDecisionsHandle);
+ adgh->ctx = ctx;
+ adgh->base_url = GNUNET_strdup (url);
+ adgh->officer_priv = *officer_priv;
GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
- &officer_pub.eddsa_pub);
- TALER_officer_aml_query_sign (officer_priv,
- &officer_sig);
+ &adgh->officer_pub.eddsa_pub);
+ adgh->options.limit = -20;
+ adgh->options.offset = INT64_MAX;
+ adgh->options.active = TALER_EXCHANGE_YNA_ALL;
+ adgh->options.investigation = TALER_EXCHANGE_YNA_ALL;
+ return adgh;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_get_aml_decisions_set_options_ (
+ struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh,
+ unsigned int num_options,
+ const struct TALER_EXCHANGE_GetAmlDecisionsOptionValue options[])
+{
+ for (unsigned int i = 0; i < num_options; i++)
{
- char pub_str[sizeof (officer_pub) * 2];
+ const struct TALER_EXCHANGE_GetAmlDecisionsOptionValue *opt = &options[i];
+
+ switch (opt->option)
+ {
+ case TALER_EXCHANGE_GET_AML_DECISIONS_OPTION_END:
+ return GNUNET_OK;
+ case TALER_EXCHANGE_GET_AML_DECISIONS_OPTION_LIMIT:
+ adgh->options.limit = opt->details.limit;
+ break;
+ case TALER_EXCHANGE_GET_AML_DECISIONS_OPTION_OFFSET:
+ adgh->options.offset = opt->details.offset;
+ break;
+ case TALER_EXCHANGE_GET_AML_DECISIONS_OPTION_H_PAYTO:
+ adgh->options.h_payto = opt->details.h_payto;
+ break;
+ case TALER_EXCHANGE_GET_AML_DECISIONS_OPTION_ACTIVE:
+ adgh->options.active = opt->details.active;
+ break;
+ case TALER_EXCHANGE_GET_AML_DECISIONS_OPTION_INVESTIGATION:
+ adgh->options.investigation = opt->details.investigation;
+ break;
+ default:
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_get_aml_decisions_start (
+ struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh,
+ TALER_EXCHANGE_GetAmlDecisionsCallback cb,
+ TALER_EXCHANGE_GET_AML_DECISIONS_RESULT_CLOSURE *cb_cls)
+{
+ CURL *eh;
+ char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2 + 32];
+ struct curl_slist *job_headers = NULL;
+
+ adgh->cb = cb;
+ adgh->cb_cls = cb_cls;
+
+ /* Build AML officer signature */
+ TALER_officer_aml_query_sign (&adgh->officer_priv,
+ &adgh->officer_sig);
+
+ /* Build the path component: aml/{officer_pub}/decisions */
+ {
+ char pub_str[sizeof (adgh->officer_pub) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (
- &officer_pub,
- sizeof (officer_pub),
+ &adgh->officer_pub,
+ sizeof (adgh->officer_pub),
pub_str,
sizeof (pub_str));
*end = '\0';
@@ -514,24 +617,18 @@ TALER_EXCHANGE_lookup_aml_decisions (
"aml/%s/decisions",
pub_str);
}
- lh = GNUNET_new (struct TALER_EXCHANGE_LookupAmlDecisions);
- lh->decisions_cb = cb;
- lh->decisions_cb_cls = cb_cls;
+
+ /* Build URL with optional query parameters */
{
char limit_s[24];
char offset_s[24];
- char payto_s[sizeof (*h_payto) * 2];
- char *end;
+ char payto_s[sizeof (*adgh->options.h_payto) * 2 + 1];
+ int64_t limit = adgh->options.limit;
+ uint64_t offset = adgh->options.offset;
+ bool omit_limit = (-20 == limit);
+ bool omit_offset = ( ( (limit < 0) && ((uint64_t) INT64_MAX == offset) ) ||
+ ( (limit > 0) && (0 == offset) ) );
- if (NULL != h_payto)
- {
- end = GNUNET_STRINGS_data_to_string (
- h_payto,
- sizeof (*h_payto),
- payto_s,
- sizeof (payto_s));
- *end = '\0';
- }
GNUNET_snprintf (limit_s,
sizeof (limit_s),
"%lld",
@@ -540,51 +637,60 @@ TALER_EXCHANGE_lookup_aml_decisions (
sizeof (offset_s),
"%llu",
(unsigned long long) offset);
- lh->url = TALER_url_join (
- exchange_url,
+
+ if (NULL != adgh->options.h_payto)
+ {
+ char *end;
+
+ end = GNUNET_STRINGS_data_to_string (
+ adgh->options.h_payto,
+ sizeof (*adgh->options.h_payto),
+ payto_s,
+ sizeof (payto_s) - 1);
+ *end = '\0';
+ }
+
+ adgh->url = TALER_url_join (
+ adgh->base_url,
arg_str,
"limit",
- limit_s,
+ omit_limit ? NULL : limit_s,
"offset",
- ( ( (limit < 0) && (UINT64_MAX == offset) ) ||
- ( (limit > 0) && (0 == offset) ) )
- ? NULL
- : offset_s,
+ omit_offset ? NULL : offset_s,
"h_payto",
- NULL != h_payto
- ? payto_s
- : NULL,
+ (NULL != adgh->options.h_payto) ? payto_s : NULL,
"active",
- TALER_EXCHANGE_YNA_ALL != active_only
- ? TALER_yna_to_string (active_only)
+ (TALER_EXCHANGE_YNA_ALL != adgh->options.active)
+ ? TALER_yna_to_string (adgh->options.active)
: NULL,
"investigation",
- TALER_EXCHANGE_YNA_ALL != investigation_only
- ? TALER_yna_to_string (investigation_only)
+ (TALER_EXCHANGE_YNA_ALL != adgh->options.investigation)
+ ? TALER_yna_to_string (adgh->options.investigation)
: NULL,
NULL);
}
- if (NULL == lh->url)
- {
- GNUNET_free (lh);
- return NULL;
- }
- eh = TALER_EXCHANGE_curl_easy_get_ (lh->url);
+
+ if (NULL == adgh->url)
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
+
+ eh = TALER_EXCHANGE_curl_easy_get_ (adgh->url);
if (NULL == eh)
{
GNUNET_break (0);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
- return NULL;
+ GNUNET_free (adgh->url);
+ adgh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
+
+ /* Build job headers with AML officer signature */
{
char *hdr;
- char sig_str[sizeof (officer_sig) * 2];
+ char sig_str[sizeof (adgh->officer_sig) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (
- &officer_sig,
- sizeof (officer_sig),
+ &adgh->officer_sig,
+ sizeof (adgh->officer_sig),
sig_str,
sizeof (sig_str));
*end = '\0';
@@ -593,34 +699,45 @@ TALER_EXCHANGE_lookup_aml_decisions (
"%s: %s",
TALER_AML_OFFICER_SIGNATURE_HEADER,
sig_str);
- lh->job_headers = curl_slist_append (NULL,
- hdr);
+ job_headers = curl_slist_append (NULL,
+ hdr);
GNUNET_free (hdr);
- lh->job_headers = curl_slist_append (lh->job_headers,
- "Content-type: application/json");
- lh->job = GNUNET_CURL_job_add2 (ctx,
+ job_headers = curl_slist_append (job_headers,
+ "Content-Type: application/json");
+ }
+
+ adgh->job = GNUNET_CURL_job_add2 (adgh->ctx,
eh,
- lh->job_headers,
- &handle_lookup_finished,
- lh);
+ job_headers,
+ &handle_get_aml_decisions_finished,
+ adgh);
+ curl_slist_free_all (job_headers);
+
+ if (NULL == adgh->job)
+ {
+ GNUNET_free (adgh->url);
+ adgh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
- return lh;
+ return TALER_EC_NONE;
}
void
-TALER_EXCHANGE_lookup_aml_decisions_cancel (
- struct TALER_EXCHANGE_LookupAmlDecisions *lh)
+TALER_EXCHANGE_get_aml_decisions_cancel (
+ struct TALER_EXCHANGE_GetAmlDecisionsHandle *adgh)
{
- if (NULL != lh->job)
+ if (NULL != adgh->job)
{
- GNUNET_CURL_job_cancel (lh->job);
- lh->job = NULL;
+ GNUNET_CURL_job_cancel (adgh->job);
+ adgh->job = NULL;
}
- curl_slist_free_all (lh->job_headers);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
+ GNUNET_free (adgh->all_rules);
+ GNUNET_free (adgh->all_mp);
+ GNUNET_free (adgh->url);
+ GNUNET_free (adgh->base_url);
+ GNUNET_free (adgh);
}
-/* end of exchange_api_lookup_aml_decisions.c */
+/* end of exchange_api_get-aml-OFFICER_PUB-decisions.c */
diff --git a/src/lib/exchange_api_get-aml-OFFICER_PUB-kyc-statistics-NAMES.c b/src/lib/exchange_api_get-aml-OFFICER_PUB-kyc-statistics-NAMES.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023, 2024 Taler Systems SA
+ Copyright (C) 2023, 2024, 2025, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -28,16 +28,22 @@
#include "exchange_api_handle.h"
#include "taler/taler_signatures.h"
#include "exchange_api_curl_defaults.h"
+#include "taler/taler-exchange/get-aml-OFFICER_PUB-kyc-statistics-NAMES.h"
/**
- * @brief A GET /aml/$OFFICER_PUB/kyc-statistics/$NAME Handle
+ * @brief A GET /aml/$OFFICER_PUB/kyc-statistics/$NAMES Handle (new API)
*/
-struct TALER_EXCHANGE_KycGetStatisticsHandle
+struct TALER_EXCHANGE_GetAmlKycStatisticsHandle
{
/**
- * The url for this request.
+ * The base URL of the exchange.
+ */
+ char *base_url;
+
+ /**
+ * The full URL for this request.
*/
char *url;
@@ -49,41 +55,72 @@ struct TALER_EXCHANGE_KycGetStatisticsHandle
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_KycStatisticsCallback stats_cb;
+ TALER_EXCHANGE_GetAmlKycStatisticsCallback cb;
/**
* Closure for @e cb.
*/
- void *stats_cb_cls;
+ TALER_EXCHANGE_GET_AML_KYC_STATISTICS_RESULT_CLOSURE *cb_cls;
+
+ /**
+ * CURL context to use.
+ */
+ struct GNUNET_CURL_Context *ctx;
/**
- * HTTP headers for the job.
+ * Public key of the AML officer.
*/
- struct curl_slist *job_headers;
+ struct TALER_AmlOfficerPublicKeyP officer_pub;
+
+ /**
+ * Private key of the AML officer.
+ */
+ struct TALER_AmlOfficerPrivateKeyP officer_priv;
+
+ /**
+ * Space-separated list of event type names to count.
+ */
+ char *names;
+
+ /**
+ * Options for this request.
+ */
+ struct
+ {
+ /**
+ * Start date for statistics window. Zero means "from the beginning".
+ */
+ struct GNUNET_TIME_Timestamp start_date;
+
+ /**
+ * End date for statistics window. #GNUNET_TIME_UNIT_FOREVER_ABS means "up to now".
+ */
+ struct GNUNET_TIME_Timestamp end_date;
+ } options;
};
/**
- * Parse the provided decision data from the "200 OK" response.
+ * Parse the provided statistics data from the "200 OK" response.
*
- * @param[in,out] lh handle (callback may be zero'ed out)
- * @param json json reply with the data for one coin
+ * @param[in,out] aksh handle (callback may be zero'ed out)
+ * @param json json reply
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static enum GNUNET_GenericReturnValue
-parse_stats_ok (
- struct TALER_EXCHANGE_KycGetStatisticsHandle *lh,
+parse_stats_ok_new (
+ struct TALER_EXCHANGE_GetAmlKycStatisticsHandle *aksh,
const json_t *json)
{
- struct TALER_EXCHANGE_KycGetStatisticsResponse lr = {
+ struct TALER_EXCHANGE_GetAmlKycStatisticsResponse lr = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
- uint64_t cnt;
+ const json_t *jstatistics;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint64 ("counter",
- &cnt),
+ GNUNET_JSON_spec_array_const ("statistics",
+ &jstatistics),
GNUNET_JSON_spec_end ()
};
@@ -96,35 +133,68 @@ parse_stats_ok (
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- lr.details.ok.counter = (unsigned long long) cnt;
- lh->stats_cb (lh->stats_cb_cls,
- &lr);
- lh->stats_cb = NULL;
+ lr.details.ok.statistics_length = json_array_size (jstatistics);
+ {
+ struct TALER_EXCHANGE_GetAmlKycStatisticsEventCounter statistics[
+ GNUNET_NZL (lr.details.ok.statistics_length)];
+ json_t *obj;
+ size_t idx;
+
+ memset (statistics,
+ 0,
+ sizeof (statistics));
+ lr.details.ok.statistics = statistics;
+ json_array_foreach (jstatistics, idx, obj)
+ {
+ struct TALER_EXCHANGE_GetAmlKycStatisticsEventCounter *ec
+ = &statistics[idx];
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_string ("name",
+ &ec->name),
+ GNUNET_JSON_spec_uint64 ("counter",
+ &ec->counter),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (obj,
+ ispec,
+ NULL,
+ NULL))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ }
+ aksh->cb (aksh->cb_cls,
+ &lr);
+ aksh->cb = NULL;
+ }
return GNUNET_OK;
}
/**
* Function called when we're done processing the
- * HTTP /aml/$OFFICER_PUB/kyc-statistics/$NAME request.
+ * HTTP GET /aml/$OFFICER_PUB/kyc-statistics/$NAMES request.
*
- * @param cls the `struct TALER_EXCHANGE_KycGetStatisticsHandle`
+ * @param cls the `struct TALER_EXCHANGE_GetAmlKycStatisticsHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
static void
-handle_lookup_finished (void *cls,
- long response_code,
- const void *response)
+handle_get_aml_kyc_statistics_finished (void *cls,
+ long response_code,
+ const void *response)
{
- struct TALER_EXCHANGE_KycGetStatisticsHandle *lh = cls;
+ struct TALER_EXCHANGE_GetAmlKycStatisticsHandle *aksh = cls;
const json_t *j = response;
- struct TALER_EXCHANGE_KycGetStatisticsResponse lr = {
+ struct TALER_EXCHANGE_GetAmlKycStatisticsResponse lr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
- lh->job = NULL;
+ aksh->job = NULL;
switch (response_code)
{
case 0:
@@ -132,16 +202,16 @@ handle_lookup_finished (void *cls,
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
- parse_stats_ok (lh,
- j))
+ parse_stats_ok_new (aksh,
+ j))
{
GNUNET_break_op (0);
lr.hr.http_status = 0;
lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
- GNUNET_assert (NULL == lh->stats_cb);
- TALER_EXCHANGE_kyc_get_statistics_cancel (lh);
+ GNUNET_assert (NULL == aksh->cb);
+ TALER_EXCHANGE_get_aml_kyc_statistics_cancel (aksh);
return;
case MHD_HTTP_NO_CONTENT:
break;
@@ -154,8 +224,6 @@ handle_lookup_finished (void *cls,
case MHD_HTTP_FORBIDDEN:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, exchange says this coin was not melted; we
- should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
lr.hr.ec = TALER_JSON_get_error_code (j);
@@ -174,68 +242,117 @@ handle_lookup_finished (void *cls,
(int) lr.hr.ec);
break;
}
- if (NULL != lh->stats_cb)
- lh->stats_cb (lh->stats_cb_cls,
- &lr);
- TALER_EXCHANGE_kyc_get_statistics_cancel (lh);
+ if (NULL != aksh->cb)
+ aksh->cb (aksh->cb_cls,
+ &lr);
+ TALER_EXCHANGE_get_aml_kyc_statistics_cancel (aksh);
}
-struct TALER_EXCHANGE_KycGetStatisticsHandle *
-TALER_EXCHANGE_kyc_get_statistics (
+struct TALER_EXCHANGE_GetAmlKycStatisticsHandle *
+TALER_EXCHANGE_get_aml_kyc_statistics_create (
struct GNUNET_CURL_Context *ctx,
- const char *exchange_url,
- const char *name,
- struct GNUNET_TIME_Timestamp start_date,
- struct GNUNET_TIME_Timestamp end_date,
+ const char *url,
const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
- TALER_EXCHANGE_KycStatisticsCallback cb,
- void *cb_cls)
+ const char *names)
+{
+ struct TALER_EXCHANGE_GetAmlKycStatisticsHandle *aksh;
+
+ aksh = GNUNET_new (struct TALER_EXCHANGE_GetAmlKycStatisticsHandle);
+ aksh->ctx = ctx;
+ aksh->base_url = GNUNET_strdup (url);
+ aksh->officer_priv = *officer_priv;
+ GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
+ &aksh->officer_pub.eddsa_pub);
+ aksh->names = GNUNET_strdup (names);
+ /* Default: no start date filter, no end date filter */
+ aksh->options.start_date = GNUNET_TIME_UNIT_ZERO_TS;
+ aksh->options.end_date = GNUNET_TIME_UNIT_FOREVER_TS;
+ return aksh;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_get_aml_kyc_statistics_set_options_ (
+ struct TALER_EXCHANGE_GetAmlKycStatisticsHandle *aksh,
+ unsigned int num_options,
+ const struct TALER_EXCHANGE_GetAmlKycStatisticsOptionValue *options)
+{
+ for (unsigned int i = 0; i < num_options; i++)
+ {
+ const struct TALER_EXCHANGE_GetAmlKycStatisticsOptionValue *opt
+ = &options[i];
+
+ switch (opt->option)
+ {
+ case TALER_EXCHANGE_GET_AML_KYC_STATISTICS_OPTION_END:
+ return GNUNET_OK;
+ case TALER_EXCHANGE_GET_AML_KYC_STATISTICS_OPTION_START_DATE:
+ aksh->options.start_date = opt->details.start_date;
+ break;
+ case TALER_EXCHANGE_GET_AML_KYC_STATISTICS_OPTION_END_DATE:
+ aksh->options.end_date = opt->details.end_date;
+ break;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_get_aml_kyc_statistics_start (
+ struct TALER_EXCHANGE_GetAmlKycStatisticsHandle *aksh,
+ TALER_EXCHANGE_GetAmlKycStatisticsCallback cb,
+ TALER_EXCHANGE_GET_AML_KYC_STATISTICS_RESULT_CLOSURE *cb_cls)
{
- struct TALER_EXCHANGE_KycGetStatisticsHandle *lh;
- CURL *eh;
- struct TALER_AmlOfficerPublicKeyP officer_pub;
struct TALER_AmlOfficerSignatureP officer_sig;
- char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2
- + 32];
+ CURL *eh;
char sd_str[32];
char ed_str[32];
const char *sd = NULL;
const char *ed = NULL;
- if (! GNUNET_TIME_absolute_is_zero (start_date.abs_time))
+ if (NULL != aksh->job)
+ {
+ GNUNET_break (0);
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ }
+ aksh->cb = cb;
+ aksh->cb_cls = cb_cls;
+ TALER_officer_aml_query_sign (&aksh->officer_priv,
+ &officer_sig);
+ if (! GNUNET_TIME_absolute_is_zero (aksh->options.start_date.abs_time))
{
unsigned long long sec;
- sec = (unsigned long long) GNUNET_TIME_timestamp_to_s (start_date);
+ sec = (unsigned long long) GNUNET_TIME_timestamp_to_s (
+ aksh->options.start_date);
GNUNET_snprintf (sd_str,
sizeof (sd_str),
"%llu",
sec);
sd = sd_str;
}
- if (! GNUNET_TIME_absolute_is_never (end_date.abs_time))
+ if (! GNUNET_TIME_absolute_is_never (aksh->options.end_date.abs_time))
{
unsigned long long sec;
- sec = (unsigned long long) GNUNET_TIME_timestamp_to_s (end_date);
+ sec = (unsigned long long) GNUNET_TIME_timestamp_to_s (
+ aksh->options.end_date);
GNUNET_snprintf (ed_str,
sizeof (ed_str),
"%llu",
sec);
ed = ed_str;
}
- GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
- &officer_pub.eddsa_pub);
- TALER_officer_aml_query_sign (officer_priv,
- &officer_sig);
{
- char pub_str[sizeof (officer_pub) * 2];
+ char pub_str[sizeof (aksh->officer_pub) * 2];
+ char arg_str[sizeof (aksh->officer_pub) * 2 + 32];
char *end;
end = GNUNET_STRINGS_data_to_string (
- &officer_pub,
- sizeof (officer_pub),
+ &aksh->officer_pub,
+ sizeof (aksh->officer_pub),
pub_str,
sizeof (pub_str));
*end = '\0';
@@ -243,32 +360,26 @@ TALER_EXCHANGE_kyc_get_statistics (
sizeof (arg_str),
"aml/%s/kyc-statistics/%s",
pub_str,
- name);
- }
- lh = GNUNET_new (struct TALER_EXCHANGE_KycGetStatisticsHandle);
- lh->stats_cb = cb;
- lh->stats_cb_cls = cb_cls;
- lh->url = TALER_url_join (exchange_url,
- arg_str,
- "start_date",
- sd,
- "end_date",
- ed,
- NULL);
- if (NULL == lh->url)
- {
- GNUNET_free (lh);
- return NULL;
+ aksh->names);
+ aksh->url = TALER_url_join (aksh->base_url,
+ arg_str,
+ "start_date",
+ sd,
+ "end_date",
+ ed,
+ NULL);
}
- eh = TALER_EXCHANGE_curl_easy_get_ (lh->url);
+ if (NULL == aksh->url)
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
+ eh = TALER_EXCHANGE_curl_easy_get_ (aksh->url);
if (NULL == eh)
{
- GNUNET_break (0);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
- return NULL;
+ GNUNET_free (aksh->url);
+ aksh->url = NULL;
+ return TALER_EC_GENERIC_ALLOCATION_FAILURE;
}
{
+ struct curl_slist *job_headers = NULL;
char *hdr;
char sig_str[sizeof (officer_sig) * 2];
char *end;
@@ -279,39 +390,46 @@ TALER_EXCHANGE_kyc_get_statistics (
sig_str,
sizeof (sig_str));
*end = '\0';
-
GNUNET_asprintf (&hdr,
"%s: %s",
TALER_AML_OFFICER_SIGNATURE_HEADER,
sig_str);
- lh->job_headers = curl_slist_append (NULL,
- hdr);
+ job_headers = curl_slist_append (NULL,
+ hdr);
GNUNET_free (hdr);
- lh->job_headers = curl_slist_append (lh->job_headers,
- "Content-type: application/json");
- lh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- lh->job_headers,
- &handle_lookup_finished,
- lh);
+ job_headers = curl_slist_append (job_headers,
+ "Content-type: application/json");
+ aksh->job = GNUNET_CURL_job_add2 (aksh->ctx,
+ eh,
+ job_headers,
+ &handle_get_aml_kyc_statistics_finished,
+ aksh);
+ curl_slist_free_all (job_headers);
+ }
+ if (NULL == aksh->job)
+ {
+ GNUNET_free (aksh->url);
+ aksh->url = NULL;
+ return TALER_EC_GENERIC_ALLOCATION_FAILURE;
}
- return lh;
+ return TALER_EC_NONE;
}
void
-TALER_EXCHANGE_kyc_get_statistics_cancel (
- struct TALER_EXCHANGE_KycGetStatisticsHandle *lh)
+TALER_EXCHANGE_get_aml_kyc_statistics_cancel (
+ struct TALER_EXCHANGE_GetAmlKycStatisticsHandle *aksh)
{
- if (NULL != lh->job)
+ if (NULL != aksh->job)
{
- GNUNET_CURL_job_cancel (lh->job);
- lh->job = NULL;
+ GNUNET_CURL_job_cancel (aksh->job);
+ aksh->job = NULL;
}
- curl_slist_free_all (lh->job_headers);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
+ GNUNET_free (aksh->url);
+ GNUNET_free (aksh->base_url);
+ GNUNET_free (aksh->names);
+ GNUNET_free (aksh);
}
-/* end of exchange_api_get_kyc_statistics.c */
+/* end of exchange_api_get-aml-OFFICER_PUB-kyc-statistics-NAMES.c */
diff --git a/src/lib/exchange_api_get-aml-OFFICER_PUB-legitimizations.c b/src/lib/exchange_api_get-aml-OFFICER_PUB-legitimizations.c
@@ -27,6 +27,7 @@
#include <gnunet/gnunet_curl_lib.h>
#include "taler/taler_exchange_service.h"
#include "taler/taler_json_lib.h"
+#include "taler/taler-exchange/get-aml-OFFICER_PUB-legitimizations.h"
#include "exchange_api_handle.h"
#include "taler/taler_signatures.h"
#include "exchange_api_curl_defaults.h"
@@ -79,11 +80,6 @@ struct TALER_EXCHANGE_GetAmlLegitimizationsHandle
char *url;
/**
- * HTTP headers for the job.
- */
- struct curl_slist *job_headers;
-
- /**
* Request options.
*/
struct
@@ -363,7 +359,7 @@ TALER_EXCHANGE_get_aml_legitimizations_set_options_ (
}
-enum TALER_EXCHANGE_AmlLegitimizationsGetStartError
+enum TALER_ErrorCode
TALER_EXCHANGE_get_aml_legitimizations_start (
struct TALER_EXCHANGE_GetAmlLegitimizationsHandle *algh,
TALER_EXCHANGE_GetAmlLegitimizationsCallback cb,
@@ -378,7 +374,7 @@ TALER_EXCHANGE_get_aml_legitimizations_start (
if (NULL != algh->job)
{
GNUNET_break (0);
- return TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_START_E_AGAIN;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
algh->cb = cb;
algh->cb_cls = cb_cls;
@@ -444,11 +440,12 @@ TALER_EXCHANGE_get_aml_legitimizations_start (
if (NULL == algh->url)
{
GNUNET_break (0);
- return TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_START_E_INTERNAL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
{
CURL *eh;
+ struct curl_slist *job_headers = NULL;
eh = TALER_EXCHANGE_curl_easy_get_ (algh->url);
if (NULL == eh)
@@ -456,7 +453,7 @@ TALER_EXCHANGE_get_aml_legitimizations_start (
GNUNET_break (0);
GNUNET_free (algh->url);
algh->url = NULL;
- return TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_START_E_INTERNAL;
+ return TALER_EC_GENERIC_ALLOCATION_FAILURE;
}
/* Add authentication header for AML officer */
@@ -475,19 +472,26 @@ TALER_EXCHANGE_get_aml_legitimizations_start (
"%s: %s",
TALER_AML_OFFICER_SIGNATURE_HEADER,
sig_str);
- algh->job_headers = curl_slist_append (NULL,
- hdr);
+ job_headers = curl_slist_append (NULL,
+ hdr);
GNUNET_free (hdr);
}
algh->job
= GNUNET_CURL_job_add2 (
algh->ctx,
eh,
- algh->job_headers,
+ job_headers,
&handle_aml_legitimizations_get_finished,
algh);
+ curl_slist_free_all (job_headers);
+ if (NULL == algh->job)
+ {
+ GNUNET_free (algh->url);
+ algh->url = NULL;
+ return TALER_EC_GENERIC_ALLOCATION_FAILURE;
+ }
}
- return TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_START_OK;
+ return TALER_EC_NONE;
}
@@ -500,7 +504,6 @@ TALER_EXCHANGE_get_aml_legitimizations_cancel (
GNUNET_CURL_job_cancel (algh->job);
algh->job = NULL;
}
- curl_slist_free_all (algh->job_headers);
GNUNET_free (algh->exchange_base_url);
GNUNET_free (algh->url);
GNUNET_free (algh);
diff --git a/src/lib/exchange_api_get-aml-OFFICER_PUB-measures.c b/src/lib/exchange_api_get-aml-OFFICER_PUB-measures.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023, 2024 Taler Systems SA
+ Copyright (C) 2023, 2024, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -25,6 +25,7 @@
#include <gnunet/gnunet_curl_lib.h>
#include "taler/taler_exchange_service.h"
#include "taler/taler_json_lib.h"
+#include "taler/taler-exchange/get-aml-OFFICER_PUB-measures.h"
#include "exchange_api_handle.h"
#include "taler/taler_signatures.h"
#include "exchange_api_curl_defaults.h"
@@ -55,11 +56,16 @@ struct Scrap
/**
* @brief A GET /aml/$OFFICER_PUB/measures Handle
*/
-struct TALER_EXCHANGE_AmlGetMeasuresHandle
+struct TALER_EXCHANGE_GetAmlMeasuresHandle
{
/**
- * The url for this request.
+ * The base URL of the exchange.
+ */
+ char *base_url;
+
+ /**
+ * The full URL for this request, set during _start.
*/
char *url;
@@ -71,17 +77,27 @@ struct TALER_EXCHANGE_AmlGetMeasuresHandle
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_AmlMeasuresCallback measures_cb;
+ TALER_EXCHANGE_GetAmlMeasuresCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ TALER_EXCHANGE_GET_AML_MEASURES_RESULT_CLOSURE *cb_cls;
/**
- * Closure for @e measures_cb.
+ * Reference to the execution context.
*/
- void *measures_cb_cls;
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Public key of the AML officer.
+ */
+ struct TALER_AmlOfficerPublicKeyP officer_pub;
/**
- * HTTP headers for the job.
+ * Private key of the AML officer (for signing).
*/
- struct curl_slist *job_headers;
+ struct TALER_AmlOfficerPrivateKeyP officer_priv;
/**
* Head of scrap list.
@@ -96,70 +112,23 @@ struct TALER_EXCHANGE_AmlGetMeasuresHandle
/**
- * Parse AML measures.
- *
- * @param jroots JSON object with measure data
- * @param[out] roots where to write the result
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-parse_aml_roots (
- const json_t *jroots,
- struct TALER_EXCHANGE_AvailableAmlMeasures *roots)
-{
- const json_t *obj;
- const char *name;
- size_t idx = 0;
-
- json_object_foreach ((json_t *) jroots, name, obj)
- {
- struct TALER_EXCHANGE_AvailableAmlMeasures *root
- = &roots[idx++];
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("check_name",
- &root->check_name),
- GNUNET_JSON_spec_string ("prog_name",
- &root->prog_name),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_object_const ("context",
- &root->context),
- NULL),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (obj,
- spec,
- NULL,
- NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- root->measure_name = name;
- }
- return GNUNET_OK;
-}
-
-
-/**
* Create array of length @a len in scrap book.
*
- * @param[in,out] lh context for allocations
+ * @param[in,out] amh context for allocations
* @param len length of array
* @return scrap array
*/
static const char **
make_scrap (
- struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
+ struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
unsigned int len)
{
struct Scrap *s = GNUNET_new (struct Scrap);
s->ptr = GNUNET_new_array (len,
const char *);
- GNUNET_CONTAINER_DLL_insert (lh->scrap_head,
- lh->scrap_tail,
+ GNUNET_CONTAINER_DLL_insert (amh->scrap_head,
+ amh->scrap_tail,
s);
return s->ptr;
}
@@ -168,17 +137,17 @@ make_scrap (
/**
* Free all scrap space.
*
- * @param[in,out] lh scrap context
+ * @param[in,out] amh scrap context
*/
static void
-free_scrap (struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh)
+free_scrap (struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh)
{
struct Scrap *s;
- while (NULL != (s = lh->scrap_head))
+ while (NULL != (s = amh->scrap_head))
{
- GNUNET_CONTAINER_DLL_remove (lh->scrap_head,
- lh->scrap_tail,
+ GNUNET_CONTAINER_DLL_remove (amh->scrap_head,
+ amh->scrap_tail,
s);
GNUNET_free (s->ptr);
GNUNET_free (s);
@@ -210,18 +179,74 @@ j_to_a (const json_t *j,
/**
+ * Parse AML root measures.
+ *
+ * @param jroots JSON object with measure data
+ * @param[out] roots where to write the result
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+parse_aml_roots (
+ const json_t *jroots,
+ struct TALER_EXCHANGE_GetAmlMeasuresMeasureInfo *roots)
+{
+ const json_t *obj;
+ const char *name;
+ size_t idx = 0;
+
+ json_object_foreach ((json_t *) jroots, name, obj)
+ {
+ struct TALER_EXCHANGE_GetAmlMeasuresMeasureInfo *root = &roots[idx++];
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("check_name",
+ &root->check_name),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("prog_name",
+ &root->prog_name),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_object_const ("context",
+ &root->context),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("operation_type",
+ &root->operation_type),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_bool ("voluntary",
+ &root->voluntary),
+ NULL),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (obj,
+ spec,
+ NULL,
+ NULL))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ root->measure_name = name;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
* Parse AML programs.
*
- * @param[in,out] lh context for allocations
+ * @param[in,out] amh context for allocations
* @param jprogs JSON object with program data
* @param[out] progs where to write the result
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
parse_aml_programs (
- struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
+ struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
const json_t *jprogs,
- struct TALER_EXCHANGE_AvailableAmlPrograms *progs)
+ struct TALER_EXCHANGE_GetAmlMeasuresProgramRequirement *progs)
{
const json_t *obj;
const char *name;
@@ -229,8 +254,8 @@ parse_aml_programs (
json_object_foreach ((json_t *) jprogs, name, obj)
{
- struct TALER_EXCHANGE_AvailableAmlPrograms *prog
- = &progs[idx++];
+ struct TALER_EXCHANGE_GetAmlMeasuresProgramRequirement *prog = &progs[idx++]
+ ;
const json_t *jcontext;
const json_t *jinputs;
struct GNUNET_JSON_Specification spec[] = {
@@ -255,30 +280,23 @@ parse_aml_programs (
return GNUNET_SYSERR;
}
prog->prog_name = name;
- prog->contexts_length
- = (unsigned int) json_array_size (jcontext);
- prog->inputs_length
- = (unsigned int) json_array_size (jinputs);
- len = prog->contexts_length + prog->inputs_length;
- if ( ((unsigned long long) len) !=
- (unsigned long long) json_array_size (jcontext)
- + (unsigned long long) json_array_size (jinputs) )
+ prog->contexts_length = json_array_size (jcontext);
+ prog->inputs_length = json_array_size (jinputs);
+ len = (unsigned int) (prog->contexts_length + prog->inputs_length);
+ if ( ((size_t) len) != prog->contexts_length + prog->inputs_length)
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- ptr = make_scrap (lh,
- len);
+ ptr = make_scrap (amh, len);
prog->contexts = ptr;
- if (! j_to_a (jcontext,
- prog->contexts))
+ if (! j_to_a (jcontext, prog->contexts))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
prog->inputs = &ptr[prog->contexts_length];
- if (! j_to_a (jinputs,
- prog->inputs))
+ if (! j_to_a (jinputs, prog->inputs))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
@@ -289,18 +307,18 @@ parse_aml_programs (
/**
- * Parse AML measures.
+ * Parse KYC checks.
*
- * @param[in,out] lh context for allocations
- * @param jchecks JSON object with measure data
+ * @param[in,out] amh context for allocations
+ * @param jchecks JSON object with check data
* @param[out] checks where to write the result
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
parse_aml_checks (
- struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
+ struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
const json_t *jchecks,
- struct TALER_EXCHANGE_AvailableKycChecks *checks)
+ struct TALER_EXCHANGE_GetAmlMeasuresCheckInfo *checks)
{
const json_t *obj;
const char *name;
@@ -308,8 +326,7 @@ parse_aml_checks (
json_object_foreach ((json_t *) jchecks, name, obj)
{
- struct TALER_EXCHANGE_AvailableKycChecks *check
- = &checks[idx++];
+ struct TALER_EXCHANGE_GetAmlMeasuresCheckInfo *check = &checks[idx++];
const json_t *jrequires;
const json_t *joutputs;
struct GNUNET_JSON_Specification spec[] = {
@@ -340,58 +357,125 @@ parse_aml_checks (
return GNUNET_SYSERR;
}
check->check_name = name;
-
- check->requires_length
- = (unsigned int) json_array_size (jrequires);
- check->outputs_length
- = (unsigned int) json_array_size (joutputs);
- len = check->requires_length + check->outputs_length;
- if ( ((unsigned long long) len) !=
- (unsigned long long) json_array_size (jrequires)
- + (unsigned long long) json_array_size (joutputs) )
+ check->requires_length = json_array_size (jrequires);
+ check->outputs_length = json_array_size (joutputs);
+ len = (unsigned int) (check->requires_length + check->outputs_length);
+ if ( ((size_t) len) != check->requires_length + check->outputs_length)
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- ptr = make_scrap (lh,
- len);
+ ptr = make_scrap (amh, len);
check->requires = ptr;
- if (! j_to_a (jrequires,
- check->requires))
+ if (! j_to_a (jrequires, check->requires))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
check->outputs = &ptr[check->requires_length];
- if (! j_to_a (joutputs,
- check->outputs))
+ if (! j_to_a (joutputs, check->outputs))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Parse default KYC rules from the default_rules array.
+ *
+ * @param[in,out] amh context for allocations
+ * @param jrules JSON array with rule data
+ * @param[out] rules where to write the result
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+parse_default_rules (
+ struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
+ const json_t *jrules,
+ struct TALER_EXCHANGE_GetAmlMeasuresKycRule *rules)
+{
+ const json_t *obj;
+ size_t idx;
+
+ json_array_foreach ((json_t *) jrules, idx, obj)
+ {
+ struct TALER_EXCHANGE_GetAmlMeasuresKycRule *rule = &rules[idx];
+ const json_t *jmeasures;
+ struct GNUNET_JSON_Specification spec[] = {
+ TALER_JSON_spec_kycte ("operation_type",
+ &rule->operation_type),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_string ("rule_name",
+ &rule->rule_name),
+ NULL),
+ TALER_JSON_spec_amount_any ("threshold",
+ &rule->threshold),
+ GNUNET_JSON_spec_relative_time ("timeframe",
+ &rule->timeframe),
+ GNUNET_JSON_spec_array_const ("measures",
+ &jmeasures),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_bool ("exposed",
+ &rule->exposed),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_bool ("is_and_combinator",
+ &rule->is_and_combinator),
+ NULL),
+ GNUNET_JSON_spec_int64 ("display_priority",
+ &rule->display_priority),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (obj,
+ spec,
+ NULL,
+ NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
+ rule->measures_length = json_array_size (jmeasures);
+ {
+ const char **ptr = make_scrap (amh,
+ (unsigned int) rule->measures_length);
+
+ rule->measures = ptr;
+ if (! j_to_a (jmeasures,
+ ptr))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ }
}
return GNUNET_OK;
}
/**
- * Parse the provided decision data from the "200 OK" response.
+ * Parse the provided measures data from the "200 OK" response.
*
- * @param[in,out] lh handle (callback may be zero'ed out)
- * @param json json reply with the data for one coin
+ * @param[in,out] amh handle (callback may be zero'ed out)
+ * @param json json reply with the data
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static enum GNUNET_GenericReturnValue
-parse_measures_ok (struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
- const json_t *json)
+parse_get_aml_measures_ok (struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
+ const json_t *json)
{
- struct TALER_EXCHANGE_AmlGetMeasuresResponse lr = {
+ struct TALER_EXCHANGE_GetAmlMeasuresResponse lr = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
const json_t *jroots;
const json_t *jprograms;
const json_t *jchecks;
+ const json_t *jdefault_rules = NULL;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_object_const ("roots",
&jroots),
@@ -399,6 +483,10 @@ parse_measures_ok (struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
&jprograms),
GNUNET_JSON_spec_object_const ("checks",
&jchecks),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_array_const ("default_rules",
+ &jdefault_rules),
+ NULL),
GNUNET_JSON_spec_end ()
};
@@ -411,61 +499,47 @@ parse_measures_ok (struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- lr.details.ok.roots_length
- = (unsigned int) json_object_size (jroots);
- lr.details.ok.programs_length
- = (unsigned int) json_object_size (jprograms);
- lr.details.ok.checks_length
- = (unsigned int) json_object_size (jchecks);
- if ( ( ((size_t) lr.details.ok.roots_length)
- != json_object_size (jroots)) ||
- ( ((size_t) lr.details.ok.programs_length)
- != json_object_size (jprograms)) ||
- ( ((size_t) lr.details.ok.checks_length)
- != json_object_size (jchecks)) )
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
+
+ lr.details.ok.roots_length = json_object_size (jroots);
+ lr.details.ok.programs_length = json_object_size (jprograms);
+ lr.details.ok.checks_length = json_object_size (jchecks);
+ lr.details.ok.default_rules_length =
+ (NULL != jdefault_rules) ? json_array_size (jdefault_rules) : 0;
{
- struct TALER_EXCHANGE_AvailableAmlMeasures roots[
+ struct TALER_EXCHANGE_GetAmlMeasuresMeasureInfo roots[
GNUNET_NZL (lr.details.ok.roots_length)];
- struct TALER_EXCHANGE_AvailableAmlPrograms progs[
+ struct TALER_EXCHANGE_GetAmlMeasuresProgramRequirement progs[
GNUNET_NZL (lr.details.ok.programs_length)];
- struct TALER_EXCHANGE_AvailableKycChecks checks[
+ struct TALER_EXCHANGE_GetAmlMeasuresCheckInfo checks[
GNUNET_NZL (lr.details.ok.checks_length)];
+ struct TALER_EXCHANGE_GetAmlMeasuresKycRule drules[
+ GNUNET_NZL (lr.details.ok.default_rules_length)];
enum GNUNET_GenericReturnValue ret;
- memset (roots,
- 0,
- sizeof (roots));
- memset (progs,
- 0,
- sizeof (progs));
- memset (checks,
- 0,
- sizeof (checks));
+ memset (roots, 0, sizeof (roots));
+ memset (progs, 0, sizeof (progs));
+ memset (checks, 0, sizeof (checks));
+ memset (drules, 0, sizeof (drules));
lr.details.ok.roots = roots;
lr.details.ok.programs = progs;
lr.details.ok.checks = checks;
- ret = parse_aml_roots (jroots,
- roots);
+ lr.details.ok.default_rules = drules;
+
+ ret = parse_aml_roots (jroots, roots);
if (GNUNET_OK == ret)
- ret = parse_aml_programs (lh,
- jprograms,
- progs);
+ ret = parse_aml_programs (amh, jprograms, progs);
if (GNUNET_OK == ret)
- ret = parse_aml_checks (lh,
- jchecks,
- checks);
+ ret = parse_aml_checks (amh, jchecks, checks);
+ if ( (GNUNET_OK == ret) && (NULL != jdefault_rules) )
+ ret = parse_default_rules (amh, jdefault_rules, drules);
if (GNUNET_OK == ret)
{
- lh->measures_cb (lh->measures_cb_cls,
- &lr);
- lh->measures_cb = NULL;
+ amh->cb (amh->cb_cls,
+ &lr);
+ amh->cb = NULL;
}
- free_scrap (lh);
+ free_scrap (amh);
return ret;
}
}
@@ -473,25 +547,25 @@ parse_measures_ok (struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh,
/**
* Function called when we're done processing the
- * HTTP /aml/$OFFICER_PUB/measures request.
+ * HTTP GET /aml/$OFFICER_PUB/measures request.
*
- * @param cls the `struct TALER_EXCHANGE_AmlGetMeasuresHandle`
+ * @param cls the `struct TALER_EXCHANGE_GetAmlMeasuresHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
static void
-handle_lookup_finished (void *cls,
- long response_code,
- const void *response)
+handle_get_aml_measures_finished (void *cls,
+ long response_code,
+ const void *response)
{
- struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh = cls;
+ struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh = cls;
const json_t *j = response;
- struct TALER_EXCHANGE_AmlGetMeasuresResponse lr = {
+ struct TALER_EXCHANGE_GetAmlMeasuresResponse lr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
- lh->job = NULL;
+ amh->job = NULL;
switch (response_code)
{
case 0:
@@ -499,36 +573,30 @@ handle_lookup_finished (void *cls,
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
- parse_measures_ok (lh,
- j))
+ parse_get_aml_measures_ok (amh,
+ j))
{
GNUNET_break_op (0);
lr.hr.http_status = 0;
lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
- GNUNET_assert (NULL == lh->measures_cb);
- TALER_EXCHANGE_aml_get_measures_cancel (lh);
+ GNUNET_assert (NULL == amh->cb);
+ TALER_EXCHANGE_get_aml_measures_cancel (amh);
return;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_BAD_REQUEST:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
break;
case MHD_HTTP_FORBIDDEN:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, exchange says this coin was not melted; we
- should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
break;
default:
/* unexpected response code */
@@ -536,44 +604,62 @@ handle_lookup_finished (void *cls,
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for get AML measures\n",
+ "Unexpected response code %u/%d for GET AML measures\n",
(unsigned int) response_code,
(int) lr.hr.ec);
break;
}
- if (NULL != lh->measures_cb)
- lh->measures_cb (lh->measures_cb_cls,
- &lr);
- TALER_EXCHANGE_aml_get_measures_cancel (lh);
+ if (NULL != amh->cb)
+ amh->cb (amh->cb_cls,
+ &lr);
+ TALER_EXCHANGE_get_aml_measures_cancel (amh);
}
-struct TALER_EXCHANGE_AmlGetMeasuresHandle *
-TALER_EXCHANGE_aml_get_measures (
+struct TALER_EXCHANGE_GetAmlMeasuresHandle *
+TALER_EXCHANGE_get_aml_measures_create (
struct GNUNET_CURL_Context *ctx,
- const char *exchange_url,
- const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
- TALER_EXCHANGE_AmlMeasuresCallback cb,
- void *cb_cls)
+ const char *url,
+ const struct TALER_AmlOfficerPrivateKeyP *officer_priv)
+{
+ struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh;
+
+ amh = GNUNET_new (struct TALER_EXCHANGE_GetAmlMeasuresHandle);
+ amh->ctx = ctx;
+ amh->base_url = GNUNET_strdup (url);
+ amh->officer_priv = *officer_priv;
+ GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
+ &amh->officer_pub.eddsa_pub);
+ return amh;
+}
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_get_aml_measures_start (
+ struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh,
+ TALER_EXCHANGE_GetAmlMeasuresCallback cb,
+ TALER_EXCHANGE_GET_AML_MEASURES_RESULT_CLOSURE *cb_cls)
{
- struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh;
CURL *eh;
- struct TALER_AmlOfficerPublicKeyP officer_pub;
struct TALER_AmlOfficerSignatureP officer_sig;
- char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2
- + 32];
+ char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2 + 32];
+ struct curl_slist *job_headers = NULL;
- GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
- &officer_pub.eddsa_pub);
- TALER_officer_aml_query_sign (officer_priv,
+ amh->cb = cb;
+ amh->cb_cls = cb_cls;
+
+ /* Build AML officer signature */
+ TALER_officer_aml_query_sign (&amh->officer_priv,
&officer_sig);
+
+ /* Build the path component: aml/{officer_pub}/measures */
{
- char pub_str[sizeof (officer_pub) * 2];
+ char pub_str[sizeof (amh->officer_pub) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (
- &officer_pub,
- sizeof (officer_pub),
+ &amh->officer_pub,
+ sizeof (amh->officer_pub),
pub_str,
sizeof (pub_str));
*end = '\0';
@@ -582,25 +668,23 @@ TALER_EXCHANGE_aml_get_measures (
"aml/%s/measures",
pub_str);
}
- lh = GNUNET_new (struct TALER_EXCHANGE_AmlGetMeasuresHandle);
- lh->measures_cb = cb;
- lh->measures_cb_cls = cb_cls;
- lh->url = TALER_url_join (exchange_url,
- arg_str,
- NULL);
- if (NULL == lh->url)
- {
- GNUNET_free (lh);
- return NULL;
- }
- eh = TALER_EXCHANGE_curl_easy_get_ (lh->url);
+
+ amh->url = TALER_url_join (amh->base_url,
+ arg_str,
+ NULL);
+ if (NULL == amh->url)
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
+
+ eh = TALER_EXCHANGE_curl_easy_get_ (amh->url);
if (NULL == eh)
{
GNUNET_break (0);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
- return NULL;
+ GNUNET_free (amh->url);
+ amh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
+
+ /* Build job headers with AML officer signature */
{
char *hdr;
char sig_str[sizeof (officer_sig) * 2];
@@ -617,34 +701,44 @@ TALER_EXCHANGE_aml_get_measures (
"%s: %s",
TALER_AML_OFFICER_SIGNATURE_HEADER,
sig_str);
- lh->job_headers = curl_slist_append (NULL,
- hdr);
+ job_headers = curl_slist_append (NULL,
+ hdr);
GNUNET_free (hdr);
- lh->job_headers = curl_slist_append (lh->job_headers,
- "Content-type: application/json");
- lh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- lh->job_headers,
- &handle_lookup_finished,
- lh);
+ job_headers = curl_slist_append (job_headers,
+ "Content-Type: application/json");
+ }
+
+ amh->job = GNUNET_CURL_job_add2 (amh->ctx,
+ eh,
+ job_headers,
+ &handle_get_aml_measures_finished,
+ amh);
+ curl_slist_free_all (job_headers);
+
+ if (NULL == amh->job)
+ {
+ GNUNET_free (amh->url);
+ amh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
- return lh;
+ return TALER_EC_NONE;
}
void
-TALER_EXCHANGE_aml_get_measures_cancel (
- struct TALER_EXCHANGE_AmlGetMeasuresHandle *lh)
+TALER_EXCHANGE_get_aml_measures_cancel (
+ struct TALER_EXCHANGE_GetAmlMeasuresHandle *amh)
{
- if (NULL != lh->job)
+ if (NULL != amh->job)
{
- GNUNET_CURL_job_cancel (lh->job);
- lh->job = NULL;
+ GNUNET_CURL_job_cancel (amh->job);
+ amh->job = NULL;
}
- curl_slist_free_all (lh->job_headers);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
+ free_scrap (amh);
+ GNUNET_free (amh->url);
+ GNUNET_free (amh->base_url);
+ GNUNET_free (amh);
}
-/* end of exchange_api_get_aml_measures.c */
+/* end of exchange_api_get-aml-OFFICER_PUB-measures.c */
diff --git a/src/lib/exchange_api_get-kyc-check-H_NORMALIZED_PAYTO.c b/src/lib/exchange_api_get-kyc-check-H_NORMALIZED_PAYTO.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021-2024 Taler Systems SA
+ Copyright (C) 2021-2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -25,19 +25,24 @@
#include <gnunet/gnunet_curl_lib.h>
#include "taler/taler_exchange_service.h"
#include "taler/taler_json_lib.h"
-#include "exchange_api_handle.h"
+#include "taler/taler-exchange/get-kyc-check-H_NORMALIZED_PAYTO.h"
#include "taler/taler_signatures.h"
#include "exchange_api_curl_defaults.h"
/**
- * @brief A ``/kyc-check`` handle
+ * @brief A GET /kyc-check/$H_NORMALIZED_PAYTO handle
*/
-struct TALER_EXCHANGE_KycCheckHandle
+struct TALER_EXCHANGE_GetKycCheckHandle
{
/**
- * The url for this request.
+ * The base URL for this request.
+ */
+ char *base_url;
+
+ /**
+ * The full URL for this request, set during _start.
*/
char *url;
@@ -49,21 +54,60 @@ struct TALER_EXCHANGE_KycCheckHandle
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_KycStatusCallback cb;
+ TALER_EXCHANGE_GetKycCheckCallback cb;
/**
* Closure for @e cb.
*/
- void *cb_cls;
+ TALER_EXCHANGE_GET_KYC_CHECK_RESULT_CLOSURE *cb_cls;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Hash of the payto URI we are checking.
+ */
+ struct TALER_NormalizedPaytoHashP h_payto;
+
+ /**
+ * Private key to authorize the request.
+ */
+ union TALER_AccountPrivateKeyP account_priv;
+
+ /**
+ * Long polling target.
+ */
+ enum TALER_EXCHANGE_KycLongPollTarget lpt;
+
+ /**
+ * Latest known rule generation (for long polling).
+ */
+ uint64_t known_rule_gen;
+
+ /**
+ * Long polling timeout.
+ */
+ struct GNUNET_TIME_Relative timeout;
};
+/**
+ * Parse an account KYC status from JSON and invoke the callback.
+ *
+ * @param[in,out] gkch handle
+ * @param j JSON to parse
+ * @param res response to fill
+ * @param status account status field within @a res to fill
+ * @return #GNUNET_OK on success
+ */
static enum GNUNET_GenericReturnValue
parse_account_status (
- struct TALER_EXCHANGE_KycCheckHandle *kch,
+ struct TALER_EXCHANGE_GetKycCheckHandle *gkch,
const json_t *j,
- struct TALER_EXCHANGE_KycStatus *ks,
+ struct TALER_EXCHANGE_GetKycCheckResponse *res,
struct TALER_EXCHANGE_AccountKycStatus *status)
{
const json_t *limits = NULL;
@@ -126,13 +170,13 @@ parse_account_status (
}
status->limits = ala;
status->limits_length = limit_length;
- kch->cb (kch->cb_cls,
- ks);
+ gkch->cb (gkch->cb_cls,
+ res);
}
else
{
- kch->cb (kch->cb_cls,
- ks);
+ gkch->cb (gkch->cb_cls,
+ res);
}
GNUNET_JSON_parse_free (spec);
return GNUNET_OK;
@@ -141,9 +185,9 @@ parse_account_status (
/**
* Function called when we're done processing the
- * HTTP /kyc-check request.
+ * HTTP GET /kyc-check/$H_NORMALIZED_PAYTO request.
*
- * @param cls the `struct TALER_EXCHANGE_KycCheckHandle`
+ * @param cls the `struct TALER_EXCHANGE_GetKycCheckHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
@@ -152,14 +196,14 @@ handle_kyc_check_finished (void *cls,
long response_code,
const void *response)
{
- struct TALER_EXCHANGE_KycCheckHandle *kch = cls;
+ struct TALER_EXCHANGE_GetKycCheckHandle *gkch = cls;
const json_t *j = response;
- struct TALER_EXCHANGE_KycStatus ks = {
+ struct TALER_EXCHANGE_GetKycCheckResponse ks = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
- kch->job = NULL;
+ gkch->job = NULL;
switch (response_code)
{
case 0:
@@ -168,7 +212,7 @@ handle_kyc_check_finished (void *cls,
case MHD_HTTP_OK:
{
if (GNUNET_OK !=
- parse_account_status (kch,
+ parse_account_status (gkch,
j,
&ks,
&ks.details.ok))
@@ -178,13 +222,13 @@ handle_kyc_check_finished (void *cls,
ks.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
- TALER_EXCHANGE_kyc_check_cancel (kch);
+ TALER_EXCHANGE_get_kyc_check_cancel (gkch);
return;
}
case MHD_HTTP_ACCEPTED:
{
if (GNUNET_OK !=
- parse_account_status (kch,
+ parse_account_status (gkch,
j,
&ks,
&ks.details.accepted))
@@ -194,15 +238,13 @@ handle_kyc_check_finished (void *cls,
ks.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
- TALER_EXCHANGE_kyc_check_cancel (kch);
+ TALER_EXCHANGE_get_kyc_check_cancel (gkch);
return;
}
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_BAD_REQUEST:
ks.hr.ec = TALER_JSON_get_error_code (j);
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
break;
case MHD_HTTP_FORBIDDEN:
{
@@ -235,8 +277,6 @@ handle_kyc_check_finished (void *cls,
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
ks.hr.ec = TALER_JSON_get_error_code (j);
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
break;
default:
/* unexpected response code */
@@ -248,25 +288,72 @@ handle_kyc_check_finished (void *cls,
(int) ks.hr.ec);
break;
}
- kch->cb (kch->cb_cls,
- &ks);
- TALER_EXCHANGE_kyc_check_cancel (kch);
+ if (NULL != gkch->cb)
+ {
+ gkch->cb (gkch->cb_cls,
+ &ks);
+ gkch->cb = NULL;
+ }
+ TALER_EXCHANGE_get_kyc_check_cancel (gkch);
}
-struct TALER_EXCHANGE_KycCheckHandle *
-TALER_EXCHANGE_kyc_check (
+struct TALER_EXCHANGE_GetKycCheckHandle *
+TALER_EXCHANGE_get_kyc_check_create (
struct GNUNET_CURL_Context *ctx,
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,
- void *cb_cls)
+ const union TALER_AccountPrivateKeyP *pk)
+{
+ struct TALER_EXCHANGE_GetKycCheckHandle *gkch;
+
+ gkch = GNUNET_new (struct TALER_EXCHANGE_GetKycCheckHandle);
+ gkch->ctx = ctx;
+ gkch->base_url = GNUNET_strdup (url);
+ gkch->h_payto = *h_payto;
+ gkch->account_priv = *pk;
+ return gkch;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_get_kyc_check_set_options_ (
+ struct TALER_EXCHANGE_GetKycCheckHandle *gkch,
+ unsigned int num_options,
+ const struct TALER_EXCHANGE_GetKycCheckOptionValue *options)
+{
+ for (unsigned int i = 0; i < num_options; i++)
+ {
+ const struct TALER_EXCHANGE_GetKycCheckOptionValue *opt = &options[i];
+
+ switch (opt->option)
+ {
+ case TALER_EXCHANGE_GET_KYC_CHECK_OPTION_END:
+ return GNUNET_OK;
+ case TALER_EXCHANGE_GET_KYC_CHECK_OPTION_KNOWN_RULE_GEN:
+ gkch->known_rule_gen = opt->details.known_rule_gen;
+ break;
+ case TALER_EXCHANGE_GET_KYC_CHECK_OPTION_LPT:
+ gkch->lpt = opt->details.lpt;
+ break;
+ case TALER_EXCHANGE_GET_KYC_CHECK_OPTION_TIMEOUT:
+ gkch->timeout = opt->details.timeout;
+ break;
+ default:
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_get_kyc_check_start (
+ struct TALER_EXCHANGE_GetKycCheckHandle *gkch,
+ TALER_EXCHANGE_GetKycCheckCallback cb,
+ TALER_EXCHANGE_GET_KYC_CHECK_RESULT_CLOSURE *cb_cls)
{
- struct TALER_EXCHANGE_KycCheckHandle *kch;
CURL *eh;
char arg_str[128];
char timeout_ms[32];
@@ -275,19 +362,21 @@ TALER_EXCHANGE_kyc_check (
struct curl_slist *job_headers = NULL;
unsigned long long tms;
+ gkch->cb = cb;
+ gkch->cb_cls = cb_cls;
{
char *hps;
hps = GNUNET_STRINGS_data_to_string_alloc (
- h_payto,
- sizeof (*h_payto));
+ &gkch->h_payto,
+ sizeof (gkch->h_payto));
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"kyc-check/%s",
hps);
GNUNET_free (hps);
}
- tms = timeout.rel_value_us
+ tms = gkch->timeout.rel_value_us
/ GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
GNUNET_snprintf (timeout_ms,
sizeof (timeout_ms),
@@ -296,43 +385,37 @@ TALER_EXCHANGE_kyc_check (
GNUNET_snprintf (krg_str,
sizeof (krg_str),
"%llu",
- (unsigned long long) known_rule_gen);
+ (unsigned long long) gkch->known_rule_gen);
GNUNET_snprintf (lpt_str,
sizeof (lpt_str),
"%d",
- (int) lpt);
- kch = GNUNET_new (struct TALER_EXCHANGE_KycCheckHandle);
- kch->cb = cb;
- kch->cb_cls = cb_cls;
- kch->url
+ (int) gkch->lpt);
+ gkch->url
= TALER_url_join (
- url,
+ gkch->base_url,
arg_str,
"timeout_ms",
- GNUNET_TIME_relative_is_zero (timeout)
+ GNUNET_TIME_relative_is_zero (gkch->timeout)
? NULL
: timeout_ms,
"min_rule",
- 0 == known_rule_gen
+ 0 == gkch->known_rule_gen
? NULL
: krg_str,
"lpt",
- TALER_EXCHANGE_KLPT_NONE == lpt
+ TALER_EXCHANGE_KLPT_NONE == gkch->lpt
? NULL
: lpt_str,
NULL);
- if (NULL == kch->url)
- {
- GNUNET_free (kch);
- return NULL;
- }
- eh = TALER_EXCHANGE_curl_easy_get_ (kch->url);
+ if (NULL == gkch->url)
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
+ eh = TALER_EXCHANGE_curl_easy_get_ (gkch->url);
if (NULL == eh)
{
GNUNET_break (0);
- GNUNET_free (kch->url);
- GNUNET_free (kch);
- return NULL;
+ GNUNET_free (gkch->url);
+ gkch->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
if (0 != tms)
{
@@ -353,9 +436,9 @@ TALER_EXCHANGE_kyc_check (
char *hdr;
GNUNET_CRYPTO_eddsa_key_get_public (
- &account_priv->reserve_priv.eddsa_priv,
+ &gkch->account_priv.reserve_priv.eddsa_priv,
&account_pub.reserve_pub.eddsa_pub);
- TALER_account_kyc_auth_sign (account_priv,
+ TALER_account_kyc_auth_sign (&gkch->account_priv,
&account_sig);
sig_hdr = GNUNET_STRINGS_data_to_string_alloc (
@@ -385,31 +468,41 @@ TALER_EXCHANGE_kyc_check (
{
GNUNET_break (0);
curl_easy_cleanup (eh);
- return NULL;
+ GNUNET_free (gkch->url);
+ gkch->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
}
- kch->job
- = GNUNET_CURL_job_add2 (ctx,
+ gkch->job
+ = GNUNET_CURL_job_add2 (gkch->ctx,
eh,
job_headers,
&handle_kyc_check_finished,
- kch);
+ gkch);
curl_slist_free_all (job_headers);
- return kch;
+ if (NULL == gkch->job)
+ {
+ GNUNET_free (gkch->url);
+ gkch->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ }
+ return TALER_EC_NONE;
}
void
-TALER_EXCHANGE_kyc_check_cancel (struct TALER_EXCHANGE_KycCheckHandle *kch)
+TALER_EXCHANGE_get_kyc_check_cancel (
+ struct TALER_EXCHANGE_GetKycCheckHandle *gkch)
{
- if (NULL != kch->job)
+ if (NULL != gkch->job)
{
- GNUNET_CURL_job_cancel (kch->job);
- kch->job = NULL;
+ GNUNET_CURL_job_cancel (gkch->job);
+ gkch->job = NULL;
}
- GNUNET_free (kch->url);
- GNUNET_free (kch);
+ GNUNET_free (gkch->url);
+ GNUNET_free (gkch->base_url);
+ GNUNET_free (gkch);
}
-/* end of exchange_api_kyc_check.c */
+/* end of exchange_api_get-kyc-check-H_NORMALIZED_PAYTO.c */
diff --git a/src/lib/exchange_api_get-kyc-info-ACCESS_TOKEN.c b/src/lib/exchange_api_get-kyc-info-ACCESS_TOKEN.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2015-2023 Taler Systems SA
+ Copyright (C) 2015-2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -25,19 +25,24 @@
#include <gnunet/gnunet_curl_lib.h>
#include "taler/taler_exchange_service.h"
#include "taler/taler_json_lib.h"
-#include "exchange_api_handle.h"
+#include "taler/taler-exchange/get-kyc-info-ACCESS_TOKEN.h"
#include "taler/taler_signatures.h"
#include "exchange_api_curl_defaults.h"
/**
- * @brief A /kyc-info Handle
+ * @brief A GET /kyc-info/$AT handle
*/
-struct TALER_EXCHANGE_KycInfoHandle
+struct TALER_EXCHANGE_GetKycInfoHandle
{
/**
- * The url for this request.
+ * The base URL for this request.
+ */
+ char *base_url;
+
+ /**
+ * The full URL for this request, set during _start.
*/
char *url;
@@ -49,31 +54,51 @@ struct TALER_EXCHANGE_KycInfoHandle
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_KycInfoCallback kyc_info_cb;
+ TALER_EXCHANGE_GetKycInfoCallback cb;
/**
* Closure for @e cb.
*/
- void *kyc_info_cb_cls;
+ TALER_EXCHANGE_GET_KYC_INFO_RESULT_CLOSURE *cb_cls;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Access token for the KYC process.
+ */
+ struct TALER_AccountAccessTokenP token;
+
+ /**
+ * ETag from a previous response for conditional requests.
+ * Borrowed pointer, not owned.
+ */
+ const char *if_none_match;
+
+ /**
+ * Long polling timeout.
+ */
+ struct GNUNET_TIME_Relative timeout;
};
/**
- * Parse the provided kyc_infoage data from the "200 OK" response
- * for one of the coins.
+ * Parse the provided kyc-info data from the "200 OK" response.
*
- * @param[in,out] lh kyc_info handle (callback may be zero'ed out)
- * @param json json reply with the data for one coin
+ * @param[in,out] lh handle (callback may be zero'ed out)
+ * @param json json reply with the data
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static enum GNUNET_GenericReturnValue
-parse_kyc_info_ok (struct TALER_EXCHANGE_KycInfoHandle *lh,
+parse_kyc_info_ok (struct TALER_EXCHANGE_GetKycInfoHandle *lh,
const json_t *json)
{
const json_t *jrequirements = NULL;
const json_t *jvoluntary_checks = NULL;
- struct TALER_EXCHANGE_KycProcessClientInformation lr = {
+ struct TALER_EXCHANGE_GetKycInfoResponse lr = {
.hr.reply = json,
.hr.http_status = MHD_HTTP_OK
};
@@ -98,22 +123,8 @@ parse_kyc_info_ok (struct TALER_EXCHANGE_KycInfoHandle *lh,
return GNUNET_SYSERR;
}
- lr.details.ok.vci_length
- = (unsigned int) json_object_size (jvoluntary_checks);
- if ( ((size_t) lr.details.ok.vci_length)
- != json_object_size (jvoluntary_checks))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- lr.details.ok.requirements_length
- = json_array_size (jrequirements);
- if ( ((size_t) lr.details.ok.requirements_length)
- != json_array_size (jrequirements))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
+ lr.details.ok.vci_length = json_object_size (jvoluntary_checks);
+ lr.details.ok.requirements_length = json_array_size (jrequirements);
{
struct TALER_EXCHANGE_VoluntaryCheckInformation vci[
@@ -190,9 +201,9 @@ parse_kyc_info_ok (struct TALER_EXCHANGE_KycInfoHandle *lh,
lr.details.ok.vci = vci;
lr.details.ok.requirements = requirements;
- lh->kyc_info_cb (lh->kyc_info_cb_cls,
- &lr);
- lh->kyc_info_cb = NULL;
+ lh->cb (lh->cb_cls,
+ &lr);
+ lh->cb = NULL;
return GNUNET_OK;
}
}
@@ -200,9 +211,9 @@ parse_kyc_info_ok (struct TALER_EXCHANGE_KycInfoHandle *lh,
/**
* Function called when we're done processing the
- * HTTP /kyc-info/$AT request.
+ * HTTP GET /kyc-info/$AT request.
*
- * @param cls the `struct TALER_EXCHANGE_KycInfoHandle`
+ * @param cls the `struct TALER_EXCHANGE_GetKycInfoHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
@@ -211,9 +222,9 @@ handle_kyc_info_finished (void *cls,
long response_code,
const void *response)
{
- struct TALER_EXCHANGE_KycInfoHandle *lh = cls;
+ struct TALER_EXCHANGE_GetKycInfoHandle *lh = cls;
const json_t *j = response;
- struct TALER_EXCHANGE_KycProcessClientInformation lr = {
+ struct TALER_EXCHANGE_GetKycInfoResponse lr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
@@ -234,16 +245,14 @@ handle_kyc_info_finished (void *cls,
lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
- GNUNET_assert (NULL == lh->kyc_info_cb);
- TALER_EXCHANGE_kyc_info_cancel (lh);
+ GNUNET_assert (NULL == lh->cb);
+ TALER_EXCHANGE_get_kyc_info_cancel (lh);
return;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_BAD_REQUEST:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
break;
case MHD_HTTP_FORBIDDEN:
lr.hr.ec = TALER_JSON_get_error_code (j);
@@ -252,14 +261,10 @@ handle_kyc_info_finished (void *cls,
case MHD_HTTP_NOT_FOUND:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, exchange says this coin was not melted; we
- should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
lr.hr.ec = TALER_JSON_get_error_code (j);
lr.hr.hint = TALER_JSON_get_error_hint (j);
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
break;
default:
/* unexpected response code */
@@ -272,38 +277,80 @@ handle_kyc_info_finished (void *cls,
(int) lr.hr.ec);
break;
}
- if (NULL != lh->kyc_info_cb)
- lh->kyc_info_cb (lh->kyc_info_cb_cls,
- &lr);
- TALER_EXCHANGE_kyc_info_cancel (lh);
+ if (NULL != lh->cb)
+ lh->cb (lh->cb_cls,
+ &lr);
+ TALER_EXCHANGE_get_kyc_info_cancel (lh);
}
-struct TALER_EXCHANGE_KycInfoHandle *
-TALER_EXCHANGE_kyc_info (
+struct TALER_EXCHANGE_GetKycInfoHandle *
+TALER_EXCHANGE_get_kyc_info_create (
struct GNUNET_CURL_Context *ctx,
const char *url,
- const struct TALER_AccountAccessTokenP *token,
- const char *if_none_match,
- struct GNUNET_TIME_Relative timeout,
- TALER_EXCHANGE_KycInfoCallback cb,
- void *cb_cls)
+ const struct TALER_AccountAccessTokenP *token)
+{
+ struct TALER_EXCHANGE_GetKycInfoHandle *lh;
+
+ lh = GNUNET_new (struct TALER_EXCHANGE_GetKycInfoHandle);
+ lh->ctx = ctx;
+ lh->base_url = GNUNET_strdup (url);
+ lh->token = *token;
+ return lh;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_get_kyc_info_set_options_ (
+ struct TALER_EXCHANGE_GetKycInfoHandle *gkih,
+ unsigned int num_options,
+ const struct TALER_EXCHANGE_GetKycInfoOptionValue *options)
+{
+ for (unsigned int i = 0; i < num_options; i++)
+ {
+ const struct TALER_EXCHANGE_GetKycInfoOptionValue *opt = &options[i];
+
+ switch (opt->option)
+ {
+ case TALER_EXCHANGE_GET_KYC_INFO_OPTION_END:
+ return GNUNET_OK;
+ case TALER_EXCHANGE_GET_KYC_INFO_OPTION_IF_NONE_MATCH:
+ gkih->if_none_match = opt->details.if_none_match;
+ break;
+ case TALER_EXCHANGE_GET_KYC_INFO_OPTION_TIMEOUT:
+ gkih->timeout = opt->details.timeout;
+ break;
+ default:
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_get_kyc_info_start (
+ struct TALER_EXCHANGE_GetKycInfoHandle *gkih,
+ TALER_EXCHANGE_GetKycInfoCallback cb,
+ TALER_EXCHANGE_GET_KYC_INFO_RESULT_CLOSURE *cb_cls)
{
- struct TALER_EXCHANGE_KycInfoHandle *lh;
CURL *eh;
char arg_str[sizeof (struct TALER_AccountAccessTokenP) * 2 + 32];
- unsigned int tms
- = (unsigned int) timeout.rel_value_us
- / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
+ unsigned int tms;
struct curl_slist *job_headers = NULL;
+ gkih->cb = cb;
+ gkih->cb_cls = cb_cls;
+ tms = (unsigned int) (gkih->timeout.rel_value_us
+ / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
{
char at_str[sizeof (struct TALER_AccountAccessTokenP) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (
- token,
- sizeof (*token),
+ &gkih->token,
+ sizeof (gkih->token),
at_str,
sizeof (at_str));
*end = '\0';
@@ -312,9 +359,6 @@ TALER_EXCHANGE_kyc_info (
"kyc-info/%s",
at_str);
}
- lh = GNUNET_new (struct TALER_EXCHANGE_KycInfoHandle);
- lh->kyc_info_cb = cb;
- lh->kyc_info_cb_cls = cb_cls;
{
char timeout_str[32];
@@ -322,26 +366,23 @@ TALER_EXCHANGE_kyc_info (
sizeof (timeout_str),
"%u",
tms);
- lh->url = TALER_url_join (url,
- arg_str,
- "timeout_ms",
- (0 == tms)
- ? NULL
- : timeout_str,
- NULL);
- }
- if (NULL == lh->url)
- {
- GNUNET_free (lh);
- return NULL;
+ gkih->url = TALER_url_join (gkih->base_url,
+ arg_str,
+ "timeout_ms",
+ (0 == tms)
+ ? NULL
+ : timeout_str,
+ NULL);
}
- eh = TALER_EXCHANGE_curl_easy_get_ (lh->url);
+ if (NULL == gkih->url)
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
+ eh = TALER_EXCHANGE_curl_easy_get_ (gkih->url);
if (NULL == eh)
{
GNUNET_break (0);
- GNUNET_free (lh->url);
- GNUNET_free (lh);
- return NULL;
+ GNUNET_free (gkih->url);
+ gkih->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
if (0 != tms)
{
@@ -350,43 +391,49 @@ TALER_EXCHANGE_kyc_info (
CURLOPT_TIMEOUT_MS,
(long) (tms + 100L)));
}
-
job_headers = curl_slist_append (job_headers,
"Content-Type: application/json");
- if (NULL != if_none_match)
+ if (NULL != gkih->if_none_match)
{
char *hdr;
GNUNET_asprintf (&hdr,
"%s: %s",
MHD_HTTP_HEADER_IF_NONE_MATCH,
- if_none_match);
+ gkih->if_none_match);
job_headers = curl_slist_append (job_headers,
hdr);
GNUNET_free (hdr);
}
- lh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- job_headers,
- &handle_kyc_info_finished,
- lh);
+ gkih->job = GNUNET_CURL_job_add2 (gkih->ctx,
+ eh,
+ job_headers,
+ &handle_kyc_info_finished,
+ gkih);
curl_slist_free_all (job_headers);
- return lh;
+ if (NULL == gkih->job)
+ {
+ GNUNET_free (gkih->url);
+ gkih->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ }
+ return TALER_EC_NONE;
}
void
-TALER_EXCHANGE_kyc_info_cancel (struct TALER_EXCHANGE_KycInfoHandle *lh)
+TALER_EXCHANGE_get_kyc_info_cancel (
+ struct TALER_EXCHANGE_GetKycInfoHandle *gkih)
{
- if (NULL != lh->job)
+ if (NULL != gkih->job)
{
- GNUNET_CURL_job_cancel (lh->job);
- lh->job = NULL;
+ GNUNET_CURL_job_cancel (gkih->job);
+ gkih->job = NULL;
}
-
- GNUNET_free (lh->url);
- GNUNET_free (lh);
+ GNUNET_free (gkih->url);
+ GNUNET_free (gkih->base_url);
+ GNUNET_free (gkih);
}
-/* end of exchange_api_kyc_info.c */
+/* end of exchange_api_get-kyc-info-ACCESS_TOKEN.c */
diff --git a/src/lib/exchange_api_get-kyc-proof-PROVIDER_NAME.c b/src/lib/exchange_api_get-kyc-proof-PROVIDER_NAME.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021, 2022 Taler Systems SA
+ Copyright (C) 2021, 2022, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -28,16 +28,22 @@
#include "exchange_api_handle.h"
#include "taler/taler_signatures.h"
#include "exchange_api_curl_defaults.h"
+#include "taler/taler-exchange/get-kyc-proof-PROVIDER_NAME.h"
/**
- * @brief A ``/kyc-proof`` handle
+ * @brief A handle for GET /kyc-proof/$PROVIDER_NAME
*/
-struct TALER_EXCHANGE_KycProofHandle
+struct TALER_EXCHANGE_GetKycProofHandle
{
/**
- * The url for this request.
+ * The base URL of the exchange.
+ */
+ char *base_url;
+
+ /**
+ * The full URL for this request.
*/
char *url;
@@ -54,39 +60,61 @@ struct TALER_EXCHANGE_KycProofHandle
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_KycProofCallback cb;
+ TALER_EXCHANGE_GetKycProofCallback cb;
/**
* Closure for @e cb.
*/
- void *cb_cls;
+ TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE *cb_cls;
+
+ /**
+ * CURL context to use.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Hash of the payto URI identifying the target account.
+ */
+ struct TALER_NormalizedPaytoHashP h_payto;
+
+ /**
+ * Name of the KYC logic / provider. Heap-allocated copy.
+ */
+ char *logic;
+
+ /**
+ * Additional query string arguments to append to the URL.
+ * Borrowed pointer (not owned), must start with '&'.
+ * NULL if not set.
+ */
+ const char *args;
};
/**
* Function called when we're done processing the
- * HTTP /kyc-proof request.
+ * HTTP GET /kyc-proof request.
*
- * @param cls the `struct TALER_EXCHANGE_KycProofHandle`
+ * @param cls the `struct TALER_EXCHANGE_GetKycProofHandle`
* @param response_code HTTP response code, 0 on error
* @param body response body
* @param body_size number of bytes in @a body
*/
static void
-handle_kyc_proof_finished (void *cls,
- long response_code,
- const void *body,
- size_t body_size)
+handle_get_kyc_proof_finished (void *cls,
+ long response_code,
+ const void *body,
+ size_t body_size)
{
- struct TALER_EXCHANGE_KycProofHandle *kph = cls;
- struct TALER_EXCHANGE_KycProofResponse kpr = {
+ struct TALER_EXCHANGE_GetKycProofHandle *gkph = cls;
+ struct TALER_EXCHANGE_GetKycProofResponse gkpr = {
.hr.http_status = (unsigned int) response_code
};
(void) body;
(void) body_size;
- kph->job = NULL;
+ gkph->job = NULL;
switch (response_code)
{
case 0:
@@ -96,10 +124,10 @@ handle_kyc_proof_finished (void *cls,
char *redirect_url;
GNUNET_assert (CURLE_OK ==
- curl_easy_getinfo (kph->eh,
+ curl_easy_getinfo (gkph->eh,
CURLINFO_REDIRECT_URL,
&redirect_url));
- kpr.details.found.redirect_url = redirect_url;
+ gkpr.details.found.redirect_url = redirect_url;
break;
}
case MHD_HTTP_BAD_REQUEST:
@@ -124,94 +152,138 @@ handle_kyc_proof_finished (void *cls,
/* unexpected response code */
GNUNET_break_op (0);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u for exchange kyc_proof\n",
+ "Unexpected response code %u for exchange get_kyc_proof\n",
(unsigned int) response_code);
break;
}
- kph->cb (kph->cb_cls,
- &kpr);
- TALER_EXCHANGE_kyc_proof_cancel (kph);
+ gkph->cb (gkph->cb_cls,
+ &gkpr);
+ TALER_EXCHANGE_get_kyc_proof_cancel (gkph);
}
-struct TALER_EXCHANGE_KycProofHandle *
-TALER_EXCHANGE_kyc_proof (
+struct TALER_EXCHANGE_GetKycProofHandle *
+TALER_EXCHANGE_get_kyc_proof_create (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_NormalizedPaytoHashP *h_payto,
- const char *logic,
- const char *args,
- TALER_EXCHANGE_KycProofCallback cb,
- void *cb_cls)
+ const char *logic)
+{
+ struct TALER_EXCHANGE_GetKycProofHandle *gkph;
+
+ gkph = GNUNET_new (struct TALER_EXCHANGE_GetKycProofHandle);
+ gkph->ctx = ctx;
+ gkph->base_url = GNUNET_strdup (url);
+ gkph->h_payto = *h_payto;
+ gkph->logic = GNUNET_strdup (logic);
+ return gkph;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_get_kyc_proof_set_options_ (
+ struct TALER_EXCHANGE_GetKycProofHandle *gkph,
+ unsigned int num_options,
+ const struct TALER_EXCHANGE_GetKycProofOptionValue *options)
+{
+ for (unsigned int i = 0; i < num_options; i++)
+ {
+ const struct TALER_EXCHANGE_GetKycProofOptionValue *opt = &options[i];
+
+ switch (opt->option)
+ {
+ case TALER_EXCHANGE_GET_KYC_PROOF_OPTION_END:
+ return GNUNET_OK;
+ case TALER_EXCHANGE_GET_KYC_PROOF_OPTION_ARGS:
+ GNUNET_assert (opt->details.args[0] == '&');
+ gkph->args = opt->details.args;
+ break;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_get_kyc_proof_start (
+ struct TALER_EXCHANGE_GetKycProofHandle *gkph,
+ TALER_EXCHANGE_GetKycProofCallback cb,
+ TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE *cb_cls)
{
- struct TALER_EXCHANGE_KycProofHandle *kph;
char *arg_str;
- if (NULL == args)
- args = "";
- else
- GNUNET_assert (args[0] == '&');
+ if (NULL != gkph->job)
+ {
+ GNUNET_break (0);
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ }
+ gkph->cb = cb;
+ gkph->cb_cls = cb_cls;
{
- char hstr[sizeof (*h_payto) * 2];
+ char hstr[sizeof (gkph->h_payto) * 2];
char *end;
- end = GNUNET_STRINGS_data_to_string (h_payto,
- sizeof (*h_payto),
+ end = GNUNET_STRINGS_data_to_string (&gkph->h_payto,
+ sizeof (gkph->h_payto),
hstr,
sizeof (hstr));
*end = '\0';
GNUNET_asprintf (&arg_str,
"kyc-proof/%s?state=%s%s",
- logic,
+ gkph->logic,
hstr,
- args);
+ (NULL != gkph->args) ? gkph->args : "");
}
- kph = GNUNET_new (struct TALER_EXCHANGE_KycProofHandle);
- kph->cb = cb;
- kph->cb_cls = cb_cls;
- kph->url = TALER_url_join (url,
- arg_str,
- NULL);
+ gkph->url = TALER_url_join (gkph->base_url,
+ arg_str,
+ NULL);
GNUNET_free (arg_str);
- if (NULL == kph->url)
- {
- GNUNET_free (kph);
- return NULL;
- }
- kph->eh = TALER_EXCHANGE_curl_easy_get_ (kph->url);
- if (NULL == kph->eh)
+ if (NULL == gkph->url)
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
+ gkph->eh = TALER_EXCHANGE_curl_easy_get_ (gkph->url);
+ if (NULL == gkph->eh)
{
GNUNET_break (0);
- GNUNET_free (kph->url);
- GNUNET_free (kph);
- return NULL;
+ GNUNET_free (gkph->url);
+ gkph->url = NULL;
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
}
/* disable location following, we want to learn the
result of a 303 redirect! */
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (kph->eh,
- CURLOPT_FOLLOWLOCATION,
- 0L));
- kph->job = GNUNET_CURL_job_add_raw (ctx,
- kph->eh,
- NULL,
- &handle_kyc_proof_finished,
- kph);
- return kph;
+ curl_easy_setopt (gkph->eh,
+ CURLOPT_FOLLOWLOCATION,
+ 0L);
+ gkph->job = GNUNET_CURL_job_add_raw (gkph->ctx,
+ gkph->eh,
+ NULL,
+ &handle_get_kyc_proof_finished,
+ gkph);
+ if (NULL == gkph->job)
+ {
+ curl_easy_cleanup (gkph->eh);
+ gkph->eh = NULL;
+ GNUNET_free (gkph->url);
+ gkph->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ }
+ return TALER_EC_NONE;
}
void
-TALER_EXCHANGE_kyc_proof_cancel (struct TALER_EXCHANGE_KycProofHandle *kph)
+TALER_EXCHANGE_get_kyc_proof_cancel (
+ struct TALER_EXCHANGE_GetKycProofHandle *gkph)
{
- if (NULL != kph->job)
+ if (NULL != gkph->job)
{
- GNUNET_CURL_job_cancel (kph->job);
- kph->job = NULL;
+ GNUNET_CURL_job_cancel (gkph->job);
+ gkph->job = NULL;
}
- GNUNET_free (kph->url);
- GNUNET_free (kph);
+ GNUNET_free (gkph->url);
+ GNUNET_free (gkph->logic);
+ GNUNET_free (gkph->base_url);
+ GNUNET_free (gkph);
}
-/* end of exchange_api_kyc_proof.c */
+/* end of exchange_api_get-kyc-proof-PROVIDER_NAME.c */
diff --git a/src/lib/exchange_api_post-aml-OFFICER_PUB-decision.c b/src/lib/exchange_api_post-aml-OFFICER_PUB-decision.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023, 2024 Taler Systems SA
+ Copyright (C) 2023, 2024, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -24,17 +24,25 @@
#include <microhttpd.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler/taler_exchange_service.h"
+#include "taler/taler-exchange/post-aml-OFFICER_PUB-decision.h"
#include "exchange_api_curl_defaults.h"
#include "taler/taler_signatures.h"
#include "taler/taler_curl_lib.h"
-#include "taler/taler_json_lib.h"
-struct TALER_EXCHANGE_AddAmlDecision
+/**
+ * @brief A POST /aml/$OFFICER_PUB/decision Handle
+ */
+struct TALER_EXCHANGE_PostAmlDecisionHandle
{
/**
- * The url for this request.
+ * The base URL of the exchange.
+ */
+ char *base_url;
+
+ /**
+ * The full URL for this request.
*/
char *url;
@@ -51,17 +59,76 @@ struct TALER_EXCHANGE_AddAmlDecision
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_AddAmlDecisionCallback cb;
+ TALER_EXCHANGE_PostAmlDecisionCallback cb;
/**
- * Closure for @a cb.
+ * Closure for @e cb.
*/
- void *cb_cls;
+ TALER_EXCHANGE_POST_AML_DECISION_RESULT_CLOSURE *cb_cls;
/**
* Reference to the execution context.
*/
struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Public key of the AML officer.
+ */
+ struct TALER_AmlOfficerPublicKeyP officer_pub;
+
+ /**
+ * Private key of the AML officer.
+ */
+ struct TALER_AmlOfficerPrivateKeyP officer_priv;
+
+ /**
+ * Hash of the payto URI of the account the decision is about.
+ */
+ struct TALER_NormalizedPaytoHashP h_payto;
+
+ /**
+ * When was the decision made.
+ */
+ struct GNUNET_TIME_Timestamp decision_time;
+
+ /**
+ * Human-readable justification.
+ */
+ char *justification;
+
+ /**
+ * True to keep the investigation open.
+ */
+ bool keep_investigating;
+
+ /**
+ * Pre-built new_rules JSON object.
+ */
+ json_t *new_rules;
+
+ /**
+ * Optional: full payto URI string, may be NULL.
+ */
+ char *payto_uri_str;
+
+ /**
+ * Optional: space-separated list of measures to trigger immediately
+ * (from options, may be NULL).
+ */
+ char *new_measures;
+
+ /**
+ * Optional: JSON object with account properties
+ * (from options, may be NULL).
+ */
+ json_t *properties;
+
+ /**
+ * Optional: JSON array of events to trigger
+ * (from options; may be NULL).
+ */
+ json_t *jevents;
+
};
@@ -69,114 +136,93 @@ struct TALER_EXCHANGE_AddAmlDecision
* Function called when we're done processing the
* HTTP POST /aml/$OFFICER_PUB/decision request.
*
- * @param cls the `struct TALER_EXCHANGE_AddAmlDecision *`
+ * @param cls the `struct TALER_EXCHANGE_PostAmlDecisionHandle *`
* @param response_code HTTP response code, 0 on error
* @param response response body, NULL if not in JSON
*/
static void
-handle_add_aml_decision_finished (void *cls,
- long response_code,
- const void *response)
+handle_post_aml_decision_finished (void *cls,
+ long response_code,
+ const void *response)
{
- struct TALER_EXCHANGE_AddAmlDecision *wh = cls;
+ struct TALER_EXCHANGE_PostAmlDecisionHandle *padh = cls;
const json_t *json = response;
- struct TALER_EXCHANGE_AddAmlDecisionResponse adr = {
+ struct TALER_EXCHANGE_PostAmlDecisionResponse pr = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
- wh->job = NULL;
+ padh->job = NULL;
switch (response_code)
{
case 0:
- /* no reply */
- adr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- adr.hr.hint = "server offline?";
+ pr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+ pr.hr.hint = "server offline?";
break;
case MHD_HTTP_NO_CONTENT:
break;
case MHD_HTTP_FORBIDDEN:
- adr.hr.ec = TALER_JSON_get_error_code (json);
- adr.hr.hint = TALER_JSON_get_error_hint (json);
+ pr.hr.ec = TALER_JSON_get_error_code (json);
+ pr.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_CONFLICT:
- adr.hr.ec = TALER_JSON_get_error_code (json);
- adr.hr.hint = TALER_JSON_get_error_hint (json);
+ pr.hr.ec = TALER_JSON_get_error_code (json);
+ pr.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
- /* unexpected response code */
GNUNET_break_op (0);
- adr.hr.ec = TALER_JSON_get_error_code (json);
- adr.hr.hint = TALER_JSON_get_error_hint (json);
+ pr.hr.ec = TALER_JSON_get_error_code (json);
+ pr.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for exchange AML decision\n",
+ "Unexpected response code %u/%d for POST AML decision\n",
(unsigned int) response_code,
- (int) adr.hr.ec);
+ (int) pr.hr.ec);
break;
}
- if (NULL != wh->cb)
+ if (NULL != padh->cb)
{
- wh->cb (wh->cb_cls,
- &adr);
- wh->cb = NULL;
+ padh->cb (padh->cb_cls,
+ &pr);
+ padh->cb = NULL;
}
- TALER_EXCHANGE_post_aml_decision_cancel (wh);
+ TALER_EXCHANGE_post_aml_decision_cancel (padh);
}
-struct TALER_EXCHANGE_AddAmlDecision *
-TALER_EXCHANGE_post_aml_decision (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const struct TALER_FullPayto payto_uri,
- struct GNUNET_TIME_Timestamp decision_time,
+/**
+ * Build the new_rules JSON object from rules and measures arrays.
+ *
+ * @param successor_measure optional successor measure name
+ * @param expiration_time when the new rules expire
+ * @param num_rules length of @a rules
+ * @param rules the rules array
+ * @param num_measures length of @a measures
+ * @param measures the measures array
+ * @return new JSON object (caller owns reference), NULL on error
+ */
+static json_t *
+build_new_rules (
const char *successor_measure,
- const char *new_measures,
struct GNUNET_TIME_Timestamp expiration_time,
unsigned int num_rules,
- const struct TALER_EXCHANGE_AccountRule *rules,
+ const struct TALER_EXCHANGE_AccountRule rules[static num_rules],
unsigned int num_measures,
- const struct TALER_EXCHANGE_MeasureInformation *measures,
- const json_t *properties,
- bool keep_investigating,
- const char *justification,
- const struct TALER_AmlOfficerPrivateKeyP *officer_priv,
- unsigned int num_events,
- const char **events,
- TALER_EXCHANGE_AddAmlDecisionCallback cb,
- void *cb_cls)
+ const struct TALER_EXCHANGE_MeasureInformation measures[static num_measures])
{
- struct TALER_AmlOfficerPublicKeyP officer_pub;
- struct TALER_AmlOfficerSignatureP officer_sig;
- struct TALER_EXCHANGE_AddAmlDecision *wh;
- CURL *eh;
- json_t *body;
- json_t *new_rules;
json_t *jrules;
json_t *jmeasures;
- json_t *jevents = NULL;
- if (0 != num_events)
- {
- jevents = json_array ();
- GNUNET_assert (NULL != jevents);
- for (unsigned int i = 0; i<num_events; i++)
- GNUNET_assert (0 ==
- json_array_append_new (jevents,
- json_string (events[i])));
- }
jrules = json_array ();
GNUNET_assert (NULL != jrules);
- for (unsigned int i = 0; i<num_rules; i++)
+ for (unsigned int i = 0; i < num_rules; i++)
{
const struct TALER_EXCHANGE_AccountRule *al = &rules[i];
- json_t *rule;
json_t *ameasures;
+ json_t *rule;
ameasures = json_array ();
GNUNET_assert (NULL != ameasures);
- for (unsigned int j = 0; j<al->num_measures; j++)
+ for (unsigned int j = 0; j < al->num_measures; j++)
GNUNET_assert (0 ==
json_array_append_new (ameasures,
json_string (al->measures[j])));
@@ -189,9 +235,6 @@ TALER_EXCHANGE_post_aml_decision (
al->timeframe),
GNUNET_JSON_pack_array_steal ("measures",
ameasures),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_array_steal ("events",
- jevents)),
GNUNET_JSON_pack_bool ("exposed",
al->exposed),
GNUNET_JSON_pack_bool ("is_and_combinator",
@@ -206,7 +249,7 @@ TALER_EXCHANGE_post_aml_decision (
jmeasures = json_object ();
GNUNET_assert (NULL != jmeasures);
- for (unsigned int i = 0; i<num_measures; i++)
+ for (unsigned int i = 0; i < num_measures; i++)
{
const struct TALER_EXCHANGE_MeasureInformation *mi = &measures[i];
json_t *measure;
@@ -227,7 +270,7 @@ TALER_EXCHANGE_post_aml_decision (
measure));
}
- new_rules = GNUNET_JSON_PACK (
+ return GNUNET_JSON_PACK (
GNUNET_JSON_pack_timestamp ("expiration_time",
expiration_time),
GNUNET_JSON_pack_allow_null (
@@ -238,75 +281,199 @@ TALER_EXCHANGE_post_aml_decision (
GNUNET_JSON_pack_object_steal ("custom_measures",
jmeasures)
);
+}
- GNUNET_CRYPTO_eddsa_key_get_public (
- &officer_priv->eddsa_priv,
- &officer_pub.eddsa_pub);
- TALER_officer_aml_decision_sign (justification,
- decision_time,
- h_payto,
- new_rules,
- properties,
- new_measures,
- keep_investigating,
- officer_priv,
- &officer_sig);
- wh = GNUNET_new (struct TALER_EXCHANGE_AddAmlDecision);
- wh->cb = cb;
- wh->cb_cls = cb_cls;
- wh->ctx = ctx;
+
+struct TALER_EXCHANGE_PostAmlDecisionHandle *
+TALER_EXCHANGE_post_aml_decision_create (
+ struct GNUNET_CURL_Context *ctx,
+ const char *url,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Timestamp decision_time,
+ const char *successor_measure,
+ struct GNUNET_TIME_Timestamp expiration_time,
+ unsigned int num_rules,
+ const struct TALER_EXCHANGE_AccountRule rules[static num_rules],
+ unsigned int num_measures,
+ const struct TALER_EXCHANGE_MeasureInformation measures[static num_measures],
+ bool keep_investigating,
+ const char *justification,
+ const struct TALER_AmlOfficerPrivateKeyP *officer_priv)
+{
+ struct TALER_EXCHANGE_PostAmlDecisionHandle *padh;
+ json_t *new_rules;
+
+ new_rules = build_new_rules (successor_measure,
+ expiration_time,
+ num_rules,
+ rules,
+ num_measures,
+ measures);
+ if (NULL == new_rules)
{
- char *path;
- char opus[sizeof (officer_pub) * 2];
- char *end;
-
- end = GNUNET_STRINGS_data_to_string (
- &officer_pub,
- sizeof (officer_pub),
- opus,
- sizeof (opus));
- *end = '\0';
- GNUNET_asprintf (&path,
- "aml/%s/decision",
- opus);
- wh->url = TALER_url_join (url,
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ padh = GNUNET_new (struct TALER_EXCHANGE_PostAmlDecisionHandle);
+ padh->ctx = ctx;
+ padh->base_url = GNUNET_strdup (url);
+ padh->h_payto = *h_payto;
+ padh->decision_time = decision_time;
+ padh->justification = GNUNET_strdup (justification);
+ padh->keep_investigating = keep_investigating;
+ padh->new_rules = new_rules;
+ padh->officer_priv = *officer_priv;
+ GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv,
+ &padh->officer_pub.eddsa_pub);
+ return padh;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGE_post_aml_decision_set_options_ (
+ struct TALER_EXCHANGE_PostAmlDecisionHandle *padh,
+ unsigned int num_options,
+ const struct TALER_EXCHANGE_PostAmlDecisionOptionValue options[])
+{
+ for (unsigned int i = 0; i < num_options; i++)
+ {
+ const struct TALER_EXCHANGE_PostAmlDecisionOptionValue *opt = &options[i];
+
+ switch (opt->option)
+ {
+ case TALER_EXCHANGE_POST_AML_DECISION_OPTION_END:
+ return GNUNET_OK;
+ case TALER_EXCHANGE_POST_AML_DECISION_OPTION_PAYTO_URI:
+ GNUNET_free (padh->payto_uri_str);
+ padh->payto_uri_str =
+ (NULL != opt->details.payto_uri.full_payto)
+ ? GNUNET_strdup (opt->details.payto_uri.full_payto)
+ : NULL;
+ break;
+ case TALER_EXCHANGE_POST_AML_DECISION_OPTION_NEW_MEASURES:
+ GNUNET_free (padh->new_measures);
+ padh->new_measures =
+ (NULL != opt->details.new_measures)
+ ? GNUNET_strdup (opt->details.new_measures)
+ : NULL;
+ break;
+ case TALER_EXCHANGE_POST_AML_DECISION_OPTION_PROPERTIES:
+ if (NULL != padh->properties)
+ json_decref (padh->properties);
+ padh->properties =
+ (NULL != opt->details.properties)
+ ? json_incref ((json_t *) opt->details.properties)
+ : NULL;
+ break;
+ case TALER_EXCHANGE_POST_AML_DECISION_OPTION_EVENTS:
+ {
+ if (NULL != padh->jevents)
+ json_decref (padh->jevents);
+ if (0 == opt->details.events.num_events)
+ {
+ padh->jevents = NULL;
+ }
+ else
+ {
+ padh->jevents = json_array ();
+ GNUNET_assert (NULL != padh->jevents);
+ for (unsigned int j = 0; j < opt->details.events.num_events; j++)
+ GNUNET_assert (0 ==
+ json_array_append_new (
+ padh->jevents,
+ json_string (opt->details.events.events[j])));
+ }
+ }
+ break;
+ default:
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_post_aml_decision_start (
+ struct TALER_EXCHANGE_PostAmlDecisionHandle *padh,
+ TALER_EXCHANGE_PostAmlDecisionCallback cb,
+ TALER_EXCHANGE_POST_AML_DECISION_RESULT_CLOSURE *cb_cls)
+{
+ CURL *eh;
+ struct TALER_AmlOfficerSignatureP officer_sig;
+ json_t *body;
+ char *path;
+ char opus[sizeof (padh->officer_pub) * 2];
+ char *end;
+ struct TALER_FullPayto payto_uri_val = {
+ .full_payto = padh->payto_uri_str
+ };
+
+ padh->cb = cb;
+ padh->cb_cls = cb_cls;
+ TALER_officer_aml_decision_sign (padh->justification,
+ padh->decision_time,
+ &padh->h_payto,
+ padh->new_rules,
+ padh->properties,
+ padh->new_measures,
+ padh->keep_investigating,
+ &padh->officer_priv,
+ &officer_sig);
+
+ end = GNUNET_STRINGS_data_to_string (
+ &padh->officer_pub,
+ sizeof (padh->officer_pub),
+ opus,
+ sizeof (opus));
+ *end = '\0';
+ GNUNET_asprintf (&path,
+ "aml/%s/decision",
+ opus);
+ padh->url = TALER_url_join (padh->base_url,
path,
NULL);
- GNUNET_free (path);
- }
- if (NULL == wh->url)
+ GNUNET_free (path);
+ if (NULL == padh->url)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not construct request URL.\n");
- GNUNET_free (wh);
- json_decref (new_rules);
- return NULL;
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
}
+
body = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("justification",
- justification),
+ padh->justification),
GNUNET_JSON_pack_data_auto ("h_payto",
- h_payto),
+ &padh->h_payto),
GNUNET_JSON_pack_allow_null (
TALER_JSON_pack_full_payto ("payto_uri",
- payto_uri)),
- GNUNET_JSON_pack_object_steal ("new_rules",
- new_rules),
- GNUNET_JSON_pack_object_incref ("properties",
- (json_t *) properties),
+ payto_uri_val)),
+ GNUNET_JSON_pack_object_incref ("new_rules",
+ padh->new_rules),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_object_incref ("properties",
+ padh->properties)),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_string ("new_measures",
- new_measures)),
+ padh->new_measures)),
GNUNET_JSON_pack_bool ("keep_investigating",
- keep_investigating),
+ padh->keep_investigating),
GNUNET_JSON_pack_data_auto ("officer_sig",
&officer_sig),
GNUNET_JSON_pack_timestamp ("decision_time",
- decision_time));
- eh = TALER_EXCHANGE_curl_easy_get_ (wh->url);
+ padh->decision_time),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_array_incref ("events",
+ padh->jevents))
+ );
+
+ eh = TALER_EXCHANGE_curl_easy_get_ (padh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=
- TALER_curl_easy_post (&wh->post_ctx,
+ TALER_curl_easy_post (&padh->post_ctx,
eh,
body)) )
{
@@ -314,37 +481,52 @@ TALER_EXCHANGE_post_aml_decision (
if (NULL != eh)
curl_easy_cleanup (eh);
json_decref (body);
- GNUNET_free (wh->url);
- return NULL;
+ GNUNET_free (padh->url);
+ padh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
json_decref (body);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Requesting URL '%s'\n",
- wh->url);
- wh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- wh->post_ctx.headers,
- &handle_add_aml_decision_finished,
- wh);
- if (NULL == wh->job)
+ padh->url);
+ padh->job = GNUNET_CURL_job_add2 (padh->ctx,
+ eh,
+ padh->post_ctx.headers,
+ &handle_post_aml_decision_finished,
+ padh);
+ if (NULL == padh->job)
{
- TALER_EXCHANGE_post_aml_decision_cancel (wh);
- return NULL;
+ TALER_curl_easy_post_finished (&padh->post_ctx);
+ GNUNET_free (padh->url);
+ padh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
- return wh;
+ return TALER_EC_NONE;
}
void
TALER_EXCHANGE_post_aml_decision_cancel (
- struct TALER_EXCHANGE_AddAmlDecision *wh)
+ struct TALER_EXCHANGE_PostAmlDecisionHandle *padh)
{
- if (NULL != wh->job)
+ if (NULL != padh->job)
{
- GNUNET_CURL_job_cancel (wh->job);
- wh->job = NULL;
+ GNUNET_CURL_job_cancel (padh->job);
+ padh->job = NULL;
}
- TALER_curl_easy_post_finished (&wh->post_ctx);
- GNUNET_free (wh->url);
- GNUNET_free (wh);
+ TALER_curl_easy_post_finished (&padh->post_ctx);
+ json_decref (padh->new_rules);
+ if (NULL != padh->properties)
+ json_decref (padh->properties);
+ if (NULL != padh->jevents)
+ json_decref (padh->jevents);
+ GNUNET_free (padh->url);
+ GNUNET_free (padh->base_url);
+ GNUNET_free (padh->justification);
+ GNUNET_free (padh->payto_uri_str);
+ GNUNET_free (padh->new_measures);
+ GNUNET_free (padh);
}
+
+
+/* end of exchange_api_post-aml-OFFICER_PUB-decision.c */
diff --git a/src/lib/exchange_api_post-kyc-start-ID.c b/src/lib/exchange_api_post-kyc-start-ID.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2024 Taler Systems SA
+ Copyright (C) 2024-2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -24,17 +24,22 @@
#include <microhttpd.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler/taler_exchange_service.h"
+#include "taler/taler-exchange/post-kyc-start-ID.h"
#include "exchange_api_curl_defaults.h"
#include "taler/taler_signatures.h"
#include "taler/taler_curl_lib.h"
-#include "taler/taler_json_lib.h"
-struct TALER_EXCHANGE_KycStartHandle
+struct TALER_EXCHANGE_PostKycStartHandle
{
/**
- * The url for this request.
+ * The base URL for this request.
+ */
+ char *base_url;
+
+ /**
+ * The full URL for this request.
*/
char *url;
@@ -51,17 +56,23 @@ struct TALER_EXCHANGE_KycStartHandle
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_KycStartCallback cb;
+ TALER_EXCHANGE_PostKycStartCallback cb;
/**
- * Closure for @a cb.
+ * Closure for @e cb.
*/
- void *cb_cls;
+ TALER_EXCHANGE_POST_KYC_START_RESULT_CLOSURE *cb_cls;
/**
* Reference to the execution context.
*/
struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Identifier for the KYC process to start.
+ */
+ char *id;
+
};
@@ -69,7 +80,7 @@ struct TALER_EXCHANGE_KycStartHandle
* Function called when we're done processing the
* HTTP POST /kyc-start/$ID request.
*
- * @param cls the `struct TALER_EXCHANGE_KycStartHandle *`
+ * @param cls the `struct TALER_EXCHANGE_PostKycStartHandle *`
* @param response_code HTTP response code, 0 on error
* @param response response body, NULL if not in JSON
*/
@@ -78,14 +89,14 @@ handle_kyc_start_finished (void *cls,
long response_code,
const void *response)
{
- struct TALER_EXCHANGE_KycStartHandle *wh = cls;
+ struct TALER_EXCHANGE_PostKycStartHandle *pksh = cls;
const json_t *json = response;
- struct TALER_EXCHANGE_KycStartResponse adr = {
+ struct TALER_EXCHANGE_PostKycStartResponse adr = {
.hr.http_status = (unsigned int) response_code,
.hr.reply = json
};
- wh->job = NULL;
+ pksh->job = NULL;
switch (response_code)
{
case 0:
@@ -122,61 +133,68 @@ handle_kyc_start_finished (void *cls,
adr.hr.ec = TALER_JSON_get_error_code (json);
adr.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for exchange AML decision\n",
+ "Unexpected response code %u/%d for exchange POST kyc-start\n",
(unsigned int) response_code,
(int) adr.hr.ec);
break;
}
- if (NULL != wh->cb)
+ if (NULL != pksh->cb)
{
- wh->cb (wh->cb_cls,
- &adr);
- wh->cb = NULL;
+ pksh->cb (pksh->cb_cls,
+ &adr);
+ pksh->cb = NULL;
}
- TALER_EXCHANGE_kyc_start_cancel (wh);
+ TALER_EXCHANGE_post_kyc_start_cancel (pksh);
}
-struct TALER_EXCHANGE_KycStartHandle *
-TALER_EXCHANGE_kyc_start (
+struct TALER_EXCHANGE_PostKycStartHandle *
+TALER_EXCHANGE_post_kyc_start_create (
struct GNUNET_CURL_Context *ctx,
const char *url,
- const char *id,
- TALER_EXCHANGE_KycStartCallback cb,
- void *cb_cls)
+ const char *id)
{
- struct TALER_EXCHANGE_KycStartHandle *wh;
- CURL *eh;
- json_t *body;
+ struct TALER_EXCHANGE_PostKycStartHandle *pksh;
+
+ pksh = GNUNET_new (struct TALER_EXCHANGE_PostKycStartHandle);
+ pksh->ctx = ctx;
+ pksh->base_url = GNUNET_strdup (url);
+ pksh->id = GNUNET_strdup (id);
+ return pksh;
+}
- wh = GNUNET_new (struct TALER_EXCHANGE_KycStartHandle);
- wh->cb = cb;
- wh->cb_cls = cb_cls;
- wh->ctx = ctx;
- {
- char *path;
- GNUNET_asprintf (&path,
- "kyc-start/%s",
- id);
- wh->url = TALER_url_join (url,
+enum TALER_ErrorCode
+TALER_EXCHANGE_post_kyc_start_start (
+ struct TALER_EXCHANGE_PostKycStartHandle *pksh,
+ TALER_EXCHANGE_PostKycStartCallback cb,
+ TALER_EXCHANGE_POST_KYC_START_RESULT_CLOSURE *cb_cls)
+{
+ CURL *eh;
+ json_t *body;
+ char *path;
+
+ pksh->cb = cb;
+ pksh->cb_cls = cb_cls;
+ GNUNET_asprintf (&path,
+ "kyc-start/%s",
+ pksh->id);
+ pksh->url = TALER_url_join (pksh->base_url,
path,
NULL);
- GNUNET_free (path);
- }
- if (NULL == wh->url)
+ GNUNET_free (path);
+ if (NULL == pksh->url)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not construct request URL.\n");
- GNUNET_free (wh);
- return NULL;
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
}
body = json_object (); /* as per spec: empty! */
GNUNET_assert (NULL != body);
- eh = TALER_EXCHANGE_curl_easy_get_ (wh->url);
+ eh = TALER_EXCHANGE_curl_easy_get_ (pksh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=
- TALER_curl_easy_post (&wh->post_ctx,
+ TALER_curl_easy_post (&pksh->post_ctx,
eh,
body)) )
{
@@ -184,37 +202,45 @@ TALER_EXCHANGE_kyc_start (
if (NULL != eh)
curl_easy_cleanup (eh);
json_decref (body);
- GNUNET_free (wh->url);
- return NULL;
+ GNUNET_free (pksh->url);
+ pksh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
json_decref (body);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Requesting URL '%s'\n",
- wh->url);
- wh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- wh->post_ctx.headers,
- &handle_kyc_start_finished,
- wh);
- if (NULL == wh->job)
+ pksh->url);
+ pksh->job = GNUNET_CURL_job_add2 (pksh->ctx,
+ eh,
+ pksh->post_ctx.headers,
+ &handle_kyc_start_finished,
+ pksh);
+ if (NULL == pksh->job)
{
- TALER_EXCHANGE_kyc_start_cancel (wh);
- return NULL;
+ TALER_curl_easy_post_finished (&pksh->post_ctx);
+ GNUNET_free (pksh->url);
+ pksh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
- return wh;
+ return TALER_EC_NONE;
}
void
-TALER_EXCHANGE_kyc_start_cancel (
- struct TALER_EXCHANGE_KycStartHandle *wh)
+TALER_EXCHANGE_post_kyc_start_cancel (
+ struct TALER_EXCHANGE_PostKycStartHandle *pksh)
{
- if (NULL != wh->job)
+ if (NULL != pksh->job)
{
- GNUNET_CURL_job_cancel (wh->job);
- wh->job = NULL;
+ GNUNET_CURL_job_cancel (pksh->job);
+ pksh->job = NULL;
}
- TALER_curl_easy_post_finished (&wh->post_ctx);
- GNUNET_free (wh->url);
- GNUNET_free (wh);
+ TALER_curl_easy_post_finished (&pksh->post_ctx);
+ GNUNET_free (pksh->url);
+ GNUNET_free (pksh->base_url);
+ GNUNET_free (pksh->id);
+ GNUNET_free (pksh);
}
+
+
+/* end of exchange_api_post-kyc-start-ID.c */
diff --git a/src/lib/exchange_api_post-kyc-wallet.c b/src/lib/exchange_api_post-kyc-wallet.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021 Taler Systems SA
+ Copyright (C) 2021-2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -20,30 +20,36 @@
* @author Christian Grothoff
*/
#include "taler/platform.h"
-#include <microhttpd.h> /* just for HTTP wallet codes */
+#include <microhttpd.h> /* just for HTTP status codes */
#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler/taler_exchange_service.h"
#include "taler/taler_json_lib.h"
-#include "exchange_api_handle.h"
+#include "taler/taler-exchange/post-kyc-wallet.h"
#include "taler/taler_signatures.h"
#include "exchange_api_curl_defaults.h"
+#include "taler/taler_curl_lib.h"
/**
- * @brief A ``/kyc-wallet`` handle
+ * @brief A POST /kyc-wallet handle
*/
-struct TALER_EXCHANGE_KycWalletHandle
+struct TALER_EXCHANGE_PostKycWalletHandle
{
/**
- * Context for #TEH_curl_easy_post(). Keeps the data that must
+ * Context for curl easy post. Keeps the data that must
* persist for Curl to make the upload.
*/
- struct TALER_CURL_PostContext ctx;
+ struct TALER_CURL_PostContext post_ctx;
/**
- * The url for this request.
+ * The base URL for this request.
+ */
+ char *base_url;
+
+ /**
+ * The full URL for this request, set during _start.
*/
char *url;
@@ -55,12 +61,27 @@ struct TALER_EXCHANGE_KycWalletHandle
/**
* Function to call with the result.
*/
- TALER_EXCHANGE_KycWalletCallback cb;
+ TALER_EXCHANGE_PostKycWalletCallback cb;
/**
* Closure for @e cb.
*/
- void *cb_cls;
+ TALER_EXCHANGE_POST_KYC_WALLET_RESULT_CLOSURE *cb_cls;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Reserve private key of the wallet.
+ */
+ struct TALER_ReservePrivateKeyP reserve_priv;
+
+ /**
+ * Balance (or balance threshold) crossed by the wallet.
+ */
+ struct TALER_Amount balance;
};
@@ -69,7 +90,7 @@ struct TALER_EXCHANGE_KycWalletHandle
* Function called when we're done processing the
* HTTP /kyc-wallet request.
*
- * @param cls the `struct TALER_EXCHANGE_KycWalletHandle`
+ * @param cls the `struct TALER_EXCHANGE_PostKycWalletHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
@@ -78,14 +99,14 @@ handle_kyc_wallet_finished (void *cls,
long response_code,
const void *response)
{
- struct TALER_EXCHANGE_KycWalletHandle *kwh = cls;
+ struct TALER_EXCHANGE_PostKycWalletHandle *pkwh = cls;
const json_t *j = response;
- struct TALER_EXCHANGE_WalletKycResponse ks = {
+ struct TALER_EXCHANGE_PostKycWalletResponse ks = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
- kwh->job = NULL;
+ pkwh->job = NULL;
switch (response_code)
{
case 0:
@@ -169,56 +190,72 @@ handle_kyc_wallet_finished (void *cls,
(int) ks.hr.ec);
break;
}
- kwh->cb (kwh->cb_cls,
- &ks);
- TALER_EXCHANGE_kyc_wallet_cancel (kwh);
+ if (NULL != pkwh->cb)
+ {
+ pkwh->cb (pkwh->cb_cls,
+ &ks);
+ pkwh->cb = NULL;
+ }
+ TALER_EXCHANGE_post_kyc_wallet_cancel (pkwh);
}
-struct TALER_EXCHANGE_KycWalletHandle *
-TALER_EXCHANGE_kyc_wallet (
+struct TALER_EXCHANGE_PostKycWalletHandle *
+TALER_EXCHANGE_post_kyc_wallet_create (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_Amount *balance,
- TALER_EXCHANGE_KycWalletCallback cb,
- void *cb_cls)
+ const struct TALER_Amount *balance)
+{
+ struct TALER_EXCHANGE_PostKycWalletHandle *pkwh;
+
+ pkwh = GNUNET_new (struct TALER_EXCHANGE_PostKycWalletHandle);
+ pkwh->ctx = ctx;
+ pkwh->base_url = GNUNET_strdup (url);
+ pkwh->reserve_priv = *reserve_priv;
+ pkwh->balance = *balance;
+ return pkwh;
+}
+
+
+enum TALER_ErrorCode
+TALER_EXCHANGE_post_kyc_wallet_start (
+ struct TALER_EXCHANGE_PostKycWalletHandle *pkwh,
+ TALER_EXCHANGE_PostKycWalletCallback cb,
+ TALER_EXCHANGE_POST_KYC_WALLET_RESULT_CLOSURE *cb_cls)
{
- struct TALER_EXCHANGE_KycWalletHandle *kwh;
CURL *eh;
json_t *req;
struct TALER_ReservePublicKeyP reserve_pub;
struct TALER_ReserveSignatureP reserve_sig;
- GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
+ pkwh->cb = cb;
+ pkwh->cb_cls = cb_cls;
+ GNUNET_CRYPTO_eddsa_key_get_public (&pkwh->reserve_priv.eddsa_priv,
&reserve_pub.eddsa_pub);
- TALER_wallet_account_setup_sign (reserve_priv,
- balance,
+ TALER_wallet_account_setup_sign (&pkwh->reserve_priv,
+ &pkwh->balance,
&reserve_sig);
req = GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("balance",
- balance),
+ &pkwh->balance),
GNUNET_JSON_pack_data_auto ("reserve_pub",
&reserve_pub),
GNUNET_JSON_pack_data_auto ("reserve_sig",
&reserve_sig));
GNUNET_assert (NULL != req);
- kwh = GNUNET_new (struct TALER_EXCHANGE_KycWalletHandle);
- kwh->cb = cb;
- kwh->cb_cls = cb_cls;
- kwh->url = TALER_url_join (url,
- "kyc-wallet",
- NULL);
- if (NULL == kwh->url)
+ pkwh->url = TALER_url_join (pkwh->base_url,
+ "kyc-wallet",
+ NULL);
+ if (NULL == pkwh->url)
{
json_decref (req);
- GNUNET_free (kwh);
- return NULL;
+ return TALER_EC_GENERIC_CONFIGURATION_INVALID;
}
- eh = TALER_EXCHANGE_curl_easy_get_ (kwh->url);
+ eh = TALER_EXCHANGE_curl_easy_get_ (pkwh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=
- TALER_curl_easy_post (&kwh->ctx,
+ TALER_curl_easy_post (&pkwh->post_ctx,
eh,
req)) )
{
@@ -226,32 +263,44 @@ TALER_EXCHANGE_kyc_wallet (
if (NULL != eh)
curl_easy_cleanup (eh);
json_decref (req);
- GNUNET_free (kwh->url);
- GNUNET_free (kwh);
- return NULL;
+ GNUNET_free (pkwh->url);
+ pkwh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
}
json_decref (req);
- kwh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- kwh->ctx.headers,
- &handle_kyc_wallet_finished,
- kwh);
- return kwh;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Requesting URL '%s'\n",
+ pkwh->url);
+ pkwh->job = GNUNET_CURL_job_add2 (pkwh->ctx,
+ eh,
+ pkwh->post_ctx.headers,
+ &handle_kyc_wallet_finished,
+ pkwh);
+ if (NULL == pkwh->job)
+ {
+ TALER_curl_easy_post_finished (&pkwh->post_ctx);
+ GNUNET_free (pkwh->url);
+ pkwh->url = NULL;
+ return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
+ }
+ return TALER_EC_NONE;
}
void
-TALER_EXCHANGE_kyc_wallet_cancel (struct TALER_EXCHANGE_KycWalletHandle *kwh)
+TALER_EXCHANGE_post_kyc_wallet_cancel (
+ struct TALER_EXCHANGE_PostKycWalletHandle *pkwh)
{
- if (NULL != kwh->job)
+ if (NULL != pkwh->job)
{
- GNUNET_CURL_job_cancel (kwh->job);
- kwh->job = NULL;
+ GNUNET_CURL_job_cancel (pkwh->job);
+ pkwh->job = NULL;
}
- GNUNET_free (kwh->url);
- TALER_curl_easy_post_finished (&kwh->ctx);
- GNUNET_free (kwh);
+ TALER_curl_easy_post_finished (&pkwh->post_ctx);
+ GNUNET_free (pkwh->url);
+ GNUNET_free (pkwh->base_url);
+ GNUNET_free (pkwh);
}
-/* end of exchange_api_kyc_wallet.c */
+/* end of exchange_api_post-kyc-wallet.c */
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
@@ -37,7 +37,7 @@ libtalertwistertesting_la_LDFLAGS = \
endif
libtalertesting_la_LDFLAGS = \
- -version-info 3:0:2 \
+ -version-info 4:0:0 \
-no-undefined
libtalertesting_la_SOURCES = \
testing_api_cmd_age_withdraw.c \
diff --git a/src/testing/testing_api_cmd_check_aml_decisions.c b/src/testing/testing_api_cmd_check_aml_decisions.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023, 2024 Taler Systems SA
+ Copyright (C) 2023, 2024, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
@@ -24,6 +24,15 @@
#include "taler/platform.h"
#include "taler/taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
+
+/**
+ * State for a "check_aml_decisions" CMD.
+ */
+struct AmlCheckState;
+
+#define TALER_EXCHANGE_GET_AML_DECISIONS_RESULT_CLOSURE \
+ struct AmlCheckState
+#include "taler/taler-exchange/get-aml-OFFICER_PUB-decisions.h"
#include "taler/taler_testing_lib.h"
#include "taler/taler_signatures.h"
#include "taler/backoff.h"
@@ -38,7 +47,7 @@ struct AmlCheckState
/**
* Handle while operation is running.
*/
- struct TALER_EXCHANGE_LookupAmlDecisions *dh;
+ struct TALER_EXCHANGE_GetAmlDecisionsHandle *dh;
/**
* Our interpreter.
@@ -70,16 +79,14 @@ struct AmlCheckState
* Callback to analyze the /aml/$OFFICER_PUB/$decision/$H_PAYTO response, just used to check
* if the response code is acceptable.
*
- * @param cls closure.
+ * @param ds our state
* @param adr response details
*/
static void
check_aml_decisions_cb (
- void *cls,
- const struct TALER_EXCHANGE_AmlDecisionsResponse *adr)
+ TALER_EXCHANGE_GET_AML_DECISIONS_RESULT_CLOSURE *ds,
+ const struct TALER_EXCHANGE_GetAmlDecisionsResponse *adr)
{
- struct AmlCheckState *ds = cls;
-
ds->dh = NULL;
if (ds->expected_http_status != adr->hr.http_status)
{
@@ -92,7 +99,7 @@ check_aml_decisions_cb (
{
const struct TALER_TESTING_Command *ref;
const char *justification;
- const struct TALER_EXCHANGE_AmlDecision *oldest = NULL;
+ const struct TALER_EXCHANGE_GetAmlDecisionsDecision *oldest = NULL;
if (NULL != ds->ref_operation)
{
@@ -110,10 +117,10 @@ check_aml_decisions_cb (
ref,
&justification))
{
- for (unsigned int i = 0; i<adr->details.ok.decisions_length; i++)
+ for (unsigned int i = 0; i<adr->details.ok.records_length; i++)
{
- const struct TALER_EXCHANGE_AmlDecision *aml_history
- = &adr->details.ok.decisions[i];
+ const struct TALER_EXCHANGE_GetAmlDecisionsDecision *aml_history
+ = &adr->details.ok.records[i];
if ( (NULL == oldest) ||
(GNUNET_TIME_timestamp_cmp (oldest->decision_time,
@@ -210,23 +217,38 @@ check_aml_decisions_run (
TALER_TESTING_get_trait_officer_priv (
ref,
&officer_priv));
- ds->dh = TALER_EXCHANGE_lookup_aml_decisions (
+ ds->dh = TALER_EXCHANGE_get_aml_decisions_create (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
- h_payto, /* NULL to return all */
- TALER_EXCHANGE_YNA_ALL,
- TALER_EXCHANGE_YNA_ALL,
- UINT64_MAX, /* offset */
- -1, /* limit */
- officer_priv,
- &check_aml_decisions_cb,
- ds);
+ officer_priv);
if (NULL == ds->dh)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
+ TALER_EXCHANGE_get_aml_decisions_set_options (
+ ds->dh,
+ TALER_EXCHANGE_get_aml_decisions_option_offset (UINT64_MAX),
+ TALER_EXCHANGE_get_aml_decisions_option_limit (-1));
+ if (NULL != h_payto)
+ TALER_EXCHANGE_get_aml_decisions_set_options (
+ ds->dh,
+ TALER_EXCHANGE_get_aml_decisions_option_filter_h_payto (h_payto));
+ {
+ enum TALER_ErrorCode ec;
+
+ ec = TALER_EXCHANGE_get_aml_decisions_start (ds->dh,
+ &check_aml_decisions_cb,
+ ds);
+ if (TALER_EC_NONE != ec)
+ {
+ GNUNET_break (0);
+ ds->dh = NULL;
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+ }
}
@@ -248,7 +270,7 @@ check_aml_decisions_cleanup (
{
TALER_TESTING_command_incomplete (ds->is,
cmd->label);
- TALER_EXCHANGE_lookup_aml_decisions_cancel (ds->dh);
+ TALER_EXCHANGE_get_aml_decisions_cancel (ds->dh);
ds->dh = NULL;
}
GNUNET_free (ds);
diff --git a/src/testing/testing_api_cmd_get_active_legitimization_measures.c b/src/testing/testing_api_cmd_get_active_legitimization_measures.c
@@ -233,7 +233,7 @@ get_active_legitimization_measures_run (
TALER_EXCHANGE_get_aml_legitimizations_option_filter_active (
TALER_EXCHANGE_YNA_YES)));
GNUNET_assert (
- TALER_EXCHANGE_GET_AML_LEGITIMIZATIONS_START_OK ==
+ TALER_EC_NONE ==
TALER_EXCHANGE_get_aml_legitimizations_start (
ds->dh,
&get_active_legitimization_measures_cb,
diff --git a/src/testing/testing_api_cmd_get_kyc_info.c b/src/testing/testing_api_cmd_get_kyc_info.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2024 Taler Systems SA
+ Copyright (C) 2024, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
@@ -25,6 +25,15 @@
#include "taler/platform.h"
#include "taler/taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
+
+/**
+ * State for a GET kyc-info CMD.
+ */
+struct GetKycInfoState;
+
+#define TALER_EXCHANGE_GET_KYC_INFO_RESULT_CLOSURE \
+ struct GetKycInfoState
+#include "taler/taler-exchange/get-kyc-info-ACCESS_TOKEN.h"
#include "taler/taler_testing_lib.h"
/**
@@ -46,7 +55,7 @@ struct GetKycInfoState
/**
* Handle to the GET /kyc-info pending operation.
*/
- struct TALER_EXCHANGE_KycInfoHandle *kwh;
+ struct TALER_EXCHANGE_GetKycInfoHandle *kwh;
/**
* Interpreter state.
@@ -69,15 +78,14 @@ struct GetKycInfoState
/**
* Handle response to the command.
*
- * @param cls closure.
+ * @param kcg our state
* @param kpci GET KYC status response details
*/
static void
kyc_info_cb (
- void *cls,
- const struct TALER_EXCHANGE_KycProcessClientInformation *kpci)
+ TALER_EXCHANGE_GET_KYC_INFO_RESULT_CLOSURE *kcg,
+ const struct TALER_EXCHANGE_GetKycInfoResponse *kpci)
{
- struct GetKycInfoState *kcg = cls;
struct TALER_TESTING_Interpreter *is = kcg->is;
kcg->kwh = NULL;
@@ -145,15 +153,25 @@ get_kyc_info_run (void *cls,
TALER_TESTING_interpreter_fail (kcg->is);
return;
}
- kcg->kwh = TALER_EXCHANGE_kyc_info (
+ kcg->kwh = TALER_EXCHANGE_get_kyc_info_create (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
- token,
- NULL /* etag */,
- GNUNET_TIME_UNIT_ZERO,
- &kyc_info_cb,
- kcg);
+ token);
GNUNET_assert (NULL != kcg->kwh);
+ {
+ enum TALER_ErrorCode ec;
+
+ ec = TALER_EXCHANGE_get_kyc_info_start (kcg->kwh,
+ &kyc_info_cb,
+ kcg);
+ if (TALER_EC_NONE != ec)
+ {
+ GNUNET_break (0);
+ kcg->kwh = NULL;
+ TALER_TESTING_interpreter_fail (kcg->is);
+ return;
+ }
+ }
}
@@ -175,7 +193,7 @@ get_kyc_info_cleanup (
{
TALER_TESTING_command_incomplete (kcg->is,
cmd->label);
- TALER_EXCHANGE_kyc_info_cancel (kcg->kwh);
+ TALER_EXCHANGE_get_kyc_info_cancel (kcg->kwh);
kcg->kwh = NULL;
}
for (unsigned int i = 0; i<kcg->num_ids; i++)
diff --git a/src/testing/testing_api_cmd_kyc_check_get.c b/src/testing/testing_api_cmd_kyc_check_get.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021-2023 Taler Systems SA
+ Copyright (C) 2021-2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
@@ -25,6 +25,15 @@
#include "taler/platform.h"
#include "taler/taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
+
+/**
+ * State for a "track transaction" CMD.
+ */
+struct KycCheckGetState;
+
+#define TALER_EXCHANGE_GET_KYC_CHECK_RESULT_CLOSURE \
+ struct KycCheckGetState
+#include "taler/taler-exchange/get-kyc-check-H_NORMALIZED_PAYTO.h"
#include "taler/taler_testing_lib.h"
/**
@@ -42,7 +51,7 @@ struct KycCheckGetState
/**
* Handle to the "track transaction" pending operation.
*/
- struct TALER_EXCHANGE_KycCheckHandle *kwh;
+ struct TALER_EXCHANGE_GetKycCheckHandle *kwh;
/**
* Interpreter state.
@@ -75,14 +84,14 @@ struct KycCheckGetState
/**
* Handle response to the command.
*
- * @param cls closure.
+ * @param kcg our state
* @param ks GET KYC status response details
*/
static void
-check_kyc_cb (void *cls,
- const struct TALER_EXCHANGE_KycStatus *ks)
+check_kyc_cb (
+ TALER_EXCHANGE_GET_KYC_CHECK_RESULT_CLOSURE *kcg,
+ const struct TALER_EXCHANGE_GetKycCheckResponse *ks)
{
- struct KycCheckGetState *kcg = cls;
struct TALER_TESTING_Interpreter *is = kcg->is;
kcg->kwh = NULL;
@@ -172,19 +181,31 @@ check_kyc_run (void *cls,
TALER_TESTING_interpreter_fail (kcg->is);
return;
}
- kcg->kwh = TALER_EXCHANGE_kyc_check (
+ kcg->kwh = TALER_EXCHANGE_get_kyc_check_create (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
h_payto,
- account_priv,
- kcg->lpt,
- 0,
- TALER_EXCHANGE_KLPT_NONE == kcg->lpt
- ? GNUNET_TIME_UNIT_ZERO
- : GNUNET_TIME_UNIT_MINUTES,
- &check_kyc_cb,
- kcg);
+ account_priv);
GNUNET_assert (NULL != kcg->kwh);
+ if (TALER_EXCHANGE_KLPT_NONE != kcg->lpt)
+ TALER_EXCHANGE_get_kyc_check_set_options (
+ kcg->kwh,
+ TALER_EXCHANGE_get_kyc_check_option_lpt (kcg->lpt),
+ TALER_EXCHANGE_get_kyc_check_option_timeout (GNUNET_TIME_UNIT_MINUTES));
+ {
+ enum TALER_ErrorCode ec;
+
+ ec = TALER_EXCHANGE_get_kyc_check_start (kcg->kwh,
+ &check_kyc_cb,
+ kcg);
+ if (TALER_EC_NONE != ec)
+ {
+ GNUNET_break (0);
+ kcg->kwh = NULL;
+ TALER_TESTING_interpreter_fail (kcg->is);
+ return;
+ }
+ }
}
@@ -205,7 +226,7 @@ check_kyc_cleanup (void *cls,
{
TALER_TESTING_command_incomplete (kcg->is,
cmd->label);
- TALER_EXCHANGE_kyc_check_cancel (kcg->kwh);
+ TALER_EXCHANGE_get_kyc_check_cancel (kcg->kwh);
kcg->kwh = NULL;
}
GNUNET_free (kcg);
diff --git a/src/testing/testing_api_cmd_kyc_proof.c b/src/testing/testing_api_cmd_kyc_proof.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021 Taler Systems SA
+ Copyright (C) 2021-2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
@@ -25,6 +25,15 @@
#include "taler/platform.h"
#include "taler/taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
+
+/**
+ * State for a "track transaction" CMD.
+ */
+struct KycProofGetState;
+
+#define TALER_EXCHANGE_GET_KYC_PROOF_RESULT_CLOSURE \
+ struct KycProofGetState
+#include "taler/taler-exchange/get-kyc-proof-PROVIDER_NAME.h"
#include "taler/taler_testing_lib.h"
/**
@@ -60,9 +69,15 @@ struct KycProofGetState
char *redirect_url;
/**
+ * Additional URL arguments (e.g. "&code=..."), kept alive
+ * for the lifetime of the request.
+ */
+ char *uargs;
+
+ /**
* Handle to the "track transaction" pending operation.
*/
- struct TALER_EXCHANGE_KycProofHandle *kph;
+ struct TALER_EXCHANGE_GetKycProofHandle *kph;
/**
* Interpreter state.
@@ -74,14 +89,14 @@ struct KycProofGetState
/**
* Handle response to the command.
*
- * @param cls closure.
+ * @param kcg our state
* @param kpr KYC proof response details
*/
static void
-proof_kyc_cb (void *cls,
- const struct TALER_EXCHANGE_KycProofResponse *kpr)
+proof_kyc_cb (
+ struct KycProofGetState *kcg,
+ const struct TALER_EXCHANGE_GetKycProofResponse *kpr)
{
- struct KycProofGetState *kcg = cls;
struct TALER_TESTING_Interpreter *is = kcg->is;
kcg->kph = NULL;
@@ -127,7 +142,6 @@ proof_kyc_run (void *cls,
struct KycProofGetState *kps = cls;
const struct TALER_TESTING_Command *res_cmd;
const struct TALER_NormalizedPaytoHashP *h_payto;
- char *uargs;
const char *exchange_url;
(void) cmd;
@@ -155,22 +169,34 @@ proof_kyc_run (void *cls,
TALER_TESTING_interpreter_fail (kps->is);
return;
}
- if (NULL == kps->code)
- uargs = NULL;
- else
- GNUNET_asprintf (&uargs,
+ if (NULL != kps->code)
+ GNUNET_asprintf (&kps->uargs,
"&code=%s",
kps->code);
- kps->kph = TALER_EXCHANGE_kyc_proof (
+ kps->kph = TALER_EXCHANGE_get_kyc_proof_create (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
h_payto,
- kps->logic,
- uargs,
- &proof_kyc_cb,
- kps);
- GNUNET_free (uargs);
+ kps->logic);
GNUNET_assert (NULL != kps->kph);
+ if (NULL != kps->uargs)
+ TALER_EXCHANGE_get_kyc_proof_set_options (
+ kps->kph,
+ TALER_EXCHANGE_get_kyc_proof_option_args (kps->uargs));
+ {
+ enum TALER_ErrorCode ec;
+
+ ec = TALER_EXCHANGE_get_kyc_proof_start (kps->kph,
+ &proof_kyc_cb,
+ kps);
+ if (TALER_EC_NONE != ec)
+ {
+ GNUNET_break (0);
+ kps->kph = NULL;
+ TALER_TESTING_interpreter_fail (kps->is);
+ return;
+ }
+ }
}
@@ -191,10 +217,11 @@ proof_kyc_cleanup (void *cls,
{
TALER_TESTING_command_incomplete (kps->is,
cmd->label);
- TALER_EXCHANGE_kyc_proof_cancel (kps->kph);
+ TALER_EXCHANGE_get_kyc_proof_cancel (kps->kph);
kps->kph = NULL;
}
GNUNET_free (kps->redirect_url);
+ GNUNET_free (kps->uargs);
GNUNET_free (kps);
}
diff --git a/src/testing/testing_api_cmd_kyc_wallet_get.c b/src/testing/testing_api_cmd_kyc_wallet_get.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021-2024 Taler Systems SA
+ Copyright (C) 2021-2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
@@ -25,6 +25,15 @@
#include "taler/platform.h"
#include "taler/taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
+
+/**
+ * State for a "/kyc-wallet" GET CMD.
+ */
+struct KycWalletGetState;
+
+#define TALER_EXCHANGE_POST_KYC_WALLET_RESULT_CLOSURE \
+ struct KycWalletGetState
+#include "taler/taler-exchange/post-kyc-wallet.h"
#include "taler/taler_testing_lib.h"
/**
@@ -78,7 +87,7 @@ struct KycWalletGetState
/**
* Handle to the "track transaction" pending operation.
*/
- struct TALER_EXCHANGE_KycWalletHandle *kwh;
+ struct TALER_EXCHANGE_PostKycWalletHandle *kwh;
/**
* Balance to pass to the exchange.
@@ -95,14 +104,14 @@ struct KycWalletGetState
/**
* Handle response to the command.
*
- * @param cls closure.
+ * @param kwg our state
* @param wkr GET deposit response details
*/
static void
-wallet_kyc_cb (void *cls,
- const struct TALER_EXCHANGE_WalletKycResponse *wkr)
+wallet_kyc_cb (
+ struct KycWalletGetState *kwg,
+ const struct TALER_EXCHANGE_PostKycWalletResponse *wkr)
{
- struct KycWalletGetState *kwg = cls;
struct TALER_TESTING_Interpreter *is = kwg->is;
kwg->kwh = NULL;
@@ -196,14 +205,26 @@ wallet_kyc_run (void *cls,
kwg->reserve_payto_uri
= TALER_reserve_make_payto (exchange_url,
&kwg->account_pub.reserve_pub);
- kwg->kwh = TALER_EXCHANGE_kyc_wallet (
+ kwg->kwh = TALER_EXCHANGE_post_kyc_wallet_create (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
&kwg->account_priv.reserve_priv,
- &kwg->balance,
- &wallet_kyc_cb,
- kwg);
+ &kwg->balance);
GNUNET_assert (NULL != kwg->kwh);
+ {
+ enum TALER_ErrorCode ec;
+
+ ec = TALER_EXCHANGE_post_kyc_wallet_start (kwg->kwh,
+ &wallet_kyc_cb,
+ kwg);
+ if (TALER_EC_NONE != ec)
+ {
+ GNUNET_break (0);
+ kwg->kwh = NULL;
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+ }
}
@@ -225,7 +246,7 @@ wallet_kyc_cleanup (
{
TALER_TESTING_command_incomplete (kwg->is,
cmd->label);
- TALER_EXCHANGE_kyc_wallet_cancel (kwg->kwh);
+ TALER_EXCHANGE_post_kyc_wallet_cancel (kwg->kwh);
kwg->kwh = NULL;
}
GNUNET_free (kwg->reserve_payto_uri.normalized_payto);
diff --git a/src/testing/testing_api_cmd_post_kyc_start.c b/src/testing/testing_api_cmd_post_kyc_start.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2024 Taler Systems SA
+ Copyright (C) 2024, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
@@ -25,6 +25,15 @@
#include "taler/platform.h"
#include "taler/taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
+
+/**
+ * State for a POST /kyc-start CMD.
+ */
+struct PostKycStartState;
+
+#define TALER_EXCHANGE_POST_KYC_START_RESULT_CLOSURE \
+ struct PostKycStartState
+#include "taler/taler-exchange/post-kyc-start-ID.h"
#include "taler/taler_testing_lib.h"
/**
@@ -56,7 +65,7 @@ struct PostKycStartState
/**
* Handle to the KYC start pending operation.
*/
- struct TALER_EXCHANGE_KycStartHandle *kwh;
+ struct TALER_EXCHANGE_PostKycStartHandle *kwh;
/**
* Interpreter state.
@@ -68,15 +77,14 @@ struct PostKycStartState
/**
* Handle response to the command.
*
- * @param cls closure.
+ * @param kcg our state
* @param ks GET KYC status response details
*/
static void
post_kyc_start_cb (
- void *cls,
- const struct TALER_EXCHANGE_KycStartResponse *ks)
+ struct PostKycStartState *kcg,
+ const struct TALER_EXCHANGE_PostKycStartResponse *ks)
{
- struct PostKycStartState *kcg = cls;
struct TALER_TESTING_Interpreter *is = kcg->is;
kcg->kwh = NULL;
@@ -146,13 +154,25 @@ post_kyc_start_run (void *cls,
TALER_TESTING_interpreter_fail (kcg->is);
return;
}
- kcg->kwh = TALER_EXCHANGE_kyc_start (
+ kcg->kwh = TALER_EXCHANGE_post_kyc_start_create (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
- id,
- &post_kyc_start_cb,
- kcg);
+ id);
GNUNET_assert (NULL != kcg->kwh);
+ {
+ enum TALER_ErrorCode ec;
+
+ ec = TALER_EXCHANGE_post_kyc_start_start (kcg->kwh,
+ &post_kyc_start_cb,
+ kcg);
+ if (TALER_EC_NONE != ec)
+ {
+ GNUNET_break (0);
+ kcg->kwh = NULL;
+ TALER_TESTING_interpreter_fail (kcg->is);
+ return;
+ }
+ }
}
@@ -173,7 +193,7 @@ post_kyc_start_cleanup (void *cls,
{
TALER_TESTING_command_incomplete (kcg->is,
cmd->label);
- TALER_EXCHANGE_kyc_start_cancel (kcg->kwh);
+ TALER_EXCHANGE_post_kyc_start_cancel (kcg->kwh);
kcg->kwh = NULL;
}
GNUNET_free (kcg->redirect_url);
diff --git a/src/testing/testing_api_cmd_take_aml_decision.c b/src/testing/testing_api_cmd_take_aml_decision.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023, 2024 Taler Systems SA
+ Copyright (C) 2023, 2024, 2026 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
@@ -24,6 +24,15 @@
#include "taler/platform.h"
#include "taler/taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
+
+/**
+ * State for a "take_aml_decision" CMD.
+ */
+struct AmlDecisionState;
+
+#define TALER_EXCHANGE_POST_AML_DECISION_RESULT_CLOSURE \
+ struct AmlDecisionState
+#include "taler/taler-exchange/post-aml-OFFICER_PUB-decision.h"
#include "taler/taler_testing_lib.h"
#include "taler/taler_signatures.h"
#include "taler/backoff.h"
@@ -36,9 +45,9 @@ struct AmlDecisionState
{
/**
- * Auditor enable handle while operation is running.
+ * Handle while operation is running.
*/
- struct TALER_EXCHANGE_AddAmlDecision *dh;
+ struct TALER_EXCHANGE_PostAmlDecisionHandle *dh;
/**
* Our interpreter.
@@ -101,19 +110,18 @@ struct AmlDecisionState
/**
- * Callback to analyze the /aml-decision/$OFFICER_PUB response, just used to check
- * if the response code is acceptable.
+ * Callback to analyze the /aml-decision/$OFFICER_PUB response, just used to
+ * check if the response code is acceptable.
*
- * @param cls closure.
- * @param adr response details
+ * @param ds our state
+ * @param pr response details
*/
static void
take_aml_decision_cb (
- void *cls,
- const struct TALER_EXCHANGE_AddAmlDecisionResponse *adr)
+ struct AmlDecisionState *ds,
+ const struct TALER_EXCHANGE_PostAmlDecisionResponse *pr)
{
- struct AmlDecisionState *ds = cls;
- const struct TALER_EXCHANGE_HttpResponse *hr = &adr->hr;
+ const struct TALER_EXCHANGE_HttpResponse *hr = &pr->hr;
ds->dh = NULL;
if (ds->expected_response != hr->http_status)
@@ -304,7 +312,7 @@ take_aml_decision_run (void *cls,
rule->measures
= GNUNET_new_array (rule->num_measures,
const char *);
- for (unsigned int k = 0; k<rule->num_measures; k++)
+ for (unsigned int k = 0; k < rule->num_measures; k++)
rule->measures[k]
= json_string_value (
json_array_get (jameasures,
@@ -347,51 +355,63 @@ take_aml_decision_run (void *cls,
mname,
err_name);
TALER_TESTING_interpreter_fail (is);
+ for (unsigned int j = 0; j < num_rules; j++)
+ GNUNET_free (rules[j].measures);
return;
}
}
GNUNET_assert (off == num_measures);
+ ds->dh = TALER_EXCHANGE_post_aml_decision_create (
+ TALER_TESTING_interpreter_get_context (is),
+ exchange_url,
+ h_payto,
+ now,
+ ds->successor_measure,
+ expiration_time,
+ num_rules,
+ rules,
+ num_measures,
+ measures,
+ ds->keep_investigating,
+ ds->justification,
+ officer_priv);
+
+ for (unsigned int j = 0; j < num_rules; j++)
+ GNUNET_free (rules[j].measures);
+
+ if (NULL == ds->dh)
{
- struct TALER_FullPayto null_payto = {
- .full_payto = NULL
- };
-
- ds->dh = TALER_EXCHANGE_post_aml_decision (
- TALER_TESTING_interpreter_get_context (is),
- exchange_url,
- h_payto,
- null_payto,
- now,
- ds->successor_measure,
- new_measures,
- expiration_time,
- num_rules,
- rules,
- num_measures,
- measures,
- ds->properties,
- ds->keep_investigating,
- ds->justification,
- officer_priv,
- 0, NULL, /* no events */
- &take_aml_decision_cb,
- ds);
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (is);
+ return;
}
- for (unsigned int j = 0; j<num_rules; j++)
+
+ /* Set optional: new_measures and properties */
+ if (NULL != new_measures)
+ TALER_EXCHANGE_post_aml_decision_set_options (
+ ds->dh,
+ TALER_EXCHANGE_post_aml_decision_option_new_measures (new_measures));
+ if (NULL != ds->properties)
+ TALER_EXCHANGE_post_aml_decision_set_options (
+ ds->dh,
+ TALER_EXCHANGE_post_aml_decision_option_properties (ds->properties));
+
{
- struct TALER_EXCHANGE_AccountRule *rule = &rules[j];
+ enum TALER_ErrorCode ec;
- GNUNET_free (rule->measures);
+ ec = TALER_EXCHANGE_post_aml_decision_start (ds->dh,
+ &take_aml_decision_cb,
+ ds);
+ if (TALER_EC_NONE != ec)
+ {
+ GNUNET_break (0);
+ ds->dh = NULL;
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
}
}
-
- if (NULL == ds->dh)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
}