-get recoup/refresh to pass

This commit is contained in:
Christian Grothoff 2022-02-10 20:15:17 +01:00
parent ed5ef2b5f7
commit d58d89dcab
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
12 changed files with 163 additions and 58 deletions

View File

@ -174,6 +174,7 @@ verify_and_execute_recoup_refresh (
const struct TALER_CoinPublicInfo *coin, const struct TALER_CoinPublicInfo *coin,
const struct TALER_ExchangeWithdrawValues *exchange_vals, const struct TALER_ExchangeWithdrawValues *exchange_vals,
const union TALER_DenominationBlindingKeyP *coin_bks, const union TALER_DenominationBlindingKeyP *coin_bks,
const struct TALER_CsNonce *nonce,
const struct TALER_CoinSpendSignatureP *coin_sig) const struct TALER_CoinSpendSignatureP *coin_sig)
{ {
struct RecoupContext pc; struct RecoupContext pc;
@ -263,6 +264,9 @@ verify_and_execute_recoup_refresh (
TALER_EC_EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED, TALER_EC_EXCHANGE_RECOUP_REFRESH_BLINDING_FAILED,
NULL); NULL);
} }
if (TALER_DENOMINATION_CS == blinded_planchet.cipher)
blinded_planchet.details.cs_blinded_planchet.nonce
= *nonce;
TALER_coin_ev_hash (&blinded_planchet, TALER_coin_ev_hash (&blinded_planchet,
&coin->denom_pub_hash, &coin->denom_pub_hash,
&h_blind); &h_blind);
@ -360,6 +364,7 @@ TEH_handler_recoup_refresh (struct MHD_Connection *connection,
union TALER_DenominationBlindingKeyP coin_bks; union TALER_DenominationBlindingKeyP coin_bks;
struct TALER_CoinSpendSignatureP coin_sig; struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_ExchangeWithdrawValues exchange_vals; struct TALER_ExchangeWithdrawValues exchange_vals;
struct TALER_CsNonce nonce;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&coin.denom_pub_hash), &coin.denom_pub_hash),
@ -371,12 +376,18 @@ TEH_handler_recoup_refresh (struct MHD_Connection *connection,
&coin_bks), &coin_bks),
GNUNET_JSON_spec_fixed_auto ("coin_sig", GNUNET_JSON_spec_fixed_auto ("coin_sig",
&coin_sig), &coin_sig),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("cs-nonce",
&nonce)),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
memset (&coin, memset (&coin,
0, 0,
sizeof (coin)); sizeof (coin));
memset (&nonce,
0,
sizeof (nonce));
coin.coin_pub = *coin_pub; coin.coin_pub = *coin_pub;
ret = TALER_MHD_parse_json_data (connection, ret = TALER_MHD_parse_json_data (connection,
root, root,
@ -392,6 +403,7 @@ TEH_handler_recoup_refresh (struct MHD_Connection *connection,
&coin, &coin,
&exchange_vals, &exchange_vals,
&coin_bks, &coin_bks,
&nonce,
&coin_sig); &coin_sig);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return res; return res;

View File

@ -177,6 +177,7 @@ verify_and_execute_recoup (
const struct TALER_CoinPublicInfo *coin, const struct TALER_CoinPublicInfo *coin,
const struct TALER_ExchangeWithdrawValues *exchange_vals, const struct TALER_ExchangeWithdrawValues *exchange_vals,
const union TALER_DenominationBlindingKeyP *coin_bks, const union TALER_DenominationBlindingKeyP *coin_bks,
const struct TALER_CsNonce *nonce,
const struct TALER_CoinSpendSignatureP *coin_sig) const struct TALER_CoinSpendSignatureP *coin_sig)
{ {
struct RecoupContext pc; struct RecoupContext pc;
@ -268,6 +269,9 @@ verify_and_execute_recoup (
TALER_EC_EXCHANGE_RECOUP_BLINDING_FAILED, TALER_EC_EXCHANGE_RECOUP_BLINDING_FAILED,
NULL); NULL);
} }
if (TALER_DENOMINATION_CS == blinded_planchet.cipher)
blinded_planchet.details.cs_blinded_planchet.nonce
= *nonce;
if (GNUNET_OK != if (GNUNET_OK !=
TALER_coin_ev_hash (&blinded_planchet, TALER_coin_ev_hash (&blinded_planchet,
&coin->denom_pub_hash, &coin->denom_pub_hash,
@ -373,6 +377,7 @@ TEH_handler_recoup (struct MHD_Connection *connection,
union TALER_DenominationBlindingKeyP coin_bks; union TALER_DenominationBlindingKeyP coin_bks;
struct TALER_CoinSpendSignatureP coin_sig; struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_ExchangeWithdrawValues exchange_vals; struct TALER_ExchangeWithdrawValues exchange_vals;
struct TALER_CsNonce nonce;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&coin.denom_pub_hash), &coin.denom_pub_hash),
@ -384,12 +389,18 @@ TEH_handler_recoup (struct MHD_Connection *connection,
&coin_bks), &coin_bks),
GNUNET_JSON_spec_fixed_auto ("coin_sig", GNUNET_JSON_spec_fixed_auto ("coin_sig",
&coin_sig), &coin_sig),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("cs-nonce",
&nonce)),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
memset (&coin, memset (&coin,
0, 0,
sizeof (coin)); sizeof (coin));
memset (&nonce,
0,
sizeof (nonce));
coin.coin_pub = *coin_pub; coin.coin_pub = *coin_pub;
ret = TALER_MHD_parse_json_data (connection, ret = TALER_MHD_parse_json_data (connection,
root, root,
@ -398,6 +409,9 @@ TEH_handler_recoup (struct MHD_Connection *connection,
return MHD_NO; /* hard failure */ return MHD_NO; /* hard failure */
if (GNUNET_NO == ret) if (GNUNET_NO == ret)
return MHD_YES; /* failure */ return MHD_YES; /* failure */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Recoup coin with BKS=%s\n",
TALER_B2S (&coin_bks));
{ {
MHD_RESULT res; MHD_RESULT res;
@ -405,6 +419,7 @@ TEH_handler_recoup (struct MHD_Connection *connection,
&coin, &coin,
&exchange_vals, &exchange_vals,
&coin_bks, &coin_bks,
&nonce,
&coin_sig); &coin_sig);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return res; return res;

View File

@ -471,9 +471,10 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
= htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW); = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
wc.wsrd.h_denomination_pub wc.wsrd.h_denomination_pub
= wc.collectable.denom_pub_hash; = wc.collectable.denom_pub_hash;
if (GNUNET_OK != TALER_coin_ev_hash (&wc.blinded_planchet, if (GNUNET_OK !=
&wc.collectable.denom_pub_hash, TALER_coin_ev_hash (&wc.blinded_planchet,
&wc.wsrd.h_coin_envelope)) &wc.collectable.denom_pub_hash,
&wc.wsrd.h_coin_envelope))
{ {
GNUNET_break (0); GNUNET_break (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
@ -502,6 +503,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
/* Sign before transaction! */ /* Sign before transaction! */
ec = TALER_EC_NONE; ec = TALER_EC_NONE;
// FIXME: swap arguments!
wc.collectable.sig = TEH_keys_denomination_sign ( wc.collectable.sig = TEH_keys_denomination_sign (
&wc.collectable.denom_pub_hash, &wc.collectable.denom_pub_hash,
&wc.blinded_planchet, &wc.blinded_planchet,

View File

@ -466,6 +466,9 @@ struct TALER_RsaPubHashP
* Master key material for the deriviation of * Master key material for the deriviation of
* private coins and blinding factors. * private coins and blinding factors.
*/ */
// FIXME: split this struct, we should have
// a different one for the Melt/Refresh secrets
// and the withdraw secrets!
struct TALER_PlanchetSecretsP struct TALER_PlanchetSecretsP
{ {
@ -840,7 +843,10 @@ struct TALER_BlindedCsPlanchet
struct GNUNET_CRYPTO_CsC c[2]; struct GNUNET_CRYPTO_CsC c[2];
/** /**
* Public Nonce * Public nonce.
* FIXME: this nonce being here has created TONS
* of trouble. Likely split off from this data
* structure in the future!
*/ */
struct TALER_CsNonce nonce; struct TALER_CsNonce nonce;
}; };
@ -1108,14 +1114,21 @@ TALER_denom_cs_derive_r_public (
/** /**
* Blind coin for blind signing with @a dk using blinding secret @a coin_bks. * Blind coin for blind signing with @a dk using blinding secret @a coin_bks.
* *
* NOTE/FIXME: As a particular oddity, the @a blinded_planchet
* is only partially initialized by this function in the
* case of CS-denominations. Here, the 'nonce' must
* be initialized separately! This has been a MAJOR
* source of bugs, and points to a likely need for a
* reorganization of either that data structure or
* this function!
*
* @param dk denomination public key to blind for * @param dk denomination public key to blind for
* @param coin_bks blinding secret to use * @param coin_bks blinding secret to use
* @param age_commitment_hash hash of the age commitment to be used for the coin. NULL if no commitment is made. * @param age_commitment_hash hash of the age commitment to be used for the coin. NULL if no commitment is made.
* @param coin_pub public key of the coin to blind * @param coin_pub public key of the coin to blind
* @param alg_values algorithm specific values to blind the planchet * @param alg_values algorithm specific values to blind the planchet
* @param[out] c_hash resulting hashed coin * @param[out] c_hash resulting hashed coin
* @param[out] coin_ev blinded coin to submit * @param[out] blinded_planchet planchet data to initialize
* @param[out] coin_ev_size number of bytes in @a coin_ev
* @return #GNUNET_OK on success * @return #GNUNET_OK on success
*/ */
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue

View File

@ -2236,7 +2236,9 @@ typedef void
* @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
* @param ps secret internals of the original refresh-reveal operation * @param rps melt secret of the refreshing operation
* @param ps coin-specific secrets derived for this coin during the refreshing operation
* @param idx index of the fresh coin in the refresh operation that is now being recouped
* @param recoup_cb the callback to call when the final result for this request is available * @param recoup_cb the callback to call when the final result for this request is available
* @param recoup_cb_cls closure for @a recoup_cb * @param recoup_cb_cls closure for @a recoup_cb
* @return NULL * @return NULL
@ -2249,7 +2251,9 @@ TALER_EXCHANGE_recoup_refresh (
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,
const struct TALER_PlanchetSecretsP *rps,
const struct TALER_PlanchetSecretsP *ps, const struct TALER_PlanchetSecretsP *ps,
unsigned int idx,
TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb, TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb,
void *recoup_cb_cls); void *recoup_cb_cls);

View File

@ -2444,7 +2444,8 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
op (bank_row, const uint64_t) \ op (bank_row, const uint64_t) \
op (reserve_priv, const struct TALER_ReservePrivateKeyP) \ op (reserve_priv, const struct TALER_ReservePrivateKeyP) \
op (planchet_secret, const struct TALER_PlanchetSecretsP) \ op (planchet_secret, const struct TALER_PlanchetSecretsP) \
op (reserve_pub, const struct TALER_ReservePublicKeyP) \ op (refresh_secret, const struct TALER_PlanchetSecretsP) \
op (reserve_pub, const struct TALER_ReservePublicKeyP) \
op (merchant_priv, const struct TALER_MerchantPrivateKeyP) \ op (merchant_priv, const struct TALER_MerchantPrivateKeyP) \
op (merchant_pub, const struct TALER_MerchantPublicKeyP) \ op (merchant_pub, const struct TALER_MerchantPublicKeyP) \
op (merchant_sig, const struct TALER_MerchantSignatureP) \ op (merchant_sig, const struct TALER_MerchantSignatureP) \

View File

@ -329,6 +329,24 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
&coin_sig), &coin_sig),
GNUNET_JSON_pack_data_auto ("coin_blind_key_secret", GNUNET_JSON_pack_data_auto ("coin_blind_key_secret",
&bks)); &bks));
if (TALER_DENOMINATION_CS == denom_sig->cipher)
{
struct TALER_CsNonce nonce;
// FIXME: add this to the spec!
/* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash()
it is not strictly clear that the nonce is needed. Best case would be
to find a way to include it more 'naturally' somehow, for example with
the variant union version of bks! */
TALER_cs_withdraw_nonce_derive (ps,
&nonce);
GNUNET_assert (
0 ==
json_object_set_new (recoup_obj,
"cs-nonce",
GNUNET_JSON_from_data_auto (
&nonce)));
}
{ {
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];

View File

@ -165,6 +165,19 @@ handle_recoup_refresh_finished (void *cls,
hr.ec = TALER_JSON_get_error_code (j); hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j); hr.hint = TALER_JSON_get_error_hint (j);
break; break;
case MHD_HTTP_FORBIDDEN:
/* 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 */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, 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);
break;
case MHD_HTTP_CONFLICT: case MHD_HTTP_CONFLICT:
{ {
/* Insufficient funds, proof attached */ /* Insufficient funds, proof attached */
@ -238,19 +251,6 @@ handle_recoup_refresh_finished (void *cls,
TALER_EXCHANGE_recoup_refresh_cancel (ph); TALER_EXCHANGE_recoup_refresh_cancel (ph);
return; return;
} }
case MHD_HTTP_FORBIDDEN:
/* 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 */
hr.ec = TALER_JSON_get_error_code (j);
hr.hint = TALER_JSON_get_error_hint (j);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, 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);
break;
case MHD_HTTP_GONE: case MHD_HTTP_GONE:
/* Kind of normal: the money was already sent to the merchant /* Kind of normal: the money was already sent to the merchant
(it was too late for the refund). */ (it was too late for the refund). */
@ -287,7 +287,9 @@ TALER_EXCHANGE_recoup_refresh (
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,
const struct TALER_PlanchetSecretsP *rps,
const struct TALER_PlanchetSecretsP *ps, const struct TALER_PlanchetSecretsP *ps,
unsigned int idx,
TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb, TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb,
void *recoup_cb_cls) void *recoup_cb_cls)
{ {
@ -302,6 +304,7 @@ TALER_EXCHANGE_recoup_refresh (
struct TALER_CoinSpendPrivateKeyP coin_priv; struct TALER_CoinSpendPrivateKeyP coin_priv;
union TALER_DenominationBlindingKeyP bks; union TALER_DenominationBlindingKeyP bks;
GNUNET_assert (NULL != recoup_cb);
GNUNET_assert (GNUNET_YES == GNUNET_assert (GNUNET_YES ==
TEAH_handle_is_ready (exchange)); TEAH_handle_is_ready (exchange));
TALER_planchet_setup_coin_priv (ps, TALER_planchet_setup_coin_priv (ps,
@ -331,6 +334,26 @@ TALER_EXCHANGE_recoup_refresh (
GNUNET_JSON_pack_data_auto ("coin_blind_key_secret", GNUNET_JSON_pack_data_auto ("coin_blind_key_secret",
&bks)); &bks));
if (TALER_DENOMINATION_CS == denom_sig->cipher)
{
struct TALER_CsNonce nonce;
// FIXME: add this to the spec!
/* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash()
it is not strictly clear that the nonce is needed. Best case would be
to find a way to include it more 'naturally' somehow, for example with
the variant union version of bks! */
TALER_cs_refresh_nonce_derive (rps,
idx,
&nonce);
GNUNET_assert (
0 ==
json_object_set_new (recoup_obj,
"cs-nonce",
GNUNET_JSON_from_data_auto (
&nonce)));
}
{ {
char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
char *end; char *end;

View File

@ -428,9 +428,10 @@ TALER_EXCHANGE_withdraw2 (
"/reserves/%s/withdraw", "/reserves/%s/withdraw",
pub_str); pub_str);
} }
// FIXME: move this to libtalerutil!
{ {
struct TALER_WithdrawRequestPS req = { struct TALER_WithdrawRequestPS req = {
.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS)), .purpose.size = htonl (sizeof (req)),
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW), .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
.reserve_pub = wh->reserve_pub, .reserve_pub = wh->reserve_pub,
.h_denomination_pub = pd->denom_pub_hash .h_denomination_pub = pd->denom_pub_hash

View File

@ -125,14 +125,14 @@ recoup_refresh_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr, const struct TALER_EXCHANGE_HttpResponse *hr,
const struct TALER_CoinSpendPublicKeyP *old_coin_pub) const struct TALER_CoinSpendPublicKeyP *old_coin_pub)
{ {
struct RecoupRefreshState *ps = cls; struct RecoupRefreshState *rrs = cls;
struct TALER_TESTING_Interpreter *is = ps->is; struct TALER_TESTING_Interpreter *is = rrs->is;
struct TALER_TESTING_Command *cmd = &is->commands[is->ip]; struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
char *cref; char *cref;
unsigned int idx; unsigned int idx;
ps->ph = NULL; rrs->ph = NULL;
if (ps->expected_response_code != hr->http_status) if (rrs->expected_response_code != hr->http_status)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u/%d to command %s in %s:%u\n", "Unexpected response code %u/%d to command %s in %s:%u\n",
@ -150,7 +150,7 @@ recoup_refresh_cb (void *cls,
} }
if (GNUNET_OK != if (GNUNET_OK !=
parse_coin_reference (ps->coin_reference, parse_coin_reference (rrs->coin_reference,
&cref, &cref,
&idx)) &idx))
{ {
@ -170,7 +170,7 @@ recoup_refresh_cb (void *cls,
struct TALER_CoinSpendPublicKeyP oc; struct TALER_CoinSpendPublicKeyP oc;
melt_cmd = TALER_TESTING_interpreter_lookup_command (is, melt_cmd = TALER_TESTING_interpreter_lookup_command (is,
ps->melt_reference); rrs->melt_reference);
if (NULL == melt_cmd) if (NULL == melt_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -185,7 +185,7 @@ recoup_refresh_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Coin %u not found in command %s\n", "Coin %u not found in command %s\n",
0, 0,
ps->melt_reference); rrs->melt_reference);
GNUNET_break (0); GNUNET_break (0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
@ -228,20 +228,21 @@ recoup_refresh_run (void *cls,
const struct TALER_TESTING_Command *cmd, const struct TALER_TESTING_Command *cmd,
struct TALER_TESTING_Interpreter *is) struct TALER_TESTING_Interpreter *is)
{ {
struct RecoupRefreshState *ps = cls; struct RecoupRefreshState *rrs = cls;
const struct TALER_TESTING_Command *coin_cmd; const struct TALER_TESTING_Command *coin_cmd;
const struct TALER_TESTING_Command *melt_cmd; const struct TALER_TESTING_Command *melt_cmd;
const struct TALER_CoinSpendPrivateKeyP *coin_priv; const struct TALER_CoinSpendPrivateKeyP *coin_priv;
const struct TALER_EXCHANGE_DenomPublicKey *denom_pub; const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
const struct TALER_DenominationSignature *coin_sig; const struct TALER_DenominationSignature *coin_sig;
const struct TALER_PlanchetSecretsP *rplanchet;
const struct TALER_PlanchetSecretsP *planchet; const struct TALER_PlanchetSecretsP *planchet;
const struct TALER_ExchangeWithdrawValues *ewv; const struct TALER_ExchangeWithdrawValues *ewv;
char *cref; char *cref;
unsigned int idx; unsigned int idx;
ps->is = is; rrs->is = is;
if (GNUNET_OK != if (GNUNET_OK !=
parse_coin_reference (ps->coin_reference, parse_coin_reference (rrs->coin_reference,
&cref, &cref,
&idx)) &idx))
{ {
@ -259,14 +260,13 @@ recoup_refresh_run (void *cls,
return; return;
} }
melt_cmd = TALER_TESTING_interpreter_lookup_command (is, melt_cmd = TALER_TESTING_interpreter_lookup_command (is,
ps->melt_reference); rrs->melt_reference);
if (NULL == melt_cmd) if (NULL == melt_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_TESTING_get_trait_coin_priv (coin_cmd, TALER_TESTING_get_trait_coin_priv (coin_cmd,
idx, idx,
@ -294,7 +294,14 @@ recoup_refresh_run (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (GNUNET_OK !=
TALER_TESTING_get_trait_refresh_secret (melt_cmd,
&rplanchet))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
if (GNUNET_OK != if (GNUNET_OK !=
TALER_TESTING_get_trait_denom_pub (coin_cmd, TALER_TESTING_get_trait_denom_pub (coin_cmd,
idx, idx,
@ -304,7 +311,6 @@ recoup_refresh_run (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_TESTING_get_trait_denom_sig (coin_cmd, TALER_TESTING_get_trait_denom_sig (coin_cmd,
idx, idx,
@ -314,19 +320,19 @@ recoup_refresh_run (void *cls,
TALER_TESTING_interpreter_fail (is); TALER_TESTING_interpreter_fail (is);
return; return;
} }
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 (is->exchange,
ps->ph = TALER_EXCHANGE_recoup_refresh (is->exchange, denom_pub,
denom_pub, coin_sig,
coin_sig, ewv,
ewv, rplanchet,
planchet, planchet,
&recoup_refresh_cb, idx,
ps); &recoup_refresh_cb,
GNUNET_assert (NULL != ps->ph); rrs);
GNUNET_assert (NULL != rrs->ph);
} }
@ -341,13 +347,13 @@ static void
recoup_refresh_cleanup (void *cls, recoup_refresh_cleanup (void *cls,
const struct TALER_TESTING_Command *cmd) const struct TALER_TESTING_Command *cmd)
{ {
struct RecoupRefreshState *ps = cls; struct RecoupRefreshState *rrs = cls;
if (NULL != ps->ph) if (NULL != rrs->ph)
{ {
TALER_EXCHANGE_recoup_refresh_cancel (ps->ph); TALER_EXCHANGE_recoup_refresh_cancel (rrs->ph);
ps->ph = NULL; rrs->ph = NULL;
} }
GNUNET_free (ps); GNUNET_free (rrs);
} }
@ -358,15 +364,15 @@ TALER_TESTING_cmd_recoup_refresh (const char *label,
const char *melt_reference, const char *melt_reference,
const char *amount) const char *amount)
{ {
struct RecoupRefreshState *ps; struct RecoupRefreshState *rrs;
ps = GNUNET_new (struct RecoupRefreshState); rrs = GNUNET_new (struct RecoupRefreshState);
ps->expected_response_code = expected_response_code; rrs->expected_response_code = expected_response_code;
ps->coin_reference = coin_reference; rrs->coin_reference = coin_reference;
ps->melt_reference = melt_reference; rrs->melt_reference = melt_reference;
if (GNUNET_OK != if (GNUNET_OK !=
TALER_string_to_amount (amount, TALER_string_to_amount (amount,
&ps->amount)) &rrs->amount))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse amount `%s' at %s\n", "Failed to parse amount `%s' at %s\n",
@ -376,7 +382,7 @@ TALER_TESTING_cmd_recoup_refresh (const char *label,
} }
{ {
struct TALER_TESTING_Command cmd = { struct TALER_TESTING_Command cmd = {
.cls = ps, .cls = rrs,
.label = label, .label = label,
.run = &recoup_refresh_run, .run = &recoup_refresh_run,
.cleanup = &recoup_refresh_cleanup .cleanup = &recoup_refresh_cleanup

View File

@ -1233,6 +1233,7 @@ melt_traits (void *cls,
&rms->bks[index]), &rms->bks[index]),
TALER_TESTING_make_trait_exchange_wd_value (index, TALER_TESTING_make_trait_exchange_wd_value (index,
&rms->alg_values[index]), &rms->alg_values[index]),
TALER_TESTING_make_trait_refresh_secret (&rms->ps),
TALER_TESTING_trait_end () TALER_TESTING_trait_end ()
}; };

View File

@ -507,10 +507,19 @@ TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet,
blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size); blinded_planchet->details.rsa_blinded_planchet.blinded_msg_size);
break; break;
case TALER_DENOMINATION_CS: case TALER_DENOMINATION_CS:
/* NOTE: it is not obvious that we need to hash the
nonce here; if we omit this, we could skip sending
the nonce in the /recoup protocol. OTOH, there is
certainly no further harm (beyond the extra
bytes send on /recoup) from including it. */
GNUNET_CRYPTO_hash_context_read ( GNUNET_CRYPTO_hash_context_read (
hash_context, hash_context,
&blinded_planchet->details.cs_blinded_planchet.nonce, &blinded_planchet->details.cs_blinded_planchet.nonce,
sizeof (blinded_planchet->details.cs_blinded_planchet.nonce)); sizeof (blinded_planchet->details.cs_blinded_planchet.nonce));
GNUNET_CRYPTO_hash_context_read (
hash_context,
&blinded_planchet->details.cs_blinded_planchet.c[0],
sizeof (struct GNUNET_CRYPTO_CsC) * 2);
break; break;
default: default:
GNUNET_break (0); GNUNET_break (0);