aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-pay.c130
1 files changed, 130 insertions, 0 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 14edfd55..2bdf891f 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -25,6 +25,8 @@
* @author Florian Dold
*/
#include "platform.h"
+#include <gnunet/gnunet_json_lib.h>
+#include <stdint.h>
#include <taler/taler_dbevents.h>
#include <taler/taler_signatures.h>
#include <taler/taler_json_lib.h>
@@ -46,6 +48,12 @@
#define MAX_COIN_ALLOWED_COINS 1024
/**
+ * TODO: What is a good value for this?
+ * Maximum number of tokens that we allow per transaction
+ */
+#define MAX_TOKEN_ALLOWED_TOKENS 128
+
+/**
* How often do we ask the exchange again about our
* KYC status? Very rarely, as if the user actively
* changes it, we should usually notice anyway.
@@ -202,6 +210,36 @@ struct DepositConfirmation
};
+struct TokenUseConfirmation
+{
+
+ /**
+ * Slug of the token family this token belongs to.
+ */
+ char *slug;
+
+ /**
+ * Signature on the deposit request made using the token private key.
+ */
+ struct TALER_TokenUseSignature sig;
+
+ /**
+ * Public key of the token.
+ */
+ struct TALER_TokenUsePublicKey pub;
+
+ /**
+ * Unblinded signature done by the merchant.
+ */
+ struct TALER_TokenIssueSignature unblinded_sig;
+
+ /**
+ * Hash of the token issue public key associated with this token.
+ */
+ struct TALER_TokenIssuePublicKeyHash h_issue;
+
+};
+
/**
* Information kept during a pay request for each exchange.
@@ -274,6 +312,11 @@ struct PayContext
struct DepositConfirmation *dc;
/**
+ * Array with @e tokens_cnt tokens we are using.
+ */
+ struct TokenUseConfirmation *tokens;
+
+ /**
* MHD connection to return to
*/
struct MHD_Connection *connection;
@@ -302,6 +345,11 @@ struct PayContext
struct MHD_Response *response;
/**
+ * Index of selected choice in the @e contract_terms choices array.
+ */
+ int64_t choice_index;
+
+ /**
* Our contract (or NULL if not available).
*/
json_t *contract_terms;
@@ -421,6 +469,12 @@ struct PayContext
size_t coins_cnt;
/**
+ * Number of tokens this payment uses. Length
+ * of the @e tokens array.
+ */
+ size_t tokens_cnt;
+
+ /**
* Number of exchanges involved in the payment. Length
* of the @e eg array.
*/
@@ -2405,6 +2459,7 @@ phase_parse_pay (struct PayContext *pc)
{
const char *session_id = NULL;
const json_t *coins;
+ const json_t *tokens;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_array_const ("coins",
&coins),
@@ -2412,6 +2467,14 @@ phase_parse_pay (struct PayContext *pc)
GNUNET_JSON_spec_string ("session_id",
&session_id),
NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_int64 ("choice_index",
+ &pc->choice_index),
+ NULL),
+ GNUNET_JSON_spec_mark_optional (
+ GNUNET_JSON_spec_array_const ("tokens",
+ &tokens),
+ NULL),
GNUNET_JSON_spec_end ()
};
@@ -2456,10 +2519,26 @@ phase_parse_pay (struct PayContext *pc)
return;
}
+ pc->tokens_cnt = json_array_size (tokens);
+ if (pc->tokens_cnt > MAX_TOKEN_ALLOWED_TOKENS)
+ {
+ GNUNET_break_op (0);
+ pay_end (pc,
+ TALER_MHD_reply_with_error (
+ pc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "'tokens' array too long"));
+ return;
+ }
+
/* note: 1 coin = 1 deposit confirmation expected */
pc->dc = GNUNET_new_array (pc->coins_cnt,
struct DepositConfirmation);
+ pc->tokens = GNUNET_new_array (pc->tokens_cnt,
+ struct TokenUseConfirmation);
+
/* This loop populates the array 'dc' in 'pc' */
{
unsigned int coins_index;
@@ -2574,6 +2653,57 @@ phase_parse_pay (struct PayContext *pc)
}
}
}
+
+ /* This look populates the array 'tokens' in 'pc' */
+ {
+ unsigned int tokens_index;
+ json_t *token;
+
+ json_array_foreach (tokens, tokens_index, token)
+ {
+ struct TokenUseConfirmation *tuc = &pc->tokens[tokens_index];
+ struct GNUNET_JSON_Specification ispec[] = {
+ GNUNET_JSON_spec_fixed_auto ("token_sig",
+ &tuc->sig),
+ GNUNET_JSON_spec_fixed_auto ("token_pub",
+ &tuc->pub),
+ // TALER_JSON_spec_denom_sig ("ub_sig",
+ // &tuc->unblinded_sig),
+ GNUNET_JSON_spec_fixed_auto ("h_issue",
+ &tuc->h_issue),
+ GNUNET_JSON_spec_end ()
+ };
+ enum GNUNET_GenericReturnValue res;
+
+ res = TALER_MHD_parse_json_data (pc->connection,
+ token,
+ ispec);
+ if (GNUNET_YES != res)
+ {
+ GNUNET_break_op (0);
+ pay_end (pc,
+ (GNUNET_NO == res)
+ ? MHD_YES
+ : MHD_NO);
+ return;
+ }
+ for (unsigned int j = 0; j<tokens_index; j++)
+ {
+ if (0 ==
+ GNUNET_memcmp (&tuc->pub,
+ &pc->tokens[j].pub))
+ {
+ GNUNET_break_op (0);
+ pay_end (pc,
+ TALER_MHD_reply_with_error (pc->connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "duplicate token in list"));
+ return;
+ }
+ }
+ }
+ }
pc->phase = PP_CHECK_CONTRACT;
}