[age-withdraw] WIP - database transaction during reveal works now

The test for age-restriction still fail, but the database transactions,
including passing arrays in/out the PQ-helpers works.
This commit is contained in:
Özgür Kesim 2023-07-26 04:04:02 +02:00
parent ac462b2753
commit 1ce9312d02
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7
9 changed files with 98 additions and 51 deletions

View File

@ -71,7 +71,7 @@ struct AgeRevealContext
* The data from the original age-withdraw. Will be retrieved from
* the DB via @a ach and @a reserve_pub.
*/
struct TALER_EXCHANGEDB_AgeWithdraw *commitment;
struct TALER_EXCHANGEDB_AgeWithdraw commitment;
};
@ -106,11 +106,8 @@ parse_age_withdraw_reveal_json (
error = "disclosed_coin_secrets must be an array";
else if (num_entries == 0)
error = "disclosed_coin_secrets must not be empty";
else if (num_entries > TALER_MAX_FRESH_COINS * (TALER_CNC_KAPPA - 1))
else if (num_entries > TALER_MAX_FRESH_COINS)
error = "maximum number of coins that can be withdrawn has been exceeded";
else if (0 != num_entries % (TALER_CNC_KAPPA - 1))
error = "the size of disclosed_coin_secrets must be a multiple of "
TALER_CNC_KAPPA_MINUS_ONE_STR;
if (NULL != error)
{
@ -120,29 +117,26 @@ parse_age_withdraw_reveal_json (
return GNUNET_SYSERR;
}
actx->num_secrets = num_entries;
actx->num_coins = num_entries / (TALER_CNC_KAPPA - 1);
actx->num_secrets = num_entries * (TALER_CNC_KAPPA - 1);
actx->num_coins = num_entries;
}
/* Continue parsing the parts */
{
unsigned int idx = 0;
unsigned int k = 0;
json_t *array = NULL;
json_t *value = NULL;
/* Parse diclosed keys */
actx->disclosed_coin_secrets =
GNUNET_new_array (num_entries,
GNUNET_new_array (actx->num_secrets,
struct TALER_PlanchetMasterSecretP);
json_array_foreach (j_disclosed_coin_secrets, idx, value) {
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL, &actx->disclosed_coin_secrets[idx]),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (value, spec, NULL, NULL))
json_array_foreach (j_disclosed_coin_secrets, idx, array) {
if (! json_is_array (array) ||
(TALER_CNC_KAPPA - 1 != json_array_size (array)))
{
char msg[256] = {0};
GNUNET_snprintf (msg,
@ -153,6 +147,32 @@ parse_age_withdraw_reveal_json (
TALER_EC_GENERIC_PARAMETER_MALFORMED,
msg);
goto EXIT;
}
json_array_foreach (array, k, value)
{
struct TALER_PlanchetMasterSecretP *sec =
&actx->disclosed_coin_secrets[2 * idx + k];
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto (NULL, sec),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (value, spec, NULL, NULL))
{
char msg[256] = {0};
GNUNET_snprintf (msg,
sizeof(msg),
"couldn't parse entry no. %d in array disclosed_coin_secrets[%d]",
k + 1,
idx + 1);
*mhd_ret = TALER_MHD_reply_with_ec (connection,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
msg);
goto EXIT;
}
}
};
}
@ -182,7 +202,7 @@ find_original_commitment (
struct MHD_Connection *connection,
const struct TALER_AgeWithdrawCommitmentHashP *h_commitment,
const struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_EXCHANGEDB_AgeWithdraw **commitment,
struct TALER_EXCHANGEDB_AgeWithdraw *commitment,
MHD_RESULT *result)
{
enum GNUNET_DB_QueryStatus qs;
@ -192,7 +212,7 @@ find_original_commitment (
qs = TEH_plugin->get_age_withdraw (TEH_plugin->cls,
reserve_pub,
h_commitment,
*commitment);
commitment);
switch (qs)
{
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
@ -262,7 +282,13 @@ calculate_blinded_hash (
connection,
result);
if (NULL == denom_key)
{
GNUNET_break_op (0);
*result = TALER_MHD_reply_with_ec (connection,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
NULL);
return GNUNET_SYSERR;
}
/* calculate age commitment hash */
{
@ -351,7 +377,7 @@ calculate_blinded_hash (
GNUNET_assert (GNUNET_OK == ret);
}
return GNUNET_SYSERR;
return ret;
}
@ -417,9 +443,9 @@ verify_commitment_and_max_age (
{
size_t i = 0; /* either 0 or 1, to index into coin_evs */
for (size_t gamma = 0; gamma<TALER_CNC_KAPPA; gamma++)
for (size_t k = 0; k<TALER_CNC_KAPPA; k++)
{
if (gamma == (size_t) commitment->noreveal_index)
if (k == (size_t) commitment->noreveal_index)
{
GNUNET_CRYPTO_hash_context_read (hash_context,
&commitment->h_coin_evs[coin_idx],
@ -432,7 +458,7 @@ verify_commitment_and_max_age (
const struct TALER_PlanchetMasterSecretP *secret;
struct TALER_BlindedCoinHashP bch;
GNUNET_assert (i<2);
GNUNET_assert (2>i);
GNUNET_assert ((TALER_CNC_KAPPA - 1) * num_coins > j);
secret = &disclosed_coin_secrets[j];
@ -478,7 +504,6 @@ verify_commitment_and_max_age (
}
}
return ret;
}
@ -572,7 +597,7 @@ TEH_handler_age_withdraw_reveal (
if (GNUNET_OK !=
verify_commitment_and_max_age (
rc->connection,
actx.commitment,
&actx.commitment,
actx.disclosed_coin_secrets,
actx.num_coins,
&result))
@ -580,7 +605,7 @@ TEH_handler_age_withdraw_reveal (
/* Finally, return the signatures */
result = reply_age_withdraw_reveal_success (rc->connection,
actx.commitment);
&actx.commitment);
} while(0);

View File

@ -29,6 +29,8 @@ BEGIN
'(age_withdraw_id BIGINT GENERATED BY DEFAULT AS IDENTITY'
',h_commitment BYTEA NOT NULL CONSTRAINT h_commitment_length CHECK(LENGTH(h_commitment)=64)'
',max_age SMALLINT NOT NULL CONSTRAINT max_age_positive CHECK(max_age>=0)'
',amount_with_fee_val INT8 NOT NULL'
',amount_with_fee_frac INT4 NOT NULL'
',reserve_pub BYTEA NOT NULL CONSTRAINT reserve_pub_length CHECK(LENGTH(reserve_pub)=32)'
',reserve_sig BYTEA NOT NULL CONSTRAINT reserve_sig_length CHECK(LENGTH(reserve_sig)=64)'
',noreveal_index SMALLINT NOT NULL CONSTRAINT noreveal_index_positive CHECK(noreveal_index>=0)'

View File

@ -143,6 +143,8 @@ WHERE
INSERT INTO exchange.age_withdraw
(h_commitment
,max_age
,amount_with_fee_val
,amount_with_fee_frac
,reserve_pub
,reserve_sig
,noreveal_index
@ -152,6 +154,8 @@ INSERT INTO exchange.age_withdraw
VALUES
(h_commitment
,maximum_age_committed
,amount_val
,amount_frac
,rpub
,rsig
,noreveal_index

View File

@ -52,15 +52,15 @@ TEH_PG_do_age_withdraw (
GNUNET_PQ_query_param_auto_from_type (&commitment->h_commitment),
GNUNET_PQ_query_param_uint16 (&commitment->max_age),
GNUNET_PQ_query_param_uint16 (&commitment->noreveal_index),
GNUNET_PQ_query_param_array_auto_from_type (commitment->num_coins,
commitment->h_coin_evs,
pg->conn),
TALER_PQ_query_param_array_blinded_coin_hash (commitment->num_coins,
commitment->h_coin_evs,
pg->conn),
GNUNET_PQ_query_param_array_uint64 (commitment->num_coins,
commitment->denom_serials,
pg->conn),
GNUNET_PQ_query_param_array_auto_from_type (commitment->num_coins,
commitment->denom_sigs,
pg->conn),
TALER_PQ_query_param_array_blinded_denom_sig (commitment->num_coins,
commitment->denom_sigs,
pg->conn),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {

View File

@ -52,27 +52,26 @@ TEH_PG_get_age_withdraw (
&aw->amount_with_fee),
GNUNET_PQ_result_spec_uint16 ("noreveal_index",
&aw->noreveal_index),
GNUNET_PQ_result_spec_array_fixed_size (
TALER_PQ_result_spec_array_blinded_coin_hash (
pg->conn,
"h_coin_evs",
sizeof(struct TALER_BlindedPlanchet),
"h_blind_evs",
&aw->num_coins,
(void **) &aw->h_coin_evs),
GNUNET_PQ_result_spec_array_fixed_size (
&aw->h_coin_evs),
TALER_PQ_result_spec_array_blinded_denom_sig (
pg->conn,
"denom_sigs",
sizeof(struct TALER_DenominationSignature),
NULL,
(void **) &aw->denom_sigs),
GNUNET_PQ_result_spec_array_fixed_size (
NULL, /* we assume that this is the same size as h_coin_evs */
&aw->denom_sigs),
TALER_PQ_result_spec_array_denom_hash (
pg->conn,
"denom_pub_hashes",
sizeof(struct TALER_DenominationHashP),
NULL,
(void **) &aw->denom_pub_hashes),
NULL, /* we assume that this is the same size as h_coin_evs */
&aw->denom_pub_hashes),
GNUNET_PQ_result_spec_end
};
GNUNET_assert (NULL != aw);
/* Used in #postgres_get_age_withdraw() to
locate the response for a /reserve/$RESERVE_PUB/age-withdraw request
using the hash of the blinded message. Also needed to ensure
@ -87,12 +86,12 @@ TEH_PG_get_age_withdraw (
",amount_with_fee_val"
",amount_with_fee_frac"
",noreveal_index"
",h_coin_evs"
",h_blind_evs"
",denom_sigs"
",ARRAY("
" SELECT denominations.denom_pub_hash FROM ("
" SELECT UNNEST(denomination_serials) AS id,"
" generate_subscripts(denominations_serials, 1) AS nr" /* for order */
" SELECT UNNEST(denom_serials) AS id,"
" generate_subscripts(denom_serials, 1) AS nr" /* for order */
" ) AS denoms"
" LEFT JOIN denominations ON denominations.denominations_serial=denoms.id"
") AS denom_pub_hashes"

View File

@ -3066,6 +3066,7 @@ typedef void
* @param coin_inputs The input for the coins to withdraw, same as in the previous call to /age-withdraw
* @param noreveal_index The index into each of the kappa coin candidates, that should not be revealed to the exchange
* @param h_commitment The commmitment from the previous call to /age-withdraw
* @param reserve_pub The public key of the reserve the original call to /age-withdraw was made to
* @param res_cb A callback for the result, maybe NULL
* @param res_cb_cls A closure for @e res_cb, maybe NULL
* @return a handle for this request; NULL if the argument was invalid.
@ -3080,6 +3081,7 @@ TALER_EXCHANGE_age_withdraw_reveal (
num_coins],
uint8_t noreveal_index,
const struct TALER_AgeWithdrawCommitmentHashP *h_commitment,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_EXCHANGE_AgeWithdrawRevealCallback res_cb,
void *res_cb_cls);

View File

@ -47,6 +47,9 @@ struct TALER_EXCHANGE_AgeWithdrawRevealHandle
/* The age-withdraw commitment */
struct TALER_AgeWithdrawCommitmentHashP h_commitment;
/* The reserve's public key */
const struct TALER_ReservePublicKeyP *reserve_pub;
/* Number of coins */
size_t num_coins;
@ -231,7 +234,7 @@ handle_age_withdraw_reveal_finished (
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, the exchange basically just says
that it doesn't know this age-withraw commitment. */
that it doesn't know this age-withdraw commitment. */
awr.hr.ec = TALER_JSON_get_error_code (j_response);
awr.hr.hint = TALER_JSON_get_error_hint (j_response);
break;
@ -299,7 +302,7 @@ prepare_url (
*end = '\0';
GNUNET_snprintf (arg_str,
sizeof (arg_str),
"age-withraw/%s/reveal",
"age-withdraw/%s/reveal",
pub_str);
awrh->request_url = TALER_url_join (exchange_url,
@ -343,6 +346,9 @@ perform_protocol (
} \
} while(0)
j_array_of_secrets = json_array ();
FAIL_IF (NULL == j_array_of_secrets);
for (size_t n = 0; n < awrh->num_coins; n++)
{
const struct TALER_PlanchetMasterSecretP *secrets =
@ -369,6 +375,8 @@ perform_protocol (
j_secrets));
}
j_request_body = GNUNET_JSON_PACK (
GNUNET_JSON_pack_data_auto ("reserve_pub",
awrh->reserve_pub),
GNUNET_JSON_pack_array_steal ("disclosed_coin_secrets",
j_array_of_secrets));
FAIL_IF (NULL == j_request_body);
@ -418,6 +426,7 @@ TALER_EXCHANGE_age_withdraw_reveal (
num_coins],
uint8_t noreveal_index,
const struct TALER_AgeWithdrawCommitmentHashP *h_commitment,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_EXCHANGE_AgeWithdrawRevealCallback reveal_cb,
void *reveal_cb_cls)
{
@ -429,6 +438,7 @@ TALER_EXCHANGE_age_withdraw_reveal (
awrh->coins_input = coins_input;
awrh->callback = reveal_cb;
awrh->callback_cls = reveal_cb_cls;
awrh->reserve_pub = reserve_pub;
if (GNUNET_OK !=
prepare_url (exchange_url,

View File

@ -290,7 +290,7 @@ run (void *cls,
MHD_HTTP_CONFLICT,
"EUR:10",
NULL),
TALER_TESTING_cmd_age_withdraw ("age-withdraw-coin-1",
TALER_TESTING_cmd_age_withdraw ("age-withdraw-coins-1",
"create-reserve-kyc-1",
8,
MHD_HTTP_OK,
@ -298,6 +298,10 @@ run (void *cls,
"EUR:5",
"EUR:5",
NULL),
/* FIXME[oec]: failing */
TALER_TESTING_cmd_age_withdraw_reveal ("age-withdraw-coins-reveal-1",
"age-withdraw-coins-1",
MHD_HTTP_OK),
TALER_TESTING_cmd_end (),
};

View File

@ -629,8 +629,8 @@ age_withdraw_reveal_run (
* Get the command and state for the previous call to "age witdraw"
*/
age_withdraw_cmd =
TALER_TESTING_interpreter_get_command (is,
awrs->age_withdraw_reference);
TALER_TESTING_interpreter_lookup_command (is,
awrs->age_withdraw_reference);
if (NULL == age_withdraw_cmd)
{
GNUNET_break (0);
@ -649,6 +649,7 @@ age_withdraw_reveal_run (
aws->coin_inputs,
aws->noreveal_index,
&aws->h_commitment,
&aws->reserve_pub,
age_withdraw_reveal_cb,
awrs);
}