aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-pay.c66
-rw-r--r--src/backend/taler-merchant-httpd_private-post-token-families.c18
-rw-r--r--src/backenddb/pg_insert_token_family.c4
-rw-r--r--src/include/taler_merchant_service.h7
-rw-r--r--src/include/taler_merchant_testing_lib.h1
-rw-r--r--src/include/taler_merchantdb_plugin.h5
-rw-r--r--src/lib/merchant_api_post_order_pay.c14
-rw-r--r--src/lib/merchant_api_post_tokenfamilies.c3
-rw-r--r--src/testing/test_merchant_api.c2
-rw-r--r--src/testing/testing_api_cmd_pay_order.c17
-rw-r--r--src/testing/testing_api_cmd_post_tokenfamilies.c8
11 files changed, 75 insertions, 70 deletions
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
index 888ea0ba..08e4b6d8 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -256,6 +256,7 @@ struct TokenUseConfirmation
/**
* Hash of the token issue public key associated with this token.
+ * Note this is set in the validate_tokens phase.
*/
struct TALER_TokenIssuePublicKeyHashP h_issue;
@@ -278,11 +279,6 @@ struct TokenEnvelope
*/
struct TALER_TokenEnvelopeP blinded_token;
- /**
- * Hash of token issue public key.
- */
- struct TALER_TokenIssuePublicKeyHashP h_issue;
-
};
@@ -1515,8 +1511,7 @@ build_token_sigs (struct PayContext *pc)
for (unsigned int i = 0; i < pc->output_tokens_len; i++)
{
json_array_append_new (token_sigs, GNUNET_JSON_PACK (
- GNUNET_JSON_pack_blinded_sig ("blind_sig", pc->output_tokens[i].sig.signature),
- GNUNET_JSON_pack_data_auto ("h_issue", &pc->output_tokens[i].h_issue)
+ GNUNET_JSON_pack_blinded_sig ("blind_sig", pc->output_tokens[i].sig.signature)
));
}
@@ -2308,20 +2303,16 @@ phase_execute_pay_transaction (struct PayContext *pc)
static enum GNUNET_GenericReturnValue
find_valid_input_tokens (struct PayContext *pc,
struct TALER_MerchantContractTokenFamilyKey *key,
+ unsigned int index,
unsigned int expected_num)
{
int num_validated = 0;
struct TokenUseConfirmation *tuc = NULL;
- for (size_t i = 0; i < pc->tokens_cnt; i++)
+ for (unsigned int j = 0; j < expected_num; j++)
{
- if (0 != GNUNET_CRYPTO_hash_cmp (&pc->tokens[i].h_issue.hash,
- &key->pub.public_key->pub_key_hash))
- {
- continue;
- }
+ tuc = &pc->tokens[index + j];
- tuc = &pc->tokens[i];
if (NULL == tuc)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -2338,6 +2329,8 @@ find_valid_input_tokens (struct PayContext *pc,
return GNUNET_NO;
}
+ tuc->h_issue.hash = key->pub.public_key->pub_key_hash;
+
if (GNUNET_OK != TALER_token_issue_verify (&tuc->pub,
&key->pub,
&tuc->unblinded_sig))
@@ -2399,26 +2392,37 @@ find_valid_input_tokens (struct PayContext *pc,
static enum GNUNET_GenericReturnValue
sign_token_envelopes (struct PayContext *pc,
- const char *token_family_slug,
struct TALER_MerchantContractTokenFamilyKey *key,
struct TALER_TokenIssuePrivateKeyP *priv,
+ unsigned int index,
unsigned int expected_num)
{
int num_signed = 0;
- for (unsigned int i = 0; i<pc->token_envelopes_cnt; i++)
+ for (unsigned int j = 0; j<expected_num; j++)
{
- if (0 != GNUNET_CRYPTO_hash_cmp (&pc->token_envelopes[i].h_issue.hash,
- &key->pub.public_key->pub_key_hash))
- {
- continue;
+ unsigned int pos = index + j;
+
+ /* TODO: Handle missing envelopes for non-critical output tokens. */
+ if (pos > pc->token_envelopes_cnt || pos > pc->output_tokens_len) {
+ GNUNET_break (0);
+ pay_end (pc,
+ TALER_MHD_reply_with_error (pc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "Token envelope array is missing "
+ "required token envelope"));
+ return GNUNET_NO;
}
+ struct TokenEnvelope *env = &pc->token_envelopes[index + j];
+ struct SignedOutputToken *output = &pc->output_tokens[index + j];
+
TALER_token_issue_sign (priv,
- &pc->token_envelopes[i].blinded_token,
- &pc->output_tokens[i].sig);
+ &env->blinded_token,
+ &output->sig);
- pc->output_tokens[i].h_issue.hash = pc->token_envelopes[i].h_issue.hash;
+ output->h_issue.hash = key->pub.public_key->pub_key_hash;
num_signed++;
}
@@ -2498,12 +2502,6 @@ phase_validate_tokens (struct PayContext *pc)
selected = pc->choices[pc->choice_index];
- /* 1. Iterate over inputs of selected choice:
- 1.1. Get key for each input.
- 1.2. Check if token signed by this key are valid at the current time.
- 1.3. Iterate over provided tokens and check if required number with matching h_issue are present.
- 1.4. Validate ub_sig with the issue public key, validate token_sig using the token_pub key of the request.
- 1.5. Sum up validated tokens and check if validated_len == tokens_cnt after loop. */
for (unsigned int i = 0; i<selected.inputs_len; i++)
{
struct TALER_MerchantContractInput input = selected.inputs[i];
@@ -2557,6 +2555,7 @@ phase_validate_tokens (struct PayContext *pc)
if (GNUNET_NO == find_valid_input_tokens (pc,
&key,
+ i,
input.details.token.count))
{
/* Error is already scheduled from find_valid_input_token. */
@@ -2621,9 +2620,9 @@ phase_validate_tokens (struct PayContext *pc)
GNUNET_assert (NULL != details.priv.private_key);
if (GNUNET_OK != sign_token_envelopes (pc,
- family.slug,
&key,
&details.priv,
+ i,
output.details.token.count))
{
/* Error is already scheduled from sign_token_envelopes. */
@@ -2704,9 +2703,6 @@ input_tokens_paid_check (
struct TokenUseConfirmation *tuc = &pc->tokens[i];
if ( (0 ==
- GNUNET_CRYPTO_hash_cmp (&tuc->h_issue.hash,
- &h_issue_pub->hash)) &&
- (0 ==
GNUNET_memcmp (&tuc->pub, use_pub)) &&
(0 ==
GNUNET_memcmp (&tuc->sig, use_sig)) &&
@@ -3375,8 +3371,6 @@ phase_parse_pay (struct PayContext *pc)
&tuc->pub),
TALER_JSON_spec_token_issue_sig ("ub_sig",
&tuc->unblinded_sig),
- GNUNET_JSON_spec_fixed_auto ("h_issue",
- &tuc->h_issue),
GNUNET_JSON_spec_end ()
};
enum GNUNET_GenericReturnValue res;
@@ -3445,8 +3439,6 @@ phase_parse_pay (struct PayContext *pc)
struct GNUNET_JSON_Specification ispec[] = {
TALER_JSON_spec_token_envelope ("token_ev",
&ev->blinded_token),
- GNUNET_JSON_spec_fixed_auto ("h_issue",
- &ev->h_issue.hash),
GNUNET_JSON_spec_end ()
};
enum GNUNET_GenericReturnValue res;
diff --git a/src/backend/taler-merchant-httpd_private-post-token-families.c b/src/backend/taler-merchant-httpd_private-post-token-families.c
index 5a342af2..069f6b29 100644
--- a/src/backend/taler-merchant-httpd_private-post-token-families.c
+++ b/src/backend/taler-merchant-httpd_private-post-token-families.c
@@ -97,6 +97,8 @@ TMH_private_post_token_families (const struct TMH_RequestHandler *rh,
&details.valid_before),
GNUNET_JSON_spec_relative_time ("duration",
&details.duration),
+ GNUNET_JSON_spec_relative_time ("rounding",
+ &details.rounding),
GNUNET_JSON_spec_end ()
};
@@ -171,6 +173,22 @@ TMH_private_post_token_families (const struct TMH_RequestHandler *rh,
"description_i18n");
}
+ if ( GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_YEARS, !=, details.rounding) &&
+ GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MONTHS, !=, details.rounding) &&
+ GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_DAYS, !=, details.rounding) &&
+ GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_HOURS, !=, details.rounding) &&
+ GNUNET_TIME_relative_cmp (GNUNET_TIME_UNIT_MINUTES, !=, details.rounding) )
+ {
+ GNUNET_break (0);
+ GNUNET_JSON_parse_free (spec);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Received invalid rounding value: %s\n",
+ GNUNET_STRINGS_relative_time_to_string (details.rounding, GNUNET_YES));
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "rounding");
+ }
/* finally, interact with DB until no serialization error */
for (unsigned int i = 0; i<MAX_RETRIES; i++)
diff --git a/src/backenddb/pg_insert_token_family.c b/src/backenddb/pg_insert_token_family.c
index bf7159b8..f533a2fb 100644
--- a/src/backenddb/pg_insert_token_family.c
+++ b/src/backenddb/pg_insert_token_family.c
@@ -56,6 +56,7 @@ TMH_PG_insert_token_family (void *cls,
GNUNET_PQ_query_param_timestamp (&details->valid_after),
GNUNET_PQ_query_param_timestamp (&details->valid_before),
GNUNET_PQ_query_param_relative_time (&details->duration),
+ GNUNET_PQ_query_param_relative_time (&details->rounding),
GNUNET_PQ_query_param_string (kind),
GNUNET_PQ_query_param_end
};
@@ -72,8 +73,9 @@ TMH_PG_insert_token_family (void *cls,
",valid_after"
",valid_before"
",duration"
+ ",rounding"
",kind)"
- " SELECT merchant_serial, $2, $3, $4, $5, $6, $7, $8, $9"
+ " SELECT merchant_serial, $2, $3, $4, $5, $6, $7, $8, $9, $10"
" FROM merchant_instances"
" WHERE merchant_id=$1");
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
index dc79303f..52034f63 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -2069,6 +2069,7 @@ typedef void
* @param valid_after when the token family becomes valid
* @param valid_before when the token family expires
* @param duration how long tokens issued by this token family are valid for
+ * @param rounding rounding duration of token family
* @param kind kind of token family, "subscription" or "discount"
* @param cb function to call with the backend's result
* @param cb_cls closure for @a cb
@@ -2085,6 +2086,7 @@ TALER_MERCHANT_token_families_post (
struct GNUNET_TIME_Timestamp valid_after,
struct GNUNET_TIME_Timestamp valid_before,
struct GNUNET_TIME_Relative duration,
+ struct GNUNET_TIME_Relative rounding,
const char *kind,
TALER_MERCHANT_TokenFamiliesPostCallback cb,
void *cb_cls);
@@ -3352,11 +3354,6 @@ struct TALER_MERCHANT_OutputToken
struct TALER_TokenEnvelopeP envelope;
/**
- * Hash of the corresponding token issue public key.
- */
- struct TALER_TokenIssuePublicKeyHashP h_issue;
-
- /**
* Blinded issue signature made by the merchant.
*/
struct TALER_TokenIssueBlindSignatureP blinded_sig;
diff --git a/src/include/taler_merchant_testing_lib.h b/src/include/taler_merchant_testing_lib.h
index 20ac3076..d4b5bd27 100644
--- a/src/include/taler_merchant_testing_lib.h
+++ b/src/include/taler_merchant_testing_lib.h
@@ -1572,6 +1572,7 @@ TALER_TESTING_cmd_merchant_post_tokenfamilies (
struct GNUNET_TIME_Timestamp valid_after,
struct GNUNET_TIME_Timestamp valid_before,
struct GNUNET_TIME_Relative duration,
+ struct GNUNET_TIME_Relative rounding,
const char *kind);
/* ****** Webhooks ******* */
diff --git a/src/include/taler_merchantdb_plugin.h b/src/include/taler_merchantdb_plugin.h
index f63fcd99..e7f3090a 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -1148,6 +1148,11 @@ struct TALER_MERCHANTDB_TokenFamilyDetails
struct GNUNET_TIME_Relative duration;
/**
+ * Rounding duration of the token family.
+ */
+ struct GNUNET_TIME_Relative rounding;
+
+ /**
* Token family kind.
*/
enum TALER_MERCHANTDB_TokenFamilyKind kind;
diff --git a/src/lib/merchant_api_post_order_pay.c b/src/lib/merchant_api_post_order_pay.c
index 33592c08..b34240b6 100644
--- a/src/lib/merchant_api_post_order_pay.c
+++ b/src/lib/merchant_api_post_order_pay.c
@@ -155,8 +155,6 @@ parse_tokens (const json_t *token_sigs,
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_blinded_token_issue_sig ("blind_sig",
&token->blinded_sig),
- GNUNET_JSON_spec_fixed_auto ("h_issue",
- &token->h_issue),
GNUNET_JSON_spec_end ()
};
@@ -480,10 +478,7 @@ TALER_MERCHANT_order_pay_frontend (
GNUNET_JSON_pack_data_auto ("token_pub",
&ut->token_pub),
TALER_JSON_pack_token_issue_sig ("ub_sig",
- &ut->ub_sig),
- /* TODO: Check if we need a more specific hash, similar to TALER_denom_pub_hash () */
- GNUNET_JSON_pack_data_auto ("h_issue",
- &ut->issue_pub.public_key->pub_key_hash));
+ &ut->ub_sig));
if (0 !=
json_array_append_new (j_tokens,
j_token))
@@ -544,8 +539,6 @@ TALER_MERCHANT_order_pay_frontend (
GNUNET_memcpy (oph->coins,
coins,
num_coins * sizeof (struct TALER_MERCHANT_PaidCoin));
- /* TODO: Copy tokens_evs to pay handle so they
- can be unblinded in the callback. */
eh = TALER_MERCHANT_curl_easy_get_ (oph->url);
if (GNUNET_OK !=
@@ -626,9 +619,8 @@ TALER_MERCHANT_order_pay (
j_token_ev = GNUNET_JSON_PACK (
TALER_JSON_pack_token_envelope ("token_ev",
- &ev->envelope),
- GNUNET_JSON_pack_data_auto ("h_issue",
- &ev->h_issue.hash));
+ &ev->envelope));
+
if (0 !=
json_array_append_new (j_output_tokens,
j_token_ev))
diff --git a/src/lib/merchant_api_post_tokenfamilies.c b/src/lib/merchant_api_post_tokenfamilies.c
index 0c5e18c2..95cbd13b 100644
--- a/src/lib/merchant_api_post_tokenfamilies.c
+++ b/src/lib/merchant_api_post_tokenfamilies.c
@@ -169,6 +169,7 @@ TALER_MERCHANT_token_families_post (
struct GNUNET_TIME_Timestamp valid_after,
struct GNUNET_TIME_Timestamp valid_before,
struct GNUNET_TIME_Relative duration,
+ struct GNUNET_TIME_Relative rounding,
const char *kind,
TALER_MERCHANT_TokenFamiliesPostCallback cb,
void *cb_cls)
@@ -193,6 +194,8 @@ TALER_MERCHANT_token_families_post (
valid_before),
GNUNET_JSON_pack_time_rel ("duration",
duration),
+ GNUNET_JSON_pack_time_rel ("rounding",
+ rounding),
GNUNET_JSON_pack_string ("kind",
kind));
handle = GNUNET_new (struct TALER_MERCHANT_TokenFamiliesPostHandle);
diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c
index fdf5e7f4..28c32c2f 100644
--- a/src/testing/test_merchant_api.c
+++ b/src/testing/test_merchant_api.c
@@ -1698,6 +1698,7 @@ run (void *cls,
GNUNET_TIME_absolute_add (
GNUNET_TIME_timestamp_get ().abs_time, GNUNET_TIME_UNIT_YEARS)),
GNUNET_TIME_UNIT_MONTHS,
+ GNUNET_TIME_UNIT_MONTHS,
"subscription"),
TALER_TESTING_cmd_merchant_post_orders_choices ("create-order-with-upcoming-output",
cred.cfg,
@@ -1720,6 +1721,7 @@ run (void *cls,
GNUNET_TIME_UNIT_ZERO_TS,
GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_YEARS),
GNUNET_TIME_UNIT_MONTHS,
+ GNUNET_TIME_UNIT_MONTHS,
"subscription"),
TALER_TESTING_cmd_merchant_post_orders_choices ("create-order-with-output",
cred.cfg,
diff --git a/src/testing/testing_api_cmd_pay_order.c b/src/testing/testing_api_cmd_pay_order.c
index dbcb5b24..97d0b66a 100644
--- a/src/testing/testing_api_cmd_pay_order.c
+++ b/src/testing/testing_api_cmd_pay_order.c
@@ -512,25 +512,11 @@ pay_cb (void *cls,
{
struct TALER_MERCHANT_PrivateTokenDetails *details =
&ps->issued_tokens[i];
+
/* The issued tokens should be in the
same order as the provided envelopes. */
- if (1 == GNUNET_CRYPTO_hash_cmp(
- &details->issue_pub.public_key->pub_key_hash,
- &pr->details.ok.tokens[i].h_issue.hash))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected token issued. "
- "Expected token with hash %s but got token with hash %s.\n",
- GNUNET_h2s (&details->issue_pub.public_key->pub_key_hash),
- GNUNET_h2s (&pr->details.ok.tokens[i].h_issue.hash));
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (ps->is);
- return;
- }
-
ps->issued_tokens[i].blinded_sig = pr->details.ok.tokens[i].blinded_sig;
-
if (GNUNET_OK !=
TALER_token_issue_sig_unblind (&details->issue_sig,
&details->blinded_sig,
@@ -880,7 +866,6 @@ pay_run (void *cls,
ps->num_issued_tokens);
for (unsigned int i = 0; i<len_output_tokens; i++)
{
- output_tokens[i].h_issue.hash = ps->issued_tokens[i].issue_pub.public_key->pub_key_hash;
output_tokens[i].envelope.blinded_pub = ps->issued_tokens[i].envelope.blinded_pub;
}
diff --git a/src/testing/testing_api_cmd_post_tokenfamilies.c b/src/testing/testing_api_cmd_post_tokenfamilies.c
index aafff9ef..c24b98db 100644
--- a/src/testing/testing_api_cmd_post_tokenfamilies.c
+++ b/src/testing/testing_api_cmd_post_tokenfamilies.c
@@ -92,6 +92,11 @@ struct PostTokenFamiliesState
struct GNUNET_TIME_Relative duration;
/**
+ * Rounding duation of token family.
+ */
+ struct GNUNET_TIME_Relative rounding;
+
+ /**
* Kind of the token family. "subscription" or "discount".
*/
const char *kind;
@@ -166,6 +171,7 @@ post_tokenfamilies_run (void *cls,
state->valid_after,
state->valid_before,
state->duration,
+ state->rounding,
state->kind,
&post_tokenfamilies_cb,
state);
@@ -241,6 +247,7 @@ TALER_TESTING_cmd_merchant_post_tokenfamilies (
struct GNUNET_TIME_Timestamp valid_after,
struct GNUNET_TIME_Timestamp valid_before,
struct GNUNET_TIME_Relative duration,
+ struct GNUNET_TIME_Relative rounding,
const char *kind) /* "subscription" or "discount" */
{
struct PostTokenFamiliesState *state;
@@ -257,6 +264,7 @@ TALER_TESTING_cmd_merchant_post_tokenfamilies (
state->valid_after = valid_after;
state->valid_before = valid_before;
state->duration = duration;
+ state->rounding = rounding;
state->kind = kind;
{
struct TALER_TESTING_Command cmd = {