diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_close.c | 5 | ||||
| -rw-r--r-- | src/exchange/taler-exchange-httpd_reserves_open.c | 1 | ||||
| -rw-r--r-- | src/exchangedb/common-0001.sql | 8 | ||||
| -rw-r--r-- | src/exchangedb/pg_insert_close_request.c | 39 | ||||
| -rw-r--r-- | src/exchangedb/pg_insert_close_request.h | 6 | ||||
| -rw-r--r-- | src/exchangedb/pg_insert_reserve_open_deposit.c | 8 | ||||
| -rw-r--r-- | src/exchangedb/pg_insert_reserve_open_deposit.h | 2 | ||||
| -rw-r--r-- | src/exchangedb/pg_iterate_kyc_reference.c | 10 | ||||
| -rw-r--r-- | src/exchangedb/pg_iterate_reserve_close_info.c | 23 | ||||
| -rw-r--r-- | src/exchangedb/pg_select_reserve_close_info.c | 8 | ||||
| -rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 15 | ||||
| -rw-r--r-- | src/exchangedb/procedures.sql | 117 | ||||
| -rw-r--r-- | src/include/taler_exchangedb_plugin.h | 8 | 
13 files changed, 147 insertions, 103 deletions
diff --git a/src/exchange/taler-exchange-httpd_reserves_close.c b/src/exchange/taler-exchange-httpd_reserves_close.c index 6d998bb9..be36f1e7 100644 --- a/src/exchange/taler-exchange-httpd_reserves_close.c +++ b/src/exchange/taler-exchange-httpd_reserves_close.c @@ -297,14 +297,13 @@ reserve_close_transaction (void *cls,      return GNUNET_DB_STATUS_HARD_ERROR;    } -    qs = TEH_plugin->insert_close_request (TEH_plugin->cls,                                           rcc->reserve_pub,                                           payto_uri,                                           &rcc->reserve_sig,                                           rcc->timestamp, -                                         &wf->closing, -                                         &rcc->wire_amount); +                                         &balance, +                                         &wf->closing);    GNUNET_free (payto_uri);    if (GNUNET_DB_STATUS_HARD_ERROR == qs)    { diff --git a/src/exchange/taler-exchange-httpd_reserves_open.c b/src/exchange/taler-exchange-httpd_reserves_open.c index c9f5e401..d446d9b4 100644 --- a/src/exchange/taler-exchange-httpd_reserves_open.c +++ b/src/exchange/taler-exchange-httpd_reserves_open.c @@ -191,6 +191,7 @@ reserve_open_transaction (void *cls,        coin->known_coin_id,        &coin->amount,        &rsc->reserve_sig, +      rsc->reserve_pub,        &insufficient_funds);      /* 0 == qs is fine, then the coin was already         spent for this very operation as identified diff --git a/src/exchangedb/common-0001.sql b/src/exchangedb/common-0001.sql index 4a0aac38..564bf3b3 100644 --- a/src/exchangedb/common-0001.sql +++ b/src/exchangedb/common-0001.sql @@ -459,7 +459,8 @@ BEGIN    PERFORM create_partitioned_table(      'CREATE TABLE IF NOT EXISTS %I'        '(reserve_open_deposit_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE / PRIMARY KEY' -      ',reserve_pub BYTEA NOT NULL' -- REFERENCES reserves (reserve_pub) ON DELETE CASCADE' +      ',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'        ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)'        ',coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)' @@ -496,7 +497,7 @@ BEGIN    EXECUTE FORMAT (      'ALTER TABLE reserves_open_deposits_' || partition_suffix || ' '        'ADD CONSTRAINT reserves_open_deposits_' || partition_suffix || '_coin_unique ' -        'PRIMARY KEY (coin_pub,reserve_pub)' +        'PRIMARY KEY (coin_pub,coin_sig)'    );  END  $$; @@ -1749,6 +1750,9 @@ BEGIN        ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'        ',close_val INT8 NOT NULL'        ',close_frac INT4 NOT NULL' +      ',close_fee_val INT8 NOT NULL' +      ',close_fee_frac INT4 NOT NULL' +      ',payto_uri VARCHAR NOT NULL'        ',PRIMARY KEY (reserve_pub,close_timestamp)'      ') %s ;'      ,table_name diff --git a/src/exchangedb/pg_insert_close_request.c b/src/exchangedb/pg_insert_close_request.c index 3622149a..43ca944f 100644 --- a/src/exchangedb/pg_insert_close_request.c +++ b/src/exchangedb/pg_insert_close_request.c @@ -33,32 +33,35 @@ TEH_PG_insert_close_request (    const char *payto_uri,    const struct TALER_ReserveSignatureP *reserve_sig,    struct GNUNET_TIME_Timestamp request_timestamp, -  const struct TALER_Amount *closing_fee, -  struct TALER_Amount *final_balance) +  const struct TALER_Amount *balance, +  const struct TALER_Amount *closing_fee)  {    struct PostgresClosure *pg = cls; -  // FIXME: deal with payto_uri and closing_fee!!    struct GNUNET_PQ_QueryParam params[] = {      GNUNET_PQ_query_param_auto_from_type (reserve_pub),      GNUNET_PQ_query_param_timestamp (&request_timestamp),      GNUNET_PQ_query_param_auto_from_type (reserve_sig), +    TALER_PQ_query_param_amount (balance), +    TALER_PQ_query_param_amount (closing_fee), +    GNUNET_PQ_query_param_string (payto_uri),      GNUNET_PQ_query_param_end    }; -  struct GNUNET_PQ_ResultSpec rs[] = { -    TALER_PQ_RESULT_SPEC_AMOUNT ("out_final_balance", -                                 final_balance), -    GNUNET_PQ_result_spec_end -  };    PREPARE (pg, -           "call_account_close", -           "SELECT " -           " out_final_balance_val" -           ",out_final_balance_frac" -           " FROM exchange_do_close_request" -           "  ($1, $2, $3)"); -  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, -                                                   "call_account_close", -                                                   params, -                                                   rs); +           "insert_account_close", +           "INSERT INTO close_requests" +           "(reserve_pub" +           ",close_timestamp" +           ",reserve_sig" +           ",close_val" +           ",close_frac," +           ",close_fee_val" +           ",close_fee_frac" +           ",payto_uri" +           ")" +           "VALUES ($1, $2, $3, $4, $5, $6, $7)" +           " ON CONFLICT DO NOTHING;"); +  return GNUNET_PQ_eval_prepared_non_select (pg->conn, +                                             "insert_account_close", +                                             params);  } diff --git a/src/exchangedb/pg_insert_close_request.h b/src/exchangedb/pg_insert_close_request.h index 09404094..c014a10b 100644 --- a/src/exchangedb/pg_insert_close_request.h +++ b/src/exchangedb/pg_insert_close_request.h @@ -34,8 +34,8 @@   * @param payto_uri where to wire the funds   * @param reserve_sig signature affiming that the account is to be closed   * @param request_timestamp time of the close request (client-side?) + * @param balance final balance in the reserve   * @param closing_fee closing fee to charge - * @param[out] final_balance set to the final balance in the account that will be wired back to the origin account   * @return transaction status code   */  enum GNUNET_DB_QueryStatus @@ -45,8 +45,8 @@ TEH_PG_insert_close_request (    const char *payto_uri,    const struct TALER_ReserveSignatureP *reserve_sig,    struct GNUNET_TIME_Timestamp request_timestamp, -  const struct TALER_Amount *closing_fee, -  struct TALER_Amount *final_balance); +  const struct TALER_Amount *balance, +  const struct TALER_Amount *closing_fee);  #endif diff --git a/src/exchangedb/pg_insert_reserve_open_deposit.c b/src/exchangedb/pg_insert_reserve_open_deposit.c index c767bfee..8bf70e7b 100644 --- a/src/exchangedb/pg_insert_reserve_open_deposit.c +++ b/src/exchangedb/pg_insert_reserve_open_deposit.c @@ -34,6 +34,7 @@ TEH_PG_insert_reserve_open_deposit (    uint64_t known_coin_id,    const struct TALER_Amount *coin_total,    const struct TALER_ReserveSignatureP *reserve_sig, +  const struct TALER_ReservePublicKeyP *reserve_pub,    bool *insufficient_funds)  {    struct PostgresClosure *pg = cls; @@ -42,11 +43,12 @@ TEH_PG_insert_reserve_open_deposit (      GNUNET_PQ_query_param_uint64 (&known_coin_id),      GNUNET_PQ_query_param_auto_from_type (coin_sig),      GNUNET_PQ_query_param_auto_from_type (reserve_sig), +    GNUNET_PQ_query_param_auto_from_type (reserve_pub),      TALER_PQ_query_param_amount (coin_total),      GNUNET_PQ_query_param_end    };    struct GNUNET_PQ_ResultSpec rs[] = { -    GNUNET_PQ_result_spec_bool ("insufficient_funds", +    GNUNET_PQ_result_spec_bool ("out_insufficient_funds",                                  insufficient_funds),      GNUNET_PQ_result_spec_end    }; @@ -54,9 +56,9 @@ TEH_PG_insert_reserve_open_deposit (    PREPARE (pg,             "insert_reserve_open_deposit",             "SELECT " -           " insufficient_funds" +           " out_insufficient_funds"             " FROM exchange_do_reserve_open_deposit" -           " ($1,$2,$3,$4,$5,$6);"); +           " ($1,$2,$3,$4,$5,$6,$7);");    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,                                                     "insert_reserve_open_deposit",                                                     params, diff --git a/src/exchangedb/pg_insert_reserve_open_deposit.h b/src/exchangedb/pg_insert_reserve_open_deposit.h index 335fda52..7eb2fe09 100644 --- a/src/exchangedb/pg_insert_reserve_open_deposit.h +++ b/src/exchangedb/pg_insert_reserve_open_deposit.h @@ -36,6 +36,7 @@   * @param known_coin_id ID of the coin in the known_coins table   * @param coin_total amount to be spent of the coin (including deposit fee)   * @param reserve_sig signature by the reserve affirming the open operation + * @param reserve_pub public key of the reserve being opened   * @param[out] insufficient_funds set to true if the coin's balance is insufficient, otherwise to false   * @return transaction status code, 0 if operation is already in the DB   */ @@ -47,6 +48,7 @@ TEH_PG_insert_reserve_open_deposit (    uint64_t known_coin_id,    const struct TALER_Amount *coin_total,    const struct TALER_ReserveSignatureP *reserve_sig, +  const struct TALER_ReservePublicKeyP *reserve_pub,    bool *insufficient_funds);  #endif diff --git a/src/exchangedb/pg_iterate_kyc_reference.c b/src/exchangedb/pg_iterate_kyc_reference.c index 4a94722c..772c51e2 100644 --- a/src/exchangedb/pg_iterate_kyc_reference.c +++ b/src/exchangedb/pg_iterate_kyc_reference.c @@ -69,11 +69,11 @@ iterate_kyc_reference_cb (void *cls,      char *provider_user_id;      char *legitimization_id;      struct GNUNET_PQ_ResultSpec rs[] = { -      GNUNET_PQ_result_spec_string ("section_name", +      GNUNET_PQ_result_spec_string ("provider_section",                                      &kyc_provider_section_name),        GNUNET_PQ_result_spec_string ("provider_user_id",                                      &provider_user_id), -      GNUNET_PQ_result_spec_string ("legi_id", +      GNUNET_PQ_result_spec_string ("provider_legitimization_id",                                      &legitimization_id),        GNUNET_PQ_result_spec_end      }; @@ -116,10 +116,10 @@ TEH_PG_iterate_kyc_reference (    PREPARE (pg,             "iterate_kyc_reference",             "SELECT " -           " section_name" +           " provider_section"             ",provider_user_id" -           ",legi_id" -           " FROM FIXME" +           ",provider_legitimization_id" +           " FROM legitimization_processes"             " WHERE h_payto=$1;");    return GNUNET_PQ_eval_prepared_multi_select (pg->conn,                                                 "iterate_kyc_reference", diff --git a/src/exchangedb/pg_iterate_reserve_close_info.c b/src/exchangedb/pg_iterate_reserve_close_info.c index c5ff6132..f1b2d452 100644 --- a/src/exchangedb/pg_iterate_reserve_close_info.c +++ b/src/exchangedb/pg_iterate_reserve_close_info.c @@ -68,7 +68,7 @@ iterate_reserve_close_info_cb (void *cls,      struct TALER_Amount amount;      struct GNUNET_TIME_Absolute ts;      struct GNUNET_PQ_ResultSpec rs[] = { -      GNUNET_PQ_result_spec_absolute_time ("timestamp", +      GNUNET_PQ_result_spec_absolute_time ("execution_date",                                             &ts),        TALER_PQ_RESULT_SPEC_AMOUNT ("amount",                                     &amount), @@ -115,14 +115,15 @@ TEH_PG_iterate_reserve_close_info (             "SELECT"             " amount_val"             ",amount_frac" -           ",timestamp" -           " FROM FIXME" -           " WHERE h_payto=$1" -           "   AND timestamp >= $2" -           " ORDER BY timestamp DESC"); -  return GNUNET_PQ_eval_prepared_multi_select (pg->conn, -                                               "iterate_reserve_close_info", -                                               params, -                                               &iterate_reserve_close_info_cb, -                                               &ic); +           ",execution_date" +           " FROM reserves_close" +           " WHERE wire_target_h_payto=$1" +           "   AND execution_date >= $2" +           " ORDER BY execution_date DESC"); +  return GNUNET_PQ_eval_prepared_multi_select ( +    pg->conn, +    "iterate_reserve_close_info", +    params, +    &iterate_reserve_close_info_cb, +    &ic);  } diff --git a/src/exchangedb/pg_select_reserve_close_info.c b/src/exchangedb/pg_select_reserve_close_info.c index 53ea4568..0b373b7b 100644 --- a/src/exchangedb/pg_select_reserve_close_info.c +++ b/src/exchangedb/pg_select_reserve_close_info.c @@ -39,7 +39,7 @@ TEH_PG_select_reserve_close_info (      GNUNET_PQ_query_param_end    };    struct GNUNET_PQ_ResultSpec rs[] = { -    TALER_PQ_RESULT_SPEC_AMOUNT ("balance", +    TALER_PQ_RESULT_SPEC_AMOUNT ("close",                                   balance),      GNUNET_PQ_result_spec_string ("payto_uri",                                    payto_uri), @@ -49,10 +49,10 @@ TEH_PG_select_reserve_close_info (    PREPARE (pg,             "select_reserve_close_info",             "SELECT " -           " balance_frac" -           ",balance_val" +           " close_frac" +           ",close_val"             ",payto_uri" -           " FROM FIXME" +           " FROM close_requests"             " WHERE reserve_pub=$1;");    return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,                                                     "select_reserve_close_info", diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 341364f9..d2e2eb5d 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -32,6 +32,9 @@  #include "pg_helper.h"  #include "pg_insert_close_request.h"  #include "pg_insert_reserve_open_deposit.h" +#include "pg_iterate_kyc_reference.h" +#include "pg_iterate_reserve_close_info.h" +#include "pg_select_reserve_close_info.h"  #include <poll.h>  #include <pthread.h>  #include <libpq-fe.h> @@ -17264,8 +17267,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)      = &postgres_select_purse_merge;    plugin->insert_history_request      = &postgres_insert_history_request; -  plugin->insert_close_request -    = &TEH_PG_insert_close_request;    plugin->insert_drain_profit      = &postgres_insert_drain_profit;    plugin->profit_drains_get_pending @@ -17294,6 +17295,16 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)      = &postgres_select_aggregation_amounts_for_kyc_check;    plugin->select_merge_amounts_for_kyc_check      = &postgres_select_merge_amounts_for_kyc_check; +  /* NEW style, sort alphabetically! */ +  plugin->insert_close_request +    = &TEH_PG_insert_close_request; +  plugin->iterate_reserve_close_info +    = &TEH_PG_iterate_reserve_close_info; +  plugin->iterate_kyc_reference +    = &TEH_PG_iterate_kyc_reference; +  plugin->select_reserve_close_info +    = &TEH_PG_select_reserve_close_info; +    return plugin;  } diff --git a/src/exchangedb/procedures.sql b/src/exchangedb/procedures.sql index 1940fa7b..8407f20c 100644 --- a/src/exchangedb/procedures.sql +++ b/src/exchangedb/procedures.sql @@ -1778,7 +1778,7 @@ ELSE    my_amount_val = my_amount_val + my_amount_frac / 100000000;    my_amount_frac = my_amount_frac % 100000000; -  UPDATE reserves +  UPDATE exchange.reserves    SET      current_balance_frac=current_balance_frac+my_amount_frac         - CASE @@ -1795,7 +1795,7 @@ ELSE    WHERE reserve_pub=in_reserve_pub;    -- ... and mark purse as finished. -  UPDATE purse_requests +  UPDATE exchange.purse_requests       SET finished=true    WHERE purse_pub=in_purse_pub;  END IF; @@ -1881,7 +1881,7 @@ THEN      out_no_funds=TRUE;      RETURN;    END IF; -  UPDATE reserves +  UPDATE exchange.reserves       SET purses_active=purses_active+1     WHERE reserve_pub=in_reserve_pub       AND purses_active < purses_allowed; @@ -1901,7 +1901,7 @@ ELSE        RETURN;      END IF;    ELSE -    UPDATE reserves +    UPDATE exchange.reserves        SET          current_balance_frac=current_balance_frac-in_purse_fee_frac           + CASE @@ -1993,7 +1993,7 @@ THEN    RETURN;  END IF; -UPDATE purse_requests +UPDATE exchange.purse_requests   SET refunded=TRUE,       finished=TRUE   WHERE purse_pub=my_purse_pub; @@ -2011,7 +2011,7 @@ FOR my_deposit IN      FROM exchange.purse_deposits    WHERE purse_pub = my_purse_pub  LOOP -  UPDATE known_coins SET +  UPDATE exchange.known_coins SET      remaining_frac=remaining_frac+my_deposit.amount_with_fee_frac       - CASE         WHEN remaining_frac+my_deposit.amount_with_fee_frac >= 100000000 @@ -2071,7 +2071,7 @@ BEGIN    out_idempotent=FALSE;    -- Update reserve balance. -  UPDATE reserves +  UPDATE exchange.reserves     SET      current_balance_frac=current_balance_frac-in_history_fee_frac         + CASE @@ -2103,57 +2103,76 @@ BEGIN  END $$; -CREATE OR REPLACE FUNCTION exchange_do_close_request( -  IN in_reserve_pub BYTEA, -  IN in_close_timestamp INT8, +CREATE OR REPLACE FUNCTION exchange_do_reserve_open_deposit( +  IN in_coin_pub BYTEA, +  IN in_known_coin_id INT8, +  IN in_coin_sig BYTEA,    IN in_reserve_sig BYTEA, -  OUT out_final_balance_val INT8, -  OUT out_final_balance_frac INT4, -  OUT out_balance_ok BOOLEAN, -  OUT out_conflict BOOLEAN) +  IN in_reserve_pub BYTEA, +  IN in_coin_total_val INT8, +  IN in_coin_total_frac INT4, +  OUT out_insufficient_funds BOOLEAN)  LANGUAGE plpgsql  AS $$  BEGIN -  SELECT -    current_balance_val -   ,current_balance_frac -  INTO -    out_final_balance_val -   ,out_final_balance_frac -  FROM exchange.reserves -  WHERE reserve_pub=in_reserve_pub; +INSERT INTO exchange.reserves_open_deposits +  (reserve_sig +  ,reserve_pub +  ,request_timestamp +  ,coin_pub +  ,coin_sig +  ,contribution_val +  ,contribution_frac +  ) +  VALUES +  (in_reserve_sig +  ,in_reserve_pub +  ,in_request_timestamp +  ,in_coin_pub +  ,in_coin_sig +  ,in_coin_total_val +  ,in_coin_total_frac) +  ON CONFLICT DO NOTHING; -  IF NOT FOUND -  THEN -    out_final_balance_val=0; -    out_final_balance_frac=0; -    out_balance_ok = FALSE; -    out_conflict = FALSE; -  END IF; +IF NOT FOUND +THEN +  -- Idempotent request known, return success. +  out_insufficient_funds=FALSE; +  RETURN; +END IF; -  INSERT INTO exchange.close_requests -    (reserve_pub -    ,close_timestamp -    ,reserve_sig -    ,close_val -    ,close_frac) -    VALUES -    (in_reserve_pub -    ,in_close_timestamp -    ,in_reserve_sig -    ,out_final_balance_val -    ,out_final_balance_frac) -  ON CONFLICT DO NOTHING; -  out_conflict = NOT FOUND; -  UPDATE reserves SET -    current_balance_val=0 -   ,current_balance_frac=0 -  WHERE reserve_pub=in_reserve_pub; -  out_balance_ok = TRUE; +-- Check and update balance of the coin. +UPDATE exchange.known_coins +  SET +    remaining_frac=remaining_frac-in_coin_total_frac +       + CASE +         WHEN remaining_frac < in_coin_total_frac +         THEN 100000000 +         ELSE 0 +         END, +    remaining_val=remaining_val-in_coin_total_val +       - CASE +         WHEN remaining_frac < in_coin_total_frac +         THEN 1 +         ELSE 0 +         END +  WHERE coin_pub=in_coin_pub +    AND ( (remaining_val > in_coin_total_val) OR +          ( (remaining_frac >= in_coin_total_frac) AND +            (remaining_val >= in_coin_total_val) ) ); -END $$; +IF NOT FOUND +THEN +  -- Insufficient balance. +  out_insufficient_funds=TRUE; +  RETURN; +END IF; +-- Everything fine, return success! +out_insufficient_funds=FALSE; + +END $$;  COMMIT; diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index bde3c813..0ce8ff47 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -4072,6 +4072,7 @@ struct TALER_EXCHANGEDB_Plugin     * @param known_coin_id ID of the coin in the known_coins table     * @param coin_total amount to be spent of the coin (including deposit fee)     * @param reserve_sig signature by the reserve affirming the open operation +   * @param reserve_pub public key of the reserve being opened     * @param[out] insufficient_funds set to true if the coin's balance is insufficient, otherwise to false     * @return transaction status code, 0 if operation is already in the DB     */ @@ -4083,6 +4084,7 @@ struct TALER_EXCHANGEDB_Plugin      uint64_t known_coin_id,      const struct TALER_Amount *coin_total,      const struct TALER_ReserveSignatureP *reserve_sig, +    const struct TALER_ReservePublicKeyP *reserve_pub,      bool *insufficient_funds); @@ -5600,8 +5602,8 @@ struct TALER_EXCHANGEDB_Plugin     * @param payto_uri where to wire the funds     * @param reserve_sig signature affiming that the account is to be closed     * @param request_timestamp timestamp of the close request +   * @param balance balance at the time of closing     * @param closing_fee closing fee to charge -   * @param[out] final_balance set to the final balance in the account that will be wired back to the origin account     * @return transaction status code     */    enum GNUNET_DB_QueryStatus @@ -5610,8 +5612,8 @@ struct TALER_EXCHANGEDB_Plugin                            const char *payto_uri,                            const struct TALER_ReserveSignatureP *reserve_sig,                            struct GNUNET_TIME_Timestamp request_timestamp, -                          const struct TALER_Amount *closing_fee, -                          struct TALER_Amount *final_balance); +                          const struct TALER_Amount *balance, +                          const struct TALER_Amount *closing_fee);    /**  | 
