fixing #3814 by removing ability to melt multiple oldcoins at the same time
This commit is contained in:
parent
068dbf020b
commit
c8b9370413
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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"),
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user