Merge branch 'age-withdraw'
This commit is contained in:
commit
20cd46f63d
@ -1 +1 @@
|
|||||||
Subproject commit 214bc664476333a2c042ae57911558d1325e725f
|
Subproject commit 02132ededc12a0a1cfd81f0ca76c384304e15259
|
@ -42,7 +42,7 @@ struct AgeRevealContext
|
|||||||
/**
|
/**
|
||||||
* Public key of the reserve for with the age-withdraw commitment was
|
* Public key of the reserve for with the age-withdraw commitment was
|
||||||
* originally made. This parameter is provided by the client again
|
* originally made. This parameter is provided by the client again
|
||||||
* during the call to reveal in order to save a database-lookup .
|
* during the call to reveal in order to save a database-lookup.
|
||||||
*/
|
*/
|
||||||
struct TALER_ReservePublicKeyP reserve_pub;
|
struct TALER_ReservePublicKeyP reserve_pub;
|
||||||
|
|
||||||
@ -52,20 +52,41 @@ struct AgeRevealContext
|
|||||||
uint32_t num_coins;
|
uint32_t num_coins;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO:oec num_coins denoms
|
* #num_coins hashes of the denominations from which the coins are withdrawn.
|
||||||
|
* Those must support age restriction.
|
||||||
*/
|
*/
|
||||||
struct TALER_DenominationHashP *denoms_h;
|
struct TALER_DenominationHashP *denoms_h;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO:oec num_coins blinded coins
|
* #num_coins denomination keys, found in the system, according to denoms_h;
|
||||||
|
*/
|
||||||
|
struct TEH_DenominationKey *denom_keys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #num_coins hases of blinded coins.
|
||||||
*/
|
*/
|
||||||
struct TALER_BlindedCoinHashP *coin_evs;
|
struct TALER_BlindedCoinHashP *coin_evs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO:oec num_coins*(kappa - 1) disclosed coins
|
* Total sum of all denominations' values
|
||||||
|
**/
|
||||||
|
struct TALER_Amount total_amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total sum of all denominations' fees
|
||||||
|
*/
|
||||||
|
struct TALER_Amount total_fee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #num_coins*(kappa - 1) disclosed coins.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_CRYPTO_EddsaPrivateKey *disclosed_coins;
|
struct GNUNET_CRYPTO_EddsaPrivateKey *disclosed_coins;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data from the original age-withdraw. Will be retrieved from
|
||||||
|
* the DB via @a ach.
|
||||||
|
*/
|
||||||
|
struct TALER_EXCHANGEDB_AgeWithdrawCommitment commitment;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,30 +96,35 @@ void
|
|||||||
age_reveal_context_free (struct AgeRevealContext *actx)
|
age_reveal_context_free (struct AgeRevealContext *actx)
|
||||||
{
|
{
|
||||||
GNUNET_free (actx->denoms_h);
|
GNUNET_free (actx->denoms_h);
|
||||||
|
GNUNET_free (actx->denom_keys);
|
||||||
GNUNET_free (actx->coin_evs);
|
GNUNET_free (actx->coin_evs);
|
||||||
GNUNET_free (actx->disclosed_coins);
|
GNUNET_free (actx->disclosed_coins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a "/age-withdraw/$ACH/reveal request. Parses the given JSON
|
* Parse the json body of an '/age-withdraw/$ACH/reveal' request. It extracts
|
||||||
* ... TODO:oec:description
|
* the denomination hashes, blinded coins and disclosed coins and allocates
|
||||||
|
* memory for those.
|
||||||
*
|
*
|
||||||
* @param connection The MHD connection to handle
|
* @param connection The MHD connection to handle
|
||||||
* @param actx The context of the operation, only partially built at call time
|
|
||||||
* @param j_denoms_h Array of hashes of the denominations for the withdrawal, in JSON format
|
* @param j_denoms_h Array of hashes of the denominations for the withdrawal, in JSON format
|
||||||
* @param j_coin_evs The blinded envelopes in JSON format for the coins that are not revealed and will be signed on success
|
* @param j_coin_evs The blinded envelopes in JSON format for the coins that are not revealed and will be signed on success
|
||||||
* @param j_disclosed_coins The n*(kappa-1) disclosed coins' private keys in JSON format, from which all other attributes (age restriction, blinding, nonce) will be derived from
|
* @param j_disclosed_coins The n*(kappa-1) disclosed coins' private keys in JSON format, from which all other attributes (age restriction, blinding, nonce) will be derived from
|
||||||
|
* @param[out] actx The context of the operation, only partially built at call time
|
||||||
|
* @param[out] mhd_mret The result if a reply is queued for MHD
|
||||||
|
* @return true on success, false on failure, with a reply already queued for MHD.
|
||||||
*/
|
*/
|
||||||
MHD_RESULT
|
static enum GNUNET_GenericReturnValue
|
||||||
handle_age_withdraw_reveal_json (
|
parse_age_withdraw_reveal_json (
|
||||||
struct MHD_Connection *connection,
|
struct MHD_Connection *connection,
|
||||||
struct AgeRevealContext *actx,
|
|
||||||
const json_t *j_denoms_h,
|
const json_t *j_denoms_h,
|
||||||
const json_t *j_coin_evs,
|
const json_t *j_coin_evs,
|
||||||
const json_t *j_disclosed_coins)
|
const json_t *j_disclosed_coins,
|
||||||
|
struct AgeRevealContext *actx,
|
||||||
|
MHD_RESULT *mhd_ret)
|
||||||
{
|
{
|
||||||
MHD_RESULT mhd_ret = MHD_NO;
|
enum GNUNET_GenericReturnValue result = GNUNET_SYSERR;
|
||||||
|
|
||||||
/* Verify JSON-structure consistency */
|
/* Verify JSON-structure consistency */
|
||||||
{
|
{
|
||||||
@ -116,135 +142,309 @@ handle_age_withdraw_reveal_json (
|
|||||||
error = "denoms_h must not be empty";
|
error = "denoms_h must not be empty";
|
||||||
else if (actx->num_coins != json_array_size (j_coin_evs))
|
else if (actx->num_coins != json_array_size (j_coin_evs))
|
||||||
error = "denoms_h and coins_evs must be arrays of the same size";
|
error = "denoms_h and coins_evs must be arrays of the same size";
|
||||||
|
else if (actx->num_coins > TALER_MAX_FRESH_COINS)
|
||||||
|
/**
|
||||||
|
* The wallet had committed to more than the maximum coins allowed, the
|
||||||
|
* reserve has been charged, but now the user can not withdraw any money
|
||||||
|
* from it. Note that the user can't get their money back in this case!
|
||||||
|
**/
|
||||||
|
error = "maximum number of coins that can be withdrawn has been exceeded";
|
||||||
else if (actx->num_coins * (TALER_CNC_KAPPA - 1)
|
else if (actx->num_coins * (TALER_CNC_KAPPA - 1)
|
||||||
!= json_array_size (j_disclosed_coins))
|
!= json_array_size (j_disclosed_coins))
|
||||||
error = "the size of array disclosed_coins must be "
|
error = "the size of array disclosed_coins must be "
|
||||||
TALER_CNC_KAPPA_MINUS_ONE_STR " times of the size of denoms_h";
|
TALER_CNC_KAPPA_MINUS_ONE_STR " times the size of denoms_h";
|
||||||
else if (actx->num_coins > TALER_MAX_FRESH_COINS)
|
|
||||||
/**
|
|
||||||
* FIXME?: If the user had commited to more than the maximum coins allowed,
|
|
||||||
* the reserve has been charged, but now the user can not withdraw any money
|
|
||||||
* from it. How can the user get their money back?
|
|
||||||
**/
|
|
||||||
error = "maximum number of coins that can be withdrawn has been exceeded";
|
|
||||||
|
|
||||||
if (NULL != error)
|
if (NULL != error)
|
||||||
return TALER_MHD_reply_with_error (connection,
|
{
|
||||||
MHD_HTTP_BAD_REQUEST,
|
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
error);
|
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||||
|
error);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse denomination keys */
|
/* Continue parsing the parts */
|
||||||
{
|
{
|
||||||
unsigned int idx;
|
unsigned int idx = 0;
|
||||||
json_t *jh;
|
json_t *value = NULL;
|
||||||
|
|
||||||
|
/* Parse denomination keys */
|
||||||
actx->denoms_h = GNUNET_new_array (actx->num_coins,
|
actx->denoms_h = GNUNET_new_array (actx->num_coins,
|
||||||
struct TALER_DenominationHashP);
|
struct TALER_DenominationHashP);
|
||||||
|
|
||||||
json_array_foreach (j_denoms_h, idx, jh) {
|
json_array_foreach (j_denoms_h, idx, value) {
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_fixed_auto (NULL, &actx->denoms_h[idx]),
|
GNUNET_JSON_spec_fixed_auto (NULL, &actx->denoms_h[idx]),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_JSON_parse (jh, spec, NULL, NULL))
|
GNUNET_JSON_parse (value, spec, NULL, NULL))
|
||||||
{
|
{
|
||||||
char msg[256] = {0};
|
char msg[256] = {0};
|
||||||
GNUNET_snprintf (msg,
|
GNUNET_snprintf (msg,
|
||||||
sizeof(msg),
|
sizeof(msg),
|
||||||
"couldn't parse entry no. %d in array denoms_h",
|
"couldn't parse entry no. %d in array denoms_h",
|
||||||
idx + 1);
|
idx + 1);
|
||||||
mhd_ret = TALER_MHD_reply_with_error (connection,
|
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||||
msg);
|
msg);
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse blinded envelopes */
|
|
||||||
{
|
|
||||||
unsigned int idx;
|
|
||||||
json_t *ce;
|
|
||||||
|
|
||||||
|
/* Parse blinded envelopes */
|
||||||
actx->coin_evs = GNUNET_new_array (actx->num_coins,
|
actx->coin_evs = GNUNET_new_array (actx->num_coins,
|
||||||
struct TALER_BlindedCoinHashP);
|
struct TALER_BlindedCoinHashP);
|
||||||
|
|
||||||
json_array_foreach (j_coin_evs, idx, ce) {
|
json_array_foreach (j_coin_evs, idx, value) {
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_fixed_auto (NULL, &actx->coin_evs[idx]),
|
GNUNET_JSON_spec_fixed_auto (NULL, &actx->coin_evs[idx]),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_JSON_parse (ce, spec, NULL, NULL))
|
GNUNET_JSON_parse (value, spec, NULL, NULL))
|
||||||
{
|
{
|
||||||
char msg[256] = {0};
|
char msg[256] = {0};
|
||||||
GNUNET_snprintf (msg,
|
GNUNET_snprintf (msg,
|
||||||
sizeof(msg),
|
sizeof(msg),
|
||||||
"couldn't parse entry no. %d in array coin_evs",
|
"couldn't parse entry no. %d in array coin_evs",
|
||||||
idx + 1);
|
idx + 1);
|
||||||
mhd_ret = TALER_MHD_reply_with_error (connection,
|
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||||
msg);
|
msg);
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse diclosed keys */
|
|
||||||
{
|
|
||||||
unsigned int idx;
|
|
||||||
json_t *dc;
|
|
||||||
|
|
||||||
|
/* Parse diclosed keys */
|
||||||
actx->disclosed_coins = GNUNET_new_array (
|
actx->disclosed_coins = GNUNET_new_array (
|
||||||
actx->num_coins * (TALER_CNC_KAPPA),
|
actx->num_coins * (TALER_CNC_KAPPA - 1),
|
||||||
struct GNUNET_CRYPTO_EddsaPrivateKey);
|
struct GNUNET_CRYPTO_EddsaPrivateKey);
|
||||||
|
|
||||||
json_array_foreach (j_coin_evs, idx, dc) {
|
json_array_foreach (j_disclosed_coins, idx, value) {
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
GNUNET_JSON_spec_fixed_auto (NULL, &actx->disclosed_coins[idx]),
|
GNUNET_JSON_spec_fixed_auto (NULL, &actx->disclosed_coins[idx]),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
GNUNET_JSON_parse (dc, spec, NULL, NULL))
|
GNUNET_JSON_parse (value, spec, NULL, NULL))
|
||||||
{
|
{
|
||||||
char msg[256] = {0};
|
char msg[256] = {0};
|
||||||
GNUNET_snprintf (msg,
|
GNUNET_snprintf (msg,
|
||||||
sizeof(msg),
|
sizeof(msg),
|
||||||
"couldn't parse entry no. %d in array disclosed_coins",
|
"couldn't parse entry no. %d in array disclosed_coins",
|
||||||
idx + 1);
|
idx + 1);
|
||||||
mhd_ret = TALER_MHD_reply_with_error (connection,
|
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||||
MHD_HTTP_BAD_REQUEST,
|
MHD_HTTP_BAD_REQUEST,
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||||
msg);
|
msg);
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO:oec: find commitment */
|
result = GNUNET_OK;
|
||||||
/* TODO:oec: check validity of denoms */
|
*mhd_ret = MHD_YES;
|
||||||
/* TODO:oec: check amount total against denoms */
|
|
||||||
/* TODO:oec: compute the disclosed blinded coins */
|
|
||||||
/* TODO:oec: generate h_commitment_comp */
|
|
||||||
/* TODO:oec: compare h_commitment_comp against h_commitment */
|
|
||||||
/* TODO:oec: sign the coins */
|
|
||||||
/* TODO:oec: send response */
|
|
||||||
|
|
||||||
|
|
||||||
/* TODO */
|
|
||||||
EXIT:
|
EXIT:
|
||||||
age_reveal_context_free (actx);
|
return result;
|
||||||
return mhd_ret;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the request belongs to an existing age-withdraw request.
|
||||||
|
* If so, sets the age_withdraw object with the request data.
|
||||||
|
* Otherwise, it queues an appropriate MHD response.
|
||||||
|
*
|
||||||
|
* @param connection The HTTP connection to the client
|
||||||
|
* @param h_commitment Original commitment value sent with the age-withdraw request
|
||||||
|
* @param reserve_pub Reserve public key used in the original age-withdraw request
|
||||||
|
* @param[out] commitment Data from the original age-withdraw request
|
||||||
|
* @param[out] result In the error cases, a response will be queued with MHD and this will be the result.
|
||||||
|
* @return GNUNET_OK if the withdraw request has been found,
|
||||||
|
* GNUNET_SYSERROR if we did not find the request in the DB
|
||||||
|
*/
|
||||||
|
static enum GNUNET_GenericReturnValue
|
||||||
|
retrieve_original_commitment (
|
||||||
|
struct MHD_Connection *connection,
|
||||||
|
const struct TALER_AgeWithdrawCommitmentHashP *h_commitment,
|
||||||
|
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||||
|
struct TALER_EXCHANGEDB_AgeWithdrawCommitment *commitment,
|
||||||
|
MHD_RESULT *result)
|
||||||
|
{
|
||||||
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
|
||||||
|
qs = TEH_plugin->get_age_withdraw_info (TEH_plugin->cls,
|
||||||
|
reserve_pub,
|
||||||
|
h_commitment,
|
||||||
|
commitment);
|
||||||
|
switch (qs)
|
||||||
|
{
|
||||||
|
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
||||||
|
return GNUNET_OK; /* Only happy case */
|
||||||
|
|
||||||
|
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
||||||
|
*result = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_NOT_FOUND,
|
||||||
|
TALER_EC_EXCHANGE_AGE_WITHDRAW_COMMITMENT_UNKNOWN,
|
||||||
|
NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GNUNET_DB_STATUS_HARD_ERROR:
|
||||||
|
*result = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||||
|
"get_age_withdraw_info");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GNUNET_DB_STATUS_SOFT_ERROR:
|
||||||
|
/* FIXME: Do we queue a result in this case or retry? */
|
||||||
|
default:
|
||||||
|
GNUNET_break (0); /* should be impossible */
|
||||||
|
*result = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given array of hashes of denomination_keys a) belong
|
||||||
|
* to valid denominations and b) those are marked as age restricted.
|
||||||
|
*
|
||||||
|
* @param connection The HTTP connection to the client
|
||||||
|
* @param len The lengths of the array @a denoms_h
|
||||||
|
* @param denoms_h array of hashes of denomination public keys
|
||||||
|
* @param[out] dks On success, will be filled with the denomination keys. Caller must deallocate.
|
||||||
|
* @param amount_with_fee The commited amount including fees
|
||||||
|
* @param[out] total_sum On success, will contain the total sum of all denominations
|
||||||
|
* @param[out] total_fee On success, will contain the total sum of all fees
|
||||||
|
* @param[out] result In the error cases, a response will be queued with MHD and this will be the result.
|
||||||
|
* @return GNUNET_OK if the denominations are valid and support age-restriction
|
||||||
|
* GNUNET_SYSERR otherwise
|
||||||
|
*/
|
||||||
|
static enum GNUNET_GenericReturnValue
|
||||||
|
all_denominations_valid (
|
||||||
|
struct MHD_Connection *connection,
|
||||||
|
uint32_t len,
|
||||||
|
const struct TALER_DenominationHashP *denoms_h,
|
||||||
|
struct TEH_DenominationKey **dks,
|
||||||
|
const struct TALER_Amount *amount_with_fee,
|
||||||
|
struct TALER_Amount *total_amount,
|
||||||
|
struct TALER_Amount *total_fee,
|
||||||
|
MHD_RESULT *result)
|
||||||
|
{
|
||||||
|
struct TEH_KeyStateHandle *ksh;
|
||||||
|
|
||||||
|
GNUNET_assert (*dks == NULL);
|
||||||
|
|
||||||
|
ksh = TEH_keys_get_state ();
|
||||||
|
if (NULL == ksh)
|
||||||
|
{
|
||||||
|
*result = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||||
|
NULL);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dks = GNUNET_new_array (len, struct TEH_DenominationKey);
|
||||||
|
TALER_amount_set_zero (TEH_currency, total_amount);
|
||||||
|
TALER_amount_set_zero (TEH_currency, total_fee);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
dks[i] = TEH_keys_denomination_by_hash2 (
|
||||||
|
ksh,
|
||||||
|
&denoms_h[i],
|
||||||
|
connection,
|
||||||
|
result);
|
||||||
|
|
||||||
|
/* Does the denomination exist? */
|
||||||
|
if (NULL == dks[i])
|
||||||
|
{
|
||||||
|
GNUNET_assert (result != NULL);
|
||||||
|
/* Note: a HTTP-response has been queued and result has been set by
|
||||||
|
* TEH_keys_denominations_by_hash2 */
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does the denomation support age restriction ? */
|
||||||
|
if (0 == dks[i]->denom_pub.age_mask.bits)
|
||||||
|
{
|
||||||
|
char msg[256] = {0};
|
||||||
|
GNUNET_snprintf (msg,
|
||||||
|
sizeof(msg),
|
||||||
|
"denomination key no. %d does not support age restriction",
|
||||||
|
i + 1);
|
||||||
|
|
||||||
|
*result = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
|
||||||
|
msg);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Accumulate the values */
|
||||||
|
if (0 > TALER_amount_add (
|
||||||
|
total_amount,
|
||||||
|
total_amount,
|
||||||
|
&dks[i]->meta.value))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
*result = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_EXCHANGE_AGE_WITHDRAW_AMOUNT_OVERFLOW,
|
||||||
|
"amount");
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Accumulate the withdraw fees */
|
||||||
|
if (0 > TALER_amount_add (
|
||||||
|
total_fee,
|
||||||
|
total_fee,
|
||||||
|
&dks[i]->meta.fees.withdraw))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
*result = TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_EXCHANGE_AGE_WITHDRAW_AMOUNT_OVERFLOW,
|
||||||
|
"fee");
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare the commited amount against the totals */
|
||||||
|
{
|
||||||
|
struct TALER_Amount sum;
|
||||||
|
TALER_amount_set_zero (TEH_currency, &sum);
|
||||||
|
|
||||||
|
GNUNET_assert (0 < TALER_amount_add (
|
||||||
|
&sum,
|
||||||
|
total_amount,
|
||||||
|
total_fee));
|
||||||
|
|
||||||
|
if (0 != TALER_amount_cmp (&sum, amount_with_fee))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
*result = TALER_MHD_reply_with_ec (connection,
|
||||||
|
TALER_EC_EXCHANGE_AGE_WITHDRAW_AMOUNT_INCORRECT,
|
||||||
|
NULL);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -254,6 +454,8 @@ TEH_handler_age_withdraw_reveal (
|
|||||||
const struct TALER_AgeWithdrawCommitmentHashP *ach,
|
const struct TALER_AgeWithdrawCommitmentHashP *ach,
|
||||||
const json_t *root)
|
const json_t *root)
|
||||||
{
|
{
|
||||||
|
MHD_RESULT result = MHD_NO;
|
||||||
|
enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
|
||||||
struct AgeRevealContext actx = {0};
|
struct AgeRevealContext actx = {0};
|
||||||
json_t *j_denoms_h;
|
json_t *j_denoms_h;
|
||||||
json_t *j_coin_evs;
|
json_t *j_coin_evs;
|
||||||
@ -270,33 +472,59 @@ TEH_handler_age_withdraw_reveal (
|
|||||||
|
|
||||||
/* Parse JSON body*/
|
/* Parse JSON body*/
|
||||||
{
|
{
|
||||||
enum GNUNET_GenericReturnValue res;
|
ret = TALER_MHD_parse_json_data (rc->connection,
|
||||||
|
|
||||||
res = TALER_MHD_parse_json_data (rc->connection,
|
|
||||||
root,
|
root,
|
||||||
spec);
|
spec);
|
||||||
if (GNUNET_OK != res)
|
if (GNUNET_OK != ret)
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
return (GNUNET_SYSERR == ret) ? MHD_NO : MHD_YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* handle reveal request */
|
do {
|
||||||
{
|
/* Extract denominations, blinded and disclosed coins */
|
||||||
MHD_RESULT res;
|
if (GNUNET_OK != parse_age_withdraw_reveal_json (rc->connection,
|
||||||
|
j_denoms_h,
|
||||||
|
j_coin_evs,
|
||||||
|
j_disclosed_coins,
|
||||||
|
&actx,
|
||||||
|
&result))
|
||||||
|
break;
|
||||||
|
|
||||||
res = handle_age_withdraw_reveal_json (rc->connection,
|
/* Find original commitment */
|
||||||
&actx,
|
if (GNUNET_OK != retrieve_original_commitment (rc->connection,
|
||||||
j_denoms_h,
|
&actx.ach,
|
||||||
j_coin_evs,
|
&actx.reserve_pub,
|
||||||
j_disclosed_coins);
|
&actx.commitment,
|
||||||
|
&result))
|
||||||
|
break;
|
||||||
|
|
||||||
GNUNET_JSON_parse_free (spec);
|
/* Ensure validity of denoms and the sum of amounts and fees */
|
||||||
return res;
|
if (GNUNET_OK != all_denominations_valid (
|
||||||
}
|
rc->connection,
|
||||||
|
actx.num_coins,
|
||||||
|
actx.denoms_h,
|
||||||
|
&actx.denom_keys,
|
||||||
|
&actx.commitment.amount_with_fee,
|
||||||
|
&actx.total_amount,
|
||||||
|
&actx.total_fee,
|
||||||
|
&result))
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
/* TODO:oec: compute the disclosed blinded coins */
|
||||||
|
/* TODO:oec: generate h_commitment_comp */
|
||||||
|
/* TODO:oec: compare h_commitment_comp against h_commitment */
|
||||||
|
/* TODO:oec: sign the coins */
|
||||||
|
/* TODO:oec: send response */
|
||||||
|
|
||||||
|
age_reveal_context_free (&actx);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user