age commitment: json parser helper and support for purses added
This commit is contained in:
parent
87025cfd17
commit
cddfaf007f
@ -456,6 +456,10 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
struct Coin *coin,
|
struct Coin *coin,
|
||||||
const json_t *jcoin)
|
const json_t *jcoin)
|
||||||
{
|
{
|
||||||
|
struct TALER_AgeAttestation attest = {0};
|
||||||
|
bool no_attest = true;
|
||||||
|
struct TALER_AgeCommitment age_commitment = {0};
|
||||||
|
bool no_age_commitment = true;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
TALER_JSON_spec_amount ("amount",
|
TALER_JSON_spec_amount ("amount",
|
||||||
TEH_currency,
|
TEH_currency,
|
||||||
@ -465,10 +469,13 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
TALER_JSON_spec_denom_sig ("ub_sig",
|
TALER_JSON_spec_denom_sig ("ub_sig",
|
||||||
&coin->cpi.denom_sig),
|
&coin->cpi.denom_sig),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
GNUNET_JSON_spec_fixed_auto ("attest",
|
||||||
&coin->cpi.h_age_commitment),
|
&attest),
|
||||||
&coin->cpi.no_age_commitment),
|
&no_attest),
|
||||||
// FIXME-Oec: proof of age is missing.
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
TALER_JSON_spec_age_commitment ("age_commitment",
|
||||||
|
&age_commitment),
|
||||||
|
&no_age_commitment),
|
||||||
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||||
&coin->coin_sig),
|
&coin->coin_sig),
|
||||||
GNUNET_JSON_spec_fixed_auto ("coin_pub",
|
GNUNET_JSON_spec_fixed_auto ("coin_pub",
|
||||||
@ -591,6 +598,48 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
TALER_amount_subtract (&coin->amount_minus_fee,
|
TALER_amount_subtract (&coin->amount_minus_fee,
|
||||||
&coin->amount,
|
&coin->amount,
|
||||||
&coin->deposit_fee));
|
&coin->deposit_fee));
|
||||||
|
|
||||||
|
// Check and verify the age restriction. Needs to happen before
|
||||||
|
// coin-signature check, because we set the h_age_commitment here.
|
||||||
|
{
|
||||||
|
if (no_attest != no_age_commitment)
|
||||||
|
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
/* FIXME: other error code? */
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
|
||||||
|
"mismatch of attest and age_commitment");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! no_age_commitment)
|
||||||
|
{
|
||||||
|
// attestation must be valid.
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TALER_age_commitment_verify (
|
||||||
|
&age_commitment,
|
||||||
|
pcc->min_age,
|
||||||
|
&attest))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
/* FIXME: other error code? */
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
|
||||||
|
"invalid attest for minimum age");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the hash of the age commitment in the coin's public info, so we
|
||||||
|
// can verify the signature later.
|
||||||
|
TALER_age_commitment_hash (&age_commitment,
|
||||||
|
&coin->cpi.h_age_commitment);
|
||||||
|
coin->cpi.no_age_commitment = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* check coin signature */
|
/* check coin signature */
|
||||||
switch (dk->denom_pub.cipher)
|
switch (dk->denom_pub.cipher)
|
||||||
{
|
{
|
||||||
|
@ -300,6 +300,10 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
struct Coin *coin,
|
struct Coin *coin,
|
||||||
const json_t *jcoin)
|
const json_t *jcoin)
|
||||||
{
|
{
|
||||||
|
struct TALER_AgeAttestation attest = {0};
|
||||||
|
bool no_attest = true;
|
||||||
|
struct TALER_AgeCommitment age_commitment = {0};
|
||||||
|
bool no_age_commitment = true;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
TALER_JSON_spec_amount ("amount",
|
TALER_JSON_spec_amount ("amount",
|
||||||
TEH_currency,
|
TEH_currency,
|
||||||
@ -309,10 +313,13 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
TALER_JSON_spec_denom_sig ("ub_sig",
|
TALER_JSON_spec_denom_sig ("ub_sig",
|
||||||
&coin->cpi.denom_sig),
|
&coin->cpi.denom_sig),
|
||||||
GNUNET_JSON_spec_mark_optional (
|
GNUNET_JSON_spec_mark_optional (
|
||||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
GNUNET_JSON_spec_fixed_auto ("attest",
|
||||||
&coin->cpi.h_age_commitment),
|
&attest),
|
||||||
&coin->cpi.no_age_commitment),
|
&no_attest),
|
||||||
// FIXME-Oec: proof of age is missing!
|
GNUNET_JSON_spec_mark_optional (
|
||||||
|
TALER_JSON_spec_age_commitment ("age_commitment",
|
||||||
|
&age_commitment),
|
||||||
|
&no_age_commitment),
|
||||||
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||||
&coin->coin_sig),
|
&coin->coin_sig),
|
||||||
GNUNET_JSON_spec_fixed_auto ("coin_pub",
|
GNUNET_JSON_spec_fixed_auto ("coin_pub",
|
||||||
@ -433,6 +440,47 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
TALER_amount_subtract (&coin->amount_minus_fee,
|
TALER_amount_subtract (&coin->amount_minus_fee,
|
||||||
&coin->amount,
|
&coin->amount,
|
||||||
&coin->deposit_fee));
|
&coin->deposit_fee));
|
||||||
|
|
||||||
|
// Check and verify the age restriction. Needs to happen before
|
||||||
|
// coin-signature check, because we set the h_age_commitment here.
|
||||||
|
{
|
||||||
|
if (no_attest != no_age_commitment)
|
||||||
|
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
/* FIXME: other error code? */
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
|
||||||
|
"mismatch of attest and age_commitment");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! no_age_commitment)
|
||||||
|
{
|
||||||
|
// attestation must be valid.
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
TALER_age_commitment_verify (
|
||||||
|
&age_commitment,
|
||||||
|
pcc->min_age,
|
||||||
|
&attest))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return TALER_MHD_reply_with_error (connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
/* FIXME: other error code? */
|
||||||
|
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
|
||||||
|
"invalid attest for minimum age");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the hash of the age commitment in the coin's public info, so we
|
||||||
|
// can verify the signature later.
|
||||||
|
TALER_age_commitment_hash (&age_commitment,
|
||||||
|
&coin->cpi.h_age_commitment);
|
||||||
|
coin->cpi.no_age_commitment = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* check coin signature */
|
/* check coin signature */
|
||||||
switch (dk->denom_pub.cipher)
|
switch (dk->denom_pub.cipher)
|
||||||
{
|
{
|
||||||
@ -470,6 +518,7 @@ parse_coin (struct MHD_Connection *connection,
|
|||||||
"total deposit contribution");
|
"total deposit contribution");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
MHD_RESULT mhd_ret = MHD_NO;
|
MHD_RESULT mhd_ret = MHD_NO;
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
@ -215,6 +215,18 @@ TALER_JSON_pack_econtract (
|
|||||||
const char *name,
|
const char *name,
|
||||||
const struct TALER_EncryptedContract *econtract);
|
const struct TALER_EncryptedContract *econtract);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate packer instruction for a JSON field of type age_commitment
|
||||||
|
*
|
||||||
|
* @param name name of the field to add to the object
|
||||||
|
* @param age_commitment age commitment to add
|
||||||
|
* @return json pack specification
|
||||||
|
*/
|
||||||
|
struct GNUNET_JSON_PackSpec
|
||||||
|
TALER_JSON_pack_age_commitment (
|
||||||
|
const char *name,
|
||||||
|
const struct TALER_AgeCommitment *age_commitment);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a TALER amount to a JSON object.
|
* Convert a TALER amount to a JSON object.
|
||||||
@ -294,6 +306,17 @@ TALER_JSON_spec_econtract (const char *name,
|
|||||||
struct TALER_EncryptedContract *econtract);
|
struct TALER_EncryptedContract *econtract);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide specification to parse a given JSON object to an age commitment.
|
||||||
|
*
|
||||||
|
* @param name name of the age commitment field in the JSON
|
||||||
|
* @param[out] age_commitment where to store the age commitment
|
||||||
|
* @return spec for parsing an age commitment
|
||||||
|
*/
|
||||||
|
struct GNUNET_JSON_Specification
|
||||||
|
TALER_JSON_spec_age_commitment (const char *name,
|
||||||
|
struct TALER_AgeCommitment *age_commitment);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide specification to parse given JSON object to an amount
|
* Provide specification to parse given JSON object to an amount
|
||||||
* in any currency in network byte order.
|
* in any currency in network byte order.
|
||||||
|
@ -401,6 +401,109 @@ TALER_JSON_spec_econtract (const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse given JSON object to an age commitmnet
|
||||||
|
*
|
||||||
|
* @param cls closure, NULL
|
||||||
|
* @param root the json object representing data
|
||||||
|
* @param[out] spec where to write the data
|
||||||
|
* @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
|
||||||
|
*/
|
||||||
|
static enum GNUNET_GenericReturnValue
|
||||||
|
parse_age_commitment (void *cls,
|
||||||
|
json_t *root,
|
||||||
|
struct GNUNET_JSON_Specification *spec)
|
||||||
|
{
|
||||||
|
struct TALER_AgeCommitment *age_commitment = spec->ptr;
|
||||||
|
json_t *pk;
|
||||||
|
unsigned int idx;
|
||||||
|
size_t num;
|
||||||
|
|
||||||
|
if (NULL == root || ! json_is_array (root))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
num = json_array_size (root);
|
||||||
|
if (32 <= num || 0 == num)
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
age_commitment->num = num;
|
||||||
|
age_commitment->keys =
|
||||||
|
GNUNET_new_array (num,
|
||||||
|
struct TALER_AgeCommitmentPublicKeyP);
|
||||||
|
|
||||||
|
json_array_foreach (root, idx, pk) {
|
||||||
|
const char *emsg;
|
||||||
|
unsigned int eline;
|
||||||
|
struct GNUNET_JSON_Specification pkspec[] = {
|
||||||
|
GNUNET_JSON_spec_fixed_auto (
|
||||||
|
NULL,
|
||||||
|
&age_commitment->keys[idx].pub),
|
||||||
|
GNUNET_JSON_spec_end ()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_JSON_parse (pk,
|
||||||
|
pkspec,
|
||||||
|
&emsg,
|
||||||
|
&eline))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
GNUNET_JSON_parse_free (spec);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return GNUNET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup data left fom parsing age commitment
|
||||||
|
*
|
||||||
|
* @param cls closure, NULL
|
||||||
|
* @param[out] spec where to free the data
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
clean_age_commitment (void *cls,
|
||||||
|
struct GNUNET_JSON_Specification *spec)
|
||||||
|
{
|
||||||
|
struct TALER_AgeCommitment *age_commitment = spec->ptr;
|
||||||
|
|
||||||
|
(void) cls;
|
||||||
|
|
||||||
|
if (NULL == age_commitment ||
|
||||||
|
NULL == age_commitment->keys)
|
||||||
|
return;
|
||||||
|
|
||||||
|
age_commitment->num = 0;
|
||||||
|
GNUNET_free (age_commitment->keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct GNUNET_JSON_Specification
|
||||||
|
TALER_JSON_spec_age_commitment (const char *name,
|
||||||
|
struct TALER_AgeCommitment *age_commitment)
|
||||||
|
{
|
||||||
|
struct GNUNET_JSON_Specification ret = {
|
||||||
|
.parser = &parse_age_commitment,
|
||||||
|
.cleaner = &clean_age_commitment,
|
||||||
|
.cls = NULL,
|
||||||
|
.field = name,
|
||||||
|
.ptr = age_commitment,
|
||||||
|
.ptr_size = 0,
|
||||||
|
.size_ptr = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse given JSON object to denomination public key.
|
* Parse given JSON object to denomination public key.
|
||||||
*
|
*
|
||||||
|
@ -71,6 +71,40 @@ TALER_JSON_pack_econtract (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct GNUNET_JSON_PackSpec
|
||||||
|
TALER_JSON_pack_age_commitment (
|
||||||
|
const char *name,
|
||||||
|
const struct TALER_AgeCommitment *age_commitment)
|
||||||
|
{
|
||||||
|
struct GNUNET_JSON_PackSpec ps = {
|
||||||
|
.field_name = name,
|
||||||
|
};
|
||||||
|
json_t *keys;
|
||||||
|
|
||||||
|
if (NULL == age_commitment ||
|
||||||
|
0 == age_commitment->num)
|
||||||
|
return ps;
|
||||||
|
|
||||||
|
GNUNET_assert (NULL !=
|
||||||
|
(keys = json_array ()));
|
||||||
|
|
||||||
|
for (size_t i = 0;
|
||||||
|
i < age_commitment->num;
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
json_t *val;
|
||||||
|
val = GNUNET_JSON_from_data (&age_commitment->keys[i],
|
||||||
|
sizeof(age_commitment->keys[i]));
|
||||||
|
GNUNET_assert (NULL != val);
|
||||||
|
GNUNET_assert (0 ==
|
||||||
|
json_array_append_new (keys, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
ps.object = keys;
|
||||||
|
return ps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct GNUNET_JSON_PackSpec
|
struct GNUNET_JSON_PackSpec
|
||||||
TALER_JSON_pack_denom_pub (
|
TALER_JSON_pack_denom_pub (
|
||||||
const char *name,
|
const char *name,
|
||||||
|
@ -485,29 +485,33 @@ TALER_EXCHANGE_purse_deposit (
|
|||||||
for (unsigned int i = 0; i<num_deposits; i++)
|
for (unsigned int i = 0; i<num_deposits; i++)
|
||||||
{
|
{
|
||||||
const struct TALER_EXCHANGE_PurseDeposit *deposit = &deposits[i];
|
const struct TALER_EXCHANGE_PurseDeposit *deposit = &deposits[i];
|
||||||
|
const struct TALER_AgeCommitmentProof *acp = deposit->age_commitment_proof;
|
||||||
struct Coin *coin = &pch->coins[i];
|
struct Coin *coin = &pch->coins[i];
|
||||||
json_t *jdeposit;
|
json_t *jdeposit;
|
||||||
#if FIXME_OEC
|
struct TALER_AgeCommitmentHash ach;
|
||||||
struct TALER_AgeCommitmentHash agh;
|
struct TALER_AgeCommitmentHash *achp = NULL;
|
||||||
struct TALER_AgeCommitmentHash *aghp = NULL;
|
|
||||||
struct TALER_AgeAttestation attest;
|
struct TALER_AgeAttestation attest;
|
||||||
|
struct TALER_AgeAttestation *attestp = NULL;
|
||||||
|
|
||||||
TALER_age_commitment_hash (&deposit->age_commitment,
|
if (NULL != acp)
|
||||||
&agh);
|
|
||||||
aghp = &agh;
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TALER_age_commitment_attest (&deposit->age_proof,
|
|
||||||
min_age,
|
|
||||||
&attest))
|
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
TALER_age_commitment_hash (&acp->commitment,
|
||||||
json_decref (deposit_arr);
|
&ach);
|
||||||
GNUNET_free (pch->base_url);
|
achp = &ach;
|
||||||
GNUNET_free (pch->coins);
|
if (GNUNET_OK !=
|
||||||
GNUNET_free (pch);
|
TALER_age_commitment_attest (acp,
|
||||||
return NULL;
|
min_age,
|
||||||
|
&attest))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
json_decref (deposit_arr);
|
||||||
|
GNUNET_free (pch->base_url);
|
||||||
|
GNUNET_free (pch->coins);
|
||||||
|
GNUNET_free (pch);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
attestp = &attest;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
GNUNET_CRYPTO_eddsa_key_get_public (&deposit->coin_priv.eddsa_priv,
|
GNUNET_CRYPTO_eddsa_key_get_public (&deposit->coin_priv.eddsa_priv,
|
||||||
&coin->coin_pub.eddsa_pub);
|
&coin->coin_pub.eddsa_pub);
|
||||||
coin->h_denom_pub = deposit->h_denom_pub;
|
coin->h_denom_pub = deposit->h_denom_pub;
|
||||||
@ -519,14 +523,12 @@ TALER_EXCHANGE_purse_deposit (
|
|||||||
&deposit->coin_priv,
|
&deposit->coin_priv,
|
||||||
&coin->coin_sig);
|
&coin->coin_sig);
|
||||||
jdeposit = GNUNET_JSON_PACK (
|
jdeposit = GNUNET_JSON_PACK (
|
||||||
#if FIXME_OEC
|
|
||||||
GNUNET_JSON_pack_allow_null (
|
GNUNET_JSON_pack_allow_null (
|
||||||
GNUNET_JSON_pack_data_auto ("h_age_commitment",
|
GNUNET_JSON_pack_data_auto ("h_age_commitment",
|
||||||
aghp)),
|
achp)),
|
||||||
GNUNET_JSON_pack_allow_null (
|
GNUNET_JSON_pack_allow_null (
|
||||||
GNUNET_JSON_pack_data_auto ("age_attestation",
|
GNUNET_JSON_pack_data_auto ("age_attestation",
|
||||||
&attest)),
|
attestp)),
|
||||||
#endif
|
|
||||||
TALER_JSON_pack_amount ("amount",
|
TALER_JSON_pack_amount ("amount",
|
||||||
&deposit->amount),
|
&deposit->amount),
|
||||||
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
GNUNET_JSON_pack_data_auto ("denom_pub_hash",
|
||||||
|
Loading…
Reference in New Issue
Block a user