[WIP] moving towards withdrawal with age restriction

Age_mask now taken into account when denominations are being setup.
However, tests fail, because denoms can't be found!?  Probably because
on initial generation of the denominations, the age mask is not setup,
yet, because age restriction hasn't been enabled yet!?
This commit is contained in:
Özgür Kesim 2022-02-07 18:39:58 +01:00
parent d02b5e213a
commit 632d17f642
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7
10 changed files with 83 additions and 30 deletions

View File

@ -152,6 +152,10 @@ static char *currency;
*/ */
static char *CFG_exchange_url; static char *CFG_exchange_url;
/**
* If age restriction is enabled, the age mask to be used
*/
static struct TALER_AgeMask age_mask = {0};
/** /**
* A subcommand supported by this program. * A subcommand supported by this program.
@ -3198,6 +3202,43 @@ sign_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
} }
/**
* Looks up the AGE_RESTRICTED setting for a denomination in the config and
* returns the age restriction (mask) accordingly.
*
* @param section_name Section in the configuration for the particular
* denomination.
*/
static struct TALER_AgeMask
load_age_mask (const char*section_name)
{
static const struct TALER_AgeMask null_mask = {0};
enum GNUNET_GenericReturnValue ret;
if (age_mask.mask == 0)
return null_mask;
if (GNUNET_OK != (GNUNET_CONFIGURATION_have_value (
kcfg,
section_name,
"AGE_RESTRICTED")))
return null_mask;
ret = GNUNET_CONFIGURATION_get_value_yesno (kcfg,
section_name,
"AGE_RESTRICTED");
if (GNUNET_YES == ret)
return age_mask;
if (GNUNET_SYSERR == ret)
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
section_name,
"AGE_RESTRICTED",
"Value must be YES or NO\n");
return null_mask;
}
/** /**
* Sign @a denomkeys with offline key. * Sign @a denomkeys with offline key.
* *
@ -3286,7 +3327,10 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub,
duration = GNUNET_TIME_absolute_get_difference ( duration = GNUNET_TIME_absolute_get_difference (
stamp_start.abs_time, stamp_start.abs_time,
stamp_expire_withdraw.abs_time); stamp_expire_withdraw.abs_time);
// FIXME-Oec: setup age mask here?
/* Load the age mask, if applicable to this denomination */
denom_pub.age_mask = load_age_mask (section_name);
TALER_denom_pub_hash (&denom_pub, TALER_denom_pub_hash (&denom_pub,
&h_denom_pub); &h_denom_pub);
switch (denom_pub.cipher) switch (denom_pub.cipher)
@ -3520,14 +3564,6 @@ do_extensions_show (char *const *args)
json_t *exts = json_object (); json_t *exts = json_object ();
const struct TALER_Extension *it; const struct TALER_Extension *it;
TALER_extensions_init ();
if (GNUNET_OK != TALER_extensions_load_taler_config (kcfg))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"error while loading taler config for extensions\n");
return;
}
for (it = TALER_extensions_get_head (); for (it = TALER_extensions_get_head ();
NULL != it; NULL != it;
it = it->next) it = it->next)
@ -3781,6 +3817,17 @@ run (void *cls,
global_ret = EXIT_NOTCONFIGURED; global_ret = EXIT_NOTCONFIGURED;
return; return;
} }
/* load age mask, if age restriction is enabled */
TALER_extensions_init ();
if (GNUNET_OK != TALER_extensions_load_taler_config (kcfg))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"error while loading taler config for extensions\n");
return;
}
age_mask = TALER_extensions_age_restriction_ageMask ();
ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
&rc); &rc);
rc = GNUNET_CURL_gnunet_rc_create (ctx); rc = GNUNET_CURL_gnunet_rc_create (ctx);

View File

@ -31,7 +31,6 @@
#include "taler_extensions.h" #include "taler_extensions.h"
#include "taler_dbevents.h" #include "taler_dbevents.h"
/** /**
* Extension carries the necessary data for a particular extension. * Extension carries the necessary data for a particular extension.
* *
@ -295,6 +294,10 @@ TEH_handler_management_post_extensions (
NULL, NULL,
0); 0);
/* FIXME-oec. Because of a change of extensions, the key might */
TEH_keys_update_states ();
CLEANUP: CLEANUP:
for (unsigned int i = 0; i < sec.num_extensions; i++) for (unsigned int i = 0; i < sec.num_extensions; i++)
{ {

View File

@ -224,8 +224,8 @@ age_restriction_load_taler_config (
if (GNUNET_OK == ret) if (GNUNET_OK == ret)
{ {
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"settings age mask to %x with #groups: %d\n", mask.mask, "setting age mask to %x with #groups: %d\n", mask.mask,
__builtin_popcount (mask.mask) - 1); __builtin_popcount (mask.mask) - 1);
_config.mask.mask = mask.mask; _config.mask.mask = mask.mask;
_config.num_groups = __builtin_popcount (mask.mask) - 1; /* no underflow, first bit always set */ _config.num_groups = __builtin_popcount (mask.mask) - 1; /* no underflow, first bit always set */

View File

@ -159,13 +159,6 @@ struct TALER_EXCHANGE_DenomPublicKey
* revoked by the exchange. * revoked by the exchange.
*/ */
bool revoked; bool revoked;
/**
* If age_mask non-zero, the denomination is age-restricted, with the age
* groups as defined in the mask.
*/
struct TALER_AgeMask age_mask;
bool age_restricted;
}; };

View File

@ -364,6 +364,9 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
sizeof (struct GNUNET_HashCode)); sizeof (struct GNUNET_HashCode));
if (! check_sigs) if (! check_sigs)
return GNUNET_OK; return GNUNET_OK;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"XXXXX checking validity of %s with age_mask %d\n", GNUNET_h2s (
&denom_key->h_key.hash), denom_key->key.age_mask.mask);
EXITIF (GNUNET_SYSERR == EXITIF (GNUNET_SYSERR ==
TALER_exchange_offline_denom_validity_verify ( TALER_exchange_offline_denom_validity_verify (
&denom_key->h_key, &denom_key->h_key,
@ -378,6 +381,8 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
&denom_key->fee_refund, &denom_key->fee_refund,
master_key, master_key,
&denom_key->master_sig)); &denom_key->master_sig));
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "XXXXX validity of %s OK\n",
GNUNET_h2s (&denom_key->h_key.hash));
return GNUNET_OK; return GNUNET_OK;
EXITIF_exit: EXITIF_exit:
/* invalidate denom_key, just to be sure */ /* invalidate denom_key, just to be sure */
@ -890,8 +895,9 @@ decode_keys_json (const json_t *resp_obj,
* "denoms" or "age_restricted_denoms" */ * "denoms" or "age_restricted_denoms" */
if (hive[s].is_optional_age_restriction) if (hive[s].is_optional_age_restriction)
{ {
dk.age_restricted = true; // dk.age_restricted = true;
dk.age_mask.mask = key_data->age_mask.mask; // dk.age_mask.mask = key_data->age_mask.mask;
GNUNET_assert (0 != key_data->age_mask.mask);
} }
for (unsigned int j = 0; for (unsigned int j = 0;

View File

@ -32,7 +32,7 @@
/** /**
* Set to 1 for extra debug logging. * Set to 1 for extra debug logging.
*/ */
#define DEBUG 0 #define DEBUG 1 /* FIXME-oec */
/** /**

View File

@ -184,6 +184,7 @@ TALER_EXCHANGE_withdraw (
{ {
struct TALER_PlanchetDetail pd; struct TALER_PlanchetDetail pd;
struct TALER_EXCHANGE_WithdrawHandle *wh; struct TALER_EXCHANGE_WithdrawHandle *wh;
bool age_restricted = (0 != pk->key.age_mask.mask);
wh = GNUNET_new (struct TALER_EXCHANGE_WithdrawHandle); wh = GNUNET_new (struct TALER_EXCHANGE_WithdrawHandle);
wh->exchange = exchange; wh->exchange = exchange;
@ -193,8 +194,8 @@ TALER_EXCHANGE_withdraw (
wh->ps = *ps; wh->ps = *ps;
wh->ach = ach; wh->ach = ach;
GNUNET_assert ( (pk->age_restricted && (NULL != ach)) || GNUNET_assert ( (age_restricted && (NULL != ach)) ||
(! pk->age_restricted && (NULL == ach)) ); (! age_restricted && (NULL == ach)));
if (GNUNET_OK != if (GNUNET_OK !=
TALER_planchet_prepare (&pk->key, TALER_planchet_prepare (&pk->key,

View File

@ -997,6 +997,7 @@ melt_run (void *cls,
const struct TALER_DenominationSignature *melt_sig; const struct TALER_DenominationSignature *melt_sig;
const struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub; const struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub;
const struct TALER_TESTING_Command *coin_command; const struct TALER_TESTING_Command *coin_command;
bool age_restricted;
if (NULL == (coin_command if (NULL == (coin_command
= TALER_TESTING_interpreter_lookup_command = TALER_TESTING_interpreter_lookup_command
@ -1026,6 +1027,7 @@ melt_run (void *cls,
TALER_TESTING_interpreter_fail (rms->is); TALER_TESTING_interpreter_fail (rms->is);
return; return;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_TESTING_get_trait_denom_pub (coin_command, TALER_TESTING_get_trait_denom_pub (coin_command,
0, 0,
@ -1035,9 +1037,11 @@ melt_run (void *cls,
TALER_TESTING_interpreter_fail (rms->is); TALER_TESTING_interpreter_fail (rms->is);
return; return;
} }
/* Melt amount starts with the melt fee of the old coin; we'll add the /* Melt amount starts with the melt fee of the old coin; we'll add the
values and withdraw fees of the fresh coins next */ values and withdraw fees of the fresh coins next */
melt_amount = melt_denom_pub->fee_refresh; melt_amount = melt_denom_pub->fee_refresh;
age_restricted = melt_denom_pub->key.age_mask.mask != 0;
for (unsigned int i = 0; i<num_fresh_coins; i++) for (unsigned int i = 0; i<num_fresh_coins; i++)
{ {
const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk; const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk;
@ -1055,7 +1059,7 @@ melt_run (void *cls,
} }
fresh_pk = TALER_TESTING_find_pk (TALER_EXCHANGE_get_keys (is->exchange), fresh_pk = TALER_TESTING_find_pk (TALER_EXCHANGE_get_keys (is->exchange),
&fresh_amount, &fresh_amount,
melt_denom_pub->age_restricted); age_restricted);
if (NULL == fresh_pk) if (NULL == fresh_pk)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -1080,8 +1084,7 @@ melt_run (void *cls,
{ {
struct TALER_AgeCommitment *ac = NULL; struct TALER_AgeCommitment *ac = NULL;
GNUNET_assert (melt_denom_pub->age_restricted == GNUNET_assert (age_restricted == (NULL != rms->age_commitment));
(NULL != rms->age_commitment));
if (NULL != rms->age_commitment) if (NULL != rms->age_commitment)
{ {

View File

@ -464,7 +464,7 @@ withdraw_run (void *cls,
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_age_restriction_commit ( TALER_age_restriction_commit (
&ws->pk->age_mask, &ws->pk->key.age_mask,
ws->age, ws->age,
seed, seed,
ac)); ac));

View File

@ -441,7 +441,7 @@ TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
(GNUNET_TIME_timestamp_cmp (now, (GNUNET_TIME_timestamp_cmp (now,
<, <,
pk->withdraw_valid_until)) && pk->withdraw_valid_until)) &&
(age_restricted == pk->age_restricted) ) (age_restricted == (0 != pk->key.age_mask.mask)) )
return pk; return pk;
} }
/* do 2nd pass to check if expiration times are to blame for /* do 2nd pass to check if expiration times are to blame for
@ -458,7 +458,7 @@ TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
GNUNET_TIME_timestamp_cmp (now, GNUNET_TIME_timestamp_cmp (now,
>, >,
pk->withdraw_valid_until) ) && pk->withdraw_valid_until) ) &&
(age_restricted == pk->age_restricted) ) (age_restricted == (0 != pk->key.age_mask.mask)) )
{ {
GNUNET_log GNUNET_log
(GNUNET_ERROR_TYPE_WARNING, (GNUNET_ERROR_TYPE_WARNING,