fixing #5178
This commit is contained in:
parent
9041840d6e
commit
499247a480
@ -753,6 +753,45 @@ reserve expired.
|
||||
{% endif %}
|
||||
|
||||
|
||||
\subsection{Hanging refresh operations}
|
||||
|
||||
This section describes cases where the exchange booked a
|
||||
coin as spent from {\tt /refresh/melt} but where the
|
||||
wallet did not yet complete {\tt /refresh/reveal}. This
|
||||
may happen even if the exchange is correct.
|
||||
|
||||
|
||||
{% if data.refresh_hanging|length() == 0 %}
|
||||
{\bf All melted coins were refreshed.}
|
||||
{% else %}
|
||||
\begin{longtable}{p{1.5cm}|c|rl}
|
||||
{\bf Key} & {\bf row} & \multicolumn{2}{|c|}{ {\bf Amount}} \\
|
||||
\hline \hline
|
||||
\endfirsthead
|
||||
{\bf Key} & {\bf row} & \multicolumn{2}{|c|}{ {\bf Amount}} \\
|
||||
\hline \hline
|
||||
\endhead
|
||||
\hline \hline
|
||||
{\bf Key} & {\bf row} & \multicolumn{2}{|c|}{ {\bf Amount}} \\
|
||||
\endfoot
|
||||
\hline
|
||||
{\bf Sum} & &
|
||||
{{ data.total_refresh_hanging.value}}.{{ data.total_refresh_hanging.fraction}} & {{ data.total_refresh_hanging.currency}} \\
|
||||
\caption{Refresh operations hanging.}
|
||||
\label{table:refresh:hanging}
|
||||
\endlastfoot
|
||||
{% for item in data.refresh_hanging %}
|
||||
\multicolumn{4}{l}{ {\tt {{ item.coin_pub }} } } \\
|
||||
\nopagebreak
|
||||
&
|
||||
{{ item.row }} &
|
||||
{{ item.amount.value }}.{{ item.amount.fraction }} &
|
||||
{{ item.amount.currency }} \\ \hline
|
||||
{% endfor %}
|
||||
\end{longtable}
|
||||
{% endif %}
|
||||
|
||||
|
||||
\subsection{Denomination key invalid at time of withdrawal}
|
||||
|
||||
This section lists cases where a denomination key was not valid for
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2016, 2017 Inria
|
||||
Copyright (C) 2016, 2017 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero Public License as published by the Free Software
|
||||
@ -275,6 +275,17 @@ static json_t *report_bad_sig_losses;
|
||||
*/
|
||||
static struct TALER_Amount total_bad_sig_loss;
|
||||
|
||||
/**
|
||||
* Array of refresh transactions where the /refresh/reveal has not yet
|
||||
* happened (and may of course never happen).
|
||||
*/
|
||||
static json_t *report_refreshs_hanging;
|
||||
|
||||
/**
|
||||
* Total amount lost by operations for which signatures were invalid.
|
||||
*/
|
||||
static struct TALER_Amount total_refresh_hanging;
|
||||
|
||||
|
||||
/* ***************************** Report logic **************************** */
|
||||
|
||||
@ -1893,7 +1904,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
}
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_REFRESH_MELT:
|
||||
amount_with_fee = &tl->details.melt->amount_with_fee;
|
||||
amount_with_fee = &tl->details.melt->session.amount_with_fee;
|
||||
fee = &tl->details.melt->melt_fee;
|
||||
fee_dki = &dki->properties.fee_refresh;
|
||||
if (GNUNET_OK !=
|
||||
@ -2104,7 +2115,7 @@ wire_transfer_information_cb (void *cls,
|
||||
coin = &tl->details.deposit->coin;
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_REFRESH_MELT:
|
||||
coin = &tl->details.melt->coin;
|
||||
coin = &tl->details.melt->session.coin;
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_REFUND:
|
||||
coin = &tl->details.refund->coin;
|
||||
@ -2967,6 +2978,54 @@ withdraw_cb (void *cls,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #reveal_data_cb().
|
||||
*/
|
||||
struct RevealContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Denomination public keys of the new coins.
|
||||
*/
|
||||
struct TALER_DenominationPublicKey *new_dps;
|
||||
|
||||
/**
|
||||
* Size of the @a new_dp and @a new_dki arrays.
|
||||
*/
|
||||
unsigned int num_newcoins;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function called with information about a refresh order.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the row in our database
|
||||
* @param num_newcoins size of the @a rrcs array
|
||||
* @param rrcs array of @a num_newcoins information about coins to be created
|
||||
* @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1
|
||||
* @param tprivs array of @e num_tprivs transfer private keys
|
||||
* @param tp transfer public key information
|
||||
*/
|
||||
static void
|
||||
reveal_data_cb (void *cls,
|
||||
uint32_t num_newcoins,
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
|
||||
unsigned int num_tprivs,
|
||||
const struct TALER_TransferPrivateKeyP *tprivs,
|
||||
const struct TALER_TransferPublicKeyP *tp)
|
||||
{
|
||||
struct RevealContext *rctx = cls;
|
||||
|
||||
rctx->num_newcoins = num_newcoins;
|
||||
rctx->new_dps = GNUNET_new_array (num_newcoins,
|
||||
struct TALER_DenominationPublicKey);
|
||||
for (unsigned int i=0;i<num_newcoins;i++)
|
||||
rctx->new_dps[i].rsa_public_key
|
||||
= GNUNET_CRYPTO_rsa_public_key_dup (rrcs[i].denom_pub.rsa_public_key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about coins that were melted, with the
|
||||
* goal of auditing the refresh's execution. Verifies the signature
|
||||
@ -2980,7 +3039,6 @@ withdraw_cb (void *cls,
|
||||
* @param coin_pub public key of the coin
|
||||
* @param coin_sig signature from the coin
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @param num_newcoins how many coins were issued
|
||||
* @param noreveal_index which index was picked by the exchange in cut-and-choose
|
||||
* @param session_hash what is the session hash
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
@ -2992,9 +3050,8 @@ refresh_session_cb (void *cls,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_CoinSpendSignatureP *coin_sig,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
uint16_t num_newcoins,
|
||||
uint16_t noreveal_index,
|
||||
const struct GNUNET_HashCode *session_hash)
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_RefreshCommitmentP *rc)
|
||||
{
|
||||
struct CoinContext *cc = cls;
|
||||
struct TALER_RefreshMeltCoinAffirmationPS rmc;
|
||||
@ -3020,7 +3077,7 @@ refresh_session_cb (void *cls,
|
||||
/* verify melt signature */
|
||||
rmc.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
|
||||
rmc.purpose.size = htonl (sizeof (rmc));
|
||||
rmc.session_hash = *session_hash;
|
||||
rmc.rc = *rc;
|
||||
TALER_amount_hton (&rmc.amount_with_fee,
|
||||
amount_with_fee);
|
||||
rmc.melt_fee = dki->properties.fee_refresh;
|
||||
@ -3050,33 +3107,57 @@ refresh_session_cb (void *cls,
|
||||
TALER_amount2s (amount_with_fee));
|
||||
|
||||
{
|
||||
struct TALER_DenominationPublicKey new_dp[num_newcoins];
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *new_dki[num_newcoins];
|
||||
struct RevealContext reveal_ctx;
|
||||
struct TALER_Amount refresh_cost;
|
||||
int err;
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (amount_with_fee->currency,
|
||||
&refresh_cost));
|
||||
qs = edb->get_refresh_order (edb->cls,
|
||||
memset (&reveal_ctx,
|
||||
0,
|
||||
sizeof (reveal_ctx));
|
||||
qs = edb->get_refresh_reveal (edb->cls,
|
||||
esession,
|
||||
session_hash,
|
||||
num_newcoins,
|
||||
new_dp);
|
||||
if (0 >= qs)
|
||||
rc,
|
||||
&reveal_data_cb,
|
||||
&reveal_ctx);
|
||||
if (0 > qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
cc->qs = GNUNET_DB_STATUS_HARD_ERROR;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) ||
|
||||
(0 == reveal_ctx.num_newcoins) )
|
||||
{
|
||||
/* This can happen if /refresh/reveal was not yet called or only
|
||||
with invalid data, even if the exchange is correctly
|
||||
operating. We still report it. */
|
||||
report (report_refreshs_hanging,
|
||||
json_pack ("{s:I, s:o, s:o}",
|
||||
"row", (json_int_t) rowid,
|
||||
"amount", TALER_JSON_from_amount (amount_with_fee),
|
||||
"coin_pub", GNUNET_JSON_from_data_auto (coin_pub)));
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
TALER_amount_add (&total_refresh_hanging,
|
||||
&total_refresh_hanging,
|
||||
amount_with_fee));
|
||||
return GNUNET_OK;
|
||||
}
|
||||
// FIXME: free reveal_ctx.num_newcoins later!
|
||||
|
||||
{
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *new_dkis[reveal_ctx.num_newcoins];
|
||||
|
||||
/* Update outstanding amounts for all new coin's denominations, and check
|
||||
that the resulting amounts are consistent with the value being refreshed. */
|
||||
err = GNUNET_NO;
|
||||
for (unsigned int i=0;i<num_newcoins;i++)
|
||||
for (unsigned int i=0;i<reveal_ctx.num_newcoins;i++)
|
||||
{
|
||||
/* lookup new coin denomination key */
|
||||
qs = get_denomination_info (&new_dp[i],
|
||||
&new_dki[i],
|
||||
qs = get_denomination_info (&reveal_ctx.new_dps[i],
|
||||
&new_dkis[i],
|
||||
NULL);
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
||||
{
|
||||
@ -3084,23 +3165,26 @@ refresh_session_cb (void *cls,
|
||||
cc->qs = qs;
|
||||
err = GNUNET_YES;
|
||||
}
|
||||
GNUNET_CRYPTO_rsa_public_key_free (new_dp[i].rsa_public_key);
|
||||
new_dp[i].rsa_public_key = NULL;
|
||||
GNUNET_CRYPTO_rsa_public_key_free (reveal_ctx.new_dps[i].rsa_public_key);
|
||||
reveal_ctx.new_dps[i].rsa_public_key = NULL;
|
||||
}
|
||||
GNUNET_free (reveal_ctx.new_dps);
|
||||
reveal_ctx.new_dps = NULL;
|
||||
|
||||
if (err)
|
||||
return GNUNET_SYSERR;
|
||||
|
||||
/* calculate total refresh cost */
|
||||
for (unsigned int i=0;i<num_newcoins;i++)
|
||||
for (unsigned int i=0;i<reveal_ctx.num_newcoins;i++)
|
||||
{
|
||||
/* update cost of refresh */
|
||||
struct TALER_Amount fee;
|
||||
struct TALER_Amount value;
|
||||
|
||||
TALER_amount_ntoh (&fee,
|
||||
&new_dki[i]->properties.fee_withdraw);
|
||||
&new_dkis[i]->properties.fee_withdraw);
|
||||
TALER_amount_ntoh (&value,
|
||||
&new_dki[i]->properties.value);
|
||||
&new_dkis[i]->properties.value);
|
||||
if ( (GNUNET_OK !=
|
||||
TALER_amount_add (&refresh_cost,
|
||||
&refresh_cost,
|
||||
@ -3147,24 +3231,24 @@ refresh_session_cb (void *cls,
|
||||
}
|
||||
|
||||
/* update outstanding denomination amounts */
|
||||
for (unsigned int i=0;i<num_newcoins;i++)
|
||||
for (unsigned int i=0;i<reveal_ctx.num_newcoins;i++)
|
||||
{
|
||||
struct DenominationSummary *dsi;
|
||||
struct TALER_Amount value;
|
||||
|
||||
dsi = get_denomination_summary (cc,
|
||||
new_dki[i],
|
||||
&new_dki[i]->properties.denom_hash);
|
||||
new_dkis[i],
|
||||
&new_dkis[i]->properties.denom_hash);
|
||||
if (NULL == dsi)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TALER_amount_ntoh (&value,
|
||||
&new_dki[i]->properties.value);
|
||||
&new_dkis[i]->properties.value);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Created fresh coin in denomination `%s' of value %s\n",
|
||||
GNUNET_h2s (&new_dki[i]->properties.denom_hash),
|
||||
GNUNET_h2s (&new_dkis[i]->properties.denom_hash),
|
||||
TALER_amount2s (&value));
|
||||
if (GNUNET_OK !=
|
||||
TALER_amount_add (&dsi->denom_balance,
|
||||
@ -3186,7 +3270,7 @@ refresh_session_cb (void *cls,
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"New balance of denomination `%s' is %s\n",
|
||||
GNUNET_h2s (&new_dki[i]->properties.denom_hash),
|
||||
GNUNET_h2s (&new_dkis[i]->properties.denom_hash),
|
||||
TALER_amount2s (&dsi->denom_balance));
|
||||
if (GNUNET_OK !=
|
||||
TALER_amount_add (&total_escrow_balance,
|
||||
@ -3208,6 +3292,7 @@ refresh_session_cb (void *cls,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* update old coin's denomination balance */
|
||||
dso = get_denomination_summary (cc,
|
||||
@ -4081,6 +4166,9 @@ run (void *cls,
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (currency,
|
||||
&total_bad_sig_loss));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (currency,
|
||||
&total_refresh_hanging));
|
||||
GNUNET_assert (NULL !=
|
||||
(report_emergencies = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
@ -4103,6 +4191,8 @@ run (void *cls,
|
||||
(report_amount_arithmetic_inconsistencies = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
(report_bad_sig_losses = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
(report_refreshs_hanging = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
(report_fee_time_inconsistencies = json_array ()));
|
||||
setup_sessions_and_run ();
|
||||
@ -4129,7 +4219,7 @@ run (void *cls,
|
||||
" s:o, s:o, s:o, s:o, s:o,"
|
||||
" s:o, s:o, s:o, s:o, s:o,"
|
||||
" s:o, s:o, s:o, s:o, s:o,"
|
||||
" s:o }",
|
||||
" s:o, s:o, s:o }",
|
||||
/* blocks of 5 for easier counting/matching to format string */
|
||||
/* block */
|
||||
"reserve_balance_insufficient_inconsistencies",
|
||||
@ -4199,7 +4289,11 @@ run (void *cls,
|
||||
TALER_JSON_from_amount (&total_aggregation_fee_income),
|
||||
/* block */
|
||||
"wire_fee_time_inconsistencies",
|
||||
report_fee_time_inconsistencies);
|
||||
report_fee_time_inconsistencies,
|
||||
"total_refresh_hanging",
|
||||
TALER_JSON_from_amount (&total_refresh_hanging),
|
||||
"refresh_hanging",
|
||||
report_refreshs_hanging);
|
||||
GNUNET_break (NULL != report);
|
||||
json_dumpf (report,
|
||||
stdout,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
|
||||
Copyright (C) 2014, 2015, 2016, 2017 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Lesser General Public License as published by the Free Software
|
||||
@ -623,7 +623,7 @@ static void
|
||||
melt_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
uint16_t noreveal_index,
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *full_response)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2015-2017 Inria & GNUnet e.V.
|
||||
Copyright (C) 2015-2017 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -143,8 +143,8 @@ TALER_EXCHANGE_verify_coin_history (const char *currency,
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||
&sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("session_hash",
|
||||
&rm.session_hash),
|
||||
GNUNET_JSON_spec_fixed_auto ("rc",
|
||||
&rm.rc),
|
||||
TALER_JSON_spec_amount_nbo ("melt_fee",
|
||||
&rm.melt_fee),
|
||||
GNUNET_JSON_spec_end()
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2015, 2016 GNUnet e.V.
|
||||
Copyright (C) 2015, 2016, 2017 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -101,7 +101,7 @@ struct MeltDataP
|
||||
/**
|
||||
* Hash over the melting session.
|
||||
*/
|
||||
struct GNUNET_HashCode melt_session_hash;
|
||||
struct TALER_RefreshCommitmentP rc;
|
||||
|
||||
/**
|
||||
* Number of coins we are melting, in NBO
|
||||
@ -180,9 +180,9 @@ struct MeltData
|
||||
{
|
||||
|
||||
/**
|
||||
* Hash over the melting session.
|
||||
* Hash over the committed data during refresh operation.
|
||||
*/
|
||||
struct GNUNET_HashCode melt_session_hash;
|
||||
struct TALER_RefreshCommitmentP rc;
|
||||
|
||||
/**
|
||||
* Number of coins we are creating
|
||||
@ -466,7 +466,6 @@ deserialize_denomination_key (struct TALER_DenominationPublicKey *dk,
|
||||
dk->rsa_public_key
|
||||
= GNUNET_CRYPTO_rsa_public_key_decode (&buf[sizeof (uint32_t)],
|
||||
pbuf_size);
|
||||
|
||||
if (NULL == dk->rsa_public_key)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -542,8 +541,6 @@ serialize_melt_data (const struct MeltData *md,
|
||||
size_t size;
|
||||
size_t asize;
|
||||
char *buf;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
|
||||
size = 0;
|
||||
asize = (size_t) -1; /* make the compiler happy */
|
||||
@ -563,18 +560,18 @@ serialize_melt_data (const struct MeltData *md,
|
||||
asize = size; /* just for invariant check later */
|
||||
size = sizeof (struct MeltDataP);
|
||||
mdp = (struct MeltDataP *) buf;
|
||||
mdp->melt_session_hash = md->melt_session_hash;
|
||||
mdp->rc = md->rc;
|
||||
mdp->num_fresh_coins = htons (md->num_fresh_coins);
|
||||
}
|
||||
size += serialize_melted_coin (&md->melted_coin,
|
||||
buf,
|
||||
size);
|
||||
for (i=0;i<md->num_fresh_coins;i++)
|
||||
for (unsigned int i=0;i<md->num_fresh_coins;i++)
|
||||
size += serialize_denomination_key (&md->fresh_pks[i],
|
||||
buf,
|
||||
size);
|
||||
for (i=0;i<TALER_CNC_KAPPA;i++)
|
||||
for(j=0;j<md->num_fresh_coins;j++)
|
||||
for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
|
||||
for(unsigned int j=0;j<md->num_fresh_coins;j++)
|
||||
size += serialize_fresh_coin (&md->fresh_coins[i][j],
|
||||
buf,
|
||||
size);
|
||||
@ -607,7 +604,7 @@ deserialize_melt_data (const char *buf,
|
||||
buf,
|
||||
sizeof (struct MeltDataP));
|
||||
md = GNUNET_new (struct MeltData);
|
||||
md->melt_session_hash = mdp.melt_session_hash;
|
||||
md->rc = mdp.rc;
|
||||
md->num_fresh_coins = ntohs (mdp.num_fresh_coins);
|
||||
md->fresh_pks = GNUNET_new_array (md->num_fresh_coins,
|
||||
struct TALER_DenominationPublicKey);
|
||||
@ -700,34 +697,14 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
|
||||
{
|
||||
struct MeltData md;
|
||||
char *buf;
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
struct TALER_Amount total;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_TransferSecretP trans_sec[TALER_CNC_KAPPA];
|
||||
struct TALER_RefreshCommitmentEntry rce[TALER_CNC_KAPPA];
|
||||
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&melt_priv->eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
/* build up melt data structure */
|
||||
for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
|
||||
{
|
||||
struct GNUNET_CRYPTO_EcdhePrivateKey *tpk;
|
||||
struct TALER_TransferPublicKeyP tp;
|
||||
|
||||
tpk = GNUNET_CRYPTO_ecdhe_key_create ();
|
||||
md.melted_coin.transfer_priv[i].ecdhe_priv = *tpk;
|
||||
GNUNET_free (tpk);
|
||||
|
||||
GNUNET_CRYPTO_ecdhe_key_get_public (&md.melted_coin.transfer_priv[i].ecdhe_priv,
|
||||
&tp.ecdhe_pub);
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
&tp,
|
||||
sizeof (struct TALER_TransferPublicKeyP));
|
||||
/* DH */
|
||||
TALER_link_derive_transfer_secret (melt_priv,
|
||||
&md.melted_coin.transfer_priv[i],
|
||||
&trans_sec[i]);
|
||||
}
|
||||
md.num_fresh_coins = fresh_pks_len;
|
||||
md.melted_coin.coin_priv = *melt_priv;
|
||||
md.melted_coin.melt_amount_with_fee = *melt_amount;
|
||||
@ -735,6 +712,9 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
|
||||
md.melted_coin.original_value = melt_pk->value;
|
||||
md.melted_coin.expire_deposit
|
||||
= melt_pk->expire_deposit;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (melt_amount->currency,
|
||||
&total));
|
||||
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
|
||||
@ -742,40 +722,24 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
|
||||
md.fresh_pks = GNUNET_new_array (fresh_pks_len,
|
||||
struct TALER_DenominationPublicKey);
|
||||
for (unsigned int i=0;i<fresh_pks_len;i++)
|
||||
{
|
||||
md.fresh_pks[i].rsa_public_key
|
||||
= GNUNET_CRYPTO_rsa_public_key_dup (fresh_pks[i].key.rsa_public_key);
|
||||
for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
|
||||
{
|
||||
md.fresh_coins[i] = GNUNET_new_array (fresh_pks_len,
|
||||
struct TALER_PlanchetSecretsP);
|
||||
for (unsigned int j=0;j<fresh_pks_len;j++)
|
||||
{
|
||||
TALER_planchet_setup_refresh (&trans_sec[i],
|
||||
j,
|
||||
&md.fresh_coins[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* verify that melt_amount is above total cost */
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (melt_amount->currency,
|
||||
&total));
|
||||
for (unsigned int j=0;j<fresh_pks_len;j++)
|
||||
{
|
||||
if ( (GNUNET_OK !=
|
||||
TALER_amount_add (&total,
|
||||
&total,
|
||||
&fresh_pks[j].value)) ||
|
||||
&fresh_pks[i].value)) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_amount_add (&total,
|
||||
&total,
|
||||
&fresh_pks[j].fee_withdraw)) )
|
||||
&fresh_pks[i].fee_withdraw)) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
free_melt_data (&md);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* verify that melt_amount is above total cost */
|
||||
if (1 ==
|
||||
TALER_amount_cmp (&total,
|
||||
melt_amount) )
|
||||
@ -787,63 +751,64 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* next, add all of the hashes from the denomination keys to the
|
||||
hash_context */
|
||||
for (unsigned int i=0;i<fresh_pks_len;i++)
|
||||
/* build up coins */
|
||||
for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
|
||||
{
|
||||
char *buf;
|
||||
size_t buf_size;
|
||||
struct GNUNET_CRYPTO_EcdhePrivateKey *tpk;
|
||||
|
||||
buf_size = GNUNET_CRYPTO_rsa_public_key_encode (fresh_pks[i].key.rsa_public_key,
|
||||
&buf);
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
buf,
|
||||
buf_size);
|
||||
GNUNET_free (buf);
|
||||
}
|
||||
{
|
||||
struct TALER_AmountNBO melt_amountn;
|
||||
tpk = GNUNET_CRYPTO_ecdhe_key_create ();
|
||||
md.melted_coin.transfer_priv[i].ecdhe_priv = *tpk;
|
||||
GNUNET_free (tpk);
|
||||
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
&coin_pub,
|
||||
sizeof (struct TALER_CoinSpendPublicKeyP));
|
||||
TALER_amount_hton (&melt_amountn,
|
||||
melt_amount);
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
&melt_amountn,
|
||||
sizeof (struct TALER_AmountNBO));
|
||||
|
||||
}
|
||||
for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
|
||||
GNUNET_CRYPTO_ecdhe_key_get_public (&md.melted_coin.transfer_priv[i].ecdhe_priv,
|
||||
&rce[i].transfer_pub.ecdhe_pub);
|
||||
TALER_link_derive_transfer_secret (melt_priv,
|
||||
&md.melted_coin.transfer_priv[i],
|
||||
&trans_sec[i]);
|
||||
md.fresh_coins[i] = GNUNET_new_array (fresh_pks_len,
|
||||
struct TALER_PlanchetSecretsP);
|
||||
rce[i].new_coins = GNUNET_new_array (fresh_pks_len,
|
||||
struct TALER_RefreshCoinData);
|
||||
for (unsigned int j=0;j<fresh_pks_len;j++)
|
||||
{
|
||||
for (unsigned int j = 0; j < fresh_pks_len; j++)
|
||||
{
|
||||
const struct TALER_PlanchetSecretsP *fc; /* coin this is about */
|
||||
struct TALER_PlanchetSecretsP *fc = &md.fresh_coins[i][j];
|
||||
struct TALER_RefreshCoinData *rcd = &rce[i].new_coins[j];
|
||||
struct TALER_PlanchetDetail pd;
|
||||
|
||||
fc = &md.fresh_coins[i][j];
|
||||
TALER_planchet_setup_refresh (&trans_sec[i],
|
||||
j,
|
||||
fc);
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&md.fresh_pks[j],
|
||||
fc,
|
||||
&pd))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_CRYPTO_hash_context_abort (hash_context);
|
||||
free_melt_data (&md);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
pd.coin_ev,
|
||||
pd.coin_ev_size);
|
||||
GNUNET_free (pd.coin_ev);
|
||||
rcd->dk = &md.fresh_pks[j];
|
||||
rcd->coin_ev = pd.coin_ev;
|
||||
rcd->coin_ev_size = pd.coin_ev_size;
|
||||
}
|
||||
}
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||
&md.melt_session_hash);
|
||||
|
||||
/* Compute refresh commitment */
|
||||
TALER_refresh_get_commitment (&md.rc,
|
||||
TALER_CNC_KAPPA,
|
||||
fresh_pks_len,
|
||||
rce,
|
||||
&coin_pub,
|
||||
melt_amount);
|
||||
/* finally, serialize everything */
|
||||
buf = serialize_melt_data (&md,
|
||||
res_size);
|
||||
for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < fresh_pks_len; j++)
|
||||
GNUNET_free_non_null (rce[i].new_coins[j].coin_ev);
|
||||
GNUNET_free_non_null (rce[i].new_coins);
|
||||
}
|
||||
free_melt_data (&md);
|
||||
return buf;
|
||||
}
|
||||
@ -909,14 +874,14 @@ static int
|
||||
verify_refresh_melt_signature_ok (struct TALER_EXCHANGE_RefreshMeltHandle *rmh,
|
||||
const json_t *json,
|
||||
struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
uint16_t *noreveal_index)
|
||||
uint32_t *noreveal_index)
|
||||
{
|
||||
struct TALER_ExchangeSignatureP exchange_sig;
|
||||
const struct TALER_EXCHANGE_Keys *key_state;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub", exchange_pub),
|
||||
GNUNET_JSON_spec_uint16 ("noreveal_index", noreveal_index),
|
||||
GNUNET_JSON_spec_uint32 ("noreveal_index", noreveal_index),
|
||||
GNUNET_JSON_spec_end()
|
||||
};
|
||||
struct TALER_RefreshMeltConfirmationPS confirm;
|
||||
@ -950,9 +915,8 @@ verify_refresh_melt_signature_ok (struct TALER_EXCHANGE_RefreshMeltHandle *rmh,
|
||||
/* verify signature by exchange */
|
||||
confirm.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT);
|
||||
confirm.purpose.size = htonl (sizeof (struct TALER_RefreshMeltConfirmationPS));
|
||||
confirm.session_hash = rmh->md->melt_session_hash;
|
||||
confirm.noreveal_index = htons (*noreveal_index);
|
||||
confirm.reserved = htons (0);
|
||||
confirm.rc = rmh->md->rc;
|
||||
confirm.noreveal_index = htonl (*noreveal_index);
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT,
|
||||
&confirm.purpose,
|
||||
@ -1076,7 +1040,7 @@ handle_refresh_melt_finished (void *cls,
|
||||
const json_t *json)
|
||||
{
|
||||
struct TALER_EXCHANGE_RefreshMeltHandle *rmh = cls;
|
||||
uint16_t noreveal_index = TALER_CNC_KAPPA; /* invalid value */
|
||||
uint32_t noreveal_index = TALER_CNC_KAPPA; /* invalid value */
|
||||
struct TALER_ExchangePublicKeyP exchange_pub;
|
||||
|
||||
rmh->job = NULL;
|
||||
@ -1145,53 +1109,13 @@ handle_refresh_melt_finished (void *cls,
|
||||
rmh->melt_cb (rmh->melt_cb_cls,
|
||||
response_code,
|
||||
TALER_JSON_get_error_code (json),
|
||||
UINT16_MAX,
|
||||
UINT32_MAX,
|
||||
NULL,
|
||||
json);
|
||||
TALER_EXCHANGE_refresh_melt_cancel (rmh);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a coin to be melted to the respective JSON encoding.
|
||||
*
|
||||
* @param melt_session_hash session hash to use
|
||||
* @param mc coin to be melted
|
||||
* @return JSON encoding of the melting request
|
||||
*/
|
||||
static json_t *
|
||||
melted_coin_to_json (const struct GNUNET_HashCode *melt_session_hash,
|
||||
const struct MeltedCoin *mc)
|
||||
{
|
||||
struct TALER_CoinSpendSignatureP confirm_sig;
|
||||
struct TALER_RefreshMeltCoinAffirmationPS melt;
|
||||
|
||||
melt.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
|
||||
melt.purpose.size = htonl (sizeof (struct TALER_RefreshMeltCoinAffirmationPS));
|
||||
melt.session_hash = *melt_session_hash;
|
||||
TALER_amount_hton (&melt.amount_with_fee,
|
||||
&mc->melt_amount_with_fee);
|
||||
TALER_amount_hton (&melt.melt_fee,
|
||||
&mc->fee_melt);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&mc->coin_priv.eddsa_priv,
|
||||
&melt.coin_pub.eddsa_pub);
|
||||
GNUNET_CRYPTO_eddsa_sign (&mc->coin_priv.eddsa_priv,
|
||||
&melt.purpose,
|
||||
&confirm_sig.eddsa_signature);
|
||||
return json_pack ("{s:o, s:o, s:o, s:o, s:o}",
|
||||
"coin_pub",
|
||||
GNUNET_JSON_from_data_auto (&melt.coin_pub),
|
||||
"denom_pub",
|
||||
GNUNET_JSON_from_rsa_public_key (mc->pub_key.rsa_public_key),
|
||||
"denom_sig",
|
||||
GNUNET_JSON_from_rsa_signature (mc->sig.rsa_signature),
|
||||
"confirm_sig",
|
||||
GNUNET_JSON_from_data_auto (&confirm_sig),
|
||||
"value_with_fee",
|
||||
TALER_JSON_from_amount (&mc->melt_amount_with_fee));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Submit a melt request to the exchange and get the exchange's
|
||||
* response.
|
||||
@ -1220,17 +1144,12 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
void *melt_cb_cls)
|
||||
{
|
||||
json_t *melt_obj;
|
||||
json_t *new_denoms;
|
||||
json_t *melt_coin;
|
||||
json_t *coin_evs;
|
||||
json_t *transfer_pubs;
|
||||
json_t *tmp;
|
||||
struct TALER_EXCHANGE_RefreshMeltHandle *rmh;
|
||||
CURL *eh;
|
||||
struct GNUNET_CURL_Context *ctx;
|
||||
struct MeltData *md;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
struct TALER_CoinSpendSignatureP confirm_sig;
|
||||
struct TALER_RefreshMeltCoinAffirmationPS melt;
|
||||
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
MAH_handle_is_ready (exchange));
|
||||
@ -1242,78 +1161,35 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* build JSON request, each of the 4 arrays first */
|
||||
new_denoms = json_array ();
|
||||
melt_coin = melted_coin_to_json (&md->melt_session_hash,
|
||||
&md->melted_coin);
|
||||
coin_evs = json_array ();
|
||||
transfer_pubs = json_array ();
|
||||
|
||||
/* now transfer_pubs */
|
||||
for (j=0;j<TALER_CNC_KAPPA;j++)
|
||||
{
|
||||
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);
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (transfer_pubs,
|
||||
GNUNET_JSON_from_data_auto (&transfer_pub)));
|
||||
}
|
||||
|
||||
/* now new_denoms */
|
||||
for (i=0;i<md->num_fresh_coins;i++)
|
||||
{
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (new_denoms,
|
||||
GNUNET_JSON_from_rsa_public_key
|
||||
(md->fresh_pks[i].rsa_public_key)));
|
||||
}
|
||||
|
||||
/* now coin_evs */
|
||||
for (j=0;j<TALER_CNC_KAPPA;j++)
|
||||
{
|
||||
tmp = json_array ();
|
||||
for (i=0;i<md->num_fresh_coins;i++)
|
||||
{
|
||||
const struct TALER_PlanchetSecretsP *fc = &md->fresh_coins[j][i];
|
||||
struct TALER_PlanchetDetail pd;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&md->fresh_pks[i],
|
||||
fc,
|
||||
&pd))
|
||||
{
|
||||
/* This should have been noticed during the preparation stage. */
|
||||
GNUNET_break (0);
|
||||
json_decref (new_denoms);
|
||||
json_decref (tmp);
|
||||
json_decref (coin_evs);
|
||||
json_decref (melt_coin);
|
||||
json_decref (transfer_pubs);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (tmp,
|
||||
GNUNET_JSON_from_data (pd.coin_ev,
|
||||
pd.coin_ev_size)));
|
||||
GNUNET_free (pd.coin_ev);
|
||||
}
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (coin_evs,
|
||||
tmp));
|
||||
}
|
||||
|
||||
/* finally, assemble main JSON request from constitutent arrays */
|
||||
melt_obj = json_pack ("{s:o, s:o, s:o, s:o}",
|
||||
"new_denoms", new_denoms,
|
||||
"melt_coin", melt_coin,
|
||||
"coin_evs", coin_evs,
|
||||
"transfer_pubs", transfer_pubs);
|
||||
melt.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
|
||||
melt.purpose.size = htonl (sizeof (struct TALER_RefreshMeltCoinAffirmationPS));
|
||||
melt.rc = md->rc;
|
||||
TALER_amount_hton (&melt.amount_with_fee,
|
||||
&md->melted_coin.melt_amount_with_fee);
|
||||
TALER_amount_hton (&melt.melt_fee,
|
||||
&md->melted_coin.fee_melt);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&md->melted_coin.coin_priv.eddsa_priv,
|
||||
&melt.coin_pub.eddsa_pub);
|
||||
GNUNET_CRYPTO_eddsa_sign (&md->melted_coin.coin_priv.eddsa_priv,
|
||||
&melt.purpose,
|
||||
&confirm_sig.eddsa_signature);
|
||||
melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}",
|
||||
"coin_pub",
|
||||
GNUNET_JSON_from_data_auto (&melt.coin_pub),
|
||||
"denom_pub",
|
||||
GNUNET_JSON_from_rsa_public_key (md->melted_coin.pub_key.rsa_public_key),
|
||||
"denom_sig",
|
||||
GNUNET_JSON_from_rsa_signature (md->melted_coin.sig.rsa_signature),
|
||||
"confirm_sig",
|
||||
GNUNET_JSON_from_data_auto (&confirm_sig),
|
||||
"value_with_fee",
|
||||
TALER_JSON_from_amount (&md->melted_coin.melt_amount_with_fee),
|
||||
"rc",
|
||||
GNUNET_JSON_from_data_auto (&melt.rc));
|
||||
if (NULL == melt_obj)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
free_melt_data (md);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1325,7 +1201,6 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
rmh->md = md;
|
||||
rmh->url = MAH_path_to_url (exchange,
|
||||
"/refresh/melt");
|
||||
|
||||
eh = curl_easy_init ();
|
||||
GNUNET_assert (NULL != (rmh->json_enc =
|
||||
json_dumps (melt_obj,
|
||||
@ -1449,7 +1324,6 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshRevealHandle *rrh,
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
struct TALER_DenominationSignature *sigs)
|
||||
{
|
||||
unsigned int i;
|
||||
json_t *jsona;
|
||||
struct GNUNET_JSON_Specification outer_spec[] = {
|
||||
GNUNET_JSON_spec_json ("ev_sigs", &jsona),
|
||||
@ -1478,7 +1352,7 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshRevealHandle *rrh,
|
||||
GNUNET_JSON_parse_free (outer_spec);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
for (i=0;i<rrh->md->num_fresh_coins;i++)
|
||||
for (unsigned int i=0;i<rrh->md->num_fresh_coins;i++)
|
||||
{
|
||||
const struct TALER_PlanchetSecretsP *fc;
|
||||
struct TALER_DenominationPublicKey *pk;
|
||||
@ -1559,7 +1433,6 @@ handle_refresh_reveal_finished (void *cls,
|
||||
{
|
||||
struct TALER_CoinSpendPrivateKeyP coin_privs[rrh->md->num_fresh_coins];
|
||||
struct TALER_DenominationSignature sigs[rrh->md->num_fresh_coins];
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
memset (sigs, 0, sizeof (sigs));
|
||||
@ -1582,7 +1455,7 @@ handle_refresh_reveal_finished (void *cls,
|
||||
json);
|
||||
rrh->reveal_cb = NULL;
|
||||
}
|
||||
for (i=0;i<rrh->md->num_fresh_coins;i++)
|
||||
for (unsigned int i=0;i<rrh->md->num_fresh_coins;i++)
|
||||
if (NULL != sigs[i].rsa_signature)
|
||||
GNUNET_CRYPTO_rsa_signature_free (sigs[i].rsa_signature);
|
||||
}
|
||||
@ -1647,17 +1520,19 @@ struct TALER_EXCHANGE_RefreshRevealHandle *
|
||||
TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
|
||||
size_t refresh_data_length,
|
||||
const char *refresh_data,
|
||||
uint16_t noreveal_index,
|
||||
uint32_t noreveal_index,
|
||||
TALER_EXCHANGE_RefreshRevealCallback reveal_cb,
|
||||
void *reveal_cb_cls)
|
||||
{
|
||||
struct TALER_EXCHANGE_RefreshRevealHandle *rrh;
|
||||
json_t *transfer_privs;
|
||||
json_t *new_denoms_h;
|
||||
json_t *coin_evs;
|
||||
json_t *reveal_obj;
|
||||
CURL *eh;
|
||||
struct GNUNET_CURL_Context *ctx;
|
||||
struct MeltData *md;
|
||||
unsigned int j;
|
||||
struct TALER_TransferPublicKeyP transfer_pub;
|
||||
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
MAH_handle_is_ready (exchange));
|
||||
@ -1678,9 +1553,45 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* now transfer_pub */
|
||||
GNUNET_CRYPTO_ecdhe_key_get_public (&md->melted_coin.transfer_priv[noreveal_index].ecdhe_priv,
|
||||
&transfer_pub.ecdhe_pub);
|
||||
|
||||
/* now new_denoms */
|
||||
GNUNET_assert (NULL != (new_denoms_h = json_array ()));
|
||||
GNUNET_assert (NULL != (coin_evs = json_array ()));
|
||||
for (unsigned int i=0;i<md->num_fresh_coins;i++)
|
||||
{
|
||||
struct GNUNET_HashCode denom_hash;
|
||||
struct TALER_PlanchetDetail pd;
|
||||
|
||||
GNUNET_CRYPTO_rsa_public_key_hash (md->fresh_pks[i].rsa_public_key,
|
||||
&denom_hash);
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (new_denoms_h,
|
||||
GNUNET_JSON_from_data_auto (&denom_hash)));
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&md->fresh_pks[i],
|
||||
&md->fresh_coins[noreveal_index][i],
|
||||
&pd))
|
||||
{
|
||||
/* This should have been noticed during the preparation stage. */
|
||||
GNUNET_break (0);
|
||||
json_decref (new_denoms_h);
|
||||
json_decref (coin_evs);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (coin_evs,
|
||||
GNUNET_JSON_from_data (pd.coin_ev,
|
||||
pd.coin_ev_size)));
|
||||
GNUNET_free (pd.coin_ev);
|
||||
}
|
||||
|
||||
/* build array of transfer private keys */
|
||||
transfer_privs = json_array ();
|
||||
for (j=0;j<TALER_CNC_KAPPA;j++)
|
||||
GNUNET_assert (NULL != (transfer_privs = json_array ()));
|
||||
for (unsigned int j=0;j<TALER_CNC_KAPPA;j++)
|
||||
{
|
||||
if (j == noreveal_index)
|
||||
{
|
||||
@ -1694,11 +1605,17 @@ TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
|
||||
}
|
||||
|
||||
/* build main JSON request */
|
||||
reveal_obj = json_pack ("{s:o, s:o}",
|
||||
"session_hash",
|
||||
GNUNET_JSON_from_data_auto (&md->melt_session_hash),
|
||||
reveal_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o}",
|
||||
"rc",
|
||||
GNUNET_JSON_from_data_auto (&md->rc),
|
||||
"transfer_pub",
|
||||
GNUNET_JSON_from_data_auto (&transfer_pub),
|
||||
"transfer_privs",
|
||||
transfer_privs);
|
||||
transfer_privs,
|
||||
"new_denoms_h",
|
||||
new_denoms_h,
|
||||
"coin_evs",
|
||||
coin_evs);
|
||||
if (NULL == reveal_obj)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
|
@ -1199,7 +1199,7 @@ static void
|
||||
melt_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
uint16_t noreveal_index,
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *exchange_pub,
|
||||
const json_t *full_response)
|
||||
{
|
||||
@ -1312,8 +1312,6 @@ link_cb (void *cls,
|
||||
struct InterpreterState *is = cls;
|
||||
struct Command *cmd = &is->commands[is->ip];
|
||||
const struct Command *ref;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
unsigned int found;
|
||||
|
||||
cmd->details.refresh_link.rlh = NULL;
|
||||
@ -1341,16 +1339,16 @@ link_cb (void *cls,
|
||||
return;
|
||||
}
|
||||
/* check that the coins match */
|
||||
for (i=0;i<num_coins;i++)
|
||||
for (j=i+1;j<num_coins;j++)
|
||||
for (unsigned int i=0;i<num_coins;i++)
|
||||
for (unsigned int j=i+1;j<num_coins;j++)
|
||||
if (0 == memcmp (&coin_privs[i],
|
||||
&coin_privs[j],
|
||||
sizeof (struct TALER_CoinSpendPrivateKeyP)))
|
||||
GNUNET_break (0);
|
||||
/* Note: coins might be legitimately permutated in here... */
|
||||
found = 0;
|
||||
for (i=0;i<num_coins;i++)
|
||||
for (j=0;j<num_coins;j++)
|
||||
for (unsigned int i=0;i<num_coins;i++)
|
||||
for (unsigned int j=0;j<num_coins;j++)
|
||||
{
|
||||
const struct FreshCoin *fc;
|
||||
|
||||
|
@ -155,7 +155,7 @@ TEH_DB_calculate_transaction_list_totals (struct TALER_EXCHANGEDB_TransactionLis
|
||||
if (GNUNET_OK !=
|
||||
TALER_amount_add (&spent,
|
||||
&spent,
|
||||
&pos->details.melt->amount_with_fee))
|
||||
&pos->details.melt->session.amount_with_fee))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
|
@ -39,7 +39,7 @@
|
||||
* release version, and the format is NOT the same that semantic
|
||||
* versioning uses either.
|
||||
*/
|
||||
#define TALER_PROTOCOL_VERSION "1:0:1"
|
||||
#define TALER_PROTOCOL_VERSION "2:0:0"
|
||||
|
||||
|
||||
/**
|
||||
@ -1662,15 +1662,37 @@ TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
|
||||
enum TEH_KS_DenominationKeyUse use)
|
||||
{
|
||||
struct GNUNET_HashCode hc;
|
||||
|
||||
GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
|
||||
&hc);
|
||||
return TEH_KS_denomination_key_lookup_by_hash (key_state,
|
||||
&hc,
|
||||
use);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look up the issue for a denom public key. Note that the result
|
||||
* is only valid while the @a key_state is not released!
|
||||
*
|
||||
* @param key_state state to look in
|
||||
* @param denom_pub_hash hash of denomination public key
|
||||
* @param use purpose for which the key is being located
|
||||
* @return the denomination key issue,
|
||||
* or NULL if denom_pub could not be found (or is not valid at this time for the given @a use)
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *
|
||||
TEH_KS_denomination_key_lookup_by_hash (const struct TEH_KS_StateHandle *key_state,
|
||||
const struct GNUNET_HashCode *denom_pub_hash,
|
||||
enum TEH_KS_DenominationKeyUse use)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
||||
struct GNUNET_TIME_Absolute now;
|
||||
const struct GNUNET_CONTAINER_MultiHashMap *map;
|
||||
|
||||
GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
|
||||
&hc);
|
||||
map = (TEH_KS_DKU_PAYBACK == use) ? key_state->revoked_map : key_state->denomkey_map;
|
||||
dki = GNUNET_CONTAINER_multihashmap_get (map,
|
||||
&hc);
|
||||
denom_pub_hash);
|
||||
if (NULL == dki)
|
||||
return NULL;
|
||||
now = GNUNET_TIME_absolute_get ();
|
||||
@ -1679,7 +1701,7 @@ TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Not returning DKI for %s, as start time is in the future\n",
|
||||
GNUNET_h2s (&hc));
|
||||
GNUNET_h2s (denom_pub_hash));
|
||||
return NULL;
|
||||
}
|
||||
now = GNUNET_TIME_absolute_get ();
|
||||
@ -1691,7 +1713,7 @@ TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Not returning DKI for %s, as time to create coins has passed\n",
|
||||
GNUNET_h2s (&hc));
|
||||
GNUNET_h2s (denom_pub_hash));
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
@ -1701,7 +1723,7 @@ TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Not returning DKI for %s, as time to spend coin has passed\n",
|
||||
GNUNET_h2s (&hc));
|
||||
GNUNET_h2s (denom_pub_hash));
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
@ -1711,7 +1733,7 @@ TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Not returning DKI for %s, as time to payback coin has passed\n",
|
||||
GNUNET_h2s (&hc));
|
||||
GNUNET_h2s (denom_pub_hash));
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
@ -120,6 +120,22 @@ TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
|
||||
enum TEH_KS_DenominationKeyUse use);
|
||||
|
||||
|
||||
/**
|
||||
* Look up the issue for a denom public key. Note that the result
|
||||
* is only valid while the @a key_state is not released!
|
||||
*
|
||||
* @param key_state state to look in
|
||||
* @param denom_pub_hash hash of denomination public key
|
||||
* @param use purpose for which the key is being located
|
||||
* @return the denomination key issue,
|
||||
* or NULL if denom_pub could not be found (or is not valid at this time for the given @a use)
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *
|
||||
TEH_KS_denomination_key_lookup_by_hash (const struct TEH_KS_StateHandle *key_state,
|
||||
const struct GNUNET_HashCode *denom_pub_hash,
|
||||
enum TEH_KS_DenominationKeyUse use);
|
||||
|
||||
|
||||
/**
|
||||
* Read signals from a pipe in a loop, and reload keys from disk if
|
||||
* SIGUSR1 is received, terminate if SIGTERM/SIGINT is received, and
|
||||
|
@ -31,24 +31,6 @@
|
||||
#include "taler-exchange-httpd_keystate.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Information for each session a coin was melted into.
|
||||
*/
|
||||
struct TEH_RESPONSE_LinkSessionInfo
|
||||
{
|
||||
/**
|
||||
* Transfer public key of the coin.
|
||||
*/
|
||||
struct TALER_TransferPublicKeyP transfer_pub;
|
||||
|
||||
/**
|
||||
* Linked data of coins being created in the session.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_LinkDataList *ldl;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #handle_transfer_data().
|
||||
*/
|
||||
@ -56,98 +38,20 @@ struct HTD_Context
|
||||
{
|
||||
|
||||
/**
|
||||
* Public key of the coin that we are tracing.
|
||||
* Public key of the coin for which we are running /refresh/link.
|
||||
*/
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
|
||||
/**
|
||||
* Session link data we collect.
|
||||
* Json array with transfer data we collect.
|
||||
*/
|
||||
struct TEH_RESPONSE_LinkSessionInfo *sessions;
|
||||
|
||||
/**
|
||||
* Database session. Nothing to do with @a sessions.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_Session *session;
|
||||
|
||||
/**
|
||||
* MHD connection, for queueing replies.
|
||||
*/
|
||||
struct MHD_Connection *connection;
|
||||
|
||||
/**
|
||||
* Number of sessions the coin was melted into.
|
||||
*/
|
||||
unsigned int num_sessions;
|
||||
|
||||
/**
|
||||
* How are we expected to proceed. #GNUNET_SYSERR if we
|
||||
* failed to return an error (should return #MHD_NO).
|
||||
* #GNUNET_NO if we succeeded in queueing an MHD error
|
||||
* (should return #MHD_YES from #TEH_execute_refresh_link),
|
||||
* #GNUNET_OK if we should call #reply_refresh_link_success().
|
||||
*/
|
||||
int status;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send a response for "/refresh/link".
|
||||
*
|
||||
* @param connection the connection to send the response to
|
||||
* @param num_sessions number of sessions the coin was used in
|
||||
* @param sessions array of @a num_session entries with
|
||||
* information for each session
|
||||
* @return a MHD result code
|
||||
*/
|
||||
static int
|
||||
reply_refresh_link_success (struct MHD_Connection *connection,
|
||||
unsigned int num_sessions,
|
||||
const struct TEH_RESPONSE_LinkSessionInfo *sessions)
|
||||
{
|
||||
json_t *mlist;
|
||||
int res;
|
||||
|
||||
mlist = json_array ();
|
||||
for (unsigned int i=0;i<num_sessions;i++)
|
||||
{
|
||||
json_t *list = json_array ();
|
||||
json_t *root;
|
||||
|
||||
for (const struct TALER_EXCHANGEDB_LinkDataList *pos = sessions[i].ldl;
|
||||
NULL != pos;
|
||||
pos = pos->next)
|
||||
{
|
||||
json_t *obj;
|
||||
|
||||
obj = json_object ();
|
||||
json_object_set_new (obj,
|
||||
"denom_pub",
|
||||
GNUNET_JSON_from_rsa_public_key (pos->denom_pub.rsa_public_key));
|
||||
json_object_set_new (obj,
|
||||
"ev_sig",
|
||||
GNUNET_JSON_from_rsa_signature (pos->ev_sig.rsa_signature));
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (list,
|
||||
obj));
|
||||
}
|
||||
root = json_object ();
|
||||
json_object_set_new (root,
|
||||
"new_coins",
|
||||
list);
|
||||
json_object_set_new (root,
|
||||
"transfer_pub",
|
||||
GNUNET_JSON_from_data_auto (&sessions[i].transfer_pub));
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (mlist,
|
||||
root));
|
||||
}
|
||||
res = TEH_RESPONSE_reply_json (connection,
|
||||
mlist,
|
||||
MHD_HTTP_OK);
|
||||
json_decref (mlist);
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* Taler error code.
|
||||
*/
|
||||
enum TALER_ErrorCode ec;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -157,58 +61,59 @@ reply_refresh_link_success (struct MHD_Connection *connection,
|
||||
*
|
||||
*
|
||||
* @param cls closure, a `struct HTD_Context`
|
||||
* @param session_hash a session the coin was melted in
|
||||
* @param transfer_pub public transfer key for the session
|
||||
* @param ldl link data related to @a transfer_pub
|
||||
*/
|
||||
static void
|
||||
handle_transfer_data (void *cls,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
const struct TALER_TransferPublicKeyP *transfer_pub)
|
||||
handle_link_data (void *cls,
|
||||
const struct TALER_TransferPublicKeyP *transfer_pub,
|
||||
const struct TALER_EXCHANGEDB_LinkDataList *ldl)
|
||||
{
|
||||
struct HTD_Context *ctx = cls;
|
||||
struct TALER_EXCHANGEDB_LinkDataList *ldl;
|
||||
struct TEH_RESPONSE_LinkSessionInfo *lsi;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
json_t *list;
|
||||
json_t *root;
|
||||
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != ctx->status)
|
||||
if (NULL == ctx->mlist)
|
||||
return;
|
||||
ldl = NULL;
|
||||
qs = TEH_plugin->get_link_data_list (TEH_plugin->cls,
|
||||
ctx->session,
|
||||
session_hash,
|
||||
&ldl);
|
||||
if (qs <= 0)
|
||||
if (NULL == (list = json_array ()))
|
||||
goto fail;
|
||||
|
||||
for (const struct TALER_EXCHANGEDB_LinkDataList *pos = ldl;
|
||||
NULL != pos;
|
||||
pos = pos->next)
|
||||
{
|
||||
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||
ctx->status = GNUNET_DB_STATUS_HARD_ERROR;
|
||||
else
|
||||
ctx->status = qs;
|
||||
return;
|
||||
json_t *obj;
|
||||
|
||||
if (NULL == (obj = json_object ()))
|
||||
goto fail;
|
||||
json_object_set_new (obj,
|
||||
"denom_pub",
|
||||
GNUNET_JSON_from_rsa_public_key (pos->denom_pub.rsa_public_key));
|
||||
json_object_set_new (obj,
|
||||
"ev_sig",
|
||||
GNUNET_JSON_from_rsa_signature (pos->ev_sig.rsa_signature));
|
||||
if (0 !=
|
||||
json_array_append_new (list,
|
||||
obj))
|
||||
goto fail;
|
||||
}
|
||||
GNUNET_assert (NULL != ldl);
|
||||
GNUNET_array_grow (ctx->sessions,
|
||||
ctx->num_sessions,
|
||||
ctx->num_sessions + 1);
|
||||
lsi = &ctx->sessions[ctx->num_sessions - 1];
|
||||
lsi->transfer_pub = *transfer_pub;
|
||||
lsi->ldl = ldl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free session data kept in @a ctx
|
||||
*
|
||||
* @param ctx context to clean up
|
||||
*/
|
||||
static void
|
||||
purge_context (struct HTD_Context *ctx)
|
||||
{
|
||||
for (unsigned int i=0;i<ctx->num_sessions;i++)
|
||||
TEH_plugin->free_link_data_list (TEH_plugin->cls,
|
||||
ctx->sessions[i].ldl);
|
||||
GNUNET_free_non_null (ctx->sessions);
|
||||
ctx->sessions = NULL;
|
||||
ctx->num_sessions = 0;
|
||||
if (NULL == (root = json_object ()))
|
||||
goto fail;
|
||||
json_object_set_new (root,
|
||||
"new_coins",
|
||||
list);
|
||||
json_object_set_new (root,
|
||||
"transfer_pub",
|
||||
GNUNET_JSON_from_data_auto (transfer_pub));
|
||||
if (0 !=
|
||||
json_array_append_new (ctx->mlist,
|
||||
root))
|
||||
goto fail;
|
||||
return;
|
||||
fail:
|
||||
ctx->ec = TALER_EC_JSON_ALLOCATION_FAILURE;
|
||||
json_decref (ctx->mlist);
|
||||
ctx->mlist = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -239,14 +144,18 @@ refresh_link_transaction (void *cls,
|
||||
struct HTD_Context *ctx = cls;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
ctx->session = session;
|
||||
ctx->status = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
||||
qs = TEH_plugin->get_transfer (TEH_plugin->cls,
|
||||
qs = TEH_plugin->get_link_data (TEH_plugin->cls,
|
||||
session,
|
||||
&ctx->coin_pub,
|
||||
&handle_transfer_data,
|
||||
&handle_link_data,
|
||||
ctx);
|
||||
ctx->session = NULL;
|
||||
if (NULL == ctx->mlist)
|
||||
{
|
||||
*mhd_ret = TEH_RESPONSE_reply_internal_error (connection,
|
||||
ctx->ec,
|
||||
"coin_pub");
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||
{
|
||||
*mhd_ret = TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
@ -254,21 +163,6 @@ refresh_link_transaction (void *cls,
|
||||
"coin_pub");
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
if (0 < qs)
|
||||
{
|
||||
qs = ctx->status;
|
||||
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||
{
|
||||
*mhd_ret = TEH_RESPONSE_reply_json_pack (ctx->connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
"{s:s}",
|
||||
"error",
|
||||
"link data not found (link)");
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
return qs;
|
||||
}
|
||||
purge_context (ctx);
|
||||
return qs;
|
||||
}
|
||||
|
||||
@ -306,19 +200,21 @@ TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh,
|
||||
return MHD_NO;
|
||||
if (GNUNET_OK != res)
|
||||
return MHD_YES;
|
||||
ctx.mlist = json_array ();
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
&mhd_ret,
|
||||
&refresh_link_transaction,
|
||||
&ctx))
|
||||
{
|
||||
purge_context (&ctx);
|
||||
if (NULL != ctx.mlist)
|
||||
json_decref (ctx.mlist);
|
||||
return mhd_ret;
|
||||
}
|
||||
mhd_ret = reply_refresh_link_success (connection,
|
||||
ctx.num_sessions,
|
||||
ctx.sessions);
|
||||
purge_context (&ctx);
|
||||
mhd_ret = TEH_RESPONSE_reply_json (connection,
|
||||
ctx.mlist,
|
||||
MHD_HTTP_OK);
|
||||
json_decref (ctx.mlist);
|
||||
return mhd_ret;
|
||||
}
|
||||
|
||||
|
@ -31,38 +31,6 @@
|
||||
#include "taler-exchange-httpd_keystate.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Details about a melt operation of an individual coin.
|
||||
*/
|
||||
struct TEH_DB_MeltDetails
|
||||
{
|
||||
|
||||
/**
|
||||
* Information about the coin being melted.
|
||||
*/
|
||||
struct TALER_CoinPublicInfo coin_info;
|
||||
|
||||
/**
|
||||
* Signature allowing the melt (using
|
||||
* a `struct TALER_EXCHANGEDB_RefreshMeltConfirmSignRequestBody`) to sign over.
|
||||
*/
|
||||
struct TALER_CoinSpendSignatureP melt_sig;
|
||||
|
||||
/**
|
||||
* How much of the coin's value did the client allow to be melted?
|
||||
* This amount includes the fees, so the final amount contributed
|
||||
* to the melt is this value minus the fee for melting the coin.
|
||||
*/
|
||||
struct TALER_Amount melt_amount_with_fee;
|
||||
|
||||
/**
|
||||
* What fee is earned by the exchange? Set delayed during
|
||||
* #verify_coin_public_info().
|
||||
*/
|
||||
struct TALER_Amount melt_fee;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send a response for a failed "/refresh/melt" request. The
|
||||
* transaction history of the given coin demonstrates that the
|
||||
@ -116,14 +84,14 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection,
|
||||
* Send a response to a "/refresh/melt" request.
|
||||
*
|
||||
* @param connection the connection to send the response to
|
||||
* @param session_hash hash of the refresh session
|
||||
* @param rc value the client commited to
|
||||
* @param noreveal_index which index will the client not have to reveal
|
||||
* @return a MHD status code
|
||||
*/
|
||||
static int
|
||||
reply_refresh_melt_success (struct MHD_Connection *connection,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t noreveal_index)
|
||||
const struct TALER_RefreshCommitmentP *rc,
|
||||
uint32_t noreveal_index)
|
||||
{
|
||||
struct TALER_RefreshMeltConfirmationPS body;
|
||||
struct TALER_ExchangePublicKeyP pub;
|
||||
@ -132,9 +100,8 @@ reply_refresh_melt_success (struct MHD_Connection *connection,
|
||||
|
||||
body.purpose.size = htonl (sizeof (struct TALER_RefreshMeltConfirmationPS));
|
||||
body.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT);
|
||||
body.session_hash = *session_hash;
|
||||
body.noreveal_index = htons (noreveal_index);
|
||||
body.reserved = htons (0);
|
||||
body.rc = *rc;
|
||||
body.noreveal_index = htonl (noreveal_index);
|
||||
if (GNUNET_OK !=
|
||||
TEH_KS_sign (&body.purpose,
|
||||
&pub,
|
||||
@ -162,63 +129,22 @@ struct RefreshMeltContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Key state that can be used to lookup keys.
|
||||
*/
|
||||
struct TEH_KS_StateHandle *key_state;
|
||||
|
||||
/**
|
||||
* Information about the denomination key of the coin being
|
||||
* melted.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
||||
|
||||
/**
|
||||
* Array of denominations of the fresh coins.
|
||||
*/
|
||||
struct TALER_DenominationPublicKey *denom_pubs;
|
||||
|
||||
/**
|
||||
* Number of new coins to be generated in the melt.
|
||||
* Size of the @e denom_pubs array.
|
||||
*/
|
||||
unsigned int num_newcoins;
|
||||
|
||||
/**
|
||||
* Details about the coin to be melted.
|
||||
*/
|
||||
struct TEH_DB_MeltDetails coin_melt_details;
|
||||
|
||||
/**
|
||||
* Set to the session hash once the @e hash_context has finished.
|
||||
*/
|
||||
struct GNUNET_HashCode session_hash;
|
||||
|
||||
/**
|
||||
* Hash operation used to calculate the session hash.
|
||||
*/
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
|
||||
/**
|
||||
* Committments to the blinded envelopes for the fresh coins.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin[TALER_CNC_KAPPA];
|
||||
|
||||
/**
|
||||
* Commmittments to the transfer public keys.
|
||||
*/
|
||||
struct TALER_TransferPublicKeyP transfer_pub[TALER_CNC_KAPPA];
|
||||
|
||||
/**
|
||||
* Initialized during #refresh_melt_transaction().
|
||||
* noreveal_index is only initialized during
|
||||
* #refresh_melt_transaction().
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshSession refresh_session;
|
||||
|
||||
/**
|
||||
* Information about the @e coin's denomination.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse coin melt requests from a JSON object and write them to
|
||||
* the database.
|
||||
* Check that the coin has sufficient funds left for the selected
|
||||
* melt operation.
|
||||
*
|
||||
* @param connection the connection to send errors to
|
||||
* @param session the database connection
|
||||
@ -233,20 +159,19 @@ refresh_check_melt (struct MHD_Connection *connection,
|
||||
int *mhd_ret)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_TransactionList *tl;
|
||||
struct TALER_EXCHANGEDB_RefreshMelt *meltp = &rmc->refresh_session.melt;
|
||||
struct TALER_Amount coin_value;
|
||||
struct TALER_Amount coin_residual;
|
||||
struct TALER_Amount spent;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
TALER_amount_ntoh (&coin_value,
|
||||
&rmc->dki->issue.properties.value);
|
||||
/* fee for THIS transaction; the melt amount includes the fee! */
|
||||
spent = rmc->coin_melt_details.melt_amount_with_fee;
|
||||
/* Start with cost of this melt transaction */
|
||||
spent = rmc->refresh_session.amount_with_fee;
|
||||
|
||||
/* add historic transaction costs of this coin */
|
||||
qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
|
||||
session,
|
||||
&rmc->coin_melt_details.coin_info.coin_pub,
|
||||
&rmc->refresh_session.coin.coin_pub,
|
||||
&tl);
|
||||
if (0 > qs)
|
||||
{
|
||||
@ -267,33 +192,32 @@ refresh_check_melt (struct MHD_Connection *connection,
|
||||
TALER_EC_REFRESH_MELT_COIN_HISTORY_COMPUTATION_FAILED);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
|
||||
/* Refuse to refresh when the coin's value is insufficient
|
||||
for the cost of all transactions. */
|
||||
if (TALER_amount_cmp (&coin_value,
|
||||
&spent) < 0)
|
||||
{
|
||||
struct TALER_Amount coin_residual;
|
||||
|
||||
GNUNET_assert (GNUNET_SYSERR !=
|
||||
TALER_amount_subtract (&coin_residual,
|
||||
&spent,
|
||||
&rmc->coin_melt_details.melt_amount_with_fee));
|
||||
&rmc->refresh_session.amount_with_fee));
|
||||
*mhd_ret = reply_refresh_melt_insufficient_funds (connection,
|
||||
&rmc->coin_melt_details.coin_info.coin_pub,
|
||||
&rmc->refresh_session.coin.coin_pub,
|
||||
coin_value,
|
||||
tl,
|
||||
&rmc->coin_melt_details.melt_amount_with_fee,
|
||||
&rmc->refresh_session.amount_with_fee,
|
||||
&coin_residual);
|
||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||
tl);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
|
||||
/* we're good, coin has sufficient funds to be melted */
|
||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||
tl);
|
||||
|
||||
meltp->coin = rmc->coin_melt_details.coin_info;
|
||||
meltp->coin_sig = rmc->coin_melt_details.melt_sig;
|
||||
meltp->session_hash = rmc->session_hash;
|
||||
meltp->amount_with_fee = rmc->coin_melt_details.melt_amount_with_fee;
|
||||
meltp->melt_fee = rmc->coin_melt_details.melt_fee;
|
||||
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
||||
}
|
||||
|
||||
@ -325,17 +249,19 @@ refresh_melt_transaction (void *cls,
|
||||
int *mhd_ret)
|
||||
{
|
||||
struct RefreshMeltContext *rmc = cls;
|
||||
struct TALER_EXCHANGEDB_RefreshMelt rm;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = TEH_plugin->get_refresh_session (TEH_plugin->cls,
|
||||
/* Check if we already created such a session */
|
||||
qs = TEH_plugin->get_melt (TEH_plugin->cls,
|
||||
session,
|
||||
&rmc->session_hash,
|
||||
&rmc->refresh_session);
|
||||
&rmc->refresh_session.rc,
|
||||
&rm);
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
|
||||
{
|
||||
*mhd_ret = reply_refresh_melt_success (connection,
|
||||
&rmc->session_hash,
|
||||
rmc->refresh_session.noreveal_index);
|
||||
&rmc->refresh_session.rc,
|
||||
rm.session.noreveal_index);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
if (0 > qs)
|
||||
@ -346,12 +272,7 @@ refresh_melt_transaction (void *cls,
|
||||
return qs;
|
||||
}
|
||||
|
||||
/* store 'global' session data */
|
||||
rmc->refresh_session.num_newcoins = rmc->num_newcoins;
|
||||
rmc->refresh_session.noreveal_index
|
||||
= GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
|
||||
TALER_CNC_KAPPA);
|
||||
|
||||
/* check coin has enough funds remaining on it to cover melt cost */
|
||||
qs = refresh_check_melt (connection,
|
||||
session,
|
||||
rmc,
|
||||
@ -359,28 +280,15 @@ refresh_melt_transaction (void *cls,
|
||||
if (0 > qs)
|
||||
return qs;
|
||||
|
||||
if ( (0 >=
|
||||
(qs = TEH_plugin->create_refresh_session (TEH_plugin->cls,
|
||||
/* pick challenge and persist it */
|
||||
rmc->refresh_session.noreveal_index
|
||||
= GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG,
|
||||
TALER_CNC_KAPPA);
|
||||
|
||||
if (0 >=
|
||||
(qs = TEH_plugin->insert_melt (TEH_plugin->cls,
|
||||
session,
|
||||
&rmc->session_hash,
|
||||
&rmc->refresh_session))) ||
|
||||
(0 >=
|
||||
(qs = TEH_plugin->insert_refresh_order (TEH_plugin->cls,
|
||||
session,
|
||||
&rmc->session_hash,
|
||||
rmc->num_newcoins,
|
||||
rmc->denom_pubs))) ||
|
||||
(0 >=
|
||||
(qs = TEH_plugin->insert_refresh_commit_coins (TEH_plugin->cls,
|
||||
session,
|
||||
&rmc->session_hash,
|
||||
rmc->num_newcoins,
|
||||
rmc->commit_coin[rmc->refresh_session.noreveal_index]))) ||
|
||||
(0 >=
|
||||
(qs = TEH_plugin->insert_refresh_transfer_public_key (TEH_plugin->cls,
|
||||
session,
|
||||
&rmc->session_hash,
|
||||
&rmc->transfer_pub[rmc->refresh_session.noreveal_index]))) )
|
||||
&rmc->refresh_session)))
|
||||
{
|
||||
if (GNUNET_DB_STATUS_SOFT_ERROR != qs)
|
||||
{
|
||||
@ -394,233 +302,6 @@ refresh_melt_transaction (void *cls,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/refresh/melt" request after the main JSON parsing has
|
||||
* happened. We now need to validate the coins being melted and the
|
||||
* session signature and then hand things of to execute the melt
|
||||
* operation.
|
||||
*
|
||||
* @param connection the MHD connection to handle
|
||||
* @param[out] mhd_ret set on failure to return value for MHD
|
||||
* @param rmc information about the melt to process
|
||||
* @return MHD result code
|
||||
*/
|
||||
static int
|
||||
refresh_melt_prepare (struct MHD_Connection *connection,
|
||||
int *mhd_ret,
|
||||
struct RefreshMeltContext *rmc)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dk;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
|
||||
struct TALER_Amount cost;
|
||||
struct TALER_Amount total_cost;
|
||||
struct TALER_Amount value;
|
||||
struct TALER_Amount fee_withdraw;
|
||||
struct TALER_Amount fee_melt;
|
||||
struct TALER_Amount total_melt;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"/refresh/melt request for session %s\n",
|
||||
GNUNET_h2s (&rmc->session_hash));
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (TEH_exchange_currency_string,
|
||||
&total_cost));
|
||||
for (unsigned int i=0;i<rmc->num_newcoins;i++)
|
||||
{
|
||||
dk = TEH_KS_denomination_key_lookup (rmc->key_state,
|
||||
&rmc->denom_pubs[i],
|
||||
TEH_KS_DKU_WITHDRAW);
|
||||
if (NULL == dk)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
*mhd_ret = TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_FRESH_DENOMINATION_KEY_NOT_FOUND,
|
||||
"new_denoms");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
dki = &dk->issue;
|
||||
TALER_amount_ntoh (&value,
|
||||
&dki->properties.value);
|
||||
TALER_amount_ntoh (&fee_withdraw,
|
||||
&dki->properties.fee_withdraw);
|
||||
if ( (GNUNET_OK !=
|
||||
TALER_amount_add (&cost,
|
||||
&value,
|
||||
&fee_withdraw)) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_amount_add (&total_cost,
|
||||
&cost,
|
||||
&total_cost)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
*mhd_ret = TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_REFRESH_MELT_COST_CALCULATION_OVERFLOW,
|
||||
"cost calculation failure");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
|
||||
dki = &rmc->dki->issue;
|
||||
TALER_amount_ntoh (&fee_melt,
|
||||
&dki->properties.fee_refresh);
|
||||
if (GNUNET_OK !=
|
||||
TALER_amount_subtract (&total_melt,
|
||||
&rmc->coin_melt_details.melt_amount_with_fee,
|
||||
&fee_melt))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
*mhd_ret = TEH_RESPONSE_reply_external_error (connection,
|
||||
TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION,
|
||||
"Melt contribution below melting fee");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&total_cost,
|
||||
&total_melt))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
/* We require total value of coins being melted and
|
||||
total value of coins being generated to match! */
|
||||
*mhd_ret = TEH_RESPONSE_reply_json_pack (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
"{s:s, s:I}",
|
||||
"error", "value mismatch",
|
||||
"code", (json_int_t) TALER_EC_REFRESH_MELT_FEES_MISSMATCH);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return TEH_DB_run_transaction (connection,
|
||||
mhd_ret,
|
||||
&refresh_melt_transaction,
|
||||
rmc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract public coin information from a JSON object.
|
||||
*
|
||||
* @param connection the connection to send error responses to
|
||||
* @param coin_info the JSON object to extract the coin info from
|
||||
* @param[out] r_melt_detail set to details about the coin's melting permission (if valid)
|
||||
* @return #GNUNET_YES if coin public info in JSON was valid
|
||||
* #GNUNET_NO JSON was invalid, response was generated
|
||||
* #GNUNET_SYSERR on internal error
|
||||
*/
|
||||
static int
|
||||
get_coin_public_info (struct MHD_Connection *connection,
|
||||
const json_t *coin_info,
|
||||
struct TEH_DB_MeltDetails *r_melt_detail)
|
||||
{
|
||||
int ret;
|
||||
struct TALER_CoinSpendSignatureP melt_sig;
|
||||
struct TALER_DenominationSignature sig;
|
||||
struct TALER_DenominationPublicKey pk;
|
||||
struct TALER_Amount amount;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("coin_pub", &r_melt_detail->coin_info.coin_pub),
|
||||
TALER_JSON_spec_denomination_signature ("denom_sig", &sig),
|
||||
TALER_JSON_spec_denomination_public_key ("denom_pub", &pk),
|
||||
GNUNET_JSON_spec_fixed_auto ("confirm_sig", &melt_sig),
|
||||
TALER_JSON_spec_amount ("value_with_fee", &amount),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
ret = TEH_PARSE_json_data (connection,
|
||||
coin_info,
|
||||
spec);
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return ret;
|
||||
}
|
||||
/* check exchange signature on the coin */
|
||||
r_melt_detail->coin_info.denom_sig = sig;
|
||||
r_melt_detail->coin_info.denom_pub = pk;
|
||||
if (GNUNET_OK !=
|
||||
TALER_test_coin_valid (&r_melt_detail->coin_info))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
r_melt_detail->coin_info.denom_sig.rsa_signature = NULL;
|
||||
r_melt_detail->coin_info.denom_pub.rsa_public_key = NULL;
|
||||
return (MHD_YES ==
|
||||
TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID,
|
||||
"denom_sig"))
|
||||
? GNUNET_NO : GNUNET_SYSERR;
|
||||
}
|
||||
r_melt_detail->melt_sig = melt_sig;
|
||||
r_melt_detail->melt_amount_with_fee = amount;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release memory from the @a commit_coin array.
|
||||
*
|
||||
* @param commit_coin array to release
|
||||
* @param kappa size of 1st dimension
|
||||
* @param num_new_coins size of 2nd dimension
|
||||
*/
|
||||
static void
|
||||
free_commit_coins (struct TALER_EXCHANGEDB_RefreshCommitCoin **commit_coin,
|
||||
unsigned int kappa,
|
||||
unsigned int num_new_coins)
|
||||
{
|
||||
for (unsigned int i=0;i<kappa;i++)
|
||||
{
|
||||
if (NULL == commit_coin[i])
|
||||
break;
|
||||
for (unsigned int j=0;j<num_new_coins;j++)
|
||||
GNUNET_free_non_null (commit_coin[i][j].coin_ev);
|
||||
GNUNET_free (commit_coin[i]);
|
||||
commit_coin[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleanup state kept in the @a rmc.
|
||||
*
|
||||
* @param rmc state to clean up; does not free @a rmc itself
|
||||
*/
|
||||
static void
|
||||
cleanup_rmc (struct RefreshMeltContext *rmc)
|
||||
{
|
||||
free_commit_coins (rmc->commit_coin,
|
||||
TALER_CNC_KAPPA,
|
||||
rmc->num_newcoins);
|
||||
if (NULL != rmc->coin_melt_details.coin_info.denom_pub.rsa_public_key)
|
||||
{
|
||||
GNUNET_CRYPTO_rsa_public_key_free (rmc->coin_melt_details.coin_info.denom_pub.rsa_public_key);
|
||||
rmc->coin_melt_details.coin_info.denom_pub.rsa_public_key = NULL;
|
||||
}
|
||||
if (NULL != rmc->coin_melt_details.coin_info.denom_sig.rsa_signature)
|
||||
{
|
||||
GNUNET_CRYPTO_rsa_signature_free (rmc->coin_melt_details.coin_info.denom_sig.rsa_signature);
|
||||
rmc->coin_melt_details.coin_info.denom_sig.rsa_signature = NULL;
|
||||
}
|
||||
if (NULL != rmc->denom_pubs)
|
||||
{
|
||||
for (unsigned int j=0;j<rmc->num_newcoins;j++)
|
||||
if (NULL != rmc->denom_pubs[j].rsa_public_key)
|
||||
GNUNET_CRYPTO_rsa_public_key_free (rmc->denom_pubs[j].rsa_public_key);
|
||||
GNUNET_free (rmc->denom_pubs);
|
||||
rmc->denom_pubs = NULL;
|
||||
}
|
||||
if (NULL != rmc->hash_context)
|
||||
{
|
||||
GNUNET_CRYPTO_hash_context_abort (rmc->hash_context);
|
||||
rmc->hash_context = NULL;
|
||||
}
|
||||
if (NULL != rmc->key_state)
|
||||
{
|
||||
TEH_KS_release (rmc->key_state);
|
||||
rmc->key_state = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/refresh/melt" request after the first parsing has
|
||||
* happened. We now need to validate the coins being melted and the
|
||||
@ -629,223 +310,70 @@ cleanup_rmc (struct RefreshMeltContext *rmc)
|
||||
* processing on to #handle_refresh_melt_binary().
|
||||
*
|
||||
* @param connection the MHD connection to handle
|
||||
* @param new_denoms array of denomination keys
|
||||
* @param melt_coin coin to melt
|
||||
* @param transfer_pubs #TALER_CNC_KAPPA-dimensional array of transfer keys
|
||||
* @param coin_evs #TALER_CNC_KAPPA-dimensional array of envelopes to sign
|
||||
* @param[in,out] rmc details about the melt request
|
||||
* @return MHD result code
|
||||
*/
|
||||
static int
|
||||
handle_refresh_melt_json (struct MHD_Connection *connection,
|
||||
const json_t *new_denoms,
|
||||
const json_t *melt_coin,
|
||||
const json_t *transfer_pubs,
|
||||
const json_t *coin_evs)
|
||||
handle_refresh_melt (struct MHD_Connection *connection,
|
||||
struct RefreshMeltContext *rmc)
|
||||
{
|
||||
int res;
|
||||
int mhd_ret;
|
||||
struct RefreshMeltContext rmc;
|
||||
|
||||
memset (&rmc,
|
||||
0,
|
||||
sizeof (rmc));
|
||||
/* For the signature check, we hash most of the inputs together
|
||||
(except for the signatures on the coins). */
|
||||
rmc.hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
|
||||
/* sanity-check that "total melt amount > melt fee" */
|
||||
{
|
||||
struct GNUNET_JSON_Specification trans_spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto (NULL, &rmc.transfer_pub[i]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
struct TALER_Amount fee_refresh;
|
||||
|
||||
res = TEH_PARSE_json_array (connection,
|
||||
transfer_pubs,
|
||||
trans_spec,
|
||||
i, -1);
|
||||
if (GNUNET_OK != res)
|
||||
TALER_amount_ntoh (&fee_refresh,
|
||||
&rmc->dki->issue.properties.fee_refresh);
|
||||
if (TALER_amount_cmp (&fee_refresh,
|
||||
&rmc->refresh_session.amount_with_fee) > 0)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
mhd_ret = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
cleanup_rmc (&rmc);
|
||||
return mhd_ret;
|
||||
return TEH_RESPONSE_reply_external_error (connection,
|
||||
TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION,
|
||||
"melt amount smaller than melting fee");
|
||||
}
|
||||
GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
|
||||
&rmc.transfer_pub[i],
|
||||
sizeof (struct TALER_TransferPublicKeyP));
|
||||
}
|
||||
|
||||
rmc.num_newcoins = json_array_size (new_denoms);
|
||||
rmc.denom_pubs = GNUNET_new_array (rmc.num_newcoins,
|
||||
struct TALER_DenominationPublicKey);
|
||||
for (unsigned int i=0;i<rmc.num_newcoins;i++)
|
||||
{
|
||||
char *buf;
|
||||
size_t buf_size;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_denomination_public_key (NULL,
|
||||
&rmc.denom_pubs[i]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
res = TEH_PARSE_json_array (connection,
|
||||
new_denoms,
|
||||
spec,
|
||||
i,
|
||||
-1);
|
||||
if (GNUNET_OK != res)
|
||||
{
|
||||
mhd_ret = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||
cleanup_rmc (&rmc);
|
||||
return mhd_ret;
|
||||
}
|
||||
buf_size = GNUNET_CRYPTO_rsa_public_key_encode (rmc.denom_pubs[i].rsa_public_key,
|
||||
&buf);
|
||||
GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
|
||||
buf,
|
||||
buf_size);
|
||||
GNUNET_free (buf);
|
||||
}
|
||||
|
||||
/* decode JSON data on coin to melt and check that this is a
|
||||
valid coin */
|
||||
{
|
||||
struct TALER_AmountNBO melt_amount;
|
||||
|
||||
res = get_coin_public_info (connection,
|
||||
melt_coin,
|
||||
&rmc.coin_melt_details);
|
||||
if (GNUNET_OK != res)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
mhd_ret = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
|
||||
cleanup_rmc (&rmc);
|
||||
return mhd_ret;
|
||||
}
|
||||
TALER_amount_hton (&melt_amount,
|
||||
&rmc.coin_melt_details.melt_amount_with_fee);
|
||||
GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
|
||||
&rmc.coin_melt_details.coin_info.coin_pub,
|
||||
sizeof (struct TALER_CoinSpendPublicKeyP));
|
||||
GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
|
||||
&melt_amount,
|
||||
sizeof (struct TALER_AmountNBO));
|
||||
}
|
||||
|
||||
/* parse JSON arrays into binary arrays and hash everything
|
||||
together for the signature check */
|
||||
for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
|
||||
{
|
||||
rmc.commit_coin[i] = GNUNET_new_array (rmc.num_newcoins,
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin);
|
||||
for (unsigned int j = 0; j < rmc.num_newcoins; j++)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *rcc = &rmc.commit_coin[i][j];
|
||||
struct GNUNET_JSON_Specification coin_spec[] = {
|
||||
GNUNET_JSON_spec_varsize (NULL,
|
||||
(void **) &rcc->coin_ev,
|
||||
&rcc->coin_ev_size),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
res = TEH_PARSE_json_array (connection,
|
||||
coin_evs,
|
||||
coin_spec,
|
||||
i,
|
||||
j,
|
||||
-1);
|
||||
if (GNUNET_OK != res)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
mhd_ret = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
cleanup_rmc (&rmc);
|
||||
return mhd_ret;
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_hash_context_read (rmc.hash_context,
|
||||
rcc->coin_ev,
|
||||
rcc->coin_ev_size);
|
||||
}
|
||||
}
|
||||
|
||||
GNUNET_CRYPTO_hash_context_finish (rmc.hash_context,
|
||||
&rmc.session_hash);
|
||||
rmc.hash_context = NULL;
|
||||
|
||||
rmc.key_state = TEH_KS_acquire ();
|
||||
if (NULL == rmc.key_state)
|
||||
{
|
||||
TALER_LOG_ERROR ("Lacking keys to operate\n");
|
||||
return TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
|
||||
"no keys");
|
||||
}
|
||||
rmc.dki = TEH_KS_denomination_key_lookup (rmc.key_state,
|
||||
&rmc.coin_melt_details.coin_info.denom_pub,
|
||||
TEH_KS_DKU_DEPOSIT);
|
||||
if (NULL == rmc.dki)
|
||||
{
|
||||
TEH_KS_release (rmc.key_state);
|
||||
TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
|
||||
return TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
|
||||
"denom_pub");
|
||||
}
|
||||
|
||||
/* verify signature of coin for melt operation */
|
||||
{
|
||||
struct TALER_RefreshMeltCoinAffirmationPS body;
|
||||
struct TALER_Amount fee_refresh;
|
||||
|
||||
TALER_amount_ntoh (&fee_refresh,
|
||||
&rmc.dki->issue.properties.fee_refresh);
|
||||
rmc.coin_melt_details.melt_fee = fee_refresh;
|
||||
body.purpose.size = htonl (sizeof (struct TALER_RefreshMeltCoinAffirmationPS));
|
||||
body.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
|
||||
body.session_hash = rmc.session_hash;
|
||||
body.rc = rmc->refresh_session.rc;
|
||||
TALER_amount_hton (&body.amount_with_fee,
|
||||
&rmc.coin_melt_details.melt_amount_with_fee);
|
||||
TALER_amount_hton (&body.melt_fee,
|
||||
&fee_refresh);
|
||||
body.coin_pub = rmc.coin_melt_details.coin_info.coin_pub;
|
||||
if (TALER_amount_cmp (&fee_refresh,
|
||||
&rmc.coin_melt_details.melt_amount_with_fee) > 0)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
cleanup_rmc (&rmc);
|
||||
return TEH_RESPONSE_reply_external_error (connection,
|
||||
TALER_EC_REFRESH_MELT_AMOUNT_INSUFFICIENT,
|
||||
"melt amount smaller than melting fee");
|
||||
}
|
||||
&rmc->refresh_session.amount_with_fee);
|
||||
body.melt_fee = rmc->dki->issue.properties.fee_refresh;
|
||||
body.coin_pub = rmc->refresh_session.coin.coin_pub;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_MELT,
|
||||
&body.purpose,
|
||||
&rmc.coin_melt_details.melt_sig.eddsa_signature,
|
||||
&rmc.coin_melt_details.coin_info.coin_pub.eddsa_pub))
|
||||
&rmc->refresh_session.coin_sig.eddsa_signature,
|
||||
&rmc->refresh_session.coin.coin_pub.eddsa_pub))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
cleanup_rmc (&rmc);
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID,
|
||||
"confirm_sig");
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare commit */
|
||||
if (GNUNET_OK !=
|
||||
refresh_melt_prepare (connection,
|
||||
&mhd_ret,
|
||||
&rmc))
|
||||
/* run transaction */
|
||||
{
|
||||
cleanup_rmc (&rmc);
|
||||
int mhd_ret;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
&mhd_ret,
|
||||
&refresh_melt_transaction,
|
||||
rmc))
|
||||
return mhd_ret;
|
||||
}
|
||||
mhd_ret = reply_refresh_melt_success (connection,
|
||||
&rmc.session_hash,
|
||||
rmc.refresh_session.noreveal_index);
|
||||
cleanup_rmc (&rmc);
|
||||
return mhd_ret;
|
||||
|
||||
/* generate ordinary response */
|
||||
return reply_refresh_melt_success (connection,
|
||||
&rmc->refresh_session.rc,
|
||||
rmc->refresh_session.noreveal_index);
|
||||
}
|
||||
|
||||
|
||||
@ -870,16 +398,22 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
|
||||
size_t *upload_data_size)
|
||||
{
|
||||
json_t *root;
|
||||
json_t *new_denoms;
|
||||
json_t *melt_coin;
|
||||
json_t *coin_evs;
|
||||
json_t *transfer_pubs;
|
||||
struct RefreshMeltContext rmc;
|
||||
int res;
|
||||
struct TEH_KS_StateHandle *key_state;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_json ("new_denoms", &new_denoms),
|
||||
GNUNET_JSON_spec_json ("melt_coin", &melt_coin),
|
||||
GNUNET_JSON_spec_json ("coin_evs", &coin_evs),
|
||||
GNUNET_JSON_spec_json ("transfer_pubs", &transfer_pubs),
|
||||
GNUNET_JSON_spec_fixed_auto ("coin_pub",
|
||||
&rmc.refresh_session.coin.coin_pub),
|
||||
TALER_JSON_spec_denomination_signature ("denom_sig",
|
||||
&rmc.refresh_session.coin.denom_sig),
|
||||
TALER_JSON_spec_denomination_public_key ("denom_pub",
|
||||
&rmc.refresh_session.coin.denom_pub),
|
||||
GNUNET_JSON_spec_fixed_auto ("confirm_sig",
|
||||
&rmc.refresh_session.coin_sig),
|
||||
TALER_JSON_spec_amount ("value_with_fee",
|
||||
&rmc.refresh_session.amount_with_fee),
|
||||
GNUNET_JSON_spec_fixed_auto ("rc",
|
||||
&rmc.refresh_session.rc),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
@ -894,6 +428,9 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
|
||||
(NULL == root) )
|
||||
return MHD_YES;
|
||||
|
||||
memset (&rmc,
|
||||
0,
|
||||
sizeof (rmc));
|
||||
res = TEH_PARSE_json_data (connection,
|
||||
root,
|
||||
spec);
|
||||
@ -901,29 +438,60 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
|
||||
/* Determine dimensionality of the request (kappa, #old and #new coins) */
|
||||
if (TALER_CNC_KAPPA != json_array_size (coin_evs))
|
||||
if (GNUNET_OK !=
|
||||
TALER_test_coin_valid (&rmc.refresh_session.coin))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_CNC_COIN_ARRAY_SIZE_INVALID,
|
||||
"coin_evs");
|
||||
return TEH_RESPONSE_reply_signature_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID,
|
||||
"denom_sig");
|
||||
}
|
||||
if (TALER_CNC_KAPPA != json_array_size (transfer_pubs))
|
||||
|
||||
/* run actual logic, now that the request was parsed */
|
||||
key_state = TEH_KS_acquire ();
|
||||
if (NULL == key_state)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
||||
TALER_EC_REFRESH_MELT_CNC_TRANSFER_ARRAY_SIZE_INVALID,
|
||||
"transfer_pubs");
|
||||
TALER_LOG_ERROR ("Lacking keys to operate\n");
|
||||
res = TEH_RESPONSE_reply_internal_error (connection,
|
||||
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
|
||||
"no keys");
|
||||
goto cleanup;
|
||||
}
|
||||
rmc.dki = TEH_KS_denomination_key_lookup (key_state,
|
||||
&rmc.refresh_session.coin.denom_pub,
|
||||
TEH_KS_DKU_DEPOSIT);
|
||||
if (NULL == rmc.dki)
|
||||
{
|
||||
TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
|
||||
res = TEH_RESPONSE_reply_arg_unknown (connection,
|
||||
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
|
||||
"denom_pub");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
res = handle_refresh_melt (connection,
|
||||
&rmc);
|
||||
|
||||
|
||||
cleanup:
|
||||
if (NULL != key_state)
|
||||
{
|
||||
TEH_KS_release (key_state);
|
||||
key_state = NULL;
|
||||
}
|
||||
if (NULL != rmc.refresh_session.coin.denom_pub.rsa_public_key)
|
||||
{
|
||||
GNUNET_CRYPTO_rsa_public_key_free (rmc.refresh_session.coin.denom_pub.rsa_public_key);
|
||||
rmc.refresh_session.coin.denom_pub.rsa_public_key = NULL;
|
||||
}
|
||||
if (NULL != rmc.refresh_session.coin.denom_sig.rsa_signature)
|
||||
{
|
||||
GNUNET_CRYPTO_rsa_signature_free (rmc.refresh_session.coin.denom_sig.rsa_signature);
|
||||
rmc.refresh_session.coin.denom_sig.rsa_signature = NULL;
|
||||
}
|
||||
res = handle_refresh_melt_json (connection,
|
||||
new_denoms,
|
||||
melt_coin,
|
||||
transfer_pubs,
|
||||
coin_evs);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -541,18 +541,18 @@ TEH_RESPONSE_compile_transaction_history (const struct TALER_EXCHANGEDB_Transact
|
||||
|
||||
ms.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
|
||||
ms.purpose.size = htonl (sizeof (struct TALER_RefreshMeltCoinAffirmationPS));
|
||||
ms.session_hash = melt->session_hash;
|
||||
ms.rc = melt->session.rc;
|
||||
TALER_amount_hton (&ms.amount_with_fee,
|
||||
&melt->amount_with_fee);
|
||||
&melt->session.amount_with_fee);
|
||||
TALER_amount_hton (&ms.melt_fee,
|
||||
&melt->melt_fee);
|
||||
ms.coin_pub = melt->coin.coin_pub;
|
||||
ms.coin_pub = melt->session.coin.coin_pub;
|
||||
/* internal sanity check before we hand out a bogus sig... */
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_MELT,
|
||||
&ms.purpose,
|
||||
&melt->coin_sig.eddsa_signature,
|
||||
&melt->coin.coin_pub.eddsa_pub))
|
||||
&melt->session.coin_sig.eddsa_signature,
|
||||
&melt->session.coin.coin_pub.eddsa_pub))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
json_decref (history);
|
||||
@ -563,10 +563,10 @@ TEH_RESPONSE_compile_transaction_history (const struct TALER_EXCHANGEDB_Transact
|
||||
json_array_append_new (history,
|
||||
json_pack ("{s:s, s:o, s:o, s:o, s:o}",
|
||||
"type", "MELT",
|
||||
"amount", TALER_JSON_from_amount (&melt->amount_with_fee),
|
||||
"amount", TALER_JSON_from_amount (&melt->session.amount_with_fee),
|
||||
"melt_fee", TALER_JSON_from_amount (&melt->melt_fee),
|
||||
"session_hash", GNUNET_JSON_from_data_auto (&melt->session_hash),
|
||||
"coin_sig", GNUNET_JSON_from_data_auto (&melt->coin_sig))));
|
||||
"rc", GNUNET_JSON_from_data_auto (&melt->session.rc),
|
||||
"coin_sig", GNUNET_JSON_from_data_auto (&melt->session.coin_sig))));
|
||||
}
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_REFUND:
|
||||
|
@ -131,7 +131,17 @@ main (int argc, char ** argv)
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_LOOP ("05 - refresh session init loop",
|
||||
NB_REFRESH_INIT),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_START_TRANSACTION (""),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_CREATE_REFRESH_SESSION ("05 - refresh session"),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("05 - denomination load",
|
||||
"05 - refresh session init loop",
|
||||
"01 - save denomination"),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("05 - reserve load",
|
||||
"05 - refresh session init loop",
|
||||
"02 - save reserve"),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_CREATE_WITHDRAW ("05 - withdraw",
|
||||
"05 - denomination load",
|
||||
"05 - reserve load"),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_CREATE_REFRESH_SESSION ("05 - refresh session",
|
||||
"05 - withdraw"),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_SAVE_ARRAY ("05 - session array",
|
||||
"05 - refresh session init loop",
|
||||
"05 - refresh session",
|
||||
@ -330,7 +340,21 @@ main (int argc, char ** argv)
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_LOOP ("29 - insert refresh session",
|
||||
NB_REFRESH_SAVE),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_START_TRANSACTION (""),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_CREATE_REFRESH_SESSION (""),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("29 - denomination load",
|
||||
"29 - insert refresh session",
|
||||
"01 - save denomination"),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_LOAD_ARRAY ("29 - reserve load",
|
||||
"29 - insert refresh session",
|
||||
"02 - save reserve"),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_CREATE_WITHDRAW ("29 - withdraw",
|
||||
"29 - denomination load",
|
||||
"29 - reserve load"),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_CREATE_REFRESH_SESSION ("29 - refresh session",
|
||||
"29 - withdraw"),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_SAVE_ARRAY ("29 - session array",
|
||||
"29 - insert refresh session",
|
||||
"29 - refresh session",
|
||||
NB_RESERVE_SAVE),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_COMMIT_TRANSACTION (""),
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_END_LOOP ("",
|
||||
"29 - insert refresh session"),
|
||||
|
@ -434,57 +434,15 @@ PERF_TALER_EXCHANGEDB_coin_free (struct PERF_TALER_EXCHANGEDB_Coin *coin)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return a randomly generated refresh session
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshSession *
|
||||
PERF_TALER_EXCHANGEDB_refresh_session_init ()
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshSession *refresh_session;
|
||||
|
||||
GNUNET_assert (NULL !=
|
||||
(refresh_session = GNUNET_new (struct TALER_EXCHANGEDB_RefreshSession)));
|
||||
refresh_session->noreveal_index = 1;
|
||||
refresh_session->num_newcoins = 1;
|
||||
|
||||
return refresh_session;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return #GNUNET_OK if the copy was successful, #GNUNET_SYSERR if it wasn't
|
||||
*/
|
||||
int
|
||||
PERF_TALER_EXCHANGEDB_refresh_session_copy (struct TALER_EXCHANGEDB_RefreshSession *session,
|
||||
struct TALER_EXCHANGEDB_RefreshSession *copy)
|
||||
{
|
||||
*copy = *session;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free a refresh session
|
||||
*/
|
||||
int
|
||||
PERF_TALER_EXCHANGEDB_refresh_session_free (struct TALER_EXCHANGEDB_RefreshSession *refresh_session)
|
||||
{
|
||||
if (NULL == refresh_session)
|
||||
return GNUNET_OK;
|
||||
GNUNET_free (refresh_session);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a melt operation
|
||||
*
|
||||
* @param session the refresh session
|
||||
* @param rc the commitment of the refresh session
|
||||
* @param dki the denomination the melted coin uses
|
||||
* @return a pointer to a #TALER_EXCHANGEDB_RefreshMelt
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshMelt *
|
||||
PERF_TALER_EXCHANGEDB_refresh_melt_init (struct GNUNET_HashCode *session,
|
||||
PERF_TALER_EXCHANGEDB_refresh_melt_init (struct TALER_RefreshCommitmentP *rc,
|
||||
struct PERF_TALER_EXCHANGEDB_Coin *coin)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshMelt *melt;
|
||||
@ -496,12 +454,12 @@ PERF_TALER_EXCHANGEDB_refresh_melt_init (struct GNUNET_HashCode *session,
|
||||
struct
|
||||
{
|
||||
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||
struct GNUNET_HashCode session;
|
||||
struct TALER_RefreshCommitmentP rc;
|
||||
} to_sign;
|
||||
|
||||
to_sign.purpose.purpose = GNUNET_SIGNATURE_PURPOSE_TEST;
|
||||
to_sign.purpose.size = htonl (sizeof (to_sign));
|
||||
to_sign.session = *session;
|
||||
to_sign.rc = *rc;
|
||||
GNUNET_CRYPTO_eddsa_sign (&coin->priv,
|
||||
&to_sign.purpose,
|
||||
&coin_sig.eddsa_signature);
|
||||
@ -513,16 +471,16 @@ PERF_TALER_EXCHANGEDB_refresh_melt_init (struct GNUNET_HashCode *session,
|
||||
TALER_string_to_amount (CURRENCY ":0.1",
|
||||
&amount_with_fee));
|
||||
melt = GNUNET_new (struct TALER_EXCHANGEDB_RefreshMelt);
|
||||
melt->coin.coin_pub = coin->public_info.coin_pub;
|
||||
melt->coin.denom_sig.rsa_signature =
|
||||
melt->session.coin.coin_pub = coin->public_info.coin_pub;
|
||||
melt->session.coin.denom_sig.rsa_signature =
|
||||
GNUNET_CRYPTO_rsa_signature_dup (coin->public_info.denom_sig.rsa_signature);
|
||||
melt->coin.denom_pub.rsa_public_key =
|
||||
melt->session.coin.denom_pub.rsa_public_key =
|
||||
GNUNET_CRYPTO_rsa_public_key_dup (coin->public_info.denom_pub.rsa_public_key);
|
||||
GNUNET_assert (NULL != melt->coin.denom_pub.rsa_public_key);
|
||||
GNUNET_assert (NULL != melt->coin.denom_sig.rsa_signature);
|
||||
melt->coin_sig = coin_sig;
|
||||
melt->session_hash = *session;
|
||||
melt->amount_with_fee = amount;
|
||||
GNUNET_assert (NULL != melt->session.coin.denom_pub.rsa_public_key);
|
||||
GNUNET_assert (NULL != melt->session.coin.denom_sig.rsa_signature);
|
||||
melt->session.coin_sig = coin_sig;
|
||||
melt->session.rc = *rc;
|
||||
melt->session.amount_with_fee = amount;
|
||||
melt->melt_fee = amount_with_fee;
|
||||
return melt;
|
||||
}
|
||||
@ -541,9 +499,9 @@ PERF_TALER_EXCHANGEDB_refresh_melt_copy (const struct TALER_EXCHANGEDB_RefreshMe
|
||||
|
||||
copy = GNUNET_new (struct TALER_EXCHANGEDB_RefreshMelt);
|
||||
*copy = *melt;
|
||||
copy->coin.denom_sig.rsa_signature =
|
||||
GNUNET_CRYPTO_rsa_signature_dup (melt->coin.denom_sig.rsa_signature);
|
||||
GNUNET_assert (NULL != copy->coin.denom_sig.rsa_signature);
|
||||
copy->session.coin.denom_sig.rsa_signature =
|
||||
GNUNET_CRYPTO_rsa_signature_dup (melt->session.coin.denom_sig.rsa_signature);
|
||||
GNUNET_assert (NULL != copy->session.coin.denom_sig.rsa_signature);
|
||||
|
||||
return copy;
|
||||
}
|
||||
@ -558,51 +516,7 @@ PERF_TALER_EXCHANGEDB_refresh_melt_copy (const struct TALER_EXCHANGEDB_RefreshMe
|
||||
int
|
||||
PERF_TALER_EXCHANGEDB_refresh_melt_free (struct TALER_EXCHANGEDB_RefreshMelt *melt)
|
||||
{
|
||||
GNUNET_CRYPTO_rsa_signature_free (melt->coin.denom_sig.rsa_signature);
|
||||
GNUNET_CRYPTO_rsa_signature_free (melt->session.coin.denom_sig.rsa_signature);
|
||||
GNUNET_free (melt);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a #TALER_EXCHANGEDB_RefreshCommitCoin
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *
|
||||
PERF_TALER_EXCHANGEDB_refresh_commit_coin_init ()
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin;
|
||||
|
||||
commit_coin = GNUNET_new (struct TALER_EXCHANGEDB_RefreshCommitCoin);
|
||||
commit_coin->coin_ev = "coin_ev";
|
||||
commit_coin->coin_ev_size = 8;
|
||||
return commit_coin;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copies a #TALER_EXCHANGEDB_RefreshCommitCoin
|
||||
*
|
||||
* @param commit_coin the commit to copy
|
||||
* @return a copy of @a commit_coin
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *
|
||||
PERF_TALER_EXCHANGEDB_refresh_commit_coin_copy (struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *copy;
|
||||
|
||||
copy = GNUNET_new (struct TALER_EXCHANGEDB_RefreshCommitCoin);
|
||||
*copy = *commit_coin;
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free a #TALER_EXCHANGEDB_RefreshCommitCoin
|
||||
*
|
||||
* @param commit_coin the coin to free
|
||||
*/
|
||||
void
|
||||
PERF_TALER_EXCHANGEDB_refresh_commit_coin_free (struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin)
|
||||
{
|
||||
GNUNET_free (commit_coin);
|
||||
}
|
||||
|
@ -168,37 +168,15 @@ int
|
||||
PERF_TALER_EXCHANGEDB_coin_free (struct PERF_TALER_EXCHANGEDB_Coin *coin);
|
||||
|
||||
|
||||
/**
|
||||
* @return a randomly generated refresh session
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshSession *
|
||||
PERF_TALER_EXCHANGEDB_refresh_session_init (void);
|
||||
|
||||
|
||||
/**
|
||||
* @return #GNUNET_OK if the copy was successful, #GNUNET_SYSERR if it wasn't
|
||||
*/
|
||||
int
|
||||
PERF_TALER_EXCHANGEDB_refresh_session_copy (struct TALER_EXCHANGEDB_RefreshSession *session,
|
||||
struct TALER_EXCHANGEDB_RefreshSession *copy);
|
||||
|
||||
|
||||
/**
|
||||
* Frees memory of a refresh_session
|
||||
*/
|
||||
int
|
||||
PERF_TALER_EXCHANGEDB_refresh_session_free (struct TALER_EXCHANGEDB_RefreshSession *refresh_session);
|
||||
|
||||
|
||||
/**
|
||||
* Create a melt operation
|
||||
*
|
||||
* @param session the refresh session
|
||||
* @param rc the commitment of the refresh session
|
||||
* @param dki the denomination the melted coin uses
|
||||
* @return a pointer to a #TALER_EXCHANGEDB_RefreshMelt
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshMelt *
|
||||
PERF_TALER_EXCHANGEDB_refresh_melt_init (struct GNUNET_HashCode *session,
|
||||
PERF_TALER_EXCHANGEDB_refresh_melt_init (struct TALER_RefreshCommitmentP *rc,
|
||||
struct PERF_TALER_EXCHANGEDB_Coin *coin);
|
||||
|
||||
|
||||
@ -221,30 +199,4 @@ PERF_TALER_EXCHANGEDB_refresh_melt_copy (const struct TALER_EXCHANGEDB_RefreshMe
|
||||
int
|
||||
PERF_TALER_EXCHANGEDB_refresh_melt_free (struct TALER_EXCHANGEDB_RefreshMelt *melt);
|
||||
|
||||
|
||||
/**
|
||||
* Create a #TALER_EXCHANGEDB_RefreshCommitCoin
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *
|
||||
PERF_TALER_EXCHANGEDB_refresh_commit_coin_init (void);
|
||||
|
||||
|
||||
/**
|
||||
* Copies a #TALER_EXCHANGEDB_RefreshCommitCoin
|
||||
*
|
||||
* @param commit_coin the commit to copy
|
||||
* @return a copy of @a commit_coin
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *
|
||||
PERF_TALER_EXCHANGEDB_refresh_commit_coin_copy (struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin);
|
||||
|
||||
|
||||
/**
|
||||
* Free a #TALER_EXCHANGEDB_RefreshCommitCoin
|
||||
*
|
||||
* @param commit_coin the coin to free
|
||||
*/
|
||||
void
|
||||
PERF_TALER_EXCHANGEDB_refresh_commit_coin_free (struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin);
|
||||
|
||||
#endif
|
||||
|
@ -65,42 +65,32 @@ data_free (struct PERF_TALER_EXCHANGEDB_Data *data)
|
||||
GNUNET_free (data->data.time);
|
||||
data->data.time = NULL;
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_DEPOSIT:
|
||||
if (NULL == data->data.deposit)
|
||||
break;
|
||||
PERF_TALER_EXCHANGEDB_deposit_free (data->data.deposit);
|
||||
data->data.deposit = NULL;
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_COIN:
|
||||
if (NULL == data->data.coin)
|
||||
break;
|
||||
PERF_TALER_EXCHANGEDB_coin_free (data->data.coin);
|
||||
GNUNET_free (data->data.coin);
|
||||
data->data.coin = NULL;
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_RESERVE:
|
||||
if (NULL == data->data.reserve)
|
||||
break;
|
||||
PERF_TALER_EXCHANGEDB_reserve_free (data->data.reserve);
|
||||
data->data.reserve = NULL;
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_DENOMINATION_INFO:
|
||||
if (NULL == data->data.dki)
|
||||
break;
|
||||
PERF_TALER_EXCHANGEDB_denomination_free (data->data.dki);
|
||||
data->data.dki = NULL;
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_REFRESH_HASH:
|
||||
if (NULL == data->data.session_hash)
|
||||
break;
|
||||
GNUNET_free (data->data.session_hash);
|
||||
data->data.session_hash = NULL;
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_NONE:
|
||||
break;
|
||||
}
|
||||
@ -124,33 +114,25 @@ data_copy (const struct PERF_TALER_EXCHANGEDB_Data *data,
|
||||
copy->data.time = GNUNET_new (struct GNUNET_TIME_Absolute);
|
||||
*copy->data.time = *data->data.time;
|
||||
return;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_DEPOSIT:
|
||||
copy->data.deposit
|
||||
= PERF_TALER_EXCHANGEDB_deposit_copy (data->data.deposit);
|
||||
return;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_COIN:
|
||||
copy->data.coin
|
||||
= PERF_TALER_EXCHANGEDB_coin_copy (data->data.coin);
|
||||
return;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_RESERVE:
|
||||
copy->data.reserve
|
||||
= PERF_TALER_EXCHANGEDB_reserve_copy (data->data.reserve);
|
||||
return;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_DENOMINATION_INFO:
|
||||
copy->data.dki
|
||||
= PERF_TALER_EXCHANGEDB_denomination_copy (data->data.dki);
|
||||
return;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_REFRESH_HASH:
|
||||
copy-> data.session_hash = GNUNET_new (struct GNUNET_HashCode);
|
||||
*copy->data.session_hash
|
||||
= *data->data.session_hash;
|
||||
copy->data.rc = data->data.rc;
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_NONE:
|
||||
break;
|
||||
}
|
||||
@ -210,9 +192,10 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
if (PERF_TALER_EXCHANGEDB_CMD_LOOP != cmd[ret].command)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Wrong type reference to %s\n",
|
||||
"%d:Wrong type reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.end_loop.label_loop);
|
||||
cmd[i].details.end_loop.label_loop,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.end_loop.index_loop = ret;
|
||||
@ -228,17 +211,19 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
"%d:Undefined reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.save_array.label_save);
|
||||
cmd[i].details.save_array.label_save,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (PERF_TALER_EXCHANGEDB_NONE == cmd[ret].exposed.type)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Wrong type reference to %s\n",
|
||||
"%d:Wrong type reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.save_array.label_save);
|
||||
cmd[i].details.save_array.label_save,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.save_array.index_save = ret;
|
||||
@ -248,17 +233,19 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
"%d:Undefined reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.save_array.label_loop);
|
||||
cmd[i].details.save_array.label_loop,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (PERF_TALER_EXCHANGEDB_CMD_LOOP != cmd[ret].command)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Wrong type reference to %s\n",
|
||||
"%d:Wrong type reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.save_array.label_loop);
|
||||
cmd[i].details.save_array.label_loop,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.save_array.index_loop = ret;
|
||||
@ -281,17 +268,19 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
"%d:Undefined reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.load_array.label_save);
|
||||
cmd[i].details.load_array.label_save,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (PERF_TALER_EXCHANGEDB_CMD_SAVE_ARRAY != cmd[ret].command)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Wrong type reference to %s\n",
|
||||
"%d:Wrong type reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.load_array.label_save);
|
||||
cmd[i].details.load_array.label_save,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.load_array.index_save = ret;
|
||||
@ -732,6 +721,34 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_CREATE_REFRESH_SESSION:
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.create_refresh_session.label_coin);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.create_refresh_session.label_coin,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (PERF_TALER_EXCHANGEDB_COIN != cmd[ret].exposed.type)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Wrong type reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.create_refresh_session.label_coin,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.create_refresh_session.index_coin = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_SESSION:
|
||||
{
|
||||
int ret;
|
||||
@ -741,34 +758,36 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
"%d:Undefined reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.get_refresh_session.label_hash);
|
||||
cmd[i].details.get_refresh_session.label_hash,
|
||||
cmd[i].label);
|
||||
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",
|
||||
"%d:Wrong type reference to %s at %s\n",
|
||||
i,
|
||||
cmd[i].details.get_refresh_session.label_hash);
|
||||
cmd[i].details.get_refresh_session.label_hash,
|
||||
cmd[i].label);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.get_refresh_session.index_hash = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_REVEAL:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.insert_refresh_order.label_hash);
|
||||
cmd[i].details.insert_refresh_reveal.label_hash);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.insert_refresh_order.label_hash);
|
||||
cmd[i].details.insert_refresh_reveal.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (PERF_TALER_EXCHANGEDB_REFRESH_HASH != cmd[ret].exposed.type)
|
||||
@ -776,19 +795,19 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Wrong type reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.insert_refresh_order.label_hash);
|
||||
cmd[i].details.insert_refresh_reveal.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.insert_refresh_order.index_hash = ret;
|
||||
cmd[i].details.insert_refresh_reveal.index_hash = ret;
|
||||
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.insert_refresh_order.label_denom);
|
||||
cmd[i].details.insert_refresh_reveal.label_denom);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.insert_refresh_order.label_denom);
|
||||
cmd[i].details.insert_refresh_reveal.label_denom);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (PERF_TALER_EXCHANGEDB_DENOMINATION_INFO != cmd[ret].exposed.type)
|
||||
@ -796,24 +815,24 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Wrong type reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.insert_refresh_order.label_denom);
|
||||
cmd[i].details.insert_refresh_reveal.label_denom);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.insert_refresh_order.index_denom = ret;
|
||||
cmd[i].details.insert_refresh_reveal.index_denom = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_ORDER:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_REVEAL:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.get_refresh_order.label_hash);
|
||||
cmd[i].details.get_refresh_reveal.label_hash);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.get_refresh_order.label_hash);
|
||||
cmd[i].details.get_refresh_reveal.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (PERF_TALER_EXCHANGEDB_REFRESH_HASH != cmd[ret].exposed.type)
|
||||
@ -821,164 +840,14 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Wrong type reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.get_refresh_order.label_hash);
|
||||
cmd[i].details.get_refresh_reveal.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.get_refresh_order.index_hash = ret;
|
||||
cmd[i].details.get_refresh_reveal.index_hash = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_COMMIT_COIN:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.insert_refresh_commit_coin.label_hash);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.insert_refresh_commit_coin.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_commit_coin.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.insert_refresh_commit_coin.index_hash = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_COMMIT_COIN:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.get_refresh_commit_coin.label_hash);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.get_refresh_commit_coin.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_commit_coin.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.get_refresh_commit_coin.index_hash = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_COMMIT_LINK:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.insert_refresh_commit_link.label_hash);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.insert_refresh_commit_link.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_commit_link.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.insert_refresh_commit_link.index_hash = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_COMMIT_LINK:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.get_refresh_commit_link.label_hash);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.get_refresh_commit_link.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_commit_link.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.get_refresh_commit_link.index_hash = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_MELT_COMMITMENT:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.get_melt_commitment.label_hash);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.get_melt_commitment.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_melt_commitment.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.get_melt_commitment.index_hash = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_OUT:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.insert_refresh_out.label_hash);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.insert_refresh_out.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_out.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.insert_refresh_out.index_hash = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_LINK_DATA_LIST:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_LINK_DATA:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
@ -1003,31 +872,6 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_TRANSFER:
|
||||
{
|
||||
int ret;
|
||||
ret = cmd_find (cmd,
|
||||
cmd[i].details.get_transfer.label_hash);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"%d:Undefined reference to %s\n",
|
||||
i,
|
||||
cmd[i].details.get_transfer.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_transfer.label_hash);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cmd[i].details.get_transfer.index_hash = ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_END:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_DEBUG:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_LOOP:
|
||||
@ -1038,7 +882,6 @@ cmd_init (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_TIME:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_CREATE_DENOMINATION:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_CREATE_RESERVE:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_CREATE_REFRESH_SESSION:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1092,12 +935,11 @@ cmd_clean (struct PERF_TALER_EXCHANGEDB_Cmd cmd[])
|
||||
static void
|
||||
interpret_end_loop (struct PERF_TALER_EXCHANGEDB_interpreter_state *state)
|
||||
{
|
||||
unsigned int i;
|
||||
int jump;
|
||||
|
||||
jump = state->cmd[state->i].details.end_loop.index_loop;
|
||||
// Cleaning up the memory in the loop
|
||||
for (i = jump; i < state->i; i++)
|
||||
for (unsigned int i = jump; i < state->i; i++)
|
||||
data_free (&state->cmd[i].exposed);
|
||||
|
||||
state->cmd[jump].details.loop.curr_iteration++;
|
||||
@ -1229,6 +1071,29 @@ interprete_load_random (struct PERF_TALER_EXCHANGEDB_interpreter_state *state)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with information about a refresh order.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the row in our database
|
||||
* @param num_newcoins size of the @a rrcs array
|
||||
* @param rrcs array of @a num_newcoins information about coins to be created
|
||||
* @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1
|
||||
* @param tprivs array of @e num_tprivs transfer private keys
|
||||
* @param tp transfer public key information
|
||||
*/
|
||||
static void
|
||||
refresh_reveal_cb (void *cls,
|
||||
uint32_t num_newcoins,
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
|
||||
unsigned int num_tprivs,
|
||||
const struct TALER_TransferPrivateKeyP *tprivs,
|
||||
const struct TALER_TransferPublicKeyP *tp)
|
||||
{
|
||||
/* intentionally empty */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over the commands, acting accordingly at each step
|
||||
*
|
||||
@ -1343,7 +1208,8 @@ interpret (struct PERF_TALER_EXCHANGEDB_interpreter_state *state)
|
||||
state->session,
|
||||
deposit);
|
||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
|
||||
state->cmd[state->i].exposed.data.deposit = deposit;
|
||||
state->cmd[state->i].exposed.data.deposit
|
||||
= PERF_TALER_EXCHANGEDB_deposit_copy (deposit);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1546,143 +1412,100 @@ interpret (struct PERF_TALER_EXCHANGEDB_interpreter_state *state)
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_CREATE_REFRESH_SESSION:
|
||||
{
|
||||
struct GNUNET_HashCode *hash;
|
||||
struct TALER_EXCHANGEDB_RefreshSession *refresh_session;
|
||||
struct TALER_EXCHANGEDB_RefreshSession refresh_session;
|
||||
unsigned int coin_index;
|
||||
struct PERF_TALER_EXCHANGEDB_Coin *coin;
|
||||
|
||||
hash = GNUNET_new (struct GNUNET_HashCode);
|
||||
refresh_session = PERF_TALER_EXCHANGEDB_refresh_session_init ();
|
||||
coin_index = state->cmd[state->i].details.create_refresh_session.index_coin;
|
||||
coin = state->cmd[coin_index].exposed.data.coin;
|
||||
|
||||
refresh_session.coin = coin->public_info;
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&refresh_session.coin_sig,
|
||||
sizeof (refresh_session.coin_sig));
|
||||
GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
hash);
|
||||
&refresh_session.rc.session_hash);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":1.1",
|
||||
&refresh_session.amount_with_fee));
|
||||
refresh_session.noreveal_index = 1;
|
||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
|
||||
state->plugin->create_refresh_session (state->session,
|
||||
state->plugin->insert_melt (state->session,
|
||||
state->session,
|
||||
hash,
|
||||
refresh_session));
|
||||
state->cmd[state->i].exposed.data.session_hash = hash;
|
||||
PERF_TALER_EXCHANGEDB_refresh_session_free (refresh_session);
|
||||
GNUNET_free (refresh_session);
|
||||
&refresh_session));
|
||||
state->cmd[state->i].exposed.data.rc = refresh_session.rc;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_SESSION:
|
||||
{
|
||||
unsigned int hash_index;
|
||||
struct GNUNET_HashCode *hash;
|
||||
struct TALER_EXCHANGEDB_RefreshSession refresh;
|
||||
const struct TALER_RefreshCommitmentP *rc;
|
||||
struct TALER_EXCHANGEDB_RefreshMelt refresh;
|
||||
|
||||
hash_index = state->cmd[state->i].details.get_refresh_session.index_hash;
|
||||
hash = state->cmd[hash_index].exposed.data.session_hash;
|
||||
state->plugin->get_refresh_session (state->session,
|
||||
rc = &state->cmd[hash_index].exposed.data.rc;
|
||||
state->plugin->get_melt (state->session,
|
||||
state->session,
|
||||
hash,
|
||||
rc,
|
||||
&refresh);
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_REVEAL:
|
||||
{
|
||||
unsigned int hash_index;
|
||||
unsigned int denom_index;
|
||||
struct GNUNET_HashCode *session_hash;
|
||||
const struct TALER_RefreshCommitmentP *rc;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *denom;
|
||||
struct TALER_TransferPublicKeyP tpub;
|
||||
struct TALER_TransferPrivateKeyP tprivs[2];
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin rrc;
|
||||
|
||||
hash_index = state->cmd[state->i].details.insert_refresh_order.index_hash;
|
||||
denom_index = state->cmd[state->i].details.insert_refresh_order.index_denom;
|
||||
session_hash = state->cmd[hash_index].exposed.data.session_hash;
|
||||
hash_index = state->cmd[state->i].details.insert_refresh_reveal.index_hash;
|
||||
denom_index = state->cmd[state->i].details.insert_refresh_reveal.index_denom;
|
||||
rc = &state->cmd[hash_index].exposed.data.rc;
|
||||
denom = state->cmd[denom_index].exposed.data.dki;
|
||||
rrc.denom_pub = denom->denom_pub;
|
||||
rrc.coin_ev = "coin_ev";
|
||||
rrc.coin_ev_size = strlen (rrc.coin_ev) + 1;
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&rrc.coin_sig,
|
||||
sizeof (struct TALER_CoinSpendSignatureP));
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
tprivs,
|
||||
sizeof (struct TALER_TransferPrivateKeyP) * 2);
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&tpub,
|
||||
sizeof (struct TALER_TransferPublicKeyP));
|
||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
|
||||
state->plugin->insert_refresh_order (state->plugin->cls,
|
||||
state->plugin->insert_refresh_reveal (state->plugin->cls,
|
||||
state->session,
|
||||
session_hash,
|
||||
rc,
|
||||
1,
|
||||
&denom->denom_pub));
|
||||
|
||||
&rrc,
|
||||
2,
|
||||
tprivs,
|
||||
&tpub));
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_ORDER:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_REVEAL:
|
||||
{
|
||||
int hash_index;
|
||||
struct GNUNET_HashCode *hash;
|
||||
struct TALER_DenominationPublicKey denom_pub;
|
||||
const struct TALER_RefreshCommitmentP *rc;
|
||||
|
||||
hash_index = state->cmd[state->i].details.get_refresh_order.index_hash;
|
||||
hash = state->cmd[hash_index].exposed.data.session_hash;
|
||||
state->plugin->get_refresh_order (state->plugin->cls,
|
||||
hash_index = state->cmd[state->i].details.get_refresh_reveal.index_hash;
|
||||
rc = &state->cmd[hash_index].exposed.data.rc;
|
||||
state->plugin->get_refresh_reveal (state->plugin->cls,
|
||||
state->session,
|
||||
hash,
|
||||
1,
|
||||
&denom_pub);
|
||||
rc,
|
||||
&refresh_reveal_cb,
|
||||
state);
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_COMMIT_COIN:
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
unsigned int hash_index;
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *refresh_commit;
|
||||
|
||||
hash_index = state->cmd[state->i].details.insert_refresh_commit_coin.index_hash;
|
||||
refresh_commit = PERF_TALER_EXCHANGEDB_refresh_commit_coin_init ();
|
||||
qs = state->plugin->insert_refresh_commit_coins (state->plugin->cls,
|
||||
state->session,
|
||||
state->cmd[hash_index].exposed.data.session_hash,
|
||||
1,
|
||||
refresh_commit);
|
||||
GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_COMMIT_COIN:
|
||||
{
|
||||
unsigned int hash_index;
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin refresh_commit;
|
||||
|
||||
hash_index = state->cmd[state->i].details.insert_refresh_commit_coin.index_hash;
|
||||
state->plugin->get_refresh_commit_coins (state->plugin->cls,
|
||||
state->session,
|
||||
state->cmd[hash_index].exposed.data.session_hash,
|
||||
1,
|
||||
&refresh_commit);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_COMMIT_LINK:
|
||||
{
|
||||
// unsigned int hash_index;
|
||||
//
|
||||
// hash_index = state->cmd[state->i].details.insert_refresh_commit_link.index_hash;
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_COMMIT_LINK:
|
||||
{
|
||||
int ret;
|
||||
unsigned int hash_index;
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin commit_coin;
|
||||
|
||||
// FIXME: this should go after the public key!
|
||||
hash_index = state->cmd[state->i].details.get_refresh_commit_link.index_hash;
|
||||
ret = state->plugin->get_refresh_commit_coins(state->plugin->cls,
|
||||
state->session,
|
||||
state->cmd[hash_index].exposed.data.session_hash,
|
||||
1,
|
||||
&commit_coin);
|
||||
GNUNET_assert (GNUNET_SYSERR != ret);
|
||||
}
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_MELT_COMMITMENT:
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_OUT:
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_LINK_DATA_LIST:
|
||||
break;
|
||||
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_TRANSFER:
|
||||
case PERF_TALER_EXCHANGEDB_CMD_GET_LINK_DATA:
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -331,7 +331,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts informations about a withdrawal in the database
|
||||
* Inserts information about a withdrawal into the database
|
||||
*
|
||||
* @exposes #PERF_TALER_EXCHANGEDB_COIN
|
||||
*
|
||||
@ -452,16 +452,18 @@
|
||||
_label_coin), \
|
||||
PERF_TALER_EXCHANGEDB_INIT_CMD_INSERT_DEPOSIT (_label "insert", \
|
||||
_label "deposit")
|
||||
|
||||
/**
|
||||
* Insert informations about a refresh session
|
||||
* melts one coin into another
|
||||
*
|
||||
* @param _label the label of the command
|
||||
*/
|
||||
#define PERF_TALER_EXCHANGEDB_INIT_CMD_CREATE_REFRESH_SESSION(_label) \
|
||||
#define PERF_TALER_EXCHANGEDB_INIT_CMD_CREATE_REFRESH_SESSION(_label, _label_coin) \
|
||||
{ \
|
||||
.command = PERF_TALER_EXCHANGEDB_CMD_CREATE_REFRESH_SESSION, \
|
||||
.label = _label, \
|
||||
.details.create_refresh_session.label_coin = _label_coin, \
|
||||
.exposed.type = PERF_TALER_EXCHANGEDB_REFRESH_HASH \
|
||||
}
|
||||
|
||||
@ -519,7 +521,7 @@ struct PERF_TALER_EXCHANGEDB_Data
|
||||
/** #PERF_TALER_EXCHANGEDB_DENOMINATION_INFO */
|
||||
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
|
||||
/** #PERF_TALER_EXCHANGEDB_REFRESH_HASH */
|
||||
struct GNUNET_HashCode *session_hash;
|
||||
struct TALER_RefreshCommitmentP rc;
|
||||
} data;
|
||||
};
|
||||
|
||||
@ -679,54 +681,19 @@ enum PERF_TALER_EXCHANGEDB_CMD_Name
|
||||
PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_SESSION,
|
||||
|
||||
/**
|
||||
* Insert a melt refresh order
|
||||
* Insert a melt refresh reveal data
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER,
|
||||
PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_REVEAL,
|
||||
|
||||
/**
|
||||
* Get informations about a refresh order
|
||||
* Get informations about a refresh reveal data
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_ORDER,
|
||||
|
||||
/**
|
||||
* Insert refresh commit coin
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_COMMIT_COIN,
|
||||
|
||||
/**
|
||||
* Get refresh commit coin
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_COMMIT_COIN,
|
||||
|
||||
/**
|
||||
* Insert refresh commit link
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_COMMIT_LINK,
|
||||
|
||||
/**
|
||||
* Get refresh commit link
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_COMMIT_LINK,
|
||||
|
||||
/**
|
||||
* Get information avout the melt commit
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_GET_MELT_COMMITMENT,
|
||||
|
||||
/**
|
||||
* Insert a new coin into the database after a melt operation
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_OUT,
|
||||
PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_REVEAL,
|
||||
|
||||
/**
|
||||
* Get the link data list of a coin
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_GET_LINK_DATA_LIST,
|
||||
|
||||
/**
|
||||
* Get the shared secret and the transfere public key
|
||||
*/
|
||||
PERF_TALER_EXCHANGEDB_CMD_GET_TRANSFER
|
||||
PERF_TALER_EXCHANGEDB_CMD_GET_LINK_DATA
|
||||
|
||||
};
|
||||
|
||||
@ -1028,6 +995,18 @@ union PERF_TALER_EXCHANGEDB_CMD_Details
|
||||
unsigned int index_deposit;
|
||||
} get_deposit;
|
||||
|
||||
/**
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_CREATE_REFRESH_SESSION command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_createRefreshSessionDetails
|
||||
{
|
||||
/**
|
||||
* label of the source of the hash of the session
|
||||
*/
|
||||
const char *label_coin;
|
||||
unsigned int index_coin;
|
||||
} create_refresh_session;
|
||||
|
||||
/**
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_SESSION command
|
||||
*/
|
||||
@ -1041,9 +1020,9 @@ union PERF_TALER_EXCHANGEDB_CMD_Details
|
||||
} get_refresh_session;
|
||||
|
||||
/**
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_ORDER command
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_REVEAL command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_insertRefreshOrderDetails
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_insertRefreshRevealDetails
|
||||
{
|
||||
/**
|
||||
* The refresh session hash
|
||||
@ -1056,12 +1035,12 @@ union PERF_TALER_EXCHANGEDB_CMD_Details
|
||||
*/
|
||||
const char *label_denom;
|
||||
unsigned int index_denom;
|
||||
} insert_refresh_order;
|
||||
} insert_refresh_reveal;
|
||||
|
||||
/**
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_ORDER command
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_REVEAL command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_getRefreshOrderDetails
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_getRefreshRevealDetails
|
||||
{
|
||||
/**
|
||||
* The session hash
|
||||
@ -1069,82 +1048,7 @@ union PERF_TALER_EXCHANGEDB_CMD_Details
|
||||
const char *label_hash;
|
||||
unsigned int index_hash;
|
||||
|
||||
} get_refresh_order;
|
||||
|
||||
/**
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_COMMIT_COIN command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_insertRefreshCommitCoinDetails
|
||||
{
|
||||
/**
|
||||
* The refresh session hash
|
||||
*/
|
||||
const char *label_hash;
|
||||
unsigned int index_hash;
|
||||
|
||||
} insert_refresh_commit_coin;
|
||||
|
||||
/**
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_COMMIT_COIN command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_getRefreshCommitCoinDetails
|
||||
{
|
||||
/**
|
||||
* The refresh session hash
|
||||
*/
|
||||
const char *label_hash;
|
||||
unsigned int index_hash;
|
||||
|
||||
} get_refresh_commit_coin;
|
||||
|
||||
/**
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_COMMIT_LINK command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_insertRefreshCommitLinkDetails
|
||||
{
|
||||
/**
|
||||
* The refresh session hash
|
||||
*/
|
||||
const char *label_hash;
|
||||
unsigned int index_hash;
|
||||
|
||||
} insert_refresh_commit_link;
|
||||
|
||||
/**
|
||||
* Data requiered by the #PERF_TALER_EXCHANGEDB_CMD_GET_REFRESH_COMMIT_LINK command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_getRefreshCommitLinkDetails
|
||||
{
|
||||
/**
|
||||
* The refresh session hash
|
||||
*/
|
||||
const char *label_hash;
|
||||
unsigned int index_hash;
|
||||
} get_refresh_commit_link;
|
||||
|
||||
/**
|
||||
* Data requiered for the #PERF_TALER_EXCHANGEDB_CMD_GET_MELT_COMMITMENT command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_getMeltCommitmentDaetails
|
||||
{
|
||||
/**
|
||||
* The refresh session hash
|
||||
*/
|
||||
const char *label_hash;
|
||||
unsigned int index_hash;
|
||||
} get_melt_commitment;
|
||||
|
||||
/**
|
||||
* Data requiered by the #PERF_TALER_EXCHANGEDB_CMD_INSERT_REFRESH_OUT command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_insertRefreshOutDetails
|
||||
{
|
||||
/**
|
||||
* The refresh session hash
|
||||
*/
|
||||
const char *label_hash;
|
||||
unsigned int index_hash;
|
||||
} insert_refresh_out;
|
||||
} get_refresh_reveal;
|
||||
|
||||
/**
|
||||
* Data requiered by the #PERF_TALER_EXCHANGEDB_CMD_GET_LINK_DATA_LIST command
|
||||
@ -1158,17 +1062,6 @@ union PERF_TALER_EXCHANGEDB_CMD_Details
|
||||
unsigned int index_hash;
|
||||
} get_link_data_list;
|
||||
|
||||
/**
|
||||
* Data requiered by the #PERF_TALER_EXCHANGEDB_CMD_GET_TRANSFER command
|
||||
*/
|
||||
struct PERF_TALER_EXCHANGEDB_CMD_getTransferDetails
|
||||
{
|
||||
/**
|
||||
* The refresh session hash
|
||||
*/
|
||||
const char *label_hash;
|
||||
unsigned int index_hash;
|
||||
} get_transfer;
|
||||
|
||||
};
|
||||
|
||||
|
@ -73,31 +73,6 @@ common_free_reserve_history (void *cls,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free memory of the link data list.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state (unused)
|
||||
* @param ldl link data list to release
|
||||
*/
|
||||
static void
|
||||
common_free_link_data_list (void *cls,
|
||||
struct TALER_EXCHANGEDB_LinkDataList *ldl)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_LinkDataList *next;
|
||||
|
||||
while (NULL != ldl)
|
||||
{
|
||||
next = ldl->next;
|
||||
if (NULL != ldl->denom_pub.rsa_public_key)
|
||||
GNUNET_CRYPTO_rsa_public_key_free (ldl->denom_pub.rsa_public_key);
|
||||
if (NULL != ldl->ev_sig.rsa_signature)
|
||||
GNUNET_CRYPTO_rsa_signature_free (ldl->ev_sig.rsa_signature);
|
||||
GNUNET_free (ldl);
|
||||
ldl = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free linked list of transactions.
|
||||
*
|
||||
@ -125,10 +100,10 @@ common_free_coin_transaction_list (void *cls,
|
||||
GNUNET_free (list->details.deposit);
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_REFRESH_MELT:
|
||||
if (NULL != list->details.melt->coin.denom_pub.rsa_public_key)
|
||||
GNUNET_CRYPTO_rsa_public_key_free (list->details.melt->coin.denom_pub.rsa_public_key);
|
||||
if (NULL != list->details.melt->coin.denom_sig.rsa_signature)
|
||||
GNUNET_CRYPTO_rsa_signature_free (list->details.melt->coin.denom_sig.rsa_signature);
|
||||
if (NULL != list->details.melt->session.coin.denom_pub.rsa_public_key)
|
||||
GNUNET_CRYPTO_rsa_public_key_free (list->details.melt->session.coin.denom_pub.rsa_public_key);
|
||||
if (NULL != list->details.melt->session.coin.denom_sig.rsa_signature)
|
||||
GNUNET_CRYPTO_rsa_signature_free (list->details.melt->session.coin.denom_sig.rsa_signature);
|
||||
GNUNET_free (list->details.melt);
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_REFUND:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -308,162 +308,85 @@ static struct TALER_Amount amount_with_fee;
|
||||
*/
|
||||
#define MELT_NOREVEAL_INDEX 1
|
||||
|
||||
|
||||
static struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins;
|
||||
|
||||
/**
|
||||
* Test APIs related to the "insert_refresh_commit_coins" function.
|
||||
*
|
||||
* @param session database sesison to use
|
||||
* @param refresh_session details about the refresh session to use
|
||||
* @param session_hash refresh melt session hash to use
|
||||
* @return #GNUNET_OK on success
|
||||
* How big do we make the coin envelopes?
|
||||
*/
|
||||
static int
|
||||
test_refresh_commit_coins (struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct TALER_EXCHANGEDB_RefreshSession *refresh_session,
|
||||
const struct GNUNET_HashCode *session_hash)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *ret_commit_coins;
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *a_ccoin;
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *b_ccoin;
|
||||
unsigned int cnt;
|
||||
int ret;
|
||||
|
||||
#define COIN_ENC_MAX_SIZE 512
|
||||
ret = GNUNET_SYSERR;
|
||||
ret_commit_coins = NULL;
|
||||
commit_coins
|
||||
= GNUNET_new_array (MELT_NEW_COINS,
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin);
|
||||
for (cnt=0; cnt < MELT_NEW_COINS; cnt++)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *ccoin;
|
||||
|
||||
ccoin = &commit_coins[cnt];
|
||||
ccoin->coin_ev_size = GNUNET_CRYPTO_random_u64
|
||||
(GNUNET_CRYPTO_QUALITY_WEAK, COIN_ENC_MAX_SIZE);
|
||||
ccoin->coin_ev = GNUNET_malloc (ccoin->coin_ev_size);
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
ccoin->coin_ev,
|
||||
ccoin->coin_ev_size);
|
||||
}
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->insert_refresh_commit_coins (plugin->cls,
|
||||
session,
|
||||
session_hash,
|
||||
MELT_NEW_COINS,
|
||||
commit_coins));
|
||||
ret_commit_coins = GNUNET_new_array (MELT_NEW_COINS,
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin);
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_refresh_commit_coins (plugin->cls,
|
||||
session,
|
||||
session_hash,
|
||||
MELT_NEW_COINS,
|
||||
ret_commit_coins));
|
||||
/* compare the refresh commit coin arrays */
|
||||
for (cnt = 0; cnt < MELT_NEW_COINS; cnt++)
|
||||
{
|
||||
a_ccoin = &commit_coins[cnt];
|
||||
b_ccoin = &ret_commit_coins[cnt];
|
||||
FAILIF (a_ccoin->coin_ev_size != b_ccoin->coin_ev_size);
|
||||
FAILIF (0 != memcmp (a_ccoin->coin_ev,
|
||||
a_ccoin->coin_ev,
|
||||
a_ccoin->coin_ev_size));
|
||||
GNUNET_free (ret_commit_coins[cnt].coin_ev);
|
||||
}
|
||||
GNUNET_free (ret_commit_coins);
|
||||
ret_commit_coins = NULL;
|
||||
ret = GNUNET_OK;
|
||||
drop:
|
||||
if (NULL != ret_commit_coins)
|
||||
{
|
||||
plugin->free_refresh_commit_coins (plugin->cls,
|
||||
MELT_NEW_COINS,
|
||||
ret_commit_coins);
|
||||
GNUNET_free (ret_commit_coins);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
|
||||
|
||||
static struct TALER_TransferPrivateKeyP tprivs[TALER_CNC_KAPPA];
|
||||
|
||||
static struct TALER_TransferPublicKeyP rctp[TALER_CNC_KAPPA];
|
||||
static struct TALER_TransferPublicKeyP tpub;
|
||||
|
||||
|
||||
/**
|
||||
* Test APIs related to the "insert_refresh_commit_coins" function.
|
||||
*
|
||||
* @param session database sesison to use
|
||||
* @param refresh_session details about the refresh session to use
|
||||
* @param session_hash refresh melt session hash to use
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
test_refresh_commit_links (struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct TALER_EXCHANGEDB_RefreshSession *refresh_session,
|
||||
const struct GNUNET_HashCode *session_hash)
|
||||
{
|
||||
int ret;
|
||||
struct TALER_TransferPublicKeyP tp;
|
||||
unsigned int i;
|
||||
|
||||
ret = GNUNET_SYSERR;
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||
plugin->get_refresh_transfer_public_key (plugin->cls,
|
||||
session,
|
||||
session_hash,
|
||||
&tp));
|
||||
for (i=0;i<TALER_CNC_KAPPA;i++)
|
||||
RND_BLK (&rctp[i]);
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->insert_refresh_transfer_public_key (plugin->cls,
|
||||
session,
|
||||
session_hash,
|
||||
&rctp[MELT_NOREVEAL_INDEX]));
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_refresh_transfer_public_key (plugin->cls,
|
||||
session,
|
||||
session_hash,
|
||||
&tp));
|
||||
FAILIF (0 !=
|
||||
memcmp (&rctp[MELT_NOREVEAL_INDEX],
|
||||
&tp,
|
||||
sizeof (struct TALER_TransferPublicKeyP)));
|
||||
ret = GNUNET_OK;
|
||||
drop:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct GNUNET_HashCode session_hash;
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the session hashes and transfer secret
|
||||
* information for a given coin. Checks if they are as expected.
|
||||
* Function called with information about a refresh order. This
|
||||
* one should not be called in a successful test.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param sh a session the coin was melted in
|
||||
* @param transfer_pub public transfer key for the session
|
||||
* @param rowid unique serial ID for the row in our database
|
||||
* @param num_newcoins size of the @a rrcs array
|
||||
* @param rrcs array of @a num_newcoins information about coins to be created
|
||||
* @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1
|
||||
* @param tprivs array of @e num_tprivs transfer private keys
|
||||
* @param tp transfer public key information
|
||||
*/
|
||||
static void
|
||||
check_transfer_data (void *cls,
|
||||
const struct GNUNET_HashCode *sh,
|
||||
const struct TALER_TransferPublicKeyP *transfer_pub)
|
||||
never_called_cb (void *cls,
|
||||
uint32_t num_newcoins,
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
|
||||
unsigned int num_tprivs,
|
||||
const struct TALER_TransferPrivateKeyP *tprivs,
|
||||
const struct TALER_TransferPublicKeyP *tp)
|
||||
{
|
||||
int *ok = cls;
|
||||
GNUNET_assert (0); /* should never be called! */
|
||||
}
|
||||
|
||||
FAILIF (0 != memcmp (&rctp[MELT_NOREVEAL_INDEX],
|
||||
transfer_pub,
|
||||
sizeof (struct TALER_TransferPublicKeyP)));
|
||||
FAILIF (0 != memcmp (&session_hash,
|
||||
sh,
|
||||
sizeof (struct GNUNET_HashCode)));
|
||||
*ok = GNUNET_OK;
|
||||
return;
|
||||
drop:
|
||||
*ok = GNUNET_SYSERR;
|
||||
|
||||
/**
|
||||
* Function called with information about a refresh order.
|
||||
* Checks that the response matches what we expect to see.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the row in our database
|
||||
* @param num_newcoins size of the @a rrcs array
|
||||
* @param rrcs array of @a num_newcoins information about coins to be created
|
||||
* @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1
|
||||
* @param tprivsr array of @e num_tprivs transfer private keys
|
||||
* @param tpr transfer public key information
|
||||
*/
|
||||
static void
|
||||
check_refresh_reveal_cb (void *cls,
|
||||
uint32_t num_newcoins,
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
|
||||
unsigned int num_tprivs,
|
||||
const struct TALER_TransferPrivateKeyP *tprivsr,
|
||||
const struct TALER_TransferPublicKeyP *tpr)
|
||||
{
|
||||
/* compare the refresh commit coin arrays */
|
||||
for (unsigned int cnt = 0; cnt < num_newcoins; cnt++)
|
||||
{
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *acoin = &revealed_coins[cnt];
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *bcoin = &rrcs[cnt];
|
||||
|
||||
GNUNET_assert (acoin->coin_ev_size == bcoin->coin_ev_size);
|
||||
GNUNET_assert (0 ==
|
||||
memcmp (acoin->coin_ev,
|
||||
bcoin->coin_ev,
|
||||
acoin->coin_ev_size));
|
||||
GNUNET_assert (0 ==
|
||||
GNUNET_CRYPTO_rsa_public_key_cmp (acoin->denom_pub.rsa_public_key,
|
||||
bcoin->denom_pub.rsa_public_key));
|
||||
}
|
||||
GNUNET_assert (0 ==
|
||||
memcmp (&tpub,
|
||||
tpr,
|
||||
sizeof (tpub)));
|
||||
GNUNET_assert (0 ==
|
||||
memcmp (tprivs,
|
||||
tprivsr,
|
||||
sizeof (struct TALER_TransferPrivateKeyP) * (TALER_CNC_KAPPA - 1)));
|
||||
}
|
||||
|
||||
|
||||
@ -487,7 +410,7 @@ static unsigned int auditor_row_cnt;
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @param num_newcoins how many coins were issued
|
||||
* @param noreveal_index which index was picked by the exchange in cut-and-choose
|
||||
* @param session_hash what is the session hash
|
||||
* @param rc what is the session hash
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
static int
|
||||
@ -497,15 +420,59 @@ audit_refresh_session_cb (void *cls,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_CoinSpendSignatureP *coin_sig,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
uint16_t num_newcoins,
|
||||
uint16_t noreveal_index,
|
||||
const struct GNUNET_HashCode *session_hash)
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_RefreshCommitmentP *rc)
|
||||
{
|
||||
auditor_row_cnt++;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Denomination keys used for fresh coins in melt test.
|
||||
*/
|
||||
static struct DenomKeyPair **new_dkp;
|
||||
|
||||
|
||||
/**
|
||||
* Function called with the session hashes and transfer secret
|
||||
* information for a given coin.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param transfer_pub public transfer key for the session
|
||||
* @param ldl link data for @a transfer_pub
|
||||
*/
|
||||
static void
|
||||
handle_link_data_cb (void *cls,
|
||||
const struct TALER_TransferPublicKeyP *transfer_pub,
|
||||
const struct TALER_EXCHANGEDB_LinkDataList *ldl)
|
||||
{
|
||||
for (const struct TALER_EXCHANGEDB_LinkDataList *ldlp = ldl;
|
||||
NULL != ldlp;
|
||||
ldlp = ldlp->next)
|
||||
{
|
||||
int found;
|
||||
|
||||
found = GNUNET_NO;
|
||||
for (unsigned int cnt=0;cnt < MELT_NEW_COINS;cnt++)
|
||||
{
|
||||
GNUNET_assert (NULL != ldlp->ev_sig.rsa_signature);
|
||||
if ( (0 ==
|
||||
GNUNET_CRYPTO_rsa_public_key_cmp (ldlp->denom_pub.rsa_public_key,
|
||||
new_dkp[cnt]->pub.rsa_public_key)) &&
|
||||
(0 ==
|
||||
GNUNET_CRYPTO_rsa_signature_cmp (ldlp->ev_sig.rsa_signature,
|
||||
revealed_coins[cnt].coin_sig.rsa_signature)) )
|
||||
{
|
||||
found = GNUNET_YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
GNUNET_assert (GNUNET_NO != found);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to test melting of coins as part of a refresh session
|
||||
*
|
||||
@ -517,30 +484,20 @@ static int
|
||||
test_melting (struct TALER_EXCHANGEDB_Session *session)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshSession refresh_session;
|
||||
struct TALER_EXCHANGEDB_RefreshSession ret_refresh_session;
|
||||
struct TALER_EXCHANGEDB_RefreshMelt ret_refresh_session;
|
||||
struct DenomKeyPair *dkp;
|
||||
struct DenomKeyPair **new_dkp;
|
||||
/* struct TALER_CoinPublicInfo *coins; */
|
||||
struct TALER_EXCHANGEDB_RefreshMelt *meltp;
|
||||
struct TALER_DenominationPublicKey *new_denom_pubs;
|
||||
struct TALER_DenominationPublicKey *ret_denom_pubs;
|
||||
struct TALER_EXCHANGEDB_LinkDataList *ldl;
|
||||
struct TALER_EXCHANGEDB_LinkDataList *ldlp;
|
||||
struct TALER_DenominationSignature ev_sigs[MELT_NEW_COINS];
|
||||
unsigned int cnt;
|
||||
int ret;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
ret = GNUNET_SYSERR;
|
||||
memset (ev_sigs, 0, sizeof (ev_sigs));
|
||||
RND_BLK (&refresh_session);
|
||||
RND_BLK (&session_hash);
|
||||
dkp = NULL;
|
||||
new_dkp = NULL;
|
||||
new_denom_pubs = NULL;
|
||||
ret_denom_pubs = NULL;
|
||||
/* create and test a refresh session */
|
||||
refresh_session.num_newcoins = MELT_NEW_COINS;
|
||||
refresh_session.noreveal_index = MELT_NOREVEAL_INDEX;
|
||||
/* create a denomination (value: 1; fraction: 100) */
|
||||
dkp = create_denom_key_pair (512,
|
||||
@ -556,33 +513,62 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
|
||||
{
|
||||
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),
|
||||
RND_BLK (&refresh_session.coin.coin_pub);
|
||||
GNUNET_CRYPTO_hash (&refresh_session.coin.coin_pub,
|
||||
sizeof (refresh_session.coin.coin_pub),
|
||||
&hc);
|
||||
meltp->coin.denom_sig.rsa_signature =
|
||||
refresh_session.coin.denom_sig.rsa_signature =
|
||||
GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key,
|
||||
&hc);
|
||||
GNUNET_assert (NULL != meltp->coin.denom_sig.rsa_signature);
|
||||
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;
|
||||
GNUNET_assert (NULL != refresh_session.coin.denom_sig.rsa_signature);
|
||||
refresh_session.coin.denom_pub = dkp->pub;
|
||||
refresh_session.amount_with_fee = amount_with_fee;
|
||||
}
|
||||
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->create_refresh_session (plugin->cls,
|
||||
/* test insert_melt & get_melt */
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||
plugin->get_melt (plugin->cls,
|
||||
session,
|
||||
&refresh_session.rc,
|
||||
&ret_refresh_session));
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->insert_melt (plugin->cls,
|
||||
session,
|
||||
&session_hash,
|
||||
&refresh_session));
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_refresh_session (plugin->cls,
|
||||
plugin->get_melt (plugin->cls,
|
||||
session,
|
||||
&session_hash,
|
||||
&refresh_session.rc,
|
||||
&ret_refresh_session));
|
||||
FAILIF (refresh_session.noreveal_index !=
|
||||
ret_refresh_session.session.noreveal_index);
|
||||
FAILIF (0 !=
|
||||
TALER_amount_cmp (&refresh_session.amount_with_fee,
|
||||
&ret_refresh_session.session.amount_with_fee));
|
||||
FAILIF (0 !=
|
||||
TALER_amount_cmp (&fee_refresh,
|
||||
&ret_refresh_session.melt_fee));
|
||||
FAILIF (0 !=
|
||||
memcmp (&refresh_session.rc,
|
||||
&ret_refresh_session.session.rc,
|
||||
sizeof (struct TALER_RefreshCommitmentP)));
|
||||
FAILIF (0 !=
|
||||
memcmp (&refresh_session.coin_sig,
|
||||
&ret_refresh_session.session.coin_sig,
|
||||
sizeof (struct TALER_CoinSpendSignatureP)));
|
||||
FAILIF (0 !=
|
||||
GNUNET_CRYPTO_rsa_signature_cmp (refresh_session.coin.denom_sig.rsa_signature,
|
||||
ret_refresh_session.session.coin.denom_sig.rsa_signature));
|
||||
FAILIF (0 != memcmp (&refresh_session.coin.coin_pub,
|
||||
&ret_refresh_session.session.coin.coin_pub,
|
||||
sizeof (refresh_session.coin.coin_pub)));
|
||||
FAILIF (0 !=
|
||||
GNUNET_CRYPTO_rsa_public_key_cmp (refresh_session.coin.denom_pub.rsa_public_key,
|
||||
ret_refresh_session.session.coin.denom_pub.rsa_public_key));
|
||||
GNUNET_CRYPTO_rsa_signature_free (ret_refresh_session.session.coin.denom_sig.rsa_signature);
|
||||
GNUNET_CRYPTO_rsa_public_key_free (ret_refresh_session.session.coin.denom_pub.rsa_public_key);
|
||||
|
||||
/* test 'select_refreshs_above_serial_id' */
|
||||
auditor_row_cnt = 0;
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->select_refreshs_above_serial_id (plugin->cls,
|
||||
@ -591,41 +577,19 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
|
||||
&audit_refresh_session_cb,
|
||||
NULL));
|
||||
FAILIF (1 != auditor_row_cnt);
|
||||
FAILIF (ret_refresh_session.num_newcoins != refresh_session.num_newcoins);
|
||||
FAILIF (ret_refresh_session.noreveal_index != refresh_session.noreveal_index);
|
||||
|
||||
/* check refresh session melt data */
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshMelt *ret_melt;
|
||||
|
||||
ret_melt = &ret_refresh_session.melt;
|
||||
FAILIF (0 != GNUNET_CRYPTO_rsa_signature_cmp
|
||||
(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,
|
||||
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_dkp = GNUNET_new_array (MELT_NEW_COINS,
|
||||
struct DenomKeyPair *);
|
||||
new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
|
||||
struct TALER_DenominationPublicKey);
|
||||
for (cnt=0; cnt < MELT_NEW_COINS; cnt++)
|
||||
revealed_coins
|
||||
= GNUNET_new_array (MELT_NEW_COINS,
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin);
|
||||
for (unsigned int cnt=0; cnt < MELT_NEW_COINS; cnt++)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
|
||||
struct GNUNET_HashCode hc;
|
||||
|
||||
new_dkp[cnt] = create_denom_key_pair (1024,
|
||||
session,
|
||||
GNUNET_TIME_absolute_get (),
|
||||
@ -636,100 +600,50 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
|
||||
&fee_refund);
|
||||
GNUNET_assert (NULL != new_dkp[cnt]);
|
||||
new_denom_pubs[cnt] = new_dkp[cnt]->pub;
|
||||
}
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->insert_refresh_order (plugin->cls,
|
||||
session,
|
||||
&session_hash,
|
||||
MELT_NEW_COINS,
|
||||
new_denom_pubs));
|
||||
ret_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
|
||||
struct TALER_DenominationPublicKey);
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_refresh_order (plugin->cls,
|
||||
session,
|
||||
&session_hash,
|
||||
MELT_NEW_COINS,
|
||||
ret_denom_pubs));
|
||||
for (cnt=0; cnt < MELT_NEW_COINS; cnt++)
|
||||
{
|
||||
FAILIF (0 != GNUNET_CRYPTO_rsa_public_key_cmp
|
||||
(ret_denom_pubs[cnt].rsa_public_key,
|
||||
new_denom_pubs[cnt].rsa_public_key));
|
||||
}
|
||||
FAILIF (GNUNET_OK !=
|
||||
test_refresh_commit_coins (session,
|
||||
&refresh_session,
|
||||
&session_hash));
|
||||
FAILIF (GNUNET_OK !=
|
||||
test_refresh_commit_links (session,
|
||||
&refresh_session,
|
||||
&session_hash));
|
||||
|
||||
for (cnt=0; cnt < MELT_NEW_COINS; cnt++)
|
||||
{
|
||||
struct GNUNET_HashCode hc;
|
||||
struct TALER_DenominationSignature test_sig;
|
||||
|
||||
ccoin = &revealed_coins[cnt];
|
||||
ccoin->coin_ev_size = (size_t) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
COIN_ENC_MAX_SIZE);
|
||||
ccoin->coin_ev = GNUNET_malloc (ccoin->coin_ev_size);
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
ccoin->coin_ev,
|
||||
ccoin->coin_ev_size);
|
||||
RND_BLK (&hc);
|
||||
ev_sigs[cnt].rsa_signature
|
||||
ccoin->denom_pub = new_dkp[cnt]->pub;
|
||||
ccoin->coin_sig.rsa_signature
|
||||
= GNUNET_CRYPTO_rsa_sign_fdh (new_dkp[cnt]->priv.rsa_private_key,
|
||||
&hc);
|
||||
GNUNET_assert (NULL != ev_sigs[cnt].rsa_signature);
|
||||
}
|
||||
RND_BLK (&tprivs);
|
||||
RND_BLK (&tpub);
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
|
||||
plugin->get_refresh_out (plugin->cls,
|
||||
plugin->get_refresh_reveal (plugin->cls,
|
||||
session,
|
||||
&session_hash,
|
||||
cnt,
|
||||
&test_sig));
|
||||
&refresh_session.rc,
|
||||
&never_called_cb,
|
||||
NULL));
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->insert_refresh_out (plugin->cls,
|
||||
plugin->insert_refresh_reveal (plugin->cls,
|
||||
session,
|
||||
&session_hash,
|
||||
cnt,
|
||||
&ev_sigs[cnt]));
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_refresh_out (plugin->cls,
|
||||
&refresh_session.rc,
|
||||
MELT_NEW_COINS,
|
||||
revealed_coins,
|
||||
TALER_CNC_KAPPA - 1,
|
||||
tprivs,
|
||||
&tpub));
|
||||
FAILIF (0 >=
|
||||
plugin->get_refresh_reveal (plugin->cls,
|
||||
session,
|
||||
&session_hash,
|
||||
cnt,
|
||||
&test_sig));
|
||||
FAILIF (0 !=
|
||||
GNUNET_CRYPTO_rsa_signature_cmp (test_sig.rsa_signature,
|
||||
ev_sigs[cnt].rsa_signature));
|
||||
GNUNET_CRYPTO_rsa_signature_free (test_sig.rsa_signature);
|
||||
}
|
||||
&refresh_session.rc,
|
||||
&check_refresh_reveal_cb,
|
||||
NULL));
|
||||
|
||||
qs = plugin->get_link_data_list (plugin->cls,
|
||||
|
||||
qs = plugin->get_link_data (plugin->cls,
|
||||
session,
|
||||
&session_hash,
|
||||
&ldl);
|
||||
&refresh_session.coin.coin_pub,
|
||||
&handle_link_data_cb,
|
||||
NULL);
|
||||
FAILIF (0 >= qs);
|
||||
FAILIF (NULL == ldl);
|
||||
for (ldlp = ldl; NULL != ldlp; ldlp = ldlp->next)
|
||||
{
|
||||
int found;
|
||||
|
||||
found = GNUNET_NO;
|
||||
for (cnt=0;cnt < MELT_NEW_COINS;cnt++)
|
||||
{
|
||||
FAILIF (NULL == ldlp->ev_sig.rsa_signature);
|
||||
if ( (0 ==
|
||||
GNUNET_CRYPTO_rsa_public_key_cmp (ldlp->denom_pub.rsa_public_key,
|
||||
new_dkp[cnt]->pub.rsa_public_key)) &&
|
||||
(0 ==
|
||||
GNUNET_CRYPTO_rsa_signature_cmp (ldlp->ev_sig.rsa_signature,
|
||||
ev_sigs[cnt].rsa_signature)) )
|
||||
{
|
||||
found = GNUNET_YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
FAILIF (GNUNET_NO == found);
|
||||
}
|
||||
plugin->free_link_data_list (plugin->cls,
|
||||
ldl);
|
||||
|
||||
{
|
||||
/* Just to test fetching a coin with melt history */
|
||||
struct TALER_EXCHANGEDB_TransactionList *tl;
|
||||
@ -737,7 +651,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
|
||||
|
||||
qs = plugin->get_coin_transactions (plugin->cls,
|
||||
session,
|
||||
&meltp->coin.coin_pub,
|
||||
&refresh_session.coin.coin_pub,
|
||||
&tl);
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs);
|
||||
plugin->free_coin_transaction_list (plugin->cls,
|
||||
@ -745,42 +659,29 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
int ok;
|
||||
|
||||
ok = GNUNET_NO;
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_transfer (plugin->cls,
|
||||
session,
|
||||
&meltp->coin.coin_pub,
|
||||
&check_transfer_data,
|
||||
&ok));
|
||||
FAILIF (GNUNET_OK != ok);
|
||||
}
|
||||
|
||||
ret = GNUNET_OK;
|
||||
drop:
|
||||
for (cnt=0; cnt < MELT_NEW_COINS; cnt++)
|
||||
if (NULL != ev_sigs[cnt].rsa_signature)
|
||||
GNUNET_CRYPTO_rsa_signature_free (ev_sigs[cnt].rsa_signature);
|
||||
if (NULL != commit_coins)
|
||||
if (NULL != revealed_coins)
|
||||
{
|
||||
plugin->free_refresh_commit_coins (plugin->cls,
|
||||
MELT_NEW_COINS,
|
||||
commit_coins);
|
||||
GNUNET_free (commit_coins);
|
||||
commit_coins = NULL;
|
||||
for (unsigned int cnt=0; cnt < MELT_NEW_COINS; cnt++)
|
||||
{
|
||||
if (NULL != revealed_coins[cnt].coin_sig.rsa_signature)
|
||||
GNUNET_CRYPTO_rsa_signature_free (revealed_coins[cnt].coin_sig.rsa_signature);
|
||||
GNUNET_free (revealed_coins[cnt].coin_ev);
|
||||
}
|
||||
GNUNET_free (revealed_coins);
|
||||
revealed_coins = NULL;
|
||||
}
|
||||
destroy_denom_key_pair (dkp);
|
||||
GNUNET_CRYPTO_rsa_signature_free (meltp->coin.denom_sig.rsa_signature);
|
||||
for (cnt = 0;
|
||||
GNUNET_CRYPTO_rsa_signature_free (refresh_session.coin.denom_sig.rsa_signature);
|
||||
for (unsigned int cnt = 0;
|
||||
(NULL != ret_denom_pubs) && (cnt < MELT_NEW_COINS)
|
||||
&& (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);
|
||||
GNUNET_free_non_null (new_denom_pubs);
|
||||
for (cnt = 0;
|
||||
for (unsigned int cnt = 0;
|
||||
(NULL != new_dkp) && (cnt < MELT_NEW_COINS) && (NULL != new_dkp[cnt]);
|
||||
cnt++)
|
||||
destroy_denom_key_pair (new_dkp[cnt]);
|
||||
@ -1439,7 +1340,7 @@ wire_missing_cb (void *cls,
|
||||
/* bool? */ int tiny,
|
||||
/* bool? */ int done)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_Deposit *deposit = cls;
|
||||
const struct TALER_EXCHANGEDB_Deposit *deposit = cls;
|
||||
struct GNUNET_HashCode h_wire;
|
||||
|
||||
if (NULL != wire)
|
||||
@ -1615,6 +1516,7 @@ run (void *cls)
|
||||
session,
|
||||
&rr,
|
||||
&rr_size));
|
||||
GNUNET_free (rr);
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_latest_reserve_in_reference (plugin->cls,
|
||||
session,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015 GNUnet e.V.
|
||||
Copyright (C) 2014, 2015, 2016, 2017 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -289,6 +289,19 @@ struct TALER_DenominationBlindingKeyP
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Commitment value for the refresh protocol.
|
||||
* See #TALER_refresh_get_commitment().
|
||||
*/
|
||||
struct TALER_RefreshCommitmentP
|
||||
{
|
||||
/**
|
||||
* The commitment is a hash code.
|
||||
*/
|
||||
struct GNUNET_HashCode session_hash;
|
||||
};
|
||||
|
||||
|
||||
GNUNET_NETWORK_STRUCT_END
|
||||
|
||||
|
||||
@ -557,12 +570,12 @@ GNUNET_NETWORK_STRUCT_END
|
||||
*
|
||||
* @param secret_seed seed to use for KDF to derive coin keys
|
||||
* @param coin_num_salt number of the coin to include in KDF
|
||||
* @param[out] fc value to initialize
|
||||
* @param[out] ps value to initialize
|
||||
*/
|
||||
void
|
||||
TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed,
|
||||
unsigned int coin_num_salt,
|
||||
struct TALER_PlanchetSecretsP *fc);
|
||||
uint32_t coin_num_salt,
|
||||
struct TALER_PlanchetSecretsP *ps);
|
||||
|
||||
|
||||
/**
|
||||
@ -656,4 +669,65 @@ TALER_link_recover_transfer_secret (const struct TALER_TransferPublicKeyP *trans
|
||||
struct TALER_TransferSecretP *transfer_secret);
|
||||
|
||||
|
||||
/**
|
||||
* Information about a coin to be created during a refresh operation.
|
||||
*/
|
||||
struct TALER_RefreshCoinData
|
||||
{
|
||||
|
||||
/**
|
||||
* The denomination's public key.
|
||||
*/
|
||||
const struct TALER_DenominationPublicKey *dk;
|
||||
|
||||
/**
|
||||
* The envelope with the blinded coin.
|
||||
*/
|
||||
char *coin_ev;
|
||||
|
||||
/**
|
||||
* Number of bytes in @a coin_ev
|
||||
*/
|
||||
size_t coin_ev_size;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* One of the #TALER_CNC_KAPPA commitments.
|
||||
*/
|
||||
struct TALER_RefreshCommitmentEntry
|
||||
{
|
||||
/**
|
||||
* Transfer public key of this commitment.
|
||||
*/
|
||||
struct TALER_TransferPublicKeyP transfer_pub;
|
||||
|
||||
/**
|
||||
* Array of @e num_new_coins new coins to be created.
|
||||
*/
|
||||
struct TALER_RefreshCoinData *new_coins;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compute the commitment for a /refresh/melt operation from
|
||||
* the respective public inputs.
|
||||
*
|
||||
* @param[out] rc set to the value the wallet must commit to
|
||||
* @param kappa number of transfer public keys involved (must be #TALER_CNC_KAPPA)
|
||||
* @param num_new_coins number of new coins to be created
|
||||
* @param commitments array of @a kappa commitments
|
||||
* @param coin_pub public key of the coin to be melted
|
||||
* @param amount_with_fee amount to be melted, including fee
|
||||
*/
|
||||
void
|
||||
TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
|
||||
uint32_t kappa,
|
||||
uint32_t num_new_coins,
|
||||
const struct TALER_RefreshCommitmentEntry *rcs,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_Amount *amount_with_fee);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -68,6 +68,11 @@ enum TALER_ErrorCode
|
||||
*/
|
||||
TALER_EC_TIMEOUT = 6,
|
||||
|
||||
/**
|
||||
* Exchange failed to allocate memory for building JSON reply.
|
||||
*/
|
||||
TALER_EC_JSON_ALLOCATION_FAILURE = 7,
|
||||
|
||||
/* ********** generic error codes ************* */
|
||||
|
||||
/**
|
||||
@ -428,6 +433,7 @@ enum TALER_ErrorCode
|
||||
*/
|
||||
TALER_EC_DEPOSIT_INVALID_TIMESTAMP = 1218,
|
||||
|
||||
|
||||
/**
|
||||
* The respective coin did not have sufficient residual value
|
||||
* for the /refresh/melt operation. The "history" in this
|
||||
@ -468,86 +474,26 @@ enum TALER_ErrorCode
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_DB_STORE_SESSION_ERROR = 1304,
|
||||
|
||||
/**
|
||||
* The exchange failed to store commit data in the
|
||||
* database.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_INTERNAL_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_DB_STORE_COMMIT_ERROR = 1306,
|
||||
|
||||
/**
|
||||
* The exchange is unaware of the denomination key that was
|
||||
* requested for one of the fresh coins. This response is provided
|
||||
* with HTTP status code MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_FRESH_DENOMINATION_KEY_NOT_FOUND = 1308,
|
||||
|
||||
/**
|
||||
* The exchange encountered a numeric overflow totaling up
|
||||
* the cost for the refresh operation. This response is provided
|
||||
* with HTTP status code MHD_HTTP_INTERNAL_SERVER_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_COST_CALCULATION_OVERFLOW = 1309,
|
||||
|
||||
/**
|
||||
* During the transaction phase, the exchange could suddenly
|
||||
* no longer find the denomination key that was
|
||||
* used to sign the melted coin. This response is provided
|
||||
* with HTTP status code MHD_HTTP_INTERNAL_SERVER_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_DB_DENOMINATION_KEY_NOT_FOUND = 1310,
|
||||
|
||||
/**
|
||||
* The exchange encountered melt fees exceeding the melted
|
||||
* coin's contribution. This response is provided
|
||||
* with HTTP status code MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION = 1311,
|
||||
|
||||
/**
|
||||
* The exchange's cost calculation does not add up to the
|
||||
* melt fees specified in the request. This response is provided
|
||||
* with HTTP status code MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_FEES_MISSMATCH = 1312,
|
||||
TALER_EC_REFRESH_MELT_FEES_EXCEED_CONTRIBUTION = 1305,
|
||||
|
||||
/**
|
||||
* The denomination key signature on the melted coin is invalid.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID = 1313,
|
||||
|
||||
/**
|
||||
* The exchange's cost calculation shows that the melt amount
|
||||
* is below the costs of the transaction. This response is provided
|
||||
* with HTTP status code MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_AMOUNT_INSUFFICIENT = 1314,
|
||||
TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID = 1306,
|
||||
|
||||
/**
|
||||
* The signature made with the coin to be melted is invalid.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID = 1315,
|
||||
|
||||
/**
|
||||
* The size of the cut-and-choose dimension of the
|
||||
* blinded coins request does not match #TALER_CNC_KAPPA.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_CNC_COIN_ARRAY_SIZE_INVALID = 1316,
|
||||
|
||||
/**
|
||||
* The size of the cut-and-choose dimension of the
|
||||
* transfer keys request does not match #TALER_CNC_KAPPA.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_CNC_TRANSFER_ARRAY_SIZE_INVALID = 1317,
|
||||
TALER_EC_REFRESH_MELT_COIN_SIGNATURE_INVALID = 1307,
|
||||
|
||||
/**
|
||||
* The exchange failed to obtain the transaction history of the
|
||||
@ -556,7 +502,8 @@ enum TALER_ErrorCode
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_INTERNAL_SERVER_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_MELT_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS = 1318,
|
||||
TALER_EC_REFRESH_MELT_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS = 1308,
|
||||
|
||||
|
||||
/**
|
||||
* The provided transfer keys do not match up with the
|
||||
@ -566,21 +513,13 @@ enum TALER_ErrorCode
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_COMMITMENT_VIOLATION = 1350,
|
||||
|
||||
/**
|
||||
* Failed to blind the envelope to reconstruct the blinded
|
||||
* coins for revealation checks.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_INTERNAL_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_BLINDING_ERROR = 1351,
|
||||
|
||||
/**
|
||||
* Failed to produce the blinded signatures over the coins
|
||||
* to be returned.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_INTERNAL_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_SIGNING_ERROR = 1352,
|
||||
TALER_EC_REFRESH_REVEAL_SIGNING_ERROR = 1351,
|
||||
|
||||
/**
|
||||
* The exchange is unaware of the refresh sessino specified in
|
||||
@ -588,7 +527,7 @@ enum TALER_ErrorCode
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN = 1353,
|
||||
TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN = 1352,
|
||||
|
||||
/**
|
||||
* The exchange failed to retrieve valid session data from the
|
||||
@ -596,23 +535,14 @@ enum TALER_ErrorCode
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_INTERNAL_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR = 1354,
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR = 1353,
|
||||
|
||||
/**
|
||||
* The exchange failed to retrieve order data from the
|
||||
* database.
|
||||
* This response is provided with HTTP status code
|
||||
* The exchange failed to retrieve previously revealed data from the
|
||||
* database. This response is provided with HTTP status code
|
||||
* MHD_HTTP_INTERNAL_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_ORDER_ERROR = 1355,
|
||||
|
||||
/**
|
||||
* The exchange failed to retrieve transfer keys from the
|
||||
* database.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_INTERNAL_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_TRANSFER_ERROR = 1356,
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_REVEAL_ERROR = 1354,
|
||||
|
||||
/**
|
||||
* The exchange failed to retrieve commitment data from the
|
||||
@ -620,7 +550,7 @@ enum TALER_ErrorCode
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_INTERNAL_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_DB_FETCH_COMMIT_ERROR = 1357,
|
||||
TALER_EC_REFRESH_REVEAL_DB_COMMIT_ERROR = 1355,
|
||||
|
||||
/**
|
||||
* The size of the cut-and-choose dimension of the
|
||||
@ -628,7 +558,45 @@ enum TALER_ErrorCode
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID = 1358,
|
||||
TALER_EC_REFRESH_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID = 1356,
|
||||
|
||||
/**
|
||||
* The number of coins to be created in refresh exceeds the limits
|
||||
* of the exchange.
|
||||
* private transfer keys request does not match #TALER_CNC_KAPPA - 1.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE = 1357,
|
||||
|
||||
/**
|
||||
* The number of envelopes given does not match the number
|
||||
* of denomination keys given.
|
||||
* This response is provided with HTTP status code
|
||||
* MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISSMATCH = 1358,
|
||||
|
||||
/**
|
||||
* The exchange encountered a numeric overflow totaling up
|
||||
* the cost for the refresh operation. This response is provided
|
||||
* with HTTP status code MHD_HTTP_INTERNAL_SERVER_ERROR.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_COST_CALCULATION_OVERFLOW = 1359,
|
||||
|
||||
/**
|
||||
* The exchange's cost calculation shows that the melt amount
|
||||
* is below the costs of the transaction. This response is provided
|
||||
* with HTTP status code MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_AMOUNT_INSUFFICIENT = 1360,
|
||||
|
||||
/**
|
||||
* The exchange is unaware of the denomination key that was
|
||||
* requested for one of the fresh coins. This response is provided
|
||||
* with HTTP status code MHD_HTTP_BAD_REQUEST.
|
||||
*/
|
||||
TALER_EC_REFRESH_REVEAL_FRESH_DENOMINATION_KEY_NOT_FOUND = 1361,
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2017 GNUnet e.V.
|
||||
Copyright (C) 2014-2017 Taler Systems SA
|
||||
|
||||
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
|
||||
@ -1110,7 +1110,7 @@ struct TALER_EXCHANGE_RefreshMeltHandle;
|
||||
* 0 if the exchange's reply is bogus (fails to follow the protocol)
|
||||
* @param ec taler-specific error code, #TALER_EC_NONE on success
|
||||
* @param noreveal_index choice by the exchange in the cut-and-choose protocol,
|
||||
* UINT16_MAX on error
|
||||
* UINT32_MAX on error
|
||||
* @param sign_key exchange key used to sign @a full_response, or NULL
|
||||
* @param full_response full response from the exchange (for logging, in case of errors)
|
||||
*/
|
||||
@ -1118,7 +1118,7 @@ typedef void
|
||||
(*TALER_EXCHANGE_RefreshMeltCallback) (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
uint16_t noreveal_index,
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *sign_key,
|
||||
const json_t *full_response);
|
||||
|
||||
@ -1223,7 +1223,7 @@ struct TALER_EXCHANGE_RefreshRevealHandle *
|
||||
TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
|
||||
size_t refresh_data_length,
|
||||
const char *refresh_data,
|
||||
uint16_t noreveal_index,
|
||||
uint32_t noreveal_index,
|
||||
TALER_EXCHANGE_RefreshRevealCallback reveal_cb,
|
||||
void *reveal_cb_cls);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2017 GNUnet e.V.
|
||||
Copyright (C) 2014-2017 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -465,7 +465,7 @@ struct TALER_EXCHANGEDB_Refund
|
||||
/**
|
||||
* @brief Specification for coin in a /refresh/melt operation.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshMelt
|
||||
struct TALER_EXCHANGEDB_RefreshSession
|
||||
{
|
||||
/**
|
||||
* Information about the coin that is being melted.
|
||||
@ -478,9 +478,9 @@ struct TALER_EXCHANGEDB_RefreshMelt
|
||||
struct TALER_CoinSpendSignatureP coin_sig;
|
||||
|
||||
/**
|
||||
* Hash of the refresh session this coin is melted into.
|
||||
* Refresh commitment this coin is melted into.
|
||||
*/
|
||||
struct GNUNET_HashCode session_hash;
|
||||
struct TALER_RefreshCommitmentP rc;
|
||||
|
||||
/**
|
||||
* How much value is being melted? This amount includes the fees,
|
||||
@ -492,65 +492,30 @@ struct TALER_EXCHANGEDB_RefreshMelt
|
||||
*/
|
||||
struct TALER_Amount amount_with_fee;
|
||||
|
||||
/**
|
||||
* Melting fee charged by the exchange. This must match the Exchange's
|
||||
* denomination key's melting fee. If the client puts in an invalid
|
||||
* melting fee (too high or too low) that does not match the Exchange's
|
||||
* denomination key, the melting operation is invalid and will be
|
||||
* rejected by the exchange. The @e amount_with_fee minus the @e
|
||||
* melt_fee is the amount that will be credited to the melting
|
||||
* session.
|
||||
*/
|
||||
struct TALER_Amount melt_fee;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @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;
|
||||
uint32_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
|
||||
* sets). These are the coins we ask the exchange to sign if the
|
||||
* respective set is selected.
|
||||
* Information about a /refresh/melt operation in the transaction history.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin
|
||||
struct TALER_EXCHANGEDB_RefreshMelt
|
||||
{
|
||||
|
||||
/**
|
||||
* Blinded message to be signed (in envelope), with @e coin_env_size bytes.
|
||||
* Overall session data.
|
||||
*/
|
||||
char *coin_ev;
|
||||
struct TALER_EXCHANGEDB_RefreshSession session;
|
||||
|
||||
/**
|
||||
* Number of bytes in @e coin_ev.
|
||||
* Melt fee the exchange charged.
|
||||
*/
|
||||
size_t coin_ev_size;
|
||||
struct TALER_Amount melt_fee;
|
||||
|
||||
};
|
||||
|
||||
@ -752,9 +717,8 @@ typedef int
|
||||
* @param coin_pub public key of the coin
|
||||
* @param coin_sig signature from the coin
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @param num_newcoins how many coins were issued
|
||||
* @param noreveal_index which index was picked by the exchange in cut-and-choose
|
||||
* @param session_hash what is the session hash
|
||||
* @param rc what is the commitment
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
typedef int
|
||||
@ -764,9 +728,56 @@ typedef int
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_CoinSpendSignatureP *coin_sig,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
uint16_t num_newcoins,
|
||||
uint16_t noreveal_index,
|
||||
const struct GNUNET_HashCode *session_hash);
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_RefreshCommitmentP *rc);
|
||||
|
||||
|
||||
/**
|
||||
* Information about a coin that was revealed to the exchange
|
||||
* during /refresh/reveal.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_RefreshRevealedCoin
|
||||
{
|
||||
/**
|
||||
* Public denomination key of the coin.
|
||||
*/
|
||||
struct TALER_DenominationPublicKey denom_pub;
|
||||
|
||||
/**
|
||||
* Blinded message to be signed (in envelope), with @e coin_env_size bytes.
|
||||
*/
|
||||
char *coin_ev;
|
||||
|
||||
/**
|
||||
* Number of bytes in @e coin_ev.
|
||||
*/
|
||||
size_t coin_ev_size;
|
||||
|
||||
/**
|
||||
* Signature generated by the exchange over the coin (in blinded format).
|
||||
*/
|
||||
struct TALER_DenominationSignature coin_sig;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function called with information about a refresh order.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid unique serial ID for the row in our database
|
||||
* @param num_newcoins size of the @a rrcs array
|
||||
* @param rrcs array of @a num_newcoins information about coins to be created
|
||||
* @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1
|
||||
* @param tprivs array of @e num_tprivs transfer private keys
|
||||
* @param tp transfer public key information
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_EXCHANGEDB_RefreshCallback)(void *cls,
|
||||
uint32_t num_newcoins,
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
|
||||
unsigned int num_tprivs,
|
||||
const struct TALER_TransferPrivateKeyP *tprivs,
|
||||
const struct TALER_TransferPublicKeyP *tp);
|
||||
|
||||
|
||||
/**
|
||||
@ -851,14 +862,13 @@ typedef int
|
||||
* information for a given coin.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param session_hash a session the coin was melted in
|
||||
* @param transfer_pub public transfer key for the session
|
||||
* @param shared_secret_enc set to shared secret for the session
|
||||
* @param ldl link data for @a transfer_pub
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_EXCHANGEDB_TransferDataCallback)(void *cls,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
const struct TALER_TransferPublicKeyP *transfer_pub);
|
||||
(*TALER_EXCHANGEDB_LinkDataCallback)(void *cls,
|
||||
const struct TALER_TransferPublicKeyP *transfer_pub,
|
||||
const struct TALER_EXCHANGEDB_LinkDataList *ldl);
|
||||
|
||||
|
||||
/**
|
||||
@ -1454,225 +1464,79 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
|
||||
|
||||
/**
|
||||
* Lookup refresh session data under the given @a session_hash.
|
||||
* Store new refresh melt commitment data.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session database handle to use
|
||||
* @param session_hash hash over the melt to use for the lookup
|
||||
* @param[out] refresh_session where to store the result
|
||||
* @return transaction status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_refresh_session) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
struct TALER_EXCHANGEDB_RefreshSession *refresh_session);
|
||||
|
||||
|
||||
/**
|
||||
* Store new refresh session data under the given @a session_hash.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session database handle to use
|
||||
* @param session_hash hash over the melt to use to locate the session
|
||||
* @param refresh_session session data to store
|
||||
* @param refresh_session operational data to store
|
||||
* @return query status for the transaction
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*create_refresh_session) (void *cls,
|
||||
(*insert_melt) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
const struct TALER_EXCHANGEDB_RefreshSession *refresh_session);
|
||||
|
||||
|
||||
/**
|
||||
* Store in the database which coin(s) we want to create
|
||||
* in a given refresh operation.
|
||||
* Lookup refresh metl commitment data under the given @a rc.
|
||||
*
|
||||
* @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 num_newcoins number of coins to generate, size of the @a denom_pubs array
|
||||
* @param denom_pubs array denominations of the coins to create
|
||||
* @return query status for the transaction
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*insert_refresh_order) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t num_newcoins,
|
||||
const struct TALER_DenominationPublicKey *denom_pubs);
|
||||
|
||||
|
||||
/**
|
||||
* Lookup in the database for the @a num_newcoins coins that we want to
|
||||
* create in the given refresh operation.
|
||||
*
|
||||
* @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 num_newcoins size of the @a denom_pubs array
|
||||
* @param[out] denom_pubs where to write @a num_newcoins denomination keys
|
||||
* @param session database handle to use
|
||||
* @param rc commitment to use for the lookup
|
||||
* @param[out] refresh_melt where to store the result
|
||||
* @return transaction status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_refresh_order) (void *cls,
|
||||
(*get_melt) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t num_newcoins,
|
||||
struct TALER_DenominationPublicKey *denom_pubs);
|
||||
const struct TALER_RefreshCommitmentP *rc,
|
||||
struct TALER_EXCHANGEDB_RefreshMelt *refresh_melt);
|
||||
|
||||
|
||||
/**
|
||||
* Store information about the commitments of the given index @a i
|
||||
* for the given refresh session in the database.
|
||||
* Store in the database which coin(s) the wallet wanted to create
|
||||
* in a given refresh operation and all of the other information
|
||||
* we learned or created in the /refresh/reveal step.
|
||||
*
|
||||
* @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 num_newcoins coin index size of the @a commit_coins array
|
||||
* @param commit_coin array of coin commitments to store
|
||||
* @return query status for the transaction
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*insert_refresh_commit_coins) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t num_newcoins,
|
||||
const struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain information about the commitment of the
|
||||
* given coin of the given refresh session from the database.
|
||||
*
|
||||
* @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 num_coins size of the @a commit_coins array
|
||||
* @param[out] commit_coins array of coin commitments to return
|
||||
* @return transaction status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_refresh_commit_coins) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t num_coins,
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins);
|
||||
|
||||
/**
|
||||
* Free refresh @a commit_coins data obtained via @e get_refresh_commit_coins.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param num_coins size of the @a commit_coins array
|
||||
* @param commit_coins array of coin commitments to free
|
||||
*/
|
||||
void
|
||||
(*free_refresh_commit_coins) (void *cls,
|
||||
unsigned int num_coins,
|
||||
struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins);
|
||||
|
||||
|
||||
/**
|
||||
* Store the commitment to the given (encrypted) refresh link data
|
||||
* for the given refresh session.
|
||||
*
|
||||
* @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 session database connection
|
||||
* @param rc identify commitment and thus refresh operation
|
||||
* @param num_rrcs_newcoins number of coins to generate, size of the
|
||||
* @a rrcs array
|
||||
* @param rrcs information about the new coins
|
||||
* @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1
|
||||
* @param tprivs transfer private keys to store
|
||||
* @param tp public key to store
|
||||
* @return query status for the transaction
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*insert_refresh_transfer_public_key) (void *cls,
|
||||
(*insert_refresh_reveal) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
const struct TALER_RefreshCommitmentP *rc,
|
||||
uint32_t num_rrcs,
|
||||
const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
|
||||
unsigned int num_tprivs,
|
||||
const struct TALER_TransferPrivateKeyP *tprivs,
|
||||
const struct TALER_TransferPublicKeyP *tp);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the commited (encrypted) refresh link data
|
||||
* for the given refresh session.
|
||||
* Lookup in the database for the @a num_newcoins coins that we
|
||||
* created in the given refresh operation.
|
||||
*
|
||||
* @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[out] tp information to return
|
||||
* @param session database connection
|
||||
* @param rc identify commitment and thus refresh operation
|
||||
* @param cb function to call with the results
|
||||
* @param cb_cls closure for @a cb
|
||||
* @return transaction status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_refresh_transfer_public_key) (void *cls,
|
||||
(*get_refresh_reveal) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
struct TALER_TransferPublicKeyP *tp);
|
||||
|
||||
|
||||
/**
|
||||
* Get signature of a new coin generated during refresh into
|
||||
* the database indexed by the refresh session and the index
|
||||
* of the coin.
|
||||
*
|
||||
* @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 newcoin_index coin index
|
||||
* @param[out] ev_sig coin signature
|
||||
* @return transaction result status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_refresh_out) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t newcoin_index,
|
||||
struct TALER_DenominationSignature *ev_sig);
|
||||
|
||||
|
||||
/**
|
||||
* Insert signature of a new coin generated during refresh into
|
||||
* the database indexed by the refresh session and the index
|
||||
* of the coin. This data is later used should an old coin
|
||||
* be used to try to obtain the private keys during "/refresh/link".
|
||||
*
|
||||
* @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 newcoin_index coin index
|
||||
* @param ev_sig coin signature
|
||||
* @return transaction result status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*insert_refresh_out) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
uint16_t newcoin_index,
|
||||
const struct TALER_DenominationSignature *ev_sig);
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the link data of a coin, that is the encrypted link
|
||||
* information, the denomination keys and the signatures.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session database connection
|
||||
* @param session_hash session to get linkage data for
|
||||
* @param[out] ldldp set to all known link data for the session
|
||||
* @return status of the transaction
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_link_data_list) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct GNUNET_HashCode *session_hash,
|
||||
struct TALER_EXCHANGEDB_LinkDataList **ldlp);
|
||||
|
||||
|
||||
/**
|
||||
* Free memory of the link data list.
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param ldl link data list to release
|
||||
*/
|
||||
void
|
||||
(*free_link_data_list) (void *cls,
|
||||
struct TALER_EXCHANGEDB_LinkDataList *ldl);
|
||||
const struct TALER_RefreshCommitmentP *rc,
|
||||
TALER_EXCHANGEDB_RefreshCallback cb,
|
||||
void *cb_cls);
|
||||
|
||||
|
||||
/**
|
||||
@ -1684,15 +1548,15 @@ struct TALER_EXCHANGEDB_Plugin
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param session database connection
|
||||
* @param coin_pub public key of the coin
|
||||
* @param tdc function to call for each session the coin was melted into
|
||||
* @param tdc_cls closure for @a tdc
|
||||
* @param ldc function to call for each session the coin was melted into
|
||||
* @param ldc_cls closure for @a tdc
|
||||
* @return statement execution status
|
||||
*/
|
||||
enum GNUNET_DB_QueryStatus
|
||||
(*get_transfer) (void *cls,
|
||||
(*get_link_data) (void *cls,
|
||||
struct TALER_EXCHANGEDB_Session *session,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
TALER_EXCHANGEDB_TransferDataCallback tdc,
|
||||
TALER_EXCHANGEDB_LinkDataCallback ldc,
|
||||
void *tdc_cls);
|
||||
|
||||
|
||||
|
@ -532,9 +532,9 @@ struct TALER_RefreshMeltCoinAffirmationPS
|
||||
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||
|
||||
/**
|
||||
* Which melting session should the coin become a part of.
|
||||
* Which melt commitment is made by the wallet.
|
||||
*/
|
||||
struct GNUNET_HashCode session_hash GNUNET_PACKED;
|
||||
struct TALER_RefreshCommitmentP rc GNUNET_PACKED;
|
||||
|
||||
/**
|
||||
* How much of the value of the coin should be melted? This amount
|
||||
@ -581,20 +581,16 @@ struct TALER_RefreshMeltConfirmationPS
|
||||
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
|
||||
|
||||
/**
|
||||
* Hash of the refresh session.
|
||||
* Commitment made in the /refresh/melt.
|
||||
*/
|
||||
struct GNUNET_HashCode session_hash GNUNET_PACKED;
|
||||
struct TALER_RefreshCommitmentP rc GNUNET_PACKED;
|
||||
|
||||
/**
|
||||
* Index that the client will not have to reveal, in NBO.
|
||||
* Must be smaller than #TALER_CNC_KAPPA.
|
||||
*/
|
||||
uint16_t noreveal_index GNUNET_PACKED;
|
||||
uint32_t noreveal_index GNUNET_PACKED;
|
||||
|
||||
/**
|
||||
* Zero.
|
||||
*/
|
||||
uint16_t reserved GNUNET_PACKED;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014, 2015 GNUnet e.V.
|
||||
Copyright (C) 2014-2017 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
@ -206,7 +206,7 @@ patch_private_key (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
|
||||
*/
|
||||
void
|
||||
TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed,
|
||||
unsigned int coin_num_salt,
|
||||
uint32_t coin_num_salt,
|
||||
struct TALER_PlanchetSecretsP *ps)
|
||||
{
|
||||
uint32_t be_salt = htonl (coin_num_salt);
|
||||
@ -314,4 +314,87 @@ TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk,
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute the commitment for a /refresh/melt operation from
|
||||
* the respective public inputs.
|
||||
*
|
||||
* @param[out] rc set to the value the wallet must commit to
|
||||
* @param kappa number of transfer public keys involved (must be #TALER_CNC_KAPPA)
|
||||
* @param num_new_coins number of new coins to be created
|
||||
* @param commitments array of @a kappa commitments
|
||||
* @param coin_pub public key of the coin to be melted
|
||||
* @param amount_with_fee amount to be melted, including fee
|
||||
*/
|
||||
void
|
||||
TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc,
|
||||
uint32_t kappa,
|
||||
uint32_t num_new_coins,
|
||||
const struct TALER_RefreshCommitmentEntry *rcs,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_Amount *amount_with_fee)
|
||||
{
|
||||
struct GNUNET_HashContext *hash_context;
|
||||
|
||||
hash_context = GNUNET_CRYPTO_hash_context_start ();
|
||||
/* first, iterate over transfer public keys for hash_context */
|
||||
for (unsigned int i=0;i<kappa;i++)
|
||||
{
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
&rcs[i].transfer_pub,
|
||||
sizeof (struct TALER_TransferPublicKeyP));
|
||||
}
|
||||
/* next, add all of the hashes from the denomination keys to the
|
||||
hash_context */
|
||||
for (unsigned int i=0;i<num_new_coins;i++)
|
||||
{
|
||||
char *buf;
|
||||
size_t buf_size;
|
||||
|
||||
/* The denomination keys should / must all be identical regardless
|
||||
of what offset we use, so we use [0]. */
|
||||
GNUNET_assert (kappa > 0); /* sanity check */
|
||||
buf_size = GNUNET_CRYPTO_rsa_public_key_encode (rcs[0].new_coins[i].dk->rsa_public_key,
|
||||
&buf);
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
buf,
|
||||
buf_size);
|
||||
GNUNET_free (buf);
|
||||
}
|
||||
|
||||
/* next, add public key of coin and amount being refreshed */
|
||||
{
|
||||
struct TALER_AmountNBO melt_amountn;
|
||||
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
coin_pub,
|
||||
sizeof (struct TALER_CoinSpendPublicKeyP));
|
||||
TALER_amount_hton (&melt_amountn,
|
||||
amount_with_fee);
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
&melt_amountn,
|
||||
sizeof (struct TALER_AmountNBO));
|
||||
}
|
||||
|
||||
/* finally, add all the envelopes */
|
||||
for (unsigned int i=0;i<kappa;i++)
|
||||
{
|
||||
const struct TALER_RefreshCommitmentEntry *rce = &rcs[i];
|
||||
|
||||
for (unsigned int j=0;j<num_new_coins;j++)
|
||||
{
|
||||
const struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
|
||||
|
||||
GNUNET_CRYPTO_hash_context_read (hash_context,
|
||||
rcd->coin_ev,
|
||||
rcd->coin_ev_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Conclude */
|
||||
GNUNET_CRYPTO_hash_context_finish (hash_context,
|
||||
&rc->session_hash);
|
||||
}
|
||||
|
||||
|
||||
/* end of crypto.c */
|
||||
|
Loading…
Reference in New Issue
Block a user