fixing #3814 by removing ability to melt multiple oldcoins at the same time

This commit is contained in:
Christian Grothoff 2016-05-16 11:55:47 +02:00
parent 068dbf020b
commit c8b9370413
16 changed files with 633 additions and 1437 deletions

View File

@ -240,21 +240,15 @@ struct MeltData
*/ */
struct TALER_LinkSecretP link_secrets[TALER_CNC_KAPPA]; struct TALER_LinkSecretP link_secrets[TALER_CNC_KAPPA];
/**
* Number of coins we are melting
*/
uint16_t num_melted_coins;
/** /**
* Number of coins we are creating * Number of coins we are creating
*/ */
uint16_t num_fresh_coins; uint16_t num_fresh_coins;
/** /**
* Information about the melted coins in an array of length @e * Information about the melted coin.
* num_melted_coins.
*/ */
struct MeltedCoin *melted_coins; struct MeltedCoin melted_coin;
/** /**
* Array of @e num_fresh_coins denomination keys for the coins to be * Array of @e num_fresh_coins denomination keys for the coins to be
@ -279,8 +273,6 @@ struct MeltData
static void static void
free_melted_coin (struct MeltedCoin *mc) free_melted_coin (struct MeltedCoin *mc)
{ {
if (NULL == mc)
return;
if (NULL != mc->pub_key.rsa_public_key) if (NULL != mc->pub_key.rsa_public_key)
GNUNET_CRYPTO_rsa_public_key_free (mc->pub_key.rsa_public_key); GNUNET_CRYPTO_rsa_public_key_free (mc->pub_key.rsa_public_key);
if (NULL != mc->sig.rsa_signature) if (NULL != mc->sig.rsa_signature)
@ -319,12 +311,7 @@ free_melt_data (struct MeltData *md)
unsigned int i; unsigned int i;
unsigned int j; unsigned int j;
if (NULL != md->melted_coins) free_melted_coin (&md->melted_coin);
{
for (i=0;i<md->num_melted_coins;i++)
free_melted_coin (&md->melted_coins[i]);
GNUNET_free (md->melted_coins);
}
if (NULL != md->fresh_pks) if (NULL != md->fresh_pks)
{ {
for (i=0;i<md->num_fresh_coins;i++) for (i=0;i<md->num_fresh_coins;i++)
@ -694,13 +681,11 @@ serialize_melt_data (const struct MeltData *md,
mdp->melt_session_hash = md->melt_session_hash; mdp->melt_session_hash = md->melt_session_hash;
for (i=0;i<TALER_CNC_KAPPA;i++) for (i=0;i<TALER_CNC_KAPPA;i++)
mdp->link_secrets[i] = md->link_secrets[i]; mdp->link_secrets[i] = md->link_secrets[i];
mdp->num_melted_coins = htons (md->num_melted_coins);
mdp->num_fresh_coins = htons (md->num_fresh_coins); mdp->num_fresh_coins = htons (md->num_fresh_coins);
} }
for (i=0;i<md->num_melted_coins;i++) size += serialize_melted_coin (&md->melted_coin,
size += serialize_melted_coin (&md->melted_coins[i], buf,
buf, size);
size);
for (i=0;i<md->num_fresh_coins;i++) for (i=0;i<md->num_fresh_coins;i++)
size += serialize_denomination_key (&md->fresh_pks[i], size += serialize_denomination_key (&md->fresh_pks[i],
buf, buf,
@ -744,10 +729,7 @@ deserialize_melt_data (const char *buf,
md->melt_session_hash = mdp.melt_session_hash; md->melt_session_hash = mdp.melt_session_hash;
for (i=0;i<TALER_CNC_KAPPA;i++) for (i=0;i<TALER_CNC_KAPPA;i++)
md->link_secrets[i] = mdp.link_secrets[i]; md->link_secrets[i] = mdp.link_secrets[i];
md->num_melted_coins = ntohs (mdp.num_melted_coins);
md->num_fresh_coins = ntohs (mdp.num_fresh_coins); md->num_fresh_coins = ntohs (mdp.num_fresh_coins);
md->melted_coins = GNUNET_new_array (md->num_melted_coins,
struct MeltedCoin);
md->fresh_pks = GNUNET_new_array (md->num_fresh_coins, md->fresh_pks = GNUNET_new_array (md->num_fresh_coins,
struct TALER_DenominationPublicKey); struct TALER_DenominationPublicKey);
for (i=0;i<TALER_CNC_KAPPA;i++) for (i=0;i<TALER_CNC_KAPPA;i++)
@ -755,11 +737,10 @@ deserialize_melt_data (const char *buf,
struct FreshCoin); struct FreshCoin);
off = sizeof (struct MeltDataP); off = sizeof (struct MeltDataP);
ok = GNUNET_YES; ok = GNUNET_YES;
for (i=0;(i<md->num_melted_coins)&&(GNUNET_YES == ok);i++) off += deserialize_melted_coin (&md->melted_coin,
off += deserialize_melted_coin (&md->melted_coins[i], &buf[off],
&buf[off], buf_size - off,
buf_size - off, &ok);
&ok);
for (i=0;(i<md->num_fresh_coins)&&(GNUNET_YES == ok);i++) for (i=0;(i<md->num_fresh_coins)&&(GNUNET_YES == ok);i++)
off += deserialize_denomination_key (&md->fresh_pks[i], off += deserialize_denomination_key (&md->fresh_pks[i],
&buf[off], &buf[off],
@ -831,17 +812,16 @@ setup_fresh_coin (struct FreshCoin *fc,
* its result immediately and does not start any asynchronous * its result immediately and does not start any asynchronous
* processing. This function is also thread-safe. * processing. This function is also thread-safe.
* *
* @param num_melts number of coins that are being melted (typically 1) * @param melt_priv private key of the coin to melt
* @param melt_privs array of @a num_melts private keys of the coins to melt * @param melt_amount amount specifying how much
* @param melt_amounts array of @a num_melts amounts specifying how much * the coin will contribute to the melt (including fee)
* each coin will contribute to the melt (including fee) * @param melt_sig signature affirming the
* @param melt_sigs array of @a num_melts signatures affirming the
* validity of the public keys corresponding to the * validity of the public keys corresponding to the
* @a melt_privs private keys * @a melt_priv private key
* @param melt_pks array of @a num_melts denomination key information * @param melt_pk denomination key information
* records corresponding to the @a melt_sigs * record corresponding to the @a melt_sig
* validity of the keys * validity of the keys
* @param check_sigs verify the validity of the signatures of @a melt_sigs * @param check_sig verify the validity of the @a melt_sig signature
* @param fresh_pks_len length of the @a pks array * @param fresh_pks_len length of the @a pks array
* @param fresh_pks array of @a pks_len denominations of fresh coins to create * @param fresh_pks array of @a pks_len denominations of fresh coins to create
* @param[out] res_size set to the size of the return value, or 0 on error * @param[out] res_size set to the size of the return value, or 0 on error
@ -852,15 +832,14 @@ setup_fresh_coin (struct FreshCoin *fc,
* Non-null results should be freed using #GNUNET_free(). * Non-null results should be freed using #GNUNET_free().
*/ */
char * char *
TALER_EXCHANGE_refresh_prepare (unsigned int num_melts, TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_priv,
const struct TALER_CoinSpendPrivateKeyP *melt_privs, const struct TALER_Amount *melt_amount,
const struct TALER_Amount *melt_amounts, const struct TALER_DenominationSignature *melt_sig,
const struct TALER_DenominationSignature *melt_sigs, const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
const struct TALER_EXCHANGE_DenomPublicKey *melt_pks, int check_sig,
int check_sigs, unsigned int fresh_pks_len,
unsigned int fresh_pks_len, const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks,
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks, size_t *res_size)
size_t *res_size)
{ {
struct MeltData md; struct MeltData md;
char *buf; char *buf;
@ -873,31 +852,25 @@ TALER_EXCHANGE_refresh_prepare (unsigned int num_melts,
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
&md.link_secrets[i], &md.link_secrets[i],
sizeof (struct TALER_LinkSecretP)); sizeof (struct TALER_LinkSecretP));
md.num_melted_coins = num_melts;
md.num_fresh_coins = fresh_pks_len; md.num_fresh_coins = fresh_pks_len;
md.melted_coins = GNUNET_new_array (num_melts, md.melted_coin.coin_priv = *melt_priv;
struct MeltedCoin); md.melted_coin.melt_amount_with_fee = *melt_amount;
for (i=0;i<num_melts;i++) md.melted_coin.fee_melt = melt_pk->fee_refresh;
md.melted_coin.original_value = melt_pk->value;
for (j=0;j<TALER_CNC_KAPPA;j++)
{ {
md.melted_coins[i].coin_priv = melt_privs[i]; struct GNUNET_CRYPTO_EcdhePrivateKey *tpk;
md.melted_coins[i].melt_amount_with_fee = melt_amounts[i];
md.melted_coins[i].fee_melt = melt_pks[i].fee_refresh;
md.melted_coins[i].original_value = melt_pks[i].value;
for (j=0;j<TALER_CNC_KAPPA;j++)
{
struct GNUNET_CRYPTO_EcdhePrivateKey *tpk;
tpk = GNUNET_CRYPTO_ecdhe_key_create (); tpk = GNUNET_CRYPTO_ecdhe_key_create ();
md.melted_coins[i].transfer_priv[j].ecdhe_priv = *tpk; md.melted_coin.transfer_priv[j].ecdhe_priv = *tpk;
GNUNET_free (tpk); GNUNET_free (tpk);
}
md.melted_coins[i].expire_deposit
= melt_pks[i].expire_deposit;
md.melted_coins[i].pub_key.rsa_public_key
= GNUNET_CRYPTO_rsa_public_key_dup (melt_pks[i].key.rsa_public_key);
md.melted_coins[i].sig.rsa_signature
= GNUNET_CRYPTO_rsa_signature_dup (melt_sigs[i].rsa_signature);
} }
md.melted_coin.expire_deposit
= melt_pk->expire_deposit;
md.melted_coin.pub_key.rsa_public_key
= GNUNET_CRYPTO_rsa_public_key_dup (melt_pk->key.rsa_public_key);
md.melted_coin.sig.rsa_signature
= GNUNET_CRYPTO_rsa_signature_dup (melt_sig->rsa_signature);
md.fresh_pks = GNUNET_new_array (fresh_pks_len, md.fresh_pks = GNUNET_new_array (fresh_pks_len,
struct TALER_DenominationPublicKey); struct TALER_DenominationPublicKey);
for (i=0;i<fresh_pks_len;i++) for (i=0;i<fresh_pks_len;i++)
@ -926,20 +899,19 @@ TALER_EXCHANGE_refresh_prepare (unsigned int num_melts,
buf_size); buf_size);
GNUNET_free (buf); GNUNET_free (buf);
} }
for (i=0;i<num_melts;i++)
{ {
struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_AmountNBO melt_amount; struct TALER_AmountNBO melt_amountn;
GNUNET_CRYPTO_eddsa_key_get_public (&melt_privs[i].eddsa_priv, GNUNET_CRYPTO_eddsa_key_get_public (&melt_priv->eddsa_priv,
&coin_pub.eddsa_pub); &coin_pub.eddsa_pub);
GNUNET_CRYPTO_hash_context_read (hash_context, GNUNET_CRYPTO_hash_context_read (hash_context,
&coin_pub, &coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP)); sizeof (struct TALER_CoinSpendPublicKeyP));
TALER_amount_hton (&melt_amount, TALER_amount_hton (&melt_amountn,
&melt_amounts[i]); melt_amount);
GNUNET_CRYPTO_hash_context_read (hash_context, GNUNET_CRYPTO_hash_context_read (hash_context,
&melt_amount, &melt_amountn,
sizeof (struct TALER_AmountNBO)); sizeof (struct TALER_AmountNBO));
} }
@ -987,23 +959,20 @@ TALER_EXCHANGE_refresh_prepare (unsigned int num_melts,
} }
for (i = 0; i < TALER_CNC_KAPPA; i++) for (i = 0; i < TALER_CNC_KAPPA; i++)
{ {
for (j = 0; j < num_melts; j++) struct TALER_RefreshCommitLinkP rcl;
{ struct TALER_TransferSecretP trans_sec;
struct TALER_RefreshCommitLinkP rcl;
struct TALER_TransferSecretP trans_sec;
GNUNET_CRYPTO_ecdhe_key_get_public (&md.melted_coins[j].transfer_priv[i].ecdhe_priv, GNUNET_CRYPTO_ecdhe_key_get_public (&md.melted_coin.transfer_priv[i].ecdhe_priv,
&rcl.transfer_pub.ecdhe_pub); &rcl.transfer_pub.ecdhe_pub);
TALER_link_derive_transfer_secret (&melt_privs[j], TALER_link_derive_transfer_secret (melt_priv,
&md.melted_coins[j].transfer_priv[i], &md.melted_coin.transfer_priv[i],
&trans_sec); &trans_sec);
TALER_transfer_encrypt (&md.link_secrets[i], TALER_transfer_encrypt (&md.link_secrets[i],
&trans_sec, &trans_sec,
&rcl.shared_secret_enc); &rcl.shared_secret_enc);
GNUNET_CRYPTO_hash_context_read (hash_context, GNUNET_CRYPTO_hash_context_read (hash_context,
&rcl, &rcl,
sizeof (struct TALER_RefreshCommitLinkP)); sizeof (struct TALER_RefreshCommitLinkP));
}
} }
GNUNET_CRYPTO_hash_context_finish (hash_context, GNUNET_CRYPTO_hash_context_finish (hash_context,
@ -1150,7 +1119,6 @@ verify_refresh_melt_signature_forbidden (struct TALER_EXCHANGE_RefreshMeltHandle
struct TALER_Amount melt_value_with_fee; struct TALER_Amount melt_value_with_fee;
struct TALER_Amount total; struct TALER_Amount total;
struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendPublicKeyP coin_pub;
unsigned int i;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("history", &history), GNUNET_JSON_spec_json ("history", &history),
GNUNET_JSON_spec_fixed_auto ("coin_pub", &coin_pub), GNUNET_JSON_spec_fixed_auto ("coin_pub", &coin_pub),
@ -1171,32 +1139,7 @@ verify_refresh_melt_signature_forbidden (struct TALER_EXCHANGE_RefreshMeltHandle
} }
/* Find out which coin was deemed problematic by the exchange */ /* Find out which coin was deemed problematic by the exchange */
mc = NULL; mc = &rmh->md->melted_coin;
for (i=0;i<rmh->md->num_melted_coins;i++)
{
if (0 == TALER_amount_cmp (&melt_value_with_fee,
&rmh->md->melted_coins[i].melt_amount_with_fee))
{
struct TALER_CoinSpendPublicKeyP mc_pub;
GNUNET_CRYPTO_eddsa_key_get_public (&rmh->md->melted_coins[i].coin_priv.eddsa_priv,
&mc_pub.eddsa_pub);
if (0 == memcmp (&mc_pub,
&coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP)))
{
mc = &rmh->md->melted_coins[i];
break;
}
}
}
if (NULL == mc)
{
/* coin not found in our original request */
GNUNET_break_op (0);
json_decref (history);
return GNUNET_SYSERR;
}
/* check basic coin properties */ /* check basic coin properties */
if (0 != TALER_amount_cmp (&original_value, if (0 != TALER_amount_cmp (&original_value,
@ -1410,7 +1353,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
{ {
json_t *melt_obj; json_t *melt_obj;
json_t *new_denoms; json_t *new_denoms;
json_t *melt_coins; json_t *melt_coin;
json_t *coin_evs; json_t *coin_evs;
json_t *transfer_pubs; json_t *transfer_pubs;
json_t *secret_encs; json_t *secret_encs;
@ -1439,63 +1382,43 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
/* build JSON request, each of the 6 arrays first */ /* build JSON request, each of the 6 arrays first */
new_denoms = json_array (); new_denoms = json_array ();
melt_coins = json_array (); melt_coin = melted_coin_to_json (&md->melt_session_hash,
&md->melted_coin);
coin_evs = json_array (); coin_evs = json_array ();
transfer_pubs = json_array (); transfer_pubs = json_array ();
secret_encs = json_array (); secret_encs = json_array ();
link_encs = json_array (); link_encs = json_array ();
for (i=0;i<md->num_melted_coins;i++)
{
const struct MeltedCoin *mc = &md->melted_coins[i];
/* now melt_coins */
json_array_append (melt_coins,
melted_coin_to_json (&md->melt_session_hash,
mc));
}
/* now transfer_pubs */ /* now transfer_pubs */
for (j=0;j<TALER_CNC_KAPPA;j++) for (j=0;j<TALER_CNC_KAPPA;j++)
{ {
tmp = json_array (); const struct MeltedCoin *mc = &md->melted_coin;
for (i=0;i<md->num_melted_coins;i++) struct TALER_TransferPublicKeyP transfer_pub;
{
const struct MeltedCoin *mc = &md->melted_coins[i];
struct TALER_TransferPublicKeyP transfer_pub;
GNUNET_CRYPTO_ecdhe_key_get_public (&mc->transfer_priv[j].ecdhe_priv, GNUNET_CRYPTO_ecdhe_key_get_public (&mc->transfer_priv[j].ecdhe_priv,
&transfer_pub.ecdhe_pub); &transfer_pub.ecdhe_pub);
json_array_append (tmp,
GNUNET_JSON_from_data (&transfer_pub,
sizeof (transfer_pub)));
}
json_array_append (transfer_pubs, json_array_append (transfer_pubs,
tmp); GNUNET_JSON_from_data (&transfer_pub,
sizeof (transfer_pub)));
} }
/* now secret_encs */ /* now secret_encs */
for (j=0;j<TALER_CNC_KAPPA;j++) for (j=0;j<TALER_CNC_KAPPA;j++)
{ {
tmp = json_array (); const struct MeltedCoin *mc = &md->melted_coin;
for (i=0;i<md->num_melted_coins;i++) struct TALER_EncryptedLinkSecretP els;
{ struct TALER_TransferSecretP trans_sec;
const struct MeltedCoin *mc = &md->melted_coins[i];
struct TALER_EncryptedLinkSecretP els;
struct TALER_TransferSecretP trans_sec;
TALER_link_derive_transfer_secret (&mc->coin_priv, TALER_link_derive_transfer_secret (&mc->coin_priv,
&mc->transfer_priv[j], &mc->transfer_priv[j],
&trans_sec); &trans_sec);
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_transfer_encrypt (&md->link_secrets[j], TALER_transfer_encrypt (&md->link_secrets[j],
&trans_sec, &trans_sec,
&els)); &els));
json_array_append (tmp,
GNUNET_JSON_from_data (&els,
sizeof (els)));
}
json_array_append (secret_encs, json_array_append (secret_encs,
tmp); GNUNET_JSON_from_data (&els,
sizeof (els)));
} }
/* now new_denoms */ /* now new_denoms */
@ -1569,7 +1492,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
/* finally, assemble main JSON request from constitutent arrays */ /* finally, assemble main JSON request from constitutent arrays */
melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}", melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}",
"new_denoms", new_denoms, "new_denoms", new_denoms,
"melt_coins", melt_coins, "melt_coin", melt_coin,
"coin_evs", coin_evs, "coin_evs", coin_evs,
"transfer_pubs", transfer_pubs, "transfer_pubs", transfer_pubs,
"secret_encs", secret_encs, "secret_encs", secret_encs,
@ -1907,11 +1830,9 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
struct TALER_EXCHANGE_RefreshRevealHandle *rrh; struct TALER_EXCHANGE_RefreshRevealHandle *rrh;
json_t *transfer_privs; json_t *transfer_privs;
json_t *reveal_obj; json_t *reveal_obj;
json_t *tmp;
CURL *eh; CURL *eh;
struct GNUNET_CURL_Context *ctx; struct GNUNET_CURL_Context *ctx;
struct MeltData *md; struct MeltData *md;
unsigned int i;
unsigned int j; unsigned int j;
if (GNUNET_YES != if (GNUNET_YES !=
@ -1947,17 +1868,9 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
noreval index! */ noreval index! */
continue; continue;
} }
tmp = json_array ();
for (i=0;i<md->num_melted_coins;i++)
{
const struct MeltedCoin *mc = &md->melted_coins[i];
json_array_append (tmp,
GNUNET_JSON_from_data (&mc->transfer_priv[j],
sizeof (struct TALER_TransferPrivateKeyP)));
}
json_array_append (transfer_privs, json_array_append (transfer_privs,
tmp); GNUNET_JSON_from_data (&md->melted_coin.transfer_priv[j],
sizeof (struct TALER_TransferPrivateKeyP)));
} }
/* build main JSON request */ /* build main JSON request */

View File

@ -398,7 +398,7 @@ struct Command
/** /**
* Information about coins to be melted. * Information about coins to be melted.
*/ */
struct MeltDetails *melted_coins; struct MeltDetails melted_coin;
/** /**
* Denominations of the fresh coins to withdraw. * Denominations of the fresh coins to withdraw.
@ -1856,13 +1856,9 @@ interpreter_run (void *cls)
} }
case OC_REFRESH_MELT: case OC_REFRESH_MELT:
{ {
unsigned int num_melted_coins;
unsigned int num_fresh_coins; unsigned int num_fresh_coins;
cmd->details.refresh_melt.noreveal_index = UINT16_MAX; cmd->details.refresh_melt.noreveal_index = UINT16_MAX;
for (num_melted_coins=0;
NULL != cmd->details.refresh_melt.melted_coins[num_melted_coins].amount;
num_melted_coins++) ;
for (num_fresh_coins=0; for (num_fresh_coins=0;
NULL != cmd->details.refresh_melt.fresh_amounts[num_fresh_coins]; NULL != cmd->details.refresh_melt.fresh_amounts[num_fresh_coins];
num_fresh_coins++) ; num_fresh_coins++) ;
@ -1871,36 +1867,33 @@ interpreter_run (void *cls)
= GNUNET_new_array (num_fresh_coins, = GNUNET_new_array (num_fresh_coins,
const struct TALER_EXCHANGE_DenomPublicKey *); const struct TALER_EXCHANGE_DenomPublicKey *);
{ {
struct TALER_CoinSpendPrivateKeyP melt_privs[num_melted_coins]; struct TALER_CoinSpendPrivateKeyP melt_priv;
struct TALER_Amount melt_amounts[num_melted_coins]; struct TALER_Amount melt_amount;
struct TALER_DenominationSignature melt_sigs[num_melted_coins]; struct TALER_DenominationSignature melt_sig;
struct TALER_EXCHANGE_DenomPublicKey melt_pks[num_melted_coins]; struct TALER_EXCHANGE_DenomPublicKey melt_pk;
struct TALER_EXCHANGE_DenomPublicKey fresh_pks[num_fresh_coins]; struct TALER_EXCHANGE_DenomPublicKey fresh_pks[num_fresh_coins];
unsigned int i; unsigned int i;
for (i=0;i<num_melted_coins;i++) const struct MeltDetails *md = &cmd->details.refresh_melt.melted_coin;
{ ref = find_command (is,
const struct MeltDetails *md = &cmd->details.refresh_melt.melted_coins[i]; md->coin_ref);
ref = find_command (is, GNUNET_assert (NULL != ref);
md->coin_ref); GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
melt_privs[i] = ref->details.reserve_withdraw.coin_priv; melt_priv = ref->details.reserve_withdraw.coin_priv;
if (GNUNET_OK != if (GNUNET_OK !=
TALER_string_to_amount (md->amount, TALER_string_to_amount (md->amount,
&melt_amounts[i])) &melt_amount))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse amount `%s' at %u\n", "Failed to parse amount `%s' at %u\n",
md->amount, md->amount,
is->ip); is->ip);
fail (is); fail (is);
return; return;
}
melt_sigs[i] = ref->details.reserve_withdraw.sig;
melt_pks[i] = *ref->details.reserve_withdraw.pk;
} }
melt_sig = ref->details.reserve_withdraw.sig;
melt_pk = *ref->details.reserve_withdraw.pk;
for (i=0;i<num_fresh_coins;i++) for (i=0;i<num_fresh_coins;i++)
{ {
if (GNUNET_OK != if (GNUNET_OK !=
@ -1920,15 +1913,14 @@ interpreter_run (void *cls)
fresh_pks[i] = *cmd->details.refresh_melt.fresh_pks[i]; fresh_pks[i] = *cmd->details.refresh_melt.fresh_pks[i];
} }
cmd->details.refresh_melt.refresh_data cmd->details.refresh_melt.refresh_data
= TALER_EXCHANGE_refresh_prepare (num_melted_coins, = TALER_EXCHANGE_refresh_prepare (&melt_priv,
melt_privs, &melt_amount,
melt_amounts, &melt_sig,
melt_sigs, &melt_pk,
melt_pks, GNUNET_YES,
GNUNET_YES, num_fresh_coins,
num_fresh_coins, fresh_pks,
fresh_pks, &cmd->details.refresh_melt.refresh_data_length);
&cmd->details.refresh_melt.refresh_data_length);
if (NULL == cmd->details.refresh_melt.refresh_data) if (NULL == cmd->details.refresh_melt.refresh_data)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -1979,16 +1971,9 @@ interpreter_run (void *cls)
GNUNET_assert (NULL != ref); GNUNET_assert (NULL != ref);
/* find reserve_withdraw command */ /* find reserve_withdraw command */
{ {
unsigned int idx;
const struct MeltDetails *md; const struct MeltDetails *md;
unsigned int num_melted_coins;
for (num_melted_coins=0; md = &ref->details.refresh_melt.melted_coin;
NULL != ref->details.refresh_melt.melted_coins[num_melted_coins].amount;
num_melted_coins++) ;
idx = cmd->details.refresh_link.coin_idx;
GNUNET_assert (idx < num_melted_coins);
md = &ref->details.refresh_melt.melted_coins[idx];
ref = find_command (is, ref = find_command (is,
md->coin_ref); md->coin_ref);
GNUNET_assert (NULL != ref); GNUNET_assert (NULL != ref);
@ -2465,11 +2450,6 @@ static void
run (void *cls) run (void *cls)
{ {
struct InterpreterState *is; struct InterpreterState *is;
static struct MeltDetails melt_coins_1[] = {
{ .amount = "EUR:4",
.coin_ref = "refresh-withdraw-coin-1" },
{ NULL, NULL }
};
static const char *melt_fresh_amounts_1[] = { static const char *melt_fresh_amounts_1[] = {
"EUR:1", "EUR:1",
"EUR:1", "EUR:1",
@ -2613,7 +2593,9 @@ run (void *cls)
{ .oc = OC_REFRESH_MELT, { .oc = OC_REFRESH_MELT,
.label = "refresh-melt-1", .label = "refresh-melt-1",
.expected_response_code = MHD_HTTP_OK, .expected_response_code = MHD_HTTP_OK,
.details.refresh_melt.melted_coins = melt_coins_1, .details.refresh_melt.melted_coin = {
.amount = "EUR:4",
.coin_ref = "refresh-withdraw-coin-1" },
.details.refresh_melt.fresh_amounts = melt_fresh_amounts_1 }, .details.refresh_melt.fresh_amounts = melt_fresh_amounts_1 },
@ -2658,7 +2640,9 @@ run (void *cls)
{ .oc = OC_REFRESH_MELT, { .oc = OC_REFRESH_MELT,
.label = "refresh-melt-failing", .label = "refresh-melt-failing",
.expected_response_code = MHD_HTTP_FORBIDDEN, .expected_response_code = MHD_HTTP_FORBIDDEN,
.details.refresh_melt.melted_coins = melt_coins_1, .details.refresh_melt.melted_coin = {
.amount = "EUR:4",
.coin_ref = "refresh-withdraw-coin-1" },
.details.refresh_melt.fresh_amounts = melt_fresh_amounts_1 }, .details.refresh_melt.fresh_amounts = melt_fresh_amounts_1 },
// FIXME: also test with coin that was already melted // FIXME: also test with coin that was already melted

View File

@ -868,18 +868,18 @@ TMH_DB_execute_reserve_withdraw (struct MHD_Connection *connection,
* @param key_state the exchange's key state * @param key_state the exchange's key state
* @param session_hash hash identifying the refresh session * @param session_hash hash identifying the refresh session
* @param coin_details details about the coin being melted * @param coin_details details about the coin being melted
* @param oldcoin_index what is the number assigned to this coin * @param[out] meltp on success, set to melt details
* @return #GNUNET_OK on success, * @return #GNUNET_OK on success,
* #GNUNET_NO if an error message was generated, * #GNUNET_NO if an error message was generated,
* #GNUNET_SYSERR on internal errors (no response generated) * #GNUNET_SYSERR on internal errors (no response generated)
*/ */
static int static int
refresh_accept_melts (struct MHD_Connection *connection, refresh_check_melt (struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct TMH_KS_StateHandle *key_state, const struct TMH_KS_StateHandle *key_state,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
const struct TMH_DB_MeltDetails *coin_details, const struct TMH_DB_MeltDetails *coin_details,
uint16_t oldcoin_index) struct TALER_EXCHANGEDB_RefreshMelt *meltp)
{ {
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dk; struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dk;
struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki; struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
@ -887,7 +887,6 @@ refresh_accept_melts (struct MHD_Connection *connection,
struct TALER_Amount coin_value; struct TALER_Amount coin_value;
struct TALER_Amount coin_residual; struct TALER_Amount coin_residual;
struct TALER_Amount spent; struct TALER_Amount spent;
struct TALER_EXCHANGEDB_RefreshMelt melt;
int res; int res;
dk = TMH_KS_denomination_key_lookup (key_state, dk = TMH_KS_denomination_key_lookup (key_state,
@ -943,22 +942,11 @@ refresh_accept_melts (struct MHD_Connection *connection,
TMH_plugin->free_coin_transaction_list (TMH_plugin->cls, TMH_plugin->free_coin_transaction_list (TMH_plugin->cls,
tl); tl);
melt.coin = coin_details->coin_info; meltp->coin = coin_details->coin_info;
melt.coin_sig = coin_details->melt_sig; meltp->coin_sig = coin_details->melt_sig;
melt.session_hash = *session_hash; meltp->session_hash = *session_hash;
melt.amount_with_fee = coin_details->melt_amount_with_fee; meltp->amount_with_fee = coin_details->melt_amount_with_fee;
melt.melt_fee = coin_details->melt_fee; meltp->melt_fee = coin_details->melt_fee;
if (GNUNET_OK !=
TMH_plugin->insert_refresh_melt (TMH_plugin->cls,
session,
oldcoin_index,
&melt))
{
GNUNET_break (0);
return (MHD_YES ==
TMH_RESPONSE_reply_internal_db_error (connection))
? GNUNET_NO : GNUNET_SYSERR;
}
return GNUNET_OK; return GNUNET_OK;
} }
@ -974,15 +962,13 @@ refresh_accept_melts (struct MHD_Connection *connection,
* @param session_hash hash code of the session the coins are melted into * @param session_hash hash code of the session the coins are melted into
* @param num_new_denoms number of entries in @a denom_pubs, size of y-dimension of @a commit_coin array * @param num_new_denoms number of entries in @a denom_pubs, size of y-dimension of @a commit_coin array
* @param denom_pubs public keys of the coins we want to withdraw in the end * @param denom_pubs public keys of the coins we want to withdraw in the end
* @param coin_count number of entries in @a coin_melt_details, size of y-dimension of @a commit_link array * @param coin_melt_detail signature and (residual) value of the respective coin should be melted
* @param coin_melt_details signatures and (residual) value of the respective coin should be melted
* @param commit_coin 2d array of coin commitments (what the exchange is to sign * @param commit_coin 2d array of coin commitments (what the exchange is to sign
* once the "/refres/reveal" of cut and choose is done), * once the "/refres/reveal" of cut and choose is done),
* x-dimension must be #TALER_CNC_KAPPA * x-dimension must be #TALER_CNC_KAPPA
* @param commit_link 2d array of coin link commitments (what the exchange is * @param commit_link array of coin link commitments (what the exchange is
* to return via "/refresh/link" to enable linkage in the * to return via "/refresh/link" to enable linkage in the
* future) * future) of length #TALER_CNC_KAPPA
* x-dimension must be #TALER_CNC_KAPPA
* @return MHD result code * @return MHD result code
*/ */
int int
@ -990,10 +976,9 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
unsigned int num_new_denoms, unsigned int num_new_denoms,
const struct TALER_DenominationPublicKey *denom_pubs, const struct TALER_DenominationPublicKey *denom_pubs,
unsigned int coin_count, const struct TMH_DB_MeltDetails *coin_melt_detail,
const struct TMH_DB_MeltDetails *coin_melt_details,
struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin, struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin,
struct TALER_RefreshCommitLinkP *const* commit_link) const struct TALER_RefreshCommitLinkP *commit_link)
{ {
struct TMH_KS_StateHandle *key_state; struct TMH_KS_StateHandle *key_state;
struct TALER_EXCHANGEDB_RefreshSession refresh_session; struct TALER_EXCHANGEDB_RefreshSession refresh_session;
@ -1028,11 +1013,26 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
} }
/* store 'global' session data */ /* store 'global' session data */
refresh_session.num_oldcoins = coin_count;
refresh_session.num_newcoins = num_new_denoms; refresh_session.num_newcoins = num_new_denoms;
refresh_session.noreveal_index refresh_session.noreveal_index
= GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
TALER_CNC_KAPPA); TALER_CNC_KAPPA);
key_state = TMH_KS_acquire ();
if (GNUNET_OK !=
(res = refresh_check_melt (connection,
session,
key_state,
session_hash,
coin_melt_detail,
&refresh_session.melt)))
{
TMH_KS_release (key_state);
TMH_plugin->rollback (TMH_plugin->cls,
session);
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
TMH_KS_release (key_state);
if (GNUNET_OK != if (GNUNET_OK !=
(res = TMH_plugin->create_refresh_session (TMH_plugin->cls, (res = TMH_plugin->create_refresh_session (TMH_plugin->cls,
session, session,
@ -1044,26 +1044,6 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
return TMH_RESPONSE_reply_internal_db_error (connection); return TMH_RESPONSE_reply_internal_db_error (connection);
} }
/* Melt old coins and check that they had enough residual value */
key_state = TMH_KS_acquire ();
for (i=0;i<coin_count;i++)
{
if (GNUNET_OK !=
(res = refresh_accept_melts (connection,
session,
key_state,
session_hash,
&coin_melt_details[i],
i)))
{
TMH_KS_release (key_state);
TMH_plugin->rollback (TMH_plugin->cls,
session);
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
}
TMH_KS_release (key_state);
/* store requested new denominations */ /* store requested new denominations */
if (GNUNET_OK != if (GNUNET_OK !=
TMH_plugin->insert_refresh_order (TMH_plugin->cls, TMH_plugin->insert_refresh_order (TMH_plugin->cls,
@ -1095,12 +1075,11 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
for (i = 0; i < TALER_CNC_KAPPA; i++) for (i = 0; i < TALER_CNC_KAPPA; i++)
{ {
if (GNUNET_OK != if (GNUNET_OK !=
TMH_plugin->insert_refresh_commit_links (TMH_plugin->cls, TMH_plugin->insert_refresh_commit_link (TMH_plugin->cls,
session, session,
session_hash, session_hash,
i, i,
coin_count, &commit_link[i]))
commit_link[i]))
{ {
TMH_plugin->rollback (TMH_plugin->cls, TMH_plugin->rollback (TMH_plugin->cls,
session); session);
@ -1122,8 +1101,9 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param session database connection to use * @param session database connection to use
* @param session_hash hash of session to query * @param session_hash hash of session to query
* @param rm details about the original melt
* @param off commitment offset to check * @param off commitment offset to check
* @param index index of the mismatch * @param index index of the mismatch, UINT_MAX if there is no such index
* @param object_name name of the object with the problem * @param object_name name of the object with the problem
* @return #GNUNET_NO if we generated the error message * @return #GNUNET_NO if we generated the error message
* #GNUNET_SYSERR if we could not even generate an error message * #GNUNET_SYSERR if we could not even generate an error message
@ -1132,6 +1112,7 @@ static int
send_melt_commitment_error (struct MHD_Connection *connection, send_melt_commitment_error (struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
const struct TALER_EXCHANGEDB_RefreshMelt *rm,
unsigned int off, unsigned int off,
unsigned int index, unsigned int index,
const char *object_name) const char *object_name)
@ -1152,6 +1133,7 @@ send_melt_commitment_error (struct MHD_Connection *connection,
} }
ret = (MHD_YES == ret = (MHD_YES ==
TMH_RESPONSE_reply_refresh_reveal_missmatch (connection, TMH_RESPONSE_reply_refresh_reveal_missmatch (connection,
rm,
mc, mc,
off, off,
index, index,
@ -1173,9 +1155,8 @@ send_melt_commitment_error (struct MHD_Connection *connection,
* @param session database connection to use * @param session database connection to use
* @param session_hash hash of session to query * @param session_hash hash of session to query
* @param off commitment offset to check * @param off commitment offset to check
* @param num_oldcoins size of the @a transfer_privs and @a melts arrays * @param transfer_priv private transfer key
* @param transfer_privs private transfer keys * @param melt information about the melted coin
* @param melts array of melted coins
* @param num_newcoins number of newcoins being generated * @param num_newcoins number of newcoins being generated
* @param denom_pubs array of @a num_newcoins keys for the new coins * @param denom_pubs array of @a num_newcoins keys for the new coins
* @return #GNUNET_OK if the committment was honest, * @return #GNUNET_OK if the committment was honest,
@ -1187,91 +1168,58 @@ check_commitment (struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
unsigned int off, unsigned int off,
unsigned int num_oldcoins, const struct TALER_TransferPrivateKeyP *transfer_priv,
const struct TALER_TransferPrivateKeyP *transfer_privs, const struct TALER_EXCHANGEDB_RefreshMelt *melt,
const struct TALER_EXCHANGEDB_RefreshMelt *melts,
unsigned int num_newcoins, unsigned int num_newcoins,
const struct TALER_DenominationPublicKey *denom_pubs) const struct TALER_DenominationPublicKey *denom_pubs)
{ {
unsigned int j; struct TALER_RefreshCommitLinkP commit_link;
struct TALER_LinkSecretP last_shared_secret; struct TALER_LinkSecretP shared_secret;
int secret_initialized = GNUNET_NO; struct TALER_TransferPublicKeyP transfer_pub_check;
struct TALER_RefreshCommitLinkP *commit_links;
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins; struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins;
unsigned int j;
commit_links = GNUNET_malloc (num_oldcoins *
sizeof (struct TALER_RefreshCommitLinkP));
if (GNUNET_OK != if (GNUNET_OK !=
TMH_plugin->get_refresh_commit_links (TMH_plugin->cls, TMH_plugin->get_refresh_commit_link (TMH_plugin->cls,
session, session,
session_hash, session_hash,
off, off,
num_oldcoins, &commit_link))
commit_links))
{ {
GNUNET_break (0); GNUNET_break (0);
GNUNET_free (commit_links);
return (MHD_YES == TMH_RESPONSE_reply_internal_db_error (connection)) return (MHD_YES == TMH_RESPONSE_reply_internal_db_error (connection))
? GNUNET_NO : GNUNET_SYSERR; ? GNUNET_NO : GNUNET_SYSERR;
} }
for (j = 0; j < num_oldcoins; j++) GNUNET_CRYPTO_ecdhe_key_get_public (&transfer_priv->ecdhe_priv,
&transfer_pub_check.ecdhe_pub);
if (0 !=
memcmp (&transfer_pub_check,
&commit_link.transfer_pub,
sizeof (struct TALER_TransferPublicKeyP)))
{ {
struct TALER_LinkSecretP shared_secret; GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
struct TALER_TransferPublicKeyP transfer_pub_check; "transfer keys do not match\n");
return send_melt_commitment_error (connection,
GNUNET_CRYPTO_ecdhe_key_get_public (&transfer_privs[j].ecdhe_priv, session,
&transfer_pub_check.ecdhe_pub); session_hash,
if (0 != melt,
memcmp (&transfer_pub_check, off,
&commit_links[j].transfer_pub, UINT_MAX,
sizeof (struct TALER_TransferPublicKeyP))) "transfer key");
{ }
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"transfer keys do not match\n"); if (GNUNET_OK !=
GNUNET_free (commit_links); TALER_link_decrypt_secret (&commit_link.shared_secret_enc,
return send_melt_commitment_error (connection, transfer_priv,
session, &melt->coin.coin_pub,
session_hash, &shared_secret))
off, {
j, return (MHD_YES ==
"transfer key"); TMH_RESPONSE_reply_internal_error (connection,
} "Transfer secret decryption error"))
? GNUNET_NO : GNUNET_SYSERR;
if (GNUNET_OK !=
TALER_link_decrypt_secret (&commit_links[j].shared_secret_enc,
&transfer_privs[j],
&melts[j].coin.coin_pub,
&shared_secret))
{
GNUNET_free (commit_links);
return (MHD_YES ==
TMH_RESPONSE_reply_internal_error (connection,
"Transfer secret decryption error"))
? GNUNET_NO : GNUNET_SYSERR;
}
if (GNUNET_NO == secret_initialized)
{
secret_initialized = GNUNET_YES;
last_shared_secret = shared_secret;
}
else if (0 != memcmp (&shared_secret,
&last_shared_secret,
sizeof (struct GNUNET_HashCode)))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"shared secrets do not match\n");
GNUNET_free (commit_links);
return send_melt_commitment_error (connection,
session,
session_hash,
off,
j,
"transfer secret");
}
} }
GNUNET_break (GNUNET_YES == secret_initialized);
GNUNET_free (commit_links);
/* Check that the commitments for all new coins were correct */ /* Check that the commitments for all new coins were correct */
commit_coins = GNUNET_malloc (num_newcoins * commit_coins = GNUNET_malloc (num_newcoins *
@ -1300,7 +1248,7 @@ check_commitment (struct MHD_Connection *connection,
size_t buf_len; size_t buf_len;
link_data = TALER_refresh_decrypt (commit_coins[j].refresh_link, link_data = TALER_refresh_decrypt (commit_coins[j].refresh_link,
&last_shared_secret); &shared_secret);
if (NULL == link_data) if (NULL == link_data)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -1342,6 +1290,7 @@ check_commitment (struct MHD_Connection *connection,
return send_melt_commitment_error (connection, return send_melt_commitment_error (connection,
session, session,
session_hash, session_hash,
melt,
off, off,
j, j,
"envelope"); "envelope");
@ -1422,7 +1371,6 @@ refresh_exchange_coin (struct MHD_Connection *connection,
* @param session database session * @param session database session
* @param session_hash hash identifying the refresh session * @param session_hash hash identifying the refresh session
* @param refresh_session information about the refresh operation we are doing * @param refresh_session information about the refresh operation we are doing
* @param melts array of "num_oldcoins" with information about melted coins
* @param denom_pubs array of "num_newcoins" denomination keys for the new coins * @param denom_pubs array of "num_newcoins" denomination keys for the new coins
* @param[out] ev_sigs where to store generated signatures for the new coins, * @param[out] ev_sigs where to store generated signatures for the new coins,
* array of length "num_newcoins", memory released by the * array of length "num_newcoins", memory released by the
@ -1436,7 +1384,6 @@ execute_refresh_reveal_transaction (struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
const struct TALER_EXCHANGEDB_RefreshSession *refresh_session, const struct TALER_EXCHANGEDB_RefreshSession *refresh_session,
const struct TALER_EXCHANGEDB_RefreshMelt *melts,
const struct TALER_DenominationPublicKey *denom_pubs, const struct TALER_DenominationPublicKey *denom_pubs,
struct TALER_DenominationSignature *ev_sigs, struct TALER_DenominationSignature *ev_sigs,
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins) struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins)
@ -1461,12 +1408,12 @@ execute_refresh_reveal_transaction (struct MHD_Connection *connection,
{ {
if (NULL == ev_sigs[j].rsa_signature) /* could be non-NULL during retries */ if (NULL == ev_sigs[j].rsa_signature) /* could be non-NULL during retries */
ev_sigs[j] = refresh_exchange_coin (connection, ev_sigs[j] = refresh_exchange_coin (connection,
session, session,
session_hash, session_hash,
key_state, key_state,
&denom_pubs[j], &denom_pubs[j],
&commit_coins[j], &commit_coins[j],
j); j);
if (NULL == ev_sigs[j].rsa_signature) if (NULL == ev_sigs[j].rsa_signature)
{ {
TMH_KS_release (key_state); TMH_KS_release (key_state);
@ -1490,21 +1437,18 @@ execute_refresh_reveal_transaction (struct MHD_Connection *connection,
* *
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param session_hash hash identifying the refresh session * @param session_hash hash identifying the refresh session
* @param num_oldcoins size of y-dimension of @a transfer_privs array
* @param transfer_privs array with the revealed transfer keys, * @param transfer_privs array with the revealed transfer keys,
* x-dimension must be #TALER_CNC_KAPPA - 1 * length must be #TALER_CNC_KAPPA - 1
* @return MHD result code * @return MHD result code
*/ */
int int
TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
unsigned int num_oldcoins, struct TALER_TransferPrivateKeyP *transfer_privs)
struct TALER_TransferPrivateKeyP **transfer_privs)
{ {
int res; int res;
struct TALER_EXCHANGEDB_Session *session; struct TALER_EXCHANGEDB_Session *session;
struct TALER_EXCHANGEDB_RefreshSession refresh_session; struct TALER_EXCHANGEDB_RefreshSession refresh_session;
struct TALER_EXCHANGEDB_RefreshMelt *melts;
struct TALER_DenominationPublicKey *denom_pubs; struct TALER_DenominationPublicKey *denom_pubs;
struct TALER_DenominationSignature *ev_sigs; struct TALER_DenominationSignature *ev_sigs;
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins; struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins;
@ -1527,33 +1471,6 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
"session_hash"); "session_hash");
if (GNUNET_SYSERR == res) if (GNUNET_SYSERR == res)
return TMH_RESPONSE_reply_internal_db_error (connection); return TMH_RESPONSE_reply_internal_db_error (connection);
if (0 == refresh_session.num_oldcoins)
{
GNUNET_break (0);
return TMH_RESPONSE_reply_internal_db_error (connection);
}
melts = GNUNET_malloc (refresh_session.num_oldcoins *
sizeof (struct TALER_EXCHANGEDB_RefreshMelt));
for (j=0;j<refresh_session.num_oldcoins;j++)
{
if (GNUNET_OK !=
TMH_plugin->get_refresh_melt (TMH_plugin->cls,
session,
session_hash,
j,
&melts[j]))
{
GNUNET_break (0);
for (i=0;i<j;i++)
{
GNUNET_CRYPTO_rsa_signature_free (melts[i].coin.denom_sig.rsa_signature);
GNUNET_CRYPTO_rsa_public_key_free (melts[i].coin.denom_pub.rsa_public_key);
}
GNUNET_free (melts);
return TMH_RESPONSE_reply_internal_db_error (connection);
}
}
denom_pubs = GNUNET_malloc (refresh_session.num_newcoins * denom_pubs = GNUNET_malloc (refresh_session.num_newcoins *
sizeof (struct TALER_DenominationPublicKey)); sizeof (struct TALER_DenominationPublicKey));
if (GNUNET_OK != if (GNUNET_OK !=
@ -1565,12 +1482,8 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
{ {
GNUNET_break (0); GNUNET_break (0);
GNUNET_free (denom_pubs); GNUNET_free (denom_pubs);
for (i=0;i<refresh_session.num_oldcoins;i++) GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature);
{ GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key);
GNUNET_CRYPTO_rsa_signature_free (melts[i].coin.denom_sig.rsa_signature);
GNUNET_CRYPTO_rsa_public_key_free (melts[i].coin.denom_pub.rsa_public_key);
}
GNUNET_free (melts);
return (MHD_YES == TMH_RESPONSE_reply_internal_db_error (connection)) return (MHD_YES == TMH_RESPONSE_reply_internal_db_error (connection))
? GNUNET_NO : GNUNET_SYSERR; ? GNUNET_NO : GNUNET_SYSERR;
} }
@ -1586,30 +1499,19 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
session, session,
session_hash, session_hash,
i + off, i + off,
refresh_session.num_oldcoins, &transfer_privs[i],
transfer_privs[i], &refresh_session.melt,
melts,
refresh_session.num_newcoins, refresh_session.num_newcoins,
denom_pubs))) denom_pubs)))
{ {
for (j=0;j<refresh_session.num_newcoins;j++) for (j=0;j<refresh_session.num_newcoins;j++)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key); GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
GNUNET_free (denom_pubs); GNUNET_free (denom_pubs);
for (i=0;i<refresh_session.num_oldcoins;i++) GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature);
{ GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key);
GNUNET_CRYPTO_rsa_signature_free (melts[i].coin.denom_sig.rsa_signature);
GNUNET_CRYPTO_rsa_public_key_free (melts[i].coin.denom_pub.rsa_public_key);
}
GNUNET_free (melts);
return (GNUNET_NO == res) ? MHD_YES : MHD_NO; return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
} }
} }
for (i=0;i<refresh_session.num_oldcoins;i++)
{
GNUNET_CRYPTO_rsa_signature_free (melts[i].coin.denom_sig.rsa_signature);
GNUNET_CRYPTO_rsa_public_key_free (melts[i].coin.denom_pub.rsa_public_key);
}
GNUNET_free (melts);
/* Client request OK, start transaction */ /* Client request OK, start transaction */
commit_coins = GNUNET_malloc (refresh_session.num_newcoins * commit_coins = GNUNET_malloc (refresh_session.num_newcoins *
@ -1620,7 +1522,6 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
session, session,
session_hash, session_hash,
&refresh_session, &refresh_session,
melts,
denom_pubs, denom_pubs,
ev_sigs, ev_sigs,
commit_coins); commit_coins);
@ -1630,6 +1531,8 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
for (j=0;j<refresh_session.num_newcoins;j++) for (j=0;j<refresh_session.num_newcoins;j++)
if (NULL != denom_pubs[j].rsa_public_key) if (NULL != denom_pubs[j].rsa_public_key)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key); GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
GNUNET_CRYPTO_rsa_signature_free (refresh_session.melt.coin.denom_sig.rsa_signature);
GNUNET_CRYPTO_rsa_public_key_free (refresh_session.melt.coin.denom_pub.rsa_public_key);
GNUNET_free (ev_sigs); GNUNET_free (ev_sigs);
GNUNET_free (denom_pubs); GNUNET_free (denom_pubs);
GNUNET_free (commit_coins); GNUNET_free (commit_coins);

View File

@ -133,13 +133,12 @@ struct TMH_DB_MeltDetails
* @param session_hash hash code of the session the coins are melted into * @param session_hash hash code of the session the coins are melted into
* @param num_new_denoms number of entries in @a denom_pubs, size of y-dimension of @a commit_coin array * @param num_new_denoms number of entries in @a denom_pubs, size of y-dimension of @a commit_coin array
* @param denom_pubs array of public denomination keys for the refresh (?) * @param denom_pubs array of public denomination keys for the refresh (?)
* @param coin_count number of entries in @ a coin_melt_details, size of y-dimension of @a commit_link array
* @param coin_melt_details signatures and (residual) value of and information about the respective coin to be melted * @param coin_melt_details signatures and (residual) value of and information about the respective coin to be melted
* @param commit_coin 2d array of coin commitments (what the exchange is to sign * @param commit_coin 2d array of coin commitments (what the exchange is to sign
* once the "/refres/reveal" of cut and choose is done) * once the "/refres/reveal" of cut and choose is done)
* @param commit_link 2d array of coin link commitments (what the exchange is * @param commit_link array of coin link commitments (what the exchange is
* to return via "/refresh/link" to enable linkage in the * to return via "/refresh/link" to enable linkage in the
* future) * future) of length #TALER_CNC_KAPPA
* @return MHD result code * @return MHD result code
*/ */
int int
@ -147,10 +146,9 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
unsigned int num_new_denoms, unsigned int num_new_denoms,
const struct TALER_DenominationPublicKey *denom_pubs, const struct TALER_DenominationPublicKey *denom_pubs,
unsigned int coin_count,
const struct TMH_DB_MeltDetails *coin_melt_details, const struct TMH_DB_MeltDetails *coin_melt_details,
struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin, struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin,
struct TALER_RefreshCommitLinkP *const* commit_link); const struct TALER_RefreshCommitLinkP *commit_link);
/** /**
@ -162,15 +160,13 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
* *
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param session_hash hash over the refresh session * @param session_hash hash over the refresh session
* @param num_oldcoins size of y-dimension of @a transfer_privs array * @param transfer_privs array of length #TALER_CNC_KAPPA-1 with the revealed transfer keys
* @param transfer_privs array with the revealed transfer keys, #TALER_CNC_KAPPA is 1st-dimension
* @return MHD result code * @return MHD result code
*/ */
int int
TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
unsigned int num_oldcoins, struct TALER_TransferPrivateKeyP *transfer_privs);
struct TALER_TransferPrivateKeyP **transfer_privs);
/** /**

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014, 2015 GNUnet e.V. Copyright (C) 2014, 2015, 2016 Inria & GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -39,25 +39,23 @@
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param num_new_denoms number of coins to be created, size of y-dimension of @a commit_link array * @param num_new_denoms number of coins to be created, size of y-dimension of @a commit_link array
* @param denom_pubs array of @a num_new_denoms keys * @param denom_pubs array of @a num_new_denoms keys
* @param coin_count number of coins to be melted, size of y-dimension of @a commit_coin array * @param coin_melt_details melting details
* @param coin_melt_details array with @a coin_count entries with melting details
* @param session_hash hash over the data that the client commits to * @param session_hash hash over the data that the client commits to
* @param commit_coin 2d array of coin commitments (what the exchange is to sign * @param commit_coin 2d array of coin commitments (what the exchange is to sign
* once the "/refres/reveal" of cut and choose is done) * once the "/refres/reveal" of cut and choose is done)
* @param commit_link 2d array of coin link commitments (what the exchange is * @param commit_link array of coin link commitments (what the exchange is
* to return via "/refresh/link" to enable linkage in the * to return via "/refresh/link" to enable linkage in the
* future) * future) of length #TALER_CNC_KAPPA
* @return MHD result code * @return MHD result code
*/ */
static int static int
handle_refresh_melt_binary (struct MHD_Connection *connection, handle_refresh_melt_binary (struct MHD_Connection *connection,
unsigned int num_new_denoms, unsigned int num_new_denoms,
const struct TALER_DenominationPublicKey *denom_pubs, const struct TALER_DenominationPublicKey *denom_pubs,
unsigned int coin_count,
const struct TMH_DB_MeltDetails *coin_melt_details, const struct TMH_DB_MeltDetails *coin_melt_details,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin, struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin,
struct TALER_RefreshCommitLinkP *const* commit_link) const struct TALER_RefreshCommitLinkP * commit_link)
{ {
unsigned int i; unsigned int i;
struct TMH_KS_StateHandle *key_state; struct TMH_KS_StateHandle *key_state;
@ -65,7 +63,6 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki; struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
struct TALER_Amount cost; struct TALER_Amount cost;
struct TALER_Amount total_cost; struct TALER_Amount total_cost;
struct TALER_Amount melt;
struct TALER_Amount value; struct TALER_Amount value;
struct TALER_Amount fee_withdraw; struct TALER_Amount fee_withdraw;
struct TALER_Amount fee_melt; struct TALER_Amount fee_melt;
@ -108,45 +105,27 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
} }
} }
GNUNET_assert (GNUNET_OK == dk = TMH_KS_denomination_key_lookup (key_state,
TALER_amount_get_zero (TMH_exchange_currency_string, &coin_melt_details->coin_info.denom_pub,
&total_melt)); TMH_KS_DKU_DEPOSIT);
for (i=0;i<coin_count;i++) if (NULL == dk)
{ {
/* calculate contribution of the i-th melt by subtracting GNUNET_break (0);
the fee; add the rest to the total_melt value */ return TMH_RESPONSE_reply_arg_invalid (connection,
dk = TMH_KS_denomination_key_lookup (key_state, "denom_pub");
&coin_melt_details[i].coin_info.denom_pub, }
TMH_KS_DKU_DEPOSIT); dki = &dk->issue;
if (NULL == dk) TALER_amount_ntoh (&fee_melt,
{ &dki->properties.fee_refresh);
GNUNET_break (0); if (GNUNET_OK !=
return TMH_RESPONSE_reply_arg_invalid (connection, TALER_amount_subtract (&total_melt,
"denom_pub"); &coin_melt_details->melt_amount_with_fee,
} &fee_melt))
dki = &dk->issue; {
TALER_amount_ntoh (&fee_melt, GNUNET_break_op (0);
&dki->properties.fee_refresh); TMH_KS_release (key_state);
if (GNUNET_OK != return TMH_RESPONSE_reply_external_error (connection,
TALER_amount_subtract (&melt, "Melt contribution below melting fee");
&coin_melt_details->melt_amount_with_fee,
&fee_melt))
{
GNUNET_break_op (0);
TMH_KS_release (key_state);
return TMH_RESPONSE_reply_external_error (connection,
"Melt contribution below melting fee");
}
if (GNUNET_OK !=
TALER_amount_add (&total_melt,
&melt,
&total_melt))
{
GNUNET_break_op (0);
TMH_KS_release (key_state);
return TMH_RESPONSE_reply_internal_error (connection,
"balance calculation failure");
}
} }
TMH_KS_release (key_state); TMH_KS_release (key_state);
if (0 != if (0 !=
@ -165,7 +144,6 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
session_hash, session_hash,
num_new_denoms, num_new_denoms,
denom_pubs, denom_pubs,
coin_count,
coin_melt_details, coin_melt_details,
commit_coin, commit_coin,
commit_link); commit_link);
@ -184,7 +162,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
*/ */
static int static int
get_coin_public_info (struct MHD_Connection *connection, get_coin_public_info (struct MHD_Connection *connection,
json_t *coin_info, const json_t *coin_info,
struct TMH_DB_MeltDetails *r_melt_detail) struct TMH_DB_MeltDetails *r_melt_detail)
{ {
int ret; int ret;
@ -335,29 +313,6 @@ free_commit_coins (struct TALER_EXCHANGEDB_RefreshCommitCoin **commit_coin,
} }
/**
* Release memory from the @a commit_link array.
*
* @param commit_link array to release
* @param kappa size of 1st dimension
* @param num_old_coins size of 2nd dimension
*/
static void
free_commit_links (struct TALER_RefreshCommitLinkP **commit_link,
unsigned int kappa,
unsigned int num_old_coins)
{
unsigned int i;
for (i=0;i<kappa;i++)
{
if (NULL == commit_link[i])
break;
GNUNET_free (commit_link[i]);
}
}
/** /**
* Handle a "/refresh/melt" request after the first parsing has happened. * Handle a "/refresh/melt" request after the first parsing has happened.
* We now need to validate the coins being melted and the session signature * We now need to validate the coins being melted and the session signature
@ -367,23 +322,19 @@ free_commit_links (struct TALER_RefreshCommitLinkP **commit_link,
* *
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param new_denoms array of denomination keys * @param new_denoms array of denomination keys
* @param melt_coins array of coins to melt * @param melt_coin coin to melt
* @param num_oldcoins number of coins that are being melted * @param transfer_pubs #TALER_CNC_KAPPA-dimensional array of transfer keys
* @param transfer_pubs #TALER_CNC_KAPPA-dimensional array of @a num_oldcoins transfer keys * @param secret_encs #TALER_CNC_KAPPA-dimensional array of old coin secrets
* @param secret_encs #TALER_CNC_KAPPA-dimensional array of @a num_oldcoins secrets * @param coin_evs #TALER_CNC_KAPPA-dimensional array of envelopes to sign
* @param num_newcoins number of coins that the refresh will generate * @param link_encs #TALER_CNC_KAPPA-dimensional array of `length(@a new_denoms)` encrypted links (2D array)
* @param coin_evs #TALER_CNC_KAPPA-dimensional array of @a num_newcoins envelopes to sign
* @param link_encs #TALER_CNC_KAPPA-dimensional array of @a num_newcoins encrypted links
* @return MHD result code * @return MHD result code
*/ */
static int static int
handle_refresh_melt_json (struct MHD_Connection *connection, handle_refresh_melt_json (struct MHD_Connection *connection,
const json_t *new_denoms, const json_t *new_denoms,
const json_t *melt_coins, const json_t *melt_coin,
unsigned int num_oldcoins,
const json_t *transfer_pubs, const json_t *transfer_pubs,
const json_t *secret_encs, const json_t *secret_encs,
unsigned int num_newcoins,
const json_t *coin_evs, const json_t *coin_evs,
const json_t *link_encs) const json_t *link_encs)
{ {
@ -391,27 +342,26 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
unsigned int i; unsigned int i;
unsigned int j; unsigned int j;
struct TALER_DenominationPublicKey *denom_pubs; struct TALER_DenominationPublicKey *denom_pubs;
unsigned int num_new_denoms; unsigned int num_newcoins;
struct TMH_DB_MeltDetails *coin_melt_details; struct TMH_DB_MeltDetails coin_melt_details;
unsigned int coin_count;
struct GNUNET_HashCode session_hash; struct GNUNET_HashCode session_hash;
struct GNUNET_HashContext *hash_context; struct GNUNET_HashContext *hash_context;
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin[TALER_CNC_KAPPA]; struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin[TALER_CNC_KAPPA];
struct TALER_RefreshCommitLinkP *commit_link[TALER_CNC_KAPPA]; struct TALER_RefreshCommitLinkP commit_link[TALER_CNC_KAPPA];
/* For the signature check, we hash most of the inputs together /* For the signature check, we hash most of the inputs together
(except for the signatures on the coins). */ (except for the signatures on the coins). */
hash_context = GNUNET_CRYPTO_hash_context_start (); hash_context = GNUNET_CRYPTO_hash_context_start ();
num_new_denoms = json_array_size (new_denoms); num_newcoins = json_array_size (new_denoms);
denom_pubs = GNUNET_malloc (num_new_denoms * denom_pubs = GNUNET_new_array (num_newcoins,
sizeof (struct TALER_DenominationPublicKey)); struct TALER_DenominationPublicKey);
for (i=0;i<num_new_denoms;i++) for (i=0;i<num_newcoins;i++)
{ {
char *buf; char *buf;
size_t buf_size; size_t buf_size;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_denomination_public_key (NULL, TALER_JSON_spec_denomination_public_key (NULL,
&denom_pubs[i]), &denom_pubs[i]),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
@ -432,42 +382,23 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
GNUNET_free (buf); GNUNET_free (buf);
} }
coin_count = json_array_size (melt_coins);
coin_melt_details = GNUNET_new_array (coin_count,
struct TMH_DB_MeltDetails);
for (i=0;i<coin_count;i++)
{ {
/* decode JSON data on coin to melt */ /* decode JSON data on coin to melt */
struct TALER_AmountNBO melt_amount; struct TALER_AmountNBO melt_amount;
// FIXME: check json_array_get() return value for NULL!
res = get_coin_public_info (connection, res = get_coin_public_info (connection,
json_array_get (melt_coins, i), melt_coin,
&coin_melt_details[i]); &coin_melt_details);
if (GNUNET_OK != res) if (GNUNET_OK != res)
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
res = (GNUNET_NO == res) ? MHD_YES : MHD_NO; res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
goto cleanup_melt_details; goto cleanup_melt_details;
} }
/* Check that the client does not try to melt the same coin twice
into the same session! */
for (j=0;j<i;j++)
{
if (0 == memcmp (&coin_melt_details[i].coin_info.coin_pub,
&coin_melt_details[j].coin_info.coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP)))
{
GNUNET_break_op (0);
res = TMH_RESPONSE_reply_external_error (connection,
"melting same coin twice in same session is not allowed");
goto cleanup_melt_details;
}
}
TALER_amount_hton (&melt_amount, TALER_amount_hton (&melt_amount,
&coin_melt_details[i].melt_amount_with_fee); &coin_melt_details.melt_amount_with_fee);
GNUNET_CRYPTO_hash_context_read (hash_context, GNUNET_CRYPTO_hash_context_read (hash_context,
&coin_melt_details[i].coin_info.coin_pub, &coin_melt_details.coin_info.coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP)); sizeof (struct TALER_CoinSpendPublicKeyP));
GNUNET_CRYPTO_hash_context_read (hash_context, GNUNET_CRYPTO_hash_context_read (hash_context,
&melt_amount, &melt_amount,
@ -480,8 +411,8 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
memset (commit_link, 0, sizeof (commit_link)); memset (commit_link, 0, sizeof (commit_link));
for (i = 0; i < TALER_CNC_KAPPA; i++) for (i = 0; i < TALER_CNC_KAPPA; i++)
{ {
commit_coin[i] = GNUNET_malloc (num_newcoins * commit_coin[i] = GNUNET_new_array (num_newcoins,
sizeof (struct TALER_EXCHANGEDB_RefreshCommitCoin)); struct TALER_EXCHANGEDB_RefreshCommitCoin);
for (j = 0; j < num_newcoins; j++) for (j = 0; j < num_newcoins; j++)
{ {
char *link_enc; char *link_enc;
@ -536,68 +467,59 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
for (i = 0; i < TALER_CNC_KAPPA; i++) for (i = 0; i < TALER_CNC_KAPPA; i++)
{ {
commit_link[i] = GNUNET_malloc (num_oldcoins * struct TALER_RefreshCommitLinkP *rcl = &commit_link[i];
sizeof (struct TALER_RefreshCommitLinkP)); struct GNUNET_JSON_Specification trans_spec[] = {
for (j = 0; j < num_oldcoins; j++) GNUNET_JSON_spec_fixed_auto (NULL, &rcl->transfer_pub),
{ GNUNET_JSON_spec_end ()
struct TALER_RefreshCommitLinkP *rcl = &commit_link[i][j]; };
struct GNUNET_JSON_Specification trans_spec[] = { struct GNUNET_JSON_Specification sec_spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL, &rcl->transfer_pub), GNUNET_JSON_spec_fixed_auto (NULL, &rcl->shared_secret_enc),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
struct GNUNET_JSON_Specification sec_spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL, &rcl->shared_secret_enc),
GNUNET_JSON_spec_end ()
};
res = TMH_PARSE_json_array (connection, res = TMH_PARSE_json_array (connection,
transfer_pubs, transfer_pubs,
trans_spec, trans_spec,
i, j, -1); i, -1);
if (GNUNET_OK != res) if (GNUNET_OK != res)
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
goto cleanup; goto cleanup;
}
res = TMH_PARSE_json_array (connection,
secret_encs,
sec_spec,
i, j, -1);
if (GNUNET_OK != res)
{
GNUNET_break_op (0);
res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
goto cleanup;
}
GNUNET_CRYPTO_hash_context_read (hash_context,
rcl,
sizeof (struct TALER_RefreshCommitLinkP));
} }
res = TMH_PARSE_json_array (connection,
secret_encs,
sec_spec,
i, -1);
if (GNUNET_OK != res)
{
GNUNET_break_op (0);
res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
goto cleanup;
}
GNUNET_CRYPTO_hash_context_read (hash_context,
rcl,
sizeof (struct TALER_RefreshCommitLinkP));
} }
GNUNET_CRYPTO_hash_context_finish (hash_context, GNUNET_CRYPTO_hash_context_finish (hash_context,
&session_hash); &session_hash);
hash_context = NULL; hash_context = NULL;
for (i=0;i<coin_count;i++) /* verify signature on coins to melt */
res = verify_coin_public_info (connection,
&session_hash,
&coin_melt_details);
if (GNUNET_OK != res)
{ {
/* verify signatures on coins to melt */ GNUNET_break_op (0);
res = verify_coin_public_info (connection, res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
&session_hash, goto cleanup;
&coin_melt_details[i]);
if (GNUNET_OK != res)
{
GNUNET_break_op (0);
res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
goto cleanup;
}
} }
/* execute commit */ /* execute commit */
res = handle_refresh_melt_binary (connection, res = handle_refresh_melt_binary (connection,
num_new_denoms, num_newcoins,
denom_pubs, denom_pubs,
coin_count, &coin_melt_details,
coin_melt_details,
&session_hash, &session_hash,
commit_coin, commit_coin,
commit_link); commit_link);
@ -605,20 +527,13 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
free_commit_coins (commit_coin, free_commit_coins (commit_coin,
TALER_CNC_KAPPA, TALER_CNC_KAPPA,
num_newcoins); num_newcoins);
free_commit_links (commit_link,
TALER_CNC_KAPPA,
num_oldcoins);
cleanup_melt_details: cleanup_melt_details:
for (j=0;j<coin_count;j++) if (NULL != coin_melt_details.coin_info.denom_pub.rsa_public_key)
{ GNUNET_CRYPTO_rsa_public_key_free (coin_melt_details.coin_info.denom_pub.rsa_public_key);
if (NULL != coin_melt_details[j].coin_info.denom_pub.rsa_public_key) if (NULL != coin_melt_details.coin_info.denom_sig.rsa_signature)
GNUNET_CRYPTO_rsa_public_key_free (coin_melt_details[j].coin_info.denom_pub.rsa_public_key); GNUNET_CRYPTO_rsa_signature_free (coin_melt_details.coin_info.denom_sig.rsa_signature);
if (NULL != coin_melt_details[j].coin_info.denom_sig.rsa_signature)
GNUNET_CRYPTO_rsa_signature_free (coin_melt_details[j].coin_info.denom_sig.rsa_signature);
}
GNUNET_free (coin_melt_details);
cleanup_denoms: cleanup_denoms:
for (j=0;j<num_new_denoms;j++) for (j=0;j<num_newcoins;j++)
if (NULL != denom_pubs[j].rsa_public_key) if (NULL != denom_pubs[j].rsa_public_key)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key); GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
GNUNET_free (denom_pubs); GNUNET_free (denom_pubs);
@ -650,19 +565,16 @@ TMH_REFRESH_handler_refresh_melt (struct TMH_RequestHandler *rh,
{ {
json_t *root; json_t *root;
json_t *new_denoms; json_t *new_denoms;
json_t *melt_coins; json_t *melt_coin;
json_t *coin_evs; json_t *coin_evs;
json_t *link_encs; json_t *link_encs;
json_t *transfer_pubs; json_t *transfer_pubs;
json_t *secret_encs; json_t *secret_encs;
unsigned int num_oldcoins;
unsigned int num_newcoins;
json_t *coin_detail; json_t *coin_detail;
json_t *trans_detail;
int res; int res;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("new_denoms", &new_denoms), GNUNET_JSON_spec_json ("new_denoms", &new_denoms),
GNUNET_JSON_spec_json ("melt_coins", &melt_coins), GNUNET_JSON_spec_json ("melt_coin", &melt_coin),
GNUNET_JSON_spec_json ("coin_evs", &coin_evs), GNUNET_JSON_spec_json ("coin_evs", &coin_evs),
GNUNET_JSON_spec_json ("link_encs", &link_encs), GNUNET_JSON_spec_json ("link_encs", &link_encs),
GNUNET_JSON_spec_json ("transfer_pubs", &transfer_pubs), GNUNET_JSON_spec_json ("transfer_pubs", &transfer_pubs),
@ -710,24 +622,11 @@ TMH_REFRESH_handler_refresh_melt (struct TMH_RequestHandler *rh,
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
} }
num_newcoins = json_array_size (coin_detail);
trans_detail = json_array_get (transfer_pubs, 0);
if (NULL == trans_detail)
{
// FIXME: generate proper HTTP response!
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
num_oldcoins = json_array_size (trans_detail);
res = handle_refresh_melt_json (connection, res = handle_refresh_melt_json (connection,
new_denoms, new_denoms,
melt_coins, melt_coin,
num_oldcoins,
transfer_pubs, transfer_pubs,
secret_encs, secret_encs,
num_newcoins,
coin_evs, coin_evs,
link_encs); link_encs);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
@ -744,53 +643,41 @@ TMH_REFRESH_handler_refresh_melt (struct TMH_RequestHandler *rh,
* *
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param session_hash hash identifying the melting session * @param session_hash hash identifying the melting session
* @param num_oldcoins length of the 2nd dimension of @a transfer_privs array
* @param tp_json private transfer keys in JSON format * @param tp_json private transfer keys in JSON format
* @return MHD result code * @return MHD result code
*/ */
static int static int
handle_refresh_reveal_json (struct MHD_Connection *connection, handle_refresh_reveal_json (struct MHD_Connection *connection,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
unsigned int num_oldcoins,
const json_t *tp_json) const json_t *tp_json)
{ {
struct TALER_TransferPrivateKeyP *transfer_privs[TALER_CNC_KAPPA - 1]; struct TALER_TransferPrivateKeyP transfer_privs[TALER_CNC_KAPPA - 1];
unsigned int i; unsigned int i;
unsigned int j;
int res; int res;
for (i = 0; i < TALER_CNC_KAPPA - 1; i++)
transfer_privs[i] = GNUNET_malloc (num_oldcoins *
sizeof (struct TALER_TransferPrivateKeyP));
res = GNUNET_OK; res = GNUNET_OK;
for (i = 0; i < TALER_CNC_KAPPA - 1; i++) for (i = 0; i < TALER_CNC_KAPPA - 1; i++)
{ {
if (GNUNET_OK != res) if (GNUNET_OK != res)
break; break;
for (j = 0; j < num_oldcoins; j++) struct GNUNET_JSON_Specification tp_spec[] = {
{ GNUNET_JSON_spec_fixed_auto (NULL, &transfer_privs[i]),
struct GNUNET_JSON_Specification tp_spec[] = { GNUNET_JSON_spec_end ()
GNUNET_JSON_spec_fixed_auto (NULL, &transfer_privs[i][j]), };
GNUNET_JSON_spec_end () if (GNUNET_OK != res)
}; break;
if (GNUNET_OK != res) res = TMH_PARSE_json_array (connection,
break; tp_json,
res = TMH_PARSE_json_array (connection, tp_spec,
tp_json, i, -1);
tp_spec, GNUNET_break_op (GNUNET_OK == res);
i, j, -1);
GNUNET_break_op (GNUNET_OK == res);
}
} }
if (GNUNET_OK != res) if (GNUNET_OK != res)
res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
else else
res = TMH_DB_execute_refresh_reveal (connection, res = TMH_DB_execute_refresh_reveal (connection,
session_hash, session_hash,
num_oldcoins,
transfer_privs); transfer_privs);
for (i = 0; i < TALER_CNC_KAPPA - 1; i++)
GNUNET_free (transfer_privs[i]);
return res; return res;
} }
@ -820,7 +707,6 @@ TMH_REFRESH_handler_refresh_reveal (struct TMH_RequestHandler *rh,
{ {
struct GNUNET_HashCode session_hash; struct GNUNET_HashCode session_hash;
int res; int res;
unsigned int num_oldcoins;
json_t *reveal_detail; json_t *reveal_detail;
json_t *root; json_t *root;
json_t *transfer_privs; json_t *transfer_privs;
@ -866,10 +752,8 @@ TMH_REFRESH_handler_refresh_reveal (struct TMH_RequestHandler *rh,
GNUNET_break_op (0); GNUNET_break_op (0);
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
} }
num_oldcoins = json_array_size (reveal_detail);
res = handle_refresh_reveal_json (connection, res = handle_refresh_reveal_json (connection,
&session_hash, &session_hash,
num_oldcoins,
transfer_privs); transfer_privs);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return res; return res;

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014, 2015, 2016 GNUnet e.V. Copyright (C) 2014, 2015, 2016 Inria & GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -978,6 +978,7 @@ TMH_RESPONSE_reply_refresh_reveal_success (struct MHD_Connection *connection,
* revealed value(s) do not match the original commitment. * revealed value(s) do not match the original commitment.
* *
* @param connection the connection to send the response to * @param connection the connection to send the response to
* @param rm details about the original melt
* @param mc all information about the original commitment * @param mc all information about the original commitment
* @param off offset in the array of kappa-commitments where * @param off offset in the array of kappa-commitments where
* the missmatch was detected * the missmatch was detected
@ -989,43 +990,35 @@ TMH_RESPONSE_reply_refresh_reveal_success (struct MHD_Connection *connection,
*/ */
int int
TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection,
const struct TALER_EXCHANGEDB_RefreshMelt *rm,
const struct TALER_EXCHANGEDB_MeltCommitment *mc, const struct TALER_EXCHANGEDB_MeltCommitment *mc,
unsigned int off, unsigned int off,
unsigned int j, unsigned int j,
const char *missmatch_object) const char *missmatch_object)
{ {
json_t *info_old;
json_t *info_new; json_t *info_new;
json_t *info_commit; json_t *info_commit;
json_t *info_links; json_t *info_links;
unsigned int i; unsigned int i;
unsigned int k; unsigned int k;
json_t *rm_json;
info_old = json_array (); rm_json = json_object ();
for (i=0;i<mc->num_oldcoins;i++) json_object_set_new (rm_json,
{ "coin_sig",
const struct TALER_EXCHANGEDB_RefreshMelt *rm; GNUNET_JSON_from_data (&rm->coin_sig,
json_t *rm_json; sizeof (struct TALER_CoinSpendSignatureP)));
json_object_set_new (rm_json,
"coin_pub",
GNUNET_JSON_from_data (&rm->coin.coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP)));
json_object_set_new (rm_json,
"melt_amount_with_fee",
TALER_JSON_from_amount (&rm->amount_with_fee));
json_object_set_new (rm_json,
"melt_fee",
TALER_JSON_from_amount (&rm->melt_fee));
rm = &mc->melts[i];
rm_json = json_object ();
json_object_set_new (rm_json,
"coin_sig",
GNUNET_JSON_from_data (&rm->coin_sig,
sizeof (struct TALER_CoinSpendSignatureP)));
json_object_set_new (rm_json,
"coin_pub",
GNUNET_JSON_from_data (&rm->coin.coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP)));
json_object_set_new (rm_json,
"melt_amount_with_fee",
TALER_JSON_from_amount (&rm->amount_with_fee));
json_object_set_new (rm_json,
"melt_fee",
TALER_JSON_from_amount (&rm->melt_fee));
json_array_append_new (info_old,
rm_json);
}
info_new = json_array (); info_new = json_array ();
for (i=0;i<mc->num_newcoins;i++) for (i=0;i<mc->num_newcoins;i++)
{ {
@ -1042,6 +1035,7 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection,
{ {
json_t *info_commit_k; json_t *info_commit_k;
json_t *info_link_k; json_t *info_link_k;
const struct TALER_RefreshCommitLinkP *cl;
info_commit_k = json_array (); info_commit_k = json_array ();
for (i=0;i<mc->num_newcoins;i++) for (i=0;i<mc->num_newcoins;i++)
@ -1069,25 +1063,17 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection,
} }
json_array_append_new (info_commit, json_array_append_new (info_commit,
info_commit_k); info_commit_k);
info_link_k = json_array ();
for (i=0;i<mc->num_oldcoins;i++)
{
const struct TALER_RefreshCommitLinkP *cl;
json_t *cl_json;
cl = &mc->commit_links[k][i]; info_link_k = json_object ();
cl_json = json_object (); cl = &mc->commit_links[k];
json_object_set_new (cl_json, json_object_set_new (info_link_k,
"transfer_pub", "transfer_pub",
GNUNET_JSON_from_data (&cl->transfer_pub, GNUNET_JSON_from_data (&cl->transfer_pub,
sizeof (struct TALER_TransferPublicKeyP))); sizeof (struct TALER_TransferPublicKeyP)));
json_object_set_new (cl_json, json_object_set_new (info_link_k,
"shared_secret_enc", "shared_secret_enc",
GNUNET_JSON_from_data (&cl->shared_secret_enc, GNUNET_JSON_from_data (&cl->shared_secret_enc,
sizeof (struct TALER_EncryptedLinkSecretP))); sizeof (struct TALER_EncryptedLinkSecretP)));
json_array_append_new (info_link_k,
cl_json);
}
json_array_append_new (info_links, json_array_append_new (info_links,
info_link_k); info_link_k);
} }
@ -1097,7 +1083,7 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection,
"error", "commitment violation", "error", "commitment violation",
"offset", (int) off, "offset", (int) off,
"index", (int) j, "index", (int) j,
"oldcoin_infos", info_old, "refresh_melt_info", rm_json,
"newcoin_infos", info_new, "newcoin_infos", info_new,
"commit_infos", info_commit, "commit_infos", info_commit,
"link_infos", info_links, "link_infos", info_links,

View File

@ -492,6 +492,7 @@ TMH_RESPONSE_reply_refresh_reveal_success (struct MHD_Connection *connection,
* revealed value(s) do not match the original commitment. * revealed value(s) do not match the original commitment.
* *
* @param connection the connection to send the response to * @param connection the connection to send the response to
* @param rm details about the original melt
* @param mc all information about the original commitment * @param mc all information about the original commitment
* @param off offset in the array of kappa-commitments where * @param off offset in the array of kappa-commitments where
* the missmatch was detected * the missmatch was detected
@ -503,6 +504,7 @@ TMH_RESPONSE_reply_refresh_reveal_success (struct MHD_Connection *connection,
*/ */
int int
TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection,
const struct TALER_EXCHANGEDB_RefreshMelt *rm,
const struct TALER_EXCHANGEDB_MeltCommitment *mc, const struct TALER_EXCHANGEDB_MeltCommitment *mc,
unsigned int off, unsigned int off,
unsigned int j, unsigned int j,

View File

@ -144,7 +144,7 @@ main (int argc, char ** argv)
PERF_TALER_EXCHANGEDB_INIT_CMD_LOOP ("06 - refresh melt init loop", PERF_TALER_EXCHANGEDB_INIT_CMD_LOOP ("06 - refresh melt init loop",
NB_MELT_INIT), NB_MELT_INIT),
PERF_TALER_EXCHANGEDB_INIT_CMD_START_TRANSACTION (""), PERF_TALER_EXCHANGEDB_INIT_CMD_START_TRANSACTION (""),
/* TODO: initialize using coins & sessions created localy /* TODO: initialize using coins & sessions created localy
* in order to make sure the same coin are not melted twice*/ * in order to make sure the same coin are not melted twice*/
PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("06 - session hash", PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("06 - session hash",
"06 - refresh melt init loop", "06 - refresh melt init loop",
@ -152,9 +152,6 @@ main (int argc, char ** argv)
PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("06 - coin", PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("06 - coin",
"06 - refresh melt init loop", "06 - refresh melt init loop",
"03 - save coin"), "03 - save coin"),
PERF_TALER_EXCHANGEDB_INIT_CMD_INSERT_REFRESH_MELT ("06 - refresh melt",
"06 - session hash",
"06 - coin"),
PERF_TALER_EXCHANGEDB_INIT_CMD_COMMIT_TRANSACTION (""), PERF_TALER_EXCHANGEDB_INIT_CMD_COMMIT_TRANSACTION (""),
PERF_TALER_EXCHANGEDB_INIT_CMD_END_LOOP ("06 - end", PERF_TALER_EXCHANGEDB_INIT_CMD_END_LOOP ("06 - end",
"06 - refresh melt init loop"), "06 - refresh melt init loop"),

View File

@ -447,7 +447,6 @@ PERF_TALER_EXCHANGEDB_refresh_session_init ()
GNUNET_assert (NULL != GNUNET_assert (NULL !=
(refresh_session = GNUNET_new (struct TALER_EXCHANGEDB_RefreshSession))); (refresh_session = GNUNET_new (struct TALER_EXCHANGEDB_RefreshSession)));
refresh_session->noreveal_index = 1; refresh_session->noreveal_index = 1;
refresh_session->num_oldcoins = 1;
refresh_session->num_newcoins = 1; refresh_session->num_newcoins = 1;
return refresh_session; return refresh_session;
@ -459,7 +458,7 @@ PERF_TALER_EXCHANGEDB_refresh_session_init ()
*/ */
int int
PERF_TALER_EXCHANGEDB_refresh_session_copy (struct TALER_EXCHANGEDB_RefreshSession *session, PERF_TALER_EXCHANGEDB_refresh_session_copy (struct TALER_EXCHANGEDB_RefreshSession *session,
struct TALER_EXCHANGEDB_RefreshSession *copy) struct TALER_EXCHANGEDB_RefreshSession *copy)
{ {
*copy = *session; *copy = *session;
return GNUNET_OK; return GNUNET_OK;

View File

@ -101,13 +101,6 @@ data_free (struct PERF_TALER_EXCHANGEDB_Data *data)
data->data.session_hash = NULL; data->data.session_hash = NULL;
break; break;
case PERF_TALER_EXCHANGEDB_REFRESH_MELT:
if (NULL == data->data.refresh_melt)
break;
PERF_TALER_EXCHANGEDB_refresh_melt_free (data->data.refresh_melt);
data->data.refresh_melt = NULL;
break;
case PERF_TALER_EXCHANGEDB_NONE: case PERF_TALER_EXCHANGEDB_NONE:
break; break;
} }
@ -158,11 +151,6 @@ data_copy (const struct PERF_TALER_EXCHANGEDB_Data *data,
= *data->data.session_hash; = *data->data.session_hash;
break; break;
case PERF_TALER_EXCHANGEDB_REFRESH_MELT:
copy->data.refresh_melt
= PERF_TALER_EXCHANGEDB_refresh_melt_copy (data->data.refresh_melt);
break;
case PERF_TALER_EXCHANGEDB_NONE: case PERF_TALER_EXCHANGEDB_NONE:
break; break;
} }
@ -770,75 +758,6 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
} }
break; break;
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_MELT:
{
int ret;
ret = cmd_find (cmd,
cmd[i].details.insert_refresh_melt.label_hash);
if (GNUNET_SYSERR == ret)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"%d:Undefined reference to %s\n",
i,
cmd[i].details.insert_refresh_melt.label_hash);
return GNUNET_SYSERR;
}
if (PERF_TALER_EXCHANGEDB_REFRESH_HASH != cmd[ret].exposed.type)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"%d:Wrong type reference to %s\n",
i,
cmd[i].details.insert_refresh_melt.label_hash);
return GNUNET_SYSERR;
}
cmd[i].details.insert_refresh_melt.index_hash = ret;
ret = cmd_find (cmd,
cmd[i].details.insert_refresh_melt.label_coin);
if (GNUNET_SYSERR == ret)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"%d:Undefined reference to %s\n",
i,
cmd[i].details.insert_refresh_melt.label_coin);
return GNUNET_SYSERR;
}
if (PERF_TALER_EXCHANGEDB_COIN != cmd[ret].exposed.type)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"%d:Wrong type reference to %s\n",
i,
cmd[i].details.insert_refresh_melt.label_coin);
return GNUNET_SYSERR;
}
cmd[i].details.insert_refresh_melt.index_coin = ret; }
break;
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_MELT:
{
int ret;
ret = cmd_find (cmd,
cmd[i].details.get_refresh_melt.label_hash);
if (GNUNET_SYSERR == ret)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"%d:Undefined reference to %s\n",
i,
cmd[i].details.get_refresh_melt.label_hash);
return GNUNET_SYSERR;
}
if (PERF_TALER_EXCHANGEDB_REFRESH_HASH != cmd[ret].exposed.type)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"%d:Wrong type reference to %s\n",
i,
cmd[i].details.get_refresh_melt.label_hash);
return GNUNET_SYSERR;
}
cmd[i].details.get_refresh_melt.index_hash = ret;
}
break;
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER: case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER:
{ {
int ret; int ret;
@ -1645,46 +1564,6 @@ interpret (struct PERF_TALER_EXCHANGEDB_interpreter_state *state)
} }
break; break;
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_MELT:
{
unsigned int hash_index;
unsigned int coin_index;
struct GNUNET_HashCode *hash;
struct TALER_EXCHANGEDB_RefreshMelt *melt;
struct PERF_TALER_EXCHANGEDB_Coin *coin;
hash_index = state->cmd[state->i].details.insert_refresh_melt.index_hash;
coin_index = state->cmd[state->i].details.insert_refresh_melt.index_coin;
hash = state->cmd[hash_index].exposed.data.session_hash;
coin = state->cmd[coin_index].exposed.data.coin;
melt = PERF_TALER_EXCHANGEDB_refresh_melt_init (hash,
coin);
state->plugin->insert_refresh_melt (state->plugin->cls,
state->session,
1,
melt);
}
break;
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_MELT:
{
int ret;
unsigned int hash_index;
struct GNUNET_HashCode *hash;
struct TALER_EXCHANGEDB_RefreshMelt melt;
hash_index = cmd_find (state->cmd,
state->cmd[state->i].details.get_refresh_melt.label_hash);
hash = state->cmd[hash_index].exposed.data.session_hash;
ret = state->plugin->get_refresh_melt (state->plugin->cls,
state->session,
hash,
1,
&melt);
GNUNET_assert (GNUNET_SYSERR != ret);
}
break;
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER: case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER:
{ {
unsigned int hash_index; unsigned int hash_index;

View File

@ -479,38 +479,6 @@
.exposed.type = PERF_TALER_EXCHANGEDB_NONE \ .exposed.type = PERF_TALER_EXCHANGEDB_NONE \
} }
/**
* Insert a melt operation in the database
*
* @param _label the label of the command
* @param _label_hash the label of the hash of the session
* @param _label_coin the label of the coin to melt
*/
#define PERF_TALER_EXCHANGEDB_INIT_CMD_INSERT_REFRESH_MELT(_label, \
_label_hash, \
_label_coin) \
{ \
.command = PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_MELT, \
.label = _label, \
.details.insert_refresh_melt.label_hash = _label_hash, \
.details.insert_refresh_melt.label_coin = _label_coin, \
.exposed.type = PERF_TALER_EXCHANGEDB_NONE \
}
/**
* Get informations about a melt operation
*
* @param _label the label of the command
* @param _label_hash the label of the hash of the refresh session
*/
#define PERF_TALER_EXCHANGEDB_INIT_CMD_GET_REFRESH_MELT(_label, \
_label_hash) \
{ \
.command = PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_MELT, \
.label = _label, \
.detail.get_refresh_melt.label_hash = _label_hash, \
.exposed.type = PERF_TALER_EXCHANGEDB_NONE \
}
/** /**
* The type of data stored in #PERF_TALER_EXCHANGEDB_Memory * The type of data stored in #PERF_TALER_EXCHANGEDB_Memory
@ -523,8 +491,7 @@ enum PERF_TALER_EXCHANGEDB_Type
PERF_TALER_EXCHANGEDB_RESERVE, PERF_TALER_EXCHANGEDB_RESERVE,
PERF_TALER_EXCHANGEDB_COIN, PERF_TALER_EXCHANGEDB_COIN,
PERF_TALER_EXCHANGEDB_DEPOSIT, PERF_TALER_EXCHANGEDB_DEPOSIT,
PERF_TALER_EXCHANGEDB_REFRESH_HASH, PERF_TALER_EXCHANGEDB_REFRESH_HASH
PERF_TALER_EXCHANGEDB_REFRESH_MELT
}; };
@ -553,8 +520,6 @@ struct PERF_TALER_EXCHANGEDB_Data
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki; struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
/** #PERF_TALER_EXCHANGEDB_REFRESH_HASH */ /** #PERF_TALER_EXCHANGEDB_REFRESH_HASH */
struct GNUNET_HashCode *session_hash; struct GNUNET_HashCode *session_hash;
/** #PERF_TALER_EXCHANGEDB_REFRESH_MELT */
struct TALER_EXCHANGEDB_RefreshMelt *refresh_melt;
} data; } data;
}; };
@ -713,16 +678,6 @@ enum PERF_TALER_EXCHANGEDB_CMD_Name
*/ */
PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_SESSION, PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_SESSION,
/**
* Insert a refresh melt
*/
PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_MELT,
/**
* Get informations about a refresh melt operation
*/
PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_MELT,
/** /**
* Insert a melt refresh order * Insert a melt refresh order
*/ */
@ -1085,36 +1040,6 @@ union PERF_TALER_EXCHANGEDB_CMD_Details
unsigned int index_hash; unsigned int index_hash;
} get_refresh_session; } get_refresh_session;
/**
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_MELT command
*/
struct PERF_TALER_EXCHANGEDB_CMD_insertRefreshMeltDetails
{
/**
* The label of the hash of the refresh session
*/
const char *label_hash;
unsigned int index_hash;
/**
* The label of the coin to melt
*/
const char *label_coin;
unsigned int index_coin;
} insert_refresh_melt;
/**
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_MELT command
*/
struct PERF_TALER_EXCHANGEDB_CMD_getRefreshMeltDetails
{
/**
* The label of the hash of the session
*/
const char *label_hash;
unsigned int index_hash;
} get_refresh_melt;
/** /**
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER command * Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER command
*/ */

View File

@ -132,15 +132,6 @@ common_free_melt_commitment (void *cls,
unsigned int i; unsigned int i;
unsigned int k; unsigned int k;
if (NULL != mc->melts)
{
for (i=0;i<mc->num_oldcoins;i++)
{
GNUNET_CRYPTO_rsa_signature_free (mc->melts[i].coin.denom_sig.rsa_signature);
GNUNET_CRYPTO_rsa_public_key_free (mc->melts[i].coin.denom_pub.rsa_public_key);
}
GNUNET_free (mc->melts);
}
if (NULL != mc->denom_pubs) if (NULL != mc->denom_pubs)
{ {
for (i=0;i<mc->num_newcoins;i++) for (i=0;i<mc->num_newcoins;i++)
@ -161,7 +152,6 @@ common_free_melt_commitment (void *cls,
} }
GNUNET_free (mc->commit_coins[k]); GNUNET_free (mc->commit_coins[k]);
} }
GNUNET_free_non_null (mc->commit_links[k]);
} }
GNUNET_free (mc); GNUNET_free (mc);
} }

View File

@ -159,8 +159,6 @@ postgres_drop_tables (void *cls,
"DROP TABLE IF EXISTS refunds;"); "DROP TABLE IF EXISTS refunds;");
SQLEXEC_ (session->conn, SQLEXEC_ (session->conn,
"DROP TABLE IF EXISTS refresh_order;"); "DROP TABLE IF EXISTS refresh_order;");
SQLEXEC_ (session->conn,
"DROP TABLE IF EXISTS refresh_melts;");
SQLEXEC_ (session->conn, SQLEXEC_ (session->conn,
"DROP TABLE IF EXISTS refresh_sessions;"); "DROP TABLE IF EXISTS refresh_sessions;");
SQLEXEC_ (session->conn, SQLEXEC_ (session->conn,
@ -338,36 +336,24 @@ postgres_create_tables (void *cls)
/** /**
* The DB will show negative values for some values of the following fields as * The DB will show negative values for some values of the following fields as
* we use them as 16 bit unsigned integers * we use them as 16 bit unsigned integers
* @a num_oldcoins
* @a num_newcoins * @a num_newcoins
* @a noreveal_index
* Do not do arithmetic in SQL on these fields. * Do not do arithmetic in SQL on these fields.
* NOTE: maybe we should instead forbid values >= 2^15 categorically? * NOTE: maybe we should instead forbid values >= 2^15 categorically?
*/ */
SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_sessions " SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_sessions "
"(session_hash BYTEA PRIMARY KEY CHECK (LENGTH(session_hash)=64)" "(session_hash BYTEA PRIMARY KEY CHECK (LENGTH(session_hash)=64)"
",num_oldcoins INT2 NOT NULL" ",old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub)"
",num_newcoins INT2 NOT NULL" ",old_coin_sig BYTEA NOT NULL CHECK(LENGTH(old_coin_sig)=64)"
",noreveal_index INT2 NOT NULL"
")");
/* Table with coins that have been melted. Gives the coin's public
key (coin_pub), the melting session, the index of this coin in that
session, the signature affirming the melting and the amount that
this coin contributed to the melting session.
*/
SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_melts "
"(coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub)"
",session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash)"
",oldcoin_index INT2 NOT NULL"
",coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)"
",amount_with_fee_val INT8 NOT NULL" ",amount_with_fee_val INT8 NOT NULL"
",amount_with_fee_frac INT4 NOT NULL" ",amount_with_fee_frac INT4 NOT NULL"
",amount_with_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ",amount_with_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",melt_fee_val INT8 NOT NULL" ",melt_fee_val INT8 NOT NULL"
",melt_fee_frac INT4 NOT NULL" ",melt_fee_frac INT4 NOT NULL"
",melt_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ",melt_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",PRIMARY KEY (session_hash, oldcoin_index)" /* a coin can be used only ",num_newcoins INT2 NOT NULL"
once in a refresh session */ ",noreveal_index INT2 NOT NULL"
") "); ")");
/* Table with information about coins that have been refunded. (Technically /* Table with information about coins that have been refunded. (Technically
one of the deposit operations that a coin was involved with is refunded.)*/ one of the deposit operations that a coin was involved with is refunded.)*/
SQLEXEC("CREATE TABLE IF NOT EXISTS refunds " SQLEXEC("CREATE TABLE IF NOT EXISTS refunds "
@ -401,15 +387,11 @@ postgres_create_tables (void *cls)
the session_hash for which this is the link information, the the session_hash for which this is the link information, the
oldcoin index and the cut-and-choose index (from 0 to #TALER_CNC_KAPPA-1), oldcoin index and the cut-and-choose index (from 0 to #TALER_CNC_KAPPA-1),
as well as the actual link data (the transfer public key and the encrypted as well as the actual link data (the transfer public key and the encrypted
link secret). link secret) */
NOTE: We might want to simplify this and not have the oldcoin_index
and instead store all link secrets, one after the other, in one big BYTEA.
(#3814) */
SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_link " SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_link "
"(session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash)" "(session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash)"
",transfer_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)" ",transfer_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)"
",link_secret_enc BYTEA NOT NULL" ",link_secret_enc BYTEA NOT NULL"
",oldcoin_index INT2 NOT NULL"
",cnc_index INT2 NOT NULL" ",cnc_index INT2 NOT NULL"
")"); ")");
/* Table with the commitments for the new coins that are to be created /* Table with the commitments for the new coins that are to be created
@ -726,7 +708,14 @@ postgres_prepare (PGconn *db_conn)
high-level information about a refresh session */ high-level information about a refresh session */
PREPARE ("get_refresh_session", PREPARE ("get_refresh_session",
"SELECT" "SELECT"
" num_oldcoins" " old_coin_pub"
",old_coin_sig"
",amount_with_fee_val"
",amount_with_fee_frac"
",amount_with_fee_curr"
",melt_fee_val "
",melt_fee_frac "
",melt_fee_curr "
",num_newcoins" ",num_newcoins"
",noreveal_index" ",noreveal_index"
" FROM refresh_sessions " " FROM refresh_sessions "
@ -738,12 +727,19 @@ postgres_prepare (PGconn *db_conn)
PREPARE ("insert_refresh_session", PREPARE ("insert_refresh_session",
"INSERT INTO refresh_sessions " "INSERT INTO refresh_sessions "
"(session_hash " "(session_hash "
",num_oldcoins " ",old_coin_pub "
",old_coin_sig "
",amount_with_fee_val "
",amount_with_fee_frac "
",amount_with_fee_curr "
",melt_fee_val "
",melt_fee_frac "
",melt_fee_curr "
",num_newcoins " ",num_newcoins "
",noreveal_index " ",noreveal_index "
") VALUES " ") VALUES "
"($1, $2, $3, $4);", "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);",
4, NULL); 11, NULL);
/* Used in #postgres_get_known_coin() to fetch /* Used in #postgres_get_known_coin() to fetch
the denomination public key and signature for the denomination public key and signature for
@ -787,54 +783,19 @@ postgres_prepare (PGconn *db_conn)
" WHERE session_hash=$1 AND newcoin_index=$2", " WHERE session_hash=$1 AND newcoin_index=$2",
2, NULL); 2, NULL);
/* Used in #postgres_insert_refresh_melt to store information /* Query the 'refresh_sessions' by coin public key */
about melted coins */ PREPARE ("get_refresh_session_by_coin",
PREPARE ("insert_refresh_melt",
"INSERT INTO refresh_melts "
"(coin_pub "
",session_hash"
",oldcoin_index "
",coin_sig "
",amount_with_fee_val "
",amount_with_fee_frac "
",amount_with_fee_curr "
",melt_fee_val "
",melt_fee_frac "
",melt_fee_curr "
") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);",
10, NULL);
/* Used in #postgres_get_refresh_melt to obtain information
about melted coins */
PREPARE ("get_refresh_melt",
"SELECT"
" coin_pub"
",coin_sig"
",amount_with_fee_val"
",amount_with_fee_frac"
",amount_with_fee_curr"
",melt_fee_val "
",melt_fee_frac "
",melt_fee_curr "
" FROM refresh_melts"
" WHERE session_hash=$1 AND oldcoin_index=$2",
2, NULL);
/* Query the 'refresh_melts' by coin public key */
PREPARE ("get_refresh_melt_by_coin",
"SELECT" "SELECT"
" session_hash" " session_hash"
/* ",oldcoin_index" // not needed */ ",old_coin_sig"
",coin_sig"
",amount_with_fee_val" ",amount_with_fee_val"
",amount_with_fee_frac" ",amount_with_fee_frac"
",amount_with_fee_curr" ",amount_with_fee_curr"
",melt_fee_val " ",melt_fee_val "
",melt_fee_frac " ",melt_fee_frac "
",melt_fee_curr " ",melt_fee_curr "
" FROM refresh_melts" " FROM refresh_sessions"
" WHERE coin_pub=$1", " WHERE old_coin_pub=$1",
1, NULL); 1, NULL);
/* Query the 'refunds' by coin public key */ /* Query the 'refunds' by coin public key */
@ -856,28 +817,27 @@ postgres_prepare (PGconn *db_conn)
1, NULL); 1, NULL);
/* Used in #postgres_insert_refresh_commit_links() to /* Used in #postgres_insert_refresh_commit_link() to
store commitments */ store commitments */
PREPARE ("insert_refresh_commit_link", PREPARE ("insert_refresh_commit_link",
"INSERT INTO refresh_commit_link " "INSERT INTO refresh_commit_link "
"(session_hash" "(session_hash"
",transfer_pub" ",transfer_pub"
",cnc_index" ",cnc_index"
",oldcoin_index"
",link_secret_enc" ",link_secret_enc"
") VALUES " ") VALUES "
"($1, $2, $3, $4, $5);", "($1, $2, $3, $4);",
5, NULL); 4, NULL);
/* Used in #postgres_get_refresh_commit_links() to /* Used in #postgres_get_refresh_commit_link() to
retrieve original commitments during /refresh/reveal */ retrieve original commitments during /refresh/reveal */
PREPARE ("get_refresh_commit_link", PREPARE ("get_refresh_commit_link",
"SELECT" "SELECT"
" transfer_pub" " transfer_pub"
",link_secret_enc" ",link_secret_enc"
" FROM refresh_commit_link" " FROM refresh_commit_link"
" WHERE session_hash=$1 AND cnc_index=$2 AND oldcoin_index=$3", " WHERE session_hash=$1 AND cnc_index=$2",
3, NULL); 2, NULL);
/* Used in #postgres_insert_refresh_commit_coins() to /* Used in #postgres_insert_refresh_commit_coins() to
store coin commitments. */ store coin commitments. */
@ -1110,10 +1070,9 @@ postgres_prepare (PGconn *db_conn)
efficient ways to express the same query. */ efficient ways to express the same query. */
PREPARE ("get_link", PREPARE ("get_link",
"SELECT link_vector_enc,ev_sig,ro.denom_pub" "SELECT link_vector_enc,ev_sig,ro.denom_pub"
" FROM refresh_melts rm " " FROM refresh_sessions rs "
" JOIN refresh_order ro USING (session_hash)" " JOIN refresh_order ro USING (session_hash)"
" JOIN refresh_commit_coin rcc USING (session_hash)" " JOIN refresh_commit_coin rcc USING (session_hash)"
" JOIN refresh_sessions rs USING (session_hash)"
" JOIN refresh_out rc USING (session_hash)" " JOIN refresh_out rc USING (session_hash)"
" WHERE ro.session_hash=$1" " WHERE ro.session_hash=$1"
" AND ro.newcoin_index=rcc.newcoin_index" " AND ro.newcoin_index=rcc.newcoin_index"
@ -1125,18 +1084,14 @@ postgres_prepare (PGconn *db_conn)
melted coin, we obtain the corresponding encrypted link secret melted coin, we obtain the corresponding encrypted link secret
and the transfer public key. This is done by first finding and the transfer public key. This is done by first finding
the session_hash(es) of all sessions the coin was melted into, the session_hash(es) of all sessions the coin was melted into,
and then constraining the result to the selected "noreveal_index" and then constraining the result to the selected "noreveal_index".
and the transfer public key to the corresponding index of the
old coin.
NOTE: This may (in theory) return multiple results, one per session NOTE: This may (in theory) return multiple results, one per session
that the old coin was melted into. */ that the old coin was melted into. */
PREPARE ("get_transfer", PREPARE ("get_transfer",
"SELECT transfer_pub,link_secret_enc,session_hash" "SELECT transfer_pub,link_secret_enc,session_hash"
" FROM refresh_melts rm" " FROM refresh_sessions rs"
" JOIN refresh_commit_link rcl USING (session_hash)" " JOIN refresh_commit_link rcl USING (session_hash)"
" JOIN refresh_sessions rs USING (session_hash)" " WHERE rs.old_coin_pub=$1"
" WHERE rm.coin_pub=$1"
" AND rm.oldcoin_index = rcl.oldcoin_index"
" AND rcl.cnc_index=rs.noreveal_index", " AND rcl.cnc_index=rs.noreveal_index",
1, NULL); 1, NULL);
@ -2288,7 +2243,7 @@ postgres_test_deposit_done (void *cls,
{ {
/* NOTE: maybe wrong type for a 'boolean' */ /* NOTE: maybe wrong type for a 'boolean' */
uint32_t done; uint32_t done = 0;
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint32 ("done", GNUNET_PQ_result_spec_uint32 ("done",
&done), &done),
@ -2812,12 +2767,14 @@ postgres_get_refresh_session (void *cls,
sizeof (struct TALER_EXCHANGEDB_RefreshSession)); sizeof (struct TALER_EXCHANGEDB_RefreshSession));
{ {
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint16 ("num_oldcoins",
&refresh_session->num_oldcoins),
GNUNET_PQ_result_spec_uint16 ("num_newcoins", GNUNET_PQ_result_spec_uint16 ("num_newcoins",
&refresh_session->num_newcoins), &refresh_session->num_newcoins),
GNUNET_PQ_result_spec_uint16 ("noreveal_index", GNUNET_PQ_result_spec_uint16 ("noreveal_index",
&refresh_session->noreveal_index), &refresh_session->noreveal_index),
GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub", &refresh_session->melt.coin.coin_pub),
GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig", &refresh_session->melt.coin_sig),
TALER_PQ_result_spec_amount ("amount_with_fee", &refresh_session->melt.amount_with_fee),
TALER_PQ_result_spec_amount ("melt_fee", &refresh_session->melt.melt_fee),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
}; };
if (GNUNET_OK != if (GNUNET_OK !=
@ -2829,6 +2786,16 @@ postgres_get_refresh_session (void *cls,
} }
} }
PQclear (result); PQclear (result);
if (GNUNET_OK !=
get_known_coin (cls,
session,
&refresh_session->melt.coin.coin_pub,
&refresh_session->melt.coin))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
refresh_session->melt.session_hash = *session_hash;
return GNUNET_YES; return GNUNET_YES;
} }
@ -2852,59 +2819,20 @@ postgres_create_refresh_session (void *cls,
PGresult *result; PGresult *result;
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (session_hash), GNUNET_PQ_query_param_auto_from_type (session_hash),
GNUNET_PQ_query_param_uint16 (&refresh_session->num_oldcoins), GNUNET_PQ_query_param_auto_from_type (&refresh_session->melt.coin.coin_pub),
GNUNET_PQ_query_param_auto_from_type (&refresh_session->melt.coin_sig),
TALER_PQ_query_param_amount (&refresh_session->melt.amount_with_fee),
TALER_PQ_query_param_amount (&refresh_session->melt.melt_fee),
GNUNET_PQ_query_param_uint16 (&refresh_session->num_newcoins), GNUNET_PQ_query_param_uint16 (&refresh_session->num_newcoins),
GNUNET_PQ_query_param_uint16 (&refresh_session->noreveal_index), GNUNET_PQ_query_param_uint16 (&refresh_session->noreveal_index),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
result = GNUNET_PQ_exec_prepared (session->conn,
"insert_refresh_session",
params);
if (PGRES_COMMAND_OK != PQresultStatus (result))
{
BREAK_DB_ERR (result);
PQclear (result);
return GNUNET_SYSERR;
}
PQclear (result);
return GNUNET_OK;
}
/**
* Store the given /refresh/melt request in the database.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param session database connection
* @param oldcoin_index index of the coin to store
* @param melt melt operation details to store; includes
* the session hash of the melt
* @return #GNUNET_OK on success
* #GNUNET_SYSERR on internal error
*/
static int
postgres_insert_refresh_melt (void *cls,
struct TALER_EXCHANGEDB_Session *session,
uint16_t oldcoin_index,
const struct TALER_EXCHANGEDB_RefreshMelt *melt)
{
PGresult *result;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (&melt->coin.coin_pub),
GNUNET_PQ_query_param_auto_from_type (&melt->session_hash),
GNUNET_PQ_query_param_uint16 (&oldcoin_index),
GNUNET_PQ_query_param_auto_from_type (&melt->coin_sig),
TALER_PQ_query_param_amount (&melt->amount_with_fee),
TALER_PQ_query_param_amount (&melt->melt_fee),
GNUNET_PQ_query_param_end
};
int ret; int ret;
/* check if the coin is already known */ /* check if the coin is already known */
ret = get_known_coin (cls, ret = get_known_coin (cls,
session, session,
&melt->coin.coin_pub, &refresh_session->melt.coin.coin_pub,
NULL); NULL);
if (GNUNET_SYSERR == ret) if (GNUNET_SYSERR == ret)
{ {
@ -2916,15 +2844,15 @@ postgres_insert_refresh_melt (void *cls,
if (GNUNET_SYSERR == if (GNUNET_SYSERR ==
insert_known_coin (cls, insert_known_coin (cls,
session, session,
&melt->coin)) &refresh_session->melt.coin))
{ {
GNUNET_break (0); GNUNET_break (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
} }
/* insert the melt */ /* insert session */
result = GNUNET_PQ_exec_prepared (session->conn, result = GNUNET_PQ_exec_prepared (session->conn,
"insert_refresh_melt", "insert_refresh_session",
params); params);
if (PGRES_COMMAND_OK != PQresultStatus (result)) if (PGRES_COMMAND_OK != PQresultStatus (result))
{ {
@ -2937,93 +2865,6 @@ postgres_insert_refresh_melt (void *cls,
} }
/**
* Get information about melted coin details from the database.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param session database connection
* @param session_hash session hash of the melt operation
* @param oldcoin_index index of the coin to retrieve
* @param melt melt data to fill in, can be NULL
* @return #GNUNET_OK on success
* #GNUNET_SYSERR on internal error
*/
static int
postgres_get_refresh_melt (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t oldcoin_index,
struct TALER_EXCHANGEDB_RefreshMelt *melt)
{
PGresult *result;
struct TALER_CoinPublicInfo coin;
struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_Amount amount_with_fee;
struct TALER_Amount melt_fee;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (session_hash),
GNUNET_PQ_query_param_uint16 (&oldcoin_index),
GNUNET_PQ_query_param_end
};
int nrows;
/* check if the melt record exists and get it */
result = GNUNET_PQ_exec_prepared (session->conn,
"get_refresh_melt",
params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
{
BREAK_DB_ERR (result);
PQclear (result);
return GNUNET_SYSERR;
}
nrows = PQntuples (result);
if (0 == nrows)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"get_refresh_melt() returned 0 matching rows\n");
PQclear (result);
return GNUNET_NO;
}
GNUNET_assert (1 == nrows); /* due to primary key constraint */
{
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &coin.coin_pub),
GNUNET_PQ_result_spec_auto_from_type ("coin_sig", &coin_sig),
TALER_PQ_result_spec_amount ("amount_with_fee", &amount_with_fee),
TALER_PQ_result_spec_amount ("melt_fee", &melt_fee),
GNUNET_PQ_result_spec_end
};
if (GNUNET_OK != GNUNET_PQ_extract_result (result, rs, 0))
{
GNUNET_break (0);
PQclear (result);
return GNUNET_SYSERR;
}
PQclear (result);
}
/* fetch the coin info and denomination info */
if (GNUNET_OK !=
get_known_coin (cls,
session,
&coin.coin_pub,
&coin))
return GNUNET_SYSERR;
if (NULL == melt)
{
GNUNET_CRYPTO_rsa_signature_free (coin.denom_sig.rsa_signature);
GNUNET_CRYPTO_rsa_public_key_free (coin.denom_pub.rsa_public_key);
return GNUNET_OK;
}
melt->coin = coin;
melt->coin_sig = coin_sig;
melt->session_hash = *session_hash;
melt->amount_with_fee = amount_with_fee;
melt->melt_fee = melt_fee;
return GNUNET_OK;
}
/** /**
* Store in the database which coin(s) we want to create * Store in the database which coin(s) we want to create
* in a given refresh operation. * in a given refresh operation.
@ -3369,48 +3210,42 @@ postgres_get_refresh_commit_coins (void *cls,
* @param session database connection to use * @param session database connection to use
* @param session_hash hash to identify refresh session * @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension) * @param cnc_index cut and choose index (1st dimension)
* @param num_links size of the @a links array to return * @param[out] link link information to store return
* @param[out] links array of link information to store return
* @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success
*/ */
static int static int
postgres_insert_refresh_commit_links (void *cls, postgres_insert_refresh_commit_link (void *cls,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index, uint16_t cnc_index,
uint16_t num_links, const struct TALER_RefreshCommitLinkP *link)
const struct TALER_RefreshCommitLinkP *links)
{ {
uint16_t i; struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (session_hash),
GNUNET_PQ_query_param_auto_from_type (&link->transfer_pub),
GNUNET_PQ_query_param_uint16 (&cnc_index),
GNUNET_PQ_query_param_auto_from_type (&link->shared_secret_enc),
GNUNET_PQ_query_param_end
};
for (i=0;i<num_links;i++) PGresult *result;
result = GNUNET_PQ_exec_prepared (session->conn,
"insert_refresh_commit_link",
params);
if (PGRES_COMMAND_OK != PQresultStatus (result))
{ {
struct GNUNET_PQ_QueryParam params[] = { BREAK_DB_ERR (result);
GNUNET_PQ_query_param_auto_from_type (session_hash),
GNUNET_PQ_query_param_auto_from_type (&links[i].transfer_pub),
GNUNET_PQ_query_param_uint16 (&cnc_index),
GNUNET_PQ_query_param_uint16 (&i),
GNUNET_PQ_query_param_auto_from_type (&links[i].shared_secret_enc),
GNUNET_PQ_query_param_end
};
PGresult *result = GNUNET_PQ_exec_prepared (session->conn,
"insert_refresh_commit_link",
params);
if (PGRES_COMMAND_OK != PQresultStatus (result))
{
BREAK_DB_ERR (result);
PQclear (result);
return GNUNET_SYSERR;
}
if (0 != strcmp ("1", PQcmdTuples (result)))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
PQclear (result); PQclear (result);
return GNUNET_SYSERR;
} }
if (0 != strcmp ("1", PQcmdTuples (result)))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
PQclear (result);
return GNUNET_OK; return GNUNET_OK;
} }
@ -3423,64 +3258,56 @@ postgres_insert_refresh_commit_links (void *cls,
* @param session database connection to use * @param session database connection to use
* @param session_hash hash to identify refresh session * @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension) * @param cnc_index cut and choose index (1st dimension)
* @param num_links size of the @a commit_link array * @param[out] link information to return
* @param[out] links array of link information to return
* @return #GNUNET_SYSERR on internal error, * @return #GNUNET_SYSERR on internal error,
* #GNUNET_NO if commitment was not found * #GNUNET_NO if commitment was not found
* #GNUNET_OK on success * #GNUNET_OK on success
*/ */
static int static int
postgres_get_refresh_commit_links (void *cls, postgres_get_refresh_commit_link (void *cls,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index, uint16_t cnc_index,
uint16_t num_links, struct TALER_RefreshCommitLinkP *link)
struct TALER_RefreshCommitLinkP *links)
{ {
uint16_t i; struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (session_hash),
GNUNET_PQ_query_param_uint16 (&cnc_index),
GNUNET_PQ_query_param_end
};
PGresult *result;
for (i=0;i<num_links;i++) result = GNUNET_PQ_exec_prepared (session->conn,
"get_refresh_commit_link",
params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
{ {
struct GNUNET_PQ_QueryParam params[] = { BREAK_DB_ERR (result);
GNUNET_PQ_query_param_auto_from_type (session_hash), PQclear (result);
GNUNET_PQ_query_param_uint16 (&cnc_index), return GNUNET_SYSERR;
GNUNET_PQ_query_param_uint16 (&i), }
GNUNET_PQ_query_param_end if (0 == PQntuples (result))
{
PQclear (result);
return GNUNET_NO;
}
{
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("transfer_pub",
&link->transfer_pub),
GNUNET_PQ_result_spec_auto_from_type ("link_secret_enc",
&link->shared_secret_enc),
GNUNET_PQ_result_spec_end
}; };
PGresult *result;
result = GNUNET_PQ_exec_prepared (session->conn, if (GNUNET_YES !=
"get_refresh_commit_link", GNUNET_PQ_extract_result (result, rs, 0))
params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
{ {
BREAK_DB_ERR (result);
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (0 == PQntuples (result))
{
PQclear (result);
return GNUNET_NO;
}
{
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("transfer_pub",
&links[i].transfer_pub),
GNUNET_PQ_result_spec_auto_from_type ("link_secret_enc",
&links[i].shared_secret_enc),
GNUNET_PQ_result_spec_end
};
if (GNUNET_YES !=
GNUNET_PQ_extract_result (result, rs, 0))
{
PQclear (result);
return GNUNET_SYSERR;
}
}
PQclear (result);
} }
PQclear (result);
return GNUNET_OK; return GNUNET_OK;
} }
@ -3502,7 +3329,6 @@ postgres_get_melt_commitment (void *cls,
struct TALER_EXCHANGEDB_RefreshSession rs; struct TALER_EXCHANGEDB_RefreshSession rs;
struct TALER_EXCHANGEDB_MeltCommitment *mc; struct TALER_EXCHANGEDB_MeltCommitment *mc;
uint16_t cnc_index; uint16_t cnc_index;
unsigned int i;
if (GNUNET_OK != if (GNUNET_OK !=
postgres_get_refresh_session (cls, postgres_get_refresh_session (cls,
@ -3512,17 +3338,6 @@ postgres_get_melt_commitment (void *cls,
return NULL; return NULL;
mc = GNUNET_new (struct TALER_EXCHANGEDB_MeltCommitment); mc = GNUNET_new (struct TALER_EXCHANGEDB_MeltCommitment);
mc->num_newcoins = rs.num_newcoins; mc->num_newcoins = rs.num_newcoins;
mc->num_oldcoins = rs.num_oldcoins;
mc->melts = GNUNET_malloc (mc->num_oldcoins *
sizeof (struct TALER_EXCHANGEDB_RefreshMelt));
for (i=0;i<mc->num_oldcoins;i++)
if (GNUNET_OK !=
postgres_get_refresh_melt (cls,
session,
session_hash,
(uint16_t) i,
&mc->melts[i]))
goto cleanup;
mc->denom_pubs = GNUNET_malloc (mc->num_newcoins * mc->denom_pubs = GNUNET_malloc (mc->num_newcoins *
sizeof (struct TALER_DenominationPublicKey)); sizeof (struct TALER_DenominationPublicKey));
if (GNUNET_OK != if (GNUNET_OK !=
@ -3545,16 +3360,12 @@ postgres_get_melt_commitment (void *cls,
mc->num_newcoins, mc->num_newcoins,
mc->commit_coins[cnc_index])) mc->commit_coins[cnc_index]))
goto cleanup; goto cleanup;
mc->commit_links[cnc_index]
= GNUNET_malloc (mc->num_oldcoins *
sizeof (struct TALER_RefreshCommitLinkP));
if (GNUNET_OK != if (GNUNET_OK !=
postgres_get_refresh_commit_links (cls, postgres_get_refresh_commit_link (cls,
session, session,
session_hash, session_hash,
cnc_index, cnc_index,
mc->num_oldcoins, &mc->commit_links[cnc_index]))
mc->commit_links[cnc_index]))
goto cleanup; goto cleanup;
} }
return mc; return mc;
@ -3803,8 +3614,8 @@ postgres_get_coin_transactions (void *cls,
struct TALER_EXCHANGEDB_TransactionList *tl; struct TALER_EXCHANGEDB_TransactionList *tl;
result = GNUNET_PQ_exec_prepared (session->conn, result = GNUNET_PQ_exec_prepared (session->conn,
"get_deposit_with_coin_pub", "get_deposit_with_coin_pub",
params); params);
if (PGRES_TUPLES_OK != PQresultStatus (result)) if (PGRES_TUPLES_OK != PQresultStatus (result))
{ {
QUERY_ERR (result); QUERY_ERR (result);
@ -3820,21 +3631,21 @@ postgres_get_coin_transactions (void *cls,
{ {
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint64 ("transaction_id", GNUNET_PQ_result_spec_uint64 ("transaction_id",
&deposit->transaction_id), &deposit->transaction_id),
TALER_PQ_result_spec_amount ("amount_with_fee", TALER_PQ_result_spec_amount ("amount_with_fee",
&deposit->amount_with_fee), &deposit->amount_with_fee),
TALER_PQ_result_spec_amount ("deposit_fee", TALER_PQ_result_spec_amount ("deposit_fee",
&deposit->deposit_fee), &deposit->deposit_fee),
GNUNET_PQ_result_spec_absolute_time ("timestamp", GNUNET_PQ_result_spec_absolute_time ("timestamp",
&deposit->timestamp), &deposit->timestamp),
GNUNET_PQ_result_spec_absolute_time ("refund_deadline", GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
&deposit->refund_deadline), &deposit->refund_deadline),
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
&deposit->merchant_pub), &deposit->merchant_pub),
GNUNET_PQ_result_spec_auto_from_type ("h_contract", GNUNET_PQ_result_spec_auto_from_type ("h_contract",
&deposit->h_contract), &deposit->h_contract),
GNUNET_PQ_result_spec_auto_from_type ("h_wire", GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&deposit->h_wire), &deposit->h_wire),
TALER_PQ_result_spec_json ("wire", TALER_PQ_result_spec_json ("wire",
&deposit->wire), &deposit->wire),
GNUNET_PQ_result_spec_auto_from_type ("coin_sig", GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
@ -3874,8 +3685,8 @@ postgres_get_coin_transactions (void *cls,
/* check if the melt records exist and get them */ /* check if the melt records exist and get them */
result = GNUNET_PQ_exec_prepared (session->conn, result = GNUNET_PQ_exec_prepared (session->conn,
"get_refresh_melt_by_coin", "get_refresh_session_by_coin",
params); params);
if (PGRES_TUPLES_OK != PQresultStatus (result)) if (PGRES_TUPLES_OK != PQresultStatus (result))
{ {
BREAK_DB_ERR (result); BREAK_DB_ERR (result);
@ -3891,10 +3702,10 @@ postgres_get_coin_transactions (void *cls,
{ {
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("session_hash", GNUNET_PQ_result_spec_auto_from_type ("session_hash",
&melt->session_hash), &melt->session_hash),
/* oldcoin_index not needed */ /* oldcoin_index not needed */
GNUNET_PQ_result_spec_auto_from_type ("coin_sig", GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
&melt->coin_sig), &melt->coin_sig),
TALER_PQ_result_spec_amount ("amount_with_fee", TALER_PQ_result_spec_amount ("amount_with_fee",
&melt->amount_with_fee), &melt->amount_with_fee),
TALER_PQ_result_spec_amount ("melt_fee", TALER_PQ_result_spec_amount ("melt_fee",
@ -4506,14 +4317,12 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
plugin->insert_refund = &postgres_insert_refund; plugin->insert_refund = &postgres_insert_refund;
plugin->get_refresh_session = &postgres_get_refresh_session; plugin->get_refresh_session = &postgres_get_refresh_session;
plugin->create_refresh_session = &postgres_create_refresh_session; plugin->create_refresh_session = &postgres_create_refresh_session;
plugin->insert_refresh_melt = &postgres_insert_refresh_melt;
plugin->get_refresh_melt = &postgres_get_refresh_melt;
plugin->insert_refresh_order = &postgres_insert_refresh_order; plugin->insert_refresh_order = &postgres_insert_refresh_order;
plugin->get_refresh_order = &postgres_get_refresh_order; plugin->get_refresh_order = &postgres_get_refresh_order;
plugin->insert_refresh_commit_coins = &postgres_insert_refresh_commit_coins; plugin->insert_refresh_commit_coins = &postgres_insert_refresh_commit_coins;
plugin->get_refresh_commit_coins = &postgres_get_refresh_commit_coins; plugin->get_refresh_commit_coins = &postgres_get_refresh_commit_coins;
plugin->insert_refresh_commit_links = &postgres_insert_refresh_commit_links; plugin->insert_refresh_commit_link = &postgres_insert_refresh_commit_link;
plugin->get_refresh_commit_links = &postgres_get_refresh_commit_links; plugin->get_refresh_commit_link = &postgres_get_refresh_commit_link;
plugin->get_melt_commitment = &postgres_get_melt_commitment; plugin->get_melt_commitment = &postgres_get_melt_commitment;
plugin->free_melt_commitment = &common_free_melt_commitment; plugin->free_melt_commitment = &common_free_melt_commitment;
plugin->insert_refresh_out = &postgres_insert_refresh_out; plugin->insert_refresh_out = &postgres_insert_refresh_out;

View File

@ -458,14 +458,13 @@ test_refresh_commit_links (struct TALER_EXCHANGEDB_Session *session,
static int static int
test_melting (struct TALER_EXCHANGEDB_Session *session) test_melting (struct TALER_EXCHANGEDB_Session *session)
{ {
#define MELT_OLD_COINS 10
struct TALER_EXCHANGEDB_RefreshSession refresh_session; struct TALER_EXCHANGEDB_RefreshSession refresh_session;
struct TALER_EXCHANGEDB_RefreshSession ret_refresh_session; struct TALER_EXCHANGEDB_RefreshSession ret_refresh_session;
struct GNUNET_HashCode session_hash; struct GNUNET_HashCode session_hash;
struct DenomKeyPair *dkp; struct DenomKeyPair *dkp;
struct DenomKeyPair **new_dkp; struct DenomKeyPair **new_dkp;
/* struct TALER_CoinPublicInfo *coins; */ /* struct TALER_CoinPublicInfo *coins; */
struct TALER_EXCHANGEDB_RefreshMelt *melts; struct TALER_EXCHANGEDB_RefreshMelt *meltp;
struct TALER_DenominationPublicKey *new_denom_pubs; struct TALER_DenominationPublicKey *new_denom_pubs;
struct TALER_DenominationPublicKey *ret_denom_pubs; struct TALER_DenominationPublicKey *ret_denom_pubs;
struct TALER_EXCHANGEDB_MeltCommitment *mc; struct TALER_EXCHANGEDB_MeltCommitment *mc;
@ -475,15 +474,40 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
ret = GNUNET_SYSERR; ret = GNUNET_SYSERR;
RND_BLK (&refresh_session); RND_BLK (&refresh_session);
RND_BLK (&session_hash); RND_BLK (&session_hash);
melts = NULL;
dkp = NULL; dkp = NULL;
new_dkp = NULL; new_dkp = NULL;
new_denom_pubs = NULL; new_denom_pubs = NULL;
ret_denom_pubs = NULL; ret_denom_pubs = NULL;
/* create and test a refresh session */ /* create and test a refresh session */
refresh_session.num_oldcoins = MELT_OLD_COINS;
refresh_session.num_newcoins = 1; refresh_session.num_newcoins = 1;
refresh_session.noreveal_index = 1; refresh_session.noreveal_index = 1;
/* create a denomination (value: 1; fraction: 100) */
dkp = create_denom_key_pair (512,
session,
&value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund);
/* initialize refresh session melt data */
{
struct GNUNET_HashCode hc;
meltp = &refresh_session.melt;
RND_BLK (&meltp->coin.coin_pub);
GNUNET_CRYPTO_hash (&meltp->coin.coin_pub,
sizeof (meltp->coin.coin_pub),
&hc);
meltp->coin.denom_sig.rsa_signature =
GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key,
&hc);
meltp->coin.denom_pub = dkp->pub;
RND_BLK (&meltp->coin_sig);
meltp->session_hash = session_hash;
meltp->amount_with_fee = amount_with_fee;
meltp->melt_fee = fee_refresh;
}
FAILIF (GNUNET_OK != plugin->create_refresh_session (plugin->cls, FAILIF (GNUNET_OK != plugin->create_refresh_session (plugin->cls,
session, session,
&session_hash, &session_hash,
@ -492,72 +516,35 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
session, session,
&session_hash, &session_hash,
&ret_refresh_session)); &ret_refresh_session));
FAILIF (0 != memcmp (&ret_refresh_session, FAILIF (ret_refresh_session.num_newcoins != refresh_session.num_newcoins);
&refresh_session, FAILIF (ret_refresh_session.noreveal_index != refresh_session.noreveal_index);
sizeof (refresh_session)));
/* create a denomination (value: 1; fraction: 100) */ /* check refresh sesison melt data */
dkp = create_denom_key_pair (512, session,
&value,
&fee_withdraw,
&fee_deposit,
&fee_refresh,
&fee_refund);
/* create MELT_OLD_COINS number of refresh melts */
melts = GNUNET_new_array (MELT_OLD_COINS,
struct TALER_EXCHANGEDB_RefreshMelt);
for (cnt=0; cnt < MELT_OLD_COINS; cnt++)
{ {
struct GNUNET_HashCode hc; struct TALER_EXCHANGEDB_RefreshMelt *ret_melt;
RND_BLK (&melts[cnt].coin.coin_pub); ret_melt = &ret_refresh_session.melt;
GNUNET_CRYPTO_hash (&melts[cnt].coin.coin_pub,
sizeof (melts[cnt].coin.coin_pub),
&hc);
melts[cnt].coin.denom_sig.rsa_signature =
GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key,
&hc);
melts[cnt].coin.denom_pub = dkp->pub;
RND_BLK (&melts[cnt].coin_sig);
melts[cnt].session_hash = session_hash;
melts[cnt].amount_with_fee = amount_with_fee;
melts[cnt].melt_fee = fee_refresh;
FAILIF (GNUNET_OK !=
plugin->insert_refresh_melt (plugin->cls,
session,
cnt,
&melts[cnt]));
}
for (cnt = 0; cnt < MELT_OLD_COINS; cnt++)
{
struct TALER_EXCHANGEDB_RefreshMelt ret_melt;
FAILIF (GNUNET_OK !=
plugin->get_refresh_melt (plugin->cls,
session,
&session_hash,
cnt,
&ret_melt));
FAILIF (0 != GNUNET_CRYPTO_rsa_signature_cmp FAILIF (0 != GNUNET_CRYPTO_rsa_signature_cmp
(ret_melt.coin.denom_sig.rsa_signature, (ret_melt->coin.denom_sig.rsa_signature,
melts[cnt].coin.denom_sig.rsa_signature)); meltp->coin.denom_sig.rsa_signature));
FAILIF (0 != memcmp (&ret_melt.coin.coin_pub, FAILIF (0 != memcmp (&ret_melt->coin.coin_pub,
&melts[cnt].coin.coin_pub, &meltp->coin.coin_pub,
sizeof (ret_melt.coin.coin_pub))); sizeof (ret_melt->coin.coin_pub)));
FAILIF (0 != GNUNET_CRYPTO_rsa_public_key_cmp FAILIF (0 != GNUNET_CRYPTO_rsa_public_key_cmp
(ret_melt.coin.denom_pub.rsa_public_key, (ret_melt->coin.denom_pub.rsa_public_key,
melts[cnt].coin.denom_pub.rsa_public_key)); meltp->coin.denom_pub.rsa_public_key));
FAILIF (0 != memcmp (&ret_melt.coin_sig, FAILIF (0 != memcmp (&ret_melt->coin_sig,
&melts[cnt].coin_sig, &meltp->coin_sig,
sizeof (ret_melt.coin_sig))); sizeof (ret_melt->coin_sig)));
FAILIF (0 != memcmp (&ret_melt.session_hash, FAILIF (0 != memcmp (&ret_melt->session_hash,
&melts[cnt].session_hash, &meltp->session_hash,
sizeof (ret_melt.session_hash))); sizeof (ret_melt->session_hash)));
FAILIF (0 != TALER_amount_cmp (&ret_melt.amount_with_fee, FAILIF (0 != TALER_amount_cmp (&ret_melt->amount_with_fee,
&melts[cnt].amount_with_fee)); &meltp->amount_with_fee));
FAILIF (0 != TALER_amount_cmp (&ret_melt.melt_fee, FAILIF (0 != TALER_amount_cmp (&ret_melt->melt_fee,
&melts[cnt].melt_fee)); &meltp->melt_fee));
GNUNET_CRYPTO_rsa_signature_free (ret_melt.coin.denom_sig.rsa_signature); GNUNET_CRYPTO_rsa_signature_free (ret_melt->coin.denom_sig.rsa_signature);
GNUNET_CRYPTO_rsa_public_key_free (ret_melt.coin.denom_pub.rsa_public_key); GNUNET_CRYPTO_rsa_public_key_free (ret_melt->coin.denom_pub.rsa_public_key);
} }
new_dkp = GNUNET_new_array (MELT_NEW_COINS, struct DenomKeyPair *); new_dkp = GNUNET_new_array (MELT_NEW_COINS, struct DenomKeyPair *);
new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS, new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
@ -619,15 +606,10 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
drop: drop:
if (NULL != dkp) if (NULL != dkp)
destroy_denom_key_pair (dkp); destroy_denom_key_pair (dkp);
if (NULL != melts) GNUNET_CRYPTO_rsa_signature_free (meltp->coin.denom_sig.rsa_signature);
{
for (cnt = 0; cnt < MELT_OLD_COINS; cnt++)
GNUNET_CRYPTO_rsa_signature_free (melts[cnt].coin.denom_sig.rsa_signature);
GNUNET_free (melts);
}
for (cnt = 0; for (cnt = 0;
(NULL != ret_denom_pubs) && (cnt < MELT_NEW_COINS) (NULL != ret_denom_pubs) && (cnt < MELT_NEW_COINS)
&& (NULL != ret_denom_pubs[cnt].rsa_public_key); && (NULL != ret_denom_pubs[cnt].rsa_public_key);
cnt++) cnt++)
GNUNET_CRYPTO_rsa_public_key_free (ret_denom_pubs[cnt].rsa_public_key); GNUNET_CRYPTO_rsa_public_key_free (ret_denom_pubs[cnt].rsa_public_key);
GNUNET_free_non_null (ret_denom_pubs); GNUNET_free_non_null (ret_denom_pubs);

View File

@ -711,12 +711,12 @@ typedef void
*/ */
struct TALER_EXCHANGE_ReserveWithdrawHandle * struct TALER_EXCHANGE_ReserveWithdrawHandle *
TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange, TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk, const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv, const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_CoinSpendPrivateKeyP *coin_priv, const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_DenominationBlindingKey *blinding_key, const struct TALER_DenominationBlindingKey *blinding_key,
TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb, TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
void *res_cb_cls); void *res_cb_cls);
/** /**
@ -745,8 +745,8 @@ TALER_EXCHANGE_reserve_withdraw_cancel (struct TALER_EXCHANGE_ReserveWithdrawHan
* to #TALER_EXCHANGE_refresh_melt() that will generate the request. * to #TALER_EXCHANGE_refresh_melt() that will generate the request.
* *
* This function does verify that the given request data is internally * This function does verify that the given request data is internally
* consistent. However, the @a melts_sigs are only verified if @a * consistent. However, the @a melts_sig is only verified if @a
* check_sigs is set to #GNUNET_YES, as this may be relatively * check_sig is set to #GNUNET_YES, as this may be relatively
* expensive and should be redundant. * expensive and should be redundant.
* *
* Aside from some non-trivial cryptographic operations that might * Aside from some non-trivial cryptographic operations that might
@ -754,17 +754,16 @@ TALER_EXCHANGE_reserve_withdraw_cancel (struct TALER_EXCHANGE_ReserveWithdrawHan
* its result immediately and does not start any asynchronous * its result immediately and does not start any asynchronous
* processing. This function is also thread-safe. * processing. This function is also thread-safe.
* *
* @param num_melts number of coins that are being melted (typically 1) * @param melt_priv private keys of the coin to melt
* @param melt_privs array of @a num_melts private keys of the coins to melt * @param melt_amount amount specifying how much
* @param melt_amounts array of @a num_melts amounts specifying how much * the coin will contribute to the melt (including fee)
* each coin will contribute to the melt (including fee) * @param melt_sig signatures affirming the
* @param melt_sigs array of @a num_melts signatures affirming the
* validity of the public keys corresponding to the * validity of the public keys corresponding to the
* @a melt_privs private keys * @a melt_priv private key
* @param melt_pks array of @a num_melts denomination key information * @param melt_pk denomination key information
* records corresponding to the @a melt_sigs * record corresponding to the @a melt_sig
* validity of the keys * validity of the keys
* @param check_sigs verify the validity of the signatures of @a melt_sigs * @param check_sig verify the validity of the signatures of @a melt_sig
* @param fresh_pks_len length of the @a pks array * @param fresh_pks_len length of the @a pks array
* @param fresh_pks array of @a pks_len denominations of fresh coins to create * @param fresh_pks array of @a pks_len denominations of fresh coins to create
* @param[out] res_size set to the size of the return value, or 0 on error * @param[out] res_size set to the size of the return value, or 0 on error
@ -775,12 +774,11 @@ TALER_EXCHANGE_reserve_withdraw_cancel (struct TALER_EXCHANGE_ReserveWithdrawHan
* Non-null results should be freed using #GNUNET_free(). * Non-null results should be freed using #GNUNET_free().
*/ */
char * char *
TALER_EXCHANGE_refresh_prepare (unsigned int num_melts, TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_priv,
const struct TALER_CoinSpendPrivateKeyP *melt_privs, const struct TALER_Amount *melt_amount,
const struct TALER_Amount *melt_amounts, const struct TALER_DenominationSignature *melt_sig,
const struct TALER_DenominationSignature *melt_sigs, const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
const struct TALER_EXCHANGE_DenomPublicKey *melt_pks, int check_sig,
int check_sigs,
unsigned int fresh_pks_len, unsigned int fresh_pks_len,
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks, const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks,
size_t *res_size); size_t *res_size);

View File

@ -358,33 +358,6 @@ struct TALER_EXCHANGEDB_Refund
}; };
/**
* @brief Global information for a refreshing session. Includes
* dimensions of the operation, security parameters and
* client signatures from "/refresh/melt" and "/refresh/commit".
*/
struct TALER_EXCHANGEDB_RefreshSession
{
/**
* Number of coins we are melting.
*/
uint16_t num_oldcoins;
/**
* Number of new coins we are creating.
*/
uint16_t num_newcoins;
/**
* Index (smaller #TALER_CNC_KAPPA) which the exchange has chosen to not
* have revealed during cut and choose.
*/
uint16_t noreveal_index;
};
/** /**
* @brief Specification for coin in a /refresh/melt operation. * @brief Specification for coin in a /refresh/melt operation.
*/ */
@ -429,6 +402,33 @@ struct TALER_EXCHANGEDB_RefreshMelt
}; };
/**
* @brief Global information for a refreshing session. Includes
* dimensions of the operation, security parameters and
* client signatures from "/refresh/melt" and "/refresh/commit".
*/
struct TALER_EXCHANGEDB_RefreshSession
{
/**
* Melt operation details.
*/
struct TALER_EXCHANGEDB_RefreshMelt melt;
/**
* Number of new coins we are creating.
*/
uint16_t num_newcoins;
/**
* Index (smaller #TALER_CNC_KAPPA) which the exchange has chosen to not
* have revealed during cut and choose.
*/
uint16_t noreveal_index;
};
/** /**
* @brief We have as many `struct TALER_EXCHANGEDB_RefreshCommitCoin` as there are new * @brief We have as many `struct TALER_EXCHANGEDB_RefreshCommitCoin` as there are new
* coins being created by the refresh (for each of the #TALER_CNC_KAPPA * coins being created by the refresh (for each of the #TALER_CNC_KAPPA
@ -557,21 +557,11 @@ struct TALER_EXCHANGEDB_TransactionList
struct TALER_EXCHANGEDB_MeltCommitment struct TALER_EXCHANGEDB_MeltCommitment
{ {
/**
* Number of coins we are melting.
*/
uint16_t num_oldcoins;
/** /**
* Number of new coins we are creating. * Number of new coins we are creating.
*/ */
uint16_t num_newcoins; uint16_t num_newcoins;
/**
* Array of @e num_oldcoins melt operation details.
*/
struct TALER_EXCHANGEDB_RefreshMelt *melts;
/** /**
* Array of @e num_newcoins denomination keys * Array of @e num_newcoins denomination keys
*/ */
@ -583,9 +573,9 @@ struct TALER_EXCHANGEDB_MeltCommitment
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins[TALER_CNC_KAPPA]; struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins[TALER_CNC_KAPPA];
/** /**
* 2D-Array of #TALER_CNC_KAPPA and @e new_oldcoins links. * Array of #TALER_CNC_KAPPA links.
*/ */
struct TALER_RefreshCommitLinkP *commit_links[TALER_CNC_KAPPA]; struct TALER_RefreshCommitLinkP commit_links[TALER_CNC_KAPPA];
}; };
@ -1116,43 +1106,6 @@ struct TALER_EXCHANGEDB_Plugin
const struct TALER_EXCHANGEDB_RefreshSession *refresh_session); const struct TALER_EXCHANGEDB_RefreshSession *refresh_session);
/**
* Store the given /refresh/melt request in the database.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param session database connection
* @param oldcoin_index index of the coin to store
* @param melt coin melt operation details to store; includes
* the session hash of the melt
* @return #GNUNET_OK on success
* #GNUNET_SYSERR on internal error
*/
int
(*insert_refresh_melt) (void *cls,
struct TALER_EXCHANGEDB_Session *session,
uint16_t oldcoin_index,
const struct TALER_EXCHANGEDB_RefreshMelt *melt);
/**
* Get information about melted coin details from the database.
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param session database connection
* @param session_hash hash to identify refresh session
* @param oldcoin_index index of the coin to retrieve
* @param melt melt data to fill in, can be NULL
* @return #GNUNET_OK on success
* #GNUNET_SYSERR on internal error
*/
int
(*get_refresh_melt) (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t oldcoin_index,
struct TALER_EXCHANGEDB_RefreshMelt *melt);
/** /**
* Store in the database which coin(s) we want to create * Store in the database which coin(s) we want to create
* in a given refresh operation. * in a given refresh operation.
@ -1245,18 +1198,16 @@ struct TALER_EXCHANGEDB_Plugin
* @param cls the @e cls of this struct with the plugin-specific state * @param cls the @e cls of this struct with the plugin-specific state
* @param session database connection to use * @param session database connection to use
* @param session_hash hash to identify refresh session * @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension), relating to #TALER_CNC_KAPPA * @param cnc_index cut and choose index, relating to #TALER_CNC_KAPPA
* @param num_links size of the @a commit_link array * @param link link information to store
* @param commit_links array of link information to store
* @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success
*/ */
int int
(*insert_refresh_commit_links) (void *cls, (*insert_refresh_commit_link) (void *cls,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index, uint16_t cnc_index,
uint16_t num_links, const struct TALER_RefreshCommitLinkP *link);
const struct TALER_RefreshCommitLinkP *commit_links);
/** /**
* Obtain the commited (encrypted) refresh link data * Obtain the commited (encrypted) refresh link data
@ -1266,19 +1217,17 @@ struct TALER_EXCHANGEDB_Plugin
* @param session database connection to use * @param session database connection to use
* @param session_hash hash to identify refresh session * @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension) * @param cnc_index cut and choose index (1st dimension)
* @param num_links size of the @a links array to return * @param[out] link information to return
* @param[out] links array link information to return
* @return #GNUNET_SYSERR on internal error, * @return #GNUNET_SYSERR on internal error,
* #GNUNET_NO if commitment was not found * #GNUNET_NO if commitment was not found
* #GNUNET_OK on success * #GNUNET_OK on success
*/ */
int int
(*get_refresh_commit_links) (void *cls, (*get_refresh_commit_link) (void *cls,
struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash, const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index, uint16_t cnc_index,
uint16_t num_links, struct TALER_RefreshCommitLinkP *link);
struct TALER_RefreshCommitLinkP *links);
/** /**