aboutsummaryrefslogtreecommitdiff
path: root/src/exchangedb
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchangedb')
-rw-r--r--src/exchangedb/exchangedb.conf4
-rw-r--r--src/exchangedb/pg_do_reserve_open.c2
-rw-r--r--src/exchangedb/pg_helper.h6
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c16
-rw-r--r--src/exchangedb/procedures.sql156
5 files changed, 183 insertions, 1 deletions
diff --git a/src/exchangedb/exchangedb.conf b/src/exchangedb/exchangedb.conf
index 1c22301ad..2bfcb2ca0 100644
--- a/src/exchangedb/exchangedb.conf
+++ b/src/exchangedb/exchangedb.conf
@@ -30,3 +30,7 @@ LEGAL_RESERVE_EXPIRATION_TIME = 7 years
# What is the desired delay between a transaction being ready and the
# aggregator triggering on it?
AGGREGATOR_SHIFT = 1 s
+
+# How many concurrent purses may be opened by a reserve
+# if the reserve is paid for a year?
+DEFAULT_PURSE_LIMIT = 1 \ No newline at end of file
diff --git a/src/exchangedb/pg_do_reserve_open.c b/src/exchangedb/pg_do_reserve_open.c
index f7a3a5f7b..ad18cb936 100644
--- a/src/exchangedb/pg_do_reserve_open.c
+++ b/src/exchangedb/pg_do_reserve_open.c
@@ -47,8 +47,10 @@ TEH_PG_do_reserve_open (
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_uint32 (&pg->def_purse_limit),
GNUNET_PQ_query_param_auto_from_type (reserve_sig),
GNUNET_PQ_query_param_timestamp (&desired_expiration),
+ GNUNET_PQ_query_param_relative_time (&pg->legal_reserve_expiration_time),
GNUNET_PQ_query_param_timestamp (&now),
TALER_PQ_query_param_amount (open_fee),
GNUNET_PQ_query_param_end
diff --git a/src/exchangedb/pg_helper.h b/src/exchangedb/pg_helper.h
index e0a4be49d..84d4c22b7 100644
--- a/src/exchangedb/pg_helper.h
+++ b/src/exchangedb/pg_helper.h
@@ -83,6 +83,12 @@ struct PostgresClosure
unsigned long long prep_gen;
/**
+ * Number of purses we allow to be opened concurrently
+ * for one year per annual fee payment.
+ */
+ uint32_t def_purse_limit;
+
+ /**
* Did we initialize the prepared statements
* for this session? (To be replaced with @e prep_gen.)
*/
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 1bb835877..a369b7107 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -15567,6 +15567,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
struct PostgresClosure *pg;
struct TALER_EXCHANGEDB_Plugin *plugin;
+ unsigned long long dpl;
pg = GNUNET_new (struct PostgresClosure);
pg->cfg = cfg;
@@ -15625,6 +15626,21 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
"exchangedb",
"AGGREGATOR_SHIFT");
}
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ "exchangedb",
+ "DEFAULT_PURSE_LIMIT",
+ &dpl))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
+ "exchangedb",
+ "DEFAULT_PURSE_LIMIT");
+ pg->def_purse_limit = 1;
+ }
+ else
+ {
+ pg->def_purse_limit = (uint32_t) dpl;
+ }
if (GNUNET_OK !=
TALER_config_get_currency (cfg,
diff --git a/src/exchangedb/procedures.sql b/src/exchangedb/procedures.sql
index 1e9b6b166..90fb7d321 100644
--- a/src/exchangedb/procedures.sql
+++ b/src/exchangedb/procedures.sql
@@ -2183,8 +2183,10 @@ CREATE OR REPLACE FUNCTION exchange_do_reserve_open(
IN in_reserve_payment_val INT8,
IN in_reserve_payment_frac INT4,
IN in_min_purse_limit INT4,
+ IN in_default_purse_limit INT4,
IN in_reserve_sig BYTEA,
IN in_desired_expiration INT8,
+ IN in_reserve_gc_delay INT8,
IN in_now INT8,
IN in_open_fee_val INT8,
IN in_open_fee_frac INT4,
@@ -2194,9 +2196,161 @@ CREATE OR REPLACE FUNCTION exchange_do_reserve_open(
OUT out_no_funds BOOLEAN)
LANGUAGE plpgsql
AS $$
+DECLARE
+ my_balance_val INT8;
+DECLARE
+ my_balance_frac INT4;
+DECLARE
+ my_cost_val INT8;
+DECLARE
+ my_cost_tmp INT8;
+DECLARE
+ my_cost_frac INT4;
+DECLARE
+ my_years_tmp INT4;
+DECLARE
+ my_years INT4;
+DECLARE
+ my_needs_update BOOL;
+DECLARE
+ my_purses_allowed INT8;
+DECLARE
+ my_expiration_date INT8;
+DECLARE
+ my_reserve_expiration INT8;
BEGIN
--- FIXME: implement!
+-- FIXME: use SELECT FOR UPDATE?
+SELECT
+ purses_allowed
+ ,expiration_date
+ ,current_balance_val
+ ,current_balance_frac
+INTO
+ my_purses_allowed
+ ,my_reserve_expiration
+ ,my_balance_val
+ ,my_balance_frac
+FROM reserves
+WHERE
+ reserve_pub=in_reserve_pub;
+
+IF NOT FOUND
+THEN
+ -- FIXME: do we need to set a 'not found'?
+ RETURN;
+END IF;
+
+-- Do not allow expiration time to start in the past already
+IF (my_reserve_expiration < in_now)
+THEN
+ my_expiration_date = in_now;
+ELSE
+ my_expiration_date = my_reserve_expiration;
+END IF;
+
+my_cost_val = 0;
+my_cost_frac = 0;
+my_needs_update = FALSE;
+my_years = 0;
+
+-- Compute years based on desired expiration time
+IF (my_expiration_date < in_desired_expiration)
+THEN
+ my_years = (31535999999999 + in_desired_expiration - my_expiration_date) / 31536000000000;
+ my_purses_allowed = in_default_purse_limit;
+ my_expiration_date = my_expiration_date + 31536000000000 * my_years;
+END IF;
+
+-- Increase years based on purses requested
+IF (my_purses_allowed < in_min_purse_limit)
+THEN
+ my_years = (31535999999999 + in_desired_expiration - in_now) / 31536000000000;
+ my_expiration_date = in_now + 31536000000000 * my_years;
+ my_years_tmp = (in_min_purse_limit + in_default_purse_limit - my_purses_allowed - 1) / in_default_purse_limit;
+ my_years = my_years + my_years_tmp;
+ 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
+ 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)
+ THEN
+ out_open_cost_val=9223372036854775807;
+ out_open_cost_frac=2147483647;
+ out_final_expiration=my_expiration_date;
+ out_no_funds=true;
+ 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;
+ my_needs_update = TRUE;
+END IF;
+
+-- check if we actually have something to do
+IF NOT my_needs_update
+THEN
+ out_final_expiration = my_reserve_expiration;
+ out_open_cost_val = 0;
+ out_open_cost_frac = 0;
+ out_no_funds=FALSE;
+ RETURN;
+END IF;
+
+-- Check payment (coins and reserve) would be sufficient.
+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;
+ RETURN;
+END IF;
+
+-- Check reserve balance is sufficient.
+IF (my_balance_val > in_reserve_payment_val)
+THEN
+ IF (my_balance_frac >= in_reserve_payment_frac)
+ THEN
+ my_balance_val=my_balance_val - in_reserve_payment_val;
+ my_balance_frac=my_balance_frac - in_reserve_payment_frac;
+ ELSE
+ my_balance_val=my_balance_val - in_reserve_payment_val - 1;
+ my_balance_frac=my_balance_frac + 100000000 - in_reserve_payment_frac;
+ END IF;
+ELSE
+ IF (my_balance_val = in_reserve_payment_val) AND (my_balance_frac >= in_reserve_payment_frac)
+ THEN
+ my_balance_val=0;
+ my_balance_frac=my_balance_frac - in_reserve_payment_frac;
+ ELSE
+ 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;
+ END IF;
+END IF;
+
+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
+ ,purses_allowed=my_purses_allowed
+WHERE
+ reserve_pub=in_reserve_pub;
+
+out_final_expiration=my_reserve_expiration;
+out_open_cost_val = my_cost_val;
+out_open_cost_frac = my_cost_frac;
+out_no_funds=FALSE;
+RETURN;
END $$;