Merge branch 'master' into age-withdraw-merge

This commit is contained in:
Özgür Kesim 2023-06-26 00:09:01 +02:00
commit b87d1112ea
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7
98 changed files with 4392 additions and 3325 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
\section{Deposit}
\section{Deposit} \label{sec:deposit}
% FIXME: split up between deposit to merchant
% and deposit to customer's (own) bank account!
\begin{figure}[h!]
\begin{sequencediagram}

View File

@ -49,9 +49,10 @@ if required.
\begin{table}[h!]
\caption{Settings for the balance trigger}
\caption{Settings for the balance trigger.}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Default AML threshold & Amount & {\em 1000 CHF} \\
KYC threshold & Amount & {\em 5000 CHF} \\
Default AML threshold & Amount & {\em 5000 CHF} \\
\end{tabular}
\end{table}

View File

@ -61,11 +61,13 @@
\begin{table}[h!]
\caption{Settings for the deposit trigger}
\caption{Settings for the deposit trigger. Note that the operation
must satisfy all of the given rules.}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Allowed bank accounts & RFC 8905 RegEx & {\em CH*} \\ \hline
KYC deposit threshold & Amount & {\em 1000 CHF} \\
Default AML deposit threshold & Amount & {\em 2500 CHF} \\
KYC deposit threshold & Amount/month & {\em 5000 CHF} \\
KYC deposit threshold & Amount/year & {\em 15000 CHF} \\
Default AML deposit threshold & Amount/month & {\em 2500 CHF} \\
\end{tabular}
\end{table}

View File

@ -68,11 +68,13 @@
\begin{table}[h!]
\caption{Settings for the pull payment trigger}
\caption{Settings for the pull payment trigger. Note that the operation
must satisfy all of the given rules.}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Permitted phone numbers & Dialing prefix & {\em +41} \\
P2P KYC threshold & Amount & {\em 100 CHF} \\
Default P2P AML threshold & Amount & {\em 1000 CHF} \\
P2P KYC threshold & Amount/month & {\em 5000 CHF} \\
P2P KYC threshold & Amount/year & {\em 15000 CHF} \\
Default P2P AML threshold & Amount/month & {\em 1000 CHF} \\
\end{tabular}
\end{table}

View File

@ -69,11 +69,13 @@
\begin{table}[h!]
\caption{Settings for the push payment trigger}
\caption{Settings for the push payment trigger. Note that the operation
must satisfy all of the given rules.}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Permitted phone numbers & Dialing prefix & {\em +41} \\
P2P KYC threshold & Amount & {\em 100 CHF} \\
Default P2P AML threshold & Amount & {\em 1000 CHF} \\
P2P KYC threshold & Amount/month & {\em 5000 CHF} \\
P2P KYC threshold & Amount/year & {\em 15000 CHF} \\
Default P2P AML threshold & Amount & {\em 1000 CHF} \\
\end{tabular}
\end{table}

View File

@ -30,16 +30,21 @@
\end{center}
\caption{Regulatory process when withdrawing digital cash from a
bank account.
When the transfer is denied the money is (eventually) returned to
If the transfer is denied or the user fails to withdraw the
funds for any other reason, the money is automatically returned
after the bounce period (see Table~\ref{table:kyc:withdraw:settings}) to
the originating bank account.}
\label{fig:kyc:withdraw}
\end{figure}
\begin{table}[h!]
\caption{Settings for the withdraw trigger}
\caption{Settings for the withdraw trigger. Note that the operation
must satisfy all of the given rules.} \label{table:kyc:withdraw:settings}
\begin{tabular}{l|l|r}
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Allowed bank accounts & RFC 8905 RegEx & {\em CH*} \\ \hline
Monthly withdraw maximum & Amount & {\em 1000 CHF} \\
{\bf Setting} & {\bf Type} & {\bf Value} \\ \hline \hline
Allowed bank accounts & RFC 8905 RegEx & {\em CH*} \\ \hline
Withdraw maximum & Amount/month & {\em 5000 CHF} \\
Withdraw maximum & Amount/year & {\em 15000 CHF} \\
Bounce period & Delay & 1 month \\
\end{tabular}
\end{table}

View File

@ -37,16 +37,48 @@ The main interactions of the system are:
\item[shutdown] the Taler payment system operator informs the customers that the system is being shut down for good
\end{description}
Taler has no accounts (this is digital cash) and thus there is no ``opening''
or ``closing'' of accounts. The equivalent of ``opening'' an account is thus
to withdraw digital cash. The equivalent of ``closing'' an account is to
either (1) deposit the funds explicitly into a bank account, or (2) the coins
will expire if the wallet was lost (including long-term offline or
{\bf Customers} begin their business relationship with us when they withdraw
digital cash. Taler has no accounts (this is digital cash) and thus there is
no ``opening'' or ``closing'' of accounts for consumers. Given digital cash,
the customers can either (1) deposit the funds explicitly into a bank account
(see Section~\ref{sec:deposit}), (2) pay a merchant (see
Section~\ref{sec:deposit}), (3) pay another customer using a peer-to-peer
transfer (see Sections~\ref{sec:push} and~\ref{sec:pull}), or (4) the coins
will expire if the wallet was lost (including offline for a long time or
uninstalled). Finally, if a wallet remains (occasionally) online but a user
does simply not spend the coins will (3) diminish in value from the change
does simply not spend the coins will (5) diminish in value from the change
fees (see Section~\ref{sec:fees:coin}) that apply to prevent the coins from
expiring outright.
For customers, we will categorically limit of digital cash withdrawn per month
to less than CHF 5000 per month and less than CHF 15000 per year, thus
ensuring that consumers remain below the thresholds where most regulatory
processes become applicable. We will, however, ensure that customers are Swiss
(see Section~\ref{sec:proc:domestic}) by requiring them to have a Swiss bank
account and/or Swiss phone number (+41-prefix). Furthermore, the wallet will
impose an upper limit of CHF 5000 on its balance at any point in time.
For {\bf merchants}, the Taler equivalent of ``opening'' an account and thus
establishing an ongoing business relationship is for a business to receive
payments (see Section~\ref{sec:deposit}) exceeding CHF 5000/month or CHF
15000/year. We will consider the account ``open'' (and require up-to-date KYB
information and check sanction lists) as long as the business has made any
transactions within the last 24 months.
In contrast to normal customers, merchants can in principle {\bf receive}
payments without limit. However, these transactions must go into the bank
account of the business: when digital coins are deposited at a business in
Taler, the business never actually receives usable digital coins but instead
the amount is always directly credited to their bank account. Depending on
the transacted amounts, the business will be subject to KYB
(Section~\ref{sec:proc:kyb}) and AML checks. As we will only transfer money
into the existing bank accounts of the merchants to compensate them for sales
made using the Taler payment system, we do not need to check the origin of
funds for those merchants as they will only receive funds from
us.\footnote{Should businesses want to use Taler for expenditures, they will
need to withdraw digital coins from their bank account just like customers,
and the limits for customers will continue to apply.}
The following sections describe the respective processes for each of these
interactions.
@ -119,7 +151,8 @@ The three main regulatory processes are:
\end{description}
\include{proc-domestic}
\include{proc-kyc}
%\include{proc-kyc}
\include{proc-kyb}
\include{proc-aml}
\chapter{Fees} \label{chap:fees}

View File

@ -1,4 +1,4 @@
\section{Domestic wallet check}
\section{Domestic wallet check} \label{sec:proc:domestic}
\begin{figure}[h!]
\begin{sequencediagram}

View File

@ -157,6 +157,8 @@ handle_config (struct TAH_RequestHandler *rh,
if (NULL == ver)
{
ver = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("name",
"taler-auditor"),
GNUNET_JSON_pack_string ("version",
AUDITOR_PROTOCOL_VERSION),
GNUNET_JSON_pack_string ("currency",

View File

@ -514,7 +514,7 @@ parallel_benchmark (TALER_TESTING_Main main_cb,
/* We always wait for the exchange, no matter if it's running locally or
remotely */
if (0 != TALER_TESTING_wait_exchange_ready (ec.exchange_url))
if (0 != TALER_TESTING_wait_httpd_ready (ec.exchange_url))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to detect running exchange at `%s'\n",

View File

@ -147,6 +147,10 @@ kyc_aml_finished (void *cls,
ea,
0 != code);
GNUNET_free (ea);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Stored encrypted KYC process #%llu attributes: %d\n",
(unsigned long long) kat->process_row,
qs);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
GNUNET_break (0);

View File

@ -601,11 +601,12 @@ TEH_handler_kyc_check (
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Suspending HTTP request on timeout (%s) now...\n",
GNUNET_TIME_relative2s (GNUNET_TIME_absolute_get_duration (
GNUNET_TIME_relative2s (GNUNET_TIME_absolute_get_remaining (
kyp->timeout),
true));
GNUNET_assert (NULL != kyp->eh);
kyp->suspended = true;
kyp->section_name = NULL;
GNUNET_CONTAINER_DLL_insert (kyp_head,
kyp_tail,
kyp);

View File

@ -221,6 +221,9 @@ proof_cb (
&old_scope);
if (TALER_KYCLOGIC_STATUS_SUCCESS == status)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"KYC process #%llu succeeded with KYC provider\n",
(unsigned long long) kpc->process_row);
kpc->kat = TEH_kyc_finished (&rc->async_scope_id,
kpc->process_row,
&kpc->h_payto,

View File

@ -65,7 +65,9 @@ BEGIN
,expiration_date=GREATEST(expiration_date,in_expiration_date)
,gc_date=GREATEST(gc_date,in_expiration_date)
WHERE reserve_pub=in_reserve_pub;
PERFORM pg_notify(in_notify, NULL);
EXECUTE FORMAT (
'NOTIFY %s'
,in_notify);
ELSE
out_duplicate = TRUE;
END IF;

View File

@ -75,8 +75,10 @@ THEN
UPDATE SET status=EXCLUDED.status | 1;
END IF;
-- Wake up everyone who might care...
PERFORM pg_notify (in_kyc_completed_notify_s, NULL);
EXECUTE FORMAT (
'NOTIFY %s'
,in_kyc_completed_notify_s);
INSERT INTO kyc_alerts
(h_payto

View File

@ -89,6 +89,7 @@ TEH_PG_insert_aml_decision (
params,
rs);
GNUNET_free (notify_s);
GNUNET_PQ_event_do_poll (pg->conn);
if (NULL != kyc_s)
free (kyc_s);
return qs;

View File

@ -25,6 +25,9 @@
#include "pg_insert_kyc_attributes.h"
#include "pg_helper.h"
void
event_do_poll (struct GNUNET_PQ_Context *db);
enum GNUNET_DB_QueryStatus
TEH_PG_insert_kyc_attributes (
@ -81,6 +84,9 @@ TEH_PG_insert_kyc_attributes (
};
enum GNUNET_DB_QueryStatus qs;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Inserting KYC attributes, wake up on %s\n",
kyc_completed_notify_s);
PREPARE (pg,
"insert_kyc_attributes",
"SELECT "
@ -92,6 +98,8 @@ TEH_PG_insert_kyc_attributes (
params,
rs);
GNUNET_free (kyc_completed_notify_s);
GNUNET_PQ_event_do_poll (pg->conn);
if (qs < 0)
return qs;
if (! ok)

View File

@ -611,6 +611,7 @@ TEH_PG_reserves_in_insert (
reserves_length,
batch_size,
results);
GNUNET_PQ_event_do_poll (pg->conn);
for (unsigned int i = 0; i<reserves_length; i++)
GNUNET_free (rrs[i].notify_s);
return qs;
@ -889,6 +890,7 @@ TEH_PG_reserves_in_insertN (
}
}
finished:
GNUNET_PQ_event_do_poll (pg->conn);
for (unsigned int i = 0; i<reserves_length; i++)
GNUNET_free (rrs[i].notify_s);
return qs;

View File

@ -2,9 +2,9 @@
# This file is in the public domain.
set -eu
echo "Initializing DB"
taler-exchange-dbinit -r test-exchange-db-postgres.conf
taler-exchange-dbinit -r -c test-exchange-db-postgres.conf
echo "Re-initializing DB"
taler-exchange-dbinit test-exchange-db-postgres.conf
taler-exchange-dbinit -c test-exchange-db-postgres.conf
echo "Re-loading procedures"
psql talercheck < procedures.sql
echo "Test PASSED"

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2021 Taler Systems SA
Copyright (C) 2014-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@ -28,12 +28,12 @@
#include <gnunet/gnunet_curl_lib.h>
/* ********************* /version *********************** */
/* ********************* /config *********************** */
/**
* @brief Information we get from the auditor about auditors.
* @brief Information we get from the auditor about itself.
*/
struct TALER_AUDITOR_VersionInformation
struct TALER_AUDITOR_ConfigInformation
{
/**
* Public key of the auditing institution. Wallets and merchants
@ -146,58 +146,91 @@ struct TALER_AUDITOR_HttpResponse
};
/**
* Response to /config request.
*/
struct TALER_AUDITOR_ConfigResponse
{
/**
* HTTP response.
*/
struct TALER_AUDITOR_HttpResponse hr;
/**
* Details depending on HTTP status.
*/
union
{
/**
* Details for #MHD_HTTP_OK.
*/
struct
{
/**
* Protocol compatibility evaluation.
*/
enum TALER_AUDITOR_VersionCompatibility compat;
/**
* Config data returned by /config.
*/
struct TALER_AUDITOR_ConfigInformation vi;
} ok;
} details;
};
/**
* Function called with information about the auditor.
*
* @param cls closure
* @param hr HTTP response data
* @param vi basic information about the auditor
* @param compat protocol compatibility information
* @param vr response data
*/
// FIXME: bad API!
typedef void
(*TALER_AUDITOR_VersionCallback) (
(*TALER_AUDITOR_ConfigCallback) (
void *cls,
const struct TALER_AUDITOR_HttpResponse *hr,
const struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility compat);
const struct TALER_AUDITOR_ConfigResponse *vr);
/**
* @brief Handle to the auditor. This is where we interact with
* a particular auditor and keep the per-auditor information.
*/
struct TALER_AUDITOR_Handle;
struct TALER_AUDITOR_GetConfigHandle;
/**
* Initialise a connection to the auditor. Will connect to the
* Obtain meta data about an auditor. Will connect to the
* auditor and obtain information about the auditor's master public
* key and the auditor's auditor. The respective information will
* be passed to the @a version_cb once available, and all future
* interactions with the auditor will be checked to be signed
* (where appropriate) by the respective master key.
* be passed to the @a config_cb once available.
*
* @param ctx the context
* @param ctx the context for CURL requests
* @param url HTTP base URL for the auditor
* @param version_cb function to call with the auditor's version information
* @param version_cb_cls closure for @a version_cb
* @param config_cb function to call with the auditor's config information
* @param config_cb_cls closure for @a config_cb
* @return the auditor handle; NULL upon error
*/
struct TALER_AUDITOR_Handle *
TALER_AUDITOR_connect (struct GNUNET_CURL_Context *ctx,
const char *url,
TALER_AUDITOR_VersionCallback version_cb,
void *version_cb_cls);
struct TALER_AUDITOR_GetConfigHandle *
TALER_AUDITOR_get_config (struct GNUNET_CURL_Context *ctx,
const char *url,
TALER_AUDITOR_ConfigCallback config_cb,
void *config_cb_cls);
/**
* Disconnect from the auditor.
* Cancel auditor config request.
*
* @param auditor the auditor handle
*/
void
TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor);
TALER_AUDITOR_get_config_cancel (struct
TALER_AUDITOR_GetConfigHandle *auditor);
/**
@ -206,17 +239,29 @@ TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor);
struct TALER_AUDITOR_DepositConfirmationHandle;
/**
* Response to /deposit-confirmation request.
*/
struct TALER_AUDITOR_DepositConfirmationResponse
{
/**
* HTTP response.
*/
struct TALER_AUDITOR_HttpResponse hr;
};
/**
* Signature of functions called with the result from our call to the
* auditor's /deposit-confirmation handler.
*
* @param cls closure
* @param hr HTTP response data
* @param dcr response data
*/
typedef void
(*TALER_AUDITOR_DepositConfirmationResultCallback)(
void *cls,
const struct TALER_AUDITOR_HttpResponse *hr);
const struct TALER_AUDITOR_DepositConfirmationResponse *dcr);
/**
@ -226,13 +271,13 @@ typedef void
* that the response is well-formed. If the auditor's reply is not
* well-formed, we return an HTTP status code of zero to @a cb.
*
* We also verify that the @a exchange_sig is valid for this deposit-confirmation
* request, and that the @a master_sig is a valid signature for @a
* exchange_pub. Also, the @a auditor must be ready to operate (i.e. have
* finished processing the /version reply). If either check fails, we do
* NOT initiate the transaction with the auditor and instead return NULL.
* We also verify that the @a exchange_sig is valid for this
* deposit-confirmation request, and that the @a master_sig is a valid
* signature for @a exchange_pub. If the check fails, we do NOT initiate the
* transaction with the auditor and instead return NULL.
*
* @param auditor the auditor handle; the auditor must be ready to operate
* @param ctx the context for CURL requests
* @param url HTTP base URL for the auditor
* @param h_wire hash of merchant wire details
* @param h_policy hash over the policy, if any
* @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the auditor)
@ -256,7 +301,8 @@ typedef void
*/
struct TALER_AUDITOR_DepositConfirmationHandle *
TALER_AUDITOR_deposit_confirmation (
struct TALER_AUDITOR_Handle *auditor,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_MerchantWireHashP *h_wire,
const struct TALER_ExtensionPolicyHashP *h_policy,
const struct TALER_PrivateContractHashP *h_contract_terms,
@ -313,34 +359,70 @@ struct TALER_AUDITOR_ExchangeInfo
};
/**
* Response to GET /exchanges request.
*/
struct TALER_AUDITOR_ListExchangesResponse
{
/**
* HTTP response.
*/
struct TALER_AUDITOR_HttpResponse hr;
/**
* Details depending on HTTP status.
*/
union
{
/**
* Details for #MHD_HTTP_OK.
*/
struct
{
/**
* Length of the @e ei array.
*/
unsigned int num_exchanges;
/**
* Array with information about exchanges
* audited by this auditor.
*/
const struct TALER_AUDITOR_ExchangeInfo *ei;
} ok;
} details;
};
/**
* Function called with the result from /exchanges.
*
* @param cls closure
* @param hr HTTP response data
* @param num_exchanges length of array at @a ei
* @param ei information about exchanges returned by the auditor
* @param ler response data
*/
typedef void
(*TALER_AUDITOR_ListExchangesResultCallback)(
void *cls,
const struct TALER_AUDITOR_HttpResponse *hr,
unsigned int num_exchanges,
const struct TALER_AUDITOR_ExchangeInfo *ei);
const struct TALER_AUDITOR_ListExchangesResponse *ler);
/**
* Submit an /exchanges request to the auditor and get the
* auditor's response. If the auditor's reply is not
* well-formed, we return an HTTP status code of zero to @a cb.
*
* @param auditor the auditor handle; the auditor must be ready to operate
* @param ctx the context for CURL requests
* @param url HTTP base URL for the auditor
* @param cb the callback to call when a reply for this request is available
* @param cb_cls closure for the above callback
* @return a handle for this request; NULL if the inputs are invalid (i.e.
* signatures fail to verify). In this case, the callback is not called.
*/
struct TALER_AUDITOR_ListExchangesHandle *
TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle *auditor,
TALER_AUDITOR_list_exchanges (struct GNUNET_CURL_Context *ctx,
const char *url,
TALER_AUDITOR_ListExchangesResultCallback cb,
void *cb_cls);

View File

@ -573,10 +573,30 @@ TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange);
* @param exchange the exchange handle
* @return the exchange's key set
*/
const struct TALER_EXCHANGE_Keys *
struct TALER_EXCHANGE_Keys *
TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange);
/**
* Increment reference counter for @a keys
*
* @param[in,out] keys object to increment reference counter for
* @return keys, with incremented reference counter
*/
struct TALER_EXCHANGE_Keys *
TALER_EXCHANGE_keys_incref (struct TALER_EXCHANGE_Keys *keys);
/**
* Deccrement reference counter for @a keys.
* Frees @a keys if reference counter becomes zero.
*
* @param[in,out] keys object to decrement reference counter for
*/
void
TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys);
/**
* Let the user set the last valid denomination time manually.
*
@ -584,8 +604,9 @@ TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange);
* @param last_denom_new new last denomination time.
*/
void
TALER_EXCHANGE_set_last_denom (struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_TIME_Timestamp last_denom_new);
TALER_EXCHANGE_set_last_denom (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_TIME_Timestamp last_denom_new);
/**
@ -633,10 +654,11 @@ enum TALER_EXCHANGE_CheckKeysFlags
* @return until when the existing response is current, 0 if we are re-downloading now
*/
struct GNUNET_TIME_Timestamp
TALER_EXCHANGE_check_keys_current (struct TALER_EXCHANGE_Handle *exchange,
enum TALER_EXCHANGE_CheckKeysFlags flags,
TALER_EXCHANGE_CertificationCallback cb,
void *cb_cls);
TALER_EXCHANGE_check_keys_current (
struct TALER_EXCHANGE_Handle *exchange,
enum TALER_EXCHANGE_CheckKeysFlags flags,
TALER_EXCHANGE_CertificationCallback cb,
void *cb_cls);
/**
@ -649,6 +671,16 @@ json_t *
TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange);
/**
* Obtain the keys from the exchange in the raw JSON format.
*
* @param keys the keys structure
* @return the keys in raw JSON
*/
json_t *
TALER_EXCHANGE_keys_to_json (struct TALER_EXCHANGE_Keys *keys);
/**
* Test if the given @a pub is a the current signing key from the exchange
* according to @a keys.
@ -1035,9 +1067,10 @@ struct TALER_EXCHANGE_WireHandle;
* @return a handle for this request
*/
struct TALER_EXCHANGE_WireHandle *
TALER_EXCHANGE_wire (struct TALER_EXCHANGE_Handle *exchange,
TALER_EXCHANGE_WireCallback wire_cb,
void *wire_cb_cls);
TALER_EXCHANGE_wire (
struct TALER_EXCHANGE_Handle *exchange,
TALER_EXCHANGE_WireCallback wire_cb,
void *wire_cb_cls);
/**
@ -1151,135 +1184,6 @@ struct TALER_EXCHANGE_DepositContractDetail
};
/**
* @brief A Deposit Handle
*/
struct TALER_EXCHANGE_DepositHandle;
/**
* Structure with information about a deposit
* operation's result.
*/
struct TALER_EXCHANGE_DepositResult
{
/**
* HTTP response data
*/
struct TALER_EXCHANGE_HttpResponse hr;
union
{
/**
* Information returned if the HTTP status is
* #MHD_HTTP_OK.
*/
struct
{
/**
* Time when the exchange generated the deposit confirmation
*/
struct GNUNET_TIME_Timestamp deposit_timestamp;
/**
* signature provided by the exchange
*/
const struct TALER_ExchangeSignatureP *exchange_sig;
/**
* exchange key used to sign @a exchange_sig.
*/
const struct TALER_ExchangePublicKeyP *exchange_pub;
/**
* Base URL for looking up wire transfers, or
* NULL to use the default base URL.
*/
const char *transaction_base_url;
} ok;
/**
* Information returned if the HTTP status is
* #MHD_HTTP_CONFLICT.
*/
struct
{
/* TODO: returning full details is not implemented */
} conflict;
} details;
};
/**
* Callbacks of this type are used to serve the result of submitting a
* deposit permission request to a exchange.
*
* @param cls closure
* @param dr deposit response details
*/
typedef void
(*TALER_EXCHANGE_DepositResultCallback) (
void *cls,
const struct TALER_EXCHANGE_DepositResult *dr);
/**
* Submit a deposit permission to the exchange and get the exchange's
* response. This API is typically used by a merchant. Note that
* while we return the response verbatim to the caller for further
* processing, we do already verify that the response is well-formed
* (i.e. that signatures included in the response are all valid). If
* the exchange's reply is not well-formed, we return an HTTP status code
* of zero to @a cb.
*
* We also verify that the @a cdd.coin_sig is valid for this deposit
* request, and that the @a cdd.ub_sig is a valid signature for @a
* coin_pub. Also, the @a exchange must be ready to operate (i.e. have
* finished processing the /keys reply). If either check fails, we do
* NOT initiate the transaction with the exchange and instead return NULL.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param dcd details about the contract the deposit is for
* @param cdd details about the coin to be deposited
* @param cb the callback to call when a reply for this request is available
* @param cb_cls closure for the above callback
* @param[out] ec if NULL is returned, set to the error code explaining why the operation failed
* @return a handle for this request; NULL if the inputs are invalid (i.e.
* signatures fail to verify). In this case, the callback is not called.
*/
struct TALER_EXCHANGE_DepositHandle *
TALER_EXCHANGE_deposit (
struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DepositContractDetail *dcd,
const struct TALER_EXCHANGE_CoinDepositDetail *cdd,
TALER_EXCHANGE_DepositResultCallback cb,
void *cb_cls,
enum TALER_ErrorCode *ec);
/**
* Change the chance that our deposit confirmation will be given to the
* auditor to 100%.
*
* @param deposit the deposit permission request handle
*/
void
TALER_EXCHANGE_deposit_force_dc (struct TALER_EXCHANGE_DepositHandle *deposit);
/**
* Cancel a deposit permission request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param deposit the deposit permission request handle
*/
void
TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit);
/**
* @brief A Batch Deposit Handle
*/
@ -1374,7 +1278,9 @@ typedef void
* finished processing the /keys reply). If either check fails, we do
* NOT initiate the transaction with the exchange and instead return NULL.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param dcd details about the contract the deposit is for
* @param num_cdds length of the @a cdds array
* @param cdds array with details about the coins to be deposited
@ -1386,7 +1292,9 @@ typedef void
*/
struct TALER_EXCHANGE_BatchDepositHandle *
TALER_EXCHANGE_batch_deposit (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_EXCHANGE_DepositContractDetail *dcd,
unsigned int num_cdds,
const struct TALER_EXCHANGE_CoinDepositDetail *cdds,
@ -1482,7 +1390,9 @@ typedef void
* finished processing the /keys reply). If this check fails, we do
* NOT initiate the transaction with the exchange and instead return NULL.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param amount the amount to be refunded; must be larger than the refund fee
* (as that fee is still being subtracted), and smaller than the amount
* (with deposit fee) of the original deposit contribution of this coin
@ -1500,7 +1410,9 @@ typedef void
*/
struct TALER_EXCHANGE_RefundHandle *
TALER_EXCHANGE_refund (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_Amount *amount,
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -1609,7 +1521,8 @@ struct TALER_EXCHANGE_NonceKey
/**
* Get a set of CS R values using a /csr-melt request.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param rms master key used for the derivation of the CS values
* @param nks_len length of the @a nks array
* @param nks array of denominations and nonces
@ -1620,12 +1533,14 @@ struct TALER_EXCHANGE_NonceKey
* In this case, the callback is not called.
*/
struct TALER_EXCHANGE_CsRMeltHandle *
TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_RefreshMasterSecretP *rms,
unsigned int nks_len,
struct TALER_EXCHANGE_NonceKey *nks,
TALER_EXCHANGE_CsRMeltCallback res_cb,
void *res_cb_cls);
TALER_EXCHANGE_csr_melt (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_RefreshMasterSecretP *rms,
unsigned int nks_len,
struct TALER_EXCHANGE_NonceKey *nks,
TALER_EXCHANGE_CsRMeltCallback res_cb,
void *res_cb_cls);
/**
@ -1713,11 +1628,12 @@ typedef void
* In this case, the callback is not called.
*/
struct TALER_EXCHANGE_CsRWithdrawHandle *
TALER_EXCHANGE_csr_withdraw (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_CsNonce *nonce,
TALER_EXCHANGE_CsRWithdrawCallback res_cb,
void *res_cb_cls);
TALER_EXCHANGE_csr_withdraw (
struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_CsNonce *nonce,
TALER_EXCHANGE_CsRWithdrawCallback res_cb,
void *res_cb_cls);
/**
@ -2127,7 +2043,8 @@ typedef void
* reply is not well-formed, we return an HTTP status code of zero to
* @a cb.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param reserve_pub public key of the reserve to inspect
* @param timeout how long to wait for an affirmative reply
* (enables long polling if the reserve does not yet exist)
@ -2138,7 +2055,8 @@ typedef void
*/
struct TALER_EXCHANGE_ReservesGetHandle *
TALER_EXCHANGE_reserves_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ReservePublicKeyP *reserve_pub,
struct GNUNET_TIME_Relative timeout,
TALER_EXCHANGE_ReservesGetCallback cb,
@ -2235,7 +2153,9 @@ typedef void
/**
* Submit a request to obtain the reserve status.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param reserve_priv private key of the reserve to inspect
* @param cb the callback to call when a reply for this request is available
* @param cb_cls closure for the above callback
@ -2244,7 +2164,9 @@ typedef void
*/
struct TALER_EXCHANGE_ReservesStatusHandle *
TALER_EXCHANGE_reserves_status (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv,
TALER_EXCHANGE_ReservesStatusCallback cb,
void *cb_cls);
@ -2353,7 +2275,9 @@ typedef void
/**
* Submit a request to obtain the reserve history.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param reserve_priv private key of the reserve to inspect
* @param cb the callback to call when a reply for this request is available
* @param cb_cls closure for the above callback
@ -2362,7 +2286,9 @@ typedef void
*/
struct TALER_EXCHANGE_ReservesHistoryHandle *
TALER_EXCHANGE_reserves_history (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv,
TALER_EXCHANGE_ReservesHistoryCallback cb,
void *cb_cls);
@ -2752,11 +2678,12 @@ struct TALER_EXCHANGE_Withdraw2Handle;
* In this case, the callback is not called.
*/
struct TALER_EXCHANGE_Withdraw2Handle *
TALER_EXCHANGE_withdraw2 (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_PlanchetDetail *pd,
const struct TALER_ReservePrivateKeyP *reserve_priv,
TALER_EXCHANGE_Withdraw2Callback res_cb,
void *res_cb_cls);
TALER_EXCHANGE_withdraw2 (
struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_PlanchetDetail *pd,
const struct TALER_ReservePrivateKeyP *reserve_priv,
TALER_EXCHANGE_Withdraw2Callback res_cb,
void *res_cb_cls);
/**
@ -3014,7 +2941,9 @@ typedef void
* argument @a rd should be committed to persistent storage
* prior to calling this function.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param rms the fresh secret that defines the refresh operation
* @param rd the refresh data specifying the characteristics of the operation
* @param melt_cb the callback to call with the result
@ -3023,11 +2952,14 @@ typedef void
* In this case, neither callback will be called.
*/
struct TALER_EXCHANGE_MeltHandle *
TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_EXCHANGE_RefreshData *rd,
TALER_EXCHANGE_MeltCallback melt_cb,
void *melt_cb_cls);
TALER_EXCHANGE_melt (
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_EXCHANGE_RefreshData *rd,
TALER_EXCHANGE_MeltCallback melt_cb,
void *melt_cb_cls);
/**
@ -3147,7 +3079,9 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
* arguments should have been committed to persistent storage
* prior to calling this function.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param rms the fresh secret that defines the refresh operation
* @param rd the refresh data that characterizes the refresh operation
* @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, must match value in @a rd
@ -3162,7 +3096,8 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
*/
struct TALER_EXCHANGE_RefreshesRevealHandle *
TALER_EXCHANGE_refreshes_reveal (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_EXCHANGE_RefreshData *rd,
unsigned int num_coins,
@ -3284,7 +3219,8 @@ typedef void
* 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 ctx CURL context
* @param url exchange base URL
* @param coin_priv private key to request link data for
* @param age_commitment_proof age commitment to the corresponding coin, might be NULL
* @param link_cb the callback to call with the useful result of the
@ -3294,7 +3230,8 @@ typedef void
*/
struct TALER_EXCHANGE_LinkHandle *
TALER_EXCHANGE_link (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_AgeCommitmentProof *age_commitment_proof,
TALER_EXCHANGE_LinkCallback link_cb,
@ -3412,7 +3349,9 @@ typedef void
* Query the exchange about which transactions were combined
* to create a wire transfer.
*
* @param exchange exchange to query
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param wtid raw wire transfer identifier to get information about
* @param cb callback to call
* @param cb_cls closure for @a cb
@ -3420,7 +3359,9 @@ typedef void
*/
struct TALER_EXCHANGE_TransfersGetHandle *
TALER_EXCHANGE_transfers_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_WireTransferIdentifierRawP *wtid,
TALER_EXCHANGE_TransfersGetCallback cb,
void *cb_cls);
@ -3550,7 +3491,9 @@ typedef void
* which aggregate wire transfer the deposit operation identified by @a coin_pub,
* @a merchant_priv and @a h_contract_terms contributed to.
*
* @param exchange the exchange to query
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param merchant_priv the merchant's private key
* @param h_wire hash of merchant's wire transfer details
* @param h_contract_terms hash of the proposal data
@ -3562,7 +3505,9 @@ typedef void
*/
struct TALER_EXCHANGE_DepositGetHandle *
TALER_EXCHANGE_deposits_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_MerchantPrivateKeyP *merchant_priv,
const struct TALER_MerchantWireHashP *h_wire,
const struct TALER_PrivateContractHashP *h_contract_terms,
@ -3605,7 +3550,7 @@ TALER_EXCHANGE_verify_coin_history (
* Parse history given in JSON format and return it in binary
* format.
*
* @param exchange connection to the exchange we can use
* @param keys exchange keys
* @param history JSON array with the history
* @param reserve_pub public key of the reserve to inspect
* @param currency currency we expect the balance to be in
@ -3620,7 +3565,7 @@ TALER_EXCHANGE_verify_coin_history (
*/
enum GNUNET_GenericReturnValue
TALER_EXCHANGE_parse_reserve_history (
struct TALER_EXCHANGE_Handle *exchange,
struct TALER_EXCHANGE_Keys *keys,
const json_t *history,
const struct TALER_ReservePublicKeyP *reserve_pub,
const char *currency,
@ -3702,7 +3647,9 @@ typedef void
* the emergency recoup protocol for a given denomination. The value
* of the coin will be refunded to the original customer (without fees).
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param pk kind of coin to pay back
* @param denom_sig signature over the coin by the exchange using @a pk
* @param exchange_vals contribution from the exchange on the withdraw
@ -3714,13 +3661,16 @@ typedef void
* In this case, the callback is not called.
*/
struct TALER_EXCHANGE_RecoupHandle *
TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_DenominationSignature *denom_sig,
const struct TALER_ExchangeWithdrawValues *exchange_vals,
const struct TALER_PlanchetMasterSecretP *ps,
TALER_EXCHANGE_RecoupResultCallback recoup_cb,
void *recoup_cb_cls);
TALER_EXCHANGE_recoup (
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_DenominationSignature *denom_sig,
const struct TALER_ExchangeWithdrawValues *exchange_vals,
const struct TALER_PlanchetMasterSecretP *ps,
TALER_EXCHANGE_RecoupResultCallback recoup_cb,
void *recoup_cb_cls);
/**
@ -3793,7 +3743,9 @@ typedef void
* revoked coin was refreshed from. The original coin is then
* considered a zombie.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param pk kind of coin to pay back
* @param denom_sig signature over the coin by the exchange using @a pk
* @param exchange_vals contribution from the exchange on the withdraw
@ -3808,7 +3760,9 @@ typedef void
*/
struct TALER_EXCHANGE_RecoupRefreshHandle *
TALER_EXCHANGE_recoup_refresh (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_DenominationSignature *denom_sig,
const struct TALER_ExchangeWithdrawValues *exchange_vals,
@ -4023,7 +3977,8 @@ struct TALER_EXCHANGE_KycProofHandle;
/**
* Run interaction with exchange to provide proof of KYC status.
*
* @param eh exchange handle to use
* @param ctx CURL context
* @param url exchange base URL
* @param h_payto hash of payto URI identifying the target account
* @param logic name of the KYC logic to run
* @param args additional args to pass, can be NULL
@ -4033,12 +3988,14 @@ struct TALER_EXCHANGE_KycProofHandle;
* @return NULL on error
*/
struct TALER_EXCHANGE_KycProofHandle *
TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *eh,
const struct TALER_PaytoHashP *h_payto,
const char *logic,
const char *args,
TALER_EXCHANGE_KycProofCallback cb,
void *cb_cls);
TALER_EXCHANGE_kyc_proof (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_PaytoHashP *h_payto,
const char *logic,
const char *args,
TALER_EXCHANGE_KycProofCallback cb,
void *cb_cls);
/**
@ -4116,7 +4073,8 @@ typedef void
* Run interaction with exchange to find out the wallet's KYC
* identifier.
*
* @param eh exchange handle to use
* @param ctx CURL context
* @param url exchange base URL
* @param reserve_priv wallet private key to check
* @param balance balance (or balance threshold) crossed by the wallet
* @param cb function to call with the result
@ -4124,11 +4082,13 @@ typedef void
* @return NULL on error
*/
struct TALER_EXCHANGE_KycWalletHandle *
TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle *eh,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_Amount *balance,
TALER_EXCHANGE_KycWalletCallback cb,
void *cb_cls);
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);
/**
@ -4353,10 +4313,11 @@ struct TALER_EXCHANGE_ManagementGetKeysHandle;
* @return the request handle; NULL upon error
*/
struct TALER_EXCHANGE_ManagementGetKeysHandle *
TALER_EXCHANGE_get_management_keys (struct GNUNET_CURL_Context *ctx,
const char *url,
TALER_EXCHANGE_ManagementGetKeysCallback cb,
void *cb_cls);
TALER_EXCHANGE_get_management_keys (
struct GNUNET_CURL_Context *ctx,
const char *url,
TALER_EXCHANGE_ManagementGetKeysCallback cb,
void *cb_cls);
/**
@ -5783,7 +5744,8 @@ struct TALER_EXCHANGE_ContractsGetHandle;
/**
* Request information about a contract from the exchange.
*
* @param exchange exchange handle
* @param ctx CURL context
* @param url exchange base URL
* @param contract_priv private key of the contract
* @param cb function to call with the exchange's result
* @param cb_cls closure for @a cb
@ -5791,7 +5753,8 @@ struct TALER_EXCHANGE_ContractsGetHandle;
*/
struct TALER_EXCHANGE_ContractsGetHandle *
TALER_EXCHANGE_contract_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ContractDiffiePrivateP *contract_priv,
TALER_EXCHANGE_ContractGetCallback cb,
void *cb_cls);
@ -5880,7 +5843,9 @@ struct TALER_EXCHANGE_PurseGetHandle;
/**
* Request information about a purse from the exchange.
*
* @param exchange exchange handle
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param purse_pub public key of the purse
* @param timeout how long to wait for a change to happen
* @param wait_for_merge true to wait for a merge event, otherwise wait for a deposit event
@ -5890,7 +5855,9 @@ struct TALER_EXCHANGE_PurseGetHandle;
*/
struct TALER_EXCHANGE_PurseGetHandle *
TALER_EXCHANGE_purse_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_PurseContractPublicKeyP *purse_pub,
struct GNUNET_TIME_Relative timeout,
bool wait_for_merge,
@ -6004,7 +5971,9 @@ struct TALER_EXCHANGE_PurseDeposit
* Inform the exchange that a purse should be created
* and coins deposited into it.
*
* @param exchange the exchange to interact with
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param purse_priv private key of the purse
* @param merge_priv the merge credential
* @param contract_priv key needed to obtain and decrypt the contract
@ -6020,7 +5989,9 @@ struct TALER_EXCHANGE_PurseDeposit
*/
struct TALER_EXCHANGE_PurseCreateDepositHandle *
TALER_EXCHANGE_purse_create_with_deposit (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_PurseContractPrivateKeyP *purse_priv,
const struct TALER_PurseMergePrivateKeyP *merge_priv,
const struct TALER_ContractDiffiePrivateP *contract_priv,
@ -6077,7 +6048,8 @@ struct TALER_EXCHANGE_PurseDeleteHandle;
* Asks the exchange to delete a purse. Will only succeed if
* the purse was not yet merged and did not yet time out.
*
* @param exchange the exchange to interact with
* @param ctx CURL context
* @param url exchange base URL
* @param purse_priv private key of the purse
* @param cb function to call with the exchange's result
* @param cb_cls closure for @a cb
@ -6085,7 +6057,8 @@ struct TALER_EXCHANGE_PurseDeleteHandle;
*/
struct TALER_EXCHANGE_PurseDeleteHandle *
TALER_EXCHANGE_purse_delete (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_PurseContractPrivateKeyP *purse_priv,
TALER_EXCHANGE_PurseDeleteCallback cb,
void *cb_cls);
@ -6182,7 +6155,9 @@ struct TALER_EXCHANGE_AccountMergeHandle;
* Inform the exchange that a purse should be merged
* with a reserve.
*
* @param exchange the exchange hosting the purse
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param reserve_exchange_url base URL of the exchange with the reserve
* @param reserve_priv private key of the reserve to merge into
* @param purse_pub public key of the purse to merge
@ -6198,7 +6173,9 @@ struct TALER_EXCHANGE_AccountMergeHandle;
*/
struct TALER_EXCHANGE_AccountMergeHandle *
TALER_EXCHANGE_account_merge (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const char *reserve_exchange_url,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_PurseContractPublicKeyP *purse_pub,
@ -6244,7 +6221,7 @@ struct TALER_EXCHANGE_PurseCreateMergeResponse
union
{
/**
* Detailed returned on #MHD_HTTP_OK.
* Details returned on #MHD_HTTP_OK.
*/
struct
{
@ -6290,7 +6267,9 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle;
* Inform the exchange that a purse should be created
* and merged with a reserve.
*
* @param exchange the exchange hosting the reserve
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param reserve_priv private key of the reserve
* @param purse_priv private key of the purse
* @param merge_priv private key of the merge capability
@ -6305,7 +6284,9 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle;
*/
struct TALER_EXCHANGE_PurseCreateMergeHandle *
TALER_EXCHANGE_purse_create_with_merge (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_PurseContractPrivateKeyP *purse_priv,
const struct TALER_PurseMergePrivateKeyP *merge_priv,
@ -6397,7 +6378,9 @@ struct TALER_EXCHANGE_PurseDepositHandle;
* Inform the exchange that a deposit should be made into
* a purse.
*
* @param exchange the exchange that issued the coins
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param purse_exchange_url base URL of the exchange hosting the purse
* @param purse_pub public key of the purse to merge
* @param min_age minimum age we need to prove for the purse
@ -6409,7 +6392,9 @@ struct TALER_EXCHANGE_PurseDepositHandle;
*/
struct TALER_EXCHANGE_PurseDepositHandle *
TALER_EXCHANGE_purse_deposit (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const char *purse_exchange_url,
const struct TALER_PurseContractPublicKeyP *purse_pub,
uint8_t min_age,
@ -6533,7 +6518,9 @@ typedef void
/**
* Submit a request to open a reserve.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param keys exchange keys
* @param reserve_priv private key of the reserve to open
* @param reserve_contribution amount to pay from the reserve's balance for the operation
* @param coin_payments_length length of the @a coin_payments array
@ -6547,7 +6534,9 @@ typedef void
*/
struct TALER_EXCHANGE_ReservesOpenHandle *
TALER_EXCHANGE_reserves_open (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_Amount *reserve_contribution,
unsigned int coin_payments_length,
@ -6635,7 +6624,8 @@ typedef void
/**
* Submit a request to get the list of attestable attributes for a reserve.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx CURL context
* @param url exchange base URL
* @param reserve_pub public key of the reserve to get available attributes for
* @param cb the callback to call when a reply for this request is available
* @param cb_cls closure for the above callback
@ -6644,7 +6634,8 @@ typedef void
*/
struct TALER_EXCHANGE_ReservesGetAttestHandle *
TALER_EXCHANGE_reserves_get_attestable (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_EXCHANGE_ReservesGetAttestCallback cb,
void *cb_cls);
@ -6738,7 +6729,8 @@ typedef void
/**
* Submit a request to attest attributes about the owner of a reserve.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx CURL context
* @param url exchange base URL
* @param reserve_priv private key of the reserve to attest
* @param attributes_length length of the @a attributes array
* @param attributes array of names of attributes to get attestations for
@ -6749,7 +6741,8 @@ typedef void
*/
struct TALER_EXCHANGE_ReservesAttestHandle *
TALER_EXCHANGE_reserves_attest (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ReservePrivateKeyP *reserve_priv,
unsigned int attributes_length,
const char *const*attributes,
@ -6847,7 +6840,8 @@ typedef void
/**
* Submit a request to close a reserve.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param ctx curl context
* @param url exchange base URL
* @param reserve_priv private key of the reserve to close
* @param target_payto_uri where to send the payment, NULL to send to reserve origin
* @param cb the callback to call when a reply for this request is available
@ -6857,7 +6851,8 @@ typedef void
*/
struct TALER_EXCHANGE_ReservesCloseHandle *
TALER_EXCHANGE_reserves_close (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const char *target_payto_uri,
TALER_EXCHANGE_ReservesCloseCallback cb,

View File

@ -514,7 +514,7 @@ typedef void
* Iterates over all of the top-level commands of an
* interpreter.
*
* @param[in] interpreter to iterate over
* @param[in] is interpreter to iterate over
* @param asc true in execution order, false for reverse execution order
* @param cb function to call on each command
* @param cb_cls closure for cb
@ -2692,9 +2692,9 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
op (fresh_coins, const struct TALER_TESTING_FreshCoinData *) \
op (claim_token, const struct TALER_ClaimTokenP) \
op (relative_time, const struct GNUNET_TIME_Relative) \
op (auditor, struct TALER_AUDITOR_Handle) \
op (exchange, struct TALER_EXCHANGE_Handle) \
op (fakebank, struct TALER_FAKEBANK_Handle) \
op (keys, struct TALER_EXCHANGE_Keys) \
op (process, struct GNUNET_OS_Process *)
@ -2741,4 +2741,26 @@ struct TALER_EXCHANGE_Handle *
TALER_TESTING_get_exchange (struct TALER_TESTING_Interpreter *is);
/**
* Get exchange URL from interpreter. Convenience function.
*
* @param is interpreter state.
* @return the exchange URL, or NULL on error
*/
const char *
TALER_TESTING_get_exchange_url (
struct TALER_TESTING_Interpreter *is);
/**
* Get exchange keys from interpreter. Convenience function.
*
* @param is interpreter state.
* @return the exchange keys, or NULL on error
*/
struct TALER_EXCHANGE_Keys *
TALER_TESTING_get_keys (
struct TALER_TESTING_Interpreter *is);
#endif

View File

@ -32,7 +32,6 @@ libtalerexchange_la_SOURCES = \
exchange_api_csr_melt.c \
exchange_api_csr_withdraw.c \
exchange_api_handle.c exchange_api_handle.h \
exchange_api_deposit.c \
exchange_api_deposits_get.c \
exchange_api_kyc_check.c \
exchange_api_kyc_proof.c \
@ -96,7 +95,7 @@ libtalerauditor_la_LDFLAGS = \
-no-undefined
libtalerauditor_la_SOURCES = \
auditor_api_curl_defaults.c auditor_api_curl_defaults.h \
auditor_api_handle.c auditor_api_handle.h \
auditor_api_get_config.c \
auditor_api_deposit_confirmation.c \
auditor_api_exchanges.c
libtalerauditor_la_LIBADD = \

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2021 Taler Systems SA
Copyright (C) 2014-2023 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,9 +25,10 @@
#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_json_lib.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler_util.h"
#include "taler_curl_lib.h"
#include "taler_json_lib.h"
#include "taler_auditor_service.h"
#include "auditor_api_handle.h"
#include "taler_signatures.h"
#include "auditor_api_curl_defaults.h"
@ -38,11 +39,6 @@
struct TALER_AUDITOR_DepositConfirmationHandle
{
/**
* The connection to auditor this request handle will use
*/
struct TALER_AUDITOR_Handle *auditor;
/**
* The url for this request.
*/
@ -87,64 +83,64 @@ handle_deposit_confirmation_finished (void *cls,
{
const json_t *json = djson;
struct TALER_AUDITOR_DepositConfirmationHandle *dh = cls;
struct TALER_AUDITOR_HttpResponse hr = {
.reply = json,
.http_status = (unsigned int) response_code
struct TALER_AUDITOR_DepositConfirmationResponse dcr = {
.hr.reply = json,
.hr.http_status = (unsigned int) response_code
};
dh->job = NULL;
switch (response_code)
{
case 0:
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
dcr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
hr.ec = TALER_EC_NONE;
dcr.hr.ec = TALER_EC_NONE;
break;
case MHD_HTTP_BAD_REQUEST:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dcr.hr.ec = TALER_JSON_get_error_code (json);
dcr.hr.hint = TALER_JSON_get_error_hint (json);
/* This should never happen, either us or the auditor is buggy
(or API version conflict); just pass JSON reply to the application */
break;
case MHD_HTTP_FORBIDDEN:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dcr.hr.ec = TALER_JSON_get_error_code (json);
dcr.hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, auditor says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dcr.hr.ec = TALER_JSON_get_error_code (json);
dcr.hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
break;
case MHD_HTTP_GONE:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dcr.hr.ec = TALER_JSON_get_error_code (json);
dcr.hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, auditor says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dcr.hr.ec = TALER_JSON_get_error_code (json);
dcr.hr.hint = TALER_JSON_get_error_hint (json);
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
break;
default:
/* unexpected response code */
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
dcr.hr.ec = TALER_JSON_get_error_code (json);
dcr.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for auditor deposit confirmation\n",
(unsigned int) response_code,
hr.ec);
dcr.hr.ec);
break;
}
dh->cb (dh->cb_cls,
&hr);
&dcr);
TALER_AUDITOR_deposit_confirmation_cancel (dh);
}
@ -237,7 +233,8 @@ verify_signatures (const struct TALER_MerchantWireHashP *h_wire,
struct TALER_AUDITOR_DepositConfirmationHandle *
TALER_AUDITOR_deposit_confirmation (
struct TALER_AUDITOR_Handle *auditor,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_MerchantWireHashP *h_wire,
const struct TALER_ExtensionPolicyHashP *h_policy,
const struct TALER_PrivateContractHashP *h_contract_terms,
@ -258,12 +255,9 @@ TALER_AUDITOR_deposit_confirmation (
void *cb_cls)
{
struct TALER_AUDITOR_DepositConfirmationHandle *dh;
struct GNUNET_CURL_Context *ctx;
json_t *deposit_confirmation_obj;
CURL *eh;
GNUNET_assert (GNUNET_YES ==
TALER_AUDITOR_handle_is_ready_ (auditor));
if (GNUNET_OK !=
verify_signatures (h_wire,
h_policy,
@ -322,18 +316,17 @@ TALER_AUDITOR_deposit_confirmation (
GNUNET_JSON_pack_data_auto ("exchange_pub",
exchange_pub));
dh = GNUNET_new (struct TALER_AUDITOR_DepositConfirmationHandle);
dh->auditor = auditor;
dh->cb = cb;
dh->cb_cls = cb_cls;
dh->url = TALER_AUDITOR_path_to_url_ (auditor,
"/deposit-confirmation");
dh->url = TALER_url_join (url,
"deposit-confirmation",
NULL);
if (NULL == dh->url)
{
GNUNET_free (dh);
return NULL;
}
eh = TALER_AUDITOR_curl_easy_get_ (dh->url);
if ( (NULL == eh) ||
(CURLE_OK !=
curl_easy_setopt (eh,
@ -356,7 +349,6 @@ TALER_AUDITOR_deposit_confirmation (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for deposit-confirmation: `%s'\n",
dh->url);
ctx = TALER_AUDITOR_handle_to_context_ (auditor);
dh->job = GNUNET_CURL_job_add2 (ctx,
eh,
dh->ctx.headers,

View File

@ -27,7 +27,8 @@
#include <gnunet/gnunet_curl_lib.h>
#include "taler_json_lib.h"
#include "taler_auditor_service.h"
#include "auditor_api_handle.h"
#include "taler_util.h"
#include "taler_curl_lib.h"
#include "taler_signatures.h"
#include "auditor_api_curl_defaults.h"
@ -44,11 +45,6 @@
struct TALER_AUDITOR_ListExchangesHandle
{
/**
* The connection to auditor this request handle will use
*/
struct TALER_AUDITOR_Handle *auditor;
/**
* The url for this request.
*/
@ -89,16 +85,16 @@ handle_exchanges_finished (void *cls,
const json_t *ja;
unsigned int ja_len;
struct TALER_AUDITOR_ListExchangesHandle *leh = cls;
struct TALER_AUDITOR_HttpResponse hr = {
.reply = json,
.http_status = (unsigned int) response_code
struct TALER_AUDITOR_ListExchangesResponse ler = {
.hr.reply = json,
.hr.http_status = (unsigned int) response_code
};
leh->job = NULL;
switch (response_code)
{
case 0:
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
ler.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
ja = json_object_get (json,
@ -107,8 +103,8 @@ handle_exchanges_finished (void *cls,
(! json_is_array (ja)) )
{
GNUNET_break (0);
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
ler.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
ler.hr.http_status = 0;
break;
}
@ -116,20 +112,21 @@ handle_exchanges_finished (void *cls,
if (ja_len > MAX_EXCHANGES)
{
GNUNET_break (0);
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
ler.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
ler.hr.http_status = 0;
break;
}
{
struct TALER_AUDITOR_ExchangeInfo ei[ja_len];
bool ok;
struct TALER_AUDITOR_ExchangeInfo ei[GNUNET_NZL (ja_len)];
bool ok = true;
ok = true;
for (unsigned int i = 0; i<ja_len; i++)
{
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("master_pub", &ei[i].master_pub),
GNUNET_JSON_spec_string ("exchange_url", &ei[i].exchange_url),
GNUNET_JSON_spec_fixed_auto ("master_pub",
&ei[i].master_pub),
GNUNET_JSON_spec_string ("exchange_url",
&ei[i].exchange_url),
GNUNET_JSON_spec_end ()
};
@ -141,76 +138,71 @@ handle_exchanges_finished (void *cls,
{
GNUNET_break_op (0);
ok = false;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
hr.http_status = 0;
ler.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
ler.hr.http_status = 0;
break;
}
}
if (! ok)
break;
ler.details.ok.ei = ei;
ler.details.ok.num_exchanges = ja_len;
leh->cb (leh->cb_cls,
&hr,
ja_len,
ei);
&ler);
TALER_AUDITOR_list_exchanges_cancel (leh);
return;
}
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the auditor is buggy
(or API version conflict); just pass JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
ler.hr.ec = TALER_JSON_get_error_code (json);
ler.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
ler.hr.ec = TALER_JSON_get_error_code (json);
ler.hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
ler.hr.ec = TALER_JSON_get_error_code (json);
ler.hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
hr.ec = TALER_JSON_get_error_code (json);
hr.hint = TALER_JSON_get_error_hint (json);
ler.hr.ec = TALER_JSON_get_error_code (json);
ler.hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for auditor list-exchanges request\n",
(unsigned int) response_code,
(int) hr.ec);
(int) ler.hr.ec);
GNUNET_break_op (0);
break;
}
if (NULL != leh->cb)
leh->cb (leh->cb_cls,
&hr,
0,
NULL);
&ler);
TALER_AUDITOR_list_exchanges_cancel (leh);
}
struct TALER_AUDITOR_ListExchangesHandle *
TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle *auditor,
TALER_AUDITOR_list_exchanges (struct GNUNET_CURL_Context *ctx,
const char *url,
TALER_AUDITOR_ListExchangesResultCallback cb,
void *cb_cls)
{
struct TALER_AUDITOR_ListExchangesHandle *leh;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
GNUNET_assert (GNUNET_YES ==
TALER_AUDITOR_handle_is_ready_ (auditor));
leh = GNUNET_new (struct TALER_AUDITOR_ListExchangesHandle);
leh->auditor = auditor;
leh->cb = cb;
leh->cb_cls = cb_cls;
leh->url = TALER_AUDITOR_path_to_url_ (auditor,
"/exchanges");
leh->url = TALER_url_join (url,
"exchanges",
NULL);
if (NULL == leh->url)
{
GNUNET_free (leh);
@ -227,7 +219,6 @@ TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle *auditor,
GNUNET_free (leh);
return NULL;
}
ctx = TALER_AUDITOR_handle_to_context_ (auditor);
leh->job = GNUNET_CURL_job_add (ctx,
eh,
&handle_exchanges_finished,

View File

@ -0,0 +1,288 @@
/*
This file is part of TALER
Copyright (C) 2014-2023 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
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
/**
* @file lib/auditor_api_get_config.c
* @brief Implementation of /config for the auditor's HTTP API
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
* @author Christian Grothoff
*/
#include "platform.h"
#include <microhttpd.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler_json_lib.h"
#include "taler_auditor_service.h"
#include "taler_signatures.h"
#include "auditor_api_curl_defaults.h"
/**
* Which revision of the Taler auditor protocol is implemented
* by this library? Used to determine compatibility.
*/
#define TALER_PROTOCOL_CURRENT 0
/**
* How many revisions back are we compatible to?
*/
#define TALER_PROTOCOL_AGE 0
/**
* Log error related to CURL operations.
*
* @param type log level
* @param function which function failed to run
* @param code what was the curl error code
*/
#define CURL_STRERROR(type, function, code) \
GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \
function, __FILE__, __LINE__, curl_easy_strerror (code));
/**
* Handle for the get config request.
*/
struct TALER_AUDITOR_GetConfigHandle
{
/**
* The context of this handle
*/
struct GNUNET_CURL_Context *ctx;
/**
* Function to call with the auditor's certification data,
* NULL if this has already been done.
*/
TALER_AUDITOR_ConfigCallback config_cb;
/**
* Closure to pass to @e config_cb.
*/
void *config_cb_cls;
/**
* Data for the request to get the /config of a auditor,
* NULL once we are past stage #MHS_INIT.
*/
struct GNUNET_CURL_Job *vr;
/**
* The url for the @e vr job.
*/
char *vr_url;
};
/* ***************** Internal /config fetching ************* */
/**
* Decode the JSON in @a resp_obj from the /config response and store the data
* in the @a key_data.
*
* @param[in] resp_obj JSON object to parse
* @param[in,out] auditor where to store the results we decoded
* @param[out] vc where to store config compatibility data
* @return #TALER_EC_NONE on success
*/
static enum TALER_ErrorCode
decode_config_json (const json_t *resp_obj,
struct TALER_AUDITOR_ConfigInformation *vi,
enum TALER_AUDITOR_VersionCompatibility *vc)
{
unsigned int age;
unsigned int revision;
unsigned int current;
char dummy;
const char *ver;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("version",
&ver),
GNUNET_JSON_spec_fixed_auto ("auditor_public_key",
&vi->auditor_pub),
GNUNET_JSON_spec_end ()
};
if (JSON_OBJECT != json_typeof (resp_obj))
{
GNUNET_break_op (0);
return TALER_EC_GENERIC_JSON_INVALID;
}
/* check the config */
if (GNUNET_OK !=
GNUNET_JSON_parse (resp_obj,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
return TALER_EC_GENERIC_JSON_INVALID;
}
if (3 != sscanf (ver,
"%u:%u:%u%c",
&current,
&revision,
&age,
&dummy))
{
GNUNET_break_op (0);
return TALER_EC_GENERIC_VERSION_MALFORMED;
}
vi->version = ver;
*vc = TALER_AUDITOR_VC_MATCH;
if (TALER_PROTOCOL_CURRENT < current)
{
*vc |= TALER_AUDITOR_VC_NEWER;
if (TALER_PROTOCOL_CURRENT < current - age)
*vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
}
if (TALER_PROTOCOL_CURRENT > current)
{
*vc |= TALER_AUDITOR_VC_OLDER;
if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current)
*vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
}
return TALER_EC_NONE;
}
/**
* Callback used when downloading the reply to a /config request
* is complete.
*
* @param cls the `struct TALER_AUDITOR_GetConfigHandle`
* @param response_code HTTP response code, 0 on error
* @param gresp_obj parsed JSON result, NULL on error, must be a `const json_t *`
*/
static void
config_completed_cb (void *cls,
long response_code,
const void *gresp_obj)
{
struct TALER_AUDITOR_GetConfigHandle *auditor = cls;
const json_t *resp_obj = gresp_obj;
struct TALER_AUDITOR_ConfigResponse vr = {
.hr.reply = resp_obj,
.hr.http_status = (unsigned int) response_code
};
auditor->vr = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received config from URL `%s' with status %ld.\n",
auditor->vr_url,
response_code);
switch (response_code)
{
case 0:
GNUNET_break_op (0);
vr.hr.ec = TALER_EC_INVALID;
break;
case MHD_HTTP_OK:
if (NULL == resp_obj)
{
GNUNET_break_op (0);
vr.hr.http_status = 0;
vr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
vr.hr.ec = decode_config_json (resp_obj,
&vr.details.ok.vi,
&vr.details.ok.compat);
if (TALER_EC_NONE != vr.hr.ec)
{
GNUNET_break_op (0);
vr.hr.http_status = 0;
break;
}
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
vr.hr.ec = TALER_JSON_get_error_code (resp_obj);
vr.hr.hint = TALER_JSON_get_error_hint (resp_obj);
break;
default:
vr.hr.ec = TALER_JSON_get_error_code (resp_obj);
vr.hr.hint = TALER_JSON_get_error_hint (resp_obj);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n",
(unsigned int) response_code,
(int) vr.hr.ec);
break;
}
auditor->config_cb (auditor->config_cb_cls,
&vr);
TALER_AUDITOR_get_config_cancel (auditor);
}
struct TALER_AUDITOR_GetConfigHandle *
TALER_AUDITOR_get_config (struct GNUNET_CURL_Context *ctx,
const char *url,
TALER_AUDITOR_ConfigCallback config_cb,
void *config_cb_cls)
{
struct TALER_AUDITOR_GetConfigHandle *auditor;
CURL *eh;
auditor = GNUNET_new (struct TALER_AUDITOR_GetConfigHandle);
auditor->config_cb = config_cb;
auditor->config_cb_cls = config_cb_cls;
auditor->ctx = ctx;
auditor->vr_url = TALER_url_join (url,
"config",
NULL);
if (NULL == auditor->vr_url)
{
GNUNET_break (0);
GNUNET_free (auditor->vr_url);
GNUNET_free (auditor);
return NULL;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Requesting auditor config with URL `%s'.\n",
auditor->vr_url);
eh = TALER_AUDITOR_curl_easy_get_ (auditor->vr_url);
if (NULL == eh)
{
GNUNET_break (0);
TALER_AUDITOR_get_config_cancel (auditor);
return NULL;
}
GNUNET_break (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_TIMEOUT,
(long) 300));
auditor->vr = GNUNET_CURL_job_add (auditor->ctx,
eh,
&config_completed_cb,
auditor);
return auditor;
}
void
TALER_AUDITOR_get_config_cancel (struct TALER_AUDITOR_GetConfigHandle *auditor)
{
if (NULL != auditor->vr)
{
GNUNET_CURL_job_cancel (auditor->vr);
auditor->vr = NULL;
}
GNUNET_free (auditor->vr_url);
GNUNET_free (auditor);
}
/* end of auditor_api_get_config.c */

View File

@ -1,449 +0,0 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 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
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
/**
* @file lib/auditor_api_handle.c
* @brief Implementation of the "handle" component of the auditor's HTTP API
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
* @author Christian Grothoff
*/
#include "platform.h"
#include <microhttpd.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler_json_lib.h"
#include "taler_auditor_service.h"
#include "taler_signatures.h"
#include "auditor_api_handle.h"
#include "auditor_api_curl_defaults.h"
#include "backoff.h"
/**
* Which revision of the Taler auditor protocol is implemented
* by this library? Used to determine compatibility.
*/
#define TALER_PROTOCOL_CURRENT 0
/**
* How many revisions back are we compatible to?
*/
#define TALER_PROTOCOL_AGE 0
/**
* Log error related to CURL operations.
*
* @param type log level
* @param function which function failed to run
* @param code what was the curl error code
*/
#define CURL_STRERROR(type, function, code) \
GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \
function, __FILE__, __LINE__, curl_easy_strerror (code));
/**
* Stages of initialization for the `struct TALER_AUDITOR_Handle`
*/
enum AuditorHandleState
{
/**
* Just allocated.
*/
MHS_INIT = 0,
/**
* Obtained the auditor's versioning data and version.
*/
MHS_VERSION = 1,
/**
* Failed to initialize (fatal).
*/
MHS_FAILED = 2
};
/**
* Handle to the auditor
*/
struct TALER_AUDITOR_Handle
{
/**
* The context of this handle
*/
struct GNUNET_CURL_Context *ctx;
/**
* The URL of the auditor (i.e. "http://auditor.taler.net/")
*/
char *url;
/**
* Function to call with the auditor's certification data,
* NULL if this has already been done.
*/
TALER_AUDITOR_VersionCallback version_cb;
/**
* Closure to pass to @e version_cb.
*/
void *version_cb_cls;
/**
* Data for the request to get the /config of a auditor,
* NULL once we are past stage #MHS_INIT.
*/
struct GNUNET_CURL_Job *vr;
/**
* The url for the @e vr job.
*/
char *vr_url;
/**
* Task for retrying /config request.
*/
struct GNUNET_SCHEDULER_Task *retry_task;
/**
* /config data of the auditor, only valid if
* @e handshake_complete is past stage #MHS_VERSION.
*/
char *version;
/**
* Version information for the callback.
*/
struct TALER_AUDITOR_VersionInformation vi;
/**
* Retry /config frequency.
*/
struct GNUNET_TIME_Relative retry_delay;
/**
* Stage of the auditor's initialization routines.
*/
enum AuditorHandleState state;
};
/* ***************** Internal /config fetching ************* */
/**
* Decode the JSON in @a resp_obj from the /config response and store the data
* in the @a key_data.
*
* @param[in] resp_obj JSON object to parse
* @param[in,out] auditor where to store the results we decoded
* @param[out] vc where to store version compatibility data
* @return #TALER_EC_NONE on success
*/
static enum TALER_ErrorCode
decode_version_json (const json_t *resp_obj,
struct TALER_AUDITOR_Handle *auditor,
enum TALER_AUDITOR_VersionCompatibility *vc)
{
struct TALER_AUDITOR_VersionInformation *vi = &auditor->vi;
unsigned int age;
unsigned int revision;
unsigned int current;
char dummy;
const char *ver;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("version",
&ver),
GNUNET_JSON_spec_fixed_auto ("auditor_public_key",
&vi->auditor_pub),
GNUNET_JSON_spec_end ()
};
if (JSON_OBJECT != json_typeof (resp_obj))
{
GNUNET_break_op (0);
return TALER_EC_GENERIC_JSON_INVALID;
}
/* check the version */
if (GNUNET_OK !=
GNUNET_JSON_parse (resp_obj,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
return TALER_EC_GENERIC_JSON_INVALID;
}
if (3 != sscanf (ver,
"%u:%u:%u%c",
&current,
&revision,
&age,
&dummy))
{
GNUNET_break_op (0);
return TALER_EC_GENERIC_VERSION_MALFORMED;
}
GNUNET_free (auditor->version);
auditor->version = GNUNET_strdup (ver);
vi->version = auditor->version;
*vc = TALER_AUDITOR_VC_MATCH;
if (TALER_PROTOCOL_CURRENT < current)
{
*vc |= TALER_AUDITOR_VC_NEWER;
if (TALER_PROTOCOL_CURRENT < current - age)
*vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
}
if (TALER_PROTOCOL_CURRENT > current)
{
*vc |= TALER_AUDITOR_VC_OLDER;
if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current)
*vc |= TALER_AUDITOR_VC_INCOMPATIBLE;
}
return TALER_EC_NONE;
}
/**
* Initiate download of /config from the auditor.
*
* @param cls auditor where to download /config from
*/
static void
request_version (void *cls);
/**
* Callback used when downloading the reply to a /config request
* is complete.
*
* @param cls the `struct TALER_AUDITOR_Handle`
* @param response_code HTTP response code, 0 on error
* @param gresp_obj parsed JSON result, NULL on error, must be a `const json_t *`
*/
static void
version_completed_cb (void *cls,
long response_code,
const void *gresp_obj)
{
struct TALER_AUDITOR_Handle *auditor = cls;
const json_t *resp_obj = gresp_obj;
enum TALER_AUDITOR_VersionCompatibility vc;
struct TALER_AUDITOR_HttpResponse hr = {
.reply = resp_obj,
.http_status = (unsigned int) response_code
};
auditor->vr = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received version from URL `%s' with status %ld.\n",
auditor->url,
response_code);
vc = TALER_AUDITOR_VC_PROTOCOL_ERROR;
switch (response_code)
{
case 0:
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* NOTE: this design is debatable. We MAY want to throw this error at the
client. We may then still additionally internally re-try. */
GNUNET_assert (NULL == auditor->retry_task);
auditor->retry_delay = EXCHANGE_LIB_BACKOFF (auditor->retry_delay);
auditor->retry_task = GNUNET_SCHEDULER_add_delayed (auditor->retry_delay,
&request_version,
auditor);
return;
case MHD_HTTP_OK:
if (NULL == resp_obj)
{
GNUNET_break_op (0);
TALER_LOG_WARNING ("NULL body for a 200-OK /config\n");
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
}
hr.ec = decode_version_json (resp_obj,
auditor,
&vc);
if (TALER_EC_NONE != hr.ec)
{
GNUNET_break_op (0);
hr.http_status = 0;
break;
}
auditor->retry_delay = GNUNET_TIME_UNIT_ZERO; /* restart quickly */
break;
default:
hr.ec = TALER_JSON_get_error_code (resp_obj);
hr.hint = TALER_JSON_get_error_hint (resp_obj);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d\n",
(unsigned int) response_code,
(int) hr.ec);
break;
}
if (MHD_HTTP_OK != response_code)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"/config failed for auditor %s: %u!\n",
auditor->url,
(unsigned int) response_code);
auditor->state = MHS_FAILED;
/* notify application that we failed */
auditor->version_cb (auditor->version_cb_cls,
&hr,
NULL,
vc);
return;
}
TALER_LOG_DEBUG ("Switching auditor state to 'version'\n");
auditor->state = MHS_VERSION;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Auditor %s is ready!\n",
auditor->url);
/* notify application about the key information */
auditor->version_cb (auditor->version_cb_cls,
&hr,
&auditor->vi,
vc);
}
/**
* Initiate download of /config from the auditor.
*
* @param cls auditor where to download /config from
*/
static void
request_version (void *cls)
{
struct TALER_AUDITOR_Handle *auditor = cls;
CURL *eh;
auditor->retry_task = NULL;
GNUNET_assert (NULL == auditor->vr);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Requesting auditor version with URL `%s'.\n",
auditor->vr_url);
eh = TALER_AUDITOR_curl_easy_get_ (auditor->vr_url);
if (NULL == eh)
{
GNUNET_break (0);
auditor->retry_delay = EXCHANGE_LIB_BACKOFF (auditor->retry_delay);
auditor->retry_task = GNUNET_SCHEDULER_add_delayed (auditor->retry_delay,
&request_version,
auditor);
return;
}
GNUNET_break (CURLE_OK ==
curl_easy_setopt (eh,
CURLOPT_TIMEOUT,
(long) 300));
auditor->vr = GNUNET_CURL_job_add (auditor->ctx,
eh,
&version_completed_cb,
auditor);
}
/* ********************* library internal API ********* */
struct GNUNET_CURL_Context *
TALER_AUDITOR_handle_to_context_ (struct TALER_AUDITOR_Handle *h)
{
return h->ctx;
}
enum GNUNET_GenericReturnValue
TALER_AUDITOR_handle_is_ready_ (struct TALER_AUDITOR_Handle *h)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Checking if auditor at `%s` is now ready: %s\n",
h->url,
(MHD_VERSION == h->state) ? "yes" : "no");
return (MHS_VERSION == h->state) ? GNUNET_YES : GNUNET_NO;
}
char *
TALER_AUDITOR_path_to_url_ (struct TALER_AUDITOR_Handle *h,
const char *path)
{
GNUNET_assert ('/' == path[0]);
return TALER_url_join (h->url,
path + 1,
NULL);
}
/* ********************* public API ******************* */
struct TALER_AUDITOR_Handle *
TALER_AUDITOR_connect (struct GNUNET_CURL_Context *ctx,
const char *url,
TALER_AUDITOR_VersionCallback version_cb,
void *version_cb_cls)
{
struct TALER_AUDITOR_Handle *auditor;
auditor = GNUNET_new (struct TALER_AUDITOR_Handle);
auditor->version_cb = version_cb;
auditor->version_cb_cls = version_cb_cls;
auditor->retry_delay = GNUNET_TIME_UNIT_SECONDS; /* start slowly */
auditor->ctx = ctx;
auditor->url = GNUNET_strdup (url);
auditor->vr_url = TALER_AUDITOR_path_to_url_ (auditor,
"/config");
if (NULL == auditor->vr_url)
{
GNUNET_break (0);
GNUNET_free (auditor->url);
GNUNET_free (auditor);
return NULL;
}
auditor->retry_task = GNUNET_SCHEDULER_add_now (&request_version,
auditor);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Connecting to auditor at URL `%s'.\n",
url);
return auditor;
}
void
TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Disconnecting from auditor at URL `%s'.\n",
auditor->url);
if (NULL != auditor->vr)
{
GNUNET_CURL_job_cancel (auditor->vr);
auditor->vr = NULL;
}
if (NULL != auditor->retry_task)
{
GNUNET_SCHEDULER_cancel (auditor->retry_task);
auditor->retry_task = NULL;
}
GNUNET_free (auditor->version);
GNUNET_free (auditor->vr_url);
GNUNET_free (auditor->url);
GNUNET_free (auditor);
}
/* end of auditor_api_handle.c */

View File

@ -1,59 +0,0 @@
/*
This file is part of TALER
Copyright (C) 2014, 2015 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
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
/**
* @file lib/auditor_api_handle.h
* @brief Internal interface to the handle part of the auditor's HTTP API
* @author Christian Grothoff
*/
#include "platform.h"
#include <gnunet/gnunet_curl_lib.h>
#include "taler_auditor_service.h"
#include "taler_curl_lib.h"
/**
* Get the context of a auditor.
*
* @param h the auditor handle to query
* @return ctx context to execute jobs in
*/
struct GNUNET_CURL_Context *
TALER_AUDITOR_handle_to_context_ (struct TALER_AUDITOR_Handle *h);
/**
* Check if the handle is ready to process requests.
*
* @param h the auditor handle to query
* @return #GNUNET_YES if we are ready, #GNUNET_NO if not
*/
int
TALER_AUDITOR_handle_is_ready_ (struct TALER_AUDITOR_Handle *h);
/**
* Obtain the URL to use for an API request.
*
* @param h the auditor handle to query
* @param path Taler API path (i.e. "/deposit-confirmation")
* @return the full URL to use with cURL
*/
char *
TALER_AUDITOR_path_to_url_ (struct TALER_AUDITOR_Handle *h,
const char *path);
/* end of auditor_api_handle.h */

View File

@ -44,6 +44,39 @@
*/
#define AUDITOR_CHANCE 20
/**
* Entry in list of ongoing interactions with an auditor.
*/
struct TEAH_AuditorInteractionEntry
{
/**
* DLL entry.
*/
struct TEAH_AuditorInteractionEntry *next;
/**
* DLL entry.
*/
struct TEAH_AuditorInteractionEntry *prev;
/**
* URL of our auditor. For logging.
*/
const char *auditor_url;
/**
* Interaction state.
*/
struct TALER_AUDITOR_DepositConfirmationHandle *dch;
/**
* Batch deposit this is for.
*/
struct TALER_EXCHANGE_BatchDepositHandle *dh;
};
/**
* @brief A Deposit Handle
*/
@ -51,9 +84,14 @@ struct TALER_EXCHANGE_BatchDepositHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange.
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* Context for our curl request(s).
*/
struct GNUNET_CURL_Context *ctx;
/**
* The url for this request.
@ -64,7 +102,7 @@ struct TALER_EXCHANGE_BatchDepositHandle
* Context for #TEH_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;
/**
* Handle for the request.
@ -112,11 +150,31 @@ struct TALER_EXCHANGE_BatchDepositHandle
*/
struct TALER_ExchangeSignatureP *exchange_sigs;
/**
* Head of DLL of interactions with this auditor.
*/
struct TEAH_AuditorInteractionEntry *ai_head;
/**
* Tail of DLL of interactions with this auditor.
*/
struct TEAH_AuditorInteractionEntry *ai_tail;
/**
* Result to return to the application once @e ai_head is empty.
*/
struct TALER_EXCHANGE_BatchDepositResult dr;
/**
* Exchange signing public key, set for #auditor_cb.
*/
struct TALER_ExchangePublicKeyP exchange_pub;
/**
* Response object to free at the end.
*/
json_t *response;
/**
* Chance that we will inform the auditor about the deposit
* is 1:n, where the value of this field is "n".
@ -131,22 +189,66 @@ struct TALER_EXCHANGE_BatchDepositHandle
};
/**
* Finish batch deposit operation by calling the callback.
*
* @param[in] dh handle to finished batch deposit operation
*/
static void
finish_dh (struct TALER_EXCHANGE_BatchDepositHandle *dh)
{
dh->cb (dh->cb_cls,
&dh->dr);
TALER_EXCHANGE_batch_deposit_cancel (dh);
}
/**
* Function called with the result from our call to the
* auditor's /deposit-confirmation handler.
*
* @param cls closure of type `struct TEAH_AuditorInteractionEntry *`
* @param dcr response
*/
static void
acc_confirmation_cb (
void *cls,
const struct TALER_AUDITOR_DepositConfirmationResponse *dcr)
{
struct TEAH_AuditorInteractionEntry *aie = cls;
struct TALER_EXCHANGE_BatchDepositHandle *dh = aie->dh;
if (MHD_HTTP_OK != dcr->hr.http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to submit deposit confirmation to auditor `%s' with HTTP status %d (EC: %d). This is acceptable if it does not happen often.\n",
aie->auditor_url,
dcr->hr.http_status,
dcr->hr.ec);
}
GNUNET_CONTAINER_DLL_remove (dh->ai_head,
dh->ai_tail,
aie);
GNUNET_free (aie);
if (NULL == dh->ai_head)
finish_dh (dh);
}
/**
* Function called for each auditor to give us a chance to possibly
* launch a deposit confirmation interaction.
*
* @param cls closure
* @param ah handle to the auditor
* @param auditor_url base URL of the auditor
* @param auditor_pub public key of the auditor
* @return NULL if no deposit confirmation interaction was launched
*/
static struct TEAH_AuditorInteractionEntry *
static void
auditor_cb (void *cls,
struct TALER_AUDITOR_Handle *ah,
const char *auditor_url,
const struct TALER_AuditorPublicKeyP *auditor_pub)
{
struct TALER_EXCHANGE_BatchDepositHandle *dh = cls;
const struct TALER_EXCHANGE_Keys *key_state;
const struct TALER_EXCHANGE_SigningPublicKey *spk;
struct TEAH_AuditorInteractionEntry *aie;
struct TALER_Amount amount_without_fee;
@ -159,31 +261,33 @@ auditor_cb (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not providing deposit confirmation to auditor\n");
return NULL;
return;
}
coin = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
dh->num_cdds);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Will provide deposit confirmation to auditor `%s'\n",
TALER_B2S (auditor_pub));
key_state = TALER_EXCHANGE_get_keys (dh->exchange);
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
dki = TALER_EXCHANGE_get_denomination_key_by_hash (dh->keys,
&dh->cdds[coin].h_denom_pub);
GNUNET_assert (NULL != dki);
spk = TALER_EXCHANGE_get_signing_key_info (key_state,
spk = TALER_EXCHANGE_get_signing_key_info (dh->keys,
&dh->exchange_pub);
if (NULL == spk)
{
GNUNET_break_op (0);
return NULL;
return;
}
GNUNET_assert (0 <=
TALER_amount_subtract (&amount_without_fee,
&dh->cdds[coin].amount,
&dki->fees.deposit));
aie = GNUNET_new (struct TEAH_AuditorInteractionEntry);
aie->dh = dh;
aie->auditor_url = auditor_url;
aie->dch = TALER_AUDITOR_deposit_confirmation (
ah,
dh->ctx,
auditor_url,
&dh->h_wire,
&dh->h_policy,
&dh->dcd.h_contract_terms,
@ -195,14 +299,16 @@ auditor_cb (void *cls,
&dh->dcd.merchant_pub,
&dh->exchange_pub,
&dh->exchange_sigs[coin],
&key_state->master_pub,
&dh->keys->master_pub,
spk->valid_from,
spk->valid_until,
spk->valid_legal,
&spk->master_sig,
&TEAH_acc_confirmation_cb,
&acc_confirmation_cb,
aie);
return aie;
GNUNET_CONTAINER_DLL_insert (dh->ai_head,
dh->ai_tail,
aie);
}
@ -221,22 +327,19 @@ handle_deposit_finished (void *cls,
{
struct TALER_EXCHANGE_BatchDepositHandle *dh = cls;
const json_t *j = response;
struct TALER_EXCHANGE_BatchDepositResult dr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
const struct TALER_EXCHANGE_Keys *keys;
struct TALER_EXCHANGE_BatchDepositResult *dr = &dh->dr;
dh->job = NULL;
keys = TALER_EXCHANGE_get_keys (dh->exchange);
dh->response = json_incref ((json_t*) j);
dr->hr.reply = dh->response;
dr->hr.http_status = (unsigned int) response_code;
switch (response_code)
{
case 0:
dr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
dr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
{
const struct TALER_EXCHANGE_Keys *key_state;
const json_t *sigs;
json_t *sig;
unsigned int idx;
@ -247,7 +350,7 @@ handle_deposit_finished (void *cls,
&dh->exchange_pub),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("transaction_base_url",
&dr.details.ok.transaction_base_url),
&dr->details.ok.transaction_base_url),
NULL),
GNUNET_JSON_spec_timestamp ("exchange_timestamp",
&dh->exchange_timestamp),
@ -260,27 +363,26 @@ handle_deposit_finished (void *cls,
NULL, NULL))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
dr->hr.http_status = 0;
dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
if (json_array_size (sigs) != dh->num_cdds)
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
dr->hr.http_status = 0;
dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
dh->exchange_sigs = GNUNET_new_array (dh->num_cdds,
struct TALER_ExchangeSignatureP);
key_state = TALER_EXCHANGE_get_keys (dh->exchange);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
TALER_EXCHANGE_test_signing_key (dh->keys,
&dh->exchange_pub))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
dr->hr.http_status = 0;
dr->hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
break;
}
json_array_foreach (sigs, idx, sig)
@ -299,11 +401,11 @@ handle_deposit_finished (void *cls,
NULL, NULL))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
dr->hr.http_status = 0;
dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
dki = TALER_EXCHANGE_get_denomination_key_by_hash (dh->keys,
&dh->cdds[idx].
h_denom_pub);
GNUNET_assert (NULL != dki);
@ -327,42 +429,41 @@ handle_deposit_finished (void *cls,
&dh->exchange_sigs[idx]))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
dr->hr.http_status = 0;
dr->hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
break;
}
}
TEAH_get_auditors_for_dc (dh->exchange,
TEAH_get_auditors_for_dc (dh->keys,
&auditor_cb,
dh);
}
dr.details.ok.exchange_sigs = dh->exchange_sigs;
dr.details.ok.exchange_pub = &dh->exchange_pub;
dr.details.ok.deposit_timestamp = dh->exchange_timestamp;
dr.details.ok.num_signatures = dh->num_cdds;
dr->details.ok.exchange_sigs = dh->exchange_sigs;
dr->details.ok.exchange_pub = &dh->exchange_pub;
dr->details.ok.deposit_timestamp = dh->exchange_timestamp;
dr->details.ok.num_signatures = dh->num_cdds;
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
dr->hr.ec = TALER_JSON_get_error_code (j);
dr->hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_FORBIDDEN:
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
dr->hr.ec = TALER_JSON_get_error_code (j);
dr->hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND:
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
dr->hr.ec = TALER_JSON_get_error_code (j);
dr->hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
break;
case MHD_HTTP_CONFLICT:
{
const struct TALER_EXCHANGE_Keys *key_state;
struct TALER_CoinSpendPublicKeyP coin_pub;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("coin_pub",
@ -378,8 +479,8 @@ handle_deposit_finished (void *cls,
NULL, NULL))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
dr->hr.http_status = 0;
dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
for (unsigned int i = 0; i<dh->num_cdds; i++)
@ -388,14 +489,13 @@ handle_deposit_finished (void *cls,
GNUNET_memcmp (&coin_pub,
&dh->cdds[i].coin_pub))
continue;
key_state = TALER_EXCHANGE_get_keys (dh->exchange);
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
dki = TALER_EXCHANGE_get_denomination_key_by_hash (dh->keys,
&dh->cdds[i].
h_denom_pub);
GNUNET_assert (NULL != dki);
if (GNUNET_OK !=
TALER_EXCHANGE_check_coin_conflict_ (
keys,
dh->keys,
j,
dki,
&dh->cdds[i].coin_pub,
@ -403,8 +503,8 @@ handle_deposit_finished (void *cls,
&dh->cdds[i].amount))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
dr->hr.http_status = 0;
dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
found = true;
@ -413,12 +513,12 @@ handle_deposit_finished (void *cls,
if (! found)
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
dr->hr.http_status = 0;
dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
dr->hr.ec = TALER_JSON_get_error_code (j);
dr->hr.hint = TALER_JSON_get_error_hint (j);
}
break;
case MHD_HTTP_GONE:
@ -426,35 +526,37 @@ handle_deposit_finished (void *cls,
/* Note: one might want to check /keys for revocation
signature here, alas tricky in case our /keys
is outdated => left to clients */
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
dr->hr.ec = TALER_JSON_get_error_code (j);
dr->hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
dr->hr.ec = TALER_JSON_get_error_code (j);
dr->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 */
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
dr->hr.ec = TALER_JSON_get_error_code (j);
dr->hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange deposit\n",
(unsigned int) response_code,
dr.hr.ec);
dr->hr.ec);
GNUNET_break_op (0);
break;
}
dh->cb (dh->cb_cls,
&dr);
TALER_EXCHANGE_batch_deposit_cancel (dh);
if (NULL != dh->ai_head)
return;
finish_dh (dh);
}
struct TALER_EXCHANGE_BatchDepositHandle *
TALER_EXCHANGE_batch_deposit (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_EXCHANGE_DepositContractDetail *dcd,
unsigned int num_cdds,
const struct TALER_EXCHANGE_CoinDepositDetail *cdds,
@ -462,16 +564,12 @@ TALER_EXCHANGE_batch_deposit (
void *cb_cls,
enum TALER_ErrorCode *ec)
{
const struct TALER_EXCHANGE_Keys *key_state;
struct TALER_EXCHANGE_BatchDepositHandle *dh;
struct GNUNET_CURL_Context *ctx;
json_t *deposit_obj;
json_t *deposits;
CURL *eh;
struct TALER_Amount amount_without_fee;
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
if (GNUNET_TIME_timestamp_cmp (dcd->refund_deadline,
>,
dcd->wire_deadline))
@ -480,10 +578,8 @@ TALER_EXCHANGE_batch_deposit (
*ec = TALER_EC_EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE;
return NULL;
}
key_state = TALER_EXCHANGE_get_keys (exchange);
dh = GNUNET_new (struct TALER_EXCHANGE_BatchDepositHandle);
dh->auditor_chance = AUDITOR_CHANCE;
dh->exchange = exchange;
dh->cb = cb;
dh->cb_cls = cb_cls;
dh->cdds = GNUNET_memdup (cdds,
@ -504,7 +600,7 @@ TALER_EXCHANGE_batch_deposit (
const struct TALER_EXCHANGE_CoinDepositDetail *cdd = &cdds[i];
const struct TALER_EXCHANGE_DenomPublicKey *dki;
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
dki = TALER_EXCHANGE_get_denomination_key_by_hash (keys,
&cdd->h_denom_pub);
if (NULL == dki)
{
@ -563,8 +659,9 @@ TALER_EXCHANGE_batch_deposit (
&cdd->coin_sig)
)));
}
dh->url = TEAH_path_to_url (exchange,
"/batch-deposit");
dh->url = TALER_url_join (url,
"batch-deposit",
NULL);
if (NULL == dh->url)
{
GNUNET_break (0);
@ -600,7 +697,7 @@ TALER_EXCHANGE_batch_deposit (
eh = TALER_EXCHANGE_curl_easy_get_ (dh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=
TALER_curl_easy_post (&dh->ctx,
TALER_curl_easy_post (&dh->post_ctx,
eh,
deposit_obj)) )
{
@ -618,10 +715,11 @@ TALER_EXCHANGE_batch_deposit (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for deposit: `%s'\n",
dh->url);
ctx = TEAH_handle_to_context (exchange);
dh->ctx = ctx;
dh->keys = TALER_EXCHANGE_keys_incref (keys);
dh->job = GNUNET_CURL_job_add2 (ctx,
eh,
dh->ctx.headers,
dh->post_ctx.headers,
&handle_deposit_finished,
dh);
return dh;
@ -640,15 +738,31 @@ void
TALER_EXCHANGE_batch_deposit_cancel (
struct TALER_EXCHANGE_BatchDepositHandle *deposit)
{
struct TEAH_AuditorInteractionEntry *aie;
while (NULL != (aie = deposit->ai_head))
{
GNUNET_assert (aie->dh == deposit);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not sending deposit confirmation to auditor `%s' due to cancellation\n",
aie->auditor_url);
TALER_AUDITOR_deposit_confirmation_cancel (aie->dch);
GNUNET_CONTAINER_DLL_remove (deposit->ai_head,
deposit->ai_tail,
aie);
GNUNET_free (aie);
}
if (NULL != deposit->job)
{
GNUNET_CURL_job_cancel (deposit->job);
deposit->job = NULL;
}
TALER_EXCHANGE_keys_decref (deposit->keys);
GNUNET_free (deposit->url);
GNUNET_free (deposit->cdds);
GNUNET_free (deposit->exchange_sigs);
TALER_curl_easy_post_finished (&deposit->ctx);
TALER_curl_easy_post_finished (&deposit->post_ctx);
json_decref (deposit->response);
GNUNET_free (deposit);
}

View File

@ -218,14 +218,15 @@ reserve_batch_withdraw_payment_required (
}
if (GNUNET_OK !=
TALER_EXCHANGE_parse_reserve_history (wh->exchange,
history,
&wh->reserve_pub,
balance.currency,
&total_in_from_history,
&total_out_from_history,
len,
rhistory))
TALER_EXCHANGE_parse_reserve_history (
TALER_EXCHANGE_get_keys (wh->exchange),
history,
&wh->reserve_pub,
balance.currency,
&total_in_from_history,
&total_out_from_history,
len,
rhistory))
{
GNUNET_break_op (0);
TALER_EXCHANGE_free_reserve_history (rhistory,

View File

@ -34,9 +34,9 @@ struct HistoryParseContext
{
/**
* Exchange we use.
* Keys of the exchange we use.
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* Our reserve public key.
@ -187,7 +187,7 @@ parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
const struct TALER_EXCHANGE_Keys *key_state;
const struct TALER_EXCHANGE_DenomPublicKey *dki;
key_state = TALER_EXCHANGE_get_keys (uc->exchange);
key_state = uc->keys;
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
&h_denom_pub);
if ( (GNUNET_YES !=
@ -275,7 +275,7 @@ parse_recoup (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
key_state = TALER_EXCHANGE_get_keys (uc->exchange);
key_state = uc->keys;
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
&rh->details.
@ -349,7 +349,7 @@ parse_closing (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
key_state = TALER_EXCHANGE_get_keys (uc->exchange);
key_state = uc->keys;
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (
key_state,
@ -647,7 +647,7 @@ parse_close (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
enum GNUNET_GenericReturnValue
TALER_EXCHANGE_parse_reserve_history (
struct TALER_EXCHANGE_Handle *exchange,
struct TALER_EXCHANGE_Keys *keys,
const json_t *history,
const struct TALER_ReservePublicKeyP *reserve_pub,
const char *currency,
@ -673,7 +673,7 @@ TALER_EXCHANGE_parse_reserve_history (
};
struct GNUNET_HashCode uuid[history_length];
struct HistoryParseContext uc = {
.exchange = exchange,
.keys = keys,
.reserve_pub = reserve_pub,
.uuids = uuid,
.total_in = total_in,

View File

@ -38,11 +38,6 @@
struct TALER_EXCHANGE_ContractsGetHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -194,7 +189,8 @@ handle_contract_get_finished (void *cls,
struct TALER_EXCHANGE_ContractsGetHandle *
TALER_EXCHANGE_contract_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ContractDiffiePrivateP *contract_priv,
TALER_EXCHANGE_ContractGetCallback cb,
void *cb_cls)
@ -203,14 +199,7 @@ TALER_EXCHANGE_contract_get (
CURL *eh;
char arg_str[sizeof (cgh->cpub) * 2 + 48];
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
cgh = GNUNET_new (struct TALER_EXCHANGE_ContractsGetHandle);
cgh->exchange = exchange;
cgh->cb = cb;
cgh->cb_cls = cb_cls;
GNUNET_CRYPTO_ecdhe_key_get_public (&contract_priv->ecdhe_priv,
@ -226,12 +215,13 @@ TALER_EXCHANGE_contract_get (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/contracts/%s",
"contracts/%s",
cpub_str);
}
cgh->url = TEAH_path_to_url (exchange,
arg_str);
cgh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == cgh->url)
{
GNUNET_free (cgh);
@ -247,7 +237,7 @@ TALER_EXCHANGE_contract_get (
GNUNET_free (cgh);
return NULL;
}
cgh->job = GNUNET_CURL_job_add (TEAH_handle_to_context (exchange),
cgh->job = GNUNET_CURL_job_add (ctx,
eh,
&handle_contract_get_finished,
cgh);

View File

@ -38,10 +38,6 @@
*/
struct TALER_EXCHANGE_CsRMeltHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* Function to call with the result.
@ -220,12 +216,14 @@ handle_csr_finished (void *cls,
struct TALER_EXCHANGE_CsRMeltHandle *
TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_RefreshMasterSecretP *rms,
unsigned int nks_len,
struct TALER_EXCHANGE_NonceKey *nks,
TALER_EXCHANGE_CsRMeltCallback res_cb,
void *res_cb_cls)
TALER_EXCHANGE_csr_melt (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_RefreshMasterSecretP *rms,
unsigned int nks_len,
struct TALER_EXCHANGE_NonceKey *nks,
TALER_EXCHANGE_CsRMeltCallback res_cb,
void *res_cb_cls)
{
struct TALER_EXCHANGE_CsRMeltHandle *csrh;
json_t *csr_arr;
@ -242,7 +240,6 @@ TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
return NULL;
}
csrh = GNUNET_new (struct TALER_EXCHANGE_CsRMeltHandle);
csrh->exchange = exchange;
csrh->cb = res_cb;
csrh->cb_cls = res_cb_cls;
csr_arr = json_array ();
@ -262,8 +259,9 @@ TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
json_array_append_new (csr_arr,
csr_obj));
}
csrh->url = TEAH_path_to_url (exchange,
"/csr-melt");
csrh->url = TALER_url_join (url,
"csr-melt",
NULL);
if (NULL == csrh->url)
{
json_decref (csr_arr);
@ -272,7 +270,6 @@ TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
}
{
CURL *eh;
struct GNUNET_CURL_Context *ctx;
json_t *req;
req = GNUNET_JSON_PACK (
@ -280,7 +277,6 @@ TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange,
rms),
GNUNET_JSON_pack_array_steal ("nks",
csr_arr));
ctx = TEAH_handle_to_context (exchange);
eh = TALER_EXCHANGE_curl_easy_get_ (csrh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=

View File

@ -1,557 +0,0 @@
/*
This file is part of TALER
Copyright (C) 2014-2021 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
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
/**
* @file lib/exchange_api_deposit.c
* @brief Implementation of the /deposit request of the exchange's HTTP API
* @author Sree Harsha Totakura <sreeharsha@totakura.in>
* @author Christian Grothoff
*/
#include "platform.h"
#include <jansson.h>
#include <microhttpd.h> /* just for HTTP status codes */
#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_json_lib.h>
#include <gnunet/gnunet_curl_lib.h>
#include "taler_json_lib.h"
#include "taler_auditor_service.h"
#include "taler_exchange_service.h"
#include "exchange_api_common.h"
#include "exchange_api_handle.h"
#include "taler_signatures.h"
#include "exchange_api_curl_defaults.h"
/**
* 1:#AUDITOR_CHANCE is the probability that we report deposits
* to the auditor.
*
* 20==5% of going to auditor. This is possibly still too high, but set
* deliberately this high for testing
*/
#define AUDITOR_CHANCE 20
/**
* @brief A Deposit Handle
*/
struct TALER_EXCHANGE_DepositHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
char *url;
/**
* Context for #TEH_curl_easy_post(). Keeps the data that must
* persist for Curl to make the upload.
*/
struct TALER_CURL_PostContext ctx;
/**
* Handle for the request.
*/
struct GNUNET_CURL_Job *job;
/**
* Function to call with the result.
*/
TALER_EXCHANGE_DepositResultCallback cb;
/**
* Closure for @a cb.
*/
void *cb_cls;
/**
* Details about the contract.
*/
struct TALER_EXCHANGE_DepositContractDetail dcd;
/**
* Details about the coin.
*/
struct TALER_EXCHANGE_CoinDepositDetail cdd;
/**
* Hash of the merchant's wire details.
*/
struct TALER_MerchantWireHashP h_wire;
/**
* Hash over the policy extension, or all zero.
*/
struct TALER_ExtensionPolicyHashP h_policy;
/**
* Time when this confirmation was generated / when the exchange received
* the deposit request.
*/
struct GNUNET_TIME_Timestamp exchange_timestamp;
/**
* Exchange signature, set for #auditor_cb.
*/
struct TALER_ExchangeSignatureP exchange_sig;
/**
* Exchange signing public key, set for #auditor_cb.
*/
struct TALER_ExchangePublicKeyP exchange_pub;
/**
* Chance that we will inform the auditor about the deposit
* is 1:n, where the value of this field is "n".
*/
unsigned int auditor_chance;
};
/**
* Function called for each auditor to give us a chance to possibly
* launch a deposit confirmation interaction.
*
* @param cls closure
* @param ah handle to the auditor
* @param auditor_pub public key of the auditor
* @return NULL if no deposit confirmation interaction was launched
*/
static struct TEAH_AuditorInteractionEntry *
auditor_cb (void *cls,
struct TALER_AUDITOR_Handle *ah,
const struct TALER_AuditorPublicKeyP *auditor_pub)
{
struct TALER_EXCHANGE_DepositHandle *dh = cls;
const struct TALER_EXCHANGE_Keys *key_state;
const struct TALER_EXCHANGE_SigningPublicKey *spk;
struct TEAH_AuditorInteractionEntry *aie;
struct TALER_Amount amount_without_fee;
const struct TALER_EXCHANGE_DenomPublicKey *dki;
if (0 !=
GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
dh->auditor_chance))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not providing deposit confirmation to auditor\n");
return NULL;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Will provide deposit confirmation to auditor `%s'\n",
TALER_B2S (auditor_pub));
key_state = TALER_EXCHANGE_get_keys (dh->exchange);
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
&dh->cdd.h_denom_pub);
GNUNET_assert (NULL != dki);
spk = TALER_EXCHANGE_get_signing_key_info (key_state,
&dh->exchange_pub);
if (NULL == spk)
{
GNUNET_break_op (0);
return NULL;
}
GNUNET_assert (0 <=
TALER_amount_subtract (&amount_without_fee,
&dh->cdd.amount,
&dki->fees.deposit));
aie = GNUNET_new (struct TEAH_AuditorInteractionEntry);
aie->dch = TALER_AUDITOR_deposit_confirmation (
ah,
&dh->h_wire,
&dh->h_policy,
&dh->dcd.h_contract_terms,
dh->exchange_timestamp,
dh->dcd.wire_deadline,
dh->dcd.refund_deadline,
&amount_without_fee,
&dh->cdd.coin_pub,
&dh->dcd.merchant_pub,
&dh->exchange_pub,
&dh->exchange_sig,
&key_state->master_pub,
spk->valid_from,
spk->valid_until,
spk->valid_legal,
&spk->master_sig,
&TEAH_acc_confirmation_cb,
aie);
return aie;
}
/**
* Function called when we're done processing the
* HTTP /deposit request.
*
* @param cls the `struct TALER_EXCHANGE_DepositHandle`
* @param response_code HTTP response code, 0 on error
* @param response parsed JSON result, NULL on error
*/
static void
handle_deposit_finished (void *cls,
long response_code,
const void *response)
{
struct TALER_EXCHANGE_DepositHandle *dh = cls;
const json_t *j = response;
struct TALER_EXCHANGE_DepositResult dr = {
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
const struct TALER_EXCHANGE_Keys *keys;
dh->job = NULL;
keys = TALER_EXCHANGE_get_keys (dh->exchange);
switch (response_code)
{
case 0:
dr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
{
const struct TALER_EXCHANGE_Keys *key_state;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
&dh->exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
&dh->exchange_pub),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("transaction_base_url",
&dr.details.ok.transaction_base_url),
NULL),
GNUNET_JSON_spec_timestamp ("exchange_timestamp",
&dh->exchange_timestamp),
GNUNET_JSON_spec_end ()
};
struct TALER_Amount amount_without_fee;
const struct TALER_EXCHANGE_DenomPublicKey *dki;
if (GNUNET_OK !=
GNUNET_JSON_parse (j,
spec,
NULL, NULL))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
key_state = TALER_EXCHANGE_get_keys (dh->exchange);
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
&dh->cdd.h_denom_pub);
GNUNET_assert (NULL != dki);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
&dh->exchange_pub))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
break;
}
GNUNET_assert (0 <=
TALER_amount_subtract (&amount_without_fee,
&dh->cdd.amount,
&dki->fees.deposit));
if (GNUNET_OK !=
TALER_exchange_online_deposit_confirmation_verify (
&dh->dcd.h_contract_terms,
&dh->h_wire,
&dh->h_policy,
dh->exchange_timestamp,
dh->dcd.wire_deadline,
dh->dcd.refund_deadline,
&amount_without_fee,
&dh->cdd.coin_pub,
&dh->dcd.merchant_pub,
&dh->exchange_pub,
&dh->exchange_sig))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_EXCHANGE_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
break;
}
TEAH_get_auditors_for_dc (dh->exchange,
&auditor_cb,
dh);
}
dr.details.ok.exchange_sig = &dh->exchange_sig;
dr.details.ok.exchange_pub = &dh->exchange_pub;
dr.details.ok.deposit_timestamp = dh->exchange_timestamp;
break;
case MHD_HTTP_BAD_REQUEST:
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_FORBIDDEN:
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, exchange says one of the signatures is
invalid; as we checked them, this should never happen, we
should pass the JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND:
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
break;
case MHD_HTTP_CONFLICT:
{
const struct TALER_EXCHANGE_Keys *key_state;
const struct TALER_EXCHANGE_DenomPublicKey *dki;
key_state = TALER_EXCHANGE_get_keys (dh->exchange);
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
&dh->cdd.h_denom_pub);
GNUNET_assert (NULL != dki);
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
if (GNUNET_OK !=
TALER_EXCHANGE_check_coin_conflict_ (
keys,
j,
dki,
&dh->cdd.coin_pub,
&dh->cdd.coin_sig,
&dh->cdd.amount))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
}
break;
case MHD_HTTP_GONE:
/* could happen if denomination was revoked */
/* Note: one might want to check /keys for revocation
signature here, alas tricky in case our /keys
is outdated => left to clients */
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.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 */
dr.hr.ec = TALER_JSON_get_error_code (j);
dr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange deposit\n",
(unsigned int) response_code,
dr.hr.ec);
GNUNET_break_op (0);
break;
}
dh->cb (dh->cb_cls,
&dr);
TALER_EXCHANGE_deposit_cancel (dh);
}
struct TALER_EXCHANGE_DepositHandle *
TALER_EXCHANGE_deposit (
struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DepositContractDetail *dcd,
const struct TALER_EXCHANGE_CoinDepositDetail *cdd,
TALER_EXCHANGE_DepositResultCallback cb,
void *cb_cls,
enum TALER_ErrorCode *ec)
{
const struct TALER_EXCHANGE_Keys *key_state;
struct TALER_EXCHANGE_DepositHandle *dh;
struct GNUNET_CURL_Context *ctx;
json_t *deposit_obj;
CURL *eh;
const struct TALER_EXCHANGE_DenomPublicKey *dki;
struct TALER_Amount amount_without_fee;
char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
if (GNUNET_TIME_timestamp_cmp (dcd->refund_deadline,
>,
dcd->wire_deadline))
{
GNUNET_break_op (0);
*ec = TALER_EC_EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE;
return NULL;
}
{
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
char *end;
end = GNUNET_STRINGS_data_to_string (
&cdd->coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP),
pub_str,
sizeof (pub_str));
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/coins/%s/deposit",
pub_str);
}
key_state = TALER_EXCHANGE_get_keys (exchange);
dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
&cdd->h_denom_pub);
if (NULL == dki)
{
*ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
GNUNET_break_op (0);
return NULL;
}
if (0 >
TALER_amount_subtract (&amount_without_fee,
&cdd->amount,
&dki->fees.deposit))
{
*ec = TALER_EC_EXCHANGE_DEPOSIT_FEE_ABOVE_AMOUNT;
GNUNET_break_op (0);
return NULL;
}
dh = GNUNET_new (struct TALER_EXCHANGE_DepositHandle);
dh->auditor_chance = AUDITOR_CHANCE;
dh->exchange = exchange;
dh->cb = cb;
dh->cb_cls = cb_cls;
dh->cdd = *cdd;
dh->dcd = *dcd;
if (NULL != dcd->policy_details)
TALER_deposit_policy_hash (dcd->policy_details,
&dh->h_policy);
TALER_merchant_wire_signature_hash (dcd->merchant_payto_uri,
&dcd->wire_salt,
&dh->h_wire);
if (GNUNET_OK !=
TALER_EXCHANGE_verify_deposit_signature_ (dcd,
&dh->h_policy,
&dh->h_wire,
cdd,
dki))
{
*ec = TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID;
GNUNET_break_op (0);
GNUNET_free (dh);
return NULL;
}
dh->url = TEAH_path_to_url (exchange,
arg_str);
if (NULL == dh->url)
{
GNUNET_break (0);
*ec = TALER_EC_GENERIC_ALLOCATION_FAILURE;
GNUNET_free (dh->url);
GNUNET_free (dh);
return NULL;
}
deposit_obj = GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("contribution",
&cdd->amount),
GNUNET_JSON_pack_string ("merchant_payto_uri",
dcd->merchant_payto_uri),
GNUNET_JSON_pack_data_auto ("wire_salt",
&dcd->wire_salt),
GNUNET_JSON_pack_data_auto ("h_contract_terms",
&dcd->h_contract_terms),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_data_auto ("h_age_commitment",
&cdd->h_age_commitment)),
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
&cdd->h_denom_pub),
TALER_JSON_pack_denom_sig ("ub_sig",
&cdd->denom_sig),
GNUNET_JSON_pack_timestamp ("timestamp",
dcd->timestamp),
GNUNET_JSON_pack_data_auto ("merchant_pub",
&dcd->merchant_pub),
GNUNET_JSON_pack_allow_null (
GNUNET_JSON_pack_timestamp ("refund_deadline",
dcd->refund_deadline)),
GNUNET_JSON_pack_timestamp ("wire_transfer_deadline",
dcd->wire_deadline),
GNUNET_JSON_pack_data_auto ("coin_sig",
&cdd->coin_sig));
GNUNET_assert (NULL != deposit_obj);
eh = TALER_EXCHANGE_curl_easy_get_ (dh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=
TALER_curl_easy_post (&dh->ctx,
eh,
deposit_obj)) )
{
*ec = TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE;
GNUNET_break (0);
if (NULL != eh)
curl_easy_cleanup (eh);
json_decref (deposit_obj);
GNUNET_free (dh->url);
GNUNET_free (dh);
return NULL;
}
json_decref (deposit_obj);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for deposit: `%s'\n",
dh->url);
ctx = TEAH_handle_to_context (exchange);
dh->job = GNUNET_CURL_job_add2 (ctx,
eh,
dh->ctx.headers,
&handle_deposit_finished,
dh);
return dh;
}
void
TALER_EXCHANGE_deposit_force_dc (struct TALER_EXCHANGE_DepositHandle *deposit)
{
deposit->auditor_chance = 1;
}
void
TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit)
{
if (NULL != deposit->job)
{
GNUNET_CURL_job_cancel (deposit->job);
deposit->job = NULL;
}
GNUNET_free (deposit->url);
TALER_curl_easy_post_finished (&deposit->ctx);
GNUNET_free (deposit);
}
/* end of exchange_api_deposit.c */

View File

@ -39,9 +39,9 @@ struct TALER_EXCHANGE_DepositGetHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -131,7 +131,7 @@ handle_deposit_wtid_finished (void *cls,
};
const struct TALER_EXCHANGE_Keys *key_state;
key_state = TALER_EXCHANGE_get_keys (dwh->exchange);
key_state = dwh->keys;
GNUNET_assert (NULL != key_state);
if (GNUNET_OK !=
GNUNET_JSON_parse (j,
@ -255,7 +255,9 @@ handle_deposit_wtid_finished (void *cls,
struct TALER_EXCHANGE_DepositGetHandle *
TALER_EXCHANGE_deposits_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_MerchantPrivateKeyP *merchant_priv,
const struct TALER_MerchantWireHashP *h_wire,
const struct TALER_PrivateContractHashP *h_contract_terms,
@ -267,7 +269,6 @@ TALER_EXCHANGE_deposits_get (
struct TALER_MerchantPublicKeyP merchant;
struct TALER_MerchantSignatureP merchant_sig;
struct TALER_EXCHANGE_DepositGetHandle *dwh;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[(sizeof (struct TALER_CoinSpendPublicKeyP)
+ sizeof (struct TALER_MerchantWireHashP)
@ -275,12 +276,6 @@ TALER_EXCHANGE_deposits_get (
+ sizeof (struct TALER_PrivateContractHashP)
+ sizeof (struct TALER_MerchantSignatureP)) * 2 + 48];
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv,
&merchant.eddsa_pub);
TALER_merchant_deposit_sign (h_contract_terms,
@ -339,7 +334,7 @@ TALER_EXCHANGE_deposits_get (
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/deposits/%s/%s/%s/%s?merchant_sig=%s%s%s",
"deposits/%s/%s/%s/%s?merchant_sig=%s%s%s",
whash_str,
mpub_str,
chash_str,
@ -352,11 +347,11 @@ TALER_EXCHANGE_deposits_get (
}
dwh = GNUNET_new (struct TALER_EXCHANGE_DepositGetHandle);
dwh->exchange = exchange;
dwh->cb = cb;
dwh->cb_cls = cb_cls;
dwh->url = TEAH_path_to_url (exchange,
arg_str);
dwh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == dwh->url)
{
GNUNET_free (dwh);
@ -365,7 +360,6 @@ TALER_EXCHANGE_deposits_get (
dwh->h_wire = *h_wire;
dwh->h_contract_terms = *h_contract_terms;
dwh->coin_pub = *coin_pub;
eh = TALER_EXCHANGE_curl_easy_get_ (dwh->url);
if (NULL == eh)
{
@ -374,11 +368,11 @@ TALER_EXCHANGE_deposits_get (
GNUNET_free (dwh);
return NULL;
}
ctx = TEAH_handle_to_context (exchange);
dwh->job = GNUNET_CURL_job_add (ctx,
eh,
&handle_deposit_wtid_finished,
dwh);
dwh->keys = TALER_EXCHANGE_keys_incref (keys);
return dwh;
}
@ -393,6 +387,7 @@ TALER_EXCHANGE_deposits_get_cancel (struct TALER_EXCHANGE_DepositGetHandle *dwh)
}
GNUNET_free (dwh->url);
TALER_curl_easy_post_finished (&dwh->ctx);
TALER_EXCHANGE_keys_decref (dwh->keys);
GNUNET_free (dwh);
}

View File

@ -110,17 +110,7 @@ struct TEAH_AuditorListEntry
/**
* Handle to the auditor.
*/
struct TALER_AUDITOR_Handle *ah;
/**
* Head of DLL of interactions with this auditor.
*/
struct TEAH_AuditorInteractionEntry *ai_head;
/**
* Tail of DLL of interactions with this auditor.
*/
struct TEAH_AuditorInteractionEntry *ai_tail;
struct TALER_AUDITOR_GetConfigHandle *ah;
/**
* Public key of the auditor.
@ -168,57 +158,24 @@ struct KeysRequest
void
TEAH_acc_confirmation_cb (void *cls,
const struct TALER_AUDITOR_HttpResponse *hr)
{
struct TEAH_AuditorInteractionEntry *aie = cls;
struct TEAH_AuditorListEntry *ale = aie->ale;
if (MHD_HTTP_OK != hr->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to submit deposit confirmation to auditor `%s' with HTTP status %d (EC: %d). This is acceptable if it does not happen often.\n",
ale->auditor_url,
hr->http_status,
hr->ec);
}
GNUNET_CONTAINER_DLL_remove (ale->ai_head,
ale->ai_tail,
aie);
GNUNET_free (aie);
}
void
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Handle *h,
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Keys *keys,
TEAH_AuditorCallback ac,
void *ac_cls)
{
if (NULL == h->auditors_head)
if (0 == keys->num_auditors)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"No auditor available for exchange `%s'. Not submitting deposit confirmations.\n",
h->url);
"No auditor available. Not submitting deposit confirmations.\n");
return;
}
for (struct TEAH_AuditorListEntry *ale = h->auditors_head;
NULL != ale;
ale = ale->next)
for (unsigned int i = 0; i<keys->num_auditors; i++)
{
struct TEAH_AuditorInteractionEntry *aie;
const struct TALER_EXCHANGE_AuditorInformation *auditor
= &keys->auditors[i];
if (! ale->is_up)
continue;
aie = ac (ac_cls,
ale->ah,
&ale->auditor_pub);
if (NULL != aie)
{
aie->ale = ale;
GNUNET_CONTAINER_DLL_insert (ale->ai_head,
ale->ai_tail,
aie);
}
ac (ac_cls,
auditor->auditor_url,
&auditor->auditor_pub);
}
}
@ -579,21 +536,18 @@ parse_global_fee (struct TALER_EXCHANGE_GlobalFee *gf,
* auditor as 'up'.
*
* @param cls closure, a `struct TEAH_AuditorListEntry *`
* @param hr http response from the auditor
* @param vi basic information about the auditor
* @param compat protocol compatibility information
* @param vr response from the auditor
*/
static void
auditor_version_cb (
auditor_config_cb (
void *cls,
const struct TALER_AUDITOR_HttpResponse *hr,
const struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility compat)
const struct TALER_AUDITOR_ConfigResponse *vr)
{
struct TEAH_AuditorListEntry *ale = cls;
enum TALER_AUDITOR_VersionCompatibility compat;
(void) hr;
if (NULL == vi)
ale->ah = NULL;
if (MHD_HTTP_OK != vr->hr.http_status)
{
/* In this case, we don't mark the auditor as 'up' */
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@ -601,7 +555,7 @@ auditor_version_cb (
ale->auditor_url);
return;
}
compat = vr->details.ok.compat;
if (0 != (TALER_AUDITOR_VC_INCOMPATIBLE & compat))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@ -667,10 +621,10 @@ update_auditors (struct TALER_EXCHANGE_Handle *exchange)
GNUNET_CONTAINER_DLL_insert (exchange->auditors_head,
exchange->auditors_tail,
ale);
ale->ah = TALER_AUDITOR_connect (exchange->ctx,
ale->auditor_url,
&auditor_version_cb,
ale);
ale->ah = TALER_AUDITOR_get_config (exchange->ctx,
ale->auditor_url,
&auditor_config_cb,
ale);
}
}
@ -2123,26 +2077,14 @@ TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange)
while (NULL != (ale = exchange->auditors_head))
{
struct TEAH_AuditorInteractionEntry *aie;
while (NULL != (aie = ale->ai_head))
{
GNUNET_assert (aie->ale == ale);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not sending deposit confirmation to auditor `%s' due to exchange disconnect\n",
ale->auditor_url);
TALER_AUDITOR_deposit_confirmation_cancel (aie->dch);
GNUNET_CONTAINER_DLL_remove (ale->ai_head,
ale->ai_tail,
aie);
GNUNET_free (aie);
}
GNUNET_CONTAINER_DLL_remove (exchange->auditors_head,
exchange->auditors_tail,
ale);
TALER_LOG_DEBUG ("Disconnecting the auditor `%s'\n",
ale->auditor_url);
TALER_AUDITOR_disconnect (ale->ah);
if (NULL != ale->ah)
{
TALER_AUDITOR_get_config_cancel (ale->ah);
ale->ah = NULL;
}
GNUNET_free (ale->auditor_url);
GNUNET_free (ale);
}
@ -2275,7 +2217,7 @@ TALER_EXCHANGE_get_denomination_key_by_hash (
}
const struct TALER_EXCHANGE_Keys *
struct TALER_EXCHANGE_Keys *
TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange)
{
(void) TALER_EXCHANGE_check_keys_current (exchange,
@ -2297,4 +2239,33 @@ TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange)
}
/**
* Obtain the keys from the exchange in the raw JSON format.
*
* @param keys the keys structure
* @return the keys in raw JSON
*/
json_t *
TALER_EXCHANGE_keys_to_json (struct TALER_EXCHANGE_Keys *keys)
{
// FIXME!
return NULL;
}
struct TALER_EXCHANGE_Keys *
TALER_EXCHANGE_keys_incref (struct TALER_EXCHANGE_Keys *keys)
{
// FIXME
return keys;
}
void
TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys)
{
// FIXME
}
/* end of exchange_api_handle.c */

View File

@ -34,32 +34,6 @@
struct TEAH_AuditorListEntry;
/**
* Entry in list of ongoing interactions with an auditor.
*/
struct TEAH_AuditorInteractionEntry
{
/**
* DLL entry.
*/
struct TEAH_AuditorInteractionEntry *next;
/**
* DLL entry.
*/
struct TEAH_AuditorInteractionEntry *prev;
/**
* Which auditor is this action associated with?
*/
struct TEAH_AuditorListEntry *ale;
/**
* Interaction state.
*/
struct TALER_AUDITOR_DepositConfirmationHandle *dch;
};
/**
* Stages of initialization for the `struct TALER_EXCHANGE_Handle`
*/
@ -178,39 +152,26 @@ struct TALER_EXCHANGE_Handle
* launch a deposit confirmation interaction.
*
* @param cls closure
* @param ah handle to the auditor
* @param auditor_url base URL of the auditor
* @param auditor_pub public key of the auditor
* @return NULL if no deposit confirmation interaction was launched
*/
typedef struct TEAH_AuditorInteractionEntry *
typedef void
(*TEAH_AuditorCallback)(void *cls,
struct TALER_AUDITOR_Handle *ah,
const char *auditor_url,
const struct TALER_AuditorPublicKeyP *auditor_pub);
/**
* 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
TEAH_acc_confirmation_cb (void *cls,
const struct TALER_AUDITOR_HttpResponse *hr);
/**
* 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 keys the keys to go over auditors for
* @param ac function to call per auditor
* @param ac_cls closure for @a ac
*/
void
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Handle *h,
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Keys *keys,
TEAH_AuditorCallback ac,
void *ac_cls);

View File

@ -36,11 +36,6 @@
struct TALER_EXCHANGE_KycProofHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -140,27 +135,22 @@ handle_kyc_proof_finished (void *cls,
struct TALER_EXCHANGE_KycProofHandle *
TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_PaytoHashP *h_payto,
const char *logic,
const char *args,
TALER_EXCHANGE_KycProofCallback cb,
void *cb_cls)
TALER_EXCHANGE_kyc_proof (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_PaytoHashP *h_payto,
const char *logic,
const char *args,
TALER_EXCHANGE_KycProofCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_KycProofHandle *kph;
struct GNUNET_CURL_Context *ctx;
char *arg_str;
if (NULL == args)
args = "";
else
GNUNET_assert (args[0] == '&');
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
{
char hstr[sizeof (struct TALER_PaytoHashP) * 2];
char *end;
@ -171,17 +161,17 @@ TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *exchange,
sizeof (hstr));
*end = '\0';
GNUNET_asprintf (&arg_str,
"/kyc-proof/%s?state=%s%s",
"kyc-proof/%s?state=%s%s",
logic,
hstr,
args);
}
kph = GNUNET_new (struct TALER_EXCHANGE_KycProofHandle);
kph->exchange = exchange;
kph->cb = cb;
kph->cb_cls = cb_cls;
kph->url = TEAH_path_to_url (exchange,
arg_str);
kph->url = TALER_url_join (url,
arg_str,
NULL);
GNUNET_free (arg_str);
if (NULL == kph->url)
{
@ -202,7 +192,6 @@ TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *exchange,
curl_easy_setopt (kph->eh,
CURLOPT_FOLLOWLOCATION,
0L));
ctx = TEAH_handle_to_context (exchange);
kph->job = GNUNET_CURL_job_add_raw (ctx,
kph->eh,
NULL,

View File

@ -42,11 +42,6 @@ struct TALER_EXCHANGE_KycWalletHandle
*/
struct TALER_CURL_PostContext ctx;
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -154,16 +149,17 @@ handle_kyc_wallet_finished (void *cls,
struct TALER_EXCHANGE_KycWalletHandle *
TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_Amount *balance,
TALER_EXCHANGE_KycWalletCallback cb,
void *cb_cls)
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)
{
struct TALER_EXCHANGE_KycWalletHandle *kwh;
CURL *eh;
json_t *req;
struct GNUNET_CURL_Context *ctx;
struct TALER_ReservePublicKeyP reserve_pub;
struct TALER_ReserveSignatureP reserve_sig;
@ -181,18 +177,17 @@ TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle *exchange,
&reserve_sig));
GNUNET_assert (NULL != req);
kwh = GNUNET_new (struct TALER_EXCHANGE_KycWalletHandle);
kwh->exchange = exchange;
kwh->cb = cb;
kwh->cb_cls = cb_cls;
kwh->url = TEAH_path_to_url (exchange,
"/kyc-wallet");
kwh->url = TALER_url_join (url,
"kyc-wallet",
NULL);
if (NULL == kwh->url)
{
json_decref (req);
GNUNET_free (kwh);
return NULL;
}
ctx = TEAH_handle_to_context (exchange);
eh = TALER_EXCHANGE_curl_easy_get_ (kwh->url);
if ( (NULL == eh) ||
(GNUNET_OK !=

View File

@ -36,11 +36,6 @@
struct TALER_EXCHANGE_LinkHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -451,26 +446,19 @@ handle_link_finished (void *cls,
struct TALER_EXCHANGE_LinkHandle *
TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct
TALER_AgeCommitmentProof *age_commitment_proof,
TALER_EXCHANGE_LinkCallback link_cb,
void *link_cb_cls)
TALER_EXCHANGE_link (
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_AgeCommitmentProof *age_commitment_proof,
TALER_EXCHANGE_LinkCallback link_cb,
void *link_cb_cls)
{
struct TALER_EXCHANGE_LinkHandle *lh;
CURL *eh;
struct GNUNET_CURL_Context *ctx;
struct TALER_CoinSpendPublicKeyP coin_pub;
char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
&coin_pub.eddsa_pub);
{
@ -485,17 +473,17 @@ TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange,
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/coins/%s/link",
"coins/%s/link",
pub_str);
}
lh = GNUNET_new (struct TALER_EXCHANGE_LinkHandle);
lh->exchange = exchange;
lh->link_cb = link_cb;
lh->link_cb_cls = link_cb_cls;
lh->coin_priv = *coin_priv;
lh->age_commitment_proof = age_commitment_proof;
lh->url = TEAH_path_to_url (exchange,
arg_str);
lh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == lh->url)
{
GNUNET_free (lh);
@ -509,7 +497,6 @@ TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_free (lh);
return NULL;
}
ctx = TEAH_handle_to_context (exchange);
lh->job = GNUNET_CURL_job_add_with_ct_json (ctx,
eh,
&handle_link_finished,

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2015-2022 Taler Systems SA
Copyright (C) 2015-2023 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
@ -41,15 +41,25 @@ struct TALER_EXCHANGE_MeltHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
*/
char *url;
/**
* The exchange base url.
*/
char *exchange_url;
/**
* Curl context.
*/
struct GNUNET_CURL_Context *cctx;
/**
* Context for #TEH_curl_easy_post(). Keeps the data that must
* persist for Curl to make the upload.
@ -159,7 +169,7 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh,
return GNUNET_SYSERR;
}
/* check that exchange signing key is permitted */
key_state = TALER_EXCHANGE_get_keys (mh->exchange);
key_state = mh->keys;
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
exchange_pub))
@ -211,7 +221,7 @@ handle_melt_finished (void *cls,
const struct TALER_EXCHANGE_Keys *keys;
mh->job = NULL;
keys = TALER_EXCHANGE_get_keys (mh->exchange);
keys = mh->keys;
switch (response_code)
{
case 0:
@ -309,7 +319,6 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
const struct TALER_EXCHANGE_Keys *key_state;
json_t *melt_obj;
CURL *eh;
struct GNUNET_CURL_Context *ctx;
char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
struct TALER_DenominationHashP h_denom_pub;
struct TALER_ExchangeWithdrawValues alg_values[mh->rd->fresh_pks_len];
@ -371,19 +380,19 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/coins/%s/melt",
"coins/%s/melt",
pub_str);
}
ctx = TEAH_handle_to_context (mh->exchange);
key_state = TALER_EXCHANGE_get_keys (mh->exchange);
key_state = mh->keys;
mh->dki = TALER_EXCHANGE_get_denomination_key (key_state,
&mh->md.melted_coin.pub_key);
/* and now we can at last begin the actual request handling */
mh->url = TEAH_path_to_url (mh->exchange,
arg_str);
mh->url = TALER_url_join (mh->exchange_url,
arg_str,
NULL);
if (NULL == mh->url)
{
json_decref (melt_obj);
@ -403,7 +412,7 @@ start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
return GNUNET_SYSERR;
}
json_decref (melt_obj);
mh->job = GNUNET_CURL_job_add2 (ctx,
mh->job = GNUNET_CURL_job_add2 (mh->cctx,
eh,
mh->ctx.headers,
&handle_melt_finished,
@ -496,11 +505,14 @@ csr_cb (void *cls,
struct TALER_EXCHANGE_MeltHandle *
TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_EXCHANGE_RefreshData *rd,
TALER_EXCHANGE_MeltCallback melt_cb,
void *melt_cb_cls)
TALER_EXCHANGE_melt (
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_EXCHANGE_RefreshData *rd,
TALER_EXCHANGE_MeltCallback melt_cb,
void *melt_cb_cls)
{
struct TALER_EXCHANGE_NonceKey nks[GNUNET_NZL (rd->fresh_pks_len)];
unsigned int nks_off = 0;
@ -511,11 +523,10 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_break (0);
return NULL;
}
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
mh = GNUNET_new (struct TALER_EXCHANGE_MeltHandle);
mh->noreveal_index = TALER_CNC_KAPPA; /* invalid value */
mh->exchange = exchange;
mh->cctx = ctx;
mh->exchange_url = GNUNET_strdup (url);
mh->rd = rd;
mh->rms = *rms;
mh->melt_cb = melt_cb;
@ -545,9 +556,11 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
break;
}
}
mh->keys = TALER_EXCHANGE_keys_incref (keys);
if (0 != nks_off)
{
mh->csr = TALER_EXCHANGE_csr_melt (exchange,
mh->csr = TALER_EXCHANGE_csr_melt (ctx,
url,
rms,
nks_off,
nks,
@ -588,7 +601,9 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh)
TALER_EXCHANGE_free_melt_data_ (&mh->md); /* does not free 'md' itself */
GNUNET_free (mh->mbds);
GNUNET_free (mh->url);
GNUNET_free (mh->exchange_url);
TALER_curl_easy_post_finished (&mh->ctx);
TALER_EXCHANGE_keys_decref (mh->keys);
GNUNET_free (mh);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2022 Taler Systems SA
Copyright (C) 2022-2023 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
@ -73,15 +73,20 @@ struct TALER_EXCHANGE_PurseCreateDepositHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
*/
char *url;
/**
* The base URL of the exchange.
*/
char *exchange_url;
/**
* Context for #TEH_curl_easy_post(). Keeps the data that must
* persist for Curl to make the upload.
@ -170,10 +175,9 @@ handle_purse_create_deposit_finished (void *cls,
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
const struct TALER_EXCHANGE_Keys *keys;
const struct TALER_EXCHANGE_Keys *keys = pch->keys;
pch->job = NULL;
keys = TALER_EXCHANGE_get_keys (pch->exchange);
switch (response_code)
{
case 0:
@ -181,7 +185,6 @@ handle_purse_create_deposit_finished (void *cls,
break;
case MHD_HTTP_OK:
{
const struct TALER_EXCHANGE_Keys *key_state;
struct GNUNET_TIME_Timestamp etime;
struct TALER_Amount total_deposited;
struct TALER_ExchangeSignatureP exchange_sig;
@ -209,9 +212,8 @@ handle_purse_create_deposit_finished (void *cls,
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
key_state = TALER_EXCHANGE_get_keys (pch->exchange);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
TALER_EXCHANGE_test_signing_key (keys,
&exchange_pub))
{
GNUNET_break_op (0);
@ -387,7 +389,7 @@ handle_purse_create_deposit_finished (void *cls,
if (GNUNET_OK !=
TALER_EXCHANGE_check_purse_coin_conflict_ (
&pch->purse_pub,
pch->exchange->url,
pch->exchange_url,
j,
&h_denom_pub,
&phac,
@ -496,7 +498,9 @@ handle_purse_create_deposit_finished (void *cls,
struct TALER_EXCHANGE_PurseCreateDepositHandle *
TALER_EXCHANGE_purse_create_with_deposit (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_PurseContractPrivateKeyP *purse_priv,
const struct TALER_PurseMergePrivateKeyP *merge_priv,
const struct TALER_ContractDiffiePrivateP *contract_priv,
@ -508,16 +512,13 @@ TALER_EXCHANGE_purse_create_with_deposit (
void *cb_cls)
{
struct TALER_EXCHANGE_PurseCreateDepositHandle *pch;
struct GNUNET_CURL_Context *ctx;
json_t *create_obj;
json_t *deposit_arr;
CURL *eh;
char arg_str[sizeof (pch->purse_pub) * 2 + 32];
char *url;
uint32_t min_age = 0;
pch = GNUNET_new (struct TALER_EXCHANGE_PurseCreateDepositHandle);
pch->exchange = exchange;
pch->cb = cb;
pch->cb_cls = cb_cls;
{
@ -542,8 +543,6 @@ TALER_EXCHANGE_purse_create_with_deposit (
return NULL;
}
}
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
if (GNUNET_OK !=
TALER_JSON_contract_hash (contract_terms,
&pch->h_contract_terms))
@ -565,13 +564,14 @@ TALER_EXCHANGE_purse_create_with_deposit (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/purses/%s/create",
"purses/%s/create",
pub_str);
}
GNUNET_CRYPTO_eddsa_key_get_public (&merge_priv->eddsa_priv,
&pch->merge_pub.eddsa_pub);
pch->url = TEAH_path_to_url (exchange,
arg_str);
pch->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == pch->url)
{
GNUNET_break (0);
@ -583,8 +583,6 @@ TALER_EXCHANGE_purse_create_with_deposit (
struct Deposit);
deposit_arr = json_array ();
GNUNET_assert (NULL != deposit_arr);
url = TEAH_path_to_url (exchange,
"/");
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Signing with URL `%s'\n",
url);
@ -610,7 +608,6 @@ TALER_EXCHANGE_purse_create_with_deposit (
{
GNUNET_break (0);
json_decref (deposit_arr);
GNUNET_free (url);
GNUNET_free (pch);
return NULL;
}
@ -648,7 +645,6 @@ TALER_EXCHANGE_purse_create_with_deposit (
json_array_append_new (deposit_arr,
jdeposit));
}
GNUNET_free (url);
TALER_wallet_purse_create_sign (pch->purse_expiration,
&pch->h_contract_terms,
&pch->merge_pub,
@ -714,7 +710,8 @@ TALER_EXCHANGE_purse_create_with_deposit (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for purse create with deposit: `%s'\n",
pch->url);
ctx = TEAH_handle_to_context (exchange);
pch->keys = TALER_EXCHANGE_keys_incref (keys);
pch->exchange_url = GNUNET_strdup (url);
pch->job = GNUNET_CURL_job_add2 (ctx,
eh,
pch->ctx.headers,
@ -734,8 +731,10 @@ TALER_EXCHANGE_purse_create_with_deposit_cancel (
pch->job = NULL;
}
GNUNET_free (pch->econtract.econtract);
GNUNET_free (pch->exchange_url);
GNUNET_free (pch->url);
GNUNET_free (pch->deposits);
TALER_EXCHANGE_keys_decref (pch->keys);
TALER_curl_easy_post_finished (&pch->ctx);
GNUNET_free (pch);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2022 Taler Systems SA
Copyright (C) 2022-2023 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
@ -41,15 +41,20 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
*/
char *url;
/**
* The exchange base URL.
*/
char *exchange_url;
/**
* Context for #TEH_curl_easy_post(). Keeps the data that must
* persist for Curl to make the upload.
@ -157,7 +162,6 @@ handle_purse_create_with_merge_finished (void *cls,
break;
case MHD_HTTP_OK:
{
const struct TALER_EXCHANGE_Keys *key_state;
struct GNUNET_TIME_Timestamp etime;
struct TALER_Amount total_deposited;
struct TALER_ExchangeSignatureP exchange_sig;
@ -184,9 +188,8 @@ handle_purse_create_with_merge_finished (void *cls,
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
key_state = TALER_EXCHANGE_get_keys (pcm->exchange);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
TALER_EXCHANGE_test_signing_key (pcm->keys,
&exchange_pub))
{
GNUNET_break_op (0);
@ -253,7 +256,7 @@ handle_purse_create_with_merge_finished (void *cls,
&pcm->merge_sig,
&pcm->merge_pub,
&pcm->purse_pub,
pcm->exchange->url,
pcm->exchange_url,
j))
{
GNUNET_break_op (0);
@ -340,7 +343,9 @@ handle_purse_create_with_merge_finished (void *cls,
struct TALER_EXCHANGE_PurseCreateMergeHandle *
TALER_EXCHANGE_purse_create_with_merge (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_PurseContractPrivateKeyP *purse_priv,
const struct TALER_PurseMergePrivateKeyP *merge_priv,
@ -353,7 +358,6 @@ TALER_EXCHANGE_purse_create_with_merge (
void *cb_cls)
{
struct TALER_EXCHANGE_PurseCreateMergeHandle *pcm;
struct GNUNET_CURL_Context *ctx;
json_t *create_with_merge_obj;
CURL *eh;
char arg_str[sizeof (pcm->reserve_pub) * 2 + 32];
@ -362,7 +366,6 @@ TALER_EXCHANGE_purse_create_with_merge (
enum TALER_WalletAccountMergeFlags flags;
pcm = GNUNET_new (struct TALER_EXCHANGE_PurseCreateMergeHandle);
pcm->exchange = exchange;
pcm->cb = cb;
pcm->cb_cls = cb_cls;
if (GNUNET_OK !=
@ -409,7 +412,7 @@ TALER_EXCHANGE_purse_create_with_merge (
const struct TALER_EXCHANGE_GlobalFee *gf;
gf = TALER_EXCHANGE_get_global_fee (
TALER_EXCHANGE_get_keys (exchange),
keys,
GNUNET_TIME_timestamp_get ());
purse_fee = gf->fees.purse;
flags = TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE;
@ -422,8 +425,6 @@ TALER_EXCHANGE_purse_create_with_merge (
flags = TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA;
}
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
{
char pub_str[sizeof (pcm->reserve_pub) * 2];
char *end;
@ -436,11 +437,12 @@ TALER_EXCHANGE_purse_create_with_merge (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/reserves/%s/purse",
"reserves/%s/purse",
pub_str);
}
pcm->url = TEAH_path_to_url (exchange,
arg_str);
pcm->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == pcm->url)
{
GNUNET_break (0);
@ -457,7 +459,7 @@ TALER_EXCHANGE_purse_create_with_merge (
{
char *payto_uri;
payto_uri = TALER_reserve_make_payto (exchange->url,
payto_uri = TALER_reserve_make_payto (url,
&pcm->reserve_pub);
TALER_wallet_purse_merge_sign (payto_uri,
merge_timestamp,
@ -546,7 +548,8 @@ TALER_EXCHANGE_purse_create_with_merge (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for purse create_with_merge: `%s'\n",
pcm->url);
ctx = TEAH_handle_to_context (exchange);
pcm->keys = TALER_EXCHANGE_keys_incref (keys);
pcm->exchange_url = GNUNET_strdup (url);
pcm->job = GNUNET_CURL_job_add2 (ctx,
eh,
pcm->ctx.headers,
@ -566,7 +569,9 @@ TALER_EXCHANGE_purse_create_with_merge_cancel (
pcm->job = NULL;
}
GNUNET_free (pcm->url);
GNUNET_free (pcm->exchange_url);
TALER_curl_easy_post_finished (&pcm->ctx);
TALER_EXCHANGE_keys_decref (pcm->keys);
GNUNET_free (pcm->econtract.econtract);
GNUNET_free (pcm);
}

View File

@ -40,11 +40,6 @@
struct TALER_EXCHANGE_PurseDeleteHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -148,26 +143,23 @@ handle_purse_delete_finished (void *cls,
struct TALER_EXCHANGE_PurseDeleteHandle *
TALER_EXCHANGE_purse_delete (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_PurseContractPrivateKeyP *purse_priv,
TALER_EXCHANGE_PurseDeleteCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_PurseDeleteHandle *pdh;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
struct TALER_PurseContractPublicKeyP purse_pub;
struct TALER_PurseContractSignatureP purse_sig;
char arg_str[sizeof (purse_pub) * 2 + 32];
pdh = GNUNET_new (struct TALER_EXCHANGE_PurseDeleteHandle);
pdh->exchange = exchange;
pdh->cb = cb;
pdh->cb_cls = cb_cls;
GNUNET_CRYPTO_eddsa_key_get_public (&purse_priv->eddsa_priv,
&purse_pub.eddsa_pub);
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
{
char pub_str[sizeof (purse_pub) * 2];
char *end;
@ -179,11 +171,12 @@ TALER_EXCHANGE_purse_delete (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/purses/%s",
"purses/%s",
pub_str);
}
pdh->url = TEAH_path_to_url (exchange,
arg_str);
pdh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == pdh->url)
{
GNUNET_break (0);
@ -223,7 +216,6 @@ TALER_EXCHANGE_purse_delete (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for purse delete: `%s'\n",
pdh->url);
ctx = TEAH_handle_to_context (exchange);
pdh->job = GNUNET_CURL_job_add2 (ctx,
eh,
pdh->xhdr,

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2022 Taler Systems SA
Copyright (C) 2022-2023 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
@ -73,9 +73,9 @@ struct TALER_EXCHANGE_PurseDepositHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -144,10 +144,9 @@ handle_purse_deposit_finished (void *cls,
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
const struct TALER_EXCHANGE_Keys *keys;
const struct TALER_EXCHANGE_Keys *keys = pch->keys;
pch->job = NULL;
keys = TALER_EXCHANGE_get_keys (pch->exchange);
switch (response_code)
{
case 0:
@ -447,7 +446,9 @@ handle_purse_deposit_finished (void *cls,
struct TALER_EXCHANGE_PurseDepositHandle *
TALER_EXCHANGE_purse_deposit (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const char *purse_exchange_url,
const struct TALER_PurseContractPublicKeyP *purse_pub,
uint8_t min_age,
@ -457,7 +458,6 @@ TALER_EXCHANGE_purse_deposit (
void *cb_cls)
{
struct TALER_EXCHANGE_PurseDepositHandle *pch;
struct GNUNET_CURL_Context *ctx;
json_t *create_obj;
json_t *deposit_arr;
CURL *eh;
@ -470,11 +470,8 @@ TALER_EXCHANGE_purse_deposit (
GNUNET_break (0);
return NULL;
}
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
pch = GNUNET_new (struct TALER_EXCHANGE_PurseDepositHandle);
pch->purse_pub = *purse_pub;
pch->exchange = exchange;
pch->cb = cb;
pch->cb_cls = cb_cls;
{
@ -489,11 +486,12 @@ TALER_EXCHANGE_purse_deposit (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/purses/%s/deposit",
"purses/%s/deposit",
pub_str);
}
pch->url = TEAH_path_to_url (exchange,
arg_str);
pch->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == pch->url)
{
GNUNET_break (0);
@ -502,8 +500,7 @@ TALER_EXCHANGE_purse_deposit (
}
deposit_arr = json_array ();
GNUNET_assert (NULL != deposit_arr);
pch->base_url = TEAH_path_to_url (exchange,
"/");
pch->base_url = GNUNET_strdup (url);
pch->num_deposits = num_deposits;
pch->coins = GNUNET_new_array (num_deposits,
struct Coin);
@ -594,7 +591,7 @@ TALER_EXCHANGE_purse_deposit (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for purse deposit: `%s'\n",
pch->url);
ctx = TEAH_handle_to_context (exchange);
pch->keys = TALER_EXCHANGE_keys_incref (keys);
pch->job = GNUNET_CURL_job_add2 (ctx,
eh,
pch->ctx.headers,
@ -616,6 +613,7 @@ TALER_EXCHANGE_purse_deposit_cancel (
GNUNET_free (pch->base_url);
GNUNET_free (pch->url);
GNUNET_free (pch->coins);
TALER_EXCHANGE_keys_decref (pch->keys);
TALER_curl_easy_post_finished (&pch->ctx);
GNUNET_free (pch);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2022 Taler Systems SA
Copyright (C) 2022-2023 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
@ -41,9 +41,9 @@ struct TALER_EXCHANGE_AccountMergeHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -148,7 +148,6 @@ handle_purse_merge_finished (void *cls,
break;
case MHD_HTTP_OK:
{
const struct TALER_EXCHANGE_Keys *key_state;
struct TALER_Amount total_deposited;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
@ -173,9 +172,8 @@ handle_purse_merge_finished (void *cls,
dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
key_state = TALER_EXCHANGE_get_keys (pch->exchange);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
TALER_EXCHANGE_test_signing_key (pch->keys,
&dr.details.ok.exchange_pub))
{
GNUNET_break_op (0);
@ -302,7 +300,9 @@ handle_purse_merge_finished (void *cls,
struct TALER_EXCHANGE_AccountMergeHandle *
TALER_EXCHANGE_account_merge (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const char *reserve_exchange_url,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_PurseContractPublicKeyP *purse_pub,
@ -316,14 +316,12 @@ TALER_EXCHANGE_account_merge (
void *cb_cls)
{
struct TALER_EXCHANGE_AccountMergeHandle *pch;
struct GNUNET_CURL_Context *ctx;
json_t *merge_obj;
CURL *eh;
char arg_str[sizeof (pch->purse_pub) * 2 + 32];
char *reserve_url;
pch = GNUNET_new (struct TALER_EXCHANGE_AccountMergeHandle);
pch->exchange = exchange;
pch->merge_priv = *merge_priv;
pch->cb = cb;
pch->cb_cls = cb_cls;
@ -332,14 +330,12 @@ TALER_EXCHANGE_account_merge (
pch->purse_expiration = purse_expiration;
pch->purse_value_after_fees = *purse_value_after_fees;
if (NULL == reserve_exchange_url)
pch->provider_url = GNUNET_strdup (exchange->url);
pch->provider_url = GNUNET_strdup (url);
else
pch->provider_url = GNUNET_strdup (reserve_exchange_url);
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
&pch->reserve_pub.eddsa_pub);
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
{
char pub_str[sizeof (*purse_pub) * 2];
char *end;
@ -352,7 +348,7 @@ TALER_EXCHANGE_account_merge (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/purses/%s/merge",
"purses/%s/merge",
pub_str);
}
reserve_url = TALER_reserve_make_payto (pch->provider_url,
@ -364,8 +360,9 @@ TALER_EXCHANGE_account_merge (
GNUNET_free (pch);
return NULL;
}
pch->url = TEAH_path_to_url (exchange,
arg_str);
pch->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == pch->url)
{
GNUNET_break (0);
@ -426,7 +423,7 @@ TALER_EXCHANGE_account_merge (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for purse merge: `%s'\n",
pch->url);
ctx = TEAH_handle_to_context (exchange);
pch->keys = TALER_EXCHANGE_keys_incref (keys);
pch->job = GNUNET_CURL_job_add2 (ctx,
eh,
pch->ctx.headers,
@ -448,6 +445,7 @@ TALER_EXCHANGE_account_merge_cancel (
GNUNET_free (pch->url);
GNUNET_free (pch->provider_url);
TALER_curl_easy_post_finished (&pch->ctx);
TALER_EXCHANGE_keys_decref (pch->keys);
GNUNET_free (pch);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2022 Taler Systems SA
Copyright (C) 2022-2023 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
@ -39,9 +39,9 @@ struct TALER_EXCHANGE_PurseGetHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -117,7 +117,6 @@ handle_purse_get_finished (void *cls,
&exchange_sig),
GNUNET_JSON_spec_end ()
};
const struct TALER_EXCHANGE_Keys *key_state;
if (GNUNET_OK !=
GNUNET_JSON_parse (j,
@ -130,9 +129,8 @@ handle_purse_get_finished (void *cls,
break;
}
key_state = TALER_EXCHANGE_get_keys (pgh->exchange);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
TALER_EXCHANGE_test_signing_key (pgh->keys,
&exchange_pub))
{
GNUNET_break_op (0);
@ -207,7 +205,9 @@ handle_purse_get_finished (void *cls,
struct TALER_EXCHANGE_PurseGetHandle *
TALER_EXCHANGE_purse_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_PurseContractPublicKeyP *purse_pub,
struct GNUNET_TIME_Relative timeout,
bool wait_for_merge,
@ -218,14 +218,7 @@ TALER_EXCHANGE_purse_get (
CURL *eh;
char arg_str[sizeof (*purse_pub) * 2 + 64];
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
pgh = GNUNET_new (struct TALER_EXCHANGE_PurseGetHandle);
pgh->exchange = exchange;
pgh->cb = cb;
pgh->cb_cls = cb_cls;
{
@ -247,19 +240,20 @@ TALER_EXCHANGE_purse_get (
if (GNUNET_TIME_relative_is_zero (timeout))
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/purses/%s/%s",
"purses/%s/%s",
cpub_str,
wait_for_merge ? "merge" : "deposit");
else
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/purses/%s/%s?timeout_ms=%s",
"purses/%s/%s?timeout_ms=%s",
cpub_str,
wait_for_merge ? "merge" : "deposit",
timeout_str);
}
pgh->url = TEAH_path_to_url (exchange,
arg_str);
pgh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == pgh->url)
{
GNUNET_free (pgh);
@ -273,10 +267,11 @@ TALER_EXCHANGE_purse_get (
GNUNET_free (pgh);
return NULL;
}
pgh->job = GNUNET_CURL_job_add (TEAH_handle_to_context (exchange),
pgh->job = GNUNET_CURL_job_add (ctx,
eh,
&handle_purse_get_finished,
pgh);
pgh->keys = TALER_EXCHANGE_keys_incref (keys);
return pgh;
}
@ -291,6 +286,7 @@ TALER_EXCHANGE_purse_get_cancel (
pgh->job = NULL;
}
GNUNET_free (pgh->url);
TALER_EXCHANGE_keys_decref (pgh->keys);
GNUNET_free (pgh);
}

View File

@ -40,9 +40,9 @@ struct TALER_EXCHANGE_RecoupHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -143,10 +143,8 @@ handle_recoup_finished (void *cls,
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
const struct TALER_EXCHANGE_Keys *keys;
ph->job = NULL;
keys = TALER_EXCHANGE_get_keys (ph->exchange);
switch (response_code)
{
case 0:
@ -177,7 +175,7 @@ handle_recoup_finished (void *cls,
rr.hr.ec = TALER_JSON_get_error_code (j);
rr.hr.hint = TALER_JSON_get_error_hint (j);
if (GNUNET_OK !=
TALER_EXCHANGE_get_min_denomination_ (keys,
TALER_EXCHANGE_get_min_denomination_ (ph->keys,
&min_key))
{
GNUNET_break (0);
@ -187,7 +185,7 @@ handle_recoup_finished (void *cls,
}
if (GNUNET_OK !=
TALER_EXCHANGE_check_coin_conflict_ (
keys,
ph->keys,
j,
&ph->pk,
&ph->coin_pub,
@ -244,16 +242,18 @@ handle_recoup_finished (void *cls,
struct TALER_EXCHANGE_RecoupHandle *
TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_DenominationSignature *denom_sig,
const struct TALER_ExchangeWithdrawValues *exchange_vals,
const struct TALER_PlanchetMasterSecretP *ps,
TALER_EXCHANGE_RecoupResultCallback recoup_cb,
void *recoup_cb_cls)
TALER_EXCHANGE_recoup (
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_DenominationSignature *denom_sig,
const struct TALER_ExchangeWithdrawValues *exchange_vals,
const struct TALER_PlanchetMasterSecretP *ps,
TALER_EXCHANGE_RecoupResultCallback recoup_cb,
void *recoup_cb_cls)
{
struct TALER_EXCHANGE_RecoupHandle *ph;
struct GNUNET_CURL_Context *ctx;
struct TALER_DenominationHashP h_denom_pub;
json_t *recoup_obj;
CURL *eh;
@ -261,8 +261,6 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
struct TALER_CoinSpendPrivateKeyP coin_priv;
union TALER_DenominationBlindingKeyP bks;
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
ph = GNUNET_new (struct TALER_EXCHANGE_RecoupHandle);
TALER_planchet_setup_coin_priv (ps,
exchange_vals,
@ -319,19 +317,19 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/coins/%s/recoup",
"coins/%s/recoup",
pub_str);
}
ph->exchange = exchange;
ph->pk = *pk;
memset (&ph->pk.key,
0,
sizeof (ph->pk.key)); /* zero out, as lifetime cannot be warranted */
ph->cb = recoup_cb;
ph->cb_cls = recoup_cb_cls;
ph->url = TEAH_path_to_url (exchange,
arg_str);
ph->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == ph->url)
{
json_decref (recoup_obj);
@ -357,7 +355,7 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for recoup: `%s'\n",
ph->url);
ctx = TEAH_handle_to_context (exchange);
ph->keys = TALER_EXCHANGE_keys_incref (keys);
ph->job = GNUNET_CURL_job_add2 (ctx,
eh,
ph->ctx.headers,
@ -377,6 +375,7 @@ TALER_EXCHANGE_recoup_cancel (struct TALER_EXCHANGE_RecoupHandle *ph)
}
GNUNET_free (ph->url);
TALER_curl_easy_post_finished (&ph->ctx);
TALER_EXCHANGE_keys_decref (ph->keys);
GNUNET_free (ph);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2017-2022 Taler Systems SA
Copyright (C) 2017-2023 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
@ -40,9 +40,9 @@ struct TALER_EXCHANGE_RecoupRefreshHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -144,10 +144,8 @@ handle_recoup_refresh_finished (void *cls,
.hr.reply = j,
.hr.http_status = (unsigned int) response_code
};
const struct TALER_EXCHANGE_Keys *keys;
ph->job = NULL;
keys = TALER_EXCHANGE_get_keys (ph->exchange);
switch (response_code)
{
case 0:
@ -191,7 +189,7 @@ handle_recoup_refresh_finished (void *cls,
rrr.hr.ec = TALER_JSON_get_error_code (j);
rrr.hr.hint = TALER_JSON_get_error_hint (j);
if (GNUNET_OK !=
TALER_EXCHANGE_get_min_denomination_ (keys,
TALER_EXCHANGE_get_min_denomination_ (ph->keys,
&min_key))
{
GNUNET_break (0);
@ -201,7 +199,7 @@ handle_recoup_refresh_finished (void *cls,
}
if (GNUNET_OK !=
TALER_EXCHANGE_check_coin_conflict_ (
keys,
ph->keys,
j,
&ph->pk,
&ph->coin_pub,
@ -246,7 +244,9 @@ handle_recoup_refresh_finished (void *cls,
struct TALER_EXCHANGE_RecoupRefreshHandle *
TALER_EXCHANGE_recoup_refresh (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_DenominationSignature *denom_sig,
const struct TALER_ExchangeWithdrawValues *exchange_vals,
@ -257,7 +257,6 @@ TALER_EXCHANGE_recoup_refresh (
void *recoup_cb_cls)
{
struct TALER_EXCHANGE_RecoupRefreshHandle *ph;
struct GNUNET_CURL_Context *ctx;
struct TALER_DenominationHashP h_denom_pub;
json_t *recoup_obj;
CURL *eh;
@ -266,10 +265,7 @@ TALER_EXCHANGE_recoup_refresh (
union TALER_DenominationBlindingKeyP bks;
GNUNET_assert (NULL != recoup_cb);
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
ph = GNUNET_new (struct TALER_EXCHANGE_RecoupRefreshHandle);
ph->exchange = exchange;
ph->pk = *pk;
memset (&ph->pk.key,
0,
@ -333,12 +329,13 @@ TALER_EXCHANGE_recoup_refresh (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/coins/%s/recoup-refresh",
"coins/%s/recoup-refresh",
pub_str);
}
ph->url = TEAH_path_to_url (exchange,
arg_str);
ph->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == ph->url)
{
json_decref (recoup_obj);
@ -364,7 +361,7 @@ TALER_EXCHANGE_recoup_refresh (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for recoup-refresh: `%s'\n",
ph->url);
ctx = TEAH_handle_to_context (exchange);
ph->keys = TALER_EXCHANGE_keys_incref (keys);
ph->job = GNUNET_CURL_job_add2 (ctx,
eh,
ph->ctx.headers,
@ -385,6 +382,7 @@ TALER_EXCHANGE_recoup_refresh_cancel (
}
GNUNET_free (ph->url);
TALER_curl_easy_post_finished (&ph->ctx);
TALER_EXCHANGE_keys_decref (ph->keys);
GNUNET_free (ph);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2015-2022 Taler Systems SA
Copyright (C) 2015-2023 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
@ -39,11 +39,6 @@
struct TALER_EXCHANGE_RefreshesRevealHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -310,7 +305,8 @@ handle_refresh_reveal_finished (void *cls,
struct TALER_EXCHANGE_RefreshesRevealHandle *
TALER_EXCHANGE_refreshes_reveal (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_RefreshMasterSecretP *rms,
const struct TALER_EXCHANGE_RefreshData *rd,
unsigned int num_coins,
@ -327,7 +323,6 @@ TALER_EXCHANGE_refreshes_reveal (
json_t *link_sigs;
json_t *old_age_commitment = NULL;
CURL *eh;
struct GNUNET_CURL_Context *ctx;
struct MeltData md;
char arg_str[sizeof (struct TALER_RefreshCommitmentP) * 2 + 32];
bool send_rms = false;
@ -342,12 +337,6 @@ TALER_EXCHANGE_refreshes_reveal (
GNUNET_break (0);
return NULL;
}
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
if (GNUNET_OK !=
TALER_EXCHANGE_get_melt_data_ (rms,
rd,
@ -467,22 +456,22 @@ TALER_EXCHANGE_refreshes_reveal (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/refreshes/%s/reveal",
"refreshes/%s/reveal",
pub_str);
}
/* finally, we can actually issue the request */
rrh = GNUNET_new (struct TALER_EXCHANGE_RefreshesRevealHandle);
rrh->exchange = exchange;
rrh->noreveal_index = noreveal_index;
rrh->reveal_cb = reveal_cb;
rrh->reveal_cb_cls = reveal_cb_cls;
rrh->md = md;
rrh->alg_values = GNUNET_memdup (alg_values,
md.num_fresh_coins
* sizeof (struct
TALER_ExchangeWithdrawValues));
rrh->url = TEAH_path_to_url (rrh->exchange,
arg_str);
rrh->alg_values
= GNUNET_memdup (alg_values,
md.num_fresh_coins
* sizeof (struct TALER_ExchangeWithdrawValues));
rrh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == rrh->url)
{
json_decref (reveal_obj);
@ -510,7 +499,6 @@ TALER_EXCHANGE_refreshes_reveal (
return NULL;
}
json_decref (reveal_obj);
ctx = TEAH_handle_to_context (rrh->exchange);
rrh->job = GNUNET_CURL_job_add2 (ctx,
eh,
rrh->ctx.headers,

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
Copyright (C) 2014-2023 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
@ -39,9 +39,9 @@ struct TALER_EXCHANGE_RefundHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -117,7 +117,6 @@ verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh,
struct TALER_ExchangePublicKeyP *exchange_pub,
struct TALER_ExchangeSignatureP *exchange_sig)
{
const struct TALER_EXCHANGE_Keys *key_state;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
exchange_sig),
@ -134,9 +133,8 @@ verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
key_state = TALER_EXCHANGE_get_keys (rh->exchange);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
TALER_EXCHANGE_test_signing_key (rh->keys,
exchange_pub))
{
GNUNET_break_op (0);
@ -672,7 +670,9 @@ handle_refund_finished (void *cls,
struct TALER_EXCHANGE_RefundHandle *
TALER_EXCHANGE_refund (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_Amount *amount,
const struct TALER_PrivateContractHashP *h_contract_terms,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@ -684,13 +684,10 @@ TALER_EXCHANGE_refund (
struct TALER_MerchantPublicKeyP merchant_pub;
struct TALER_MerchantSignatureP merchant_sig;
struct TALER_EXCHANGE_RefundHandle *rh;
struct GNUNET_CURL_Context *ctx;
json_t *refund_obj;
CURL *eh;
char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange));
GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv,
&merchant_pub.eddsa_pub);
TALER_merchant_refund_sign (coin_pub,
@ -711,7 +708,7 @@ TALER_EXCHANGE_refund (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/coins/%s/refund",
"coins/%s/refund",
pub_str);
}
refund_obj = GNUNET_JSON_PACK (
@ -726,11 +723,11 @@ TALER_EXCHANGE_refund (
GNUNET_JSON_pack_data_auto ("merchant_sig",
&merchant_sig));
rh = GNUNET_new (struct TALER_EXCHANGE_RefundHandle);
rh->exchange = exchange;
rh->cb = cb;
rh->cb_cls = cb_cls;
rh->url = TEAH_path_to_url (exchange,
arg_str);
rh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == rh->url)
{
json_decref (refund_obj);
@ -761,7 +758,7 @@ TALER_EXCHANGE_refund (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"URL for refund: `%s'\n",
rh->url);
ctx = TEAH_handle_to_context (exchange);
rh->keys = TALER_EXCHANGE_keys_incref (keys);
rh->job = GNUNET_CURL_job_add2 (ctx,
eh,
rh->ctx.headers,
@ -781,6 +778,7 @@ TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund)
}
GNUNET_free (refund->url);
TALER_curl_easy_post_finished (&refund->ctx);
TALER_EXCHANGE_keys_decref (refund->keys);
GNUNET_free (refund);
}

View File

@ -38,11 +38,6 @@
struct TALER_EXCHANGE_ReservesAttestHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -131,6 +126,8 @@ handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh,
GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
/* FIXME: validate exchange_pub is actually
a good exchange signing key */
rsh->cb (rsh->cb_cls,
&rs);
rsh->cb = NULL;
@ -228,7 +225,8 @@ handle_reserves_attest_finished (void *cls,
struct TALER_EXCHANGE_ReservesAttestHandle *
TALER_EXCHANGE_reserves_attest (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ReservePrivateKeyP *reserve_priv,
unsigned int attributes_length,
const char *const*attributes,
@ -236,7 +234,6 @@ TALER_EXCHANGE_reserves_attest (
void *cb_cls)
{
struct TALER_EXCHANGE_ReservesAttestHandle *rsh;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
struct TALER_ReserveSignatureP reserve_sig;
@ -248,12 +245,6 @@ TALER_EXCHANGE_reserves_attest (
GNUNET_break (0);
return NULL;
}
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
details = json_array ();
GNUNET_assert (NULL != details);
for (unsigned int i = 0; i<attributes_length; i++)
@ -263,7 +254,6 @@ TALER_EXCHANGE_reserves_attest (
json_string (attributes[i])));
}
rsh = GNUNET_new (struct TALER_EXCHANGE_ReservesAttestHandle);
rsh->exchange = exchange;
rsh->cb = cb;
rsh->cb_cls = cb_cls;
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
@ -280,11 +270,12 @@ TALER_EXCHANGE_reserves_attest (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/reserves-attest/%s",
"reserves-attest/%s",
pub_str);
}
rsh->url = TEAH_path_to_url (exchange,
arg_str);
rsh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == rsh->url)
{
json_decref (details);
@ -328,7 +319,6 @@ TALER_EXCHANGE_reserves_attest (
}
json_decref (attest_obj);
}
ctx = TEAH_handle_to_context (exchange);
rsh->job = GNUNET_CURL_job_add2 (ctx,
eh,
rsh->post_ctx.headers,

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
Copyright (C) 2014-2023 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
@ -38,11 +38,6 @@
struct TALER_EXCHANGE_ReservesCloseHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -269,26 +264,19 @@ handle_reserves_close_finished (void *cls,
struct TALER_EXCHANGE_ReservesCloseHandle *
TALER_EXCHANGE_reserves_close (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const char *target_payto_uri,
TALER_EXCHANGE_ReservesCloseCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_ReservesCloseHandle *rch;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
struct TALER_PaytoHashP h_payto;
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
rch = GNUNET_new (struct TALER_EXCHANGE_ReservesCloseHandle);
rch->exchange = exchange;
rch->cb = cb;
rch->cb_cls = cb_cls;
rch->ts = GNUNET_TIME_timestamp_get ();
@ -306,11 +294,12 @@ TALER_EXCHANGE_reserves_close (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/reserves/%s/close",
"reserves/%s/close",
pub_str);
}
rch->url = TEAH_path_to_url (exchange,
arg_str);
rch->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == rch->url)
{
GNUNET_free (rch);
@ -357,7 +346,6 @@ TALER_EXCHANGE_reserves_close (
}
json_decref (close_obj);
}
ctx = TEAH_handle_to_context (exchange);
rch->job = GNUNET_CURL_job_add2 (ctx,
eh,
rch->post_ctx.headers,

View File

@ -38,11 +38,6 @@
struct TALER_EXCHANGE_ReservesGetHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -186,23 +181,17 @@ handle_reserves_get_finished (void *cls,
struct TALER_EXCHANGE_ReservesGetHandle *
TALER_EXCHANGE_reserves_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ReservePublicKeyP *reserve_pub,
struct GNUNET_TIME_Relative timeout,
TALER_EXCHANGE_ReservesGetCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_ReservesGetHandle *rgh;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 16 + 32];
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
{
char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2];
char *end;
@ -223,22 +212,22 @@ TALER_EXCHANGE_reserves_get (
if (GNUNET_TIME_relative_is_zero (timeout))
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/reserves/%s",
"reserves/%s",
pub_str);
else
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/reserves/%s?timeout_ms=%s",
"reserves/%s?timeout_ms=%s",
pub_str,
timeout_str);
}
rgh = GNUNET_new (struct TALER_EXCHANGE_ReservesGetHandle);
rgh->exchange = exchange;
rgh->cb = cb;
rgh->cb_cls = cb_cls;
rgh->reserve_pub = *reserve_pub;
rgh->url = TEAH_path_to_url (exchange,
arg_str);
rgh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == rgh->url)
{
GNUNET_free (rgh);
@ -252,7 +241,6 @@ TALER_EXCHANGE_reserves_get (
GNUNET_free (rgh);
return NULL;
}
ctx = TEAH_handle_to_context (exchange);
rgh->job = GNUNET_CURL_job_add (ctx,
eh,
&handle_reserves_get_finished,

View File

@ -38,11 +38,6 @@
struct TALER_EXCHANGE_ReservesGetAttestHandle
{
/**
* The connection to exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* The url for this request.
*/
@ -211,22 +206,16 @@ handle_reserves_get_attestable_finished (void *cls,
struct TALER_EXCHANGE_ReservesGetAttestHandle *
TALER_EXCHANGE_reserves_get_attestable (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_EXCHANGE_ReservesGetAttestCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
{
char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2];
char *end;
@ -239,16 +228,16 @@ TALER_EXCHANGE_reserves_get_attestable (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/reserves-attest/%s",
"reserves-attest/%s",
pub_str);
}
rgah = GNUNET_new (struct TALER_EXCHANGE_ReservesGetAttestHandle);
rgah->exchange = exchange;
rgah->cb = cb;
rgah->cb_cls = cb_cls;
rgah->reserve_pub = *reserve_pub;
rgah->url = TEAH_path_to_url (exchange,
arg_str);
rgah->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == rgah->url)
{
GNUNET_free (rgah);
@ -262,7 +251,6 @@ TALER_EXCHANGE_reserves_get_attestable (
GNUNET_free (rgah);
return NULL;
}
ctx = TEAH_handle_to_context (exchange);
rgah->job = GNUNET_CURL_job_add (ctx,
eh,
&handle_reserves_get_attestable_finished,

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
Copyright (C) 2014-2023 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
@ -39,9 +39,9 @@ struct TALER_EXCHANGE_ReservesHistoryHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -131,7 +131,7 @@ handle_reserves_history_ok (struct TALER_EXCHANGE_ReservesHistoryHandle *rsh,
rhistory = GNUNET_new_array (len,
struct TALER_EXCHANGE_ReserveHistoryEntry);
if (GNUNET_OK !=
TALER_EXCHANGE_parse_reserve_history (rsh->exchange,
TALER_EXCHANGE_parse_reserve_history (rsh->keys,
history,
&rsh->reserve_pub,
rs.details.ok.balance.currency,
@ -250,26 +250,19 @@ handle_reserves_history_finished (void *cls,
struct TALER_EXCHANGE_ReservesHistoryHandle *
TALER_EXCHANGE_reserves_history (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv,
TALER_EXCHANGE_ReservesHistoryCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_ReservesHistoryHandle *rsh;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
const struct TALER_EXCHANGE_Keys *keys;
const struct TALER_EXCHANGE_GlobalFee *gf;
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
rsh = GNUNET_new (struct TALER_EXCHANGE_ReservesHistoryHandle);
rsh->exchange = exchange;
rsh->cb = cb;
rsh->cb_cls = cb_cls;
rsh->ts = GNUNET_TIME_timestamp_get ();
@ -287,11 +280,12 @@ TALER_EXCHANGE_reserves_history (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/reserves/%s/history",
"reserves/%s/history",
pub_str);
}
rsh->url = TEAH_path_to_url (exchange,
arg_str);
rsh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == rsh->url)
{
GNUNET_free (rsh);
@ -305,15 +299,6 @@ TALER_EXCHANGE_reserves_history (
GNUNET_free (rsh);
return NULL;
}
keys = TALER_EXCHANGE_get_keys (exchange);
if (NULL == keys)
{
GNUNET_break (0);
curl_easy_cleanup (eh);
GNUNET_free (rsh->url);
GNUNET_free (rsh);
return NULL;
}
gf = TALER_EXCHANGE_get_global_fee (keys,
rsh->ts);
if (NULL == gf)
@ -349,7 +334,7 @@ TALER_EXCHANGE_reserves_history (
}
json_decref (history_obj);
}
ctx = TEAH_handle_to_context (exchange);
rsh->keys = TALER_EXCHANGE_keys_incref (keys);
rsh->job = GNUNET_CURL_job_add2 (ctx,
eh,
rsh->post_ctx.headers,
@ -370,6 +355,7 @@ TALER_EXCHANGE_reserves_history_cancel (
}
TALER_curl_easy_post_finished (&rsh->post_ctx);
GNUNET_free (rsh->url);
TALER_EXCHANGE_keys_decref (rsh->keys);
GNUNET_free (rsh);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
Copyright (C) 2014-2023 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
@ -67,9 +67,9 @@ struct TALER_EXCHANGE_ReservesOpenHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -321,7 +321,6 @@ handle_reserves_open_finished (void *cls,
break;
case MHD_HTTP_CONFLICT:
{
const struct TALER_EXCHANGE_Keys *keys;
const struct CoinData *cd = NULL;
struct TALER_CoinSpendPublicKeyP coin_pub;
const struct TALER_EXCHANGE_DenomPublicKey *dk;
@ -331,8 +330,6 @@ handle_reserves_open_finished (void *cls,
GNUNET_JSON_spec_end ()
};
keys = TALER_EXCHANGE_get_keys (roh->exchange);
GNUNET_assert (NULL != keys);
if (GNUNET_OK !=
GNUNET_JSON_parse (j,
spec,
@ -362,7 +359,7 @@ handle_reserves_open_finished (void *cls,
rs.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
dk = TALER_EXCHANGE_get_denomination_key_by_hash (keys,
dk = TALER_EXCHANGE_get_denomination_key_by_hash (roh->keys,
&cd->h_denom_pub);
if (NULL == dk)
{
@ -372,7 +369,7 @@ handle_reserves_open_finished (void *cls,
break;
}
if (GNUNET_OK !=
TALER_EXCHANGE_check_coin_conflict_ (keys,
TALER_EXCHANGE_check_coin_conflict_ (roh->keys,
j,
dk,
&coin_pub,
@ -427,7 +424,9 @@ handle_reserves_open_finished (void *cls,
struct TALER_EXCHANGE_ReservesOpenHandle *
TALER_EXCHANGE_reserves_open (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_Amount *reserve_contribution,
unsigned int coin_payments_length,
@ -438,20 +437,11 @@ TALER_EXCHANGE_reserves_open (
void *cb_cls)
{
struct TALER_EXCHANGE_ReservesOpenHandle *roh;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
const struct TALER_EXCHANGE_Keys *keys;
json_t *cpa;
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
roh = GNUNET_new (struct TALER_EXCHANGE_ReservesOpenHandle);
roh->exchange = exchange;
roh->cb = cb;
roh->cb_cls = cb_cls;
roh->ts = GNUNET_TIME_timestamp_get ();
@ -469,11 +459,12 @@ TALER_EXCHANGE_reserves_open (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/reserves/%s/open",
"reserves/%s/open",
pub_str);
}
roh->url = TEAH_path_to_url (exchange,
arg_str);
roh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == roh->url)
{
GNUNET_free (roh);
@ -487,15 +478,6 @@ TALER_EXCHANGE_reserves_open (
GNUNET_free (roh);
return NULL;
}
keys = TALER_EXCHANGE_get_keys (exchange);
if (NULL == keys)
{
GNUNET_break (0);
curl_easy_cleanup (eh);
GNUNET_free (roh->url);
GNUNET_free (roh);
return NULL;
}
TALER_wallet_reserve_open_sign (reserve_contribution,
roh->ts,
expiration_time,
@ -578,7 +560,7 @@ TALER_EXCHANGE_reserves_open (
}
json_decref (open_obj);
}
ctx = TEAH_handle_to_context (exchange);
roh->keys = TALER_EXCHANGE_keys_incref (keys);
roh->job = GNUNET_CURL_job_add2 (ctx,
eh,
roh->post_ctx.headers,
@ -600,6 +582,7 @@ TALER_EXCHANGE_reserves_open_cancel (
TALER_curl_easy_post_finished (&roh->post_ctx);
GNUNET_free (roh->coins);
GNUNET_free (roh->url);
TALER_EXCHANGE_keys_decref (roh->keys);
GNUNET_free (roh);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2022 Taler Systems SA
Copyright (C) 2014-2023 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
@ -39,9 +39,9 @@ struct TALER_EXCHANGE_ReservesStatusHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -119,7 +119,7 @@ handle_reserves_status_ok (struct TALER_EXCHANGE_ReservesStatusHandle *rsh,
rhistory = GNUNET_new_array (len,
struct TALER_EXCHANGE_ReserveHistoryEntry);
if (GNUNET_OK !=
TALER_EXCHANGE_parse_reserve_history (rsh->exchange,
TALER_EXCHANGE_parse_reserve_history (rsh->keys,
history,
&rsh->reserve_pub,
rs.details.ok.balance.currency,
@ -233,27 +233,21 @@ handle_reserves_status_finished (void *cls,
struct TALER_EXCHANGE_ReservesStatusHandle *
TALER_EXCHANGE_reserves_status (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_ReservePrivateKeyP *reserve_priv,
TALER_EXCHANGE_ReservesStatusCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_ReservesStatusHandle *rsh;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
struct TALER_ReserveSignatureP reserve_sig;
struct GNUNET_TIME_Timestamp ts
= GNUNET_TIME_timestamp_get ();
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
rsh = GNUNET_new (struct TALER_EXCHANGE_ReservesStatusHandle);
rsh->exchange = exchange;
rsh->cb = cb;
rsh->cb_cls = cb_cls;
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
@ -270,11 +264,12 @@ TALER_EXCHANGE_reserves_status (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/reserves/%s/status",
"reserves/%s/status",
pub_str);
}
rsh->url = TEAH_path_to_url (exchange,
arg_str);
rsh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == rsh->url)
{
GNUNET_free (rsh);
@ -312,7 +307,7 @@ TALER_EXCHANGE_reserves_status (
}
json_decref (status_obj);
}
ctx = TEAH_handle_to_context (exchange);
rsh->keys = TALER_EXCHANGE_keys_incref (keys);
rsh->job = GNUNET_CURL_job_add2 (ctx,
eh,
rsh->post_ctx.headers,
@ -333,6 +328,7 @@ TALER_EXCHANGE_reserves_status_cancel (
}
TALER_curl_easy_post_finished (&rsh->post_ctx);
GNUNET_free (rsh->url);
TALER_EXCHANGE_keys_decref (rsh->keys);
GNUNET_free (rsh);
}

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2014-2021 Taler Systems SA
Copyright (C) 2014-2023 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
@ -38,9 +38,9 @@ struct TALER_EXCHANGE_TransfersGetHandle
{
/**
* The connection to exchange this request handle will use
* The keys of the exchange this request handle will use
*/
struct TALER_EXCHANGE_Handle *exchange;
struct TALER_EXCHANGE_Keys *keys;
/**
* The url for this request.
@ -130,7 +130,7 @@ check_transfers_get_response_ok (
}
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (
TALER_EXCHANGE_get_keys (wdh->exchange),
wdh->keys,
&td->exchange_pub))
{
GNUNET_break_op (0);
@ -320,25 +320,18 @@ handle_transfers_get_finished (void *cls,
struct TALER_EXCHANGE_TransfersGetHandle *
TALER_EXCHANGE_transfers_get (
struct TALER_EXCHANGE_Handle *exchange,
struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
const struct TALER_WireTransferIdentifierRawP *wtid,
TALER_EXCHANGE_TransfersGetCallback cb,
void *cb_cls)
{
struct TALER_EXCHANGE_TransfersGetHandle *wdh;
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[sizeof (struct TALER_WireTransferIdentifierRawP) * 2 + 32];
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
wdh = GNUNET_new (struct TALER_EXCHANGE_TransfersGetHandle);
wdh->exchange = exchange;
wdh->cb = cb;
wdh->cb_cls = cb_cls;
@ -354,11 +347,12 @@ TALER_EXCHANGE_transfers_get (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"/transfers/%s",
"transfers/%s",
wtid_str);
}
wdh->url = TEAH_path_to_url (wdh->exchange,
arg_str);
wdh->url = TALER_url_join (url,
arg_str,
NULL);
if (NULL == wdh->url)
{
GNUNET_free (wdh);
@ -372,7 +366,7 @@ TALER_EXCHANGE_transfers_get (
GNUNET_free (wdh);
return NULL;
}
ctx = TEAH_handle_to_context (exchange);
wdh->keys = TALER_EXCHANGE_keys_incref (keys);
wdh->job = GNUNET_CURL_job_add_with_ct_json (ctx,
eh,
&handle_transfers_get_finished,
@ -397,6 +391,7 @@ TALER_EXCHANGE_transfers_get_cancel (
wdh->job = NULL;
}
GNUNET_free (wdh->url);
TALER_EXCHANGE_keys_decref (wdh->keys);
GNUNET_free (wdh);
}

View File

@ -192,7 +192,8 @@ reserve_withdraw_payment_required (
}
if (GNUNET_OK !=
TALER_EXCHANGE_parse_reserve_history (wh->exchange,
TALER_EXCHANGE_parse_reserve_history (TALER_EXCHANGE_get_keys (
wh->exchange),
history,
&wh->reserve_pub,
balance.currency,

View File

@ -29,19 +29,21 @@ set -eu
# Exit, with status code "skip" (no 'real' failure)
function exit_skip() {
echo " SKIP: " "$@"
echo " SKIP: " "$@" >&2
exit 77
}
# Exit, with error message (hard failure)
function exit_fail() {
echo " FAIL: " "$@"
echo " FAIL: " "$@" >&2
exit 1
}
# Cleanup to run whenever we exit
function cleanup()
{
echo "Taler unified setup terminating!" >&2
for n in $(jobs -p)
do
kill $n 2> /dev/null || true
@ -53,6 +55,7 @@ function cleanup()
# Install cleanup handler (except for kill -9)
trap cleanup EXIT
WAIT_FOR_SIGNAL=0
START_AUDITOR=0
START_BACKUP=0
START_EXCHANGE=0
@ -71,7 +74,7 @@ LOGLEVEL="DEBUG"
DEFAULT_SLEEP="0.2"
# Parse command-line options
while getopts ':abc:d:efghl:mnr:stu:vw' OPTION; do
while getopts ':abc:d:efghl:mnr:stu:vwW' OPTION; do
case "$OPTION" in
a)
START_AUDITOR="1"
@ -82,7 +85,7 @@ while getopts ':abc:d:efghl:mnr:stu:vw' OPTION; do
c)
CONF_ORIG="$OPTARG"
;;
c)
d)
WIRE_DOMAIN="$OPTARG"
;;
e)
@ -142,6 +145,9 @@ while getopts ':abc:d:efghl:mnr:stu:vw' OPTION; do
w)
START_WIREWATCH="1"
;;
W)
WAIT_FOR_SIGNAL="1"
;;
?)
exit_fail "Unrecognized command line option"
;;
@ -201,22 +207,40 @@ register_sandbox_account() {
demobank \
delete \
--bank-account "$1" &> /dev/null || true
libeufin-cli sandbox \
demobank \
register --name "$3"
MAYBE_IBAN="${4:-}"
if test -n "$MAYBE_IBAN"; then
libeufin-cli sandbox \
demobank \
register --name "$3" --iban "$MAYBE_IBAN"
else
libeufin-cli sandbox \
demobank \
register --name "$3"
fi
unset LIBEUFIN_SANDBOX_USERNAME
unset LIBEUFIN_SANDBOX_PASSWORD
}
BANK_PORT=$(taler-config -c "$CONF" -s "BANK" -o "HTTP_PORT")
if [ "1" = "$START_NEXUS" ]
if [[ "1" = "$START_NEXUS" || "1" = "$START_FAKEBANK" ]]
then
NEXUS_PORT="$BANK_PORT"
SANDBOX_PORT="1$BANK_PORT"
BANK_PORT=$(taler-config -c "$CONF" -s "BANK" -o "HTTP_PORT")
if [ "1" = "$START_NEXUS" ]
then
NEXUS_PORT="$BANK_PORT"
SANDBOX_PORT="1$BANK_PORT"
else
NEXUS_PORT="0"
SANDBOX_PORT="1$BANK_PORT"
fi
else
NEXUS_PORT="0"
SANDBOX_PORT="1$BANK_PORT"
if [ "1" = "$START_SANDBOX" ]
then
BANK_PORT=$(taler-config -c "$CONF" -s "BANK" -o "HTTP_PORT")
SANDBOX_PORT="$BANK_PORT"
fi
fi
if [ "1" = "$START_SANDBOX" ]
@ -256,7 +280,11 @@ then
fi
echo "OK"
echo -n "Register Sandbox users ..."
register_sandbox_account fortytwo x "Forty Two"
# The specified IBAN and name must match the ones hard-coded into
# the C helper for the add-incoming call. Without this value,
# Sandbox won't find the target account to debit along a /add-incoming
# call.
register_sandbox_account fortytwo x "User42" FR7630006000011234567890189
register_sandbox_account fortythree x "Forty Three"
register_sandbox_account exchange x "Exchange Company"
register_sandbox_account tor x "Tor Project"
@ -610,7 +638,7 @@ then
if [ "1" != "$OK" ]
then
cat "$LAST_RESPONSE"
exit_skip "Failed to setup exchange keys, check secmod logs"
exit_fail "Failed to setup exchange keys, check secmod logs"
fi
rm "$LAST_RESPONSE"
echo " OK"
@ -662,7 +690,7 @@ then
if [ "1" != "$OK" ]
then
cat "$LAST_RESPONSE"
exit_skip " Failed to setup keys"
exit_fail " Failed to setup keys"
fi
rm "$LAST_RESPONSE"
echo " OK"
@ -681,7 +709,17 @@ fi
# Signal caller that we are ready.
echo "<<READY>>"
# Wait until caller stops us.
read
if [ "1" = "$WAIT_FOR_SIGNAL" ]
then
while true
do
sleep 0.1
done
else
# Wait until caller stops us.
read
fi
echo "Taler unified setup terminating!" >&2
exit 0

View File

@ -41,7 +41,7 @@
*/
#define CONFIG_FILE "test_auditor_api-rsa.conf"
static struct TALER_AUDITOR_Handle *ah;
static struct TALER_AUDITOR_GetConfigHandle *ah;
static struct GNUNET_CURL_Context *ctx;
@ -62,7 +62,11 @@ do_shutdown (void *cls)
GNUNET_SCHEDULER_cancel (tt);
tt = NULL;
}
TALER_AUDITOR_disconnect (ah);
if (NULL != ah)
{
TALER_AUDITOR_get_config_cancel (ah);
ah = NULL;
}
GNUNET_CURL_fini (ctx);
GNUNET_CURL_gnunet_rc_destroy (rc);
}
@ -82,20 +86,16 @@ do_timeout (void *cls)
* Function called with information about the auditor.
*
* @param cls closure
* @param hr http response details
* @param vi basic information about the auditor
* @param compat protocol compatibility information
* @param vr response details
*/
static void
version_cb (void *cls,
const struct TALER_AUDITOR_HttpResponse *hr,
const struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility compat)
const struct TALER_AUDITOR_ConfigResponse *vr)
{
(void) cls;
(void) hr;
if ( (NULL != vi) &&
(TALER_AUDITOR_VC_MATCH == compat) )
ah = NULL;
if ( (MHD_HTTP_OK == vr->hr.http_status) &&
(TALER_AUDITOR_VC_MATCH == vr->details.ok.compat) )
global_ret = 0;
else
global_ret = 2;
@ -118,10 +118,10 @@ run (void *cls)
ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
&rc);
rc = GNUNET_CURL_gnunet_rc_create (ctx);
ah = TALER_AUDITOR_connect (ctx,
auditor_url,
&version_cb,
NULL);
ah = TALER_AUDITOR_get_config (ctx,
auditor_url,
&version_cb,
NULL);
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
NULL);
tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,

View File

@ -142,8 +142,8 @@ run (void *cls,
"fetch-transactions-at-nexus",
"exchange", /* from taler-nexus-prepare */
"x", /* from taler-nexus-prepare */
"http://localhost:5001",
"my-bank-account") /* from taler-nexus-prepare */
"http://localhost:8082",
"exchange-nexus") /* from taler-nexus-prepare */
: TALER_TESTING_cmd_sleep ("nop",
0),
TALER_TESTING_cmd_bank_debits ("history-2b",

View File

@ -11,7 +11,7 @@ CURRENCY_ROUND_UNIT = EUR:0.01
[auditor]
BASE_URL = "http://localhost:8083/"
PORT = 8083
PUBLIC_KEY = SA7JVMCW3MMN7SYAWJ9AB0BGJDX6MP3PNN2JWQ3T8233MDSQC7Z0
PUBLIC_KEY = T0XJ9QZ59YDN7QG3RE40SB2HY7W0ASR1EKF4WZDGZ1G159RSQC80
TINY_AMOUNT = EUR:0.01
[auditordb-postgres]

View File

@ -0,0 +1 @@
<EFBFBD>G,U<><55><EFBFBD>{<7B>~#r<>-<11><>H<11> <0B><17><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2018, 2021 Taler Systems SA
Copyright (C) 2018-2023 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
@ -132,13 +132,15 @@ do_retry (void *cls)
* to check if the response code is acceptable.
*
* @param cls closure.
* @param hr HTTP response details
* @param dcr response details
*/
static void
deposit_confirmation_cb (void *cls,
const struct TALER_AUDITOR_HttpResponse *hr)
deposit_confirmation_cb (
void *cls,
const struct TALER_AUDITOR_DepositConfirmationResponse *dcr)
{
struct DepositConfirmationState *dcs = cls;
const struct TALER_AUDITOR_HttpResponse *hr = &dcr->hr;
dcs->dc = NULL;
if (dcs->expected_response_code != hr->http_status)
@ -208,7 +210,7 @@ deposit_confirmation_run (void *cls,
const struct TALER_CoinSpendPrivateKeyP *coin_priv;
const struct TALER_EXCHANGE_Keys *keys;
const struct TALER_EXCHANGE_SigningPublicKey *spk;
struct TALER_AUDITOR_Handle *auditor;
const char *auditor_url;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
@ -229,9 +231,14 @@ deposit_confirmation_run (void *cls,
TALER_TESTING_interpreter_fail (is);
return;
}
GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_auditor (auditor_cmd,
&auditor));
if (GNUNET_OK !=
TALER_TESTING_get_trait_auditor_url (auditor_cmd,
&auditor_url))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
}
deposit_cmd
= TALER_TESTING_interpreter_lookup_command (is,
@ -317,25 +324,27 @@ deposit_confirmation_run (void *cls,
if (GNUNET_TIME_absolute_is_zero (refund_deadline.abs_time))
refund_deadline = timestamp;
}
dcs->dc = TALER_AUDITOR_deposit_confirmation (auditor,
&h_wire,
&no_h_policy,
&h_contract_terms,
*exchange_timestamp,
*wire_deadline,
refund_deadline,
&amount_without_fee,
&coin_pub,
&merchant_pub,
exchange_pub,
exchange_sig,
&keys->master_pub,
spk->valid_from,
spk->valid_until,
spk->valid_legal,
&spk->master_sig,
&deposit_confirmation_cb,
dcs);
dcs->dc = TALER_AUDITOR_deposit_confirmation (
TALER_TESTING_interpreter_get_context (is),
auditor_url,
&h_wire,
&no_h_policy,
&h_contract_terms,
*exchange_timestamp,
*wire_deadline,
refund_deadline,
&amount_without_fee,
&coin_pub,
&merchant_pub,
exchange_pub,
exchange_sig,
&keys->master_pub,
spk->valid_from,
spk->valid_until,
spk->valid_legal,
&spk->master_sig,
&deposit_confirmation_cb,
dcs);
if (NULL == dcs->dc)
{

View File

@ -1,6 +1,6 @@
/*
This file is part of TALER
Copyright (C) 2018 Taler Systems SA
Copyright (C) 2018-2023 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
@ -127,11 +127,10 @@ do_retry (void *cls)
*/
static void
exchanges_cb (void *cls,
const struct TALER_AUDITOR_HttpResponse *hr,
unsigned int num_exchanges,
const struct TALER_AUDITOR_ExchangeInfo *ei)
const struct TALER_AUDITOR_ListExchangesResponse *ler)
{
struct ExchangesState *es = cls;
const struct TALER_AUDITOR_HttpResponse *hr = &ler->hr;
es->leh = NULL;
if (es->expected_response_code != hr->http_status)
@ -164,24 +163,30 @@ exchanges_cb (void *cls,
hr->http_status);
return;
}
if (MHD_HTTP_OK != hr->http_status)
{
TALER_TESTING_interpreter_next (es->is);
return;
}
if (NULL != es->exchange_url)
{
unsigned int found = GNUNET_NO;
bool found = false;
unsigned int num_exchanges = ler->details.ok.num_exchanges;
const struct TALER_AUDITOR_ExchangeInfo *ei = ler->details.ok.ei;
for (unsigned int i = 0;
i<num_exchanges;
i++)
if (0 == strcmp (es->exchange_url,
ei[i].exchange_url))
found = GNUNET_YES;
if (GNUNET_NO == found)
found = true;
if (! found)
{
TALER_LOG_ERROR ("Exchange '%s' doesn't exist at this auditor\n",
es->exchange_url);
TALER_TESTING_interpreter_fail (es->is);
return;
}
TALER_LOG_DEBUG ("Exchange '%s' exists at this auditor!\n",
es->exchange_url);
}
@ -203,7 +208,7 @@ exchanges_run (void *cls,
{
struct ExchangesState *es = cls;
const struct TALER_TESTING_Command *auditor_cmd;
struct TALER_AUDITOR_Handle *auditor;
const char *auditor_url;
(void) cmd;
auditor_cmd = TALER_TESTING_interpreter_get_command (is,
@ -214,15 +219,20 @@ exchanges_run (void *cls,
TALER_TESTING_interpreter_fail (is);
return;
}
GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_auditor (auditor_cmd,
&auditor));
if (GNUNET_OK !=
TALER_TESTING_get_trait_auditor_url (auditor_cmd,
&auditor_url))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
es->is = is;
es->leh = TALER_AUDITOR_list_exchanges (auditor,
&exchanges_cb,
es);
es->leh = TALER_AUDITOR_list_exchanges (
TALER_TESTING_interpreter_get_context (is),
auditor_url,
&exchanges_cb,
es);
if (NULL == es->leh)
{
GNUNET_break (0);
@ -287,14 +297,6 @@ exchanges_traits (void *cls,
}
/**
* Create a "list exchanges" command.
*
* @param label command label.
* @param auditor auditor connection.
* @param expected_response_code expected HTTP response code.
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_exchanges (const char *label,
unsigned int expected_response_code)
@ -318,16 +320,6 @@ TALER_TESTING_cmd_exchanges (const char *label,
}
/**
* Create a "list exchanges" command and check whether
* a particular exchange belongs to the returned bundle.
*
* @param label command label.
* @param expected_response_code expected HTTP response code.
* @param exchange_url URL of the exchange supposed to
* be included in the response.
* @return the command.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_exchanges_with_url (const char *label,
unsigned int expected_response_code,

View File

@ -288,8 +288,7 @@ command_cb (void *cls,
* to be allocated, and the second to actually populate every
* element.
*
* @param is interpreter state (supposedly having the
* current CMD pointing at a "history" CMD).
* @param hs history state
* @param[out] rh history array to initialize.
* @return number of entries in @a rh.
*/

View File

@ -251,12 +251,15 @@ batch_deposit_run (void *cls,
&wire_salt),
GNUNET_JSON_spec_end ()
};
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url
= TALER_TESTING_get_exchange_url (is);
(void) cmd;
if (NULL == exchange)
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
memset (cdds,
0,
sizeof (cdds));
@ -383,13 +386,16 @@ batch_deposit_run (void *cls,
.refund_deadline = ds->refund_deadline
};
ds->dh = TALER_EXCHANGE_batch_deposit (exchange,
&dcd,
ds->num_coins,
cdds,
&batch_deposit_cb,
ds,
&ec);
ds->dh = TALER_EXCHANGE_batch_deposit (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
TALER_TESTING_get_keys (is),
&dcd,
ds->num_coins,
cdds,
&batch_deposit_cb,
ds,
&ec);
}
if (NULL == ds->dh)
{

View File

@ -190,13 +190,16 @@ get_run (void *cls,
struct ContractGetState *ds = cls;
const struct TALER_ContractDiffiePrivateP *contract_priv;
const struct TALER_TESTING_Command *ref;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url;
(void) cmd;
if (NULL == exchange)
return;
ds->is = is;
exchange_url = TALER_TESTING_get_exchange_url (is);
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
ref = TALER_TESTING_interpreter_lookup_command (ds->is,
ds->contract_ref);
GNUNET_assert (NULL != ref);
@ -210,7 +213,8 @@ get_run (void *cls,
}
ds->contract_priv = *contract_priv;
ds->dh = TALER_EXCHANGE_contract_get (
exchange,
TALER_TESTING_interpreter_get_context (is),
exchange_url,
contract_priv,
&get_cb,
ds);

View File

@ -98,7 +98,7 @@ struct DepositState
/**
* Deposit handle while operation is running.
*/
struct TALER_EXCHANGE_DepositHandle *dh;
struct TALER_EXCHANGE_BatchDepositHandle *dh;
/**
* Timestamp of the /deposit operation in the wallet (contract signing time).
@ -215,7 +215,7 @@ do_retry (void *cls)
*/
static void
deposit_cb (void *cls,
const struct TALER_EXCHANGE_DepositResult *dr)
const struct TALER_EXCHANGE_BatchDepositResult *dr)
{
struct DepositState *ds = cls;
@ -254,10 +254,11 @@ deposit_cb (void *cls,
}
if (MHD_HTTP_OK == dr->hr.http_status)
{
GNUNET_assert (1 == dr->details.ok.num_signatures);
ds->deposit_succeeded = GNUNET_YES;
ds->exchange_timestamp = dr->details.ok.deposit_timestamp;
ds->exchange_pub = *dr->details.ok.exchange_pub;
ds->exchange_sig = *dr->details.ok.exchange_sig;
ds->exchange_sig = dr->details.ok.exchange_sigs[0];
}
TALER_TESTING_interpreter_next (ds->is);
}
@ -296,12 +297,15 @@ deposit_run (void *cls,
&wire_salt),
GNUNET_JSON_spec_end ()
};
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url
= TALER_TESTING_get_exchange_url (is);
(void) cmd;
if (NULL == exchange)
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
ds->is = is;
if (NULL != ds->deposit_reference)
{
@ -469,12 +473,16 @@ deposit_run (void *cls,
.refund_deadline = ds->refund_deadline
};
ds->dh = TALER_EXCHANGE_deposit (exchange,
&dcd,
&cdd,
&deposit_cb,
ds,
&ec);
ds->dh = TALER_EXCHANGE_batch_deposit (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
TALER_TESTING_get_keys (is),
&dcd,
1,
&cdd,
&deposit_cb,
ds,
&ec);
}
if (NULL == ds->dh)
{
@ -505,7 +513,7 @@ deposit_cleanup (void *cls,
{
TALER_TESTING_command_incomplete (ds->is,
cmd->label);
TALER_EXCHANGE_deposit_cancel (ds->dh);
TALER_EXCHANGE_batch_deposit_cancel (ds->dh);
ds->dh = NULL;
}
if (NULL != ds->retry_task)

View File

@ -198,12 +198,8 @@ track_transaction_run (void *cls,
struct TALER_MerchantWireHashP h_wire_details;
struct TALER_PrivateContractHashP h_contract_terms;
const struct TALER_MerchantPrivateKeyP *merchant_priv;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
tts->cmd = cmd;
if (NULL == exchange)
return;
tts->is = is;
transaction_cmd
= TALER_TESTING_interpreter_lookup_command (tts->is,
@ -275,14 +271,17 @@ track_transaction_run (void *cls,
return;
}
tts->tth = TALER_EXCHANGE_deposits_get (exchange,
merchant_priv,
&h_wire_details,
&h_contract_terms,
&coin_pub,
GNUNET_TIME_UNIT_ZERO,
&deposit_wtid_cb,
tts);
tts->tth = TALER_EXCHANGE_deposits_get (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
merchant_priv,
&h_wire_details,
&h_contract_terms,
&coin_pub,
GNUNET_TIME_UNIT_ZERO,
&deposit_wtid_cb,
tts);
GNUNET_assert (NULL != tts->tth);
}

View File

@ -49,9 +49,9 @@ struct GetAuditorState
struct TALER_TESTING_Interpreter *is;
/**
* Auditor handle we produced.
* Auditor handle used to get the configuration.
*/
struct TALER_AUDITOR_Handle *auditor;
struct TALER_AUDITOR_GetConfigHandle *auditor;
/**
* URL of the auditor.
@ -70,23 +70,28 @@ struct GetAuditorState
* Function called with information about the auditor.
*
* @param cls closure
* @param hr HTTP response data
* @param vi basic information about the auditor
* @param compat protocol compatibility information
* @param vr response data
*/
static void
version_cb (
void *cls,
const struct TALER_AUDITOR_HttpResponse *hr,
const struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility compat)
const struct TALER_AUDITOR_ConfigResponse *vr)
{
struct GetAuditorState *gas = cls;
if (MHD_HTTP_OK != hr->http_status)
gas->auditor = NULL;
if (MHD_HTTP_OK != vr->hr.http_status)
{
TALER_TESTING_unexpected_status (gas->is,
hr->http_status);
vr->hr.http_status);
return;
}
if ( (NULL != gas->priv_file) &&
(0 != GNUNET_memcmp (&gas->auditor_pub,
&vr->details.ok.vi.auditor_pub)) )
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (gas->is);
return;
}
TALER_TESTING_interpreter_next (gas->is);
@ -130,10 +135,10 @@ get_auditor_run (void *cls,
}
gas->is = is;
gas->auditor
= TALER_AUDITOR_connect (TALER_TESTING_interpreter_get_context (is),
gas->auditor_url,
&version_cb,
gas);
= TALER_AUDITOR_get_config (TALER_TESTING_interpreter_get_context (is),
gas->auditor_url,
&version_cb,
gas);
if (NULL == gas->auditor)
{
GNUNET_break (0);
@ -157,7 +162,8 @@ get_auditor_cleanup (void *cls,
if (NULL != gas->auditor)
{
TALER_AUDITOR_disconnect (gas->auditor);
GNUNET_break (0);
TALER_AUDITOR_get_config_cancel (gas->auditor);
gas->auditor = NULL;
}
GNUNET_free (gas->priv_file);
@ -186,7 +192,6 @@ get_auditor_traits (void *cls,
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_auditor_priv (&gas->auditor_priv),
TALER_TESTING_make_trait_auditor_pub (&gas->auditor_pub),
TALER_TESTING_make_trait_auditor (gas->auditor),
TALER_TESTING_make_trait_auditor_url (gas->auditor_url),
TALER_TESTING_trait_end ()
};

View File

@ -189,7 +189,7 @@ get_exchange_traits (void *cls,
{
struct GetExchangeState *ges = cls;
unsigned int off = (NULL == ges->master_priv_file) ? 1 : 0;
const struct TALER_EXCHANGE_Keys *keys
struct TALER_EXCHANGE_Keys *keys
= TALER_EXCHANGE_get_keys (ges->exchange);
if (NULL != keys)
@ -198,6 +198,7 @@ get_exchange_traits (void *cls,
TALER_TESTING_make_trait_master_priv (&ges->master_priv),
TALER_TESTING_make_trait_master_pub (&keys->master_pub),
TALER_TESTING_make_trait_exchange (ges->exchange),
TALER_TESTING_make_trait_keys (keys),
TALER_TESTING_make_trait_exchange_url (ges->exchange_url),
TALER_TESTING_trait_end ()
};

View File

@ -127,13 +127,16 @@ proof_kyc_run (void *cls,
const struct TALER_TESTING_Command *res_cmd;
const struct TALER_PaytoHashP *h_payto;
char *uargs;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url;
(void) cmd;
if (NULL == exchange)
return;
kps->is = is;
exchange_url = TALER_TESTING_get_exchange_url (is);
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
res_cmd = TALER_TESTING_interpreter_lookup_command (
kps->is,
kps->payment_target_reference);
@ -157,12 +160,14 @@ proof_kyc_run (void *cls,
GNUNET_asprintf (&uargs,
"&code=%s",
kps->code);
kps->kph = TALER_EXCHANGE_kyc_proof (exchange,
h_payto,
kps->logic,
uargs,
&proof_kyc_cb,
kps);
kps->kph = TALER_EXCHANGE_kyc_proof (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
h_payto,
kps->logic,
uargs,
&proof_kyc_cb,
kps);
GNUNET_free (uargs);
GNUNET_assert (NULL != kps->kph);
}

View File

@ -147,13 +147,16 @@ wallet_kyc_run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct KycWalletGetState *kwg = cls;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url;
kwg->cmd = cmd;
if (NULL == exchange)
return;
kwg->is = is;
exchange_url = TALER_TESTING_get_exchange_url (is);
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
if (NULL != kwg->reserve_reference)
{
const struct TALER_TESTING_Command *res_cmd;
@ -185,13 +188,15 @@ wallet_kyc_run (void *cls,
GNUNET_CRYPTO_eddsa_key_get_public (&kwg->reserve_priv.eddsa_priv,
&kwg->reserve_pub.eddsa_pub);
kwg->reserve_payto_uri
= TALER_reserve_make_payto (TALER_EXCHANGE_get_base_url (exchange),
= TALER_reserve_make_payto (exchange_url,
&kwg->reserve_pub);
kwg->kwh = TALER_EXCHANGE_kyc_wallet (exchange,
&kwg->reserve_priv,
&kwg->balance,
&wallet_kyc_cb,
kwg);
kwg->kwh = TALER_EXCHANGE_kyc_wallet (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
&kwg->reserve_priv,
&kwg->balance,
&wallet_kyc_cb,
kwg);
GNUNET_assert (NULL != kwg->kwh);
}

View File

@ -189,12 +189,8 @@ deposit_run (void *cls,
{
struct PurseCreateDepositState *ds = cls;
struct TALER_EXCHANGE_PurseDeposit deposits[ds->num_coin_references];
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
(void) cmd;
if (NULL == exchange)
return;
ds->is = is;
for (unsigned int i = 0; i<ds->num_coin_references; i++)
{
@ -259,7 +255,9 @@ deposit_run (void *cls,
"pay_deadline",
GNUNET_JSON_from_timestamp (ds->purse_expiration)));
ds->dh = TALER_EXCHANGE_purse_create_with_deposit (
exchange,
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
&ds->purse_priv,
&ds->merge_priv,
&ds->contract_priv,

View File

@ -97,12 +97,15 @@ purse_delete_run (void *cls,
struct PurseDeleteState *pds = cls;
const struct TALER_PurseContractPrivateKeyP *purse_priv;
const struct TALER_TESTING_Command *ref;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url;
(void) cmd;
if (NULL == exchange)
exchange_url = TALER_TESTING_get_exchange_url (is);
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
ref = TALER_TESTING_interpreter_lookup_command (is,
pds->purse_cmd);
if (NULL == ref)
@ -121,7 +124,8 @@ purse_delete_run (void *cls,
}
pds->is = is;
pds->pdh = TALER_EXCHANGE_purse_delete (
exchange,
TALER_TESTING_interpreter_get_context (is),
exchange_url,
purse_priv,
&purse_delete_cb,
pds);

View File

@ -259,11 +259,7 @@ deposit_run (void *cls,
struct TALER_EXCHANGE_PurseDeposit deposits[ds->num_coin_references];
const struct TALER_PurseContractPublicKeyP *purse_pub;
const struct TALER_TESTING_Command *purse_cmd;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
(void) cmd;
ds->is = is;
purse_cmd = TALER_TESTING_interpreter_lookup_command (is,
@ -321,7 +317,9 @@ deposit_run (void *cls,
}
ds->dh = TALER_EXCHANGE_purse_deposit (
exchange,
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
NULL, /* FIXME #7271: WADs support: purse exchange URL */
&ds->purse_pub,
ds->min_age,

View File

@ -183,11 +183,7 @@ status_run (void *cls,
{
struct StatusState *ss = cls;
const struct TALER_TESTING_Command *create_purse;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
ss->is = is;
create_purse
= TALER_TESTING_interpreter_lookup_command (is,
@ -202,12 +198,15 @@ status_run (void *cls,
TALER_TESTING_interpreter_fail (is);
return;
}
ss->pgh = TALER_EXCHANGE_purse_get (exchange,
ss->purse_pub,
ss->timeout,
ss->wait_for_merge,
&purse_status_cb,
ss);
ss->pgh = TALER_EXCHANGE_purse_get (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
ss->purse_pub,
ss->timeout,
ss->wait_for_merge,
&purse_status_cb,
ss);
if (! GNUNET_TIME_relative_is_zero (ss->timeout))
{
TALER_TESTING_interpreter_next (is);

View File

@ -201,12 +201,8 @@ merge_run (void *cls,
const struct TALER_PurseMergePrivateKeyP *merge_priv;
const json_t *ct;
const struct TALER_TESTING_Command *ref;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
(void) cmd;
if (NULL == exchange)
return;
ds->is = is;
ref = TALER_TESTING_interpreter_lookup_command (ds->is,
ds->merge_ref);
@ -322,7 +318,9 @@ merge_run (void *cls,
&ds->merge_pub.eddsa_pub);
ds->merge_timestamp = GNUNET_TIME_timestamp_get ();
ds->dh = TALER_EXCHANGE_account_merge (
exchange,
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
NULL, /* no wad */
&ds->reserve_priv,
&ds->purse_pub,

View File

@ -182,11 +182,7 @@ recoup_run (void *cls,
char *cref;
unsigned int idx;
const struct TALER_ExchangeWithdrawValues *ewv;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
ps->is = is;
if (GNUNET_OK !=
TALER_TESTING_parse_coin_reference (
@ -259,13 +255,16 @@ recoup_run (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Trying to recoup denomination '%s'\n",
TALER_B2S (&denom_pub->h_key));
ps->ph = TALER_EXCHANGE_recoup (exchange,
denom_pub,
coin_sig,
ewv,
planchet,
&recoup_cb,
ps);
ps->ph = TALER_EXCHANGE_recoup (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
denom_pub,
coin_sig,
ewv,
planchet,
&recoup_cb,
ps);
GNUNET_assert (NULL != ps->ph);
}

View File

@ -184,11 +184,7 @@ recoup_refresh_run (void *cls,
const struct TALER_ExchangeWithdrawValues *ewv;
char *cref;
unsigned int idx;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
rrs->is = is;
if (GNUNET_OK !=
TALER_TESTING_parse_coin_reference (
@ -273,15 +269,18 @@ recoup_refresh_run (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Trying to recoup_refresh denomination '%s'\n",
TALER_B2S (&denom_pub->h_key));
rrs->ph = TALER_EXCHANGE_recoup_refresh (exchange,
denom_pub,
coin_sig,
ewv,
rplanchet,
planchet,
idx,
&recoup_refresh_cb,
rrs);
rrs->ph = TALER_EXCHANGE_recoup_refresh (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
denom_pub,
coin_sig,
ewv,
rplanchet,
planchet,
idx,
&recoup_refresh_cb,
rrs);
GNUNET_assert (NULL != rrs->ph);
}

View File

@ -496,12 +496,8 @@ refresh_reveal_run (void *cls,
struct RefreshRevealState *rrs = cls;
struct RefreshMeltState *rms;
const struct TALER_TESTING_Command *melt_cmd;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
rrs->cmd = cmd;
if (NULL == exchange)
return;
rrs->is = is;
melt_cmd = TALER_TESTING_interpreter_lookup_command (is,
rrs->melt_reference);
@ -518,14 +514,16 @@ refresh_reveal_run (void *cls,
for (unsigned int i = 0; i<rms->num_fresh_coins; i++)
alg_values[i] = rms->mbds[i].alg_value;
rrs->rrh = TALER_EXCHANGE_refreshes_reveal (exchange,
&rms->rms,
&rms->refresh_data,
rms->num_fresh_coins,
alg_values,
rms->noreveal_index,
&reveal_cb,
rrs);
rrs->rrh = TALER_EXCHANGE_refreshes_reveal (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
&rms->rms,
&rms->refresh_data,
rms->num_fresh_coins,
alg_values,
rms->noreveal_index,
&reveal_cb,
rrs);
}
if (NULL == rrs->rrh)
{
@ -783,13 +781,16 @@ refresh_link_run (void *cls,
const struct TALER_TESTING_Command *reveal_cmd;
const struct TALER_TESTING_Command *melt_cmd;
const struct TALER_TESTING_Command *coin_cmd;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url;
rls->cmd = cmd;
if (NULL == exchange)
return;
rls->is = is;
exchange_url = TALER_TESTING_get_exchange_url (is);
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
reveal_cmd = TALER_TESTING_interpreter_lookup_command (rls->is,
rls->reveal_reference);
if (NULL == reveal_cmd)
@ -832,11 +833,13 @@ refresh_link_run (void *cls,
}
/* finally, use private key from withdraw sign command */
rls->rlh = TALER_EXCHANGE_link (exchange,
coin_priv,
rms->refresh_data.melt_age_commitment_proof,
&link_cb,
rls);
rls->rlh = TALER_EXCHANGE_link (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
coin_priv,
rms->refresh_data.melt_age_commitment_proof,
&link_cb,
rls);
if (NULL == rls->rlh)
{
@ -908,12 +911,8 @@ melt_cb (void *cls,
{
struct RefreshMeltState *rms = cls;
const struct TALER_EXCHANGE_HttpResponse *hr = &mr->hr;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (rms->is);
rms->rmh = NULL;
if (NULL == exchange)
return;
if (rms->expected_response_code != hr->http_status)
{
if (0 != rms->do_retry)
@ -973,11 +972,14 @@ melt_cb (void *cls,
{
TALER_LOG_DEBUG ("Doubling the melt (%s)\n",
rms->cmd->label);
rms->rmh = TALER_EXCHANGE_melt (exchange,
&rms->rms,
&rms->refresh_data,
&melt_cb,
rms);
rms->rmh = TALER_EXCHANGE_melt (
TALER_TESTING_interpreter_get_context (rms->is),
TALER_TESTING_get_exchange_url (rms->is),
TALER_TESTING_get_keys (rms->is),
&rms->rms,
&rms->refresh_data,
&melt_cb,
rms);
rms->double_melt = false;
return;
}
@ -1149,11 +1151,14 @@ melt_run (void *cls,
GNUNET_assert (age_restricted ==
(NULL != age_commitment_proof));
rms->rmh = TALER_EXCHANGE_melt (exchange,
&rms->rms,
&rms->refresh_data,
&melt_cb,
rms);
rms->rmh = TALER_EXCHANGE_melt (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
&rms->rms,
&rms->refresh_data,
&melt_cb,
rms);
if (NULL == rms->rmh)
{

View File

@ -53,11 +53,6 @@ struct RefundState
*/
uint64_t refund_transaction_id;
/**
* Connection to the exchange.
*/
struct TALER_EXCHANGE_Handle *exchange;
/**
* Handle to the refund operation.
*/
@ -116,9 +111,6 @@ refund_run (void *cls,
const struct TALER_MerchantPrivateKeyP *merchant_priv;
const struct TALER_TESTING_Command *coin_cmd;
rs->exchange = TALER_TESTING_get_exchange (is);
if (NULL == rs->exchange)
return;
rs->is = is;
if (GNUNET_OK !=
TALER_string_to_amount (rs->refund_amount,
@ -172,14 +164,17 @@ refund_run (void *cls,
TALER_TESTING_interpreter_fail (is);
return;
}
rs->rh = TALER_EXCHANGE_refund (rs->exchange,
&refund_amount,
&h_contract_terms,
&coin,
rs->refund_transaction_id,
merchant_priv,
&refund_cb,
rs);
rs->rh = TALER_EXCHANGE_refund (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
&refund_amount,
&h_contract_terms,
&coin,
rs->refund_transaction_id,
merchant_priv,
&refund_cb,
rs);
GNUNET_assert (NULL != rs->rh);
}

View File

@ -152,12 +152,15 @@ attest_run (void *cls,
{
struct AttestState *ss = cls;
const struct TALER_TESTING_Command *create_reserve;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url;
if (NULL == exchange)
return;
ss->is = is;
exchange_url = TALER_TESTING_get_exchange_url (is);
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
create_reserve
= TALER_TESTING_interpreter_lookup_command (is,
ss->reserve_reference);
@ -179,12 +182,14 @@ attest_run (void *cls,
}
GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv,
&ss->reserve_pub.eddsa_pub);
ss->rsh = TALER_EXCHANGE_reserves_attest (exchange,
ss->reserve_priv,
ss->attrs_len,
ss->attrs,
&reserve_attest_cb,
ss);
ss->rsh = TALER_EXCHANGE_reserves_attest (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
ss->reserve_priv,
ss->attrs_len,
ss->attrs,
&reserve_attest_cb,
ss);
}

View File

@ -142,11 +142,7 @@ close_run (void *cls,
{
struct CloseState *ss = cls;
const struct TALER_TESTING_Command *create_reserve;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
if (NULL == exchange)
return;
ss->is = is;
create_reserve
= TALER_TESTING_interpreter_lookup_command (is,
@ -169,11 +165,13 @@ close_run (void *cls,
}
GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv,
&ss->reserve_pub.eddsa_pub);
ss->rsh = TALER_EXCHANGE_reserves_close (exchange,
ss->reserve_priv,
ss->target_account,
&reserve_close_cb,
ss);
ss->rsh = TALER_EXCHANGE_reserves_close (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
ss->reserve_priv,
ss->target_account,
&reserve_close_cb,
ss);
}

View File

@ -178,12 +178,15 @@ status_run (void *cls,
{
struct StatusState *ss = cls;
const struct TALER_TESTING_Command *create_reserve;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url;
if (NULL == exchange)
return;
ss->is = is;
exchange_url = TALER_TESTING_get_exchange_url (is);
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
create_reserve
= TALER_TESTING_interpreter_lookup_command (is,
ss->reserve_reference);
@ -197,11 +200,13 @@ status_run (void *cls,
TALER_TESTING_interpreter_fail (is);
return;
}
ss->rsh = TALER_EXCHANGE_reserves_get (exchange,
ss->reserve_pubp,
ss->timeout,
&reserve_status_cb,
ss);
ss->rsh = TALER_EXCHANGE_reserves_get (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
ss->reserve_pubp,
ss->timeout,
&reserve_status_cb,
ss);
if (! GNUNET_TIME_relative_is_zero (ss->timeout))
{
TALER_TESTING_interpreter_next (is);

View File

@ -125,12 +125,15 @@ get_attestable_run (void *cls,
const struct TALER_TESTING_Command *ref_reserve;
const struct TALER_ReservePrivateKeyP *reserve_priv;
const struct TALER_ReservePublicKeyP *reserve_pub;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
const char *exchange_url;
if (NULL == exchange)
return;
ss->is = is;
exchange_url = TALER_TESTING_get_exchange_url (is);
if (NULL == exchange_url)
{
GNUNET_break (0);
return;
}
ref_reserve
= TALER_TESTING_interpreter_lookup_command (is,
ss->reserve_reference);
@ -162,10 +165,12 @@ get_attestable_run (void *cls,
}
ss->reserve_pub = *reserve_pub;
}
ss->rgah = TALER_EXCHANGE_reserves_get_attestable (exchange,
&ss->reserve_pub,
&reserve_get_attestable_cb,
ss);
ss->rgah = TALER_EXCHANGE_reserves_get_attestable (
TALER_TESTING_interpreter_get_context (is),
exchange_url,
&ss->reserve_pub,
&reserve_get_attestable_cb,
ss);
}

View File

@ -369,10 +369,13 @@ history_run (void *cls,
}
GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv,
&ss->reserve_pub.eddsa_pub);
ss->rsh = TALER_EXCHANGE_reserves_history (exchange,
ss->reserve_priv,
&reserve_history_cb,
ss);
ss->rsh = TALER_EXCHANGE_reserves_history (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
ss->reserve_priv,
&reserve_history_cb,
ss);
}

View File

@ -256,7 +256,9 @@ open_run (void *cls,
cpi->h_denom_pub = denom_pub->h_key;
}
ss->rsh = TALER_EXCHANGE_reserves_open (
exchange,
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
ss->reserve_priv,
&ss->reserve_pay,
ss->cpl,

View File

@ -245,7 +245,9 @@ purse_run (void *cls,
GNUNET_JSON_from_timestamp (ds->purse_expiration)));
ds->merge_timestamp = GNUNET_TIME_timestamp_get ();
ds->dh = TALER_EXCHANGE_purse_create_with_merge (
exchange,
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
&ds->reserve_priv,
&ds->purse_priv,
&ds->merge_priv,

View File

@ -341,10 +341,13 @@ status_run (void *cls,
}
GNUNET_CRYPTO_eddsa_key_get_public (&ss->reserve_priv->eddsa_priv,
&ss->reserve_pub.eddsa_pub);
ss->rsh = TALER_EXCHANGE_reserves_status (exchange,
ss->reserve_priv,
&reserve_status_cb,
ss);
ss->rsh = TALER_EXCHANGE_reserves_status (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
ss->reserve_priv,
&reserve_status_cb,
ss);
}

View File

@ -345,10 +345,13 @@ track_transfer_run (void *cls,
}
GNUNET_assert (NULL != wtid_ptr);
}
tts->tth = TALER_EXCHANGE_transfers_get (exchange,
wtid_ptr,
&track_transfer_cb,
tts);
tts->tth = TALER_EXCHANGE_transfers_get (
TALER_TESTING_interpreter_get_context (is),
TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
wtid_ptr,
&track_transfer_cb,
tts);
GNUNET_assert (NULL != tts->tth);
}

View File

@ -1,796 +0,0 @@
/*
This file is part of TALER
Copyright (C) 2018-2020 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 Foundation; either version 3, or
(at your option) any later version.
TALER is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
/**
* @file testing/testing_api_helpers_exchange.c
* @brief helper functions
* @author Christian Grothoff
* @author Marcello Stanisci
*/
#include "platform.h"
#include "taler_json_lib.h"
#include <gnunet/gnunet_curl_lib.h>
#include "taler_signatures.h"
#include "taler_extensions.h"
#include "taler_testing_lib.h"
/**
* Run multiple taler-exchange-httpd processes in
* parallel using GNU parallel?
*/
#define GNU_PARALLEL 0
void
TALER_TESTING_cleanup_files (const char *config_name)
{
if (GNUNET_OK !=
GNUNET_CONFIGURATION_parse_and_run (config_name,
&TALER_TESTING_cleanup_files_cfg,
NULL))
exit (77);
}
enum GNUNET_GenericReturnValue
TALER_TESTING_run_auditor_exchange (const char *config_filename,
const char *exchange_master_pub,
const char *exchange_base_url,
int do_remove)
{
struct GNUNET_OS_Process *proc;
enum GNUNET_OS_ProcessStatusType type;
unsigned long code;
TALER_LOG_DEBUG ("Add exchange (%s,%s) to the auditor\n",
exchange_base_url,
exchange_master_pub);
proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
"taler-auditor-exchange",
"taler-auditor-exchange",
"-c", config_filename,
"-u", exchange_base_url,
"-m", exchange_master_pub,
(GNUNET_YES == do_remove)
? "-r"
: NULL,
NULL);
if (NULL == proc)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to run `taler-auditor-exchange`, is your PATH correct?\n");
return GNUNET_SYSERR;
}
GNUNET_assert (GNUNET_OK ==
GNUNET_OS_process_wait_status (proc,
&type,
&code));
GNUNET_OS_process_destroy (proc);
if ( (0 != code) ||
(GNUNET_OS_PROCESS_EXITED != type) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"taler-auditor-exchange terminated with error (%d/%d)\n",
(int) type,
(int) code);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
enum GNUNET_GenericReturnValue
TALER_TESTING_exchange_db_reset (const char *config_filename)
{
struct GNUNET_OS_Process *proc;
enum GNUNET_OS_ProcessStatusType type;
unsigned long code;
proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
"taler-exchange-dbinit",
"taler-exchange-dbinit",
"-c", config_filename,
"-L", "WARNING",
"-r",
NULL);
if (NULL == proc)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to run `taler-exchange-dbinit`, is your PATH correct?\n");
return GNUNET_NO;
}
if (GNUNET_SYSERR ==
GNUNET_OS_process_wait_status (proc,
&type,
&code))
{
GNUNET_break (0);
GNUNET_OS_process_destroy (proc);
return GNUNET_SYSERR;
}
GNUNET_OS_process_destroy (proc);
if ( (type == GNUNET_OS_PROCESS_EXITED) &&
(0 != code) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to setup (exchange) database, exit code %d\n",
(int) code);
return GNUNET_NO;
}
if ( (type != GNUNET_OS_PROCESS_EXITED) ||
(0 != code) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected error (%d/%d) running `taler-exchange-dbinit'!\n",
(int) type,
(int) code);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
enum GNUNET_GenericReturnValue
TALER_TESTING_auditor_db_reset (const char *config_filename)
{
struct GNUNET_OS_Process *proc;
enum GNUNET_OS_ProcessStatusType type;
unsigned long code;
proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
"taler-auditor-dbinit",
"taler-auditor-dbinit",
"-c", config_filename,
"-R",
NULL);
if (NULL == proc)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to run `taler-auditor-dbinit`, is your PATH correct?\n");
return GNUNET_NO;
}
if (GNUNET_SYSERR ==
GNUNET_OS_process_wait_status (proc,
&type,
&code))
{
GNUNET_break (0);
GNUNET_OS_process_destroy (proc);
return GNUNET_SYSERR;
}
GNUNET_OS_process_destroy (proc);
if ( (type == GNUNET_OS_PROCESS_EXITED) &&
(0 != code) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to setup (auditor) database, exit code %d\n",
(int) code);
return GNUNET_NO;
}
if ( (type != GNUNET_OS_PROCESS_EXITED) ||
(0 != code) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected error (%d/%d) running `taler-auditor-dbinit'!\n",
(int) type,
(int) code);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
/**
* Type of closure for
* #sign_keys_for_exchange.
*/
struct SignInfo
{
/**
* Members will be set to the exchange configuration.
*/
struct TALER_TESTING_ExchangeConfiguration *ec;
/**
* Name of the configuration file to use.
*/
const char *config_filename;
/**
* Did we reset the database?
*/
int db_reset;
};
/**
* Sign the keys for an exchange given configuration @a cfg.
* The information to be signed must be in a file "auditor.in".
*
* @param[in,out] cls a `struct SignInfo` with further parameters
* @param cfg configuration to use
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
sign_keys_for_exchange (void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct SignInfo *si = cls;
char *exchange_master_pub;
int ret;
/* Load the extensions */
if (GNUNET_OK != TALER_extensions_init (cfg))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"couldn't load extensions");
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"exchange",
"BASE_URL",
&si->ec->exchange_url))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
"exchange",
"BASE_URL");
si->ec->exchange_url = NULL;
return GNUNET_NO;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"auditor",
"BASE_URL",
&si->ec->auditor_url))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
"auditor",
"BASE_URL");
GNUNET_free (si->ec->exchange_url);
si->ec->exchange_url = NULL;
si->ec->auditor_url = NULL;
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"exchange",
"MASTER_PUBLIC_KEY",
&exchange_master_pub))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"MASTER_PUBLIC_KEY");
ret = GNUNET_SYSERR;
goto fail;
}
if ( (GNUNET_OK !=
TALER_TESTING_run_auditor_exchange (si->config_filename,
exchange_master_pub,
si->ec->exchange_url,
GNUNET_NO)) &&
(GNUNET_YES == si->db_reset) )
{
ret = GNUNET_NO;
goto fail;
}
GNUNET_free (exchange_master_pub);
return GNUNET_OK;
fail:
GNUNET_free (si->ec->exchange_url);
GNUNET_free (si->ec->auditor_url);
si->ec->exchange_url = NULL;
si->ec->auditor_url = NULL;
return ret;
}
enum GNUNET_GenericReturnValue
TALER_TESTING_prepare_exchange (const char *config_filename,
int reset_db,
struct TALER_TESTING_ExchangeConfiguration *ec)
{
struct SignInfo si = {
.config_filename = config_filename,
.ec = ec,
.db_reset = reset_db
};
if (GNUNET_YES == reset_db)
{
if (GNUNET_OK !=
TALER_TESTING_exchange_db_reset (config_filename))
return GNUNET_NO;
if (GNUNET_OK !=
TALER_TESTING_auditor_db_reset (config_filename))
return GNUNET_NO;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_parse_and_run (config_filename,
&sign_keys_for_exchange,
&si))
return GNUNET_NO;
return GNUNET_OK;
}
int
TALER_TESTING_wait_exchange_ready (const char *base_url)
{
char *wget_cmd;
unsigned int iter;
GNUNET_asprintf (&wget_cmd,
"wget -q -t 1 -T 1 %sseed -o /dev/null -O /dev/null",
base_url); // make sure ends with '/'
/* give child time to start and bind against the socket */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Waiting for `taler-exchange-httpd` service to be ready (check with: %s)\n",
wget_cmd);
iter = 0;
do
{
if (10 == iter)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Failed to launch `taler-exchange-httpd` service (or `wget')\n");
GNUNET_free (wget_cmd);
return 77;
}
sleep (1);
iter++;
}
while (0 != system (wget_cmd));
GNUNET_free (wget_cmd);
return 0;
}
/**
* Wait for the auditor to have started. Waits for at
* most 10s, after that returns 77 to indicate an error.
*
* @param base_url what URL should we expect the auditor
* to be running at
* @return 0 on success
*/
int
TALER_TESTING_wait_auditor_ready (const char *base_url)
{
char *wget_cmd;
unsigned int iter;
GNUNET_asprintf (&wget_cmd,
"wget -q -t 1 -T 1 %sversion -o /dev/null -O /dev/null",
base_url); // make sure ends with '/'
/* give child time to start and bind against the socket */
fprintf (stderr,
"Waiting for `taler-auditor-httpd' to be ready at %s\n",
base_url);
iter = 0;
do
{
if (10 == iter)
{
fprintf (stderr,
"Failed to launch `taler-auditor-httpd' (or `wget')\n");
GNUNET_free (wget_cmd);
return 77;
}
fprintf (stderr, ".\n");
sleep (1);
iter++;
}
while (0 != system (wget_cmd));
GNUNET_free (wget_cmd);
return 0;
}
enum GNUNET_GenericReturnValue
TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb,
void *main_cb_cls,
const char *config_file)
{
struct TALER_TESTING_SetupContext setup_ctx = {
.config_filename = config_file,
.main_cb = main_cb,
.main_cb_cls = main_cb_cls
};
enum GNUNET_GenericReturnValue result;
result =
GNUNET_CONFIGURATION_parse_and_run (config_file,
&TALER_TESTING_setup_with_exchange_cfg,
&setup_ctx);
if (GNUNET_OK != result)
return result;
return GNUNET_OK;
}
/**
* Stop taler-exchange-crypto helpers.
*
* @param[in] helpers the process handles.
*/
static void
stop_helpers (struct GNUNET_OS_Process *helpers[3])
{
for (unsigned int i = 0; i<3; i++)
{
if (NULL == helpers[i])
continue;
GNUNET_break (0 ==
GNUNET_OS_process_kill (helpers[i],
SIGTERM));
GNUNET_break (GNUNET_OK ==
GNUNET_OS_process_wait (helpers[i]));
GNUNET_OS_process_destroy (helpers[i]);
}
}
/**
* Start taler-exchange-crypto helpers.
*
* @param config_filename configuration file to use
* @param[out] helpers where to store the process handles.
*/
static enum GNUNET_GenericReturnValue
start_helpers (const char *config_filename,
struct GNUNET_OS_Process *helpers[3])
{
char *dir;
const struct GNUNET_OS_ProjectData *pd;
pd = GNUNET_OS_project_data_get ();
GNUNET_OS_init (TALER_project_data_default ());
dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
GNUNET_OS_init (pd);
if (NULL == dir)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
{
char *fn;
GNUNET_asprintf (&fn,
"%s/%s",
dir,
"taler-exchange-secmod-eddsa");
helpers[0] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
fn,
"taler-exchange-secmod-eddsa",
"-c", config_filename,
"-L", "INFO",
NULL);
GNUNET_free (fn);
}
{
char *fn;
GNUNET_asprintf (&fn,
"%s/%s",
dir,
"taler-exchange-secmod-rsa");
helpers[1] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
fn,
"taler-exchange-secmod-rsa",
"-c", config_filename,
"-L", "INFO",
NULL);
GNUNET_free (fn);
}
{
char *fn;
GNUNET_asprintf (&fn,
"%s/%s",
dir,
"taler-exchange-secmod-cs");
helpers[2] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
fn,
"taler-exchange-secmod-cs",
"-c", config_filename,
"-L", "INFO",
NULL);
GNUNET_free (fn);
}
GNUNET_free (dir);
if ( (NULL == helpers[0]) ||
(NULL == helpers[1]) ||
(NULL == helpers[2]) )
{
stop_helpers (helpers);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
enum GNUNET_GenericReturnValue
TALER_TESTING_setup_with_exchange_cfg (
void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
const struct TALER_TESTING_SetupContext *setup_ctx = cls;
struct GNUNET_OS_Process *exchanged;
struct GNUNET_OS_Process *helpers[3];
unsigned long long port;
char *serve;
char *base_url;
int result;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"exchange",
"SERVE",
&serve))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"SERVE");
return GNUNET_NO;
}
if (0 == strcmp ("tcp",
serve))
{
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg,
"exchange",
"PORT",
&port))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"PORT");
GNUNET_free (serve);
return GNUNET_NO;
}
if (GNUNET_OK !=
GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
(uint16_t) port))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Required port %llu not available, skipping.\n",
port);
GNUNET_free (serve);
return GNUNET_NO;
}
}
GNUNET_free (serve);
if (GNUNET_OK !=
start_helpers (setup_ctx->config_filename,
helpers))
{
GNUNET_break (0);
return 77;
}
exchanged = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
#if GNU_PARALLEL
"parallel",
#endif
"taler-exchange-httpd",
"taler-exchange-httpd",
"-L", "INFO",
"-a", /* some tests may need timetravel */
"-c", setup_ctx->config_filename,
#if GNU_PARALLEL
"-r",
":::",
"-",
"-",
"-",
"-",
#endif
NULL);
if (NULL == exchanged)
{
GNUNET_break (0);
stop_helpers (helpers);
return 77;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"exchange",
"BASE_URL",
&base_url))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchange",
"BASE_URL");
stop_helpers (helpers);
return GNUNET_NO;
}
if (0 != TALER_TESTING_wait_exchange_ready (base_url))
{
GNUNET_free (base_url);
stop_helpers (helpers);
GNUNET_break (0 ==
GNUNET_OS_process_kill (exchanged,
SIGTERM));
#if GNU_PARALLEL
/* GNU Parallel kills on 2nd SIGTERM, need to give it a
chance to process the 1st signal first... */
sleep (1);
GNUNET_break (0 ==
GNUNET_OS_process_kill (exchanged,
SIGTERM));
#endif
GNUNET_break (GNUNET_OK ==
GNUNET_OS_process_wait (exchanged));
GNUNET_OS_process_destroy (exchanged);
return 77;
}
GNUNET_free (base_url);
/* NOTE: this call blocks. */
result = TALER_TESTING_setup (setup_ctx->main_cb,
setup_ctx->main_cb_cls,
cfg,
exchanged,
GNUNET_YES);
GNUNET_break (0 ==
GNUNET_OS_process_kill (exchanged,
SIGTERM));
#if GNU_PARALLEL
/* GNU Parallel kills on 2nd SIGTERM, need to give it a
chance to process the 1st signal first... */
sleep (1);
GNUNET_break (0 ==
GNUNET_OS_process_kill (exchanged,
SIGTERM));
#endif
GNUNET_break (GNUNET_OK ==
GNUNET_OS_process_wait (exchanged));
GNUNET_OS_process_destroy (exchanged);
stop_helpers (helpers);
return result;
}
enum GNUNET_GenericReturnValue
TALER_TESTING_setup_with_auditor_and_exchange_cfg (
void *cls,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
const struct TALER_TESTING_SetupContext *setup_ctx = cls;
struct GNUNET_OS_Process *auditord;
unsigned long long port;
char *serve;
char *base_url;
int result;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"auditor",
"SERVE",
&serve))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"auditor",
"SERVE");
return GNUNET_NO;
}
if (0 == strcmp ("tcp", serve))
{
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg,
"auditor",
"PORT",
&port))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"auditor",
"PORT");
GNUNET_free (serve);
return GNUNET_NO;
}
if (GNUNET_OK !=
GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
(uint16_t) port))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Required port %llu not available, skipping.\n",
port);
GNUNET_free (serve);
return GNUNET_NO;
}
}
GNUNET_free (serve);
auditord = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
"taler-auditor-httpd",
"taler-auditor-httpd",
"-c", setup_ctx->config_filename,
NULL);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
"auditor",
"BASE_URL",
&base_url))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"auditor",
"BASE_URL");
return GNUNET_NO;
}
if (0 != TALER_TESTING_wait_auditor_ready (base_url))
{
GNUNET_free (base_url);
GNUNET_break (0 ==
GNUNET_OS_process_kill (auditord,
SIGTERM));
GNUNET_break (GNUNET_OK ==
GNUNET_OS_process_wait (auditord));
GNUNET_OS_process_destroy (auditord);
return 77;
}
GNUNET_free (base_url);
/* NOTE: this call blocks. */
result = TALER_TESTING_setup_with_exchange_cfg ((void *) setup_ctx,
cfg);
GNUNET_break (0 ==
GNUNET_OS_process_kill (auditord,
SIGTERM));
GNUNET_break (GNUNET_OK ==
GNUNET_OS_process_wait (auditord));
GNUNET_OS_process_destroy (auditord);
return result;
}
enum GNUNET_GenericReturnValue
TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb,
void *main_cb_cls,
const char *config_file)
{
struct TALER_TESTING_SetupContext setup_ctx = {
.config_filename = config_file,
.main_cb = main_cb,
.main_cb_cls = main_cb_cls
};
return GNUNET_CONFIGURATION_parse_and_run (
config_file,
&TALER_TESTING_setup_with_auditor_and_exchange_cfg,
&setup_ctx);
}
/* end of testing_api_helpers_exchange.c */

View File

@ -385,7 +385,7 @@ do_timeout (void *cls)
*
* @param cls the `struct TALER_TESTING_Interpreter *`
* @param type type of the process
* @param exit_code status code of the process
* @param code status code of the process
*/
static void
maint_child_death (void *cls,

View File

@ -102,4 +102,59 @@ TALER_TESTING_get_exchange (struct TALER_TESTING_Interpreter *is)
}
const char *
TALER_TESTING_get_exchange_url (struct TALER_TESTING_Interpreter *is)
{
const char *exchange_url;
const struct TALER_TESTING_Command *exchange_cmd;
exchange_cmd
= TALER_TESTING_interpreter_get_command (is,
"exchange");
if (NULL == exchange_cmd)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return NULL;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_exchange_url (exchange_cmd,
&exchange_url))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return NULL;
}
return exchange_url;
}
struct TALER_EXCHANGE_Keys *
TALER_TESTING_get_keys (
struct TALER_TESTING_Interpreter *is)
{
struct TALER_EXCHANGE_Keys *keys;
const struct TALER_TESTING_Command *exchange_cmd;
exchange_cmd
= TALER_TESTING_interpreter_get_command (is,
"exchange");
if (NULL == exchange_cmd)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return NULL;
}
if (GNUNET_OK !=
TALER_TESTING_get_trait_keys (exchange_cmd,
&keys))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return NULL;
}
return keys;
}
/* end of testing_api_traits.c */