diff options
| -rw-r--r-- | src/exchange/taler-exchange-httpd.c | 44 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_attest.c | 27 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_attest.h | 8 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_open.c | 15 | ||||
| -rw-r--r-- | src/exchangedb/common-0001.sql | 5 | ||||
| -rw-r--r-- | src/exchangedb/exchange-0001-part.sql | 4 | ||||
| -rw-r--r-- | src/exchangedb/pg_insert_records_by_table.c | 7 | ||||
| -rw-r--r-- | src/exchangedb/procedures.sql | 41 | ||||
| -rw-r--r-- | src/include/taler_exchangedb_plugin.h | 1 | ||||
| -rw-r--r-- | src/lib/exchange_api_reserves_attest.c | 8 | ||||
| -rw-r--r-- | src/lib/exchange_api_reserves_get_attestable.c | 4 | ||||
| -rw-r--r-- | src/testing/test_exchange_p2p.c | 14 | ||||
| -rw-r--r-- | src/testing/testing_api_cmd_reserve_open.c | 6 | 
13 files changed, 100 insertions, 84 deletions
| diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index a45c9d2b..34f93879 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -389,10 +389,6 @@ handle_post_reserves (struct TEH_RequestContext *rc,        .handler = &TEH_handler_reserves_open      },      { -      .op = "attest", -      .handler = &TEH_handler_reserves_attest -    }, -    {        .op = "close",        .handler = &TEH_handler_reserves_close      }, @@ -1055,27 +1051,6 @@ handle_post_auditors (struct TEH_RequestContext *rc,  /** - * Handle a GET "/reserves/$RID/$XXX" request. - * - * @param rc request context - * @param args array of additional options (length: 1, just the reserve_pub) - * @return MHD result code - */ -static MHD_RESULT -handler_reserves_get3 (struct TEH_RequestContext *rc, -                       const char *const args[3]) -{ -  if (0 == strcmp (args[2], -                   "attest")) -    return TEH_handler_reserves_get_attest (rc, -                                            args); -  GNUNET_break_op (0); -  return r404 (rc->connection, -               "/reserves/$RID/*"); -} - - -/**   * Handle incoming HTTP request.   *   * @param cls closure for MHD daemon (unused) @@ -1190,15 +1165,21 @@ handle_mhd_request (void *cls,      },      {        .url = "reserves", +      .method = MHD_HTTP_METHOD_POST, +      .handler.post = &handle_post_reserves, +      .nargs = 2 +    }, +    { +      .url = "reserves-attest",        .method = MHD_HTTP_METHOD_GET, -      .handler.get = &handler_reserves_get3, -      .nargs = 3 +      .handler.get = &TEH_handler_reserves_get_attest, +      .nargs = 1      },      { -      .url = "reserves", +      .url = "reserves-attest",        .method = MHD_HTTP_METHOD_POST, -      .handler.post = &handle_post_reserves, -      .nargs = 2 +      .handler.post = &TEH_handler_reserves_attest, +      .nargs = 1      },      /* coins */      { @@ -1441,7 +1422,8 @@ handle_mhd_request (void *cls,          continue;        found = true;        /* The URL is a match!  What we now do depends on the method. */ -      if (0 == strcasecmp (method, MHD_HTTP_METHOD_OPTIONS)) +      if (0 == strcasecmp (method, +                           MHD_HTTP_METHOD_OPTIONS))        {          GNUNET_async_scope_restore (&old_scope);          return TALER_MHD_reply_cors_preflight (connection); diff --git a/src/exchange/taler-exchange-httpd_reserves_attest.c b/src/exchange/taler-exchange-httpd_reserves_attest.c index a740bb25..f88f2c30 100644 --- a/src/exchange/taler-exchange-httpd_reserves_attest.c +++ b/src/exchange/taler-exchange-httpd_reserves_attest.c @@ -48,7 +48,7 @@ struct ReserveAttestContext    /**     * Public key of the reserve the inquiry is about.     */ -  const struct TALER_ReservePublicKeyP *reserve_pub; +  struct TALER_ReservePublicKeyP reserve_pub;    /**     * Hash of the payto URI of this reserve. @@ -122,7 +122,7 @@ reply_reserve_attest_success (struct MHD_Connection *connection,      &TEH_keys_exchange_sign_,      now,      rhc->etime, -    rhc->reserve_pub, +    &rhc->reserve_pub,      rhc->json_attest,      &exchange_pub,      &exchange_sig); @@ -273,8 +273,8 @@ reserve_attest_transaction (void *cls,  MHD_RESULT  TEH_handler_reserves_attest (struct TEH_RequestContext *rc, -                             const struct TALER_ReservePublicKeyP *reserve_pub, -                             const json_t *root) +                             const json_t *root, +                             const char *const args[1])  {    struct ReserveAttestContext rsc = {      .etime = GNUNET_TIME_UNIT_FOREVER_TS @@ -291,7 +291,18 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,    };    struct GNUNET_TIME_Timestamp now; -  rsc.reserve_pub = reserve_pub; +  if (GNUNET_OK != +      GNUNET_STRINGS_string_to_data (args[0], +                                     strlen (args[0]), +                                     &rsc.reserve_pub, +                                     sizeof (rsc.reserve_pub))) +  { +    GNUNET_break_op (0); +    return TALER_MHD_reply_with_error (rc->connection, +                                       MHD_HTTP_BAD_REQUEST, +                                       TALER_EC_GENERIC_RESERVE_PUB_MALFORMED, +                                       args[0]); +  }    {      enum GNUNET_GenericReturnValue res; @@ -324,7 +335,7 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,    if (GNUNET_OK !=        TALER_wallet_reserve_attest_request_verify (rsc.timestamp,                                                    rsc.details, -                                                  reserve_pub, +                                                  &rsc.reserve_pub,                                                    &rsc.reserve_sig))    {      GNUNET_break_op (0); @@ -338,7 +349,7 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,      char *payto_uri;      payto_uri = TALER_reserve_make_payto (TEH_base_url, -                                          rsc.reserve_pub); +                                          &rsc.reserve_pub);      TALER_payto_hash (payto_uri,                        &rsc.h_payto);      GNUNET_free (payto_uri); @@ -360,7 +371,7 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,      return TALER_MHD_reply_with_error (rc->connection,                                         MHD_HTTP_NOT_FOUND,                                         TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN, -                                       NULL); +                                       args[0]);    }    if (TALER_EC_NONE != rsc.ec)    { diff --git a/src/exchange/taler-exchange-httpd_reserves_attest.h b/src/exchange/taler-exchange-httpd_reserves_attest.h index d5ec8fd7..66bbdf71 100644 --- a/src/exchange/taler-exchange-httpd_reserves_attest.h +++ b/src/exchange/taler-exchange-httpd_reserves_attest.h @@ -26,16 +26,16 @@  /** - * Handle a POST "/reserves/$RID/attest" request. + * Handle a POST "/reserves-attest/$RID" request.   *   * @param rc request context - * @param reserve_pub public key of the reserve   * @param root uploaded body from the client + * @param args args[0] has public key of the reserve   * @return MHD result code   */  MHD_RESULT  TEH_handler_reserves_attest (struct TEH_RequestContext *rc, -                             const struct TALER_ReservePublicKeyP *reserve_pub, -                             const json_t *root); +                             const json_t *root, +                             const char *const args[1]);  #endif diff --git a/src/exchange/taler-exchange-httpd_reserves_open.c b/src/exchange/taler-exchange-httpd_reserves_open.c index 6ad2592f..ced291d7 100644 --- a/src/exchange/taler-exchange-httpd_reserves_open.c +++ b/src/exchange/taler-exchange-httpd_reserves_open.c @@ -108,6 +108,7 @@ struct ReserveOpenContext     * for the operation.     */    bool no_funds; +  }; @@ -122,6 +123,8 @@ static MHD_RESULT  reply_reserve_open_success (struct MHD_Connection *connection,                              const struct ReserveOpenContext *rsc)  { +  struct GNUNET_TIME_Timestamp now; +  struct GNUNET_TIME_Timestamp re;    unsigned int status;    status = MHD_HTTP_OK; @@ -129,11 +132,18 @@ reply_reserve_open_success (struct MHD_Connection *connection,                                   <,                                   rsc->desired_expiration))      status = MHD_HTTP_PAYMENT_REQUIRED; +  now = GNUNET_TIME_timestamp_get (); +  if (GNUNET_TIME_timestamp_cmp (rsc->reserve_expiration, +                                 <, +                                 now)) +    re = now; +  else +    re = rsc->reserve_expiration;    return TALER_MHD_REPLY_JSON_PACK (      connection,      status,      GNUNET_JSON_pack_timestamp ("reserve_expiration", -                                rsc->reserve_expiration), +                                re),      TALER_JSON_pack_amount ("open_cost",                              &rsc->open_cost));  } @@ -234,7 +244,8 @@ reserve_open_transaction (void *cls,    }    GNUNET_log (GNUNET_ERROR_TYPE_INFO, -              "Do reserve open\n"); +              "Do reserve open with reserve payment of %s\n", +              TALER_amount2s (&rsc->total));    qs = TEH_plugin->do_reserve_open (TEH_plugin->cls,                                      /* inputs */                                      rsc->reserve_pub, diff --git a/src/exchangedb/common-0001.sql b/src/exchangedb/common-0001.sql index 21f53110..68d8643e 100644 --- a/src/exchangedb/common-0001.sql +++ b/src/exchangedb/common-0001.sql @@ -460,8 +460,7 @@ BEGIN      'CREATE TABLE IF NOT EXISTS %I'        '(reserve_open_deposit_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE / PRIMARY KEY'        ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)' -      ',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=32)' -      ',request_timestamp INT8 NOT NULL' +      ',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32)'        ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)'        ',coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)'        ',contribution_val INT8 NOT NULL' @@ -482,7 +481,7 @@ BEGIN    EXECUTE FORMAT (      'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_reserve '      'ON ' || table_name || ' ' -    '(reserve_pub,request_timestamp);' +    '(reserve_pub);'    );  END  $$; diff --git a/src/exchangedb/exchange-0001-part.sql b/src/exchangedb/exchange-0001-part.sql index c9c3e2f0..48515a47 100644 --- a/src/exchangedb/exchange-0001-part.sql +++ b/src/exchangedb/exchange-0001-part.sql @@ -259,8 +259,8 @@ SELECT create_table_reserves_open_deposits();  COMMENT ON TABLE reserves_open_deposits    IS 'coin contributions paying for a reserve to remain open'; -COMMENT ON COLUMN reserves_open_deposits.request_timestamp -  IS 'Identifies the specific reserve open request being paid for.'; +COMMENT ON COLUMN reserves_open_deposits.reserve_pub +  IS 'Identifies the specific reserve being paid for (possibly together with reserve_sig).';  CREATE TABLE IF NOT EXISTS reserves_open_deposits_default    PARTITION OF reserves_open_deposits diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c index f70cce22..90d38987 100644 --- a/src/exchangedb/pg_insert_records_by_table.c +++ b/src/exchangedb/pg_insert_records_by_table.c @@ -358,8 +358,6 @@ irbt_cb_table_reserves_open_requests (struct PostgresClosure *pg,    struct GNUNET_PQ_QueryParam params[] = {      GNUNET_PQ_query_param_uint64 (&td->serial),      GNUNET_PQ_query_param_timestamp ( -      &td->details.reserves_open_requests.request_timestamp), -    GNUNET_PQ_query_param_timestamp (        &td->details.reserves_open_requests.expiration_date),      GNUNET_PQ_query_param_auto_from_type (        &td->details.reserves_open_requests.reserve_sig), @@ -402,8 +400,6 @@ irbt_cb_table_reserves_open_deposits (  {    struct GNUNET_PQ_QueryParam params[] = {      GNUNET_PQ_query_param_uint64 (&td->serial), -    GNUNET_PQ_query_param_timestamp ( -      &td->details.reserves_open_deposits.request_timestamp),      GNUNET_PQ_query_param_auto_from_type (        &td->details.reserves_open_deposits.coin_pub),      GNUNET_PQ_query_param_auto_from_type ( @@ -421,13 +417,12 @@ irbt_cb_table_reserves_open_deposits (             "(reserve_open_deposit_uuid"             ",reserve_sig"             ",reserve_pub" -           ",request_timestamp"             ",coin_pub"             ",coin_sig"             ",contribution_val"             ",contribution_frac"             ") VALUES " -           "($1, $2, $3, $4, $5, $6, $7, $8);"); +           "($1, $2, $3, $4, $5, $6, $7);");    return GNUNET_PQ_eval_prepared_non_select (pg->conn,                                               "insert_into_table_reserves_open_deposits",                                               params); diff --git a/src/exchangedb/procedures.sql b/src/exchangedb/procedures.sql index 90fb7d32..912a37db 100644 --- a/src/exchangedb/procedures.sql +++ b/src/exchangedb/procedures.sql @@ -2119,7 +2119,6 @@ BEGIN  INSERT INTO exchange.reserves_open_deposits    (reserve_sig    ,reserve_pub -  ,request_timestamp    ,coin_pub    ,coin_sig    ,contribution_val @@ -2128,7 +2127,6 @@ INSERT INTO exchange.reserves_open_deposits    VALUES    (in_reserve_sig    ,in_reserve_pub -  ,in_request_timestamp    ,in_coin_pub    ,in_coin_sig    ,in_coin_total_val @@ -2237,8 +2235,9 @@ WHERE  IF NOT FOUND  THEN -  -- FIXME: do we need to set a 'not found'?  -  RETURN;   +  -- FIXME: do we need to set a 'not found'? +  RAISE NOTICE 'reserve not found'; +  RETURN;  END IF;  -- Do not allow expiration time to start in the past already @@ -2272,9 +2271,10 @@ THEN    my_purses_allowed = my_purses_allowed + (in_default_purse_limit * my_years_tmp);  END IF; +  -- Compute cost based on annual fees  IF (my_years > 0) -THEN  +THEN    my_cost_val = my_years * in_open_fee_val;    my_cost_tmp = my_years * in_open_fee_frac / 100000000;    IF (CAST (my_cost_val + my_cost_tmp AS INT8) < my_cost_val) @@ -2282,8 +2282,9 @@ THEN      out_open_cost_val=9223372036854775807;      out_open_cost_frac=2147483647;      out_final_expiration=my_expiration_date; -    out_no_funds=true; -    RETURN; +    out_no_funds=FALSE; +    RAISE NOTICE 'arithmetic issue computing amount'; +  RETURN;    END IF;    my_cost_val = CAST (my_cost_val + my_cost_tmp AS INT8);    my_cost_frac = my_years * in_open_fee_frac % 100000000; @@ -2297,6 +2298,7 @@ THEN    out_open_cost_val = 0;    out_open_cost_frac = 0;    out_no_funds=FALSE; +  RAISE NOTICE 'no change required';    RETURN;  END IF; @@ -2305,10 +2307,22 @@ IF ( (in_total_paid_val < my_cost_val) OR       ( (in_total_paid_val = my_cost_val) AND         (in_total_paid_frac < my_cost_frac) ) )  THEN -  out_final_expiration=my_reserve_expiration;    out_open_cost_val = my_cost_val;    out_open_cost_frac = my_cost_frac; -  out_no_funds=TRUE; +  out_no_funds=FALSE; +  -- We must return a failure, which is indicated by +  -- the expiration being below the desired expiration. +  IF (my_reserve_expiration >= in_desired_expiration) +  THEN +    -- This case is relevant especially if the purse +    -- count was to be increased and the payment was +    -- insufficient to cover this for the full period. +    RAISE NOTICE 'forcing low expiration time'; +    out_final_expiration = 0; +  ELSE +    out_final_expiration = my_reserve_expiration; +  END IF; +  RAISE NOTICE 'amount paid too low';    RETURN;  END IF; @@ -2329,11 +2343,12 @@ ELSE      my_balance_val=0;      my_balance_frac=my_balance_frac - in_reserve_payment_frac;    ELSE -    out_final_expiration=my_reserve_expiration; +    out_final_expiration = my_reserve_expiration;      out_open_cost_val = my_cost_val;      out_open_cost_frac = my_cost_frac;      out_no_funds=TRUE; -    RETURN; +    RAISE NOTICE 'reserve balance too low'; +  RETURN;    END IF;  END IF; @@ -2341,12 +2356,12 @@ UPDATE reserves SET    current_balance_val=my_balance_val   ,current_balance_frac=my_balance_frac   ,gc_date=my_reserve_expiration + in_reserve_gc_delay - ,expiration_date=my_reserve_expiration + ,expiration_date=my_expiration_date   ,purses_allowed=my_purses_allowed  WHERE   reserve_pub=in_reserve_pub; -out_final_expiration=my_reserve_expiration; +out_final_expiration=my_expiration_date;  out_open_cost_val = my_cost_val;  out_open_cost_frac = my_cost_frac;  out_no_funds=FALSE; diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 008909c3..06fa2479 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -331,7 +331,6 @@ struct TALER_EXCHANGEDB_TableData      struct      {        struct TALER_ReservePublicKeyP reserve_pub; -      struct GNUNET_TIME_Timestamp request_timestamp;        struct TALER_CoinSpendPublicKeyP coin_pub;        struct TALER_CoinSpendSignatureP coin_sig;        struct TALER_ReserveSignatureP reserve_sig; diff --git a/src/lib/exchange_api_reserves_attest.c b/src/lib/exchange_api_reserves_attest.c index a7a89a2e..c1cf8276 100644 --- a/src/lib/exchange_api_reserves_attest.c +++ b/src/lib/exchange_api_reserves_attest.c @@ -16,7 +16,7 @@  */  /**   * @file lib/exchange_api_reserves_attest.c - * @brief Implementation of the POST /reserves/$RESERVE_PUB/attest requests + * @brief Implementation of the POST /reserves-attest/$RESERVE_PUB requests   * @author Christian Grothoff   */  #include "platform.h" @@ -33,7 +33,7 @@  /** - * @brief A /reserves/$RID/attest Handle + * @brief A /reserves-attest/$RID Handle   */  struct TALER_EXCHANGE_ReservesAttestHandle  { @@ -141,7 +141,7 @@ handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh,  /**   * Function called when we're done processing the - * HTTP /reserves/$RID/attest request. + * HTTP /reserves-attest/$RID request.   *   * @param cls the `struct TALER_EXCHANGE_ReservesAttestHandle`   * @param response_code HTTP response code, 0 on error @@ -280,7 +280,7 @@ TALER_EXCHANGE_reserves_attest (      *end = '\0';      GNUNET_snprintf (arg_str,                       sizeof (arg_str), -                     "/reserves/%s/attest", +                     "/reserves-attest/%s",                       pub_str);    }    rsh->url = TEAH_path_to_url (exchange, diff --git a/src/lib/exchange_api_reserves_get_attestable.c b/src/lib/exchange_api_reserves_get_attestable.c index 401418cd..3a5fd25d 100644 --- a/src/lib/exchange_api_reserves_get_attestable.c +++ b/src/lib/exchange_api_reserves_get_attestable.c @@ -133,7 +133,7 @@ handle_reserves_get_attestable_ok (  /**   * Function called when we're done processing the - * HTTP GET /reserves/$RID/attest request. + * HTTP GET /reserves-attest/$RID request.   *   * @param cls the `struct TALER_EXCHANGE_ReservesGetAttestableHandle`   * @param response_code HTTP response code, 0 on error @@ -241,7 +241,7 @@ TALER_EXCHANGE_reserves_get_attestable (      *end = '\0';      GNUNET_snprintf (arg_str,                       sizeof (arg_str), -                     "/reserves/%s/attest", +                     "/reserves-attest/%s",                       pub_str);    }    rgah = GNUNET_new (struct TALER_EXCHANGE_ReservesGetAttestHandle); diff --git a/src/testing/test_exchange_p2p.c b/src/testing/test_exchange_p2p.c index d0a0a989..693391c6 100644 --- a/src/testing/test_exchange_p2p.c +++ b/src/testing/test_exchange_p2p.c @@ -382,7 +382,7 @@ run (void *cls,                                      MHD_HTTP_PAYMENT_REQUIRED, // FIXME: or CONFLICT?                                      NULL,                                      NULL), -    TALER_TESTING_cmd_reserve_open ("reserve-open-101-ok", +    TALER_TESTING_cmd_reserve_open ("reserve-open-101-ok-a",                                      "create-reserve-101",                                      "EUR:0.01",                                      GNUNET_TIME_UNIT_MONTHS, @@ -394,30 +394,32 @@ run (void *cls,                                "create-reserve-101",                                "EUR:1.03",                                MHD_HTTP_OK), -    TALER_TESTING_cmd_reserve_open ("reserve-open-101-ok", +    TALER_TESTING_cmd_reserve_open ("reserve-open-101-ok-b",                                      "create-reserve-101",                                      "EUR:0",                                      GNUNET_TIME_UNIT_MONTHS,                                      2, /* min purses */                                      MHD_HTTP_OK,                                      "withdraw-coin-100", -                                    "EUR:0.02", +                                    "EUR:0.03", /* 0.02 for the reserve open, 0.01 for deposit fee */                                      NULL,                                      NULL), -    /* FIXME: use purse quota here */ +    /* FIXME: use purse creation with purse quota here */      TALER_TESTING_cmd_reserve_get_attestable ("reserve-101-attestable",                                                "create-reserve-101", -                                              MHD_HTTP_OK, +                                              MHD_HTTP_NOT_FOUND,                                                NULL),      TALER_TESTING_cmd_reserve_get_attestable ("reserve-101-attest",                                                "create-reserve-101", -                                              MHD_HTTP_CONFLICT, +                                              MHD_HTTP_NOT_FOUND,                                                "nx-attribute-name",                                                NULL), +#if 0      TALER_TESTING_cmd_reserve_close ("reserve-101-close",                                       "create-reserve-101",                                       NULL, /* to origin */                                       MHD_HTTP_OK), +#endif      TALER_TESTING_cmd_end ()    }; diff --git a/src/testing/testing_api_cmd_reserve_open.c b/src/testing/testing_api_cmd_reserve_open.c index 67209d02..cc0e649d 100644 --- a/src/testing/testing_api_cmd_reserve_open.c +++ b/src/testing/testing_api_cmd_reserve_open.c @@ -319,6 +319,7 @@ TALER_TESTING_cmd_reserve_open (const char *label,      ss->cpl++;    va_end (ap);    GNUNET_assert (0 == (ss->cpl % 2)); +  ss->cpl /= 2; /* name and amount per coin */    ss->cd = GNUNET_new_array (ss->cpl,                               struct CoinDetail);    i = 0; @@ -326,11 +327,12 @@ TALER_TESTING_cmd_reserve_open (const char *label,              expected_response_code);    while (NULL != (name = va_arg (ap, const char *)))    { -    ss->cd[i].name = name; +    struct CoinDetail *cd = &ss->cd[i]; +    cd->name = name;      GNUNET_assert (GNUNET_OK ==                     TALER_string_to_amount (va_arg (ap,                                                     const char *), -                                           &ss->cd[i].amount)); +                                           &cd->amount));      i++;    }    va_end (ap); | 
