fix #7123
This commit is contained in:
parent
40175318e9
commit
a25429cadd
@ -30,14 +30,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the @a body as POST data to the easy handle in @a ctx.
|
|
||||||
*
|
|
||||||
* @param[in,out] ctx a request context (updated)
|
|
||||||
* @param eh easy handle to use
|
|
||||||
* @param body JSON body to add to @e ctx
|
|
||||||
* @return #GNUNET_OK on success #GNUNET_SYSERR on failure
|
|
||||||
*/
|
|
||||||
enum GNUNET_GenericReturnValue
|
enum GNUNET_GenericReturnValue
|
||||||
TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx,
|
TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx,
|
||||||
CURL *eh,
|
CURL *eh,
|
||||||
@ -101,11 +93,6 @@ TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free the data in @a ctx.
|
|
||||||
*
|
|
||||||
* @param[in] ctx a request context (updated)
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
TALER_curl_easy_post_finished (struct TALER_CURL_PostContext *ctx)
|
TALER_curl_easy_post_finished (struct TALER_CURL_PostContext *ctx)
|
||||||
{
|
{
|
||||||
|
@ -386,12 +386,6 @@ TALER_EXCHANGE_parse_reserve_history (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free memory (potentially) allocated by #TALER_EXCHANGE_parse_reserve_history().
|
|
||||||
*
|
|
||||||
* @param rhistory result to free
|
|
||||||
* @param len number of entries in @a rhistory
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
TALER_EXCHANGE_free_reserve_history (
|
TALER_EXCHANGE_free_reserve_history (
|
||||||
struct TALER_EXCHANGE_ReserveHistory *rhistory,
|
struct TALER_EXCHANGE_ReserveHistory *rhistory,
|
||||||
@ -416,17 +410,6 @@ TALER_EXCHANGE_free_reserve_history (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify a coins transaction history as returned by the exchange.
|
|
||||||
*
|
|
||||||
* @param dk fee structure for the coin, NULL to skip verifying fees
|
|
||||||
* @param currency expected currency for the coin
|
|
||||||
* @param coin_pub public key of the coin
|
|
||||||
* @param history history of the coin in json encoding
|
|
||||||
* @param[out] h_denom_pub set to the hash of the coin's denomination (if available)
|
|
||||||
* @param[out] total how much of the coin has been spent according to @a history
|
|
||||||
* @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not
|
|
||||||
*/
|
|
||||||
enum GNUNET_GenericReturnValue
|
enum GNUNET_GenericReturnValue
|
||||||
TALER_EXCHANGE_verify_coin_history (
|
TALER_EXCHANGE_verify_coin_history (
|
||||||
const struct TALER_EXCHANGE_DenomPublicKey *dk,
|
const struct TALER_EXCHANGE_DenomPublicKey *dk,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of TALER
|
This file is part of TALER
|
||||||
Copyright (C) 2014-2018 Taler Systems SA
|
Copyright (C) 2014-2018, 2021 Taler Systems SA
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
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
|
terms of the GNU General Public License as published by the Free Software
|
||||||
@ -23,12 +23,6 @@
|
|||||||
#include "exchange_api_curl_defaults.h"
|
#include "exchange_api_curl_defaults.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a curl handle with the right defaults for the exchange lib. In the
|
|
||||||
* future, we might manage a pool of connections here.
|
|
||||||
*
|
|
||||||
* @param url URL to query
|
|
||||||
*/
|
|
||||||
CURL *
|
CURL *
|
||||||
TALER_EXCHANGE_curl_easy_get_ (const char *url)
|
TALER_EXCHANGE_curl_easy_get_ (const char *url)
|
||||||
{
|
{
|
||||||
@ -45,6 +39,12 @@ TALER_EXCHANGE_curl_easy_get_ (const char *url)
|
|||||||
curl_easy_setopt (eh,
|
curl_easy_setopt (eh,
|
||||||
CURLOPT_FOLLOWLOCATION,
|
CURLOPT_FOLLOWLOCATION,
|
||||||
1L));
|
1L));
|
||||||
|
/* Enable compression (using whatever curl likes), see
|
||||||
|
https://curl.se/libcurl/c/CURLOPT_ACCEPT_ENCODING.html */
|
||||||
|
GNUNET_break (CURLE_OK ==
|
||||||
|
curl_easy_setopt (eh,
|
||||||
|
CURLOPT_ACCEPT_ENCODING,
|
||||||
|
""));
|
||||||
/* limit MAXREDIRS to 5 as a simple security measure against
|
/* limit MAXREDIRS to 5 as a simple security measure against
|
||||||
a potential infinite loop caused by a malicious target */
|
a potential infinite loop caused by a malicious target */
|
||||||
GNUNET_assert (CURLE_OK ==
|
GNUNET_assert (CURLE_OK ==
|
||||||
|
@ -166,13 +166,6 @@ struct KeysRequest
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signature of functions called with the result from our call to the
|
|
||||||
* auditor's /deposit-confirmation handler.
|
|
||||||
*
|
|
||||||
* @param cls closure of type `struct TEAH_AuditorInteractionEntry *`
|
|
||||||
* @param hr HTTP response
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
TEAH_acc_confirmation_cb (void *cls,
|
TEAH_acc_confirmation_cb (void *cls,
|
||||||
const struct TALER_AUDITOR_HttpResponse *hr)
|
const struct TALER_AUDITOR_HttpResponse *hr)
|
||||||
@ -195,15 +188,6 @@ TEAH_acc_confirmation_cb (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterate over all available auditors for @a h, calling
|
|
||||||
* @a ac and giving it a chance to start a deposit
|
|
||||||
* confirmation interaction.
|
|
||||||
*
|
|
||||||
* @param h exchange to go over auditors for
|
|
||||||
* @param ac function to call per auditor
|
|
||||||
* @param ac_cls closure for @a ac
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Handle *h,
|
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Handle *h,
|
||||||
TEAH_AuditorCallback ac,
|
TEAH_AuditorCallback ac,
|
||||||
@ -1054,12 +1038,6 @@ static void
|
|||||||
request_keys (void *cls);
|
request_keys (void *cls);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Let the user set the last valid denomination time manually.
|
|
||||||
*
|
|
||||||
* @param exchange the exchange handle.
|
|
||||||
* @param last_denom_new new last denomination time.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
TALER_EXCHANGE_set_last_denom (struct TALER_EXCHANGE_Handle *exchange,
|
TALER_EXCHANGE_set_last_denom (struct TALER_EXCHANGE_Handle *exchange,
|
||||||
struct GNUNET_TIME_Absolute last_denom_new)
|
struct GNUNET_TIME_Absolute last_denom_new)
|
||||||
@ -1071,14 +1049,6 @@ TALER_EXCHANGE_set_last_denom (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if our current response for /keys is valid, and if
|
|
||||||
* not trigger download.
|
|
||||||
*
|
|
||||||
* @param exchange exchange to check keys for
|
|
||||||
* @param flags options controlling when to download what
|
|
||||||
* @return until when the response is current, 0 if we are re-downloading
|
|
||||||
*/
|
|
||||||
struct GNUNET_TIME_Absolute
|
struct GNUNET_TIME_Absolute
|
||||||
TALER_EXCHANGE_check_keys_current (struct TALER_EXCHANGE_Handle *exchange,
|
TALER_EXCHANGE_check_keys_current (struct TALER_EXCHANGE_Handle *exchange,
|
||||||
enum TALER_EXCHANGE_CheckKeysFlags flags)
|
enum TALER_EXCHANGE_CheckKeysFlags flags)
|
||||||
@ -1330,12 +1300,6 @@ keys_completed_cb (void *cls,
|
|||||||
/* ********************* library internal API ********* */
|
/* ********************* library internal API ********* */
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the context of a exchange.
|
|
||||||
*
|
|
||||||
* @param h the exchange handle to query
|
|
||||||
* @return ctx context to execute jobs in
|
|
||||||
*/
|
|
||||||
struct GNUNET_CURL_Context *
|
struct GNUNET_CURL_Context *
|
||||||
TEAH_handle_to_context (struct TALER_EXCHANGE_Handle *h)
|
TEAH_handle_to_context (struct TALER_EXCHANGE_Handle *h)
|
||||||
{
|
{
|
||||||
@ -1343,12 +1307,6 @@ TEAH_handle_to_context (struct TALER_EXCHANGE_Handle *h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the handle is ready to process requests.
|
|
||||||
*
|
|
||||||
* @param h the exchange handle to query
|
|
||||||
* @return #GNUNET_YES if we are ready, #GNUNET_NO if not
|
|
||||||
*/
|
|
||||||
enum GNUNET_GenericReturnValue
|
enum GNUNET_GenericReturnValue
|
||||||
TEAH_handle_is_ready (struct TALER_EXCHANGE_Handle *h)
|
TEAH_handle_is_ready (struct TALER_EXCHANGE_Handle *h)
|
||||||
{
|
{
|
||||||
@ -1356,13 +1314,6 @@ TEAH_handle_is_ready (struct TALER_EXCHANGE_Handle *h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the URL to use for an API request.
|
|
||||||
*
|
|
||||||
* @param h handle for the exchange
|
|
||||||
* @param path Taler API path (i.e. "/reserve/withdraw")
|
|
||||||
* @return the full URL to use with cURL
|
|
||||||
*/
|
|
||||||
char *
|
char *
|
||||||
TEAH_path_to_url (struct TALER_EXCHANGE_Handle *h,
|
TEAH_path_to_url (struct TALER_EXCHANGE_Handle *h,
|
||||||
const char *path)
|
const char *path)
|
||||||
@ -1611,17 +1562,6 @@ deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialize the latest key data from @a
|
|
||||||
* exchange to be persisted on disk (to be used with
|
|
||||||
* #TALER_EXCHANGE_OPTION_DATA to more efficiently recover
|
|
||||||
* the state).
|
|
||||||
*
|
|
||||||
* @param exchange which exchange's key and wire data should be
|
|
||||||
* serialized
|
|
||||||
* @return NULL on error (i.e. no current data available);
|
|
||||||
* otherwise JSON object owned by the caller
|
|
||||||
*/
|
|
||||||
json_t *
|
json_t *
|
||||||
TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange)
|
TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange)
|
||||||
{
|
{
|
||||||
@ -1790,24 +1730,6 @@ TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise a connection to the exchange. Will connect to the
|
|
||||||
* exchange and obtain information about the exchange's master
|
|
||||||
* public key and the exchange's auditor.
|
|
||||||
* The respective information will be passed to the @a cert_cb
|
|
||||||
* once available, and all future interactions with the exchange
|
|
||||||
* will be checked to be signed (where appropriate) by the
|
|
||||||
* respective master key.
|
|
||||||
*
|
|
||||||
* @param ctx the context
|
|
||||||
* @param url HTTP base URL for the exchange
|
|
||||||
* @param cert_cb function to call with the exchange's
|
|
||||||
* certification information
|
|
||||||
* @param cert_cb_cls closure for @a cert_cb
|
|
||||||
* @param ... list of additional arguments,
|
|
||||||
* terminated by #TALER_EXCHANGE_OPTION_END.
|
|
||||||
* @return the exchange handle; NULL upon error
|
|
||||||
*/
|
|
||||||
struct TALER_EXCHANGE_Handle *
|
struct TALER_EXCHANGE_Handle *
|
||||||
TALER_EXCHANGE_connect (
|
TALER_EXCHANGE_connect (
|
||||||
struct GNUNET_CURL_Context *ctx,
|
struct GNUNET_CURL_Context *ctx,
|
||||||
@ -1825,7 +1747,7 @@ TALER_EXCHANGE_connect (
|
|||||||
/* Disable 100 continue processing */
|
/* Disable 100 continue processing */
|
||||||
GNUNET_break (GNUNET_OK ==
|
GNUNET_break (GNUNET_OK ==
|
||||||
GNUNET_CURL_append_header (ctx,
|
GNUNET_CURL_append_header (ctx,
|
||||||
"Expect:"));
|
MHD_HTTP_HEADER_EXPECT ":"));
|
||||||
exchange = GNUNET_new (struct TALER_EXCHANGE_Handle);
|
exchange = GNUNET_new (struct TALER_EXCHANGE_Handle);
|
||||||
exchange->ctx = ctx;
|
exchange->ctx = ctx;
|
||||||
exchange->url = GNUNET_strdup (url);
|
exchange->url = GNUNET_strdup (url);
|
||||||
@ -1968,11 +1890,6 @@ request_keys (void *cls)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect from the exchange
|
|
||||||
*
|
|
||||||
* @param exchange the exchange handle
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange)
|
TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange)
|
||||||
{
|
{
|
||||||
@ -2025,14 +1942,6 @@ TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if the given @a pub is a the current signing key from the exchange
|
|
||||||
* according to @a keys.
|
|
||||||
*
|
|
||||||
* @param keys the exchange's key set
|
|
||||||
* @param pub claimed current online signing key for the exchange
|
|
||||||
* @return #GNUNET_OK if @a pub is (according to /keys) a current signing key
|
|
||||||
*/
|
|
||||||
enum GNUNET_GenericReturnValue
|
enum GNUNET_GenericReturnValue
|
||||||
TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys,
|
TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys,
|
||||||
const struct TALER_ExchangePublicKeyP *pub)
|
const struct TALER_ExchangePublicKeyP *pub)
|
||||||
@ -2058,12 +1967,6 @@ TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get exchange's base URL.
|
|
||||||
*
|
|
||||||
* @param exchange exchange handle.
|
|
||||||
* @return the base URL from the handle.
|
|
||||||
*/
|
|
||||||
const char *
|
const char *
|
||||||
TALER_EXCHANGE_get_base_url (const struct TALER_EXCHANGE_Handle *exchange)
|
TALER_EXCHANGE_get_base_url (const struct TALER_EXCHANGE_Handle *exchange)
|
||||||
{
|
{
|
||||||
@ -2071,14 +1974,6 @@ TALER_EXCHANGE_get_base_url (const struct TALER_EXCHANGE_Handle *exchange)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the denomination key details from the exchange.
|
|
||||||
*
|
|
||||||
* @param keys the exchange's key set
|
|
||||||
* @param pk public key of the denomination to lookup
|
|
||||||
* @return details about the given denomination key, NULL if the key is
|
|
||||||
* not found
|
|
||||||
*/
|
|
||||||
const struct TALER_EXCHANGE_DenomPublicKey *
|
const struct TALER_EXCHANGE_DenomPublicKey *
|
||||||
TALER_EXCHANGE_get_denomination_key (
|
TALER_EXCHANGE_get_denomination_key (
|
||||||
const struct TALER_EXCHANGE_Keys *keys,
|
const struct TALER_EXCHANGE_Keys *keys,
|
||||||
@ -2093,12 +1988,6 @@ TALER_EXCHANGE_get_denomination_key (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a copy of a denomination public key.
|
|
||||||
*
|
|
||||||
* @param key key to copy
|
|
||||||
* @returns a copy, must be freed with #TALER_EXCHANGE_destroy_denomination_key
|
|
||||||
*/
|
|
||||||
struct TALER_EXCHANGE_DenomPublicKey *
|
struct TALER_EXCHANGE_DenomPublicKey *
|
||||||
TALER_EXCHANGE_copy_denomination_key (
|
TALER_EXCHANGE_copy_denomination_key (
|
||||||
const struct TALER_EXCHANGE_DenomPublicKey *key)
|
const struct TALER_EXCHANGE_DenomPublicKey *key)
|
||||||
@ -2113,12 +2002,6 @@ TALER_EXCHANGE_copy_denomination_key (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy a denomination public key.
|
|
||||||
* Should only be called with keys created by #TALER_EXCHANGE_copy_denomination_key.
|
|
||||||
*
|
|
||||||
* @param key key to destroy.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
TALER_EXCHANGE_destroy_denomination_key (
|
TALER_EXCHANGE_destroy_denomination_key (
|
||||||
struct TALER_EXCHANGE_DenomPublicKey *key)
|
struct TALER_EXCHANGE_DenomPublicKey *key)
|
||||||
@ -2128,13 +2011,6 @@ TALER_EXCHANGE_destroy_denomination_key (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the denomination key details from the exchange.
|
|
||||||
*
|
|
||||||
* @param keys the exchange's key set
|
|
||||||
* @param hc hash of the public key of the denomination to lookup
|
|
||||||
* @return details about the given denomination key
|
|
||||||
*/
|
|
||||||
const struct TALER_EXCHANGE_DenomPublicKey *
|
const struct TALER_EXCHANGE_DenomPublicKey *
|
||||||
TALER_EXCHANGE_get_denomination_key_by_hash (
|
TALER_EXCHANGE_get_denomination_key_by_hash (
|
||||||
const struct TALER_EXCHANGE_Keys *keys,
|
const struct TALER_EXCHANGE_Keys *keys,
|
||||||
@ -2148,12 +2024,6 @@ TALER_EXCHANGE_get_denomination_key_by_hash (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the keys from the exchange.
|
|
||||||
*
|
|
||||||
* @param exchange the exchange handle
|
|
||||||
* @return the exchange's key set
|
|
||||||
*/
|
|
||||||
const struct TALER_EXCHANGE_Keys *
|
const struct TALER_EXCHANGE_Keys *
|
||||||
TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange)
|
TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange)
|
||||||
{
|
{
|
||||||
@ -2163,13 +2033,6 @@ TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the keys from the exchange in the
|
|
||||||
* raw JSON format
|
|
||||||
*
|
|
||||||
* @param exchange the exchange handle
|
|
||||||
* @return the exchange's keys in raw JSON
|
|
||||||
*/
|
|
||||||
json_t *
|
json_t *
|
||||||
TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange)
|
TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange)
|
||||||
{
|
{
|
||||||
|
@ -418,19 +418,6 @@ handle_link_finished (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit a link request to the exchange and get the exchange's response.
|
|
||||||
*
|
|
||||||
* This API is typically not used by anyone, it is more a threat against those
|
|
||||||
* trying to receive a funds transfer by abusing the refresh protocol.
|
|
||||||
*
|
|
||||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
|
||||||
* @param coin_priv private key to request link data for
|
|
||||||
* @param link_cb the callback to call with the useful result of the
|
|
||||||
* refresh operation the @a coin_priv was involved in (if any)
|
|
||||||
* @param link_cb_cls closure for @a link_cb
|
|
||||||
* @return a handle for this request
|
|
||||||
*/
|
|
||||||
struct TALER_EXCHANGE_LinkHandle *
|
struct TALER_EXCHANGE_LinkHandle *
|
||||||
TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange,
|
TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange,
|
||||||
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
|
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
|
||||||
@ -496,12 +483,6 @@ TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel a link request. This function cannot be used
|
|
||||||
* on a request handle if the callback was already invoked.
|
|
||||||
*
|
|
||||||
* @param lh the link handle
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
TALER_EXCHANGE_link_cancel (struct TALER_EXCHANGE_LinkHandle *lh)
|
TALER_EXCHANGE_link_cancel (struct TALER_EXCHANGE_LinkHandle *lh)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user