-modify link API to return 'ps' so that linked coins can be refreshed
This commit is contained in:
parent
730d8c893c
commit
4d26042b5a
@ -1701,6 +1701,60 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh);
|
||||
/* ********************* /refreshes/$RCH/reveal ***************************** */
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -1786,6 +1840,64 @@ TALER_EXCHANGE_refreshes_reveal_cancel (
|
||||
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
|
||||
@ -1793,20 +1905,12 @@ struct TALER_EXCHANGE_LinkHandle;
|
||||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user