diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-09-01 17:37:00 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-09-01 17:37:00 +0200 |
commit | 0188860eddca95d80d2253c7e2893daf3b3d6dca (patch) | |
tree | b6cc9c5ab4b9d3aad7fd7fe9bdabadd1d2e87345 /src | |
parent | 6996910aeee8fad4f0d249590b46570d514d2eb3 (diff) |
introduce zero_limits for #9039/#9040 to signal clients that they must do KYC before even attempting to work with an exchange
Diffstat (limited to 'src')
-rw-r--r-- | src/exchange/taler-exchange-httpd.c | 7 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd.h | 5 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_keys.c | 3 | ||||
-rw-r--r-- | src/include/taler_exchange_service.h | 29 | ||||
-rw-r--r-- | src/include/taler_kyclogic_lib.h | 13 | ||||
-rw-r--r-- | src/kyclogic/kyclogic_api.c | 33 | ||||
-rw-r--r-- | src/lib/exchange_api_handle.c | 69 |
7 files changed, 159 insertions, 0 deletions
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 52e8ef6af..f45865381 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -176,6 +176,11 @@ float TEH_stefan_lin; json_t *TEH_hard_limits; /** + * JSON array with zero limits for /keys response. + */ +json_t *TEH_zero_limits; + +/** * Where to redirect users from "/"? */ static char *toplevel_redirect_url; @@ -2141,6 +2146,8 @@ exchange_serve_process_config (const char *cfg_fn) } TEH_hard_limits = TALER_KYCLOGIC_get_hard_limits (); + TEH_zero_limits + = TALER_KYCLOGIC_get_zero_limits (); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (TEH_cfg, "exchange", diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h index d6350c897..7f2233eab 100644 --- a/src/exchange/taler-exchange-httpd.h +++ b/src/exchange/taler-exchange-httpd.h @@ -103,6 +103,11 @@ extern struct TALER_EXCHANGEDB_Plugin *TEH_plugin; extern json_t *TEH_hard_limits; /** + * JSON array with zero limits for /keys response. + */ +extern json_t *TEH_zero_limits; + +/** * Absolute STEFAN parameter. */ extern struct TALER_Amount TEH_stefan_abs; diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c index e57e7d4f5..9998ccbbb 100644 --- a/src/exchange/taler-exchange-httpd_keys.c +++ b/src/exchange/taler-exchange-httpd_keys.c @@ -2416,6 +2416,9 @@ create_krd (struct TEH_KeyStateHandle *ksh, GNUNET_JSON_pack_array_incref ( "hard_limits", TEH_hard_limits), + GNUNET_JSON_pack_array_incref ( + "zero_limits", + TEH_zero_limits), TALER_JSON_pack_amount ("stefan_abs", &TEH_stefan_abs), TALER_JSON_pack_amount ("stefan_log", diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 3e6840266..b9b1f8778 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -450,6 +450,22 @@ struct TALER_EXCHANGE_WireAccount /** + * Applicable soft limits of zero for an account (or wallet). + * Clients should begin a KYC process before attempting + * these operations. + */ +struct TALER_EXCHANGE_ZeroLimitedOperation +{ + + /** + * Operation type for which the restriction applies. + */ + enum TALER_KYCLOGIC_KycTriggerEvent operation_type; + +}; + + +/** * Applicable limits for an account (or wallet). Exceeding these limits may * trigger additional KYC requirements or be categorically verboten. */ @@ -569,6 +585,14 @@ struct TALER_EXCHANGE_Keys struct TALER_EXCHANGE_AccountLimit *hard_limits; /** + * Array of operations with a default soft limit of zero + * that apply at this exchange. + * Clients should begin a KYC process before attempting + * these operations. + */ + struct TALER_EXCHANGE_ZeroLimitedOperation *zero_limits; + + /** * Array of wire fees by wire method. */ struct TALER_EXCHANGE_WireFeesByMethod *fees; @@ -638,6 +662,11 @@ struct TALER_EXCHANGE_Keys unsigned int hard_limits_length; /** + * Length of @e zero_limits array. + */ + unsigned int zero_limits_length; + + /** * Length of the @e wallet_balance_limit_without_kyc * array. */ diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h index 17ca2fe04..2387ac074 100644 --- a/src/include/taler_kyclogic_lib.h +++ b/src/include/taler_kyclogic_lib.h @@ -370,6 +370,19 @@ TALER_KYCLOGIC_get_hard_limits (void); /** + * Return JSON array of ZeroLimitedOperation objects with + * operations for which this exchange has a limit + * of zero, that means KYC is always required (or + * the operation is categorically forbidden). + * + * @return the JSON array of ZeroLimitedOperation objects, + * empty array if there are no hard limits + */ +json_t * +TALER_KYCLOGIC_get_zero_limits (void); + + +/** * Get human-readable name of KYC rule. * * @param r rule to convert diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c index 5f5b45f92..16cd16c72 100644 --- a/src/kyclogic/kyclogic_api.c +++ b/src/kyclogic/kyclogic_api.c @@ -3585,4 +3585,37 @@ TALER_KYCLOGIC_get_hard_limits () } +json_t * +TALER_KYCLOGIC_get_zero_limits () +{ + const struct TALER_KYCLOGIC_KycRule *rules + = default_rules.kyc_rules; + unsigned int num_rules + = default_rules.num_kyc_rules; + json_t *zero_limits; + + zero_limits = json_array (); + GNUNET_assert (NULL != zero_limits); + for (unsigned int i = 0; i<num_rules; i++) + { + const struct TALER_KYCLOGIC_KycRule *rule = &rules[i]; + json_t *zero_limit; + + if (! rule->exposed) + continue; + if (rule->verboten) + continue; /* see: hard_limits */ + if (! TALER_amount_is_zero (&rule->threshold)) + continue; + zero_limit = GNUNET_JSON_PACK ( + TALER_JSON_pack_kycte ("operation_type", + rule->trigger)); + GNUNET_assert (0 == + json_array_append_new (zero_limits, + zero_limit)); + } + return zero_limits; +} + + /* end of kyclogic_api.c */ diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c index 329e2c2e6..c39440857 100644 --- a/src/lib/exchange_api_handle.c +++ b/src/lib/exchange_api_handle.c @@ -813,6 +813,57 @@ parse_hard_limits (const json_t *hard_limits, /** + * Decode the JSON array in @a zero_limits from the /keys response + * and store the data in `zero_limits` array the @a key_data. + * + * @param[in] zero_limits JSON array to parse + * @param[out] key_data where to store the results we decoded + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + * (malformed JSON) + */ +static enum GNUNET_GenericReturnValue +parse_zero_limits (const json_t *zero_limits, + struct TALER_EXCHANGE_Keys *key_data) +{ + json_t *obj; + size_t off; + + key_data->zero_limits_length + = (unsigned int) json_array_size (zero_limits); + if ( ((size_t) key_data->zero_limits_length) + != json_array_size (zero_limits)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + key_data->zero_limits + = GNUNET_new_array (key_data->zero_limits_length, + struct TALER_EXCHANGE_ZeroLimitedOperation); + + json_array_foreach (zero_limits, off, obj) + { + struct TALER_EXCHANGE_ZeroLimitedOperation *zol + = &key_data->zero_limits[off]; + struct GNUNET_JSON_Specification spec[] = { + TALER_JSON_spec_kycte ("operation_type", + &zol->operation_type), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (obj, + spec, + NULL, NULL)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + } + return GNUNET_OK; +} + + +/** * Decode the JSON in @a resp_obj from the /keys response * and store the data in the @a key_data. * @@ -976,6 +1027,7 @@ decode_keys_json (const json_t *resp_obj, } { const json_t *hard_limits = NULL; + const json_t *zero_limits = NULL; struct GNUNET_JSON_Specification sspec[] = { TALER_JSON_spec_currency_specification ( "currency_specification", @@ -994,6 +1046,11 @@ decode_keys_json (const json_t *resp_obj, "hard_limits", &hard_limits), NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_array_const ( + "zero_limits", + &zero_limits), + NULL), GNUNET_JSON_spec_double ( "stefan_lin", &key_data->stefan_lin), @@ -1021,6 +1078,15 @@ decode_keys_json (const json_t *resp_obj, "Parsing hard limits of /keys failed\n"); EXITIF (1); } + if ( (NULL != zero_limits) && + (GNUNET_OK != + parse_zero_limits (zero_limits, + key_data)) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Parsing hard limits of /keys failed\n"); + EXITIF (1); + } } key_data->currency = GNUNET_strdup (currency); @@ -1964,6 +2030,9 @@ TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys) GNUNET_array_grow (keys->hard_limits, keys->hard_limits_length, 0); + GNUNET_array_grow (keys->zero_limits, + keys->zero_limits_length, + 0); json_decref (keys->extensions); GNUNET_free (keys->cspec.name); json_decref (keys->cspec.map_alt_unit_names); |