Merge branch 'master' of ssh://git.taler.net/exchange
This commit is contained in:
commit
f46dc9ea5e
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 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
|
||||
@ -1063,9 +1063,15 @@ struct TALER_EXCHANGE_CsRResponse
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* Signature over the coin.
|
||||
* Length of the @e alg_values array.
|
||||
*/
|
||||
struct TALER_DenominationCsPublicR r_pubs;
|
||||
unsigned int arg_values_len;
|
||||
|
||||
/**
|
||||
* Values contributed by the exchange for the
|
||||
* respective coin's withdraw operation.
|
||||
*/
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values;
|
||||
} success;
|
||||
|
||||
/**
|
||||
@ -1092,12 +1098,29 @@ typedef void
|
||||
const struct TALER_EXCHANGE_CsRResponse *csrr);
|
||||
|
||||
|
||||
/**
|
||||
* Information we pass per coin to a /csr request.
|
||||
*/
|
||||
struct TALER_EXCHANGE_NonceKey
|
||||
{
|
||||
/**
|
||||
* Which denomination key is the /csr request for?
|
||||
*/
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk;
|
||||
|
||||
/**
|
||||
* What is the client nonce for the request?
|
||||
*/
|
||||
struct TALER_CsNonce nonce;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a CS R using a /csr request.
|
||||
*
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param pk denomination of coin the R's will be used for
|
||||
* @param nonce public nonce for CS R request
|
||||
* @param nks_len length of the @a nks array
|
||||
* @param nks array of denominations and nonces
|
||||
* @param res_cb the callback to call when the final result for this request is available
|
||||
* @param res_cb_cls closure for the above callback
|
||||
* @return handle for the operation on success, NULL on error, i.e.
|
||||
@ -1106,8 +1129,8 @@ typedef void
|
||||
*/
|
||||
struct TALER_EXCHANGE_CsRHandle *
|
||||
TALER_EXCHANGE_csr (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk,
|
||||
const struct TALER_CsNonce *nonce,
|
||||
unsigned int nks_len,
|
||||
struct TALER_EXCHANGE_NonceKey *nks,
|
||||
TALER_EXCHANGE_CsRCallback res_cb,
|
||||
void *res_cb_cls);
|
||||
|
||||
@ -1383,10 +1406,21 @@ struct TALER_EXCHANGE_WithdrawResponse
|
||||
*/
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* Private key of the coin.
|
||||
*/
|
||||
struct TALER_CoinSpendPrivateKeyP coin_priv;
|
||||
|
||||
/**
|
||||
* Signature over the coin.
|
||||
*/
|
||||
struct TALER_DenominationSignature sig;
|
||||
|
||||
/**
|
||||
* Values contributed from the exchange during the
|
||||
* withdraw protocol.
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues exchange_vals;
|
||||
} success;
|
||||
|
||||
/**
|
||||
@ -1541,50 +1575,45 @@ TALER_EXCHANGE_withdraw2_cancel (struct TALER_EXCHANGE_Withdraw2Handle *wh);
|
||||
|
||||
|
||||
/**
|
||||
* Melt (partially spent) coins to obtain fresh coins that are
|
||||
* unlinkable to the original coin(s). Note that melting more
|
||||
* than one coin in a single request will make those coins linkable,
|
||||
* so the safest operation only melts one coin at a time.
|
||||
*
|
||||
* This API is typically used by a wallet. Note that to ensure that
|
||||
* no money is lost in case of hardware failures, is operation does
|
||||
* not actually initiate the request. Instead, it generates a buffer
|
||||
* which the caller must store before proceeding with the actual call
|
||||
* to #TALER_EXCHANGE_melt() that will generate the request.
|
||||
*
|
||||
* This function does verify that the given request data is internally
|
||||
* consistent. However, the @a melts_sigs are NOT verified.
|
||||
*
|
||||
* Aside from some non-trivial cryptographic operations that might
|
||||
* take a bit of CPU time to complete, this function returns
|
||||
* its result immediately and does not start any asynchronous
|
||||
* processing. This function is also thread-safe.
|
||||
*
|
||||
* @param melt_priv private keys of the coin to melt
|
||||
* @param melt_amount amount specifying how much
|
||||
* the coin will contribute to the melt (including fee)
|
||||
* @param melt_sig signatures affirming the
|
||||
* validity of the public keys corresponding to the
|
||||
* @a melt_priv private key
|
||||
* @param melt_pk denomination key information
|
||||
* record corresponding to the @a melt_sig
|
||||
* validity of the keys
|
||||
* @param fresh_pks_len length of the @a pks array
|
||||
* @param fresh_pks array of @a pks_len denominations of fresh coins to create
|
||||
* @return NULL
|
||||
* if the inputs are invalid (i.e. denomination key not with this exchange).
|
||||
* Otherwise, JSON data structure to store persistently
|
||||
* before proceeding to #TALER_EXCHANGE_melt().
|
||||
* Non-null results should be freed using GNUNET_free().
|
||||
* Information needed to melt (partially spent) coins to obtain fresh coins
|
||||
* that are unlinkable to the original coin(s). Note that melting more than
|
||||
* one coin in a single request will make those coins linkable, so we only melt one coin at a time.
|
||||
*/
|
||||
json_t *
|
||||
TALER_EXCHANGE_refresh_prepare (
|
||||
const struct TALER_CoinSpendPrivateKeyP *melt_priv,
|
||||
const struct TALER_Amount *melt_amount,
|
||||
const struct TALER_DenominationSignature *melt_sig,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
|
||||
unsigned int fresh_pks_len,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks);
|
||||
struct TALER_EXCHANGE_RefreshData
|
||||
{
|
||||
/**
|
||||
* private key of the coin to melt
|
||||
*/
|
||||
struct TALER_CoinSpendPrivateKeyP melt_priv;
|
||||
|
||||
/**
|
||||
* amount specifying how much the coin will contribute to the melt
|
||||
* (including fee)
|
||||
*/
|
||||
struct TALER_Amount melt_amount;
|
||||
|
||||
/**
|
||||
* signatures affirming the validity of the public keys corresponding to the
|
||||
* @e melt_priv private key
|
||||
*/
|
||||
struct TALER_DenominationSignature melt_sig;
|
||||
|
||||
/**
|
||||
* denomination key information record corresponding to the @e melt_sig
|
||||
* validity of the keys
|
||||
*/
|
||||
struct TALER_EXCHANGE_DenomPublicKey melt_pk;
|
||||
|
||||
/**
|
||||
* array of @e pks_len denominations of fresh coins to create
|
||||
*/
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
|
||||
|
||||
/**
|
||||
* length of the @e pks array
|
||||
*/
|
||||
unsigned int fresh_pks_len;
|
||||
};
|
||||
|
||||
|
||||
/* ********************* /coins/$COIN_PUB/melt ***************************** */
|
||||
@ -1603,6 +1632,8 @@ struct TALER_EXCHANGE_MeltHandle;
|
||||
*
|
||||
* @param cls closure
|
||||
* @param hr HTTP response data
|
||||
* @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, 0 if the operation failed
|
||||
* @param alg_values array @a num_coins of exchange values contributed to the refresh operation
|
||||
* @param noreveal_index choice by the exchange in the cut-and-choose protocol,
|
||||
* UINT32_MAX on error
|
||||
* @param sign_key exchange key used to sign @a full_response, or NULL
|
||||
@ -1611,6 +1642,8 @@ typedef void
|
||||
(*TALER_EXCHANGE_MeltCallback) (
|
||||
void *cls,
|
||||
const struct TALER_EXCHANGE_HttpResponse *hr,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
uint32_t noreveal_index,
|
||||
const struct TALER_ExchangePublicKeyP *sign_key);
|
||||
|
||||
@ -1626,8 +1659,8 @@ typedef void
|
||||
* prior to calling this function.
|
||||
*
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param refresh_data the refresh data as returned from
|
||||
#TALER_EXCHANGE_refresh_prepare())
|
||||
* @param ps the fresh secret that defines the refresh operation
|
||||
* @param rd the refresh data specifying the characteristics of the operation
|
||||
* @param melt_cb the callback to call with the result
|
||||
* @param melt_cb_cls closure for @a melt_cb
|
||||
* @return a handle for this request; NULL if the argument was invalid.
|
||||
@ -1635,7 +1668,8 @@ typedef void
|
||||
*/
|
||||
struct TALER_EXCHANGE_MeltHandle *
|
||||
TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const json_t *refresh_data,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
TALER_EXCHANGE_MeltCallback melt_cb,
|
||||
void *melt_cb_cls);
|
||||
|
||||
@ -1664,6 +1698,7 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh);
|
||||
* @param cls closure
|
||||
* @param hr HTTP response data
|
||||
* @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed
|
||||
* @param exchange_vals array of contributions from the exchange on the refreshes
|
||||
* @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error
|
||||
* @param sigs array of signature over @a num_coins coins, NULL on error
|
||||
*/
|
||||
@ -1672,7 +1707,7 @@ typedef void
|
||||
void *cls,
|
||||
const struct TALER_EXCHANGE_HttpResponse *hr,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_PlanchetSecretsP *coin_privs,
|
||||
const struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
const struct TALER_DenominationSignature *sigs);
|
||||
|
||||
|
||||
@ -1692,8 +1727,10 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
|
||||
* prior to calling this function.
|
||||
*
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param refresh_data the refresh data as returned from
|
||||
#TALER_EXCHANGE_refresh_prepare())
|
||||
* @param ps the fresh secret that defines the refresh operation
|
||||
* @param rd the refresh data that characterizes the refresh operation
|
||||
* @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, must match value in @a rd
|
||||
* @param alg_values array @a num_coins of exchange values contributed to the refresh operation
|
||||
* @param noreveal_index response from the exchange to the
|
||||
* #TALER_EXCHANGE_melt() invocation
|
||||
* @param reveal_cb the callback to call with the final result of the
|
||||
@ -1705,7 +1742,10 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
|
||||
struct TALER_EXCHANGE_RefreshesRevealHandle *
|
||||
TALER_EXCHANGE_refreshes_reveal (
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const json_t *refresh_data,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
uint32_t noreveal_index,
|
||||
TALER_EXCHANGE_RefreshesRevealCallback reveal_cb,
|
||||
void *reveal_cb_cls);
|
||||
@ -2124,6 +2164,7 @@ typedef void
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param pk kind of coin to pay back
|
||||
* @param denom_sig signature over the coin by the exchange using @a pk
|
||||
* @param exchange_vals contribution from the exchange on the withdraw
|
||||
* @param ps secret internals of the original planchet
|
||||
* @param recoup_cb the callback to call when the final result for this request is available
|
||||
* @param recoup_cb_cls closure for @a recoup_cb
|
||||
@ -2135,6 +2176,7 @@ struct TALER_EXCHANGE_RecoupHandle *
|
||||
TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk,
|
||||
const struct TALER_DenominationSignature *denom_sig,
|
||||
const struct TALER_ExchangeWithdrawValues *exchange_vals,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
TALER_EXCHANGE_RecoupResultCallback recoup_cb,
|
||||
void *recoup_cb_cls);
|
||||
@ -2184,7 +2226,8 @@ typedef void
|
||||
* @param exchange the exchange handle; the exchange must be ready to operate
|
||||
* @param pk kind of coin to pay back
|
||||
* @param denom_sig signature over the coin by the exchange using @a pk
|
||||
* @param ps secret internals of the original planchet
|
||||
* @param exchange_vals contribution from the exchange on the withdraw
|
||||
* @param ps secret internals of the original refresh-reveal operation
|
||||
* @param recoup_cb the callback to call when the final result for this request is available
|
||||
* @param recoup_cb_cls closure for @a recoup_cb
|
||||
* @return NULL
|
||||
@ -2196,6 +2239,7 @@ TALER_EXCHANGE_recoup_refresh (
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *pk,
|
||||
const struct TALER_DenominationSignature *denom_sig,
|
||||
const struct TALER_ExchangeWithdrawValues *exchange_vals,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb,
|
||||
void *recoup_cb_cls);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2015-2021 Taler Systems SA
|
||||
Copyright (C) 2015-2022 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
|
||||
@ -73,7 +73,23 @@ struct TALER_EXCHANGE_MeltHandle
|
||||
/**
|
||||
* Actual information about the melt operation.
|
||||
*/
|
||||
struct MeltData *md;
|
||||
struct MeltData md;
|
||||
|
||||
/**
|
||||
* The secret the entire melt operation is seeded from.
|
||||
*/
|
||||
const struct TALER_PlanchetSecretsP *ps;
|
||||
|
||||
/**
|
||||
* Details about the characteristics of the requested melt operation.
|
||||
*/
|
||||
const struct TALER_EXCHANGE_RefreshData *rd;
|
||||
|
||||
/**
|
||||
* Array of `num_fresh_coins` contributory values of
|
||||
* the exchange to the melt operation.
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues *alg_values;
|
||||
|
||||
/**
|
||||
* Public key of the coin being melted.
|
||||
@ -106,9 +122,12 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh,
|
||||
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_uint32 ("noreveal_index", noreveal_index),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
|
||||
&exchange_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
|
||||
exchange_pub),
|
||||
GNUNET_JSON_spec_uint32 ("noreveal_index",
|
||||
noreveal_index),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
struct TALER_RefreshMeltConfirmationPS confirm;
|
||||
@ -338,6 +357,12 @@ handle_melt_finished (void *cls,
|
||||
{
|
||||
mh->melt_cb (mh->melt_cb_cls,
|
||||
&hr,
|
||||
(0 == hr.http_status)
|
||||
? 0
|
||||
: mh->rd->fresh_pks_len,
|
||||
(0 == hr.http_status)
|
||||
? NULL
|
||||
: mh->alg_values,
|
||||
noreveal_index,
|
||||
(0 == hr.http_status)
|
||||
? NULL
|
||||
@ -419,40 +444,37 @@ handle_melt_finished (void *cls,
|
||||
if (NULL != mh->melt_cb)
|
||||
mh->melt_cb (mh->melt_cb_cls,
|
||||
&hr,
|
||||
0,
|
||||
NULL,
|
||||
UINT32_MAX,
|
||||
NULL);
|
||||
TALER_EXCHANGE_melt_cancel (mh);
|
||||
}
|
||||
|
||||
|
||||
struct TALER_EXCHANGE_MeltHandle *
|
||||
TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const json_t *refresh_data,
|
||||
TALER_EXCHANGE_MeltCallback melt_cb,
|
||||
void *melt_cb_cls)
|
||||
static enum GNUNET_GenericReturnValue
|
||||
start_melt (struct TALER_EXCHANGE_MeltHandle *mh)
|
||||
{
|
||||
const struct TALER_EXCHANGE_Keys *key_state;
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *dki;
|
||||
json_t *melt_obj;
|
||||
struct TALER_EXCHANGE_MeltHandle *mh;
|
||||
CURL *eh;
|
||||
struct GNUNET_CURL_Context *ctx;
|
||||
struct MeltData *md;
|
||||
struct TALER_CoinSpendSignatureP confirm_sig;
|
||||
char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
|
||||
struct TALER_DenominationHash h_denom_pub;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TEAH_handle_is_ready (exchange));
|
||||
md = TALER_EXCHANGE_deserialize_melt_data_ (refresh_data,
|
||||
exchange->key_data.currency);
|
||||
if (NULL == md)
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGE_get_melt_data_ (mh->ps,
|
||||
mh->rd,
|
||||
mh->alg_values,
|
||||
&mh->md))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TALER_denom_pub_hash (&md->melted_coin.pub_key,
|
||||
TALER_denom_pub_hash (&mh->md.melted_coin.pub_key,
|
||||
&h_denom_pub);
|
||||
TALER_wallet_melt_sign (&md->melted_coin.melt_amount_with_fee,
|
||||
&md->melted_coin.fee_melt,
|
||||
@ -489,29 +511,19 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
pub_str);
|
||||
}
|
||||
|
||||
key_state = TALER_EXCHANGE_get_keys (exchange);
|
||||
ctx = TEAH_handle_to_context (mh->exchange);
|
||||
key_state = TALER_EXCHANGE_get_keys (mh->exchange);
|
||||
dki = TALER_EXCHANGE_get_denomination_key (key_state,
|
||||
&md->melted_coin.pub_key);
|
||||
&mh->md.melted_coin.pub_key);
|
||||
|
||||
/* and now we can at last begin the actual request handling */
|
||||
mh = GNUNET_new (struct TALER_EXCHANGE_MeltHandle);
|
||||
mh->exchange = exchange;
|
||||
mh->coin_pub = coin_pub;
|
||||
mh->dki = *dki;
|
||||
memset (&mh->dki.key,
|
||||
0,
|
||||
sizeof (mh->dki.key)); /* lifetime not warranted, so better
|
||||
not copy the pointers */
|
||||
mh->melt_cb = melt_cb;
|
||||
mh->melt_cb_cls = melt_cb_cls;
|
||||
mh->md = md;
|
||||
mh->url = TEAH_path_to_url (exchange,
|
||||
|
||||
mh->url = TEAH_path_to_url (mh->exchange,
|
||||
arg_str);
|
||||
if (NULL == mh->url)
|
||||
{
|
||||
json_decref (melt_obj);
|
||||
GNUNET_free (mh);
|
||||
return NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
eh = TALER_EXCHANGE_curl_easy_get_ (mh->url);
|
||||
if ( (NULL == eh) ||
|
||||
@ -524,17 +536,154 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
if (NULL != eh)
|
||||
curl_easy_cleanup (eh);
|
||||
json_decref (melt_obj);
|
||||
GNUNET_free (mh->url);
|
||||
GNUNET_free (mh);
|
||||
return NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
json_decref (melt_obj);
|
||||
ctx = TEAH_handle_to_context (exchange);
|
||||
mh->job = GNUNET_CURL_job_add2 (ctx,
|
||||
eh,
|
||||
mh->ctx.headers,
|
||||
&handle_melt_finished,
|
||||
mh);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fail_mh (struct TALER_EXCHANGE_MeltHandle *mh)
|
||||
{
|
||||
// FIXME: do return more than NULLs if
|
||||
// the /csr failed!
|
||||
mh->melt_cb (mh->melt_cb_cls,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
UINT32_MAX,
|
||||
NULL);
|
||||
TALER_EXCHANGE_melt_cancel (mh);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callbacks of this type are used to serve the result of submitting a
|
||||
* CS R request to a exchange.
|
||||
*
|
||||
* @param cls closure with our `struct TALER_EXCHANGE_MeltHandle *`
|
||||
* @param csrr response details
|
||||
*/
|
||||
static void
|
||||
csr_cb (void *cls,
|
||||
const struct TALER_EXCHANGE_CsRResponse *csrr)
|
||||
{
|
||||
struct TALER_EXCHANGE_MeltHandle *mh = cls;
|
||||
unsigned int nks_off = 0;
|
||||
|
||||
for (unsigned int i = 0; i<rd->fresh_pks_len; i++)
|
||||
{
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = &rd->fresh_pks[i];
|
||||
struct TALER_ExchangeWithdrawValues *wv = &mh->alg_values[i];
|
||||
|
||||
switch (fresh_pk->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
GNUNET_break (0);
|
||||
fail_mh (mh).
|
||||
return;
|
||||
case TALER_DENOMINATION_RSA:
|
||||
GNUNET_assert (TALER_DENOMINATION_RSA == wv->cipher);
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
GNUNET_assert (TALER_DENOMINATION_CS == wv->cipher);
|
||||
*wv = csrr->details.success.alg_values[nks_off];
|
||||
nks_off++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
start_melt (mh))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
fail_mh (mh);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct TALER_EXCHANGE_MeltHandle *
|
||||
TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
TALER_EXCHANGE_MeltCallback melt_cb,
|
||||
void *melt_cb_cls)
|
||||
s
|
||||
{
|
||||
const struct TALER_EXCHANGE_NonceKey *nks[GNUNET_NZL (rd->refresh_pks_len)];
|
||||
unsigned int nks_off = 0;
|
||||
|
||||
if (0 == rd->refresh_pks_len)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_assert (GNUNET_YES ==
|
||||
TEAH_handle_is_ready (exchange));
|
||||
mh = GNUNET_new (struct TALER_EXCHANGE_MeltHandle);
|
||||
mh->exchange = exchange;
|
||||
mh->rd = rd;
|
||||
mh->ps = ps;
|
||||
mh->melt_cb = melt_cb;
|
||||
mh->melt_cb_cls = melt_cb_cls;
|
||||
mh->alg_values = GNUNET_new_array (struct TALER_ExchangeWithdrawValues,
|
||||
rd->fresh_pks_len);
|
||||
for (unsigned int i = 0; i<rd->fresh_pks_len; i++)
|
||||
{
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = &rd->fresh_pks[i];
|
||||
struct TALER_ExchangeWithdrawValues *wv = &mh->alg_values[i];
|
||||
|
||||
switch (fresh_pk->cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_INVALID:
|
||||
GNUNET_break (0);
|
||||
GNUNET_free (mh->alg_values);
|
||||
GNUNET_free (mh);
|
||||
return NULL;
|
||||
case TALER_DENOMINATION_RSA:
|
||||
wv->cipher = TALER_DENOMINATION_RSA;
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
wv->cipher = TALER_DENOMINATION_CS;
|
||||
nks[nks_off].pk = fresh_pk;
|
||||
// derive nonce for refresh by index and ps;
|
||||
// FIXME: include fresh_pk or not?
|
||||
TALER_CRYPTO_XXX (ps,
|
||||
fresh_pk,
|
||||
i,
|
||||
&nks[nks_off].nonce);
|
||||
nks_off++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 != nks_off)
|
||||
{
|
||||
mh->csr = TALER_EXCHANGE_csr (exchange,
|
||||
nks_off,
|
||||
nks,
|
||||
&csr_cb,
|
||||
mh);
|
||||
if (NULL == mh->csr)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_EXCHANGE_melt_cancel (mh->csr);
|
||||
return NULL;
|
||||
}
|
||||
return mh;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
start_melt (mh))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_EXCHANGE_melt_cancel (mh->csr);
|
||||
return NULL;
|
||||
}
|
||||
return mh;
|
||||
}
|
||||
|
||||
@ -547,8 +696,7 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh)
|
||||
GNUNET_CURL_job_cancel (mh->job);
|
||||
mh->job = NULL;
|
||||
}
|
||||
TALER_EXCHANGE_free_melt_data_ (mh->md); /* does not free 'md' itself */
|
||||
GNUNET_free (mh->md);
|
||||
TALER_EXCHANGE_free_melt_data_ (&mh->md); /* does not free 'md' itself */
|
||||
GNUNET_free (mh->url);
|
||||
TALER_curl_easy_post_finished (&mh->ctx);
|
||||
GNUNET_free (mh);
|
||||
|
@ -23,24 +23,11 @@
|
||||
#include "exchange_api_refresh_common.h"
|
||||
|
||||
|
||||
/**
|
||||
* Free all information associated with a melted coin session.
|
||||
*
|
||||
* @param mc melted coin to release, the pointer itself is NOT
|
||||
* freed (as it is typically not allocated by itself)
|
||||
*/
|
||||
static void
|
||||
free_melted_coin (struct MeltedCoin *mc)
|
||||
{
|
||||
TALER_denom_pub_free (&mc->pub_key);
|
||||
TALER_denom_sig_free (&mc->sig);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TALER_EXCHANGE_free_melt_data_ (struct MeltData *md)
|
||||
{
|
||||
free_melted_coin (&md->melted_coin);
|
||||
TALER_denom_pub_free (&md->melted_coin.pub_key);
|
||||
TALER_denom_sig_free (&md->melted_coin.sig);
|
||||
if (NULL != md->fresh_pks)
|
||||
{
|
||||
for (unsigned int i = 0; i<md->num_fresh_coins; i++)
|
||||
@ -55,296 +42,12 @@ TALER_EXCHANGE_free_melt_data_ (struct MeltData *md)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialize information about a coin we are melting.
|
||||
*
|
||||
* @param mc information to serialize
|
||||
* @return NULL on error
|
||||
*/
|
||||
static json_t *
|
||||
serialize_melted_coin (const struct MeltedCoin *mc)
|
||||
{
|
||||
json_t *tprivs;
|
||||
|
||||
tprivs = json_array ();
|
||||
GNUNET_assert (NULL != tprivs);
|
||||
for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (
|
||||
tprivs,
|
||||
GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto (
|
||||
"transfer_priv",
|
||||
&mc->transfer_priv[i]))));
|
||||
return GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("coin_priv",
|
||||
&mc->coin_priv),
|
||||
TALER_JSON_pack_denom_sig ("denom_sig",
|
||||
&mc->sig),
|
||||
TALER_JSON_pack_denom_pub ("denom_pub",
|
||||
&mc->pub_key),
|
||||
TALER_JSON_pack_amount ("melt_amount_with_fee",
|
||||
&mc->melt_amount_with_fee),
|
||||
TALER_JSON_pack_amount ("original_value",
|
||||
&mc->original_value),
|
||||
TALER_JSON_pack_amount ("melt_fee",
|
||||
&mc->fee_melt),
|
||||
GNUNET_JSON_pack_timestamp ("expire_deposit",
|
||||
mc->expire_deposit),
|
||||
GNUNET_JSON_pack_array_steal ("transfer_privs",
|
||||
tprivs));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserialize information about a coin we are melting.
|
||||
*
|
||||
* @param[out] mc information to deserialize
|
||||
* @param currency expected currency
|
||||
* @param in JSON object to read data from
|
||||
* @return #GNUNET_NO to report errors
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
deserialize_melted_coin (struct MeltedCoin *mc,
|
||||
const char *currency,
|
||||
const json_t *in)
|
||||
{
|
||||
json_t *trans_privs;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("coin_priv",
|
||||
&mc->coin_priv),
|
||||
TALER_JSON_spec_denom_sig ("denom_sig",
|
||||
&mc->sig),
|
||||
TALER_JSON_spec_denom_pub ("denom_pub",
|
||||
&mc->pub_key),
|
||||
TALER_JSON_spec_amount ("melt_amount_with_fee",
|
||||
currency,
|
||||
&mc->melt_amount_with_fee),
|
||||
TALER_JSON_spec_amount ("original_value",
|
||||
currency,
|
||||
&mc->original_value),
|
||||
TALER_JSON_spec_amount ("melt_fee",
|
||||
currency,
|
||||
&mc->fee_melt),
|
||||
GNUNET_JSON_spec_timestamp ("expire_deposit",
|
||||
&mc->expire_deposit),
|
||||
GNUNET_JSON_spec_json ("transfer_privs",
|
||||
&trans_privs),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (in,
|
||||
spec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
if (TALER_CNC_KAPPA != json_array_size (trans_privs))
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
|
||||
{
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("transfer_priv",
|
||||
&mc->transfer_priv[i]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (json_array_get (trans_privs,
|
||||
i),
|
||||
spec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return GNUNET_NO;
|
||||
}
|
||||
}
|
||||
json_decref (trans_privs);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialize melt data.
|
||||
*
|
||||
* @param md data to serialize
|
||||
* @return serialized melt data
|
||||
*/
|
||||
static json_t *
|
||||
serialize_melt_data (const struct MeltData *md)
|
||||
{
|
||||
json_t *fresh_coins;
|
||||
|
||||
fresh_coins = json_array ();
|
||||
GNUNET_assert (NULL != fresh_coins);
|
||||
for (int i = 0; i<md->num_fresh_coins; i++)
|
||||
{
|
||||
json_t *planchet_secrets;
|
||||
|
||||
planchet_secrets = json_array ();
|
||||
GNUNET_assert (NULL != planchet_secrets);
|
||||
for (unsigned int j = 0; j<TALER_CNC_KAPPA; j++)
|
||||
{
|
||||
json_t *ps;
|
||||
|
||||
ps = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("ps",
|
||||
&md->fresh_coins[j][i]));
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (planchet_secrets,
|
||||
ps));
|
||||
}
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (
|
||||
fresh_coins,
|
||||
GNUNET_JSON_PACK (
|
||||
TALER_JSON_pack_denom_pub ("denom_pub",
|
||||
&md->fresh_pks[i]),
|
||||
GNUNET_JSON_pack_array_steal ("planchet_secrets",
|
||||
planchet_secrets)))
|
||||
);
|
||||
}
|
||||
return GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_array_steal ("fresh_coins",
|
||||
fresh_coins),
|
||||
GNUNET_JSON_pack_object_steal ("melted_coin",
|
||||
serialize_melted_coin (&md->melted_coin)),
|
||||
GNUNET_JSON_pack_data_auto ("rc",
|
||||
&md->rc));
|
||||
}
|
||||
|
||||
|
||||
struct MeltData *
|
||||
TALER_EXCHANGE_deserialize_melt_data_ (const json_t *melt_data,
|
||||
const char *currency)
|
||||
{
|
||||
struct MeltData *md = GNUNET_new (struct MeltData);
|
||||
json_t *fresh_coins;
|
||||
json_t *melted_coin;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("rc",
|
||||
&md->rc),
|
||||
GNUNET_JSON_spec_json ("melted_coin",
|
||||
&melted_coin),
|
||||
GNUNET_JSON_spec_json ("fresh_coins",
|
||||
&fresh_coins),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
bool ok;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (melt_data,
|
||||
spec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
GNUNET_free (md);
|
||||
return NULL;
|
||||
}
|
||||
if (! (json_is_array (fresh_coins) &&
|
||||
json_is_object (melted_coin)) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return NULL;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
deserialize_melted_coin (&md->melted_coin,
|
||||
currency,
|
||||
melted_coin))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return NULL;
|
||||
}
|
||||
md->num_fresh_coins = json_array_size (fresh_coins);
|
||||
md->fresh_pks = GNUNET_new_array (md->num_fresh_coins,
|
||||
struct TALER_DenominationPublicKey);
|
||||
for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
|
||||
md->fresh_coins[i] = GNUNET_new_array (md->num_fresh_coins,
|
||||
struct TALER_PlanchetSecretsP);
|
||||
ok = true;
|
||||
for (unsigned int i = 0; i<md->num_fresh_coins; i++)
|
||||
{
|
||||
const json_t *ji = json_array_get (fresh_coins,
|
||||
i);
|
||||
json_t *planchet_secrets;
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_json ("planchet_secrets",
|
||||
&planchet_secrets),
|
||||
TALER_JSON_spec_denom_pub ("denom_pub",
|
||||
&md->fresh_pks[i]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (ji,
|
||||
ispec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
if ( (! json_is_array (planchet_secrets)) ||
|
||||
(TALER_CNC_KAPPA != json_array_size (planchet_secrets)) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ok = false;
|
||||
GNUNET_JSON_parse_free (ispec);
|
||||
break;
|
||||
}
|
||||
for (unsigned int j = 0; j<TALER_CNC_KAPPA; j++)
|
||||
{
|
||||
struct GNUNET_JSON_Specification jspec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("ps",
|
||||
&md->fresh_coins[j][i]),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (json_array_get (planchet_secrets,
|
||||
j),
|
||||
jspec,
|
||||
NULL, NULL))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
json_decref (planchet_secrets);
|
||||
if (! ok)
|
||||
break;
|
||||
}
|
||||
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
if (! ok)
|
||||
{
|
||||
TALER_EXCHANGE_free_melt_data_ (md);
|
||||
GNUNET_free (md);
|
||||
return NULL;
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
|
||||
json_t *
|
||||
TALER_EXCHANGE_refresh_prepare (
|
||||
const struct TALER_CoinSpendPrivateKeyP *melt_priv,
|
||||
const struct TALER_Amount *melt_amount,
|
||||
const struct TALER_DenominationSignature *melt_sig,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
|
||||
unsigned int fresh_pks_len,
|
||||
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks)
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_EXCHANGE_get_melt_data_ (
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct struct TALER_EXCHANGE_RefreshData *rd,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
struct MeltData *md)
|
||||
{
|
||||
struct MeltData md;
|
||||
json_t *ret;
|
||||
@ -359,68 +62,68 @@ TALER_EXCHANGE_refresh_prepare (
|
||||
memset (&md,
|
||||
0,
|
||||
sizeof (md));
|
||||
md.num_fresh_coins = fresh_pks_len;
|
||||
md.melted_coin.coin_priv = *melt_priv;
|
||||
md.melted_coin.melt_amount_with_fee = *melt_amount;
|
||||
md.melted_coin.fee_melt = melt_pk->fee_refresh;
|
||||
md.melted_coin.original_value = melt_pk->value;
|
||||
md.melted_coin.expire_deposit
|
||||
= melt_pk->expire_deposit;
|
||||
md.num_fresh_coins = rd->fresh_pks_len;
|
||||
md.melted_coin.coin_priv = rd->melt_priv;
|
||||
md.melted_coin.melt_amount_with_fee = rd->melt_amount;
|
||||
md.melted_coin.fee_melt = rd->melt_pk->fee_refresh;
|
||||
md.melted_coin.original_value = rd->melt_pk->value;
|
||||
md.melted_coin.expire_deposit = rd->melt_pk->expire_deposit;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_set_zero (melt_amount->currency,
|
||||
&total));
|
||||
TALER_denom_pub_deep_copy (&md.melted_coin.pub_key,
|
||||
&melt_pk->key);
|
||||
&rd->melt_pk->key);
|
||||
TALER_denom_sig_deep_copy (&md.melted_coin.sig,
|
||||
melt_sig);
|
||||
md.fresh_pks = GNUNET_new_array (fresh_pks_len,
|
||||
rd->melt_sig);
|
||||
md.fresh_pks = GNUNET_new_array (rd->fresh_pks_len,
|
||||
struct TALER_DenominationPublicKey);
|
||||
for (unsigned int i = 0; i<fresh_pks_len; i++)
|
||||
for (unsigned int i = 0; i<rd->fresh_pks_len; i++)
|
||||
{
|
||||
TALER_denom_pub_deep_copy (&md.fresh_pks[i],
|
||||
&fresh_pks[i].key);
|
||||
if ( (0 >
|
||||
TALER_amount_add (&total,
|
||||
&total,
|
||||
&fresh_pks[i].value)) ||
|
||||
&rd->fresh_pks[i].value)) ||
|
||||
(0 >
|
||||
TALER_amount_add (&total,
|
||||
&total,
|
||||
&fresh_pks[i].fee_withdraw)) )
|
||||
&rd->fresh_pks[i].fee_withdraw)) )
|
||||
{
|
||||
GNUNET_break (0);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
return NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
/* verify that melt_amount is above total cost */
|
||||
if (1 ==
|
||||
TALER_amount_cmp (&total,
|
||||
melt_amount) )
|
||||
rd->melt_amount) )
|
||||
{
|
||||
/* Eh, this operation is more expensive than the
|
||||
@a melt_amount. This is not OK. */
|
||||
GNUNET_break (0);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
return NULL;
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
/* build up coins */
|
||||
for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
|
||||
{
|
||||
// FIXME: derive!
|
||||
GNUNET_CRYPTO_ecdhe_key_create (
|
||||
&md.melted_coin.transfer_priv[i].ecdhe_priv);
|
||||
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,
|
||||
TALER_link_derive_transfer_secret (&rd->melt_priv,
|
||||
&md.melted_coin.transfer_priv[i],
|
||||
&trans_sec[i]);
|
||||
md.fresh_coins[i] = GNUNET_new_array (rd->fresh_pks_len,
|
||||
struct TALER_PlanchetSecretsP);
|
||||
rce[i].new_coins = GNUNET_new_array (fresh_pks_len,
|
||||
rce[i].new_coins = GNUNET_new_array (rd->fresh_pks_len,
|
||||
struct TALER_RefreshCoinData);
|
||||
for (unsigned int j = 0; j<fresh_pks_len; j++)
|
||||
for (unsigned int j = 0; j<rd->fresh_pks_len; j++)
|
||||
{
|
||||
struct TALER_PlanchetSecretsP *fc = &md.fresh_coins[i][j];
|
||||
struct TALER_RefreshCoinData *rcd = &rce[i].new_coins[j];
|
||||
@ -458,15 +161,12 @@ TALER_EXCHANGE_refresh_prepare (
|
||||
fresh_pks_len,
|
||||
rce,
|
||||
&coin_pub,
|
||||
melt_amount);
|
||||
/* finally, serialize everything */
|
||||
ret = serialize_melt_data (&md);
|
||||
&rd->melt_amount);
|
||||
for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < fresh_pks_len; j++)
|
||||
GNUNET_free (rce[i].new_coins[j].coin_ev);
|
||||
GNUNET_free (rce[i].new_coins);
|
||||
}
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
return ret;
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2015-2020 Taler Systems SA
|
||||
Copyright (C) 2015-2022 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
|
||||
@ -102,6 +102,12 @@ struct MeltData
|
||||
*/
|
||||
struct TALER_DenominationPublicKey *fresh_pks;
|
||||
|
||||
/**
|
||||
* Array of @e num_fresh_coins with exchange contributions
|
||||
* made during the refresh.
|
||||
*/
|
||||
struct TALER_ExchangeWithdrawValues *exchange_vals;
|
||||
|
||||
/**
|
||||
* Arrays of @e num_fresh_coins with information about the fresh
|
||||
* coins to be created, for each cut-and-choose dimension.
|
||||
@ -111,15 +117,19 @@ struct MeltData
|
||||
|
||||
|
||||
/**
|
||||
* Deserialize melt data.
|
||||
* Compute the melt data from the refresh data and secret.
|
||||
*
|
||||
* @param data json data to deserialize
|
||||
* @param currency expected currency for the coins
|
||||
* @return deserialized melt data, NULL on error
|
||||
* @param ps secret internals of the refresh-reveal operation
|
||||
* @param rd refresh data with the characteristics of the operation
|
||||
* @param alg_values contributions from the exchange into the melt
|
||||
* @param[out] rd where to write the derived melt data
|
||||
*/
|
||||
struct MeltData *
|
||||
TALER_EXCHANGE_deserialize_melt_data_ (const json_t *data,
|
||||
const char *currency);
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_EXCHANGE_get_melt_data_ (
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct struct TALER_EXCHANGE_RefreshData *rd,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
struct MeltData *md);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -73,7 +73,7 @@ struct TALER_EXCHANGE_RefreshesRevealHandle
|
||||
/**
|
||||
* Actual information about the melt operation.
|
||||
*/
|
||||
struct MeltData *md;
|
||||
struct MeltData md;
|
||||
|
||||
/**
|
||||
* The index selected by the exchange in cut-and-choose to not be revealed.
|
||||
@ -95,12 +95,14 @@ struct TALER_EXCHANGE_RefreshesRevealHandle
|
||||
*
|
||||
* @param rrh operation handle
|
||||
* @param json reply from the exchange
|
||||
* @param[out] sigs array of length `num_fresh_coins`, initialized to contain RSA signatures
|
||||
* @param[out] sigs array of length `num_fresh_coins`, initialized to contain the coin private keys
|
||||
* @param[out] sigs array of length `num_fresh_coins`, initialized to contain signatures
|
||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
|
||||
const json_t *json,
|
||||
struct TALER_CoinSpendPrivateKeyP *coin_privs,
|
||||
struct TALER_DenominationSignature *sigs)
|
||||
{
|
||||
json_t *jsona;
|
||||
@ -165,6 +167,7 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
|
||||
|
||||
/* needed to verify the signature, and we didn't store it earlier,
|
||||
hence recomputing it here... */
|
||||
coin_privs[i] = fc->coin_priv;
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&fc->coin_priv.eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
/* FIXME-Oec: Age commitment hash. */
|
||||
@ -223,13 +226,15 @@ handle_refresh_reveal_finished (void *cls,
|
||||
case MHD_HTTP_OK:
|
||||
{
|
||||
struct TALER_DenominationSignature sigs[rrh->md->num_fresh_coins];
|
||||
int ret;
|
||||
struct TALER_CoinSpendPrivateKeyP coin_privs[rrh->md->num_fresh_coins];
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
memset (sigs,
|
||||
0,
|
||||
sizeof (sigs));
|
||||
ret = refresh_reveal_ok (rrh,
|
||||
j,
|
||||
coin_privs,
|
||||
sigs);
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
@ -241,7 +246,7 @@ handle_refresh_reveal_finished (void *cls,
|
||||
rrh->reveal_cb (rrh->reveal_cb_cls,
|
||||
&hr,
|
||||
rrh->md->num_fresh_coins,
|
||||
rrh->md->fresh_coins[rrh->noreveal_index],
|
||||
coin_privs,
|
||||
sigs);
|
||||
rrh->reveal_cb = NULL;
|
||||
}
|
||||
@ -298,7 +303,10 @@ handle_refresh_reveal_finished (void *cls,
|
||||
struct TALER_EXCHANGE_RefreshesRevealHandle *
|
||||
TALER_EXCHANGE_refreshes_reveal (
|
||||
struct TALER_EXCHANGE_Handle *exchange,
|
||||
const json_t *refresh_data,
|
||||
const struct TALER_PlanchetSecretsP *ps,
|
||||
const struct TALER_EXCHANGE_RefreshData *rd,
|
||||
unsigned int num_coins,
|
||||
const struct TALER_ExchangeWithdrawValues *alg_values,
|
||||
uint32_t noreveal_index,
|
||||
TALER_EXCHANGE_RefreshesRevealCallback reveal_cb,
|
||||
void *reveal_cb_cls)
|
||||
@ -311,10 +319,11 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
json_t *link_sigs;
|
||||
CURL *eh;
|
||||
struct GNUNET_CURL_Context *ctx;
|
||||
struct MeltData *md;
|
||||
struct MeltData md;
|
||||
struct TALER_TransferPublicKeyP transfer_pub;
|
||||
char arg_str[sizeof (struct TALER_RefreshCommitmentP) * 2 + 32];
|
||||
|
||||
GNUNET_assert (num_coins == rd->fresh_pks_len);
|
||||
if (noreveal_index >= TALER_CNC_KAPPA)
|
||||
{
|
||||
/* We check this here, as it would be really bad to below just
|
||||
@ -330,9 +339,11 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
}
|
||||
md = TALER_EXCHANGE_deserialize_melt_data_ (refresh_data,
|
||||
exchange->key_data.currency);
|
||||
if (NULL == md)
|
||||
if (GNUNET_OK !=
|
||||
TALER_EXCHANGE_get_melt_data_ (ps,
|
||||
rd,
|
||||
alg_values,
|
||||
&md))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return NULL;
|
||||
@ -340,33 +351,31 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
|
||||
/* now transfer_pub */
|
||||
GNUNET_CRYPTO_ecdhe_key_get_public (
|
||||
&md->melted_coin.transfer_priv[noreveal_index].ecdhe_priv,
|
||||
&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 ()));
|
||||
GNUNET_assert (NULL != (link_sigs = json_array ()));
|
||||
for (unsigned int i = 0; i<md->num_fresh_coins; i++)
|
||||
for (unsigned int i = 0; i<md.num_fresh_coins; i++)
|
||||
{
|
||||
struct TALER_DenominationHash denom_hash;
|
||||
struct TALER_ExchangeWithdrawValues alg_values;
|
||||
struct TALER_PlanchetDetail pd;
|
||||
struct TALER_CoinPubHash c_hash;
|
||||
|
||||
TALER_denom_pub_hash (&md->fresh_pks[i],
|
||||
TALER_denom_pub_hash (&md.fresh_pks[i],
|
||||
&denom_hash);
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (new_denoms_h,
|
||||
GNUNET_JSON_from_data_auto (
|
||||
&denom_hash)));
|
||||
|
||||
// TODO: implement cipher handling
|
||||
alg_values.cipher = TALER_DENOMINATION_RSA;
|
||||
if (GNUNET_OK !=
|
||||
TALER_planchet_prepare (&md->fresh_pks[i],
|
||||
&alg_values,
|
||||
&md->fresh_coins[noreveal_index][i],
|
||||
TALER_planchet_prepare (&md.fresh_pks[i],
|
||||
&rrh->exchange_vals[i],
|
||||
&md.fresh_coins[noreveal_index][i],
|
||||
&c_hash,
|
||||
&pd))
|
||||
{
|
||||
@ -374,6 +383,7 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
GNUNET_break (0);
|
||||
json_decref (new_denoms_h);
|
||||
json_decref (coin_evs);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
return NULL;
|
||||
}
|
||||
GNUNET_assert (0 ==
|
||||
@ -394,7 +404,7 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
blinded_msg,
|
||||
pd.blinded_planchet.details.rsa_blinded_planchet.
|
||||
blinded_msg_size,
|
||||
&md->melted_coin.coin_priv,
|
||||
&md.melted_coin.coin_priv,
|
||||
&link_sig);
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (
|
||||
@ -417,7 +427,7 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
GNUNET_assert (0 ==
|
||||
json_array_append_new (transfer_privs,
|
||||
GNUNET_JSON_from_data_auto (
|
||||
&md->melted_coin.transfer_priv[j])));
|
||||
&md.melted_coin.transfer_priv[j])));
|
||||
}
|
||||
|
||||
/* build main JSON request */
|
||||
@ -436,9 +446,8 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
char pub_str[sizeof (struct TALER_RefreshCommitmentP) * 2];
|
||||
char *end;
|
||||
|
||||
end = GNUNET_STRINGS_data_to_string (&md->rc,
|
||||
sizeof (struct
|
||||
TALER_RefreshCommitmentP),
|
||||
end = GNUNET_STRINGS_data_to_string (&md.rc,
|
||||
sizeof (md.rc),
|
||||
pub_str,
|
||||
sizeof (pub_str));
|
||||
*end = '\0';
|
||||
@ -459,6 +468,7 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
if (NULL == rrh->url)
|
||||
{
|
||||
json_decref (reveal_obj);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
GNUNET_free (rrh);
|
||||
return NULL;
|
||||
}
|
||||
@ -473,6 +483,7 @@ TALER_EXCHANGE_refreshes_reveal (
|
||||
if (NULL != eh)
|
||||
curl_easy_cleanup (eh);
|
||||
json_decref (reveal_obj);
|
||||
TALER_EXCHANGE_free_melt_data_ (&md);
|
||||
GNUNET_free (rrh->url);
|
||||
GNUNET_free (rrh);
|
||||
return NULL;
|
||||
@ -499,8 +510,8 @@ TALER_EXCHANGE_refreshes_reveal_cancel (
|
||||
}
|
||||
GNUNET_free (rrh->url);
|
||||
TALER_curl_easy_post_finished (&rrh->ctx);
|
||||
TALER_EXCHANGE_free_melt_data_ (rrh->md); /* does not free 'md' itself */
|
||||
GNUNET_free (rrh->md);
|
||||
TALER_EXCHANGE_free_melt_data_ (&rrh->md);
|
||||
GNUNET_free (rrh->exchange_vals);
|
||||
GNUNET_free (rrh);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user