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];
/**
* Number of coins we are melting
*/
uint16_t num_melted_coins;
/**
* Number of coins we are creating
*/
uint16_t num_fresh_coins;
/**
* Information about the melted coins in an array of length @e
* num_melted_coins.
* Information about the melted coin.
*/
struct MeltedCoin *melted_coins;
struct MeltedCoin melted_coin;
/**
* Array of @e num_fresh_coins denomination keys for the coins to be
@ -279,8 +273,6 @@ struct MeltData
static void
free_melted_coin (struct MeltedCoin *mc)
{
if (NULL == mc)
return;
if (NULL != mc->pub_key.rsa_public_key)
GNUNET_CRYPTO_rsa_public_key_free (mc->pub_key.rsa_public_key);
if (NULL != mc->sig.rsa_signature)
@ -319,12 +311,7 @@ free_melt_data (struct MeltData *md)
unsigned int i;
unsigned int j;
if (NULL != md->melted_coins)
{
for (i=0;i<md->num_melted_coins;i++)
free_melted_coin (&md->melted_coins[i]);
GNUNET_free (md->melted_coins);
}
free_melted_coin (&md->melted_coin);
if (NULL != md->fresh_pks)
{
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;
for (i=0;i<TALER_CNC_KAPPA;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);
}
for (i=0;i<md->num_melted_coins;i++)
size += serialize_melted_coin (&md->melted_coins[i],
buf,
size);
size += serialize_melted_coin (&md->melted_coin,
buf,
size);
for (i=0;i<md->num_fresh_coins;i++)
size += serialize_denomination_key (&md->fresh_pks[i],
buf,
@ -744,10 +729,7 @@ deserialize_melt_data (const char *buf,
md->melt_session_hash = mdp.melt_session_hash;
for (i=0;i<TALER_CNC_KAPPA;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->melted_coins = GNUNET_new_array (md->num_melted_coins,
struct MeltedCoin);
md->fresh_pks = GNUNET_new_array (md->num_fresh_coins,
struct TALER_DenominationPublicKey);
for (i=0;i<TALER_CNC_KAPPA;i++)
@ -755,11 +737,10 @@ deserialize_melt_data (const char *buf,
struct FreshCoin);
off = sizeof (struct MeltDataP);
ok = GNUNET_YES;
for (i=0;(i<md->num_melted_coins)&&(GNUNET_YES == ok);i++)
off += deserialize_melted_coin (&md->melted_coins[i],
&buf[off],
buf_size - off,
&ok);
off += deserialize_melted_coin (&md->melted_coin,
&buf[off],
buf_size - off,
&ok);
for (i=0;(i<md->num_fresh_coins)&&(GNUNET_YES == ok);i++)
off += deserialize_denomination_key (&md->fresh_pks[i],
&buf[off],
@ -831,17 +812,16 @@ setup_fresh_coin (struct FreshCoin *fc,
* its result immediately and does not start any asynchronous
* processing. This function is also thread-safe.
*
* @param num_melts number of coins that are being melted (typically 1)
* @param melt_privs array of @a num_melts private keys of the coins to melt
* @param melt_amounts array of @a num_melts amounts specifying how much
* each coin will contribute to the melt (including fee)
* @param melt_sigs array of @a num_melts signatures affirming the
* @param melt_priv private key of the coin to melt
* @param melt_amount amount specifying how much
* the coin will contribute to the melt (including fee)
* @param melt_sig signature affirming the
* validity of the public keys corresponding to the
* @a melt_privs private keys
* @param melt_pks array of @a num_melts denomination key information
* records corresponding to the @a melt_sigs
* @a melt_priv private key
* @param melt_pk denomination key information
* record corresponding to the @a melt_sig
* 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 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
@ -852,15 +832,14 @@ setup_fresh_coin (struct FreshCoin *fc,
* Non-null results should be freed using #GNUNET_free().
*/
char *
TALER_EXCHANGE_refresh_prepare (unsigned int num_melts,
const struct TALER_CoinSpendPrivateKeyP *melt_privs,
const struct TALER_Amount *melt_amounts,
const struct TALER_DenominationSignature *melt_sigs,
const struct TALER_EXCHANGE_DenomPublicKey *melt_pks,
int check_sigs,
unsigned int fresh_pks_len,
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks,
size_t *res_size)
TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_priv,
const struct TALER_Amount *melt_amount,
const struct TALER_DenominationSignature *melt_sig,
const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
int check_sig,
unsigned int fresh_pks_len,
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks,
size_t *res_size)
{
struct MeltData md;
char *buf;
@ -873,31 +852,25 @@ TALER_EXCHANGE_refresh_prepare (unsigned int num_melts,
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
&md.link_secrets[i],
sizeof (struct TALER_LinkSecretP));
md.num_melted_coins = num_melts;
md.num_fresh_coins = fresh_pks_len;
md.melted_coins = GNUNET_new_array (num_melts,
struct MeltedCoin);
for (i=0;i<num_melts;i++)
md.melted_coin.coin_priv = *melt_priv;
md.melted_coin.melt_amount_with_fee = *melt_amount;
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];
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;
struct GNUNET_CRYPTO_EcdhePrivateKey *tpk;
tpk = GNUNET_CRYPTO_ecdhe_key_create ();
md.melted_coins[i].transfer_priv[j].ecdhe_priv = *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);
tpk = GNUNET_CRYPTO_ecdhe_key_create ();
md.melted_coin.transfer_priv[j].ecdhe_priv = *tpk;
GNUNET_free (tpk);
}
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,
struct TALER_DenominationPublicKey);
for (i=0;i<fresh_pks_len;i++)
@ -926,20 +899,19 @@ TALER_EXCHANGE_refresh_prepare (unsigned int num_melts,
buf_size);
GNUNET_free (buf);
}
for (i=0;i<num_melts;i++)
{
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);
GNUNET_CRYPTO_hash_context_read (hash_context,
&coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP));
TALER_amount_hton (&melt_amount,
&melt_amounts[i]);
TALER_amount_hton (&melt_amountn,
melt_amount);
GNUNET_CRYPTO_hash_context_read (hash_context,
&melt_amount,
&melt_amountn,
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 (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,
&rcl.transfer_pub.ecdhe_pub);
TALER_link_derive_transfer_secret (&melt_privs[j],
&md.melted_coins[j].transfer_priv[i],
&trans_sec);
TALER_transfer_encrypt (&md.link_secrets[i],
&trans_sec,
&rcl.shared_secret_enc);
GNUNET_CRYPTO_hash_context_read (hash_context,
&rcl,
sizeof (struct TALER_RefreshCommitLinkP));
}
GNUNET_CRYPTO_ecdhe_key_get_public (&md.melted_coin.transfer_priv[i].ecdhe_priv,
&rcl.transfer_pub.ecdhe_pub);
TALER_link_derive_transfer_secret (melt_priv,
&md.melted_coin.transfer_priv[i],
&trans_sec);
TALER_transfer_encrypt (&md.link_secrets[i],
&trans_sec,
&rcl.shared_secret_enc);
GNUNET_CRYPTO_hash_context_read (hash_context,
&rcl,
sizeof (struct TALER_RefreshCommitLinkP));
}
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 total;
struct TALER_CoinSpendPublicKeyP coin_pub;
unsigned int i;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("history", &history),
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 */
mc = NULL;
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;
}
mc = &rmh->md->melted_coin;
/* check basic coin properties */
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 *new_denoms;
json_t *melt_coins;
json_t *melt_coin;
json_t *coin_evs;
json_t *transfer_pubs;
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 */
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 ();
transfer_pubs = json_array ();
secret_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 */
for (j=0;j<TALER_CNC_KAPPA;j++)
{
tmp = json_array ();
for (i=0;i<md->num_melted_coins;i++)
{
const struct MeltedCoin *mc = &md->melted_coins[i];
struct TALER_TransferPublicKeyP transfer_pub;
const struct MeltedCoin *mc = &md->melted_coin;
struct TALER_TransferPublicKeyP transfer_pub;
GNUNET_CRYPTO_ecdhe_key_get_public (&mc->transfer_priv[j].ecdhe_priv,
&transfer_pub.ecdhe_pub);
json_array_append (tmp,
GNUNET_JSON_from_data (&transfer_pub,
sizeof (transfer_pub)));
}
GNUNET_CRYPTO_ecdhe_key_get_public (&mc->transfer_priv[j].ecdhe_priv,
&transfer_pub.ecdhe_pub);
json_array_append (transfer_pubs,
tmp);
GNUNET_JSON_from_data (&transfer_pub,
sizeof (transfer_pub)));
}
/* now secret_encs */
for (j=0;j<TALER_CNC_KAPPA;j++)
{
tmp = json_array ();
for (i=0;i<md->num_melted_coins;i++)
{
const struct MeltedCoin *mc = &md->melted_coins[i];
struct TALER_EncryptedLinkSecretP els;
struct TALER_TransferSecretP trans_sec;
const struct MeltedCoin *mc = &md->melted_coin;
struct TALER_EncryptedLinkSecretP els;
struct TALER_TransferSecretP trans_sec;
TALER_link_derive_transfer_secret (&mc->coin_priv,
&mc->transfer_priv[j],
&trans_sec);
GNUNET_assert (GNUNET_OK ==
TALER_transfer_encrypt (&md->link_secrets[j],
&trans_sec,
&els));
json_array_append (tmp,
GNUNET_JSON_from_data (&els,
sizeof (els)));
}
TALER_link_derive_transfer_secret (&mc->coin_priv,
&mc->transfer_priv[j],
&trans_sec);
GNUNET_assert (GNUNET_OK ==
TALER_transfer_encrypt (&md->link_secrets[j],
&trans_sec,
&els));
json_array_append (secret_encs,
tmp);
GNUNET_JSON_from_data (&els,
sizeof (els)));
}
/* now new_denoms */
@ -1569,7 +1492,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
/* finally, assemble main JSON request from constitutent arrays */
melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}",
"new_denoms", new_denoms,
"melt_coins", melt_coins,
"melt_coin", melt_coin,
"coin_evs", coin_evs,
"transfer_pubs", transfer_pubs,
"secret_encs", secret_encs,
@ -1907,11 +1830,9 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
struct TALER_EXCHANGE_RefreshRevealHandle *rrh;
json_t *transfer_privs;
json_t *reveal_obj;
json_t *tmp;
CURL *eh;
struct GNUNET_CURL_Context *ctx;
struct MeltData *md;
unsigned int i;
unsigned int j;
if (GNUNET_YES !=
@ -1947,17 +1868,9 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
noreval index! */
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,
tmp);
GNUNET_JSON_from_data (&md->melted_coin.transfer_priv[j],
sizeof (struct TALER_TransferPrivateKeyP)));
}
/* build main JSON request */

View File

@ -398,7 +398,7 @@ struct Command
/**
* Information about coins to be melted.
*/
struct MeltDetails *melted_coins;
struct MeltDetails melted_coin;
/**
* Denominations of the fresh coins to withdraw.
@ -1856,13 +1856,9 @@ interpreter_run (void *cls)
}
case OC_REFRESH_MELT:
{
unsigned int num_melted_coins;
unsigned int num_fresh_coins;
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;
NULL != cmd->details.refresh_melt.fresh_amounts[num_fresh_coins];
num_fresh_coins++) ;
@ -1871,36 +1867,33 @@ interpreter_run (void *cls)
= GNUNET_new_array (num_fresh_coins,
const struct TALER_EXCHANGE_DenomPublicKey *);
{
struct TALER_CoinSpendPrivateKeyP melt_privs[num_melted_coins];
struct TALER_Amount melt_amounts[num_melted_coins];
struct TALER_DenominationSignature melt_sigs[num_melted_coins];
struct TALER_EXCHANGE_DenomPublicKey melt_pks[num_melted_coins];
struct TALER_CoinSpendPrivateKeyP melt_priv;
struct TALER_Amount melt_amount;
struct TALER_DenominationSignature melt_sig;
struct TALER_EXCHANGE_DenomPublicKey melt_pk;
struct TALER_EXCHANGE_DenomPublicKey fresh_pks[num_fresh_coins];
unsigned int i;
for (i=0;i<num_melted_coins;i++)
{
const struct MeltDetails *md = &cmd->details.refresh_melt.melted_coins[i];
ref = find_command (is,
md->coin_ref);
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
const struct MeltDetails *md = &cmd->details.refresh_melt.melted_coin;
ref = find_command (is,
md->coin_ref);
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
melt_privs[i] = ref->details.reserve_withdraw.coin_priv;
if (GNUNET_OK !=
TALER_string_to_amount (md->amount,
&melt_amounts[i]))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse amount `%s' at %u\n",
md->amount,
is->ip);
fail (is);
return;
}
melt_sigs[i] = ref->details.reserve_withdraw.sig;
melt_pks[i] = *ref->details.reserve_withdraw.pk;
melt_priv = ref->details.reserve_withdraw.coin_priv;
if (GNUNET_OK !=
TALER_string_to_amount (md->amount,
&melt_amount))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failed to parse amount `%s' at %u\n",
md->amount,
is->ip);
fail (is);
return;
}
melt_sig = ref->details.reserve_withdraw.sig;
melt_pk = *ref->details.reserve_withdraw.pk;
for (i=0;i<num_fresh_coins;i++)
{
if (GNUNET_OK !=
@ -1920,15 +1913,14 @@ interpreter_run (void *cls)
fresh_pks[i] = *cmd->details.refresh_melt.fresh_pks[i];
}
cmd->details.refresh_melt.refresh_data
= TALER_EXCHANGE_refresh_prepare (num_melted_coins,
melt_privs,
melt_amounts,
melt_sigs,
melt_pks,
GNUNET_YES,
num_fresh_coins,
fresh_pks,
&cmd->details.refresh_melt.refresh_data_length);
= TALER_EXCHANGE_refresh_prepare (&melt_priv,
&melt_amount,
&melt_sig,
&melt_pk,
GNUNET_YES,
num_fresh_coins,
fresh_pks,
&cmd->details.refresh_melt.refresh_data_length);
if (NULL == cmd->details.refresh_melt.refresh_data)
{
GNUNET_break (0);
@ -1979,16 +1971,9 @@ interpreter_run (void *cls)
GNUNET_assert (NULL != ref);
/* find reserve_withdraw command */
{
unsigned int idx;
const struct MeltDetails *md;
unsigned int num_melted_coins;
for (num_melted_coins=0;
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];
md = &ref->details.refresh_melt.melted_coin;
ref = find_command (is,
md->coin_ref);
GNUNET_assert (NULL != ref);
@ -2465,11 +2450,6 @@ static void
run (void *cls)
{
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[] = {
"EUR:1",
"EUR:1",
@ -2613,7 +2593,9 @@ run (void *cls)
{ .oc = OC_REFRESH_MELT,
.label = "refresh-melt-1",
.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 },
@ -2658,7 +2640,9 @@ run (void *cls)
{ .oc = OC_REFRESH_MELT,
.label = "refresh-melt-failing",
.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 },
// 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 session_hash hash identifying the refresh session
* @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,
* #GNUNET_NO if an error message was generated,
* #GNUNET_SYSERR on internal errors (no response generated)
*/
static int
refresh_accept_melts (struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session,
const struct TMH_KS_StateHandle *key_state,
const struct GNUNET_HashCode *session_hash,
const struct TMH_DB_MeltDetails *coin_details,
uint16_t oldcoin_index)
refresh_check_melt (struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session,
const struct TMH_KS_StateHandle *key_state,
const struct GNUNET_HashCode *session_hash,
const struct TMH_DB_MeltDetails *coin_details,
struct TALER_EXCHANGEDB_RefreshMelt *meltp)
{
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dk;
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_residual;
struct TALER_Amount spent;
struct TALER_EXCHANGEDB_RefreshMelt melt;
int res;
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,
tl);
melt.coin = coin_details->coin_info;
melt.coin_sig = coin_details->melt_sig;
melt.session_hash = *session_hash;
melt.amount_with_fee = coin_details->melt_amount_with_fee;
melt.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;
}
meltp->coin = coin_details->coin_info;
meltp->coin_sig = coin_details->melt_sig;
meltp->session_hash = *session_hash;
meltp->amount_with_fee = coin_details->melt_amount_with_fee;
meltp->melt_fee = coin_details->melt_fee;
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 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 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 the respective coin should be melted
* @param coin_melt_detail signature and (residual) value of the respective coin should be melted
* @param commit_coin 2d array of coin commitments (what the exchange is to sign
* once the "/refres/reveal" of cut and choose is done),
* 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
* future)
* x-dimension must be #TALER_CNC_KAPPA
* future) of length #TALER_CNC_KAPPA
* @return MHD result code
*/
int
@ -990,10 +976,9 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
const struct GNUNET_HashCode *session_hash,
unsigned int num_new_denoms,
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_detail,
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 TALER_EXCHANGEDB_RefreshSession refresh_session;
@ -1028,11 +1013,26 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
}
/* store 'global' session data */
refresh_session.num_oldcoins = coin_count;
refresh_session.num_newcoins = num_new_denoms;
refresh_session.noreveal_index
= GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
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 !=
(res = TMH_plugin->create_refresh_session (TMH_plugin->cls,
session,
@ -1044,26 +1044,6 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *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 */
if (GNUNET_OK !=
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++)
{
if (GNUNET_OK !=
TMH_plugin->insert_refresh_commit_links (TMH_plugin->cls,
session,
session_hash,
i,
coin_count,
commit_link[i]))
TMH_plugin->insert_refresh_commit_link (TMH_plugin->cls,
session,
session_hash,
i,
&commit_link[i]))
{
TMH_plugin->rollback (TMH_plugin->cls,
session);
@ -1122,8 +1101,9 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
* @param connection the MHD connection to handle
* @param session database connection to use
* @param session_hash hash of session to query
* @param rm details about the original melt
* @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
* @return #GNUNET_NO if we generated the 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,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
const struct TALER_EXCHANGEDB_RefreshMelt *rm,
unsigned int off,
unsigned int index,
const char *object_name)
@ -1152,6 +1133,7 @@ send_melt_commitment_error (struct MHD_Connection *connection,
}
ret = (MHD_YES ==
TMH_RESPONSE_reply_refresh_reveal_missmatch (connection,
rm,
mc,
off,
index,
@ -1173,9 +1155,8 @@ send_melt_commitment_error (struct MHD_Connection *connection,
* @param session database connection to use
* @param session_hash hash of session to query
* @param off commitment offset to check
* @param num_oldcoins size of the @a transfer_privs and @a melts arrays
* @param transfer_privs private transfer keys
* @param melts array of melted coins
* @param transfer_priv private transfer key
* @param melt information about the melted coin
* @param num_newcoins number of newcoins being generated
* @param denom_pubs array of @a num_newcoins keys for the new coins
* @return #GNUNET_OK if the committment was honest,
@ -1187,91 +1168,58 @@ check_commitment (struct MHD_Connection *connection,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
unsigned int off,
unsigned int num_oldcoins,
const struct TALER_TransferPrivateKeyP *transfer_privs,
const struct TALER_EXCHANGEDB_RefreshMelt *melts,
const struct TALER_TransferPrivateKeyP *transfer_priv,
const struct TALER_EXCHANGEDB_RefreshMelt *melt,
unsigned int num_newcoins,
const struct TALER_DenominationPublicKey *denom_pubs)
{
unsigned int j;
struct TALER_LinkSecretP last_shared_secret;
int secret_initialized = GNUNET_NO;
struct TALER_RefreshCommitLinkP *commit_links;
struct TALER_RefreshCommitLinkP commit_link;
struct TALER_LinkSecretP shared_secret;
struct TALER_TransferPublicKeyP transfer_pub_check;
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins;
unsigned int j;
commit_links = GNUNET_malloc (num_oldcoins *
sizeof (struct TALER_RefreshCommitLinkP));
if (GNUNET_OK !=
TMH_plugin->get_refresh_commit_links (TMH_plugin->cls,
session,
session_hash,
off,
num_oldcoins,
commit_links))
TMH_plugin->get_refresh_commit_link (TMH_plugin->cls,
session,
session_hash,
off,
&commit_link))
{
GNUNET_break (0);
GNUNET_free (commit_links);
return (MHD_YES == TMH_RESPONSE_reply_internal_db_error (connection))
? 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;
struct TALER_TransferPublicKeyP transfer_pub_check;
GNUNET_CRYPTO_ecdhe_key_get_public (&transfer_privs[j].ecdhe_priv,
&transfer_pub_check.ecdhe_pub);
if (0 !=
memcmp (&transfer_pub_check,
&commit_links[j].transfer_pub,
sizeof (struct TALER_TransferPublicKeyP)))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"transfer keys do not match\n");
GNUNET_free (commit_links);
return send_melt_commitment_error (connection,
session,
session_hash,
off,
j,
"transfer key");
}
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_log (GNUNET_ERROR_TYPE_WARNING,
"transfer keys do not match\n");
return send_melt_commitment_error (connection,
session,
session_hash,
melt,
off,
UINT_MAX,
"transfer key");
}
if (GNUNET_OK !=
TALER_link_decrypt_secret (&commit_link.shared_secret_enc,
transfer_priv,
&melt->coin.coin_pub,
&shared_secret))
{
return (MHD_YES ==
TMH_RESPONSE_reply_internal_error (connection,
"Transfer secret decryption error"))
? GNUNET_NO : GNUNET_SYSERR;
}
GNUNET_break (GNUNET_YES == secret_initialized);
GNUNET_free (commit_links);
/* Check that the commitments for all new coins were correct */
commit_coins = GNUNET_malloc (num_newcoins *
@ -1300,7 +1248,7 @@ check_commitment (struct MHD_Connection *connection,
size_t buf_len;
link_data = TALER_refresh_decrypt (commit_coins[j].refresh_link,
&last_shared_secret);
&shared_secret);
if (NULL == link_data)
{
GNUNET_break (0);
@ -1342,6 +1290,7 @@ check_commitment (struct MHD_Connection *connection,
return send_melt_commitment_error (connection,
session,
session_hash,
melt,
off,
j,
"envelope");
@ -1422,7 +1371,6 @@ refresh_exchange_coin (struct MHD_Connection *connection,
* @param session database session
* @param session_hash hash identifying the refresh session
* @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[out] ev_sigs where to store generated signatures for the new coins,
* 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,
const struct GNUNET_HashCode *session_hash,
const struct TALER_EXCHANGEDB_RefreshSession *refresh_session,
const struct TALER_EXCHANGEDB_RefreshMelt *melts,
const struct TALER_DenominationPublicKey *denom_pubs,
struct TALER_DenominationSignature *ev_sigs,
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 */
ev_sigs[j] = refresh_exchange_coin (connection,
session,
session_hash,
key_state,
&denom_pubs[j],
&commit_coins[j],
j);
session,
session_hash,
key_state,
&denom_pubs[j],
&commit_coins[j],
j);
if (NULL == ev_sigs[j].rsa_signature)
{
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 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,
* x-dimension must be #TALER_CNC_KAPPA - 1
* length must be #TALER_CNC_KAPPA - 1
* @return MHD result code
*/
int
TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
const struct GNUNET_HashCode *session_hash,
unsigned int num_oldcoins,
struct TALER_TransferPrivateKeyP **transfer_privs)
struct TALER_TransferPrivateKeyP *transfer_privs)
{
int res;
struct TALER_EXCHANGEDB_Session *session;
struct TALER_EXCHANGEDB_RefreshSession refresh_session;
struct TALER_EXCHANGEDB_RefreshMelt *melts;
struct TALER_DenominationPublicKey *denom_pubs;
struct TALER_DenominationSignature *ev_sigs;
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins;
@ -1527,33 +1471,6 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
"session_hash");
if (GNUNET_SYSERR == res)
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 *
sizeof (struct TALER_DenominationPublicKey));
if (GNUNET_OK !=
@ -1565,12 +1482,8 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
{
GNUNET_break (0);
GNUNET_free (denom_pubs);
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);
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);
return (MHD_YES == TMH_RESPONSE_reply_internal_db_error (connection))
? GNUNET_NO : GNUNET_SYSERR;
}
@ -1586,30 +1499,19 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
session,
session_hash,
i + off,
refresh_session.num_oldcoins,
transfer_privs[i],
melts,
&transfer_privs[i],
&refresh_session.melt,
refresh_session.num_newcoins,
denom_pubs)))
{
for (j=0;j<refresh_session.num_newcoins;j++)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
GNUNET_free (denom_pubs);
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);
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);
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 */
commit_coins = GNUNET_malloc (refresh_session.num_newcoins *
@ -1620,7 +1522,6 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
session,
session_hash,
&refresh_session,
melts,
denom_pubs,
ev_sigs,
commit_coins);
@ -1630,6 +1531,8 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
for (j=0;j<refresh_session.num_newcoins;j++)
if (NULL != 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 (denom_pubs);
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 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 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 commit_coin 2d array of coin commitments (what the exchange is to sign
* 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
* future)
* future) of length #TALER_CNC_KAPPA
* @return MHD result code
*/
int
@ -147,10 +146,9 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection,
const struct GNUNET_HashCode *session_hash,
unsigned int num_new_denoms,
const struct TALER_DenominationPublicKey *denom_pubs,
unsigned int coin_count,
const struct TMH_DB_MeltDetails *coin_melt_details,
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 session_hash hash over the refresh session
* @param num_oldcoins size of y-dimension of @a transfer_privs array
* @param transfer_privs array with the revealed transfer keys, #TALER_CNC_KAPPA is 1st-dimension
* @param transfer_privs array of length #TALER_CNC_KAPPA-1 with the revealed transfer keys
* @return MHD result code
*/
int
TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection,
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
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
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 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 coin_count number of coins to be melted, size of y-dimension of @a commit_coin array
* @param coin_melt_details array with @a coin_count entries with melting details
* @param coin_melt_details melting details
* @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
* 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
* future)
* future) of length #TALER_CNC_KAPPA
* @return MHD result code
*/
static int
handle_refresh_melt_binary (struct MHD_Connection *connection,
unsigned int num_new_denoms,
const struct TALER_DenominationPublicKey *denom_pubs,
unsigned int coin_count,
const struct TMH_DB_MeltDetails *coin_melt_details,
const struct GNUNET_HashCode *session_hash,
struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin,
struct TALER_RefreshCommitLinkP *const* commit_link)
const struct TALER_RefreshCommitLinkP * commit_link)
{
unsigned int i;
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_Amount cost;
struct TALER_Amount total_cost;
struct TALER_Amount melt;
struct TALER_Amount value;
struct TALER_Amount fee_withdraw;
struct TALER_Amount fee_melt;
@ -108,45 +105,27 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
}
}
GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (TMH_exchange_currency_string,
&total_melt));
for (i=0;i<coin_count;i++)
dk = TMH_KS_denomination_key_lookup (key_state,
&coin_melt_details->coin_info.denom_pub,
TMH_KS_DKU_DEPOSIT);
if (NULL == dk)
{
/* calculate contribution of the i-th melt by subtracting
the fee; add the rest to the total_melt value */
dk = TMH_KS_denomination_key_lookup (key_state,
&coin_melt_details[i].coin_info.denom_pub,
TMH_KS_DKU_DEPOSIT);
if (NULL == dk)
{
GNUNET_break (0);
return TMH_RESPONSE_reply_arg_invalid (connection,
"denom_pub");
}
dki = &dk->issue;
TALER_amount_ntoh (&fee_melt,
&dki->properties.fee_refresh);
if (GNUNET_OK !=
TALER_amount_subtract (&melt,
&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");
}
GNUNET_break (0);
return TMH_RESPONSE_reply_arg_invalid (connection,
"denom_pub");
}
dki = &dk->issue;
TALER_amount_ntoh (&fee_melt,
&dki->properties.fee_refresh);
if (GNUNET_OK !=
TALER_amount_subtract (&total_melt,
&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");
}
TMH_KS_release (key_state);
if (0 !=
@ -165,7 +144,6 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
session_hash,
num_new_denoms,
denom_pubs,
coin_count,
coin_melt_details,
commit_coin,
commit_link);
@ -184,7 +162,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
*/
static int
get_coin_public_info (struct MHD_Connection *connection,
json_t *coin_info,
const json_t *coin_info,
struct TMH_DB_MeltDetails *r_melt_detail)
{
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.
* 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 new_denoms array of denomination keys
* @param melt_coins array of coins to melt
* @param num_oldcoins number of coins that are being melted
* @param transfer_pubs #TALER_CNC_KAPPA-dimensional array of @a num_oldcoins transfer keys
* @param secret_encs #TALER_CNC_KAPPA-dimensional array of @a num_oldcoins secrets
* @param num_newcoins number of coins that the refresh will generate
* @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
* @param melt_coin coin to melt
* @param transfer_pubs #TALER_CNC_KAPPA-dimensional array of transfer keys
* @param secret_encs #TALER_CNC_KAPPA-dimensional array of old coin secrets
* @param coin_evs #TALER_CNC_KAPPA-dimensional array of envelopes to sign
* @param link_encs #TALER_CNC_KAPPA-dimensional array of `length(@a new_denoms)` encrypted links (2D array)
* @return MHD result code
*/
static int
handle_refresh_melt_json (struct MHD_Connection *connection,
const json_t *new_denoms,
const json_t *melt_coins,
unsigned int num_oldcoins,
const json_t *melt_coin,
const json_t *transfer_pubs,
const json_t *secret_encs,
unsigned int num_newcoins,
const json_t *coin_evs,
const json_t *link_encs)
{
@ -391,27 +342,26 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
unsigned int i;
unsigned int j;
struct TALER_DenominationPublicKey *denom_pubs;
unsigned int num_new_denoms;
struct TMH_DB_MeltDetails *coin_melt_details;
unsigned int coin_count;
unsigned int num_newcoins;
struct TMH_DB_MeltDetails coin_melt_details;
struct GNUNET_HashCode session_hash;
struct GNUNET_HashContext *hash_context;
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
(except for the signatures on the coins). */
hash_context = GNUNET_CRYPTO_hash_context_start ();
num_new_denoms = json_array_size (new_denoms);
denom_pubs = GNUNET_malloc (num_new_denoms *
sizeof (struct TALER_DenominationPublicKey));
for (i=0;i<num_new_denoms;i++)
num_newcoins = json_array_size (new_denoms);
denom_pubs = GNUNET_new_array (num_newcoins,
struct TALER_DenominationPublicKey);
for (i=0;i<num_newcoins;i++)
{
char *buf;
size_t buf_size;
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_denomination_public_key (NULL,
&denom_pubs[i]),
&denom_pubs[i]),
GNUNET_JSON_spec_end ()
};
@ -432,42 +382,23 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
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 */
struct TALER_AmountNBO melt_amount;
// FIXME: check json_array_get() return value for NULL!
res = get_coin_public_info (connection,
json_array_get (melt_coins, i),
&coin_melt_details[i]);
melt_coin,
&coin_melt_details);
if (GNUNET_OK != res)
{
GNUNET_break_op (0);
res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
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,
&coin_melt_details[i].melt_amount_with_fee);
&coin_melt_details.melt_amount_with_fee);
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));
GNUNET_CRYPTO_hash_context_read (hash_context,
&melt_amount,
@ -480,8 +411,8 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
memset (commit_link, 0, sizeof (commit_link));
for (i = 0; i < TALER_CNC_KAPPA; i++)
{
commit_coin[i] = GNUNET_malloc (num_newcoins *
sizeof (struct TALER_EXCHANGEDB_RefreshCommitCoin));
commit_coin[i] = GNUNET_new_array (num_newcoins,
struct TALER_EXCHANGEDB_RefreshCommitCoin);
for (j = 0; j < num_newcoins; j++)
{
char *link_enc;
@ -536,68 +467,59 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
for (i = 0; i < TALER_CNC_KAPPA; i++)
{
commit_link[i] = GNUNET_malloc (num_oldcoins *
sizeof (struct TALER_RefreshCommitLinkP));
for (j = 0; j < num_oldcoins; j++)
{
struct TALER_RefreshCommitLinkP *rcl = &commit_link[i][j];
struct GNUNET_JSON_Specification trans_spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL, &rcl->transfer_pub),
GNUNET_JSON_spec_end ()
};
struct GNUNET_JSON_Specification sec_spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL, &rcl->shared_secret_enc),
GNUNET_JSON_spec_end ()
};
struct TALER_RefreshCommitLinkP *rcl = &commit_link[i];
struct GNUNET_JSON_Specification trans_spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL, &rcl->transfer_pub),
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,
transfer_pubs,
trans_spec,
i, j, -1);
if (GNUNET_OK != res)
{
GNUNET_break_op (0);
res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
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,
transfer_pubs,
trans_spec,
i, -1);
if (GNUNET_OK != res)
{
GNUNET_break_op (0);
res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
goto cleanup;
}
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,
&session_hash);
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 */
res = verify_coin_public_info (connection,
&session_hash,
&coin_melt_details[i]);
if (GNUNET_OK != res)
{
GNUNET_break_op (0);
res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
goto cleanup;
}
GNUNET_break_op (0);
res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
goto cleanup;
}
/* execute commit */
res = handle_refresh_melt_binary (connection,
num_new_denoms,
num_newcoins,
denom_pubs,
coin_count,
coin_melt_details,
&coin_melt_details,
&session_hash,
commit_coin,
commit_link);
@ -605,20 +527,13 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
free_commit_coins (commit_coin,
TALER_CNC_KAPPA,
num_newcoins);
free_commit_links (commit_link,
TALER_CNC_KAPPA,
num_oldcoins);
cleanup_melt_details:
for (j=0;j<coin_count;j++)
{
if (NULL != coin_melt_details[j].coin_info.denom_pub.rsa_public_key)
GNUNET_CRYPTO_rsa_public_key_free (coin_melt_details[j].coin_info.denom_pub.rsa_public_key);
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);
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.coin_info.denom_sig.rsa_signature)
GNUNET_CRYPTO_rsa_signature_free (coin_melt_details.coin_info.denom_sig.rsa_signature);
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)
GNUNET_CRYPTO_rsa_public_key_free (denom_pubs[j].rsa_public_key);
GNUNET_free (denom_pubs);
@ -650,19 +565,16 @@ TMH_REFRESH_handler_refresh_melt (struct TMH_RequestHandler *rh,
{
json_t *root;
json_t *new_denoms;
json_t *melt_coins;
json_t *melt_coin;
json_t *coin_evs;
json_t *link_encs;
json_t *transfer_pubs;
json_t *secret_encs;
unsigned int num_oldcoins;
unsigned int num_newcoins;
json_t *coin_detail;
json_t *trans_detail;
int res;
struct GNUNET_JSON_Specification spec[] = {
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 ("link_encs", &link_encs),
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);
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,
new_denoms,
melt_coins,
num_oldcoins,
melt_coin,
transfer_pubs,
secret_encs,
num_newcoins,
coin_evs,
link_encs);
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 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
* @return MHD result code
*/
static int
handle_refresh_reveal_json (struct MHD_Connection *connection,
const struct GNUNET_HashCode *session_hash,
unsigned int num_oldcoins,
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 j;
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;
for (i = 0; i < TALER_CNC_KAPPA - 1; i++)
{
if (GNUNET_OK != res)
break;
for (j = 0; j < num_oldcoins; j++)
{
struct GNUNET_JSON_Specification tp_spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL, &transfer_privs[i][j]),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK != res)
break;
res = TMH_PARSE_json_array (connection,
tp_json,
tp_spec,
i, j, -1);
GNUNET_break_op (GNUNET_OK == res);
}
struct GNUNET_JSON_Specification tp_spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL, &transfer_privs[i]),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK != res)
break;
res = TMH_PARSE_json_array (connection,
tp_json,
tp_spec,
i, -1);
GNUNET_break_op (GNUNET_OK == res);
}
if (GNUNET_OK != res)
res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
else
res = TMH_DB_execute_refresh_reveal (connection,
session_hash,
num_oldcoins,
transfer_privs);
for (i = 0; i < TALER_CNC_KAPPA - 1; i++)
GNUNET_free (transfer_privs[i]);
return res;
}
@ -820,7 +707,6 @@ TMH_REFRESH_handler_refresh_reveal (struct TMH_RequestHandler *rh,
{
struct GNUNET_HashCode session_hash;
int res;
unsigned int num_oldcoins;
json_t *reveal_detail;
json_t *root;
json_t *transfer_privs;
@ -866,10 +752,8 @@ TMH_REFRESH_handler_refresh_reveal (struct TMH_RequestHandler *rh,
GNUNET_break_op (0);
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
}
num_oldcoins = json_array_size (reveal_detail);
res = handle_refresh_reveal_json (connection,
&session_hash,
num_oldcoins,
transfer_privs);
GNUNET_JSON_parse_free (spec);
return res;

View File

@ -1,6 +1,6 @@
/*
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
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.
*
* @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 off offset in the array of kappa-commitments where
* the missmatch was detected
@ -989,43 +990,35 @@ TMH_RESPONSE_reply_refresh_reveal_success (struct MHD_Connection *connection,
*/
int
TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection,
const struct TALER_EXCHANGEDB_RefreshMelt *rm,
const struct TALER_EXCHANGEDB_MeltCommitment *mc,
unsigned int off,
unsigned int j,
const char *missmatch_object)
{
json_t *info_old;
json_t *info_new;
json_t *info_commit;
json_t *info_links;
unsigned int i;
unsigned int k;
json_t *rm_json;
info_old = json_array ();
for (i=0;i<mc->num_oldcoins;i++)
{
const struct TALER_EXCHANGEDB_RefreshMelt *rm;
json_t *rm_json;
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));
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 ();
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_link_k;
const struct TALER_RefreshCommitLinkP *cl;
info_commit_k = json_array ();
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,
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];
cl_json = json_object ();
json_object_set_new (cl_json,
"transfer_pub",
GNUNET_JSON_from_data (&cl->transfer_pub,
sizeof (struct TALER_TransferPublicKeyP)));
json_object_set_new (cl_json,
"shared_secret_enc",
GNUNET_JSON_from_data (&cl->shared_secret_enc,
sizeof (struct TALER_EncryptedLinkSecretP)));
json_array_append_new (info_link_k,
cl_json);
}
info_link_k = json_object ();
cl = &mc->commit_links[k];
json_object_set_new (info_link_k,
"transfer_pub",
GNUNET_JSON_from_data (&cl->transfer_pub,
sizeof (struct TALER_TransferPublicKeyP)));
json_object_set_new (info_link_k,
"shared_secret_enc",
GNUNET_JSON_from_data (&cl->shared_secret_enc,
sizeof (struct TALER_EncryptedLinkSecretP)));
json_array_append_new (info_links,
info_link_k);
}
@ -1097,7 +1083,7 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection,
"error", "commitment violation",
"offset", (int) off,
"index", (int) j,
"oldcoin_infos", info_old,
"refresh_melt_info", rm_json,
"newcoin_infos", info_new,
"commit_infos", info_commit,
"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.
*
* @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 off offset in the array of kappa-commitments where
* the missmatch was detected
@ -503,6 +504,7 @@ TMH_RESPONSE_reply_refresh_reveal_success (struct MHD_Connection *connection,
*/
int
TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection,
const struct TALER_EXCHANGEDB_RefreshMelt *rm,
const struct TALER_EXCHANGEDB_MeltCommitment *mc,
unsigned int off,
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",
NB_MELT_INIT),
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*/
PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("06 - session hash",
"06 - refresh melt init loop",
@ -152,9 +152,6 @@ main (int argc, char ** argv)
PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("06 - coin",
"06 - refresh melt init loop",
"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_END_LOOP ("06 - end",
"06 - refresh melt init loop"),

View File

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

View File

@ -101,13 +101,6 @@ data_free (struct PERF_TALER_EXCHANGEDB_Data *data)
data->data.session_hash = NULL;
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:
break;
}
@ -158,11 +151,6 @@ data_copy (const struct PERF_TALER_EXCHANGEDB_Data *data,
= *data->data.session_hash;
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:
break;
}
@ -770,75 +758,6 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
}
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:
{
int ret;
@ -1645,46 +1564,6 @@ interpret (struct PERF_TALER_EXCHANGEDB_interpreter_state *state)
}
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:
{
unsigned int hash_index;

View File

@ -479,38 +479,6 @@
.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
@ -523,8 +491,7 @@ enum PERF_TALER_EXCHANGEDB_Type
PERF_TALER_EXCHANGEDB_RESERVE,
PERF_TALER_EXCHANGEDB_COIN,
PERF_TALER_EXCHANGEDB_DEPOSIT,
PERF_TALER_EXCHANGEDB_REFRESH_HASH,
PERF_TALER_EXCHANGEDB_REFRESH_MELT
PERF_TALER_EXCHANGEDB_REFRESH_HASH
};
@ -553,8 +520,6 @@ struct PERF_TALER_EXCHANGEDB_Data
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
/** #PERF_TALER_EXCHANGEDB_REFRESH_HASH */
struct GNUNET_HashCode *session_hash;
/** #PERF_TALER_EXCHANGEDB_REFRESH_MELT */
struct TALER_EXCHANGEDB_RefreshMelt *refresh_melt;
} data;
};
@ -713,16 +678,6 @@ enum PERF_TALER_EXCHANGEDB_CMD_Name
*/
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
*/
@ -1085,36 +1040,6 @@ union PERF_TALER_EXCHANGEDB_CMD_Details
unsigned int index_hash;
} 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
*/

View File

@ -132,15 +132,6 @@ common_free_melt_commitment (void *cls,
unsigned int i;
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)
{
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_non_null (mc->commit_links[k]);
}
GNUNET_free (mc);
}

View File

@ -159,8 +159,6 @@ postgres_drop_tables (void *cls,
"DROP TABLE IF EXISTS refunds;");
SQLEXEC_ (session->conn,
"DROP TABLE IF EXISTS refresh_order;");
SQLEXEC_ (session->conn,
"DROP TABLE IF EXISTS refresh_melts;");
SQLEXEC_ (session->conn,
"DROP TABLE IF EXISTS refresh_sessions;");
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
* we use them as 16 bit unsigned integers
* @a num_oldcoins
* @a num_newcoins
* @a noreveal_index
* Do not do arithmetic in SQL on these fields.
* NOTE: maybe we should instead forbid values >= 2^15 categorically?
*/
SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_sessions "
"(session_hash BYTEA PRIMARY KEY CHECK (LENGTH(session_hash)=64)"
",num_oldcoins INT2 NOT NULL"
",num_newcoins INT2 NOT NULL"
",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)"
",old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub)"
",old_coin_sig BYTEA NOT NULL CHECK(LENGTH(old_coin_sig)=64)"
",amount_with_fee_val INT8 NOT NULL"
",amount_with_fee_frac INT4 NOT NULL"
",amount_with_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",melt_fee_val INT8 NOT NULL"
",melt_fee_frac INT4 NOT NULL"
",melt_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",PRIMARY KEY (session_hash, oldcoin_index)" /* a coin can be used only
once in a refresh session */
") ");
",num_newcoins INT2 NOT NULL"
",noreveal_index INT2 NOT NULL"
")");
/* Table with information about coins that have been refunded. (Technically
one of the deposit operations that a coin was involved with is refunded.)*/
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
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
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) */
link secret) */
SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_link "
"(session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash)"
",transfer_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)"
",link_secret_enc BYTEA NOT NULL"
",oldcoin_index INT2 NOT NULL"
",cnc_index INT2 NOT NULL"
")");
/* 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 */
PREPARE ("get_refresh_session",
"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"
",noreveal_index"
" FROM refresh_sessions "
@ -738,12 +727,19 @@ postgres_prepare (PGconn *db_conn)
PREPARE ("insert_refresh_session",
"INSERT INTO refresh_sessions "
"(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 "
",noreveal_index "
") VALUES "
"($1, $2, $3, $4);",
4, NULL);
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);",
11, NULL);
/* Used in #postgres_get_known_coin() to fetch
the denomination public key and signature for
@ -787,54 +783,19 @@ postgres_prepare (PGconn *db_conn)
" WHERE session_hash=$1 AND newcoin_index=$2",
2, NULL);
/* Used in #postgres_insert_refresh_melt to store information
about melted coins */
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",
/* Query the 'refresh_sessions' by coin public key */
PREPARE ("get_refresh_session_by_coin",
"SELECT"
" session_hash"
/* ",oldcoin_index" // not needed */
",coin_sig"
",old_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 coin_pub=$1",
" FROM refresh_sessions"
" WHERE old_coin_pub=$1",
1, NULL);
/* Query the 'refunds' by coin public key */
@ -856,28 +817,27 @@ postgres_prepare (PGconn *db_conn)
1, NULL);
/* Used in #postgres_insert_refresh_commit_links() to
/* Used in #postgres_insert_refresh_commit_link() to
store commitments */
PREPARE ("insert_refresh_commit_link",
"INSERT INTO refresh_commit_link "
"(session_hash"
",transfer_pub"
",cnc_index"
",oldcoin_index"
",link_secret_enc"
") VALUES "
"($1, $2, $3, $4, $5);",
5, NULL);
"($1, $2, $3, $4);",
4, NULL);
/* Used in #postgres_get_refresh_commit_links() to
/* Used in #postgres_get_refresh_commit_link() to
retrieve original commitments during /refresh/reveal */
PREPARE ("get_refresh_commit_link",
"SELECT"
" transfer_pub"
",link_secret_enc"
" FROM refresh_commit_link"
" WHERE session_hash=$1 AND cnc_index=$2 AND oldcoin_index=$3",
3, NULL);
" WHERE session_hash=$1 AND cnc_index=$2",
2, NULL);
/* Used in #postgres_insert_refresh_commit_coins() to
store coin commitments. */
@ -1110,10 +1070,9 @@ postgres_prepare (PGconn *db_conn)
efficient ways to express the same query. */
PREPARE ("get_link",
"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_commit_coin rcc USING (session_hash)"
" JOIN refresh_sessions rs USING (session_hash)"
" JOIN refresh_out rc USING (session_hash)"
" WHERE ro.session_hash=$1"
" 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
and the transfer public key. This is done by first finding
the session_hash(es) of all sessions the coin was melted into,
and then constraining the result to the selected "noreveal_index"
and the transfer public key to the corresponding index of the
old coin.
and then constraining the result to the selected "noreveal_index".
NOTE: This may (in theory) return multiple results, one per session
that the old coin was melted into. */
PREPARE ("get_transfer",
"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_sessions rs USING (session_hash)"
" WHERE rm.coin_pub=$1"
" AND rm.oldcoin_index = rcl.oldcoin_index"
" WHERE rs.old_coin_pub=$1"
" AND rcl.cnc_index=rs.noreveal_index",
1, NULL);
@ -2288,7 +2243,7 @@ postgres_test_deposit_done (void *cls,
{
/* NOTE: maybe wrong type for a 'boolean' */
uint32_t done;
uint32_t done = 0;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint32 ("done",
&done),
@ -2812,12 +2767,14 @@ postgres_get_refresh_session (void *cls,
sizeof (struct TALER_EXCHANGEDB_RefreshSession));
{
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint16 ("num_oldcoins",
&refresh_session->num_oldcoins),
GNUNET_PQ_result_spec_uint16 ("num_newcoins",
&refresh_session->num_newcoins),
GNUNET_PQ_result_spec_uint16 ("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
};
if (GNUNET_OK !=
@ -2829,6 +2786,16 @@ postgres_get_refresh_session (void *cls,
}
}
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;
}
@ -2852,59 +2819,20 @@ postgres_create_refresh_session (void *cls,
PGresult *result;
struct GNUNET_PQ_QueryParam params[] = {
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->noreveal_index),
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;
/* check if the coin is already known */
ret = get_known_coin (cls,
session,
&melt->coin.coin_pub,
&refresh_session->melt.coin.coin_pub,
NULL);
if (GNUNET_SYSERR == ret)
{
@ -2916,15 +2844,15 @@ postgres_insert_refresh_melt (void *cls,
if (GNUNET_SYSERR ==
insert_known_coin (cls,
session,
&melt->coin))
&refresh_session->melt.coin))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
}
/* insert the melt */
/* insert session */
result = GNUNET_PQ_exec_prepared (session->conn,
"insert_refresh_melt",
"insert_refresh_session",
params);
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
* in a given refresh operation.
@ -3369,48 +3210,42 @@ postgres_get_refresh_commit_coins (void *cls,
* @param session database connection to use
* @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension)
* @param num_links size of the @a links array to return
* @param[out] links array of link information to store return
* @param[out] link link information to store return
* @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success
*/
static int
postgres_insert_refresh_commit_links (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
uint16_t num_links,
const struct TALER_RefreshCommitLinkP *links)
postgres_insert_refresh_commit_link (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
const struct TALER_RefreshCommitLinkP *link)
{
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[] = {
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;
}
BREAK_DB_ERR (result);
PQclear (result);
return GNUNET_SYSERR;
}
if (0 != strcmp ("1", PQcmdTuples (result)))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
PQclear (result);
return GNUNET_OK;
}
@ -3423,64 +3258,56 @@ postgres_insert_refresh_commit_links (void *cls,
* @param session database connection to use
* @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension)
* @param num_links size of the @a commit_link array
* @param[out] links array of link information to return
* @param[out] link information to return
* @return #GNUNET_SYSERR on internal error,
* #GNUNET_NO if commitment was not found
* #GNUNET_OK on success
*/
static int
postgres_get_refresh_commit_links (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
uint16_t num_links,
struct TALER_RefreshCommitLinkP *links)
postgres_get_refresh_commit_link (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
struct TALER_RefreshCommitLinkP *link)
{
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[] = {
GNUNET_PQ_query_param_auto_from_type (session_hash),
GNUNET_PQ_query_param_uint16 (&cnc_index),
GNUNET_PQ_query_param_uint16 (&i),
GNUNET_PQ_query_param_end
BREAK_DB_ERR (result);
PQclear (result);
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",
&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,
"get_refresh_commit_link",
params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
if (GNUNET_YES !=
GNUNET_PQ_extract_result (result, rs, 0))
{
BREAK_DB_ERR (result);
PQclear (result);
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;
}
@ -3502,7 +3329,6 @@ postgres_get_melt_commitment (void *cls,
struct TALER_EXCHANGEDB_RefreshSession rs;
struct TALER_EXCHANGEDB_MeltCommitment *mc;
uint16_t cnc_index;
unsigned int i;
if (GNUNET_OK !=
postgres_get_refresh_session (cls,
@ -3512,17 +3338,6 @@ postgres_get_melt_commitment (void *cls,
return NULL;
mc = GNUNET_new (struct TALER_EXCHANGEDB_MeltCommitment);
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 *
sizeof (struct TALER_DenominationPublicKey));
if (GNUNET_OK !=
@ -3545,16 +3360,12 @@ postgres_get_melt_commitment (void *cls,
mc->num_newcoins,
mc->commit_coins[cnc_index]))
goto cleanup;
mc->commit_links[cnc_index]
= GNUNET_malloc (mc->num_oldcoins *
sizeof (struct TALER_RefreshCommitLinkP));
if (GNUNET_OK !=
postgres_get_refresh_commit_links (cls,
session,
session_hash,
cnc_index,
mc->num_oldcoins,
mc->commit_links[cnc_index]))
postgres_get_refresh_commit_link (cls,
session,
session_hash,
cnc_index,
&mc->commit_links[cnc_index]))
goto cleanup;
}
return mc;
@ -3803,8 +3614,8 @@ postgres_get_coin_transactions (void *cls,
struct TALER_EXCHANGEDB_TransactionList *tl;
result = GNUNET_PQ_exec_prepared (session->conn,
"get_deposit_with_coin_pub",
params);
"get_deposit_with_coin_pub",
params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
{
QUERY_ERR (result);
@ -3820,21 +3631,21 @@ postgres_get_coin_transactions (void *cls,
{
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint64 ("transaction_id",
&deposit->transaction_id),
&deposit->transaction_id),
TALER_PQ_result_spec_amount ("amount_with_fee",
&deposit->amount_with_fee),
TALER_PQ_result_spec_amount ("deposit_fee",
&deposit->deposit_fee),
GNUNET_PQ_result_spec_absolute_time ("timestamp",
&deposit->timestamp),
&deposit->timestamp),
GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
&deposit->refund_deadline),
&deposit->refund_deadline),
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
&deposit->merchant_pub),
&deposit->merchant_pub),
GNUNET_PQ_result_spec_auto_from_type ("h_contract",
&deposit->h_contract),
&deposit->h_contract),
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&deposit->h_wire),
&deposit->h_wire),
TALER_PQ_result_spec_json ("wire",
&deposit->wire),
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 */
result = GNUNET_PQ_exec_prepared (session->conn,
"get_refresh_melt_by_coin",
params);
"get_refresh_session_by_coin",
params);
if (PGRES_TUPLES_OK != PQresultStatus (result))
{
BREAK_DB_ERR (result);
@ -3891,10 +3702,10 @@ postgres_get_coin_transactions (void *cls,
{
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_auto_from_type ("session_hash",
&melt->session_hash),
&melt->session_hash),
/* oldcoin_index not needed */
GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
&melt->coin_sig),
GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
&melt->coin_sig),
TALER_PQ_result_spec_amount ("amount_with_fee",
&melt->amount_with_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->get_refresh_session = &postgres_get_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->get_refresh_order = &postgres_get_refresh_order;
plugin->insert_refresh_commit_coins = &postgres_insert_refresh_commit_coins;
plugin->get_refresh_commit_coins = &postgres_get_refresh_commit_coins;
plugin->insert_refresh_commit_links = &postgres_insert_refresh_commit_links;
plugin->get_refresh_commit_links = &postgres_get_refresh_commit_links;
plugin->insert_refresh_commit_link = &postgres_insert_refresh_commit_link;
plugin->get_refresh_commit_link = &postgres_get_refresh_commit_link;
plugin->get_melt_commitment = &postgres_get_melt_commitment;
plugin->free_melt_commitment = &common_free_melt_commitment;
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
test_melting (struct TALER_EXCHANGEDB_Session *session)
{
#define MELT_OLD_COINS 10
struct TALER_EXCHANGEDB_RefreshSession refresh_session;
struct TALER_EXCHANGEDB_RefreshSession ret_refresh_session;
struct GNUNET_HashCode session_hash;
struct DenomKeyPair *dkp;
struct DenomKeyPair **new_dkp;
/* struct TALER_CoinPublicInfo *coins; */
struct TALER_EXCHANGEDB_RefreshMelt *melts;
struct TALER_EXCHANGEDB_RefreshMelt *meltp;
struct TALER_DenominationPublicKey *new_denom_pubs;
struct TALER_DenominationPublicKey *ret_denom_pubs;
struct TALER_EXCHANGEDB_MeltCommitment *mc;
@ -475,15 +474,40 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
ret = GNUNET_SYSERR;
RND_BLK (&refresh_session);
RND_BLK (&session_hash);
melts = NULL;
dkp = NULL;
new_dkp = NULL;
new_denom_pubs = NULL;
ret_denom_pubs = NULL;
/* create and test a refresh session */
refresh_session.num_oldcoins = MELT_OLD_COINS;
refresh_session.num_newcoins = 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,
session,
&session_hash,
@ -492,72 +516,35 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
session,
&session_hash,
&ret_refresh_session));
FAILIF (0 != memcmp (&ret_refresh_session,
&refresh_session,
sizeof (refresh_session)));
FAILIF (ret_refresh_session.num_newcoins != refresh_session.num_newcoins);
FAILIF (ret_refresh_session.noreveal_index != refresh_session.noreveal_index);
/* create a denomination (value: 1; fraction: 100) */
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++)
/* check refresh sesison melt data */
{
struct GNUNET_HashCode hc;
struct TALER_EXCHANGEDB_RefreshMelt *ret_melt;
RND_BLK (&melts[cnt].coin.coin_pub);
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));
ret_melt = &ret_refresh_session.melt;
FAILIF (0 != GNUNET_CRYPTO_rsa_signature_cmp
(ret_melt.coin.denom_sig.rsa_signature,
melts[cnt].coin.denom_sig.rsa_signature));
FAILIF (0 != memcmp (&ret_melt.coin.coin_pub,
&melts[cnt].coin.coin_pub,
sizeof (ret_melt.coin.coin_pub)));
(ret_melt->coin.denom_sig.rsa_signature,
meltp->coin.denom_sig.rsa_signature));
FAILIF (0 != memcmp (&ret_melt->coin.coin_pub,
&meltp->coin.coin_pub,
sizeof (ret_melt->coin.coin_pub)));
FAILIF (0 != GNUNET_CRYPTO_rsa_public_key_cmp
(ret_melt.coin.denom_pub.rsa_public_key,
melts[cnt].coin.denom_pub.rsa_public_key));
FAILIF (0 != memcmp (&ret_melt.coin_sig,
&melts[cnt].coin_sig,
sizeof (ret_melt.coin_sig)));
FAILIF (0 != memcmp (&ret_melt.session_hash,
&melts[cnt].session_hash,
sizeof (ret_melt.session_hash)));
FAILIF (0 != TALER_amount_cmp (&ret_melt.amount_with_fee,
&melts[cnt].amount_with_fee));
FAILIF (0 != TALER_amount_cmp (&ret_melt.melt_fee,
&melts[cnt].melt_fee));
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);
(ret_melt->coin.denom_pub.rsa_public_key,
meltp->coin.denom_pub.rsa_public_key));
FAILIF (0 != memcmp (&ret_melt->coin_sig,
&meltp->coin_sig,
sizeof (ret_melt->coin_sig)));
FAILIF (0 != memcmp (&ret_melt->session_hash,
&meltp->session_hash,
sizeof (ret_melt->session_hash)));
FAILIF (0 != TALER_amount_cmp (&ret_melt->amount_with_fee,
&meltp->amount_with_fee));
FAILIF (0 != TALER_amount_cmp (&ret_melt->melt_fee,
&meltp->melt_fee));
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);
}
new_dkp = GNUNET_new_array (MELT_NEW_COINS, struct DenomKeyPair *);
new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
@ -619,15 +606,10 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
drop:
if (NULL != dkp)
destroy_denom_key_pair (dkp);
if (NULL != melts)
{
for (cnt = 0; cnt < MELT_OLD_COINS; cnt++)
GNUNET_CRYPTO_rsa_signature_free (melts[cnt].coin.denom_sig.rsa_signature);
GNUNET_free (melts);
}
GNUNET_CRYPTO_rsa_signature_free (meltp->coin.denom_sig.rsa_signature);
for (cnt = 0;
(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++)
GNUNET_CRYPTO_rsa_public_key_free (ret_denom_pubs[cnt].rsa_public_key);
GNUNET_free_non_null (ret_denom_pubs);

View File

@ -711,12 +711,12 @@ typedef void
*/
struct TALER_EXCHANGE_ReserveWithdrawHandle *
TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_DenominationBlindingKey *blinding_key,
TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
void *res_cb_cls);
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
const struct TALER_DenominationBlindingKey *blinding_key,
TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
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.
*
* This function does verify that the given request data is internally
* consistent. However, the @a melts_sigs are only verified if @a
* check_sigs is set to #GNUNET_YES, as this may be relatively
* consistent. However, the @a melts_sig is only verified if @a
* check_sig is set to #GNUNET_YES, as this may be relatively
* expensive and should be redundant.
*
* 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
* processing. This function is also thread-safe.
*
* @param num_melts number of coins that are being melted (typically 1)
* @param melt_privs array of @a num_melts private keys of the coins to melt
* @param melt_amounts array of @a num_melts amounts specifying how much
* each coin will contribute to the melt (including fee)
* @param melt_sigs array of @a num_melts signatures affirming the
* @param melt_priv private keys of the coin to melt
* @param melt_amount amount specifying how much
* the coin will contribute to the melt (including fee)
* @param melt_sig signatures affirming the
* validity of the public keys corresponding to the
* @a melt_privs private keys
* @param melt_pks array of @a num_melts denomination key information
* records corresponding to the @a melt_sigs
* @a melt_priv private key
* @param melt_pk denomination key information
* record corresponding to the @a melt_sig
* 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 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
@ -775,12 +774,11 @@ TALER_EXCHANGE_reserve_withdraw_cancel (struct TALER_EXCHANGE_ReserveWithdrawHan
* Non-null results should be freed using #GNUNET_free().
*/
char *
TALER_EXCHANGE_refresh_prepare (unsigned int num_melts,
const struct TALER_CoinSpendPrivateKeyP *melt_privs,
const struct TALER_Amount *melt_amounts,
const struct TALER_DenominationSignature *melt_sigs,
const struct TALER_EXCHANGE_DenomPublicKey *melt_pks,
int check_sigs,
TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_priv,
const struct TALER_Amount *melt_amount,
const struct TALER_DenominationSignature *melt_sig,
const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
int check_sig,
unsigned int fresh_pks_len,
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks,
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.
*/
@ -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
* 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
{
/**
* Number of coins we are melting.
*/
uint16_t num_oldcoins;
/**
* Number of new coins we are creating.
*/
uint16_t num_newcoins;
/**
* Array of @e num_oldcoins melt operation details.
*/
struct TALER_EXCHANGEDB_RefreshMelt *melts;
/**
* Array of @e num_newcoins denomination keys
*/
@ -583,9 +573,9 @@ struct TALER_EXCHANGEDB_MeltCommitment
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);
/**
* 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
* 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 session database connection to use
* @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension), relating to #TALER_CNC_KAPPA
* @param num_links size of the @a commit_link array
* @param commit_links array of link information to store
* @param cnc_index cut and choose index, relating to #TALER_CNC_KAPPA
* @param link link information to store
* @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success
*/
int
(*insert_refresh_commit_links) (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
uint16_t num_links,
const struct TALER_RefreshCommitLinkP *commit_links);
(*insert_refresh_commit_link) (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
const struct TALER_RefreshCommitLinkP *link);
/**
* Obtain the commited (encrypted) refresh link data
@ -1266,19 +1217,17 @@ struct TALER_EXCHANGEDB_Plugin
* @param session database connection to use
* @param session_hash hash to identify refresh session
* @param cnc_index cut and choose index (1st dimension)
* @param num_links size of the @a links array to return
* @param[out] links array link information to return
* @param[out] link information to return
* @return #GNUNET_SYSERR on internal error,
* #GNUNET_NO if commitment was not found
* #GNUNET_OK on success
*/
int
(*get_refresh_commit_links) (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
uint16_t num_links,
struct TALER_RefreshCommitLinkP *links);
(*get_refresh_commit_link) (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct GNUNET_HashCode *session_hash,
uint16_t cnc_index,
struct TALER_RefreshCommitLinkP *link);
/**