[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 data from the original age-withdraw. Will be retrieved from
* the DB via @a ach and @a reserve_pub. * 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"; error = "disclosed_coin_secrets must be an array";
else if (num_entries == 0) else if (num_entries == 0)
error = "disclosed_coin_secrets must not be empty"; 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"; 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) if (NULL != error)
{ {
@ -120,29 +117,26 @@ parse_age_withdraw_reveal_json (
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
actx->num_secrets = num_entries; actx->num_secrets = num_entries * (TALER_CNC_KAPPA - 1);
actx->num_coins = num_entries / (TALER_CNC_KAPPA - 1); actx->num_coins = num_entries;
} }
/* Continue parsing the parts */ /* Continue parsing the parts */
{ {
unsigned int idx = 0; unsigned int idx = 0;
unsigned int k = 0;
json_t *array = NULL;
json_t *value = NULL; json_t *value = NULL;
/* Parse diclosed keys */ /* Parse diclosed keys */
actx->disclosed_coin_secrets = actx->disclosed_coin_secrets =
GNUNET_new_array (num_entries, GNUNET_new_array (actx->num_secrets,
struct TALER_PlanchetMasterSecretP); struct TALER_PlanchetMasterSecretP);
json_array_foreach (j_disclosed_coin_secrets, idx, value) { json_array_foreach (j_disclosed_coin_secrets, idx, array) {
struct GNUNET_JSON_Specification spec[] = { if (! json_is_array (array) ||
GNUNET_JSON_spec_fixed_auto (NULL, &actx->disclosed_coin_secrets[idx]), (TALER_CNC_KAPPA - 1 != json_array_size (array)))
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
GNUNET_JSON_parse (value, spec, NULL, NULL))
{ {
char msg[256] = {0}; char msg[256] = {0};
GNUNET_snprintf (msg, GNUNET_snprintf (msg,
@ -153,6 +147,32 @@ parse_age_withdraw_reveal_json (
TALER_EC_GENERIC_PARAMETER_MALFORMED, TALER_EC_GENERIC_PARAMETER_MALFORMED,
msg); msg);
goto EXIT; 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, struct MHD_Connection *connection,
const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, const struct TALER_AgeWithdrawCommitmentHashP *h_commitment,
const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_EXCHANGEDB_AgeWithdraw **commitment, struct TALER_EXCHANGEDB_AgeWithdraw *commitment,
MHD_RESULT *result) MHD_RESULT *result)
{ {
enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qs;
@ -192,7 +212,7 @@ find_original_commitment (
qs = TEH_plugin->get_age_withdraw (TEH_plugin->cls, qs = TEH_plugin->get_age_withdraw (TEH_plugin->cls,
reserve_pub, reserve_pub,
h_commitment, h_commitment,
*commitment); commitment);
switch (qs) switch (qs)
{ {
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
@ -262,7 +282,13 @@ calculate_blinded_hash (
connection, connection,
result); result);
if (NULL == denom_key) 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; return GNUNET_SYSERR;
}
/* calculate age commitment hash */ /* calculate age commitment hash */
{ {
@ -351,7 +377,7 @@ calculate_blinded_hash (
GNUNET_assert (GNUNET_OK == ret); 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 */ 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, GNUNET_CRYPTO_hash_context_read (hash_context,
&commitment->h_coin_evs[coin_idx], &commitment->h_coin_evs[coin_idx],
@ -432,7 +458,7 @@ verify_commitment_and_max_age (
const struct TALER_PlanchetMasterSecretP *secret; const struct TALER_PlanchetMasterSecretP *secret;
struct TALER_BlindedCoinHashP bch; struct TALER_BlindedCoinHashP bch;
GNUNET_assert (i<2); GNUNET_assert (2>i);
GNUNET_assert ((TALER_CNC_KAPPA - 1) * num_coins > j); GNUNET_assert ((TALER_CNC_KAPPA - 1) * num_coins > j);
secret = &disclosed_coin_secrets[j]; secret = &disclosed_coin_secrets[j];
@ -478,7 +504,6 @@ verify_commitment_and_max_age (
} }
} }
return ret; return ret;
} }
@ -572,7 +597,7 @@ TEH_handler_age_withdraw_reveal (
if (GNUNET_OK != if (GNUNET_OK !=
verify_commitment_and_max_age ( verify_commitment_and_max_age (
rc->connection, rc->connection,
actx.commitment, &actx.commitment,
actx.disclosed_coin_secrets, actx.disclosed_coin_secrets,
actx.num_coins, actx.num_coins,
&result)) &result))
@ -580,7 +605,7 @@ TEH_handler_age_withdraw_reveal (
/* Finally, return the signatures */ /* Finally, return the signatures */
result = reply_age_withdraw_reveal_success (rc->connection, result = reply_age_withdraw_reveal_success (rc->connection,
actx.commitment); &actx.commitment);
} while(0); } while(0);

View File

@ -29,6 +29,8 @@ BEGIN
'(age_withdraw_id BIGINT GENERATED BY DEFAULT AS IDENTITY' '(age_withdraw_id BIGINT GENERATED BY DEFAULT AS IDENTITY'
',h_commitment BYTEA NOT NULL CONSTRAINT h_commitment_length CHECK(LENGTH(h_commitment)=64)' ',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)' ',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_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)' ',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)' ',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 INSERT INTO exchange.age_withdraw
(h_commitment (h_commitment
,max_age ,max_age
,amount_with_fee_val
,amount_with_fee_frac
,reserve_pub ,reserve_pub
,reserve_sig ,reserve_sig
,noreveal_index ,noreveal_index
@ -152,6 +154,8 @@ INSERT INTO exchange.age_withdraw
VALUES VALUES
(h_commitment (h_commitment
,maximum_age_committed ,maximum_age_committed
,amount_val
,amount_frac
,rpub ,rpub
,rsig ,rsig
,noreveal_index ,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_auto_from_type (&commitment->h_commitment),
GNUNET_PQ_query_param_uint16 (&commitment->max_age), GNUNET_PQ_query_param_uint16 (&commitment->max_age),
GNUNET_PQ_query_param_uint16 (&commitment->noreveal_index), GNUNET_PQ_query_param_uint16 (&commitment->noreveal_index),
GNUNET_PQ_query_param_array_auto_from_type (commitment->num_coins, TALER_PQ_query_param_array_blinded_coin_hash (commitment->num_coins,
commitment->h_coin_evs, commitment->h_coin_evs,
pg->conn), pg->conn),
GNUNET_PQ_query_param_array_uint64 (commitment->num_coins, GNUNET_PQ_query_param_array_uint64 (commitment->num_coins,
commitment->denom_serials, commitment->denom_serials,
pg->conn), pg->conn),
GNUNET_PQ_query_param_array_auto_from_type (commitment->num_coins, TALER_PQ_query_param_array_blinded_denom_sig (commitment->num_coins,
commitment->denom_sigs, commitment->denom_sigs,
pg->conn), pg->conn),
GNUNET_PQ_query_param_end GNUNET_PQ_query_param_end
}; };
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {

View File

@ -52,27 +52,26 @@ TEH_PG_get_age_withdraw (
&aw->amount_with_fee), &aw->amount_with_fee),
GNUNET_PQ_result_spec_uint16 ("noreveal_index", GNUNET_PQ_result_spec_uint16 ("noreveal_index",
&aw->noreveal_index), &aw->noreveal_index),
GNUNET_PQ_result_spec_array_fixed_size ( TALER_PQ_result_spec_array_blinded_coin_hash (
pg->conn, pg->conn,
"h_coin_evs", "h_blind_evs",
sizeof(struct TALER_BlindedPlanchet),
&aw->num_coins, &aw->num_coins,
(void **) &aw->h_coin_evs), &aw->h_coin_evs),
GNUNET_PQ_result_spec_array_fixed_size ( TALER_PQ_result_spec_array_blinded_denom_sig (
pg->conn, pg->conn,
"denom_sigs", "denom_sigs",
sizeof(struct TALER_DenominationSignature), NULL, /* we assume that this is the same size as h_coin_evs */
NULL, &aw->denom_sigs),
(void **) &aw->denom_sigs), TALER_PQ_result_spec_array_denom_hash (
GNUNET_PQ_result_spec_array_fixed_size (
pg->conn, pg->conn,
"denom_pub_hashes", "denom_pub_hashes",
sizeof(struct TALER_DenominationHashP), NULL, /* we assume that this is the same size as h_coin_evs */
NULL, &aw->denom_pub_hashes),
(void **) &aw->denom_pub_hashes),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
}; };
GNUNET_assert (NULL != aw);
/* Used in #postgres_get_age_withdraw() to /* Used in #postgres_get_age_withdraw() to
locate the response for a /reserve/$RESERVE_PUB/age-withdraw request locate the response for a /reserve/$RESERVE_PUB/age-withdraw request
using the hash of the blinded message. Also needed to ensure 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_val"
",amount_with_fee_frac" ",amount_with_fee_frac"
",noreveal_index" ",noreveal_index"
",h_coin_evs" ",h_blind_evs"
",denom_sigs" ",denom_sigs"
",ARRAY(" ",ARRAY("
" SELECT denominations.denom_pub_hash FROM (" " SELECT denominations.denom_pub_hash FROM ("
" SELECT UNNEST(denomination_serials) AS id," " SELECT UNNEST(denom_serials) AS id,"
" generate_subscripts(denominations_serials, 1) AS nr" /* for order */ " generate_subscripts(denom_serials, 1) AS nr" /* for order */
" ) AS denoms" " ) AS denoms"
" LEFT JOIN denominations ON denominations.denominations_serial=denoms.id" " LEFT JOIN denominations ON denominations.denominations_serial=denoms.id"
") AS denom_pub_hashes" ") 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 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 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 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 A callback for the result, maybe NULL
* @param res_cb_cls A closure for @e res_cb, 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. * @return a handle for this request; NULL if the argument was invalid.
@ -3080,6 +3081,7 @@ TALER_EXCHANGE_age_withdraw_reveal (
num_coins], num_coins],
uint8_t noreveal_index, uint8_t noreveal_index,
const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, const struct TALER_AgeWithdrawCommitmentHashP *h_commitment,
const struct TALER_ReservePublicKeyP *reserve_pub,
TALER_EXCHANGE_AgeWithdrawRevealCallback res_cb, TALER_EXCHANGE_AgeWithdrawRevealCallback res_cb,
void *res_cb_cls); void *res_cb_cls);

View File

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

View File

@ -290,7 +290,7 @@ run (void *cls,
MHD_HTTP_CONFLICT, MHD_HTTP_CONFLICT,
"EUR:10", "EUR:10",
NULL), NULL),
TALER_TESTING_cmd_age_withdraw ("age-withdraw-coin-1", TALER_TESTING_cmd_age_withdraw ("age-withdraw-coins-1",
"create-reserve-kyc-1", "create-reserve-kyc-1",
8, 8,
MHD_HTTP_OK, MHD_HTTP_OK,
@ -298,6 +298,10 @@ run (void *cls,
"EUR:5", "EUR:5",
"EUR:5", "EUR:5",
NULL), 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 (), 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" * Get the command and state for the previous call to "age witdraw"
*/ */
age_withdraw_cmd = age_withdraw_cmd =
TALER_TESTING_interpreter_get_command (is, TALER_TESTING_interpreter_lookup_command (is,
awrs->age_withdraw_reference); awrs->age_withdraw_reference);
if (NULL == age_withdraw_cmd) if (NULL == age_withdraw_cmd)
{ {
GNUNET_break (0); GNUNET_break (0);
@ -649,6 +649,7 @@ age_withdraw_reveal_run (
aws->coin_inputs, aws->coin_inputs,
aws->noreveal_index, aws->noreveal_index,
&aws->h_commitment, &aws->h_commitment,
&aws->reserve_pub,
age_withdraw_reveal_cb, age_withdraw_reveal_cb,
awrs); awrs);
} }