Compare commits

..

No commits in common. "b87d1112ea479537bda5e1ba1e1100ee53315315" and "ddedf03a816e5139b235a3ebdf5b600508c5ed5f" have entirely different histories.

98 changed files with 3325 additions and 4392 deletions

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -37,48 +37,16 @@ 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 \item[shutdown] the Taler payment system operator informs the customers that the system is being shut down for good
\end{description} \end{description}
{\bf Customers} begin their business relationship with us when they withdraw Taler has no accounts (this is digital cash) and thus there is no ``opening''
digital cash. Taler has no accounts (this is digital cash) and thus there is or ``closing'' of accounts. The equivalent of ``opening'' an account is thus
no ``opening'' or ``closing'' of accounts for consumers. Given digital cash, to withdraw digital cash. The equivalent of ``closing'' an account is to
the customers can either (1) deposit the funds explicitly into a bank account either (1) deposit the funds explicitly into a bank account, or (2) the coins
(see Section~\ref{sec:deposit}), (2) pay a merchant (see will expire if the wallet was lost (including long-term offline or
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 uninstalled). Finally, if a wallet remains (occasionally) online but a user
does simply not spend the coins will (5) diminish in value from the change does simply not spend the coins will (3) diminish in value from the change
fees (see Section~\ref{sec:fees:coin}) that apply to prevent the coins from fees (see Section~\ref{sec:fees:coin}) that apply to prevent the coins from
expiring outright. 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 The following sections describe the respective processes for each of these
interactions. interactions.
@ -151,8 +119,7 @@ The three main regulatory processes are:
\end{description} \end{description}
\include{proc-domestic} \include{proc-domestic}
%\include{proc-kyc} \include{proc-kyc}
\include{proc-kyb}
\include{proc-aml} \include{proc-aml}
\chapter{Fees} \label{chap:fees} \chapter{Fees} \label{chap:fees}

View File

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

View File

@ -157,8 +157,6 @@ handle_config (struct TAH_RequestHandler *rh,
if (NULL == ver) if (NULL == ver)
{ {
ver = GNUNET_JSON_PACK ( ver = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("name",
"taler-auditor"),
GNUNET_JSON_pack_string ("version", GNUNET_JSON_pack_string ("version",
AUDITOR_PROTOCOL_VERSION), AUDITOR_PROTOCOL_VERSION),
GNUNET_JSON_pack_string ("currency", 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 /* We always wait for the exchange, no matter if it's running locally or
remotely */ remotely */
if (0 != TALER_TESTING_wait_httpd_ready (ec.exchange_url)) if (0 != TALER_TESTING_wait_exchange_ready (ec.exchange_url))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to detect running exchange at `%s'\n", "Failed to detect running exchange at `%s'\n",

View File

@ -147,10 +147,6 @@ kyc_aml_finished (void *cls,
ea, ea,
0 != code); 0 != code);
GNUNET_free (ea); 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) if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{ {
GNUNET_break (0); GNUNET_break (0);

View File

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

View File

@ -221,9 +221,6 @@ proof_cb (
&old_scope); &old_scope);
if (TALER_KYCLOGIC_STATUS_SUCCESS == status) 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->kat = TEH_kyc_finished (&rc->async_scope_id,
kpc->process_row, kpc->process_row,
&kpc->h_payto, &kpc->h_payto,

View File

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

View File

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

View File

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

View File

@ -25,9 +25,6 @@
#include "pg_insert_kyc_attributes.h" #include "pg_insert_kyc_attributes.h"
#include "pg_helper.h" #include "pg_helper.h"
void
event_do_poll (struct GNUNET_PQ_Context *db);
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
TEH_PG_insert_kyc_attributes ( TEH_PG_insert_kyc_attributes (
@ -84,9 +81,6 @@ TEH_PG_insert_kyc_attributes (
}; };
enum GNUNET_DB_QueryStatus qs; 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, PREPARE (pg,
"insert_kyc_attributes", "insert_kyc_attributes",
"SELECT " "SELECT "
@ -98,8 +92,6 @@ TEH_PG_insert_kyc_attributes (
params, params,
rs); rs);
GNUNET_free (kyc_completed_notify_s); GNUNET_free (kyc_completed_notify_s);
GNUNET_PQ_event_do_poll (pg->conn);
if (qs < 0) if (qs < 0)
return qs; return qs;
if (! ok) if (! ok)

View File

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

View File

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

View File

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

View File

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

View File

@ -514,7 +514,7 @@ typedef void
* Iterates over all of the top-level commands of an * Iterates over all of the top-level commands of an
* interpreter. * interpreter.
* *
* @param[in] is interpreter to iterate over * @param[in] interpreter to iterate over
* @param asc true in execution order, false for reverse execution order * @param asc true in execution order, false for reverse execution order
* @param cb function to call on each command * @param cb function to call on each command
* @param cb_cls closure for cb * @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 (fresh_coins, const struct TALER_TESTING_FreshCoinData *) \
op (claim_token, const struct TALER_ClaimTokenP) \ op (claim_token, const struct TALER_ClaimTokenP) \
op (relative_time, const struct GNUNET_TIME_Relative) \ op (relative_time, const struct GNUNET_TIME_Relative) \
op (auditor, struct TALER_AUDITOR_Handle) \
op (exchange, struct TALER_EXCHANGE_Handle) \ op (exchange, struct TALER_EXCHANGE_Handle) \
op (fakebank, struct TALER_FAKEBANK_Handle) \ op (fakebank, struct TALER_FAKEBANK_Handle) \
op (keys, struct TALER_EXCHANGE_Keys) \
op (process, struct GNUNET_OS_Process *) op (process, struct GNUNET_OS_Process *)
@ -2741,26 +2741,4 @@ struct TALER_EXCHANGE_Handle *
TALER_TESTING_get_exchange (struct TALER_TESTING_Interpreter *is); 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 #endif

View File

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

View File

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

View File

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

View File

@ -1,288 +0,0 @@
/*
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

@ -0,0 +1,449 @@
/*
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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -110,7 +110,17 @@ struct TEAH_AuditorListEntry
/** /**
* Handle to the auditor. * Handle to the auditor.
*/ */
struct TALER_AUDITOR_GetConfigHandle *ah; 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;
/** /**
* Public key of the auditor. * Public key of the auditor.
@ -158,24 +168,57 @@ struct KeysRequest
void void
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Keys *keys, 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_AuditorCallback ac, TEAH_AuditorCallback ac,
void *ac_cls) void *ac_cls)
{ {
if (0 == keys->num_auditors) if (NULL == h->auditors_head)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"No auditor available. Not submitting deposit confirmations.\n"); "No auditor available for exchange `%s'. Not submitting deposit confirmations.\n",
h->url);
return; return;
} }
for (unsigned int i = 0; i<keys->num_auditors; i++) for (struct TEAH_AuditorListEntry *ale = h->auditors_head;
NULL != ale;
ale = ale->next)
{ {
const struct TALER_EXCHANGE_AuditorInformation *auditor struct TEAH_AuditorInteractionEntry *aie;
= &keys->auditors[i];
ac (ac_cls, if (! ale->is_up)
auditor->auditor_url, continue;
&auditor->auditor_pub); 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);
}
} }
} }
@ -536,18 +579,21 @@ parse_global_fee (struct TALER_EXCHANGE_GlobalFee *gf,
* auditor as 'up'. * auditor as 'up'.
* *
* @param cls closure, a `struct TEAH_AuditorListEntry *` * @param cls closure, a `struct TEAH_AuditorListEntry *`
* @param vr response from the auditor * @param hr http response from the auditor
* @param vi basic information about the auditor
* @param compat protocol compatibility information
*/ */
static void static void
auditor_config_cb ( auditor_version_cb (
void *cls, void *cls,
const struct TALER_AUDITOR_ConfigResponse *vr) const struct TALER_AUDITOR_HttpResponse *hr,
const struct TALER_AUDITOR_VersionInformation *vi,
enum TALER_AUDITOR_VersionCompatibility compat)
{ {
struct TEAH_AuditorListEntry *ale = cls; struct TEAH_AuditorListEntry *ale = cls;
enum TALER_AUDITOR_VersionCompatibility compat;
ale->ah = NULL; (void) hr;
if (MHD_HTTP_OK != vr->hr.http_status) if (NULL == vi)
{ {
/* In this case, we don't mark the auditor as 'up' */ /* In this case, we don't mark the auditor as 'up' */
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@ -555,7 +601,7 @@ auditor_config_cb (
ale->auditor_url); ale->auditor_url);
return; return;
} }
compat = vr->details.ok.compat;
if (0 != (TALER_AUDITOR_VC_INCOMPATIBLE & compat)) if (0 != (TALER_AUDITOR_VC_INCOMPATIBLE & compat))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@ -621,10 +667,10 @@ update_auditors (struct TALER_EXCHANGE_Handle *exchange)
GNUNET_CONTAINER_DLL_insert (exchange->auditors_head, GNUNET_CONTAINER_DLL_insert (exchange->auditors_head,
exchange->auditors_tail, exchange->auditors_tail,
ale); ale);
ale->ah = TALER_AUDITOR_get_config (exchange->ctx, ale->ah = TALER_AUDITOR_connect (exchange->ctx,
ale->auditor_url, ale->auditor_url,
&auditor_config_cb, &auditor_version_cb,
ale); ale);
} }
} }
@ -2077,14 +2123,26 @@ TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange)
while (NULL != (ale = exchange->auditors_head)) 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, GNUNET_CONTAINER_DLL_remove (exchange->auditors_head,
exchange->auditors_tail, exchange->auditors_tail,
ale); ale);
if (NULL != ale->ah) TALER_LOG_DEBUG ("Disconnecting the auditor `%s'\n",
{ ale->auditor_url);
TALER_AUDITOR_get_config_cancel (ale->ah); TALER_AUDITOR_disconnect (ale->ah);
ale->ah = NULL;
}
GNUNET_free (ale->auditor_url); GNUNET_free (ale->auditor_url);
GNUNET_free (ale); GNUNET_free (ale);
} }
@ -2217,7 +2275,7 @@ TALER_EXCHANGE_get_denomination_key_by_hash (
} }
struct TALER_EXCHANGE_Keys * const struct TALER_EXCHANGE_Keys *
TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange) TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange)
{ {
(void) TALER_EXCHANGE_check_keys_current (exchange, (void) TALER_EXCHANGE_check_keys_current (exchange,
@ -2239,33 +2297,4 @@ 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 */ /* end of exchange_api_handle.c */

View File

@ -34,6 +34,32 @@
struct TEAH_AuditorListEntry; 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` * Stages of initialization for the `struct TALER_EXCHANGE_Handle`
*/ */
@ -152,26 +178,39 @@ struct TALER_EXCHANGE_Handle
* launch a deposit confirmation interaction. * launch a deposit confirmation interaction.
* *
* @param cls closure * @param cls closure
* @param auditor_url base URL of the auditor * @param ah handle to the auditor
* @param auditor_pub public key of the auditor * @param auditor_pub public key of the auditor
* @return NULL if no deposit confirmation interaction was launched
*/ */
typedef void typedef struct TEAH_AuditorInteractionEntry *
(*TEAH_AuditorCallback)(void *cls, (*TEAH_AuditorCallback)(void *cls,
const char *auditor_url, struct TALER_AUDITOR_Handle *ah,
const struct TALER_AuditorPublicKeyP *auditor_pub); 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 * Iterate over all available auditors for @a h, calling
* @a ac and giving it a chance to start a deposit * @a ac and giving it a chance to start a deposit
* confirmation interaction. * confirmation interaction.
* *
* @param keys the keys to go over auditors for * @param h exchange to go over auditors for
* @param ac function to call per auditor * @param ac function to call per auditor
* @param ac_cls closure for @a ac * @param ac_cls closure for @a ac
*/ */
void void
TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Keys *keys, TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Handle *h,
TEAH_AuditorCallback ac, TEAH_AuditorCallback ac,
void *ac_cls); void *ac_cls);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2018-2023 Taler Systems SA Copyright (C) 2018 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it TALER is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by under the terms of the GNU General Public License as published by
@ -127,10 +127,11 @@ do_retry (void *cls)
*/ */
static void static void
exchanges_cb (void *cls, exchanges_cb (void *cls,
const struct TALER_AUDITOR_ListExchangesResponse *ler) const struct TALER_AUDITOR_HttpResponse *hr,
unsigned int num_exchanges,
const struct TALER_AUDITOR_ExchangeInfo *ei)
{ {
struct ExchangesState *es = cls; struct ExchangesState *es = cls;
const struct TALER_AUDITOR_HttpResponse *hr = &ler->hr;
es->leh = NULL; es->leh = NULL;
if (es->expected_response_code != hr->http_status) if (es->expected_response_code != hr->http_status)
@ -163,30 +164,24 @@ exchanges_cb (void *cls,
hr->http_status); hr->http_status);
return; return;
} }
if (MHD_HTTP_OK != hr->http_status)
{
TALER_TESTING_interpreter_next (es->is);
return;
}
if (NULL != es->exchange_url) if (NULL != es->exchange_url)
{ {
bool found = false; unsigned int found = GNUNET_NO;
unsigned int num_exchanges = ler->details.ok.num_exchanges;
const struct TALER_AUDITOR_ExchangeInfo *ei = ler->details.ok.ei;
for (unsigned int i = 0; for (unsigned int i = 0;
i<num_exchanges; i<num_exchanges;
i++) i++)
if (0 == strcmp (es->exchange_url, if (0 == strcmp (es->exchange_url,
ei[i].exchange_url)) ei[i].exchange_url))
found = true; found = GNUNET_YES;
if (! found) if (GNUNET_NO == found)
{ {
TALER_LOG_ERROR ("Exchange '%s' doesn't exist at this auditor\n", TALER_LOG_ERROR ("Exchange '%s' doesn't exist at this auditor\n",
es->exchange_url); es->exchange_url);
TALER_TESTING_interpreter_fail (es->is); TALER_TESTING_interpreter_fail (es->is);
return; return;
} }
TALER_LOG_DEBUG ("Exchange '%s' exists at this auditor!\n", TALER_LOG_DEBUG ("Exchange '%s' exists at this auditor!\n",
es->exchange_url); es->exchange_url);
} }
@ -208,7 +203,7 @@ exchanges_run (void *cls,
{ {
struct ExchangesState *es = cls; struct ExchangesState *es = cls;
const struct TALER_TESTING_Command *auditor_cmd; const struct TALER_TESTING_Command *auditor_cmd;
const char *auditor_url; struct TALER_AUDITOR_Handle *auditor;
(void) cmd; (void) cmd;
auditor_cmd = TALER_TESTING_interpreter_get_command (is, auditor_cmd = TALER_TESTING_interpreter_get_command (is,
@ -219,20 +214,15 @@ exchanges_run (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (GNUNET_OK != GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_auditor_url (auditor_cmd, TALER_TESTING_get_trait_auditor (auditor_cmd,
&auditor_url)) &auditor));
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
es->is = is; es->is = is;
es->leh = TALER_AUDITOR_list_exchanges ( es->leh = TALER_AUDITOR_list_exchanges (auditor,
TALER_TESTING_interpreter_get_context (is), &exchanges_cb,
auditor_url, es);
&exchanges_cb,
es);
if (NULL == es->leh) if (NULL == es->leh)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -297,6 +287,14 @@ 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 struct TALER_TESTING_Command
TALER_TESTING_cmd_exchanges (const char *label, TALER_TESTING_cmd_exchanges (const char *label,
unsigned int expected_response_code) unsigned int expected_response_code)
@ -320,6 +318,16 @@ 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 struct TALER_TESTING_Command
TALER_TESTING_cmd_exchanges_with_url (const char *label, TALER_TESTING_cmd_exchanges_with_url (const char *label,
unsigned int expected_response_code, unsigned int expected_response_code,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,796 @@
/*
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 cls the `struct TALER_TESTING_Interpreter *`
* @param type type of the process * @param type type of the process
* @param code status code of the process * @param exit_code status code of the process
*/ */
static void static void
maint_child_death (void *cls, maint_child_death (void *cls,

View File

@ -102,59 +102,4 @@ 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 */ /* end of testing_api_traits.c */