diff --git a/ChangeLog b/ChangeLog index c161addcf..d8adb7d97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Fri Jul 14 17:38:54 CEST 2017 + Fix #4751 by not allowing denomination deletion (GC) + to cascade into reserve_out table (and tolerating such + deletion failures). This way, denominations will be kept + around until the last reserve that references them (or + known_coins derived from them) is closed. Naturally, in + most case we expect reserves to be closed much faster + than DKs, so in practice this should rarely apply. -CG + Sun Jun 11 17:03:56 CEST 2017 Finish implementation and testing of automated refunding of expired reserves (#4956). -CG diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am index c2e77f117..62dd19106 100644 --- a/src/auditor/Makefile.am +++ b/src/auditor/Makefile.am @@ -32,6 +32,7 @@ taler_auditor_sign_SOURCES = \ taler_auditor_sign_LDADD = \ $(LIBGCRYPT_LIBS) \ $(top_builddir)/src/util/libtalerutil.la \ + $(top_builddir)/src/auditordb/libtalerauditordb.la \ $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ -lgnunetutil $(XLIB) diff --git a/src/auditor/taler-auditor-sign.c b/src/auditor/taler-auditor-sign.c index d1a205b3d..5494cd2f5 100644 --- a/src/auditor/taler-auditor-sign.c +++ b/src/auditor/taler-auditor-sign.c @@ -21,6 +21,7 @@ */ #include #include "taler_exchangedb_lib.h" +#include "taler_auditordb_lib.h" /** @@ -59,6 +60,11 @@ static struct TALER_MasterPublicKeyP master_public_key; */ static struct GNUNET_CONFIGURATION_Handle *cfg; +/** + * Handle to access the auditor's database. + */ +static struct TALER_AUDITORDB_Plugin *adb; + /** * Print denomination key details for diagnostics. @@ -180,7 +186,6 @@ main (int argc, unsigned int dks_len; struct TALER_ExchangeKeyValidityPS kv; off_t in_size; - unsigned int i; GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-auditor-sign", @@ -223,7 +228,8 @@ main (int argc, "Auditor URL not given in neither configuration nor command-line\n"); return 1; } - if (GNUNET_YES != GNUNET_DISK_file_test (auditor_key_file)) + if (GNUNET_YES != + GNUNET_DISK_file_test (auditor_key_file)) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Auditor private key `%s' does not exist yet, creating it!\n", auditor_key_file); @@ -277,9 +283,18 @@ main (int argc, "Denomination list has length zero, signature not produced.\n"); GNUNET_DISK_file_close (fh); GNUNET_free (eddsa_priv); - return 2; - + return 2; } + if (NULL == + (adb = TALER_AUDITORDB_plugin_load (cfg))) + { + fprintf (stderr, + "Failed to initialize auditor database plugin.\n"); + GNUNET_DISK_file_close (fh); + GNUNET_free (eddsa_priv); + return 3; + } + kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS); kv.purpose.size = htonl (sizeof (struct TALER_ExchangeKeyValidityPS)); GNUNET_CRYPTO_hash (auditor_url, @@ -299,6 +314,7 @@ main (int argc, "Failed to read input file `%s': %s\n", exchange_request_file, STRERROR (errno)); + TALER_AUDITORDB_plugin_unload (adb); GNUNET_DISK_file_close (fh); GNUNET_free (sigs); GNUNET_free (dks); @@ -306,7 +322,7 @@ main (int argc, return 1; } GNUNET_DISK_file_close (fh); - for (i=0;iget_session (adb->cls); + if (NULL == session) + { + fprintf (stderr, + "Failed to initialize database session\n"); + TALER_AUDITORDB_plugin_unload (adb); + GNUNET_free (dks); + GNUNET_free (sigs); + GNUNET_free (eddsa_priv); + return 3; + } + for (unsigned int i=0;iinsert_denomination_info (adb->cls, + session, + dk); + if (0 > qs) + { + fprintf (stderr, + "Failed to store key in auditor DB\n"); + TALER_AUDITORDB_plugin_unload (adb); + GNUNET_free (dks); + GNUNET_free (sigs); + GNUNET_free (eddsa_priv); + return 3; + } + } + } + TALER_AUDITORDB_plugin_unload (adb); /* write result to disk */ if (GNUNET_OK != @@ -357,7 +410,6 @@ main (int argc, GNUNET_free (dks); return 1; } - GNUNET_free (sigs); GNUNET_free (dks); GNUNET_free (eddsa_priv); diff --git a/src/auditordb/plugin_auditordb_postgres.c b/src/auditordb/plugin_auditordb_postgres.c index 4862cf204..e31bb0257 100644 --- a/src/auditordb/plugin_auditordb_postgres.c +++ b/src/auditordb/plugin_auditordb_postgres.c @@ -138,12 +138,12 @@ postgres_drop_tables (void *cls) { struct PostgresClosure *pc = cls; struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS predicted_result;"), - GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS historic_ledger;"), - GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS historic_losses;"), - GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS historic_denomination_revenue;"), - GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS balance_summary;"), - GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS denomination_pending;"), + GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_predicted_result;"), + GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_historic_ledger;"), + GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_historic_losses;"), + GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_historic_denomination_revenue;"), + GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_balance_summary;"), + GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_denomination_pending;"), GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_reserve_balance;"), GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_wire_fee_balance;"), GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS auditor_reserves;"), @@ -274,9 +274,9 @@ postgres_create_tables (void *cls) last melt from "refresh_sessions" that the auditor is aware of; "refund_serial_id" tells us the last entry in "refunds" for this denom_pub that the auditor is aware of. */ - GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS denomination_pending" + GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_denomination_pending" "(denom_pub_hash BYTEA PRIMARY KEY" - /* " REFERENCES auditor_denominations (denom_pub_hash) ON DELETE CASCADE" // Do we want this? */ + " REFERENCES auditor_denominations (denom_pub_hash) ON DELETE CASCADE" ",denom_balance_val INT8 NOT NULL" ",denom_balance_frac INT4 NOT NULL" ",denom_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" @@ -285,12 +285,12 @@ postgres_create_tables (void *cls) ",denom_risk_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ")"), /* Table with the sum of the outstanding coins from - "denomination_pending" (denom_pubs must belong to the + "auditor_denomination_pending" (denom_pubs must belong to the respective's exchange's master public key); it represents the - balance_summary of the exchange at this point (modulo + auditor_balance_summary of the exchange at this point (modulo unexpected historic_loss-style events where denomination keys are compromised) */ - GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS balance_summary" + GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_balance_summary" "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)" ",denom_balance_val INT8 NOT NULL" ",denom_balance_frac INT4 NOT NULL" @@ -317,7 +317,7 @@ postgres_create_tables (void *cls) historic_reserve_revenue); the deposit, melt and refund fees are given individually; the delta to the revenue_balance is from coins that were withdrawn but never deposited prior to expiration. */ - GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS historic_denomination_revenue" + GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_historic_denomination_revenue" "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)" ",denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)" ",revenue_timestamp INT8 NOT NULL" @@ -330,7 +330,7 @@ postgres_create_tables (void *cls) compromised, we incur a loss. These losses are totaled up here. (NOTE: the 'bankrupcy' protocol is not yet implemented, so right now this table is not used.) */ - GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS historic_losses" + GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_historic_losses" "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)" ",denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)" ",loss_timestamp INT8 NOT NULL" @@ -339,9 +339,9 @@ postgres_create_tables (void *cls) ",loss_balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ")"), /* Table with historic profits from reserves; we eventually - GC "historic_reserve_revenue", and then store the totals + GC "auditor_historic_reserve_revenue", and then store the totals in here (by time intervals). */ - GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS historic_reserve_summary" + GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_historic_reserve_summary" "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)" ",start_date INT8 NOT NULL" ",end_date INT8 NOT NULL" @@ -349,8 +349,8 @@ postgres_create_tables (void *cls) ",reserve_profits_frac INT4 NOT NULL" ",reserve_profits_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ")"), - GNUNET_PQ_make_try_execute ("CREATE INDEX historic_reserve_summary_by_master_pub_start_date " - "ON historic_reserve_summary(master_pub,start_date)"), + GNUNET_PQ_make_try_execute ("CREATE INDEX auditor_historic_reserve_summary_by_master_pub_start_date " + "ON auditor_historic_reserve_summary(master_pub,start_date)"), /* Table with historic business ledger; basically, when the exchange operator decides to use operating costs for anything but wire transfers to merchants, it goes in here. This happens when the @@ -358,12 +358,12 @@ postgres_create_tables (void *cls) is free-form but should be a human-readable wire transfer identifier. This is NOT yet used and outside of the scope of the core auditing logic. However, once we do take fees to use - operating costs, and if we still want "predicted_result" to match + operating costs, and if we still want "auditor_predicted_result" to match the tables overall, we'll need a command-line tool to insert rows - into this table and update "predicted_result" accordingly. + into this table and update "auditor_predicted_result" accordingly. (So this table for now just exists as a reminder of what we'll need in the long term.) */ - GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS historic_ledger" + GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_historic_ledger" "(master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)" ",purpose VARCHAR NOT NULL" ",timestamp INT8 NOT NULL" @@ -372,12 +372,12 @@ postgres_create_tables (void *cls) ",balance_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ")"), GNUNET_PQ_make_try_execute ("CREATE INDEX history_ledger_by_master_pub_and_time " - "ON historic_ledger(master_pub,timestamp)"), - /* Table with the sum of the ledger, historic_revenue, - historic_losses and the auditor_reserve_balance. This is the + "ON auditor_historic_ledger(master_pub,timestamp)"), + /* Table with the sum of the ledger, auditor_historic_revenue, + auditor_historic_losses and the auditor_reserve_balance. This is the final amount that the exchange should have in its bank account right now. */ - GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS predicted_result" + GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS auditor_predicted_result" "(master_pub BYTEA PRIMARY KEY CHECK (LENGTH(master_pub)=32)" ",balance_val INT8 NOT NULL" ",balance_frac INT4 NOT NULL" @@ -616,8 +616,8 @@ postgres_prepare (PGconn *db_conn) " WHERE master_pub=$1;", 1), /* Used in #postgres_insert_denomination_balance() */ - GNUNET_PQ_make_prepare ("denomination_pending_insert", - "INSERT INTO denomination_pending " + GNUNET_PQ_make_prepare ("auditor_denomination_pending_insert", + "INSERT INTO auditor_denomination_pending " "(denom_pub_hash" ",denom_balance_val" ",denom_balance_frac" @@ -628,8 +628,8 @@ postgres_prepare (PGconn *db_conn) ") VALUES ($1,$2,$3,$4,$5,$6,$7);", 7), /* Used in #postgres_update_denomination_balance() */ - GNUNET_PQ_make_prepare ("denomination_pending_update", - "UPDATE denomination_pending SET" + GNUNET_PQ_make_prepare ("auditor_denomination_pending_update", + "UPDATE auditor_denomination_pending SET" " denom_balance_val=$1" ",denom_balance_frac=$2" ",denom_balance_curr=$3" @@ -639,7 +639,7 @@ postgres_prepare (PGconn *db_conn) " WHERE denom_pub_hash=$7", 7), /* Used in #postgres_get_denomination_balance() */ - GNUNET_PQ_make_prepare ("denomination_pending_select", + GNUNET_PQ_make_prepare ("auditor_denomination_pending_select", "SELECT" " denom_balance_val" ",denom_balance_frac" @@ -647,12 +647,12 @@ postgres_prepare (PGconn *db_conn) ",denom_risk_val" ",denom_risk_frac" ",denom_risk_curr" - " FROM denomination_pending" + " FROM auditor_denomination_pending" " WHERE denom_pub_hash=$1", 1), /* Used in #postgres_insert_balance_summary() */ - GNUNET_PQ_make_prepare ("balance_summary_insert", - "INSERT INTO balance_summary " + GNUNET_PQ_make_prepare ("auditor_balance_summary_insert", + "INSERT INTO auditor_balance_summary " "(master_pub" ",denom_balance_val" ",denom_balance_frac" @@ -672,8 +672,8 @@ postgres_prepare (PGconn *db_conn) ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);", 16), /* Used in #postgres_update_balance_summary() */ - GNUNET_PQ_make_prepare ("balance_summary_update", - "UPDATE balance_summary SET" + GNUNET_PQ_make_prepare ("auditor_balance_summary_update", + "UPDATE auditor_balance_summary SET" " denom_balance_val=$1" ",denom_balance_frac=$2" ",denom_balance_curr=$3" @@ -692,7 +692,7 @@ postgres_prepare (PGconn *db_conn) " WHERE master_pub=$16;", 16), /* Used in #postgres_get_balance_summary() */ - GNUNET_PQ_make_prepare ("balance_summary_select", + GNUNET_PQ_make_prepare ("auditor_balance_summary_select", "SELECT" " denom_balance_val" ",denom_balance_frac" @@ -709,12 +709,12 @@ postgres_prepare (PGconn *db_conn) ",risk_val" ",risk_frac" ",risk_curr" - " FROM balance_summary" + " FROM auditor_balance_summary" " WHERE master_pub=$1;", 1), /* Used in #postgres_insert_historic_denom_revenue() */ - GNUNET_PQ_make_prepare ("historic_denomination_revenue_insert", - "INSERT INTO historic_denomination_revenue" + GNUNET_PQ_make_prepare ("auditor_historic_denomination_revenue_insert", + "INSERT INTO auditor_historic_denomination_revenue" "(master_pub" ",denom_pub_hash" ",revenue_timestamp" @@ -724,19 +724,19 @@ postgres_prepare (PGconn *db_conn) ") VALUES ($1,$2,$3,$4,$5,$6);", 6), /* Used in #postgres_select_historic_denom_revenue() */ - GNUNET_PQ_make_prepare ("historic_denomination_revenue_select", + GNUNET_PQ_make_prepare ("auditor_historic_denomination_revenue_select", "SELECT" " denom_pub_hash" ",revenue_timestamp" ",revenue_balance_val" ",revenue_balance_frac" ",revenue_balance_curr" - " FROM historic_denomination_revenue" + " FROM auditor_historic_denomination_revenue" " WHERE master_pub=$1;", 1), /* Used in #postgres_insert_historic_losses() */ - GNUNET_PQ_make_prepare ("historic_losses_insert", - "INSERT INTO historic_losses" + GNUNET_PQ_make_prepare ("auditor_historic_losses_insert", + "INSERT INTO auditor_historic_losses" "(master_pub" ",denom_pub_hash" ",loss_timestamp" @@ -746,19 +746,19 @@ postgres_prepare (PGconn *db_conn) ") VALUES ($1,$2,$3,$4,$5,$6);", 6), /* Used in #postgres_select_historic_losses() */ - GNUNET_PQ_make_prepare ("historic_losses_select", + GNUNET_PQ_make_prepare ("auditor_historic_losses_select", "SELECT" " denom_pub_hash" ",loss_timestamp" ",loss_balance_val" ",loss_balance_frac" ",loss_balance_curr" - " FROM historic_losses" + " FROM auditor_historic_losses" " WHERE master_pub=$1;", 1), /* Used in #postgres_insert_historic_reserve_revenue() */ - GNUNET_PQ_make_prepare ("historic_reserve_summary_insert", - "INSERT INTO historic_reserve_summary" + GNUNET_PQ_make_prepare ("auditor_historic_reserve_summary_insert", + "INSERT INTO auditor_historic_reserve_summary" "(master_pub" ",start_date" ",end_date" @@ -768,19 +768,19 @@ postgres_prepare (PGconn *db_conn) ") VALUES ($1,$2,$3,$4,$5,$6);", 6), /* Used in #postgres_select_historic_reserve_revenue() */ - GNUNET_PQ_make_prepare ("historic_reserve_summary_select", + GNUNET_PQ_make_prepare ("auditor_historic_reserve_summary_select", "SELECT" " start_date" ",end_date" ",reserve_profits_val" ",reserve_profits_frac" ",reserve_profits_curr" - " FROM historic_reserve_summary" + " FROM auditor_historic_reserve_summary" " WHERE master_pub=$1;", 1), /* Used in #postgres_insert_predicted_result() */ - GNUNET_PQ_make_prepare ("predicted_result_insert", - "INSERT INTO predicted_result" + GNUNET_PQ_make_prepare ("auditor_predicted_result_insert", + "INSERT INTO auditor_predicted_result" "(master_pub" ",balance_val" ",balance_frac" @@ -788,20 +788,20 @@ postgres_prepare (PGconn *db_conn) ") VALUES ($1,$2,$3,$4);", 4), /* Used in #postgres_update_predicted_result() */ - GNUNET_PQ_make_prepare ("predicted_result_update", - "UPDATE predicted_result SET" + GNUNET_PQ_make_prepare ("auditor_predicted_result_update", + "UPDATE auditor_predicted_result SET" " balance_val=$1" ",balance_frac=$2" ",balance_curr=$3" " WHERE master_pub=$4;", 4), /* Used in #postgres_get_predicted_balance() */ - GNUNET_PQ_make_prepare ("predicted_result_select", + GNUNET_PQ_make_prepare ("auditor_predicted_result_select", "SELECT" " balance_val" ",balance_frac" ",balance_curr" - " FROM predicted_result" + " FROM auditor_predicted_result" " WHERE master_pub=$1;", 1), GNUNET_PQ_PREPARED_STATEMENT_END @@ -1668,7 +1668,7 @@ postgres_insert_denomination_balance (void *cls, }; return GNUNET_PQ_eval_prepared_non_select (session->conn, - "denomination_pending_insert", + "auditor_denomination_pending_insert", params); } @@ -1699,7 +1699,7 @@ postgres_update_denomination_balance (void *cls, }; return GNUNET_PQ_eval_prepared_non_select (session->conn, - "denomination_pending_update", + "auditor_denomination_pending_update", params); } @@ -1732,7 +1732,7 @@ postgres_get_denomination_balance (void *cls, }; return GNUNET_PQ_eval_prepared_singleton_select (session->conn, - "denomination_pending_select", + "auditor_denomination_pending_select", params, rs); } @@ -1785,7 +1785,7 @@ postgres_insert_balance_summary (void *cls, refund_fee_balance)); return GNUNET_PQ_eval_prepared_non_select (session->conn, - "balance_summary_insert", + "auditor_balance_summary_insert", params); } @@ -1825,7 +1825,7 @@ postgres_update_balance_summary (void *cls, }; return GNUNET_PQ_eval_prepared_non_select (session->conn, - "balance_summary_update", + "auditor_balance_summary_update", params); } @@ -1867,7 +1867,7 @@ postgres_get_balance_summary (void *cls, }; return GNUNET_PQ_eval_prepared_singleton_select (session->conn, - "balance_summary_select", + "auditor_balance_summary_select", params, rs); } @@ -1904,7 +1904,7 @@ postgres_insert_historic_denom_revenue (void *cls, }; return GNUNET_PQ_eval_prepared_non_select (session->conn, - "historic_denomination_revenue_insert", + "auditor_historic_denomination_revenue_insert", params); } @@ -2009,7 +2009,7 @@ postgres_select_historic_denom_revenue (void *cls, enum GNUNET_DB_QueryStatus qs; qs = GNUNET_PQ_eval_prepared_multi_select (session->conn, - "historic_denomination_revenue_select", + "auditor_historic_denomination_revenue_select", params, &historic_denom_revenue_cb, &hrc); @@ -2051,7 +2051,7 @@ postgres_insert_historic_losses (void *cls, }; return GNUNET_PQ_eval_prepared_non_select (session->conn, - "historic_losses_insert", + "auditor_historic_losses_insert", params); } @@ -2155,7 +2155,7 @@ postgres_select_historic_losses (void *cls, enum GNUNET_DB_QueryStatus qs; qs = GNUNET_PQ_eval_prepared_multi_select (session->conn, - "historic_losses_select", + "auditor_historic_losses_select", params, &losses_cb, &lctx); @@ -2193,7 +2193,7 @@ postgres_insert_historic_reserve_revenue (void *cls, }; return GNUNET_PQ_eval_prepared_non_select (session->conn, - "historic_reserve_summary_insert", + "auditor_historic_reserve_summary_insert", params); } @@ -2296,7 +2296,7 @@ postgres_select_historic_reserve_revenue (void *cls, }; qs = GNUNET_PQ_eval_prepared_multi_select (session->conn, - "historic_reserve_summary_select", + "auditor_historic_reserve_summary_select", params, &historic_reserve_revenue_cb, &hrc); @@ -2329,7 +2329,7 @@ postgres_insert_predicted_result (void *cls, }; return GNUNET_PQ_eval_prepared_non_select (session->conn, - "predicted_result_insert", + "auditor_predicted_result_insert", params); } @@ -2357,7 +2357,7 @@ postgres_update_predicted_result (void *cls, }; return GNUNET_PQ_eval_prepared_non_select (session->conn, - "predicted_result_update", + "auditor_predicted_result_update", params); } @@ -2388,7 +2388,7 @@ postgres_get_predicted_balance (void *cls, }; return GNUNET_PQ_eval_prepared_singleton_select (session->conn, - "predicted_result_select", + "auditor_predicted_result_select", params, rs); } diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 8b3fe7f03..a1039d1a0 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -240,7 +240,7 @@ postgres_create_tables (void *cls) GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS reserves_out" "(reserve_out_serial_id BIGSERIAL" ",h_blind_ev BYTEA PRIMARY KEY" - ",denom_pub_hash BYTEA NOT NULL REFERENCES denominations (denom_pub_hash) ON DELETE CASCADE" + ",denom_pub_hash BYTEA NOT NULL REFERENCES denominations (denom_pub_hash)" /* do NOT CASCADE on DELETE, we may keep the denomination key alive! */ ",denom_sig BYTEA NOT NULL" ",reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE CASCADE" ",reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)" @@ -398,8 +398,7 @@ postgres_create_tables (void *cls) /* Table for /payback information */ GNUNET_PQ_make_execute("CREATE TABLE IF NOT EXISTS payback " "(payback_uuid BIGSERIAL" - ",reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE CASCADE" - ",coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE" + ",coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub)" /* do NOT CASCADE on delete, we may keep the coin alive! */ ",coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)" ",coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)" ",amount_val INT8 NOT NULL" @@ -1302,8 +1301,7 @@ postgres_prepare (PGconn *db_conn) information */ GNUNET_PQ_make_prepare ("payback_insert", "INSERT INTO payback " - "(reserve_pub" - ",coin_pub" + "(coin_pub" ",coin_sig" ",coin_blind" ",amount_val" @@ -1312,14 +1310,14 @@ postgres_prepare (PGconn *db_conn) ",timestamp" ",h_blind_ev" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9);", - 9), + "($1, $2, $3, $4, $5, $6, $7, $8);", + 8), /* Used in #postgres_select_payback_above_serial_id() to obtain payback transactions */ GNUNET_PQ_make_prepare ("payback_get_incr", "SELECT" " payback_uuid" ",timestamp" - ",reserve_pub" + ",ro.reserve_pub" ",coin_pub" ",coin_sig" ",coin_blind" @@ -1334,6 +1332,8 @@ postgres_prepare (PGconn *db_conn) " USING (coin_pub)" " JOIN denominations denoms" " USING (denom_pub_hash)" + " JOIN reserves_out ro" + " USING (h_blind_ev)" " WHERE payback_uuid>=$1" " ORDER BY payback_uuid ASC;", 1), @@ -1374,7 +1374,9 @@ postgres_prepare (PGconn *db_conn) " USING (coin_pub)" " JOIN denominations denoms" " USING (denom_pub_hash)" - " WHERE payback.reserve_pub=$1;", + " JOIN reserves_out ro" + " USING (h_blind_ev)" + " WHERE ro.reserve_pub=$1;", 1), /* Used in #postgres_get_reserve_history() */ GNUNET_PQ_make_prepare ("close_by_reserve", @@ -1411,7 +1413,7 @@ postgres_prepare (PGconn *db_conn) for a coin */ GNUNET_PQ_make_prepare ("payback_by_coin", "SELECT" - " payback.reserve_pub" + " ro.reserve_pub" ",coin_sig" ",coin_blind" ",amount_val" @@ -1420,12 +1422,13 @@ postgres_prepare (PGconn *db_conn) ",timestamp" ",denoms.denom_pub" ",coins.denom_sig" - " FROM payback" " JOIN known_coins coins" " USING (coin_pub)" " JOIN denominations denoms" " USING (denom_pub_hash)" + " JOIN reserves_out ro" + " USING (h_blind_ev)" " WHERE payback.coin_pub=$1;", 1), /* Used in #postgres_get_reserve_by_h_blind() */ @@ -1452,6 +1455,11 @@ postgres_prepare (PGconn *db_conn) " AND current_balance_val = 0" " AND current_balance_frac = 0;", 1), + GNUNET_PQ_make_prepare ("gc_wire_fee", + "DELETE" + " FROM wire_fee" + " WHERE end_date < $1;", + 1), GNUNET_PQ_PREPARED_STATEMENT_END }; @@ -2267,8 +2275,8 @@ add_withdraw_coin (void *cls, */ static void add_payback (void *cls, - PGresult *result, - unsigned int num_results) + PGresult *result, + unsigned int num_results) { struct ReserveHistoryContext *rhc = cls; @@ -4873,6 +4881,7 @@ postgres_gc (void *cls) { struct PostgresClosure *pc = cls; struct GNUNET_TIME_Absolute now; + struct GNUNET_TIME_Absolute long_ago; struct GNUNET_PQ_QueryParam params_none[] = { GNUNET_PQ_query_param_end }; @@ -4880,26 +4889,46 @@ postgres_gc (void *cls) GNUNET_PQ_query_param_absolute_time (&now), GNUNET_PQ_query_param_end }; + struct GNUNET_PQ_QueryParam params_ancient_time[] = { + GNUNET_PQ_query_param_absolute_time (&long_ago), + GNUNET_PQ_query_param_end + }; PGconn *conn; int ret; - + now = GNUNET_TIME_absolute_get (); + /* Keep wire fees for 10 years, that should always + be enough _and_ they are tiny so it does not + matter to make this tight */ + long_ago = GNUNET_TIME_absolute_subtract (now, + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_YEARS, + 10)); conn = GNUNET_PQ_connect (pc->connection_cfg_str); if (NULL == conn) return GNUNET_SYSERR; ret = postgres_prepare (conn); if (GNUNET_OK == ret) { - if ( (0 > GNUNET_PQ_eval_prepared_non_select (conn, + if ( + (0 > GNUNET_PQ_eval_prepared_non_select (conn, + "gc_reserves", + params_time)) || + (0 > GNUNET_PQ_eval_prepared_non_select (conn, "gc_prewire", params_none)) || (0 > GNUNET_PQ_eval_prepared_non_select (conn, - "gc_denominations", - params_time)) || - (0 > GNUNET_PQ_eval_prepared_non_select (conn, - "gc_reserves", - params_time)) ) + "gc_wire_fee", + params_ancient_time)) + ) ret = GNUNET_SYSERR; + /* This one may fail due to foreign key constraints from + payback and reserves_out tables to known_coins; these + are NOT using 'ON DROP CASCADE' and might keep denomination + keys alive for a bit longer, thus causing this statement + to fail. */ + (void) GNUNET_PQ_eval_prepared_non_select (conn, + "gc_denominations", + params_time); } PQfinish (conn); return ret; @@ -5995,7 +6024,6 @@ postgres_insert_payback_request (void *cls, struct GNUNET_TIME_Absolute expiry; struct TALER_EXCHANGEDB_Reserve reserve; struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub), GNUNET_PQ_query_param_auto_from_type (coin_sig), GNUNET_PQ_query_param_auto_from_type (coin_blind),