diff --git a/src/exchange/taler-exchange-httpd_reserves_open.c b/src/exchange/taler-exchange-httpd_reserves_open.c index d446d9b40..d3ff37d67 100644 --- a/src/exchange/taler-exchange-httpd_reserves_open.c +++ b/src/exchange/taler-exchange-httpd_reserves_open.c @@ -102,6 +102,12 @@ struct ReserveOpenContext * Desired minimum purse limit. */ uint32_t purse_limit; + + /** + * Set to true if the reserve balance is too low + * for the operation. + */ + bool no_funds; }; @@ -223,12 +229,14 @@ reserve_open_transaction (void *cls, /* inputs */ rsc->reserve_pub, &rsc->total, + &rsc->reserve_payment, rsc->purse_limit, &rsc->reserve_sig, rsc->desired_expiration, rsc->timestamp, &rsc->gf->fees.account, /* outputs */ + &rsc->no_funds, &rsc->open_cost, &rsc->reserve_expiration); switch (qs) @@ -253,6 +261,15 @@ reserve_open_transaction (void *cls, case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: break; } + if (rsc->no_funds) + { + *mhd_ret + = TEH_RESPONSE_reply_reserve_insufficient_balance ( + connection, + &rsc->reserve_payment, + rsc->reserve_pub); + return GNUNET_DB_STATUS_HARD_ERROR; + } return qs; } @@ -342,13 +359,10 @@ TEH_handler_reserves_open (struct TEH_RequestContext *rc, cleanup_rsc (&rsc); return MHD_YES; /* failure */ } - /* FIXME-DOLD: Alternatively, we could here add coin->amount_minus_fee and - thereby charge the deposit fee even when paying the reserve-open fee. - To be decided... */ if (0 > TALER_amount_add (&rsc.total, &rsc.total, - &coin->amount)) + &coin->amount_minus_fee)) { GNUNET_break (0); cleanup_rsc (&rsc); diff --git a/src/exchangedb/pg_do_reserve_open.c b/src/exchangedb/pg_do_reserve_open.c index bd4f72401..f7a3a5f7b 100644 --- a/src/exchangedb/pg_do_reserve_open.c +++ b/src/exchangedb/pg_do_reserve_open.c @@ -31,11 +31,13 @@ TEH_PG_do_reserve_open ( void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *total_paid, + const struct TALER_Amount *reserve_payment, uint32_t min_purse_limit, const struct TALER_ReserveSignatureP *reserve_sig, struct GNUNET_TIME_Timestamp desired_expiration, struct GNUNET_TIME_Timestamp now, const struct TALER_Amount *open_fee, + bool *no_funds, struct TALER_Amount *open_cost, struct GNUNET_TIME_Timestamp *final_expiration) { @@ -43,6 +45,7 @@ TEH_PG_do_reserve_open ( struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (reserve_pub), TALER_PQ_query_param_amount (total_paid), + TALER_PQ_query_param_amount (reserve_payment), GNUNET_PQ_query_param_uint32 (&min_purse_limit), GNUNET_PQ_query_param_auto_from_type (reserve_sig), GNUNET_PQ_query_param_timestamp (&desired_expiration), @@ -51,9 +54,11 @@ TEH_PG_do_reserve_open ( GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("open_cost", + GNUNET_PQ_result_spec_bool ("out_no_funds", + no_funds), + TALER_PQ_RESULT_SPEC_AMOUNT ("out_open_cost", open_cost), - GNUNET_PQ_result_spec_timestamp ("final_expiration", + GNUNET_PQ_result_spec_timestamp ("out_final_expiration", final_expiration), GNUNET_PQ_result_spec_end }; @@ -61,11 +66,12 @@ TEH_PG_do_reserve_open ( PREPARE (pg, "do_reserve_open", "SELECT " - " open_cost_val" - ",open_cost_frac" - ",final_expiration" + " out_open_cost_val" + ",out_open_cost_frac" + ",out_final_expiration" + ",out_no_funds" " FROM exchange_do_reserve_open" - " ($1,$2,$3,$4,$5,$6,$7,$8,$9);"); + " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);"); return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "do_reserve_open", params, diff --git a/src/exchangedb/pg_do_reserve_open.h b/src/exchangedb/pg_do_reserve_open.h index aeef59eb0..acf2d67ee 100644 --- a/src/exchangedb/pg_do_reserve_open.h +++ b/src/exchangedb/pg_do_reserve_open.h @@ -27,15 +27,20 @@ /** - * Insert reserve close operation into database. + * Perform reserve open operation on database. * * @param cls closure * @param reserve_pub which reserve is this about? - * @param execution_date when did we perform the transfer? - * @param receiver_account to which account do we transfer, in payto://-format - * @param wtid identifier for the wire transfer - * @param amount_with_fee amount we charged to the reserve - * @param closing_fee how high is the closing fee + * @param total_paid total amount paid (coins and reserve) + * @param reserve_payment amount to be paid from the reserve + * @param min_purse_limit minimum number of purses we should be able to open + * @param reserve_sig signature by the reserve for the operation + * @param desired_expiration when should the reserve expire (earliest time) + * @param now when did we the client initiate the action + * @param open_fee annual fee to be charged for the open operation by the exchange + * @param[out] no_funds set to true if reserve balance is insufficient + * @param[out] open_cost set to the actual cost + * @param[out] final_expiration when will the reserve expire now * @return transaction status code */ enum GNUNET_DB_QueryStatus @@ -43,11 +48,13 @@ TEH_PG_do_reserve_open ( void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *total_paid, + const struct TALER_Amount *reserve_payment, uint32_t min_purse_limit, const struct TALER_ReserveSignatureP *reserve_sig, struct GNUNET_TIME_Timestamp desired_expiration, struct GNUNET_TIME_Timestamp now, const struct TALER_Amount *open_fee, + bool *no_funds, struct TALER_Amount *open_cost, struct GNUNET_TIME_Timestamp *final_expiration); diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index d2e2eb5df..04455808c 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -17296,6 +17296,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) plugin->select_merge_amounts_for_kyc_check = &postgres_select_merge_amounts_for_kyc_check; /* NEW style, sort alphabetically! */ + plugin->insert_reserve_open_deposit + = &TEH_PG_insert_reserve_open_deposit; plugin->insert_close_request = &TEH_PG_insert_close_request; plugin->iterate_reserve_close_info diff --git a/src/exchangedb/procedures.sql b/src/exchangedb/procedures.sql index 8407f20c7..f39e359c1 100644 --- a/src/exchangedb/procedures.sql +++ b/src/exchangedb/procedures.sql @@ -2175,4 +2175,30 @@ out_insufficient_funds=FALSE; END $$; + +CREATE OR REPLACE FUNCTION exchange_do_reserve_open( + IN in_reserve_pub BYTEA, + IN in_total_paid_val INT8, + IN in_total_paid_frac INT4, + IN in_reserve_payment_val INT8, + IN in_reserve_payment_frac INT4, + IN in_min_purse_limit INT4, + IN in_reserve_sig BYTEA, + IN in_desired_expiration INT8, + IN in_now INT8, + IN in_open_fee_val INT8, + IN in_open_fee_frac INT4, + OUT out_open_cost_val INT8, + OUT out_open_cost_frac INT4, + OUT out_final_expiration INT8, + OUT out_no_funds BOOLEAN) +LANGUAGE plpgsql +AS $$ +BEGIN + +-- FIXME: implement! + +END $$ + + COMMIT; diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 0ce8ff473..7644e45ab 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -4093,22 +4093,29 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls closure * @param reserve_pub which reserve is this about? - * @param execution_date when did we perform the transfer? - * @param receiver_account to which account do we transfer, in payto://-format - * @param wtid identifier for the wire transfer - * @param amount_with_fee amount we charged to the reserve - * @param closing_fee how high is the closing fee + * @param total_paid total amount paid (coins and reserve) + * @param reserve_payment amount to be paid from the reserve + * @param min_purse_limit minimum number of purses we should be able to open + * @param reserve_sig signature by the reserve for the operation + * @param desired_expiration when should the reserve expire (earliest time) + * @param now when did we the client initiate the action + * @param open_fee annual fee to be charged for the open operation by the exchange + * @param[out] no_funds set to true if reserve balance is insufficient + * @param[out] open_cost set to the actual cost + * @param[out] final_expiration when will the reserve expire now * @return transaction status code */ enum GNUNET_DB_QueryStatus (*do_reserve_open)(void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *total_paid, + const struct TALER_Amount *reserve_payment, uint32_t min_purse_limit, const struct TALER_ReserveSignatureP *reserve_sig, struct GNUNET_TIME_Timestamp desired_expiration, struct GNUNET_TIME_Timestamp now, const struct TALER_Amount *open_fee, + bool *no_funds, struct TALER_Amount *open_cost, struct GNUNET_TIME_Timestamp *final_expiration);