aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-02-12 14:00:58 +0100
committerChristian Grothoff <christian@grothoff.org>2022-02-12 14:00:58 +0100
commit7cedf3f0bf0bd9c4f89c26bfbb4e276423860f65 (patch)
treea7748cd052e7c111ce1604997f6a1c8cd03356f6 /src
parent4d26042b5a8cf14f1e3376c7002ad844f70eb1f6 (diff)
downloadexchange-7cedf3f0bf0bd9c4f89c26bfbb4e276423860f65.tar.xz
-clean up refresh reveal API
Diffstat (limited to 'src')
-rw-r--r--src/include/taler_exchange_service.h104
-rw-r--r--src/lib/exchange_api_refreshes_reveal.c83
-rw-r--r--src/testing/testing_api_cmd_refresh.c25
3 files changed, 137 insertions, 75 deletions
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 6c3d86ee3..3b227fe3e 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -1638,6 +1638,72 @@ struct TALER_EXCHANGE_MeltHandle;
/**
+ * Information we obtain per coin during melting.
+ */
+struct TALER_EXCHANGE_MeltBlindingDetail
+{
+ /**
+ * Exchange values contributed to the refresh operation
+ */
+ struct TALER_ExchangeWithdrawValues alg_value;
+
+ /**
+ * Blinding keys used to blind the fresh coins
+ */
+ union TALER_DenominationBlindingKeyP bks;
+
+};
+
+
+/**
+ * Response returned to a /melt request.
+ */
+struct TALER_EXCHANGE_MeltResponse
+{
+ /**
+ * Full HTTP response details.
+ */
+ struct TALER_EXCHANGE_HttpResponse hr;
+
+ /**
+ * Parsed response details, variant depending on the
+ * @e hr.http_status.
+ */
+ union
+ {
+ /**
+ * Results for status #MHD_HTTP_SUCCESS.
+ */
+ struct
+ {
+
+ /**
+ * Length of the @a mbds array with the exchange values
+ * and blinding keys we are using.
+ */
+ unsigned int num_mbds;
+
+ /**
+ * Information returned per coin.
+ */
+ const struct TALER_EXCHANGE_MeltBlindingDetail *mbds;
+
+ /**
+ * Key used by the exchange to sign the response.
+ */
+ struct TALER_ExchangePublicKeyP sign_key;
+
+ /**
+ * Gamma value chosen by the exchange.
+ */
+ uint32_t noreveal_index;
+ } success;
+
+ } details;
+};
+
+
+/**
* Callbacks of this type are used to notify the application about the result
* of the /coins/$COIN_PUB/melt stage. If successful, the @a noreveal_index
* should be committed to disk prior to proceeding
@@ -1650,7 +1716,7 @@ struct TALER_EXCHANGE_MeltHandle;
* @param bks array of @a num_coins blinding keys used to blind the fresh coins
* @param noreveal_index choice by the exchange in the cut-and-choose protocol,
* UINT32_MAX on error
- * @param sign_key exchange key used to sign @a full_response, or NULL
+ * @param sign_key exchange key used to sign the response, or NULL
*/
typedef void
(*TALER_EXCHANGE_MeltCallback) (
@@ -1734,13 +1800,22 @@ struct TALER_EXCHANGE_RevealResult
*/
struct TALER_EXCHANGE_HttpResponse hr;
+ /**
+ * Parsed response details, variant depending on the
+ * @e hr.http_status.
+ */
union
{
+ /**
+ * Results for status #MHD_HTTP_SUCCESS.
+ */
struct
{
/**
- * Array of @e num_coins values about the
- * coins obtained via the refresh operation.
+ * Array of @e num_coins values about the coins obtained via the refresh
+ * operation. The array give the coins in the same order (and should
+ * have the same length) in which the original melt request specified the
+ * respective denomination keys.
*/
const struct TALER_EXCHANGE_RevealedCoinInfo *coins;
@@ -1759,25 +1834,15 @@ struct TALER_EXCHANGE_RevealResult
* 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
- * that were remelted. The @a coin_privs and @a sigs arrays give the
- * coins in the same order (and should have the same length) in which
- * the original request specified the respective denomination keys.
+ * that were remelted.
*
* @param cls closure
- * @param hr HTTP response data
- * @param num_coins number of fresh coins created, length of the @a sigs, @a psa 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 psa array of @a num_coins planchet secrets (derived from the transfer secret) for each of the coins
- * @param sigs array of signature over @a num_coins coins, NULL on error
+ * @param rr result of the reveal operation
*/
typedef void
(*TALER_EXCHANGE_RefreshesRevealCallback)(
void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr,
- unsigned int num_coins,
- const struct TALER_CoinSpendPrivateKeyP *coin_privs,
- const struct TALER_PlanchetMasterSecretP *psa,
- const struct TALER_DenominationSignature *sigs);
+ const struct TALER_EXCHANGE_RevealResult *rr);
/**
@@ -1877,8 +1942,15 @@ struct TALER_EXCHANGE_LinkResult
*/
struct TALER_EXCHANGE_HttpResponse hr;
+ /**
+ * Parsed response details, variant depending on the
+ * @e hr.http_status.
+ */
union
{
+ /**
+ * Results for status #MHD_HTTP_SUCCESS.
+ */
struct
{
/**
diff --git a/src/lib/exchange_api_refreshes_reveal.c b/src/lib/exchange_api_refreshes_reveal.c
index 0b44aa355..b17720768 100644
--- a/src/lib/exchange_api_refreshes_reveal.c
+++ b/src/lib/exchange_api_refreshes_reveal.c
@@ -99,15 +99,13 @@ struct TALER_EXCHANGE_RefreshesRevealHandle
*
* @param rrh operation handle
* @param json reply from the exchange
- * @param[out] coin_privs array of length `num_fresh_coins`, initialized to contain the coin private keys
- * @param[out] sigs array of length `num_fresh_coins`, initialized to contain signatures
+ * @param[out] rcis array of length `num_fresh_coins`, initialized to contain the coin data
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
*/
static enum GNUNET_GenericReturnValue
refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
const json_t *json,
- struct TALER_CoinSpendPrivateKeyP *coin_privs,
- struct TALER_DenominationSignature *sigs)
+ struct TALER_EXCHANGE_RevealedCoinInfo *rcis)
{
json_t *jsona;
struct GNUNET_JSON_Specification outer_spec[] = {
@@ -140,7 +138,8 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
}
for (unsigned int i = 0; i<rrh->md.num_fresh_coins; i++)
{
- const struct TALER_PlanchetMasterSecretP *fc;
+ struct TALER_EXCHANGE_RevealedCoinInfo *rci =
+ &rcis[i];
struct TALER_DenominationPublicKey *pk;
json_t *jsonai;
struct TALER_BlindedDenominationSignature blind_sig;
@@ -154,7 +153,7 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
struct TALER_FreshCoin coin;
union TALER_DenominationBlindingKeyP bks;
- fc = &rrh->md.fresh_coins[rrh->noreveal_index][i];
+ rci->ps = rrh->md.fresh_coins[rrh->noreveal_index][i];
pk = &rrh->md.fresh_pks[i];
jsonai = json_array_get (jsona, i);
GNUNET_assert (NULL != jsonai);
@@ -169,15 +168,15 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
return GNUNET_SYSERR;
}
- TALER_planchet_setup_coin_priv (fc,
+ TALER_planchet_setup_coin_priv (&rci->ps,
&rrh->alg_values[i],
- &coin_privs[i]);
- TALER_planchet_blinding_secret_create (fc,
+ &rci->coin_priv);
+ TALER_planchet_blinding_secret_create (&rci->ps,
&rrh->alg_values[i],
&bks);
/* needed to verify the signature, and we didn't store it earlier,
hence recomputing it here... */
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_privs[i].eddsa_priv,
+ GNUNET_CRYPTO_eddsa_key_get_public (&rci->coin_priv.eddsa_priv,
&coin_pub.eddsa_pub);
/* FIXME-Oec: Age commitment hash. */
TALER_coin_pub_hash (&coin_pub,
@@ -187,7 +186,7 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
TALER_planchet_to_coin (pk,
&blind_sig,
&bks,
- &coin_privs[i],
+ &rci->coin_priv,
&coin_hash,
&rrh->alg_values[i],
&coin))
@@ -198,7 +197,7 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
return GNUNET_SYSERR;
}
GNUNET_JSON_parse_free (spec);
- sigs[i] = coin.sig;
+ rci->sig = coin.sig;
}
GNUNET_JSON_parse_free (outer_spec);
return GNUNET_OK;
@@ -220,94 +219,86 @@ handle_refresh_reveal_finished (void *cls,
{
struct TALER_EXCHANGE_RefreshesRevealHandle *rrh = cls;
const json_t *j = response;
- struct TALER_EXCHANGE_HttpResponse hr = {
- .reply = j,
- .http_status = (unsigned int) response_code
+ struct TALER_EXCHANGE_RevealResult rr = {
+ .hr.reply = j,
+ .hr.http_status = (unsigned int) response_code
};
rrh->job = NULL;
switch (response_code)
{
case 0:
- hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+ rr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
{
- struct TALER_DenominationSignature sigs[rrh->md.num_fresh_coins];
- struct TALER_CoinSpendPrivateKeyP coin_privs[rrh->md.num_fresh_coins];
+ struct TALER_EXCHANGE_RevealedCoinInfo rcis[rrh->md.num_fresh_coins];
enum GNUNET_GenericReturnValue ret;
- memset (sigs,
+ memset (rcis,
0,
- sizeof (sigs));
+ sizeof (rcis));
ret = refresh_reveal_ok (rrh,
j,
- coin_privs,
- sigs);
+ rcis);
if (GNUNET_OK != ret)
{
- hr.http_status = 0;
- hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
+ rr.hr.http_status = 0;
+ rr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
else
{
GNUNET_assert (rrh->noreveal_index < TALER_CNC_KAPPA);
+ rr.details.success.num_coins = rrh->md.num_fresh_coins;
+ rr.details.success.coins = rcis;
rrh->reveal_cb (rrh->reveal_cb_cls,
- &hr,
- rrh->md.num_fresh_coins,
- coin_privs,
- rrh->md.fresh_coins[rrh->noreveal_index],
- sigs);
+ &rr);
rrh->reveal_cb = NULL;
}
for (unsigned int i = 0; i<rrh->md.num_fresh_coins; i++)
- TALER_denom_sig_free (&sigs[i]);
+ TALER_denom_sig_free (&rcis[i].sig);
TALER_EXCHANGE_refreshes_reveal_cancel (rrh);
return;
}
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 */
- hr.ec = TALER_JSON_get_error_code (j);
- hr.hint = TALER_JSON_get_error_hint (j);
+ rr.hr.ec = TALER_JSON_get_error_code (j);
+ rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_CONFLICT:
/* Nothing really to verify, exchange says our reveal is inconsistent
with our commitment, so either side is buggy; we
should pass the JSON reply to the application */
- hr.ec = TALER_JSON_get_error_code (j);
- hr.hint = TALER_JSON_get_error_hint (j);
+ rr.hr.ec = TALER_JSON_get_error_code (j);
+ rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_GONE:
/* Server claims key expired or has been revoked */
- hr.ec = TALER_JSON_get_error_code (j);
- hr.hint = TALER_JSON_get_error_hint (j);
+ rr.hr.ec = TALER_JSON_get_error_code (j);
+ rr.hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
- hr.ec = TALER_JSON_get_error_code (j);
- hr.hint = TALER_JSON_get_error_hint (j);
+ rr.hr.ec = TALER_JSON_get_error_code (j);
+ rr.hr.hint = TALER_JSON_get_error_hint (j);
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);
+ rr.hr.ec = TALER_JSON_get_error_code (j);
+ rr.hr.hint = TALER_JSON_get_error_hint (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d for exchange refreshes reveal\n",
(unsigned int) response_code,
- (int) hr.ec);
+ (int) rr.hr.ec);
break;
}
if (NULL != rrh->reveal_cb)
rrh->reveal_cb (rrh->reveal_cb_cls,
- &hr,
- 0,
- NULL,
- NULL,
- NULL);
+ &rr);
TALER_EXCHANGE_refreshes_reveal_cancel (rrh);
}
diff --git a/src/testing/testing_api_cmd_refresh.c b/src/testing/testing_api_cmd_refresh.c
index a36e20084..8b0329b38 100644
--- a/src/testing/testing_api_cmd_refresh.c
+++ b/src/testing/testing_api_cmd_refresh.c
@@ -358,13 +358,10 @@ do_reveal_retry (void *cls)
*/
static void
reveal_cb (void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr,
- unsigned int num_coins,
- const struct TALER_CoinSpendPrivateKeyP *coin_privs,
- const struct TALER_PlanchetMasterSecretP *psa,
- const struct TALER_DenominationSignature *sigs)
+ const struct TALER_EXCHANGE_RevealResult *rr)
{
struct RefreshRevealState *rrs = cls;
+ const struct TALER_EXCHANGE_HttpResponse *hr = &rr->hr;
const struct TALER_TESTING_Command *melt_cmd;
rrs->rrh = NULL;
@@ -417,20 +414,22 @@ reveal_cb (void *cls,
TALER_TESTING_interpreter_fail (rrs->is);
return;
}
- rrs->num_fresh_coins = num_coins;
switch (hr->http_status)
{
case MHD_HTTP_OK:
- rrs->psa = GNUNET_memdup (psa,
- num_coins
- * sizeof (struct TALER_PlanchetMasterSecretP));
- rrs->fresh_coins = GNUNET_new_array (num_coins,
+ rrs->num_fresh_coins = rr->details.success.num_coins;
+ rrs->psa = GNUNET_new_array (rrs->num_fresh_coins,
+ struct TALER_PlanchetMasterSecretP);
+ rrs->fresh_coins = GNUNET_new_array (rrs->num_fresh_coins,
struct TALER_TESTING_FreshCoinData);
- for (unsigned int i = 0; i<num_coins; i++)
+ for (unsigned int i = 0; i<rrs->num_fresh_coins; i++)
{
+ const struct TALER_EXCHANGE_RevealedCoinInfo *coin
+ = &rr->details.success.coins[i];
struct TALER_TESTING_FreshCoinData *fc = &rrs->fresh_coins[i];
const union TALER_DenominationBlindingKeyP *bks;
+ rrs->psa[i] = coin->ps;
if (GNUNET_OK !=
TALER_TESTING_get_trait_denom_pub (melt_cmd,
i,
@@ -449,10 +448,10 @@ reveal_cb (void *cls,
TALER_TESTING_interpreter_fail (rrs->is);
return;
}
- fc->coin_priv = coin_privs[i];
+ fc->coin_priv = coin->coin_priv;
fc->blinding_key = *bks;
TALER_denom_sig_deep_copy (&fc->sig,
- &sigs[i]);
+ &coin->sig);
}
if (0 != rrs->total_backoff.rel_value_us)
{