diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/extensions/auction_brandt/extension_auction_brandt.c | 166 | ||||
| -rw-r--r-- | src/testing/test_exchange_auction.conf | 159 | 
2 files changed, 304 insertions, 21 deletions
| diff --git a/src/extensions/auction_brandt/extension_auction_brandt.c b/src/extensions/auction_brandt/extension_auction_brandt.c index a5f3af8c..24ac452b 100644 --- a/src/extensions/auction_brandt/extension_auction_brandt.c +++ b/src/extensions/auction_brandt/extension_auction_brandt.c @@ -27,6 +27,8 @@  #include <microhttpd.h>  #define AUCTION_BRANDT "auction_brandt" +#define LOG_PREFIX "[auction_brandt] " +#define MAX_RESULT_SIZE 10 * 1024  /* Path to the replay program. */  static char *replay_program; @@ -77,7 +79,7 @@ json_error (json_t **output,    GNUNET_assert (*output);    GNUNET_log (GNUNET_ERROR_TYPE_INFO, -              "[auction_brandt] got error: %s\n", +              LOG_PREFIX "got error: %s\n",                error);    return GNUNET_SYSERR; @@ -86,6 +88,7 @@ json_error (json_t **output,  /**   * @brief returns an JSON with the result   */ +#if 0  static enum GNUNET_GenericReturnValue  json_result (json_t **output,               const struct transcript *tr) @@ -119,6 +122,9 @@ json_result (json_t **output,  } +#endif + +  /*   * @brief Parses a given json as transcript.   * @@ -126,13 +132,16 @@ json_result (json_t **output,   * @param[out] transcript Parsed transcript data   * @param[out] jresult JSON output, both, for results or errors   * @return GNUNET_OK on succes + * + * TODO: + *   - fix leakages + *   - parse and verify signatures   */  static enum GNUNET_GenericReturnValue  parse_transcript (const json_t *jtr,                    struct transcript *tr,                    json_t **output)  { -  // TODO: json_error_t jerror;    // TODO: struct GNUNET_CRYPTO_EddsaSignature sig;    GNUNET_assert (jtr); @@ -167,7 +176,7 @@ parse_transcript (const json_t *jtr,        if (! json_is_array (prices)) -        // TODO: leak!? +        // TODO: fix leak!?          return json_error (output, "no prices found");        tr->k = json_array_size (prices); @@ -176,7 +185,7 @@ parse_transcript (const json_t *jtr,        json_array_foreach (prices, idx, val)        {          if (! json_is_string (val)) -          // TODO: leak!_ +          // TODO: fix leak!_            return json_error (output, "prices not strings");          tr->prices[idx] = (char *) json_string_value (val); @@ -192,7 +201,7 @@ parse_transcript (const json_t *jtr,      bidders = json_object_get (jtr, "bidders");      if (! bidders || ! json_is_array (bidders)) -      // TODO: leak!_ +      // TODO: fix leak!_        return json_error (output, "bidders not found");      // TODO: parse bidders as pub keys; @@ -207,14 +216,14 @@ parse_transcript (const json_t *jtr,      messages = json_object_get (jtr, "transcript");      if (! json_is_array (messages)) -      // TODO: leak! +      // TODO: fix leak!        return json_error (output, "no messages found");      nm = json_array_size (messages);      if (nm != (4 * tr->n)) -      // TODO: leak! +      // TODO: fix leak!        return json_error (output, "not the right no. of messages found");    } @@ -229,7 +238,8 @@ parse_transcript (const json_t *jtr,      if (! json_is_array (winners))      {        GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -                  "winners not provided, continuing without\n"); +                  LOG_PREFIX "winners not provided, continuing without\n"); +      // TODO: fix leakage        goto CONT;      } @@ -255,13 +265,118 @@ parse_transcript (const json_t *jtr,                               spec,                               (const char**) &error,                               NULL)) -        // TODO: leak! +        // TODO: fix leak!          return json_error (output, "couldn't parse winners");      }  CONT: +    // TODO: fix leakages +  } +  *output = NULL; +  return GNUNET_OK; +} + + +/** + * @brief replay an auction using the external program + * + * @param[in] root The original JSON transcript + * @param[in] transcript The transcript object parsed so far + * @param[out] result The JSON result from the program + * @return GNUNET_OK on success + * + * TODO: Make this asynchronous (giving out a replay-ID to poll from)? + */ +static enum GNUNET_GenericReturnValue +replay_transcript (const json_t*root, +                   struct transcript *tr, +                   json_t **result) +{ +  struct GNUNET_DISK_PipeHandle *pi; +  struct GNUNET_DISK_PipeHandle *po; +  const struct GNUNET_DISK_FileHandle *fd; +  struct GNUNET_OS_Process *proc; + +  pi = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_WRITE); +  po = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_READ); +  proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR, +                                  pi, po, NULL, +                                  replay_program, +                                  replay_program, +                                  NULL); +  if (NULL == proc) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                LOG_PREFIX "couldn't create auction replay program '%s'\n", +                replay_program); + +    return json_error (result, "internal error"); +  } + +  // Write original transcript JSON to stdin +  { +    ssize_t sz; +    char *str; +    size_t str_len; + + +    fd = GNUNET_DISK_pipe_handle (pi, GNUNET_DISK_PIPE_END_WRITE); +    str = json_dumps (root, JSON_COMPACT); +    str_len = strlen (str); +    sz = GNUNET_DISK_file_write (fd, +                                 str, +                                 str_len); +    free (str); +    if (sz != str_len) +    { +      GNUNET_log (GNUNET_ERROR_TYPE_INFO, +                  LOG_PREFIX "couldn't write all data to replay_program\n"); +    } +  } + +  // Read output from stdout +  { +    ssize_t sz; +    char buf[MAX_RESULT_SIZE]; +    fd = GNUNET_DISK_pipe_handle (po, GNUNET_DISK_PIPE_END_READ); + +    sz = GNUNET_DISK_file_read (fd, +                                buf, +                                sizeof(buf)); +    if (GNUNET_SYSERR == sz) +    { +      GNUNET_log (GNUNET_ERROR_TYPE_INFO, +                  LOG_PREFIX "couldn't read data from replay_program\n"); +    } +    else +    { +      json_error_t error; +      json_t *res; +      res = json_loads (buf, +                        JSON_DECODE_ANY, +                        &error); + +      if (! res) +        return json_error (result, error.text); + +      *result = json_copy (res); +      json_decref (res); +    }    } -  return json_result (output, tr); + +  if (GNUNET_OK != GNUNET_OS_process_wait (proc)) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                LOG_PREFIX "error while launching auction replay program '%s'\n", +                replay_program); + +    json_object_clear (*result); +    return json_error (result, "internal error"); +  } + + +  // TODO: parse result +  return GNUNET_OK;  } @@ -338,7 +453,7 @@ auction_http_get_handler (    /* TODO: return some meta-data about supported version, limits, etc.*/    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -              "auction_http_get_handler not implemented yet\n"); +              LOG_PREFIX "auction_http_get_handler not implemented yet\n");    return TALER_MHD_reply_with_error (connection,                                       MHD_HTTP_NOT_IMPLEMENTED, @@ -359,17 +474,26 @@ auction_http_post_handler (  {    struct transcript tr = {};    enum GNUNET_GenericReturnValue ret; -  json_t *result; - -  ret = parse_transcript (root, &tr, &result); - -  /* TODO */ -  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, -              "auction_http_post_handler not implemented yet\n"); +  json_t *result1; +  json_t *result2; + +  ret = parse_transcript (root, +                          &tr, +                          &result1); +  if (GNUNET_OK != ret) +    return TALER_MHD_reply_json_steal (connection, +                                       result1, +                                       MHD_HTTP_BAD_REQUEST); +  GNUNET_assert (NULL == result1); + +  ret = replay_transcript (root, +                           &tr, +                           &result2);    return TALER_MHD_reply_json_steal (connection, -                                     result, -                                     GNUNET_OK == ret? MHD_HTTP_OK : +                                     result2, +                                     GNUNET_OK == ret? +                                     MHD_HTTP_OK :                                       MHD_HTTP_BAD_REQUEST);  } @@ -427,7 +551,7 @@ libtaler_extension_auction_brandt_init (void *arg)    }    /* TODO: check if replay_program is actually executable */    GNUNET_log (GNUNET_ERROR_TYPE_INFO, -              "[auction_brandt] loading... using replay_program '%s'\n", +              LOG_PREFIX "loading... using replay_program '%s'\n",                replay_program);    return &TE_auction_brandt; diff --git a/src/testing/test_exchange_auction.conf b/src/testing/test_exchange_auction.conf new file mode 100644 index 00000000..ee5ef7bc --- /dev/null +++ b/src/testing/test_exchange_auction.conf @@ -0,0 +1,159 @@ +# This file is in the public domain. +# + +[PATHS] +# Persistent data storage for the testcase +TALER_TEST_HOME = test_exchange_api_home/ +TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/ + +[taler-exchange-secmod-rsa] +# Reduce from 1 year to speed up test +LOOKAHEAD_SIGN = 24 days + +[taler-exchange-secmod-eddsa] +# Reduce from 1 year to speed up test +LOOKAHEAD_SIGN = 24 days +# Reduce from 12 weeks to ensure we have multiple +DURATION = 14 days + +[taler] +# Currency supported by the exchange (can only be one) +CURRENCY = EUR +CURRENCY_ROUND_UNIT = EUR:0.01 + +[auditor] +BASE_URL = "http://localhost:8083/" + +# HTTP port the auditor listens to +PORT = 8083 + +[exchange] + +TERMS_ETAG = 0 +PRIVACY_ETAG = 0 + +# HTTP port the exchange listens to +PORT = 8081 + +# Master public key used to sign the exchange's various keys +MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG + +# How to access our database +DB = postgres + +# Base URL of the exchange. Must be set to a URL where the +# exchange (or the twister) is actually listening. +BASE_URL = "http://localhost:8081/" + +# How big is an individual shard to be processed +# by taler-exchange-expire (in time).  It may take +# this much time for an expired purse to be really +# cleaned up and the coins refunded. +EXPIRE_SHARD_SIZE = 300 ms + +EXPIRE_IDLE_SLEEP_INTERVAL = 1 s + + +[exchangedb-postgres] +CONFIG = "postgres:///talercheck" + +[auditordb-postgres] +CONFIG = "postgres:///talercheck" + +# Sections starting with "exchange-account-" configure the bank accounts +# of the exchange.  The "URL" specifies the account in +# payto://-format. +[exchange-account-1] +# What is the URL of our account? +PAYTO_URI = "payto://x-taler-bank/localhost/42?receiver-name=42" +# ENABLE_CREDIT = YES + +[exchange-accountcredentials-1] +WIRE_GATEWAY_URL = "http://localhost:9081/42/" + +[exchange-account-2] +# What is the bank account (with the "Taler Bank" demo system)? +PAYTO_URI = "payto://x-taler-bank/localhost/2?receiver-name=2" +ENABLE_DEBIT = YES +ENABLE_CREDIT = YES + +[exchange-accountcredentials-2] +WIRE_GATEWAY_AUTH_METHOD = basic +USERNAME = Exchange +PASSWORD = x +WIRE_GATEWAY_URL = "http://localhost:9081/2/" + +[bank] +HTTP_PORT = 9081 + +# Enabled extensions +#[exchange-extension-age_restriction] +#ENABLED = YES +# default age groups: +#AGE_GROUPS = "8:10:12:14:16:18:21" + +[exchange-extension-auction_brandt] +ENABLED = YES +REPLAY_PROGRAM = "/usr/local/bin/taler-exchange-auction_brandt-replay" + +# Sections starting with "coin_" specify which denominations +# the exchange should support (and their respective fee structure) +[coin_eur_ct_1] +value = EUR:0.01 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.00 +fee_deposit = EUR:0.00 +fee_refresh = EUR:0.01 +fee_refund = EUR:0.01 +CIPHER = RSA +rsa_keysize = 1024 + +[coin_eur_ct_10] +value = EUR:0.10 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +CIPHER = RSA +rsa_keysize = 1024 + +[coin_eur_1] +value = EUR:1 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +CIPHER = RSA +rsa_keysize = 1024 + +[coin_eur_5] +value = EUR:5 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +CIPHER = RSA +rsa_keysize = 1024 + +[coin_eur_10] +value = EUR:10 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.03 +fee_refund = EUR:0.01 +CIPHER = RSA +rsa_keysize = 1024 | 
