gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[merchant] branch master updated: mostly dead code elimination


From: gnunet
Subject: [merchant] branch master updated: mostly dead code elimination
Date: Sun, 02 Feb 2025 16:42:10 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new 399592ff mostly dead code elimination
399592ff is described below

commit 399592ff65e78f56c2b51084d8f8eb3da8d00c58
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Feb 2 16:42:03 2025 +0100

    mostly dead code elimination
---
 src/backend/taler-merchant-httpd_contract.c        | 387 ---------------------
 src/backend/taler-merchant-httpd_contract.h        |  79 -----
 .../taler-merchant-httpd_private-post-orders.c     | 241 +------------
 src/include/taler_merchant_util.h                  |  26 ++
 src/testing/test_merchant_api.c                    |   2 +-
 src/util/Makefile.am                               |   3 +-
 src/util/contract_parse.c                          |  52 +--
 src/util/json.c                                    | 171 +++++++++
 8 files changed, 225 insertions(+), 736 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_contract.c 
b/src/backend/taler-merchant-httpd_contract.c
index ae5bdd6c..983ee576 100644
--- a/src/backend/taler-merchant-httpd_contract.c
+++ b/src/backend/taler-merchant-httpd_contract.c
@@ -26,393 +26,6 @@
 #include "taler-merchant-httpd_contract.h"
 
 
-enum TALER_MERCHANT_ContractInputType
-TMH_contract_input_type_from_string (const char *str)
-{
-  /* For now, only 'token' is the only supported option. */
-  if (0 == strcmp ("token", str))
-  {
-    return TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN;
-  }
-
-  return TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID;
-}
-
-
-enum TALER_MERCHANT_ContractOutputType
-TMH_contract_output_type_from_string (const char *str)
-{
-  /* For now, only 'token' is the only supported option. */
-  if (0 == strcmp ("token", str))
-  {
-    return TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN;
-  }
-  return TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID;
-}
-
-
-const char *
-TMH_string_from_contract_input_type (enum TALER_MERCHANT_ContractInputType t)
-{
-  switch (t)
-  {
-  case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN:
-    return "token";
-#if FUTURE
-  case TALER_MERCHANT_CONTRACT_INPUT_TYPE_COIN:
-    return "coin";
-#endif
-  default:
-    return "invalid";
-  }
-}
-
-
-const char *
-TMH_string_from_contract_output_type (enum TALER_MERCHANT_ContractOutputType t)
-{
-  switch (t)
-  {
-  case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
-    return "token";
-#if FUTURE
-  case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_COIN:
-    return "coin";
-#endif
-  case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
-    return "donation_receipt";
-  default:
-    return "invalid";
-  }
-}
-
-
-/**
- * Parse given JSON object to choices array.
- *
- * @param cls closure, pointer to array length
- * @param root the json array representing the choices
- * @param[out] ospec where to write the data
- * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
- */
-static enum GNUNET_GenericReturnValue
-parse_choices (void *cls,
-               json_t *root,
-               struct GNUNET_JSON_Specification *ospec)
-{
-  struct TALER_MERCHANT_ContractChoice **choices = ospec->ptr;
-  unsigned int *choices_len = cls;
-
-  if (! json_is_array (root))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-
-  GNUNET_array_grow (*choices,
-                     *choices_len,
-                     json_array_size (root));
-
-  for (unsigned int i = 0; i<*choices_len; i++)
-  {
-    struct TALER_MERCHANT_ContractChoice *choice = &(*choices)[i];
-    const json_t *jinputs;
-    const json_t *joutputs;
-    struct GNUNET_JSON_Specification spec[] = {
-      TALER_JSON_spec_amount_any ("amount",
-                                  &choice->amount),
-      GNUNET_JSON_spec_mark_optional (
-        TALER_JSON_spec_amount_any ("max_fee",
-                                    &choice->max_fee),
-        NULL),
-      GNUNET_JSON_spec_array_const ("inputs",
-                                    &jinputs),
-      GNUNET_JSON_spec_array_const ("outputs",
-                                    &joutputs),
-      GNUNET_JSON_spec_end ()
-    };
-    const char *error_name;
-    unsigned int error_line;
-
-    if (GNUNET_OK !=
-        GNUNET_JSON_parse (json_array_get (root, i),
-                           spec,
-                           &error_name,
-                           &error_line))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to parse %s at %u: %s\n",
-                  spec[error_line].field,
-                  error_line,
-                  error_name);
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
-
-    {
-      const json_t *jinput;
-      size_t idx;
-      json_array_foreach ((json_t *) jinputs, idx, jinput)
-      {
-        struct TALER_MERCHANT_ContractInput input = {
-          .details.token.count = 1
-        };
-        const char *kind;
-        struct GNUNET_JSON_Specification ispec[] = {
-          GNUNET_JSON_spec_string ("kind",
-                                   &kind),
-          GNUNET_JSON_spec_string ("token_family_slug",
-                                   &input.details.token.token_family_slug),
-          GNUNET_JSON_spec_mark_optional (
-            GNUNET_JSON_spec_uint32 ("count",
-                                     &input.details.token.count),
-            NULL),
-          GNUNET_JSON_spec_end ()
-        };
-        const char *ierror_name;
-        unsigned int ierror_line;
-
-        if (GNUNET_OK !=
-            GNUNET_JSON_parse (jinput,
-                               ispec,
-                               &ierror_name,
-                               &ierror_line))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Failed to parse %s at %u: %s\n",
-                      ispec[ierror_line].field,
-                      ierror_line,
-                      ierror_name);
-          GNUNET_break_op (0);
-          return GNUNET_SYSERR;
-        }
-
-        input.type = TMH_contract_input_type_from_string (kind);
-
-        if (TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID == input.type)
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Field 'kind' invalid in input #%u\n",
-                      (unsigned int) idx);
-          GNUNET_break_op (0);
-          return GNUNET_SYSERR;
-        }
-
-        if (0 == input.details.token.count)
-        {
-          /* Ignore inputs with 'number' field set to 0 */
-          continue;
-        }
-
-        GNUNET_array_append (choice->inputs,
-                             choice->inputs_len,
-                             input);
-      }
-    }
-
-    {
-      const json_t *joutput;
-      size_t idx;
-      json_array_foreach ((json_t *) joutputs, idx, joutput)
-      {
-        struct TALER_MERCHANT_ContractOutput output = {
-          .details.token.count = 1
-        };
-        const char *kind;
-        uint32_t ki;
-        struct GNUNET_JSON_Specification ispec[] = {
-          GNUNET_JSON_spec_string ("kind",
-                                   &kind),
-          GNUNET_JSON_spec_string ("token_family_slug",
-                                   // FIXME...
-                                   (const char **) &output.details.token.
-                                   token_family_slug),
-          GNUNET_JSON_spec_uint32 ("key_index",
-                                   &ki),
-          GNUNET_JSON_spec_mark_optional (
-            GNUNET_JSON_spec_uint32 ("count",
-                                     &output.details.token.count),
-            NULL),
-          GNUNET_JSON_spec_end ()
-        };
-        const char *ierror_name;
-        unsigned int ierror_line;
-
-        if (GNUNET_OK !=
-            GNUNET_JSON_parse (joutput,
-                               ispec,
-                               &ierror_name,
-                               &ierror_line))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Failed to parse %s at %u: %s\n",
-                      ispec[ierror_line].field,
-                      ierror_line,
-                      ierror_name);
-          GNUNET_break_op (0);
-          return GNUNET_SYSERR;
-        }
-        output.details.token.key_index = ki;
-        output.type = TMH_contract_output_type_from_string (kind);
-
-        if (TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID == output.type)
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Field 'kind' invalid in output #%u\n",
-                      (unsigned int) idx);
-          GNUNET_break_op (0);
-          return GNUNET_SYSERR;
-        }
-
-        if (0 == output.details.token.count)
-        {
-          /* Ignore outputs with 'number' field set to 0 */
-          continue;
-        }
-
-        GNUNET_array_append (choice->outputs,
-                             choice->outputs_len,
-                             output);
-      }
-    }
-  }
-  return GNUNET_OK;
-}
-
-
-struct GNUNET_JSON_Specification
-TALER_JSON_spec_choices (const char *name,
-                         struct TALER_MERCHANT_ContractChoice **choices,
-                         unsigned int *choices_len)
-{
-  struct GNUNET_JSON_Specification ret = {
-    .cls = (void *) choices_len,
-    .parser = &parse_choices,
-    .field = name,
-    .ptr = choices,
-  };
-
-  return ret;
-}
-
-
-/**
- * Parse given JSON object to token families array.
- *
- * @param cls closure, pointer to array length
- * @param root the json object representing the token families. The keys are
- *             the token family slugs.
- * @param[out] ospec where to write the data
- * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
- */
-static enum GNUNET_GenericReturnValue
-parse_token_families (void *cls,
-                      json_t *root,
-                      struct GNUNET_JSON_Specification *ospec)
-{
-  struct TALER_MERCHANT_ContractTokenFamily **families = ospec->ptr;
-  unsigned int *families_len = cls;
-  json_t *jfamily;
-  const char *slug;
-
-  if (! json_is_object (root))
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  json_object_foreach (root, slug, jfamily)
-  {
-    const json_t *keys;
-    struct TALER_MERCHANT_ContractTokenFamily family = {
-      .slug = GNUNET_strdup (slug)
-    };
-    struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_array_const ("keys",
-                                    &keys),
-      GNUNET_JSON_spec_bool ("critical",
-                             &family.critical),
-      GNUNET_JSON_spec_end ()
-    };
-    const char *error_name;
-    unsigned int error_line;
-
-    if (GNUNET_OK !=
-        GNUNET_JSON_parse (jfamily,
-                           spec,
-                           &error_name,
-                           &error_line))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to parse %s at %u: %s\n",
-                  spec[error_line].field,
-                  error_line,
-                  error_name);
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
-    GNUNET_array_grow (family.keys,
-                       family.keys_len,
-                       json_array_size (keys));
-
-    for (unsigned int i = 0; i<family.keys_len; i++)
-    {
-      struct TALER_MERCHANT_ContractTokenFamilyKey *key = &family.keys[i];
-      struct GNUNET_JSON_Specification key_spec[] = {
-        TALER_JSON_spec_token_pub (
-          "public_key",
-          &key->pub),
-        GNUNET_JSON_spec_timestamp (
-          "valid_after",
-          &key->valid_after),
-        GNUNET_JSON_spec_timestamp (
-          "valid_before",
-          &key->valid_before),
-        GNUNET_JSON_spec_end ()
-      };
-      const char *ierror_name;
-      unsigned int ierror_line;
-
-      if (GNUNET_OK !=
-          GNUNET_JSON_parse (json_array_get (keys,
-                                             i),
-                             key_spec,
-                             &ierror_name,
-                             &ierror_line))
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Failed to parse %s at %u: %s\n",
-                    key_spec[ierror_line].field,
-                    ierror_line,
-                    ierror_name);
-        GNUNET_break_op (0);
-        return GNUNET_SYSERR;
-      }
-    }
-    GNUNET_array_append (*families,
-                         *families_len,
-                         family);
-  }
-  return GNUNET_OK;
-}
-
-
-struct GNUNET_JSON_Specification
-TALER_JSON_spec_token_families (
-  const char *name,
-  struct TALER_MERCHANT_ContractTokenFamily **families,
-  unsigned int *families_len)
-{
-  struct GNUNET_JSON_Specification ret = {
-    .cls = (void *) families_len,
-    .parser = &parse_token_families,
-    .field = name,
-    .ptr = families,
-  };
-
-  return ret;
-}
-
-
 enum GNUNET_GenericReturnValue
 TMH_find_token_family_key (
   const char *slug,
diff --git a/src/backend/taler-merchant-httpd_contract.h 
b/src/backend/taler-merchant-httpd_contract.h
index 751a59ef..463398ce 100644
--- a/src/backend/taler-merchant-httpd_contract.h
+++ b/src/backend/taler-merchant-httpd_contract.h
@@ -28,85 +28,6 @@
 #include <jansson.h>
 
 
-enum TALER_MERCHANT_ContractInputType
-TMH_contract_input_type_from_string (const char *str);
-
-
-enum TALER_MERCHANT_ContractOutputType
-TMH_contract_output_type_from_string (const char *str);
-
-
-const char *
-TMH_string_from_contract_input_type (enum TALER_MERCHANT_ContractInputType t);
-
-
-const char *
-TMH_string_from_contract_output_type (enum TALER_MERCHANT_ContractOutputType 
t);
-
-/**
- * Serialize @a contract to a JSON object, ready to be stored in the database.
- * The @a contract can be of v0 or v1.
- *
- * @param[in] contract contract struct to serialize
- * @param[in] instance merchant instance for this contract
- * @param[in] exchanges JSON array of exchanges
- * @param[out] out serialized contract as JSON object
- * @return #GNUNET_OK on success
- *         #GNUNET_NO if @a contract was not valid
- *         #GNUNET_SYSERR on failure
- */
-enum GNUNET_GenericReturnValue
-TMH_serialize_contract (const struct TALER_MERCHANT_Contract *contract,
-                        const struct TMH_MerchantInstance *instance,
-                        json_t *exchanges,
-                        json_t **out);
-
-
-enum GNUNET_GenericReturnValue
-TMH_serialize_contract_v0 (const struct TALER_MERCHANT_Contract *contract,
-                           const struct TMH_MerchantInstance *instance,
-                           json_t *exchanges,
-                           json_t **out);
-
-
-enum GNUNET_GenericReturnValue
-TMH_serialize_contract_v1 (const struct TALER_MERCHANT_Contract *contract,
-                           const struct TMH_MerchantInstance *instance,
-                           json_t *exchanges,
-                           json_t **out);
-
-/**
- * Provide specification to parse given JSON array to an array
- * of contract choices.
- *
- * @param name name of the choices field in the JSON
- * @param[out] choices set to the first element of the array
- * @param[out] choices_len set to the length of the @a choices array
- * @return spec for parsing a choices array
- */
-struct GNUNET_JSON_Specification
-TALER_JSON_spec_choices (
-  const char *name,
-  struct TALER_MERCHANT_ContractChoice **choices,
-  unsigned int *choices_len);
-
-
-/**
- * Provide specification to parse given JSON object to an array
- * of token families.
- *
- * @param name name of the token families field in the JSON
- * @param[out] families set to the first element of the array
- * @param[out] families_len set to the length of the @a families
- * @return spec for parsing a token families object
- */
-struct GNUNET_JSON_Specification
-TALER_JSON_spec_token_families (
-  const char *name,
-  struct TALER_MERCHANT_ContractTokenFamily **families,
-  unsigned int *families_len);
-
-
 /**
  * Find matching token family in @a families based on @a slug. Then use
  * @a valid_after to find the matching public key within it.
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c 
b/src/backend/taler-merchant-httpd_private-post-orders.c
index 195fbd32..292323ab 100644
--- a/src/backend/taler-merchant-httpd_private-post-orders.c
+++ b/src/backend/taler-merchant-httpd_private-post-orders.c
@@ -818,6 +818,9 @@ clean_order (void *cls)
     json_decref (mctf->description_i18n);
     switch (mctf->kind)
     {
+    case TALER_MERCHANT_CONTRACT_TOKEN_KIND_INVALID:
+      GNUNET_break (0);
+      break;
     case TALER_MERCHANT_CONTRACT_TOKEN_KIND_SUBSCRIPTION:
       for (size_t j = 0; j<mctf->details.subscription.trusted_domains_len; j++)
         GNUNET_free (mctf->details.subscription.trusted_domains[j]);
@@ -1696,12 +1699,14 @@ add_output_token_family (struct OrderContext *oc,
                       "lookup_token_family_key");
     return GNUNET_SYSERR;
   case GNUNET_DB_STATUS_SOFT_ERROR:
+    /* Single-statement transaction shouldn't possibly cause serialization 
errors.
+       Thus treating like a hard error. */
     GNUNET_break (0);
     reply_with_error (oc,
                       MHD_HTTP_INTERNAL_SERVER_ERROR,
                       TALER_EC_GENERIC_DB_SOFT_FAILURE,
                       "lookup_token_family_key");
-    return GNUNET_SYSERR; /* FIXME: retry instead? */
+    return GNUNET_SYSERR;
   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Output token family slug %s unknown\n",
@@ -1861,12 +1866,14 @@ add_output_token_family (struct OrderContext *oc,
                         NULL);
       return GNUNET_SYSERR;
     case GNUNET_DB_STATUS_SOFT_ERROR:
+      /* Single-statement transaction shouldn't possibly cause serialization 
errors.
+         Thus treating like a hard error. */
       GNUNET_break (0);
       reply_with_error (oc,
                         MHD_HTTP_INTERNAL_SERVER_ERROR,
                         TALER_EC_GENERIC_DB_SOFT_FAILURE,
                         NULL);
-      return GNUNET_SYSERR; // FIXME: or retry?
+      return GNUNET_SYSERR;
     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
       GNUNET_break (0);
       reply_with_error (oc,
@@ -3003,11 +3010,10 @@ parse_order (struct OrderContext *oc)
       {
         GNUNET_break_op (0);
         GNUNET_JSON_parse_free (spec);
-        // FIXME: use CONFLICT and a different EC!
         reply_with_error (oc,
-                          MHD_HTTP_BAD_REQUEST,
-                          TALER_EC_GENERIC_CURRENCY_MISMATCH,
-                          "no trusted exchange for this currency");
+                          MHD_HTTP_CONFLICT,
+                          
TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGE_FOR_CURRENCY,
+                          oc->parse_order.details.v0.brutto.currency);
         return;
       }
       if (NULL != choices)
@@ -3337,224 +3343,13 @@ parse_order (struct OrderContext *oc)
 static void
 parse_donau_instances (struct OrderContext *oc)
 {
+  /* FIXME-#9059: not yet implemented! */
   return;
 }
 
 
 #endif
 
-/**
- * Parse the inputs for a particular choice.
- *
- * @param[in,out] oc order context
- * @param[out] choice to parse inputs for
- * @param jinputs array of inputs to parse
- * @return #GNUNET_OK on success, #GNUNET_SYSERR
- *   if an error was encountered (and already handled)
- */
-static enum GNUNET_GenericReturnValue
-parse_order_inputs (struct OrderContext *oc,
-                    struct TALER_MERCHANT_ContractChoice *choice,
-                    const json_t *jinputs)
-{
-  const json_t *jinput;
-  size_t idx;
-
-  json_array_foreach ((json_t *) jinputs, idx, jinput)
-  {
-    struct TALER_MERCHANT_ContractInput input = {
-      .details.token.count = 1
-    };
-    const char *kind;
-    const char *ierror_name;
-    unsigned int ierror_line;
-    struct GNUNET_JSON_Specification ispec[] = {
-      // FIXME: define spec parser for 'kind'...
-      GNUNET_JSON_spec_string ("kind",
-                               &kind),
-      GNUNET_JSON_spec_string ("token_family_slug",
-                               &input.details.token.token_family_slug),
-      GNUNET_JSON_spec_mark_optional (
-        GNUNET_JSON_spec_uint32 ("count",
-                                 &input.details.token.count),
-        NULL),
-      GNUNET_JSON_spec_end ()
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_JSON_parse (jinput,
-                           ispec,
-                           &ierror_name,
-                           &ierror_line))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Invalid input #%u for field %s\n",
-                  (unsigned int) idx,
-                  ierror_name);
-      reply_with_error (oc,
-                        MHD_HTTP_BAD_REQUEST,
-                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                        ierror_name);
-      return GNUNET_SYSERR;
-    }
-
-    input.type = TMH_contract_input_type_from_string (kind);
-    if (TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID == input.type)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Field 'kind' invalid in input #%u\n",
-                  (unsigned int) idx);
-      reply_with_error (oc,
-                        MHD_HTTP_BAD_REQUEST,
-                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                        "kind");
-      return GNUNET_SYSERR;
-    }
-
-    if (0 == input.details.token.count)
-    {
-      /* Ignore inputs with 'number' field set to 0 */
-      continue;
-    }
-
-    if (GNUNET_OK !=
-        add_input_token_family (oc,
-                                input.details.token.token_family_slug))
-    {
-      /* error is already scheduled, return. */
-      return GNUNET_SYSERR;
-    }
-
-    GNUNET_array_append (choice->inputs,
-                         choice->inputs_len,
-                         input);
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Parse the outputs for a particular choice.
- *
- * @param[in,out] oc order context
- * @param[out] choice to parse inputs for
- * @param joutputs array of outputs to parse
- * @return #GNUNET_OK on success, #GNUNET_SYSERR
- *   if an error was encountered (and already handled)
- */
-static enum GNUNET_GenericReturnValue
-parse_order_outputs (struct OrderContext *oc,
-                     struct TALER_MERCHANT_ContractChoice *choice,
-                     const json_t *joutputs)
-{
-  const json_t *joutput;
-  size_t idx;
-
-  json_array_foreach ((json_t *) joutputs, idx, joutput)
-  {
-    struct TALER_MERCHANT_ContractOutput output = {
-      .details.token.count = 1
-    };
-    const char *kind;
-    const char *ierror_name;
-    unsigned int ierror_line;
-    bool nots;
-    struct GNUNET_TIME_Timestamp valid_at;
-    struct GNUNET_JSON_Specification ispec[] = {
-      // FIXME: define spec parser for 'kind'...
-      GNUNET_JSON_spec_string ("kind",
-                               &kind),
-      GNUNET_JSON_spec_string ("token_family_slug",
-                               // FIXME...
-                               (const char **) &output.details.token.
-                               token_family_slug),
-      GNUNET_JSON_spec_mark_optional (
-        GNUNET_JSON_spec_uint32 ("count",
-                                 &output.details.token.count),
-        NULL),
-      GNUNET_JSON_spec_mark_optional (
-        GNUNET_JSON_spec_timestamp ("valid_at",
-                                    &valid_at),
-        &nots),
-      GNUNET_JSON_spec_end ()
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_JSON_parse (joutput,
-                           ispec,
-                           &ierror_name,
-                           &ierror_line))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Invalid output #%u for field %s\n",
-                  (unsigned int) idx,
-                  ierror_name);
-      reply_with_error (oc,
-                        MHD_HTTP_BAD_REQUEST,
-                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                        ierror_name);
-      return GNUNET_SYSERR;
-    }
-    if (nots)
-    {
-      valid_at = oc->parse_order.pay_deadline;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Looking for output token valid at pay deadline %s\n",
-                  GNUNET_TIME_timestamp2s (valid_at));
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Looking for output token valid at %s\n",
-                  GNUNET_TIME_timestamp2s (valid_at));
-    }
-    if (GNUNET_TIME_timestamp_cmp (valid_at,
-                                   <,
-                                   oc->parse_order.pay_deadline))
-    {
-      reply_with_error (oc,
-                        MHD_HTTP_BAD_REQUEST,
-                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                        "valid_at before pay_deadline");
-      return GNUNET_SYSERR;
-    }
-
-    output.type = TMH_contract_output_type_from_string (kind);
-    if (TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID == output.type)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Field 'kind' invalid in output #%u\n",
-                  (unsigned int) idx);
-      reply_with_error (oc,
-                        MHD_HTTP_BAD_REQUEST,
-                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                        "kind");
-      return GNUNET_SYSERR;
-    }
-
-    if (0 == output.details.token.count)
-    {
-      /* Ignore outputs with 'number' field set to 0. */
-      continue;
-    }
-
-    if (GNUNET_OK !=
-        add_output_token_family (oc,
-                                 output.details.token.token_family_slug,
-                                 valid_at,
-                                 &output.details.token.key_index))
-    {
-      /* Error is already scheduled, return. */
-      return GNUNET_SYSERR;
-    }
-
-    GNUNET_array_append (choice->outputs,
-                         choice->outputs_len,
-                         output);
-  }
-  return GNUNET_OK;
-}
-
 
 /**
  * Parse contract choices. Upon success, continue
@@ -3652,11 +3447,10 @@ parse_choices (struct OrderContext *oc)
     {
       GNUNET_break_op (0);
       GNUNET_JSON_parse_free (spec);
-      // FIXME: use CONFLICT and a different EC!
       reply_with_error (oc,
-                        MHD_HTTP_BAD_REQUEST,
-                        TALER_EC_GENERIC_CURRENCY_MISMATCH,
-                        "no trusted exchange for this currency");
+                        MHD_HTTP_CONFLICT,
+                        
TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_NO_EXCHANGE_FOR_CURRENCY,
+                        choice->amount.currency);
       return;
     }
 
@@ -3744,6 +3538,9 @@ parse_choices (struct OrderContext *oc)
         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
           GNUNET_assert (0);
           break;
+        case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT:
+          GNUNET_break (0); /* FIXME-#9059: not yet implemented! */
+          break;
         case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
           /* Ignore inputs tokens with 'count' field set to 0 */
           if (0 == output.details.token.count)
diff --git a/src/include/taler_merchant_util.h 
b/src/include/taler_merchant_util.h
index 6d665bdd..a261e16f 100644
--- a/src/include/taler_merchant_util.h
+++ b/src/include/taler_merchant_util.h
@@ -664,6 +664,19 @@ TALER_MERCHANT_contract_parse (json_t *input,
                                bool nonce_optional);
 
 
+/**
+ * Provide specification to parse an JSON contract input type.
+ * The value is provided as a descriptive string.
+ *
+ * @param name name of the JSON member with the contract type
+ * @param[out] cit where to store the contract input type
+ * @return spec for parsing a contract input type
+ */
+struct GNUNET_JSON_Specification
+TALER_MERCHANT_json_spec_cit (const char *name,
+                              enum TALER_MERCHANT_ContractInputType *cit);
+
+
 /**
  * Parse JSON contract terms choice input.
  *
@@ -681,6 +694,19 @@ TALER_MERCHANT_parse_choice_input (
   bool order);
 
 
+/**
+ * Provide specification to parse an JSON contract output type.
+ * The value is provided as a descriptive string.
+ *
+ * @param name name of the JSON member with the contract type
+ * @param[out] cot where to store the contract output type
+ * @return spec for parsing a contract output type
+ */
+struct GNUNET_JSON_Specification
+TALER_MERCHANT_json_spec_cot (const char *name,
+                              enum TALER_MERCHANT_ContractOutputType *cot);
+
+
 /**
  * Parse JSON contract terms choice output.
  *
diff --git a/src/testing/test_merchant_api.c b/src/testing/test_merchant_api.c
index 99a54281..72f21fae 100644
--- a/src/testing/test_merchant_api.c
+++ b/src/testing/test_merchant_api.c
@@ -229,7 +229,7 @@ run (void *cls,
     TALER_TESTING_cmd_merchant_post_orders_no_claim (
       "create-proposal-bad-currency",
       merchant_url,
-      MHD_HTTP_BAD_REQUEST,
+      MHD_HTTP_CONFLICT,
       "4",
       GNUNET_TIME_UNIT_ZERO_TS,
       GNUNET_TIME_UNIT_FOREVER_TS,
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 4e9c0062..a49d6801 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -41,6 +41,7 @@ lib_LTLIBRARIES = \
 libtalermerchantutil_la_SOURCES = \
   contract_parse.c \
   contract_serialize.c \
+  json.c \
   os_installation.c
 libtalermerchantutil_la_LIBADD = \
   -lgnunetjson \
@@ -49,7 +50,7 @@ libtalermerchantutil_la_LIBADD = \
   -ltalerutil \
   $(XLIB)
 libtalermerchantutil_la_LDFLAGS = \
-  -version-info 0:0:0 \
+  -version-info 1:0:1 \
   -export-dynamic -no-undefined
 
 test_contract_SOURCES = \
diff --git a/src/util/contract_parse.c b/src/util/contract_parse.c
index 85970d5c..11e51666 100644
--- a/src/util/contract_parse.c
+++ b/src/util/contract_parse.c
@@ -111,42 +111,6 @@ spec_merchant_details (const char *name,
 }
 
 
-/**
- * Get enum value from contract input type string.
- *
- * @param str contract input type string
- * @return enum value of input type
- */
-static enum TALER_MERCHANT_ContractInputType
-contract_input_type_from_string (const char *str)
-{
-  /* For now, only 'token' is the only supported option. */
-  if (0 == strcmp ("token",
-                   str))
-    return TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN;
-  return TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID;
-}
-
-
-/**
- * Get enum value from contract output type string.
- *
- * @param str contract output type string
- * @return enum value of output type
- */
-static enum TALER_MERCHANT_ContractOutputType
-contract_output_type_from_string (const char *str)
-{
-  if (0 == strcmp ("token",
-                   str))
-    return TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN;
-  if (0 == strcmp ("tax-receipt",
-                   str))
-    return TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT;
-  return TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID;
-}
-
-
 /**
  * Get enum value from contract token type string.
  *
@@ -173,12 +137,11 @@ TALER_MERCHANT_parse_choice_input (
   size_t index,
   bool order)
 {
-  const char *type;
   const char *ename;
   unsigned int eline;
   struct GNUNET_JSON_Specification ispec[] = {
-    GNUNET_JSON_spec_string ("type",
-                             &type),
+    TALER_MERCHANT_json_spec_cit ("type",
+                                  &input->type),
     GNUNET_JSON_spec_end ()
   };
 
@@ -197,11 +160,10 @@ TALER_MERCHANT_parse_choice_input (
     return GNUNET_SYSERR;
   }
 
-  input->type = contract_input_type_from_string (type);
-
   switch (input->type)
   {
   case TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID:
+    GNUNET_break (0);
     break;
   case TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN:
     {
@@ -249,12 +211,11 @@ TALER_MERCHANT_parse_choice_output (
   size_t index,
   bool order)
 {
-  const char *type;
   const char *ename;
   unsigned int eline;
   struct GNUNET_JSON_Specification ispec[] = {
-    GNUNET_JSON_spec_string ("type",
-                             &type),
+    TALER_MERCHANT_json_spec_cot ("type",
+                                  &output->type),
     GNUNET_JSON_spec_end ()
   };
 
@@ -273,11 +234,10 @@ TALER_MERCHANT_parse_choice_output (
     return GNUNET_SYSERR;
   }
 
-  output->type = contract_output_type_from_string (type);
-
   switch (output->type)
   {
   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID:
+    GNUNET_break (0);
     break;
   case TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN:
     {
diff --git a/src/util/json.c b/src/util/json.c
new file mode 100644
index 00000000..89022c6d
--- /dev/null
+++ b/src/util/json.c
@@ -0,0 +1,171 @@
+/*
+  This file is part of TALER
+  (C) 2025 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU Lesser General Public License as published by the Free 
Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file util/json.c
+ * @brief helper functions to parse JSON
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_common.h>
+#include <gnunet/gnunet_json_lib.h>
+#include <jansson.h>
+#include <taler/taler_json_lib.h>
+#include <taler/taler_util.h>
+#include "taler_merchant_util.h"
+
+
+/**
+ * Parse given JSON object to `enum TALER_MERCHANT_ContractInputType`
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_contract_input_type (void *cls,
+                           json_t *root,
+                           struct GNUNET_JSON_Specification *spec)
+{
+  static const struct Entry
+  {
+    const char *name;
+    enum TALER_MERCHANT_ContractInputType val;
+  } lt [] = {
+#if FUTURE
+    { .name = "coin",
+      .val = TALER_MERCHANT_CONTRACT_INPUT_TYPE_COIN },
+#endif
+    { .name = "token",
+      .val = TALER_MERCHANT_CONTRACT_INPUT_TYPE_TOKEN },
+    { .name = NULL,
+      .val = TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID }
+  };
+  enum TALER_MERCHANT_ContractInputType *res
+    = (enum TALER_MERCHANT_ContractInputType *) spec->ptr;
+
+  (void) cls;
+  if (json_is_string (root))
+  {
+    const char *str;
+
+    str = json_string_value (root);
+    if (NULL == str)
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    for (unsigned int i = 0; NULL != lt[i].name; i++)
+    {
+      if (0 == strcasecmp (str,
+                           lt[i].name))
+      {
+        *res = lt[i].val;
+        return GNUNET_OK;
+      }
+    }
+  }
+  GNUNET_break_op (0);
+  return GNUNET_SYSERR;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_MERCHANT_json_spec_cit (const char *name,
+                              enum TALER_MERCHANT_ContractInputType *cit)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_contract_input_type,
+    .field = name,
+    .ptr = cit
+  };
+
+  *cit = TALER_MERCHANT_CONTRACT_INPUT_TYPE_INVALID;
+  return ret;
+}
+
+
+/**
+ * Parse given JSON object to `enum TALER_MERCHANT_ContractOutputType`
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_contract_output_type (void *cls,
+                            json_t *root,
+                            struct GNUNET_JSON_Specification *spec)
+{
+  static const struct Entry
+  {
+    const char *name;
+    enum TALER_MERCHANT_ContractOutputType val;
+  } lt [] = {
+    { .name = "token",
+      .val = TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_TOKEN },
+    { .name = "tax-receipt",
+      .val = TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_DONATION_RECEIPT },
+#if FUTURE
+    { .name = "coin",
+      .val = TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_COIN },
+#endif
+    { .name = NULL,
+      .val = TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID }
+  };
+  enum TALER_MERCHANT_ContractOutputType *res
+    = (enum TALER_MERCHANT_ContractOutputType *) spec->ptr;
+
+  (void) cls;
+  if (json_is_string (root))
+  {
+    const char *str;
+
+    str = json_string_value (root);
+    if (NULL == str)
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    for (unsigned int i = 0; NULL != lt[i].name; i++)
+    {
+      if (0 == strcasecmp (str,
+                           lt[i].name))
+      {
+        *res = lt[i].val;
+        return GNUNET_OK;
+      }
+    }
+  }
+  GNUNET_break_op (0);
+  return GNUNET_SYSERR;
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_MERCHANT_json_spec_cot (const char *name,
+                              enum TALER_MERCHANT_ContractOutputType *cot)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_contract_output_type,
+    .field = name,
+    .ptr = cot
+  };
+
+  *cot = TALER_MERCHANT_CONTRACT_OUTPUT_TYPE_INVALID;
+  return ret;
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]