diff options
Diffstat (limited to 'src/exchange')
| -rw-r--r-- | src/exchange/taler-exchange-aggregator.c | 12 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd.c | 65 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_deposit.c | 193 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_keystate.c | 9 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_refund.c | 99 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_responses.c | 4 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_wire.c | 4 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_withdraw.c | 4 | 
8 files changed, 213 insertions, 177 deletions
diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index 21a29e50..69c73746 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -330,6 +330,8 @@ refund_by_coin_cb (void *cls,   *   * @param cls a `struct AggregationUnit`   * @param row_id identifies database entry + * @param exchange_timestamp when did the deposit happen + * @param wallet_timestamp when did the contract happen   * @param merchant_pub public key of the merchant   * @param coin_pub public key of the coin   * @param amount_with_fee amount that was deposited including fee @@ -343,6 +345,8 @@ refund_by_coin_cb (void *cls,  static enum GNUNET_DB_QueryStatus  deposit_cb (void *cls,              uint64_t row_id, +            struct GNUNET_TIME_Absolute exchange_timestamp, +            struct GNUNET_TIME_Absolute wallet_timestamp,              const struct TALER_MerchantPublicKeyP *merchant_pub,              const struct TALER_CoinSpendPublicKeyP *coin_pub,              const struct TALER_Amount *amount_with_fee, @@ -358,6 +362,8 @@ deposit_cb (void *cls,    /* NOTE: potential optimization: use custom SQL API to not       fetch this one: */    (void) wire_deadline; /* already checked by SQL query */ +  (void) exchange_timestamp; +  (void) wallet_timestamp;    au->merchant_pub = *merchant_pub;    GNUNET_log (GNUNET_ERROR_TYPE_INFO,                "Aggregator processing payment %s with amount %s\n", @@ -501,6 +507,8 @@ deposit_cb (void *cls,   *   * @param cls a `struct AggregationUnit`   * @param row_id identifies database entry + * @param exchange_timestamp when did the exchange receive the deposit + * @param wallet_timestamp when did the wallet sign the contract   * @param merchant_pub public key of the merchant   * @param coin_pub public key of the coin   * @param amount_with_fee amount that was deposited including fee @@ -514,6 +522,8 @@ deposit_cb (void *cls,  static enum GNUNET_DB_QueryStatus  aggregate_cb (void *cls,                uint64_t row_id, +              struct GNUNET_TIME_Absolute exchange_timestamp, +              struct GNUNET_TIME_Absolute wallet_timestamp,                const struct TALER_MerchantPublicKeyP *merchant_pub,                const struct TALER_CoinSpendPublicKeyP *coin_pub,                const struct TALER_Amount *amount_with_fee, @@ -529,6 +539,8 @@ aggregate_cb (void *cls,    /* NOTE: potential optimization: use custom SQL API to not       fetch these: */    (void) wire_deadline; /* checked by SQL */ +  (void) exchange_timestamp; +  (void) wallet_timestamp;    (void) wire; /* must match */    GNUNET_break (0 == GNUNET_memcmp (&au->merchant_pub,                                      merchant_pub)); diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 339303d5..c614b711 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -421,6 +421,45 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,  /** + * Handle a "/seed" request. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param args array of additional options (must be empty for this function) + * @return MHD result code + */ +static MHD_RESULT +handler_seed (const struct TEH_RequestHandler *rh, +              struct MHD_Connection *connection, +              const char *const args[]) +{ +#define SEED_SIZE 32 +  char *body; +  MHD_RESULT ret; +  struct MHD_Response *resp; + +  (void) rh; +  body = malloc (SEED_SIZE); /* must use malloc(), because MHD will use free() */ +  if (NULL == body) +    return MHD_NO; +  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, +                              body, +                              SEED_SIZE); +  resp = MHD_create_response_from_buffer (SEED_SIZE, +                                          body, +                                          MHD_RESPMEM_MUST_FREE); +  TALER_MHD_add_global_headers (resp); +  ret = MHD_queue_response (connection, +                            MHD_HTTP_OK, +                            resp); +  GNUNET_break (MHD_YES == ret); +  MHD_destroy_response (resp); +  return ret; +#undef SEED_SIZE +} + + +/**   * Handle incoming HTTP request.   *   * @param cls closure for MHD daemon (unused) @@ -472,6 +511,11 @@ handle_mhd_request (void *cls,        .method = MHD_HTTP_METHOD_GET,        .handler.get = &TEH_handler_agpl_redirect      }, +    { +      .url = "seed", +      .method = MHD_HTTP_METHOD_GET, +      .handler.get = &handler_seed +    },      /* Terms of service */      {        .url = "terms", @@ -654,9 +698,10 @@ handle_mhd_request (void *cls,      {        struct TEH_RequestHandler *rh = &handlers[i]; -      if (0 != strncmp (tok, -                        rh->url, -                        tok_size)) +      if ( (0 != strncmp (tok, +                          rh->url, +                          tok_size)) || +           (tok_size != strlen (rh->url) ) )          continue;        found = GNUNET_YES;        /* The URL is a match!  What we now do depends on the method. */ @@ -782,8 +827,8 @@ exchange_serve_process_config (void)                                                      &TEH_master_public_key.                                                      eddsa_pub))      { -      fprintf (stderr, -               "Invalid master public key given in exchange configuration."); +      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                  "Invalid master public key given in exchange configuration.");        GNUNET_free (master_public_key_str);        return GNUNET_SYSERR;      } @@ -795,14 +840,18 @@ exchange_serve_process_config (void)    if (GNUNET_OK !=        TEH_WIRE_init (TEH_cfg)) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Failed to setup wire subsystem\n");      return GNUNET_SYSERR; +  }    if (NULL ==        (TEH_plugin = TALER_EXCHANGEDB_plugin_load (TEH_cfg)))    { -    fprintf (stderr, -             "Failed to initialize DB subsystem\n"); +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Failed to initialize DB subsystem\n");      TEH_WIRE_done ();      return GNUNET_SYSERR;    } @@ -814,6 +863,8 @@ exchange_serve_process_config (void)                                &serve_unixpath,                                &unixpath_mode))    { +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "Failed to setup HTTPd subsystem\n");      TEH_WIRE_done ();      return GNUNET_SYSERR;    } diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 3f895857..fe8fdf06 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -47,7 +47,7 @@   * @param coin_pub public key of the coin   * @param h_wire hash of wire details   * @param h_contract_terms hash of contract details - * @param timestamp client's timestamp + * @param exchange_timestamp exchange's timestamp   * @param refund_deadline until when this deposit be refunded   * @param merchant merchant public key   * @param amount_without_fee fraction of coin value to deposit, without the fee @@ -58,7 +58,7 @@ reply_deposit_success (struct MHD_Connection *connection,                         const struct TALER_CoinSpendPublicKeyP *coin_pub,                         const struct GNUNET_HashCode *h_wire,                         const struct GNUNET_HashCode *h_contract_terms, -                       struct GNUNET_TIME_Absolute timestamp, +                       struct GNUNET_TIME_Absolute exchange_timestamp,                         struct GNUNET_TIME_Absolute refund_deadline,                         const struct TALER_MerchantPublicKeyP *merchant,                         const struct TALER_Amount *amount_without_fee) @@ -70,7 +70,7 @@ reply_deposit_success (struct MHD_Connection *connection,      .purpose.size = htonl (sizeof (dc)),      .h_contract_terms = *h_contract_terms,      .h_wire = *h_wire, -    .timestamp = GNUNET_TIME_absolute_hton (timestamp), +    .exchange_timestamp = GNUNET_TIME_absolute_hton (exchange_timestamp),      .refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),      .coin_pub = *coin_pub,      .merchant = *merchant @@ -88,12 +88,16 @@ reply_deposit_success (struct MHD_Connection *connection,                                         TALER_EC_EXCHANGE_BAD_CONFIGURATION,                                         "no keys");    } -  return TALER_MHD_reply_json_pack (connection, -                                    MHD_HTTP_OK, -                                    "{s:s, s:o, s:o}", -                                    "status", "DEPOSIT_OK", -                                    "sig", GNUNET_JSON_from_data_auto (&sig), -                                    "pub", GNUNET_JSON_from_data_auto (&pub)); +  return TALER_MHD_reply_json_pack ( +    connection, +    MHD_HTTP_OK, +    "{s:o, s:o, s:o}", +    "exchange_timestamp", +    GNUNET_JSON_from_time_abs (exchange_timestamp), +    "exchange_sig", +    GNUNET_JSON_from_data_auto (&sig), +    "exchange_pub", +    GNUNET_JSON_from_data_auto (&pub));  } @@ -108,6 +112,11 @@ struct DepositContext    const struct TALER_EXCHANGEDB_Deposit *deposit;    /** +   * Our timestamp (when we received the request). +   */ +  struct GNUNET_TIME_Absolute exchange_timestamp; + +  /**     * Value of the coin.     */    struct TALER_Amount value; @@ -116,12 +125,11 @@ struct DepositContext  /** - * Execute database transaction for /deposit.  Runs the transaction - * logic; IF it returns a non-error code, the transaction logic MUST - * NOT queue a MHD response.  IF it returns an hard error, the - * transaction logic MUST queue a MHD response and set @a mhd_ret.  IF - * it returns the soft error code, the function MAY be called again to - * retry and MUST not queue a MHD response. + * Check if /deposit is already in the database.  IF it returns a non-error + * code, the transaction logic MUST NOT queue a MHD response.  IF it returns + * an hard error, the transaction logic MUST queue a MHD response and set @a + * mhd_ret.  We do return a "hard" error also if we found the deposit in the + * database and generated a regular response.   *   * @param cls a `struct DepositContext`   * @param connection MHD request context @@ -130,20 +138,22 @@ struct DepositContext   * @return transaction status   */  static enum GNUNET_DB_QueryStatus -deposit_transaction (void *cls, -                     struct MHD_Connection *connection, -                     struct TALER_EXCHANGEDB_Session *session, -                     MHD_RESULT *mhd_ret) +deposit_precheck (void *cls, +                  struct MHD_Connection *connection, +                  struct TALER_EXCHANGEDB_Session *session, +                  MHD_RESULT *mhd_ret)  {    struct DepositContext *dc = cls;    const struct TALER_EXCHANGEDB_Deposit *deposit = dc->deposit; -  struct TALER_Amount spent; +  struct TALER_Amount deposit_fee;    enum GNUNET_DB_QueryStatus qs;    qs = TEH_plugin->have_deposit (TEH_plugin->cls,                                   session,                                   deposit, -                                 GNUNET_YES /* check refund deadline */); +                                 GNUNET_YES /* check refund deadline */, +                                 &deposit_fee, +                                 &dc->exchange_timestamp);    if (qs < 0)    {      if (GNUNET_DB_STATUS_HARD_ERROR == qs) @@ -165,12 +175,12 @@ deposit_transaction (void *cls,      GNUNET_assert (0 <=                     TALER_amount_subtract (&amount_without_fee,                                            &deposit->amount_with_fee, -                                          &deposit->deposit_fee)); +                                          &deposit_fee));      *mhd_ret = reply_deposit_success (connection,                                        &deposit->coin.coin_pub,                                        &deposit->h_wire,                                        &deposit->h_contract_terms, -                                      deposit->timestamp, +                                      dc->exchange_timestamp,                                        deposit->refund_deadline,                                        &deposit->merchant_pub,                                        &amount_without_fee); @@ -178,6 +188,44 @@ deposit_transaction (void *cls,         never try again. */      return GNUNET_DB_STATUS_HARD_ERROR;    } +  return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; +} + + +/** + * Execute database transaction for /deposit.  Runs the transaction + * logic; IF it returns a non-error code, the transaction logic MUST + * NOT queue a MHD response.  IF it returns an hard error, the + * transaction logic MUST queue a MHD response and set @a mhd_ret.  IF + * it returns the soft error code, the function MAY be called again to + * retry and MUST not queue a MHD response. + * + * @param cls a `struct DepositContext` + * @param connection MHD request context + * @param session database session and transaction to use + * @param[out] mhd_ret set to MHD status on error + * @return transaction status + */ +static enum GNUNET_DB_QueryStatus +deposit_transaction (void *cls, +                     struct MHD_Connection *connection, +                     struct TALER_EXCHANGEDB_Session *session, +                     MHD_RESULT *mhd_ret) +{ +  struct DepositContext *dc = cls; +  const struct TALER_EXCHANGEDB_Deposit *deposit = dc->deposit; +  struct TALER_Amount spent; +  enum GNUNET_DB_QueryStatus qs; + +  /* Theoretically, someone other threat may have received +     and committed the deposit in the meantime. Check now +     that we are in the transaction scope. */ +  qs = deposit_precheck (cls, +                         connection, +                         session, +                         mhd_ret); +  if (qs < 0) +    return qs;    /* Start with fee for THIS transaction */    spent = deposit->amount_with_fee; @@ -237,6 +285,7 @@ deposit_transaction (void *cls,    }    qs = TEH_plugin->insert_deposit (TEH_plugin->cls,                                     session, +                                   dc->exchange_timestamp,                                     deposit);    if (GNUNET_DB_STATUS_HARD_ERROR == qs)    { @@ -251,45 +300,6 @@ deposit_transaction (void *cls,  /** - * Check that @a ts is reasonably close to our own RTC. - * - * @param ts timestamp to check - * @return #GNUNET_OK if @a ts is reasonable - */ -static int -check_timestamp_current (struct GNUNET_TIME_Absolute ts) -{ -  struct GNUNET_TIME_Relative r; -  struct GNUNET_TIME_Relative tolerance; - -  /* Let's be VERY generous (after all, this is basically about -     which year the deposit counts for in terms of tax purposes) */ -  tolerance = GNUNET_TIME_UNIT_MONTHS; -  r = GNUNET_TIME_absolute_get_duration (ts); -  if (r.rel_value_us > tolerance.rel_value_us) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, -                "Deposit timestamp too old: %llu vs %llu > %llu\n", -                (unsigned long long) ts.abs_value_us, -                (unsigned long long) GNUNET_TIME_absolute_get ().abs_value_us, -                (unsigned long long) tolerance.rel_value_us); -    return GNUNET_SYSERR; -  } -  r = GNUNET_TIME_absolute_get_remaining (ts); -  if (r.rel_value_us > tolerance.rel_value_us) -  { -    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, -                "Deposit timestamp too new: %llu vs %llu < - %llu\n", -                (unsigned long long) ts.abs_value_us, -                (unsigned long long) GNUNET_TIME_absolute_get ().abs_value_us, -                (unsigned long long) tolerance.rel_value_us); -    return GNUNET_SYSERR; -  } -  return GNUNET_OK; -} - - -/**   * Handle a "/coins/$COIN_PUB/deposit" request.  Parses the JSON, and, if   * successful, passes the JSON data to #deposit_transaction() to   * further check the details of the operation specified.  If everything checks @@ -312,15 +322,22 @@ TEH_handler_deposit (struct MHD_Connection *connection,    struct GNUNET_HashCode my_h_wire;    struct GNUNET_JSON_Specification spec[] = {      GNUNET_JSON_spec_json ("wire", &wire), -    TALER_JSON_spec_amount ("contribution", &deposit.amount_with_fee), +    TALER_JSON_spec_amount ("contribution", +                            &deposit.amount_with_fee),      GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",                                   &deposit.coin.denom_pub_hash), -    TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig), -    GNUNET_JSON_spec_fixed_auto ("merchant_pub", &deposit.merchant_pub), -    GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &deposit.h_contract_terms), -    GNUNET_JSON_spec_fixed_auto ("h_wire", &deposit.h_wire), -    GNUNET_JSON_spec_fixed_auto ("coin_sig",  &deposit.csig), -    GNUNET_JSON_spec_absolute_time ("timestamp", &deposit.timestamp), +    TALER_JSON_spec_denomination_signature ("ub_sig", +                                            &deposit.coin.denom_sig), +    GNUNET_JSON_spec_fixed_auto ("merchant_pub", +                                 &deposit.merchant_pub), +    GNUNET_JSON_spec_fixed_auto ("h_contract_terms", +                                 &deposit.h_contract_terms), +    GNUNET_JSON_spec_fixed_auto ("h_wire", +                                 &deposit.h_wire), +    GNUNET_JSON_spec_fixed_auto ("coin_sig", +                                 &deposit.csig), +    GNUNET_JSON_spec_absolute_time ("timestamp", +                                    &deposit.timestamp),      GNUNET_JSON_spec_absolute_time ("refund_deadline",                                      &deposit.refund_deadline),      GNUNET_JSON_spec_absolute_time ("wire_transfer_deadline", @@ -359,17 +376,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,                                         TALER_EC_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE,                                         "refund_deadline");    } - -  if (GNUNET_OK != -      check_timestamp_current (deposit.timestamp)) -  { -    GNUNET_break_op (0); -    GNUNET_JSON_parse_free (spec); -    return TALER_MHD_reply_with_error (connection, -                                       MHD_HTTP_BAD_REQUEST, -                                       TALER_EC_DEPOSIT_INVALID_TIMESTAMP, -                                       "timestamp"); -  }    if (GNUNET_OK !=        TALER_JSON_merchant_wire_signature_hash (wire,                                                 &my_h_wire)) @@ -393,6 +399,26 @@ TEH_handler_deposit (struct MHD_Connection *connection,                                         "h_wire");    } +  /* Check for idempotency: did we get this request before? */ +  dc.deposit = &deposit; +  { +    MHD_RESULT mhd_ret; + +    if (GNUNET_OK != +        TEH_DB_run_transaction (connection, +                                "precheck deposit", +                                &mhd_ret, +                                &deposit_precheck, +                                &dc)) +    { +      GNUNET_JSON_parse_free (spec); +      return mhd_ret; +    } +  } + +  /* new deposit */ +  dc.exchange_timestamp = GNUNET_TIME_absolute_get (); +  (void) GNUNET_TIME_round_abs (&dc.exchange_timestamp);    /* check denomination exists and is valid */    {      struct TEH_KS_StateHandle *key_state; @@ -400,7 +426,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,      enum TALER_ErrorCode ec;      unsigned int hc; -    key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); +    key_state = TEH_KS_acquire (dc.exchange_timestamp);      if (NULL == key_state)      {        TALER_LOG_ERROR ("Lacking keys to operate\n"); @@ -494,7 +520,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,        .purpose.size = htonl (sizeof (dr)),        .h_contract_terms = deposit.h_contract_terms,        .h_wire = deposit.h_wire, -      .timestamp = GNUNET_TIME_absolute_hton (deposit.timestamp), +      .wallet_timestamp = GNUNET_TIME_absolute_hton (deposit.timestamp),        .refund_deadline = GNUNET_TIME_absolute_hton (deposit.refund_deadline),        .merchant = deposit.merchant_pub,        .coin_pub = deposit.coin.coin_pub @@ -520,7 +546,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,    }    /* execute transaction */ -  dc.deposit = &deposit;    {      MHD_RESULT mhd_ret; @@ -549,7 +574,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,                                   &deposit.coin.coin_pub,                                   &deposit.h_wire,                                   &deposit.h_contract_terms, -                                 deposit.timestamp, +                                 dc.exchange_timestamp,                                   deposit.refund_deadline,                                   &deposit.merchant_pub,                                   &amount_without_fee); diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c index 152d2dad..fbb5da35 100644 --- a/src/exchange/taler-exchange-httpd_keystate.c +++ b/src/exchange/taler-exchange-httpd_keystate.c @@ -1,6 +1,6 @@  /*    This file is part of TALER -  Copyright (C) 2014--2019 Taler Systems SA +  Copyright (C) 2014--2020 Taler Systems SA    TALER is free software; you can redistribute it and/or modify it under the    terms of the GNU Affero General Public License as published by the Free Software @@ -44,7 +44,7 @@   * #TALER_PROTOCOL_CURRENT and #TALER_PROTOCOL_AGE in   * exchange_api_handle.c!   */ -#define EXCHANGE_PROTOCOL_VERSION "7:0:0" +#define EXCHANGE_PROTOCOL_VERSION "8:0:0"  /** @@ -801,7 +801,7 @@ reload_keys_denom_iter (void *cls,      handle_signal (SIGTERM);      return GNUNET_SYSERR;    } - +  GNUNET_assert (NULL != dki->denom_priv.rsa_private_key);    GNUNET_log (GNUNET_ERROR_TYPE_INFO,                "Adding denomination key `%s' (%s) to active set\n",                alias, @@ -1660,6 +1660,9 @@ reload_public_denoms_cb (                  GNUNET_h2s (&issue->properties.denom_hash));      return;    } +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Loaded denomination key %s from DB, no private key (hopefully revoked!)\n", +              GNUNET_h2s (&issue->properties.denom_hash));    /* we can assert here as we checked for duplicates just above */    GNUNET_assert (GNUNET_OK == ret);  } diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c index 7c2b149f..a6a2c3d6 100644 --- a/src/exchange/taler-exchange-httpd_refund.c +++ b/src/exchange/taler-exchange-httpd_refund.c @@ -73,12 +73,13 @@ reply_refund_success (struct MHD_Connection *connection,                                         TALER_EC_EXCHANGE_BAD_CONFIGURATION,                                         "no online signing key");    } -  return TALER_MHD_reply_json_pack (connection, -                                    MHD_HTTP_OK, -                                    "{s:s, s:o, s:o}", -                                    "status", "REFUND_OK", -                                    "sig", GNUNET_JSON_from_data_auto (&sig), -                                    "pub", GNUNET_JSON_from_data_auto (&pub)); +  return TALER_MHD_reply_json_pack ( +    connection, +    MHD_HTTP_OK, +    "{s:o, s:o, s:o}", +    "refund_fee", TALER_JSON_from_amount (&refund->refund_fee), +    "exchange_sig", GNUNET_JSON_from_data_auto (&sig), +    "exchange_pub", GNUNET_JSON_from_data_auto (&pub));  } @@ -246,18 +247,15 @@ refund_transaction (void *cls,    }    /* check currency is compatible */ -  if ( (GNUNET_YES != -        TALER_amount_cmp_currency (&refund->details.refund_amount, -                                   &dep->amount_with_fee)) || -       (GNUNET_YES != -        TALER_amount_cmp_currency (&refund->details.refund_fee, -                                   &dep->deposit_fee)) ) +  if (GNUNET_YES != +      TALER_amount_cmp_currency (&refund->details.refund_amount, +                                 &dep->amount_with_fee))    {      GNUNET_break_op (0); /* currency mismatch */      TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,                                              tl);      *mhd_ret = TALER_MHD_reply_with_error (connection, -                                           MHD_HTTP_PRECONDITION_FAILED, +                                           MHD_HTTP_BAD_REQUEST,                                             TALER_EC_REFUND_CURRENCY_MISMATCH,                                             "currencies involved do not match");      return GNUNET_DB_STATUS_HARD_ERROR; @@ -339,15 +337,14 @@ refund_transaction (void *cls,   * the fee structure, so this is not done here.   *   * @param connection the MHD connection to handle - * @param refund information about the refund + * @param[in,out] refund information about the refund   * @return MHD result code   */  static MHD_RESULT  verify_and_execute_refund (struct MHD_Connection *connection, -                           const struct TALER_EXCHANGEDB_Refund *refund) +                           struct TALER_EXCHANGEDB_Refund *refund)  {    struct GNUNET_HashCode denom_hash; -  struct TALER_Amount expect_fee;    {      struct TALER_RefundRequestPS rr = { @@ -361,8 +358,6 @@ verify_and_execute_refund (struct MHD_Connection *connection,      TALER_amount_hton (&rr.refund_amount,                         &refund->details.refund_amount); -    TALER_amount_hton (&rr.refund_fee, -                       &refund->details.refund_fee);      if (GNUNET_OK !=          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,                                      &rr, @@ -429,43 +424,12 @@ verify_and_execute_refund (struct MHD_Connection *connection,                                             ec,                                             "denomination not found, but coin known");        } -      TALER_amount_ntoh (&expect_fee, +      TALER_amount_ntoh (&refund->details.refund_fee,                           &dki->issue.properties.fee_refund);      }      TEH_KS_release (key_state);    } -  /* Check refund fee matches fee of denomination key! */ -  if (GNUNET_YES != -      TALER_amount_cmp_currency (&expect_fee, -                                 &refund->details.refund_fee) ) -  { -    GNUNET_break_op (0); -    return TALER_MHD_reply_with_error (connection, -                                       MHD_HTTP_BAD_REQUEST, -                                       TALER_EC_REFUND_FEE_CURRENCY_MISMATCH, -                                       "refund_fee"); -  } -  { -    int fee_cmp; - -    fee_cmp = TALER_amount_cmp (&refund->details.refund_fee, -                                &expect_fee); -    if (-1 == fee_cmp) -    { -      return TALER_MHD_reply_with_error (connection, -                                         MHD_HTTP_BAD_REQUEST, -                                         TALER_EC_REFUND_FEE_TOO_LOW, -                                         "refund_fee"); -    } -    if (1 == fee_cmp) -    { -      GNUNET_log (GNUNET_ERROR_TYPE_INFO, -                  "Refund fee proposed by merchant is higher than necessary.\n"); -    } -  } - -    /* Finally run the actual transaction logic */    {      MHD_RESULT mhd_ret; @@ -502,16 +466,20 @@ TEH_handler_refund (struct MHD_Connection *connection,                      const struct TALER_CoinSpendPublicKeyP *coin_pub,                      const json_t *root)  { -  struct TALER_EXCHANGEDB_Refund refund; +  struct TALER_EXCHANGEDB_Refund refund = { +    .details.refund_fee.currency = {0}                                        /* set to invalid, just to be sure */ +  };    struct GNUNET_JSON_Specification spec[] = { -    TALER_JSON_spec_amount ("refund_amount", &refund.details.refund_amount), -    TALER_JSON_spec_amount ("refund_fee", &refund.details.refund_fee), +    TALER_JSON_spec_amount ("refund_amount", +                            &refund.details.refund_amount),      GNUNET_JSON_spec_fixed_auto ("h_contract_terms",                                   &refund.details.h_contract_terms), -    GNUNET_JSON_spec_fixed_auto ("merchant_pub", &refund.details.merchant_pub), +    GNUNET_JSON_spec_fixed_auto ("merchant_pub", +                                 &refund.details.merchant_pub),      GNUNET_JSON_spec_uint64 ("rtransaction_id",                               &refund.details.rtransaction_id), -    GNUNET_JSON_spec_fixed_auto ("merchant_sig", &refund.details.merchant_sig), +    GNUNET_JSON_spec_fixed_auto ("merchant_sig", +                                 &refund.details.merchant_sig),      GNUNET_JSON_spec_end ()    }; @@ -527,27 +495,6 @@ TEH_handler_refund (struct MHD_Connection *connection,      if (GNUNET_NO == res)        return MHD_YES; /* failure */    } -  if (GNUNET_YES != -      TALER_amount_cmp_currency (&refund.details.refund_amount, -                                 &refund.details.refund_fee) ) -  { -    GNUNET_break_op (0); -    GNUNET_JSON_parse_free (spec); -    return TALER_MHD_reply_with_error (connection, -                                       MHD_HTTP_BAD_REQUEST, -                                       TALER_EC_REFUND_FEE_CURRENCY_MISMATCH, -                                       "refund_amount or refund_fee"); -  } -  if (-1 == TALER_amount_cmp (&refund.details.refund_amount, -                              &refund.details.refund_fee) ) -  { -    GNUNET_break_op (0); -    GNUNET_JSON_parse_free (spec); -    return TALER_MHD_reply_with_error (connection, -                                       MHD_HTTP_BAD_REQUEST, -                                       TALER_EC_REFUND_FEE_ABOVE_AMOUNT, -                                       "refund_amount"); -  }    {      MHD_RESULT res; diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index 06673afc..f6595161 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -66,7 +66,7 @@ TEH_RESPONSE_compile_transaction_history (            .purpose.size = htonl (sizeof (dr)),            .h_contract_terms = deposit->h_contract_terms,            .h_wire = deposit->h_wire, -          .timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp), +          .wallet_timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp),            .refund_deadline = GNUNET_TIME_absolute_hton (              deposit->refund_deadline),            .merchant = deposit->merchant_pub, @@ -185,8 +185,6 @@ TEH_RESPONSE_compile_transaction_history (          TALER_amount_hton (&rr.refund_amount,                             &refund->refund_amount); -        TALER_amount_hton (&rr.refund_fee, -                           &refund->refund_fee);  #if ENABLE_SANITY_CHECKS          /* internal sanity check before we hand out a bogus sig... */          if (GNUNET_OK != diff --git a/src/exchange/taler-exchange-httpd_wire.c b/src/exchange/taler-exchange-httpd_wire.c index 38bbad4a..471fa4fa 100644 --- a/src/exchange/taler-exchange-httpd_wire.c +++ b/src/exchange/taler-exchange-httpd_wire.c @@ -341,6 +341,8 @@ TEH_WIRE_init (const struct GNUNET_CONFIGURATION_Handle *cfg)                                      &ret);      if (GNUNET_OK != ret)      { +      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                  "Error setting up bank accounts\n");        TEH_WIRE_done ();        return GNUNET_SYSERR;      } @@ -349,6 +351,8 @@ TEH_WIRE_init (const struct GNUNET_CONFIGURATION_Handle *cfg)         (0 == json_object_size (wire_fee_object)) )    {      TEH_WIRE_done (); +    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "No bank accounts configured\n");      return GNUNET_SYSERR;    }    wire_methods = json_pack ("{s:O, s:O, s:o}", diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c index 4d662e71..c4c72d6a 100644 --- a/src/exchange/taler-exchange-httpd_withdraw.c +++ b/src/exchange/taler-exchange-httpd_withdraw.c @@ -306,8 +306,6 @@ withdraw_transaction (void *cls,  #endif    wc->collectable.denom_pub_hash = wc->denom_pub_hash;    wc->collectable.amount_with_fee = wc->amount_required; -  TALER_amount_ntoh (&wc->collectable.withdraw_fee, -                     &wc->dki->issue.properties.fee_withdraw);    wc->collectable.reserve_pub = wc->wsrd.reserve_pub;    wc->collectable.h_coin_envelope = wc->wsrd.h_coin_envelope;    wc->collectable.reserve_sig = wc->signature; @@ -436,8 +434,6 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,      }      TALER_amount_hton (&wc.wsrd.amount_with_fee,                         &wc.amount_required); -    TALER_amount_hton (&wc.wsrd.withdraw_fee, -                       &fee_withdraw);    }    /* verify signature! */  | 
