summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/taler_exchange_service.h124
-rw-r--r--src/lib/exchange_api_link.c91
-rw-r--r--src/testing/testing_api_cmd_refresh.c50
3 files changed, 181 insertions, 84 deletions
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index af06d149a..6c3d86ee3 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -1702,6 +1702,60 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh);
/**
+ * Information about a coin obtained via /refreshes/$RCH/reveal.
+ */
+struct TALER_EXCHANGE_RevealedCoinInfo
+{
+ /**
+ * Private key of the coin.
+ */
+ struct TALER_CoinSpendPrivateKeyP coin_priv;
+
+ /**
+ * Master secret of this coin.
+ */
+ struct TALER_PlanchetMasterSecretP ps;
+
+ /**
+ * Signature affirming the validity of the coin.
+ */
+ struct TALER_DenominationSignature sig;
+
+};
+
+
+/**
+ * Result of a /refreshes/$RCH/reveal request.
+ */
+struct TALER_EXCHANGE_RevealResult
+{
+ /**
+ * HTTP status.
+ */
+ struct TALER_EXCHANGE_HttpResponse hr;
+
+ union
+ {
+ struct
+ {
+ /**
+ * Array of @e num_coins values about the
+ * coins obtained via the refresh operation.
+ */
+ const struct TALER_EXCHANGE_RevealedCoinInfo *coins;
+
+ /**
+ * Number of coins returned.
+ */
+ unsigned int num_coins;
+ } success;
+
+ } details;
+
+};
+
+
+/**
* Callbacks of this type are used to return the final result of
* submitting a refresh request to a exchange. If the operation was
* successful, this function returns the signatures over the coins
@@ -1787,26 +1841,76 @@ struct TALER_EXCHANGE_LinkHandle;
/**
+ * Information about a coin obtained via /link.
+ */
+struct TALER_EXCHANGE_LinkedCoinInfo
+{
+ /**
+ * Private key of the coin.
+ */
+ struct TALER_CoinSpendPrivateKeyP coin_priv;
+
+ /**
+ * Master secret of this coin.
+ */
+ struct TALER_PlanchetMasterSecretP ps;
+
+ /**
+ * Signature affirming the validity of the coin.
+ */
+ struct TALER_DenominationSignature sig;
+
+ /**
+ * Denomination public key of the coin.
+ */
+ struct TALER_DenominationPublicKey pub;
+};
+
+
+/**
+ * Result of a /link request.
+ */
+struct TALER_EXCHANGE_LinkResult
+{
+ /**
+ * HTTP status.
+ */
+ struct TALER_EXCHANGE_HttpResponse hr;
+
+ union
+ {
+ struct
+ {
+ /**
+ * Array of @e num_coins values about the
+ * coins obtained via linkage.
+ */
+ const struct TALER_EXCHANGE_LinkedCoinInfo *coins;
+
+ /**
+ * Number of coins returned.
+ */
+ unsigned int num_coins;
+ } success;
+
+ } details;
+
+};
+
+
+/**
* Callbacks of this type are used to return the final result of submitting a
* /coins/$COIN_PUB/link request to a exchange. If the operation was
* successful, this function returns the signatures over the coins that were
* created when the original coin was melted.
*
* @param cls closure
- * @param hr HTTP response data
- * @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
- * @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
- * @param sigs array of signature over @a num_coins coins, NULL on error
- * @param pubs array of public keys for the @a sigs, NULL on error
+ * @param lr result of the /link operation
*/
typedef void
(*TALER_EXCHANGE_LinkCallback) (
void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr,
- unsigned int num_coins,
- const struct TALER_CoinSpendPrivateKeyP *coin_privs,
- const struct TALER_DenominationSignature *sigs,
- const struct TALER_DenominationPublicKey *pubs);
+ const struct TALER_EXCHANGE_LinkResult *lr);
/**
diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c
index ff1efe15b..6ebb72271 100644
--- a/src/lib/exchange_api_link.c
+++ b/src/lib/exchange_api_link.c
@@ -77,9 +77,7 @@ struct TALER_EXCHANGE_LinkHandle
* @param json json reply with the data for one coin
* @param coin_num number of the coin
* @param trans_pub our transfer public key
- * @param[out] coin_priv where to return private coin key
- * @param[out] sig where to return private coin signature
- * @param[out] pub where to return the public key for the coin
+ * @param[out] lci where to return coin details
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
static enum GNUNET_GenericReturnValue
@@ -87,9 +85,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
const json_t *json,
uint32_t coin_num,
const struct TALER_TransferPublicKeyP *trans_pub,
- struct TALER_CoinSpendPrivateKeyP *coin_priv,
- struct TALER_DenominationSignature *sig,
- struct TALER_DenominationPublicKey *pub)
+ struct TALER_EXCHANGE_LinkedCoinInfo *lci)
{
struct TALER_BlindedDenominationSignature bsig;
struct TALER_DenominationPublicKey rpub;
@@ -111,7 +107,6 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
GNUNET_JSON_spec_end ()
};
struct TALER_TransferSecretP secret;
- struct TALER_PlanchetMasterSecretP ps;
struct TALER_PlanchetDetail pd;
struct TALER_CoinPubHash c_hash;
@@ -129,18 +124,18 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
&secret);
TALER_transfer_secret_to_planchet_secret (&secret,
coin_num,
- &ps);
- TALER_planchet_setup_coin_priv (&ps,
+ &lci->ps);
+ TALER_planchet_setup_coin_priv (&lci->ps,
&alg_values,
- coin_priv);
- TALER_planchet_blinding_secret_create (&ps,
+ &lci->coin_priv);
+ TALER_planchet_blinding_secret_create (&lci->ps,
&alg_values,
&bks);
if (GNUNET_OK !=
TALER_planchet_prepare (&rpub,
&alg_values,
&bks,
- coin_priv,
+ &lci->coin_priv,
&c_hash,
&pd))
{
@@ -150,7 +145,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
}
/* extract coin and signature */
if (GNUNET_OK !=
- TALER_denom_sig_unblind (sig,
+ TALER_denom_sig_unblind (&lci->sig,
&bsig,
&bks,
&c_hash,
@@ -186,7 +181,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
}
/* clean up */
- TALER_denom_pub_deep_copy (pub,
+ TALER_denom_pub_deep_copy (&lci->pub,
&rpub);
GNUNET_JSON_parse_free (spec);
return GNUNET_OK;
@@ -208,9 +203,9 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
unsigned int session;
unsigned int num_coins;
int ret;
- struct TALER_EXCHANGE_HttpResponse hr = {
- .reply = json,
- .http_status = MHD_HTTP_OK
+ struct TALER_EXCHANGE_LinkResult lr = {
+ .hr.reply = json,
+ .hr.http_status = MHD_HTTP_OK
};
if (! json_is_array (json))
@@ -263,12 +258,9 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
{
unsigned int off_coin; /* index into 1d array */
unsigned int i;
- struct TALER_CoinSpendPrivateKeyP coin_privs[GNUNET_NZL (num_coins)];
- struct TALER_DenominationSignature sigs[GNUNET_NZL (num_coins)];
- struct TALER_DenominationPublicKey pubs[GNUNET_NZL (num_coins)];
+ struct TALER_EXCHANGE_LinkedCoinInfo lcis[GNUNET_NZL (num_coins)];
- memset (sigs, 0, sizeof (sigs));
- memset (pubs, 0, sizeof (pubs));
+ memset (lcis, 0, sizeof (lcis));
off_coin = 0;
for (session = 0; session<json_array_size (json); session++)
{
@@ -301,6 +293,9 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
/* decode all coins */
for (i = 0; i<json_array_size (jsona); i++)
{
+ struct TALER_EXCHANGE_LinkedCoinInfo *lci;
+
+ lci = &lcis[i + off_coin];
GNUNET_assert (i + off_coin < num_coins);
if (GNUNET_OK !=
parse_link_coin (lh,
@@ -308,9 +303,7 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
i),
i,
&trans_pub,
- &coin_privs[i + off_coin],
- &sigs[i + off_coin],
- &pubs[i + off_coin]))
+ lci))
{
GNUNET_break_op (0);
break;
@@ -330,12 +323,10 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
if (off_coin == num_coins)
{
+ lr.details.success.num_coins = num_coins;
+ lr.details.success.coins = lcis;
lh->link_cb (lh->link_cb_cls,
- &hr,
- num_coins,
- coin_privs,
- sigs,
- pubs);
+ &lr);
lh->link_cb = NULL;
ret = GNUNET_OK;
}
@@ -349,8 +340,8 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
GNUNET_assert (off_coin <= num_coins);
for (i = 0; i<off_coin; i++)
{
- TALER_denom_sig_free (&sigs[i]);
- TALER_denom_pub_free (&pubs[i]);
+ TALER_denom_sig_free (&lcis[i].sig);
+ TALER_denom_pub_free (&lcis[i].pub);
}
}
return ret;
@@ -372,16 +363,16 @@ handle_link_finished (void *cls,
{
struct TALER_EXCHANGE_LinkHandle *lh = cls;
const json_t *j = response;
- struct TALER_EXCHANGE_HttpResponse hr = {
- .reply = j,
- .http_status = (unsigned int) response_code
+ struct TALER_EXCHANGE_LinkResult lr = {
+ .hr.reply = j,
+ .hr.http_status = (unsigned int) response_code
};
lh->job = NULL;
switch (response_code)
{
case 0:
- hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+ lr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK !=
@@ -389,49 +380,45 @@ handle_link_finished (void *cls,
j))
{
GNUNET_break_op (0);
- hr.http_status = 0;
- hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ lr.hr.http_status = 0;
+ lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
GNUNET_assert (NULL == lh->link_cb);
TALER_EXCHANGE_link_cancel (lh);
return;
case MHD_HTTP_BAD_REQUEST:
- hr.ec = TALER_JSON_get_error_code (j);
- hr.hint = TALER_JSON_get_error_hint (j);
+ lr.hr.ec = TALER_JSON_get_error_code (j);
+ lr.hr.hint = TALER_JSON_get_error_hint (j);
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
break;
case MHD_HTTP_NOT_FOUND:
- hr.ec = TALER_JSON_get_error_code (j);
- hr.hint = TALER_JSON_get_error_hint (j);
+ lr.hr.ec = TALER_JSON_get_error_code (j);
+ lr.hr.hint = TALER_JSON_get_error_hint (j);
/* Nothing really to verify, exchange says this coin was not melted; we
should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
- hr.ec = TALER_JSON_get_error_code (j);
- hr.hint = TALER_JSON_get_error_hint (j);
+ lr.hr.ec = TALER_JSON_get_error_code (j);
+ lr.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 */
GNUNET_break_op (0);
- hr.ec = TALER_JSON_get_error_code (j);
- hr.hint = TALER_JSON_get_error_hint (j);
+ lr.hr.ec = TALER_JSON_get_error_code (j);
+ lr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange link\n",
(unsigned int) response_code,
- (int) hr.ec);
+ (int) lr.hr.ec);
break;
}
if (NULL != lh->link_cb)
lh->link_cb (lh->link_cb_cls,
- &hr,
- 0,
- NULL,
- NULL,
- NULL);
+ &lr);
TALER_EXCHANGE_link_cancel (lh);
}
diff --git a/src/testing/testing_api_cmd_refresh.c b/src/testing/testing_api_cmd_refresh.c
index 769a8fef8..a36e20084 100644
--- a/src/testing/testing_api_cmd_refresh.c
+++ b/src/testing/testing_api_cmd_refresh.c
@@ -608,13 +608,10 @@ do_link_retry (void *cls)
*/
static void
link_cb (void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr,
- unsigned int num_coins,
- const struct TALER_CoinSpendPrivateKeyP *coin_privs,
- const struct TALER_DenominationSignature *sigs,
- const struct TALER_DenominationPublicKey *pubs)
+ const struct TALER_EXCHANGE_LinkResult *lr)
{
struct RefreshLinkState *rls = cls;
+ const struct TALER_EXCHANGE_HttpResponse *hr = &lr->hr;
const struct TALER_TESTING_Command *reveal_cmd;
struct TALER_TESTING_Command *link_cmd = &rls->is->commands[rls->is->ip];
unsigned int found;
@@ -683,11 +680,11 @@ link_cb (void *cls,
TALER_TESTING_interpreter_fail (rls->is);
return;
}
- if (num_coins != *num_fresh_coins)
+ if (lr->details.success.num_coins != *num_fresh_coins)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected number of fresh coins: %d vs %d in %s:%u\n",
- num_coins,
+ lr->details.success.num_coins,
*num_fresh_coins,
__FILE__,
__LINE__);
@@ -695,11 +692,11 @@ link_cb (void *cls,
return;
}
/* check that the coins match */
- for (unsigned int i = 0; i<num_coins; i++)
- for (unsigned int j = i + 1; j<num_coins; j++)
+ for (unsigned int i = 0; i<lr->details.success.num_coins; i++)
+ for (unsigned int j = i + 1; j<lr->details.success.num_coins; j++)
if (0 ==
- GNUNET_memcmp (&coin_privs[i],
- &coin_privs[j]))
+ GNUNET_memcmp (&lr->details.success.coins[i].coin_priv,
+ &lr->details.success.coins[j].coin_priv))
GNUNET_break (0);
/* Note: coins might be legitimately permutated in here... */
found = 0;
@@ -717,29 +714,38 @@ link_cb (void *cls,
return;
}
- for (unsigned int i = 0; i<num_coins; i++)
- for (unsigned int j = 0; j<num_coins; j++)
+ for (unsigned int i = 0; i<lr->details.success.num_coins; i++)
+ {
+ const struct TALER_EXCHANGE_LinkedCoinInfo *lci_i
+ = &lr->details.success.coins[i];
+
+ for (unsigned int j = 0; j<lr->details.success.num_coins; j++)
{
+ const struct TALER_TESTING_FreshCoinData *fcj
+ = &(*fc)[j];
+
if ( (0 ==
- GNUNET_memcmp (&coin_privs[i],
- &(*fc)[j].coin_priv)) &&
+ GNUNET_memcmp (&fcj->coin_priv,
+ &lci_i->coin_priv)) &&
(0 ==
- TALER_denom_sig_cmp (&(*fc)[i].sig,
- &sigs[j])) &&
+ TALER_denom_sig_cmp (&fcj->sig,
+ &lci_i->sig)) &&
(0 ==
- TALER_denom_pub_cmp (&(*fc)[i].pk->key,
- &pubs[j])) )
+ TALER_denom_pub_cmp (&fcj->pk->key,
+ &lci_i->pub)) )
{
found++;
break;
}
- }
+ } /* for j*/
+ } /* for i */
}
- if (found != num_coins)
+ if (found != lr->details.success.num_coins)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Only %u/%u coins match expectations\n",
- found, num_coins);
+ found,
+ lr->details.success.num_coins);
GNUNET_break (0);
TALER_TESTING_interpreter_fail (rls->is);
return;