summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/taler-merchant-httpd_auditors.c2
-rw-r--r--src/backend/taler-merchant-httpd_auditors.h2
-rw-r--r--src/backend/taler-merchant-httpd_mints.c464
-rw-r--r--src/backend/taler-merchant-httpd_mints.h22
-rw-r--r--src/backend/taler-merchant-httpd_pay.c32
5 files changed, 371 insertions, 151 deletions
diff --git a/src/backend/taler-merchant-httpd_auditors.c b/src/backend/taler-merchant-httpd_auditors.c
index 480c4bb1..ac112166 100644
--- a/src/backend/taler-merchant-httpd_auditors.c
+++ b/src/backend/taler-merchant-httpd_auditors.c
@@ -72,7 +72,7 @@ json_t *j_auditors;
*/
int
TMH_AUDITORS_check_dk (struct TALER_MINT_Handle *mh,
- struct TALER_MINT_DenomPublicKey *dk)
+ const struct TALER_MINT_DenomPublicKey *dk)
{
// First, we should probably check to see if dk is expired.
//
diff --git a/src/backend/taler-merchant-httpd_auditors.h b/src/backend/taler-merchant-httpd_auditors.h
index 410f34d7..a0323941 100644
--- a/src/backend/taler-merchant-httpd_auditors.h
+++ b/src/backend/taler-merchant-httpd_auditors.h
@@ -57,7 +57,7 @@ TMH_AUDITORS_init (const struct GNUNET_CONFIGURATION_Handle *cfg);
*/
int
TMH_AUDITORS_check_dk (struct TALER_MINT_Handle *mh,
- struct TALER_MINT_DenomPublicKey *dk);
+ const struct TALER_MINT_DenomPublicKey *dk);
/**
diff --git a/src/backend/taler-merchant-httpd_mints.c b/src/backend/taler-merchant-httpd_mints.c
index 29ae8baa..aecca780 100644
--- a/src/backend/taler-merchant-httpd_mints.c
+++ b/src/backend/taler-merchant-httpd_mints.c
@@ -24,14 +24,86 @@
/**
+ * How often do we retry fetching /keys?
+ */
+#define KEYS_RETRY_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60)
+
+
+/**
+ * Mint
+ */
+struct Mint;
+
+
+/**
+ * Information we keep for a pending #MMH_MINTS_find_mint() operation.
+ */
+struct TMH_MINTS_FindOperation
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct TMH_MINTS_FindOperation *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct TMH_MINTS_FindOperation *prev;
+
+ /**
+ * Function to call with the result.
+ */
+ TMH_MINTS_FindContinuation fc;
+
+ /**
+ * Closure for @e fc.
+ */
+ void *fc_cls;
+
+ /**
+ * Mint we wait for the /keys for.
+ */
+ struct Mint *my_mint;
+
+ /**
+ * Task scheduled to asynchrnously return the result.
+ */
+ struct GNUNET_SCHEDULER_Task *at;
+
+};
+
+
+/**
* Mint
*/
struct Mint
{
+
/**
- * Hostname
+ * Kept in a DLL.
*/
- char *hostname;
+ struct Mint *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct Mint *prev;
+
+ /**
+ * Head of FOs pending for this mint.
+ */
+ struct TMH_MINTS_FindOperation *fo_head;
+
+ /**
+ * Tail of FOs pending for this mint.
+ */
+ struct TMH_MINTS_FindOperation *fo_tail;
+
+ /**
+ * (base) URI of the mint.
+ */
+ char *uri;
/**
* A connection to this mint
@@ -39,14 +111,15 @@ struct Mint
struct TALER_MINT_Handle *conn;
/**
- * This mint's context (useful to the event loop)
+ * Master public key, guaranteed to be set ONLY for
+ * trusted mints.
*/
- struct TALER_MINT_Context *ctx;
+ struct TALER_MasterPublicKeyP master_pub;
/**
- * Task we use to drive the interaction with this mint.
+ * At what time should we try to fetch /keys again?
*/
- struct GNUNET_SCHEDULER_Task *poller_task;
+ struct GNUNET_TIME_Absolute retry_time;
/**
* Flag which indicates whether some HTTP transfer between
@@ -54,18 +127,35 @@ struct Mint
*/
int pending;
+ /**
+ * #GNUNET_YES if this mint is from our configuration and
+ * explicitly trusted, #GNUNET_NO if we need to check each
+ * key to be sure it is trusted.
+ */
+ int trusted;
+
};
/**
- * Trusted mints (FIXME: they are NOT all trusted!).
+ * Context for all mint operations (useful to the event loop)
*/
-static struct Mint **mints;
+static struct TALER_MINT_Context *ctx;
/**
- * Length of the #mints array.
+ * Task we use to drive the interaction with this mint.
*/
-static unsigned int nmints;
+static struct GNUNET_SCHEDULER_Task *poller_task;
+
+/**
+ * Head of mints we know about.
+ */
+static struct Mint *mint_head;
+
+/**
+ * Tail of mints we know about.
+ */
+static struct Mint *mint_tail;
/**
* List of our trusted mints for inclusion in contracts.
@@ -91,21 +181,32 @@ static void
keys_mgmt_cb (void *cls,
const struct TALER_MINT_Keys *keys)
{
- /* HOT UPDATE: the merchants need the denomination keys!
- Because it wants to (firstly) verify the deposit confirmation
- sent by the mint, and the signed blob depends (among the
- other things) on the coin's deposit fee. That information
- is never communicated by the wallet to the merchant.
- Again, the merchant needs it because it wants to verify that
- the wallet didn't exceede the limit imposed by the merchant
- on the total deposit fee for a purchase */
+ struct Mint *mint = cls;
+ struct TMH_MINTS_FindOperation *fo;
if (NULL != keys)
{
- ((struct Mint *) cls)->pending = 0;
+ mint->pending = GNUNET_NO;
}
else
- printf ("no keys gotten\n");
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to fetch /keys from `%s'\n",
+ mint->uri);
+ TALER_MINT_disconnect (mint->conn);
+ mint->conn = NULL;
+ mint->pending = GNUNET_SYSERR; /* failed hard */
+ mint->retry_time = GNUNET_TIME_relative_to_absolute (KEYS_RETRY_FREQ);
+ }
+ while (NULL != (fo = mint->fo_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (mint->fo_head,
+ mint->fo_tail,
+ fo);
+ fo->fc (fo->fc_cls,
+ (NULL != keys) ? mint->conn : NULL);
+ GNUNET_free (fo);
+ }
}
@@ -119,7 +220,6 @@ static void
context_task (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct Mint *mint = cls;
long timeout;
int max_fd;
fd_set read_fd_set;
@@ -129,14 +229,14 @@ context_task (void *cls,
struct GNUNET_NETWORK_FDSet *ws;
struct GNUNET_TIME_Relative delay;
- mint->poller_task = NULL;
- TALER_MINT_perform (mint->ctx);
+ poller_task = NULL;
+ TALER_MINT_perform (ctx);
max_fd = -1;
timeout = -1;
FD_ZERO (&read_fd_set);
FD_ZERO (&write_fd_set);
FD_ZERO (&except_fd_set);
- TALER_MINT_get_select_info (mint->ctx,
+ TALER_MINT_get_select_info (ctx,
&read_fd_set,
&write_fd_set,
&except_fd_set,
@@ -156,19 +256,45 @@ context_task (void *cls,
GNUNET_NETWORK_fdset_copy_native (ws,
&write_fd_set,
max_fd + 1);
- mint->poller_task =
+ poller_task =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
delay,
rs,
ws,
&context_task,
- mint);
+ NULL);
GNUNET_NETWORK_fdset_destroy (rs);
GNUNET_NETWORK_fdset_destroy (ws);
}
/**
+ * Task to return find operation result asynchronously to caller.
+ *
+ * @param cls a `struct TMH_MINTS_FindOperation`
+ * @param tc unused
+ */
+static void
+return_result (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct TMH_MINTS_FindOperation *fo = cls;
+ struct Mint *mint = fo->my_mint;
+
+ fo->at = NULL;
+ GNUNET_CONTAINER_DLL_remove (mint->fo_head,
+ mint->fo_tail,
+ fo);
+ fo->fc (fo->fc_cls,
+ (GNUNET_SYSERR == mint->pending) ? NULL : mint->conn);
+ GNUNET_free (fo);
+ GNUNET_SCHEDULER_cancel (poller_task);
+ GNUNET_SCHEDULER_add_now (&context_task,
+ NULL);
+}
+
+
+/**
* Find a mint that matches @a chosen_mint. If we cannot connect
* to the mint, or if it is not acceptable, @a fc is called with
* NULL for the mint.
@@ -176,142 +302,202 @@ context_task (void *cls,
* @param chosen_mint URI of the mint we would like to talk to
* @param fc function to call with the handles for the mint
* @param fc_cls closure for @a fc
+ * @return NULL on error
*/
-void
+struct TMH_MINTS_FindOperation *
TMH_MINTS_find_mint (const char *chosen_mint,
TMH_MINTS_FindContinuation fc,
void *fc_cls)
{
- unsigned int mint_index;
+ struct Mint *mint;
+ struct TMH_MINTS_FindOperation *fo;
- for (mint_index = 0; mint_index <= nmints; mint_index++)
+ if (NULL == ctx)
{
- /* no mint found in array */
- if (mint_index == nmints)
- {
- mint_index = -1;
- break;
- }
-
+ GNUNET_break (0);
+ return NULL;
+ }
+ /* Check if the mint is known */
+ for (mint = mint_head; NULL != mint; mint = mint->next)
/* test it by checking public key --- FIXME: hostname or public key!?
Should probably be URI, not hostname anyway! */
- if (0 == strcmp (mints[mint_index]->hostname,
+ if (0 == strcmp (mint->uri,
chosen_mint))
break;
+ if (NULL == mint)
+ {
+ /* This is a new mint */
+ mint = GNUNET_new (struct Mint);
+ mint->uri = GNUNET_strdup (chosen_mint);
+ mint->pending = GNUNET_YES;
+ GNUNET_CONTAINER_DLL_insert (mint_head,
+ mint_tail,
+ mint);
+ }
+
+ /* check if we should resume this mint */
+ if ( (GNUNET_SYSERR == mint->pending) &&
+ (0 == GNUNET_TIME_absolute_get_remaining (mint->retry_time).rel_value_us) )
+ mint->pending = GNUNET_YES;
+
+ fo = GNUNET_new (struct TMH_MINTS_FindOperation);
+ fo->fc = fc;
+ fo->fc_cls = fc_cls;
+ fo->my_mint = mint;
+ GNUNET_CONTAINER_DLL_insert (mint->fo_head,
+ mint->fo_tail,
+ fo);
+
+ if (GNUNET_NO == mint->pending)
+ {
+ /* We are not currently waiting for a reply, immediately
+ return result */
+ fo->at = GNUNET_SCHEDULER_add_now (&return_result,
+ fo);
+ return fo;
}
- /* FIXME: if the mint is not found, we should download /keys
- and check if the given mint is audited by an acceptable auditor...
- #4075! */
- if (-1 == mint_index)
- fc (fc_cls, NULL);
- fc (fc_cls,
- mints[mint_index]->conn);
- GNUNET_SCHEDULER_cancel (mints[mint_index]->poller_task);
- GNUNET_SCHEDULER_add_now (&context_task,
- mints[mint_index]->ctx);
+ /* If new or resumed, retry fetching /keys */
+ if ( (NULL == mint->conn) &&
+ (GNUNET_YES == mint->pending) )
+ {
+ mint->conn = TALER_MINT_connect (ctx,
+ mint->uri,
+ &keys_mgmt_cb,
+ mint,
+ TALER_MINT_OPTION_END);
+ GNUNET_break (NULL != mint->conn);
+ }
+ return fo;
}
/**
- * Parses "trusted" mints listed in the configuration.
+ * Abort pending find operation.
*
- * @param cfg the configuration
- * @return the number of mints found; #GNUNET_SYSERR upon error in
- * parsing.
+ * @param fo handle to operation to abort
*/
-int
-TMH_MINTS_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
+void
+TMH_MINTS_find_mint_cancel (struct TMH_MINTS_FindOperation *fo)
{
- char *mints_str;
- char *token_nf; /* do no free (nf) */
- char *mint_section;
- char *mint_hostname;
- struct Mint **r_mints;
- struct Mint *mint;
- unsigned int cnt;
- int ok;
- const struct TALER_MINT_Keys *keys;
- json_t *j_mint;
+ struct Mint *mint = fo->my_mint;
- ok = 0;
- mints_str = NULL;
- token_nf = NULL;
- mint_section = NULL;
- mint_hostname = NULL;
- r_mints = NULL;
- cnt = 0;
- EXITIF (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "merchant",
- "TRUSTED_MINTS",
- &mints_str));
- for (token_nf = strtok (mints_str, " ");
- NULL != token_nf;
- token_nf = strtok (NULL, " "))
+ if (NULL != fo->at)
{
- GNUNET_assert (0 < GNUNET_asprintf (&mint_section,
- "mint-%s", token_nf));
- EXITIF (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- mint_section,
- "HOSTNAME",
- &mint_hostname));
- mint = GNUNET_new (struct Mint);
- mint->hostname = mint_hostname;
- GNUNET_array_append (r_mints,
- cnt,
- mint);
- GNUNET_free (mint_section);
- mint_section = NULL;
+ GNUNET_SCHEDULER_cancel (fo->at);
+ fo->at = NULL;
}
- ok = 1;
+ GNUNET_CONTAINER_DLL_remove (mint->fo_head,
+ mint->fo_tail,
+ fo);
+ GNUNET_free (fo);
+}
- mints = r_mints;
- nmints = cnt;
- for (cnt = 0; cnt < nmints; cnt++)
+/**
+ * Function called on each configuration section. Finds sections
+ * about mints and parses the entries.
+ *
+ * @param cls closure, with a `const struct GNUNET_CONFIGURATION_Handle *`
+ * @param section name of the section
+ */
+static void
+parse_mints (void *cls,
+ const char *section)
+{
+ const struct GNUNET_CONFIGURATION_Handle *cfg = cfg;
+ char *uri;
+ char *mks;
+ struct Mint *mint;
+
+ if (0 != strncasecmp (section,
+ "mint-",
+ strlen ("mint-")))
+ return;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ section,
+ "URI",
+ &uri))
{
- EXITIF (NULL == (mints[cnt]->ctx = TALER_MINT_init ()));
- mints[cnt]->pending = 1;
- mints[cnt]->conn = TALER_MINT_connect (mints[cnt]->ctx,
- mints[cnt]->hostname,
- &keys_mgmt_cb,
- mints[cnt],
- TALER_MINT_OPTION_END);
- EXITIF (NULL == mints[cnt]->conn);
- mints[cnt]->poller_task =
- GNUNET_SCHEDULER_add_now (&context_task,
- mints[cnt]);
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "URI");
+ return;
}
-
- trusted_mints = json_array ();
- for (cnt = 0; cnt < nmints; cnt++)
+ mint = GNUNET_new (struct Mint);
+ mint->uri = uri;
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ section,
+ "MASTER_KEY",
+ &mks))
{
- if (! mints[cnt]->pending)
+ if (GNUNET_OK ==
+ GNUNET_CRYPTO_eddsa_public_key_from_string (mks,
+ strlen (mks),
+ &mint->master_pub.eddsa_pub))
{
- keys = TALER_MINT_get_keys (mints[cnt]->conn);
- j_mint = json_pack ("{s:s, s:o}",
- "url", mints[cnt]->hostname,
- "master_pub",
- TALER_json_from_data
- (&keys->master_pub.eddsa_pub,
- sizeof (keys->master_pub.eddsa_pub)));
- json_array_append_new (trusted_mints, j_mint);
+ mint->trusted = GNUNET_YES;
}
+ else
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "MASTER_KEY",
+ _("ill-formed key"));
+ }
+ GNUNET_free (mks);
}
+ GNUNET_CONTAINER_DLL_insert (mint_head,
+ mint_tail,
+ mint);
+ mint->pending = GNUNET_YES;
+ mint->conn = TALER_MINT_connect (ctx,
+ mint->uri,
+ &keys_mgmt_cb,
+ mint,
+ TALER_MINT_OPTION_END);
+ GNUNET_break (NULL != mint->conn);
+}
- EXITIF_exit:
- GNUNET_free_non_null (mints_str);
- GNUNET_free_non_null (mint_section);
- GNUNET_free_non_null (mint_hostname);
- if (! ok)
- {
- GNUNET_free_non_null (r_mints);
+
+/**
+ * Parses "trusted" mints listed in the configuration.
+ *
+ * @param cfg the configuration
+ * @return #GNUNET_OK on success; #GNUNET_SYSERR upon error in
+ * parsing.
+ */
+int
+TMH_MINTS_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ struct Mint *mint;
+ json_t *j_mint;
+
+ ctx = TALER_MINT_init ();
+ if (NULL == ctx)
return GNUNET_SYSERR;
+ GNUNET_CONFIGURATION_iterate_sections (cfg,
+ &parse_mints,
+ (void *) cfg);
+ /* build JSON with list of trusted mints */
+ trusted_mints = json_array ();
+ for (mint = mint_head; NULL != mint; mint = mint->next)
+ {
+ if (GNUNET_YES != mint->trusted)
+ continue;
+ j_mint = json_pack ("{s:s, s:o}",
+ "url", mint->uri,
+ "master_pub", TALER_json_from_data (&mint->master_pub,
+ sizeof (struct TALER_MasterPublicKeyP)));
+ json_array_append_new (trusted_mints,
+ j_mint);
}
- return cnt;
+ poller_task = GNUNET_SCHEDULER_add_now (&context_task,
+ NULL);
+ return GNUNET_OK;
}
@@ -321,16 +507,22 @@ TMH_MINTS_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
void
TMH_MINTS_done ()
{
- unsigned int cnt;
+ struct Mint *mint;
- for (cnt = 0; cnt < nmints; cnt++)
+ while (NULL != (mint = mint_head))
{
- if (NULL != mints[cnt]->conn)
- TALER_MINT_disconnect (mints[cnt]->conn);
- if (NULL != mints[cnt]->poller_task)
- {
- GNUNET_SCHEDULER_cancel (mints[cnt]->poller_task);
- mints[cnt]->poller_task = NULL;
- }
+ GNUNET_CONTAINER_DLL_remove (mint_head,
+ mint_tail,
+ mint);
+ if (NULL != mint->conn)
+ TALER_MINT_disconnect (mint->conn);
+ GNUNET_free (mint->uri);
+ GNUNET_free (mint);
+ }
+ if (NULL != poller_task)
+ {
+ GNUNET_SCHEDULER_cancel (poller_task);
+ poller_task = NULL;
}
+ TALER_MINT_fini (ctx);
}
diff --git a/src/backend/taler-merchant-httpd_mints.h b/src/backend/taler-merchant-httpd_mints.h
index 4ae4ea6c..0892a0a5 100644
--- a/src/backend/taler-merchant-httpd_mints.h
+++ b/src/backend/taler-merchant-httpd_mints.h
@@ -40,8 +40,8 @@ json_t *trusted_mints;
* Parses "trusted" mints listed in the configuration.
*
* @param cfg the configuration
- * @return the number of mints found; #GNUNET_SYSERR upon error in
- * parsing.
+ * @return #GNUNET_OK on success; #GNUNET_SYSERR upon error in
+ * parsing or initialization.
*/
int
TMH_MINTS_init (const struct GNUNET_CONFIGURATION_Handle *cfg);
@@ -57,7 +57,6 @@ TMH_MINTS_done (void);
/**
* Function called with the result of a #TMH_MINTS_find_mint()
* operation.
- * FIXME: do we really need both mint and ctx?
*
* @param cls closure
* @param mint handle to the mint
@@ -69,6 +68,12 @@ typedef void
/**
+ * Information we keep for a pending #MMH_MINTS_find_mint() operation.
+ */
+struct TMH_MINTS_FindOperation;
+
+
+/**
* Find a mint that matches @a chosen_mint. If we cannot connect
* to the mint, or if it is not acceptable, @a fc is called with
* NULL for the mint.
@@ -81,9 +86,18 @@ typedef void
* operation in case MHD connection goes down and needs to
* free fc_cls.
*/
-void
+struct TMH_MINTS_FindOperation *
TMH_MINTS_find_mint (const char *chosen_mint,
TMH_MINTS_FindContinuation fc,
void *fc_cls);
+
+/**
+ * Abort pending find operation.
+ *
+ * @param fo handle to operation to abort
+ */
+void
+TMH_MINTS_find_mint_cancel (struct TMH_MINTS_FindOperation *fo);
+
#endif
diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c
index 31675921..b287bdd1 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -27,6 +27,7 @@
#include "taler-merchant-httpd.h"
#include "taler-merchant-httpd_parsing.h"
#include "taler-merchant-httpd_responses.h"
+#include "taler-merchant-httpd_auditors.h"
#include "taler-merchant-httpd_mints.h"
#include "taler_merchantdb_lib.h"
@@ -111,6 +112,13 @@ struct PayContext
struct MHD_Connection *connection;
/**
+ * Handle for operation to lookup /keys (and auditors) from
+ * the mint used for this transaction; NULL if no operation is
+ * pending.
+ */
+ struct TMH_MINTS_FindOperation *fo;
+
+ /**
* Placeholder for #TMH_PARSE_post_json() to keep its internal state.
*/
void *json_parse_context;
@@ -300,6 +308,11 @@ pay_context_cleanup (struct TM_HandlerContext *hc)
}
}
GNUNET_free_non_null (pc->dc);
+ if (NULL != pc->fo)
+ {
+ TMH_MINTS_find_mint_cancel (pc->fo);
+ pc->fo = NULL;
+ }
if (NULL != pc->response)
{
MHD_destroy_response (pc->response);
@@ -325,6 +338,7 @@ process_pay_with_mint (void *cls,
const struct TALER_MINT_Keys *keys;
unsigned int i;
+ pc->fo = NULL;
if (NULL == mh)
{
/* The mint on offer is not in the set of our (trusted)
@@ -364,8 +378,8 @@ process_pay_with_mint (void *cls,
return;
}
if (GNUNET_OK !=
- TMH_AUDITOR_check_dk (mh,
- denom_details))
+ TMH_AUDITORS_check_dk (mh,
+ denom_details))
{
resume_pay_with_response (pc,
MHD_HTTP_BAD_REQUEST,
@@ -395,19 +409,19 @@ process_pay_with_mint (void *cls,
&acc_fee))
{
/* acc_fee > max_fee, customer needs to cover difference */
- struct Amount excess_fee;
- struct Amount total_needed;
+ struct TALER_Amount excess_fee;
+ struct TALER_Amount total_needed;
/* compute fee amount to be covered by customer */
GNUNET_assert (GNUNET_OK ==
TALER_amount_subtract (&excess_fee,
- acc_fee,
+ &acc_fee,
&pc->max_fee));
/* add that to the total */
if (GNUNET_OK !=
TALER_amount_add (&total_needed,
&excess_fee,
- pc->amount))
+ &pc->amount))
{
GNUNET_break (0);
resume_pay_with_response (pc,
@@ -612,9 +626,9 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
/* Find the responsible mint, this may take a while... */
pc->pending = pc->coins_cnt;
- TMH_MINTS_find_mint (pc->chosen_mint,
- &process_pay_with_mint,
- pc);
+ pc->fo = TMH_MINTS_find_mint (pc->chosen_mint,
+ &process_pay_with_mint,
+ pc);
/* ... so we suspend connection until the last coin has been ack'd
or until we have encountered a hard error. Eventually, we will