diff options
Diffstat (limited to 'src/auditordb')
| -rw-r--r-- | src/auditordb/Makefile.am | 23 | ||||
| -rw-r--r-- | src/auditordb/plugin_auditordb_postgres.c | 1824 | ||||
| -rw-r--r-- | src/auditordb/test-auditor-db-postgres.conf | 7 | ||||
| -rw-r--r-- | src/auditordb/test_auditordb.c | 798 | 
4 files changed, 2559 insertions, 93 deletions
| diff --git a/src/auditordb/Makefile.am b/src/auditordb/Makefile.am index e8ec4027..640f95f2 100644 --- a/src/auditordb/Makefile.am +++ b/src/auditordb/Makefile.am @@ -12,7 +12,8 @@ pkgcfg_DATA = \    auditordb-postgres.conf  EXTRA_DIST = \ -  auditordb-postgres.conf  +  auditordb-postgres.conf \ +  test-auditor-db-postgres.conf  plugindir = $(libdir)/taler @@ -49,5 +50,21 @@ libtalerauditordb_la_LDFLAGS = \    -no-undefined -EXTRA_test_auditordb_postgres_DEPENDENCIES = \ -  libtaler_plugin_auditordb_postgres.la +#EXTRA_test_auditordb_postgres_DEPENDENCIES = \ +#  libtaler_plugin_auditordb_postgres.la + + +check_PROGRAMS = \ +  test-auditordb-postgres + +AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH; +TESTS = \ +  test-auditordb-postgres + +test_auditordb_postgres_SOURCES = \ +  test_auditordb.c +test_auditordb_postgres_LDADD = \ +  libtalerauditordb.la \ +  $(top_srcdir)/src/pq/libtalerpq.la \ +  $(top_srcdir)/src/util/libtalerutil.la \ +  -lgnunetutil diff --git a/src/auditordb/plugin_auditordb_postgres.c b/src/auditordb/plugin_auditordb_postgres.c index 3205d489..81c1b436 100644 --- a/src/auditordb/plugin_auditordb_postgres.c +++ b/src/auditordb/plugin_auditordb_postgres.c @@ -17,9 +17,8 @@  /**   * @file plugin_auditordb_postgres.c   * @brief Low-level (statement-level) Postgres database access for the auditor - * @author Florian Dold   * @author Christian Grothoff - * @author Sree Harsha Totakura + * @author Gabor X Toth   */  #include "platform.h"  #include "taler_pq_lib.h" @@ -326,7 +325,7 @@ postgres_create_tables (void *cls)       of; "refund_serial_id" tells us the last entry in "refunds"       for this denom_pub that the auditor is aware of. */    SQLEXEC ("CREATE TABLE IF NOT EXISTS denomination_pending" -	   "(denom_pub_hash BYTEA PRIMARY KEY REFERENCES denominations (denom_pub_hash) ON DELETE CASCADE" +	   "(denom_pub_hash BYTEA PRIMARY KEY 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" @@ -435,8 +434,8 @@ postgres_create_tables (void *cls)             ",reserve_profits_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"  	   ")"); -  SQLEXEC_INDEX("CREATE INDEX historic_reserve_summary_by_master_pub_start_date" -                " ON historic_ledger(master_pub,start_date)"); +  SQLEXEC_INDEX("CREATE INDEX historic_reserve_summary_by_master_pub_start_date " +                "ON historic_reserve_summary(master_pub,start_date)");    /* Table with historic business ledger; basically, when the exchange @@ -510,13 +509,457 @@ postgres_prepare (PGconn *db_conn)      PQclear (result); result = NULL;                            \    } while (0); -  /* Used in #postgres_XXX() */ -  PREPARE ("test_insert", -           "INSERT INTO test " -           "(test_pub" -           ") VALUES " -           "($1);", +  /* Used in #postgres_insert_denomination_info() */ +  PREPARE ("auditor_denominations_insert", +           "INSERT INTO auditor_denominations " +           "(denom_pub_hash" +           ",master_pub" +           ",valid_from" +           ",expire_withdraw" +           ",expire_deposit" +           ",expire_legal" +           ",coin_val" +           ",coin_frac" +           ",coin_curr" +           ",fee_withdraw_val" +           ",fee_withdraw_frac" +           ",fee_withdraw_curr" +           ",fee_deposit_val" +           ",fee_deposit_frac" +           ",fee_deposit_curr" +           ",fee_refresh_val" +           ",fee_refresh_frac" +           ",fee_refresh_curr" +           ",fee_refund_val" +           ",fee_refund_frac" +           ",fee_refund_curr" +           ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);", +           21, NULL); + +  /* Used in #postgres_insert_denomination_info() */ +  PREPARE ("auditor_denominations_select", +           "SELECT" +           " denom_pub_hash" +           ",valid_from" +           ",expire_withdraw" +           ",expire_deposit" +           ",expire_legal" +           ",coin_val" +           ",coin_frac" +           ",coin_curr" +           ",fee_withdraw_val" +           ",fee_withdraw_frac" +           ",fee_withdraw_curr" +           ",fee_deposit_val" +           ",fee_deposit_frac" +           ",fee_deposit_curr" +           ",fee_refresh_val" +           ",fee_refresh_frac" +           ",fee_refresh_curr" +           ",fee_refund_val" +           ",fee_refund_frac" +           ",fee_refund_curr" +           " FROM auditor_denominations" +           " WHERE master_pub=$1;",             1, NULL); + +  /* Used in #postgres_insert_auditor_progress() */ +  PREPARE ("auditor_progress_insert", +           "INSERT INTO auditor_progress " +	   "(master_pub" +	   ",last_reserve_in_serial_id" +           ",last_reserve_out_serial_id" +	   ",last_deposit_serial_id" +           ",last_melt_serial_id" +	   ",last_refund_serial_id" +	   ",last_prewire_serial_id" +           ") VALUES ($1,$2,$3,$4,$5,$6,$7);", +           7, NULL); + +  /* Used in #postgres_update_auditor_progress() */ +  PREPARE ("auditor_progress_update", +           "UPDATE auditor_progress SET " +	   " last_reserve_in_serial_id=$1" +           ",last_reserve_out_serial_id=$2" +	   ",last_deposit_serial_id=$3" +           ",last_melt_serial_id=$4" +	   ",last_refund_serial_id=$5" +	   ",last_prewire_serial_id=$6" +           " WHERE master_pub=$7", +           7, NULL); + +  /* Used in #postgres_get_auditor_progress() */ +  PREPARE ("auditor_progress_select", +           "SELECT" +	   " last_reserve_in_serial_id" +           ",last_reserve_out_serial_id" +	   ",last_deposit_serial_id" +           ",last_melt_serial_id" +	   ",last_refund_serial_id" +	   ",last_prewire_serial_id" +           " FROM auditor_progress" +           " WHERE master_pub=$1;", +           1, NULL); + +  /* Used in #postgres_insert_reserve_info() */ +  PREPARE ("auditor_reserves_insert", +           "INSERT INTO auditor_reserves " +	   "(reserve_pub" +           ",master_pub" +           ",reserve_balance_val" +           ",reserve_balance_frac" +           ",reserve_balance_curr" +           ",withdraw_fee_balance_val" +           ",withdraw_fee_balance_frac" +           ",withdraw_fee_balance_curr" +           ",expiration_date" +	   ",last_reserve_in_serial_id" +           ",last_reserve_out_serial_id" +           ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);", +           11, NULL); + +  /* Used in #postgres_update_reserve_info() */ +  PREPARE ("auditor_reserves_update", +           "UPDATE auditor_reserves SET" +           " reserve_balance_val=$1" +           ",reserve_balance_frac=$2" +           ",reserve_balance_curr=$3" +           ",withdraw_fee_balance_val=$4" +           ",withdraw_fee_balance_frac=$5" +           ",withdraw_fee_balance_curr=$6" +           ",expiration_date=$7" +	   ",last_reserve_in_serial_id=$8" +           ",last_reserve_out_serial_id=$9" +           " WHERE reserve_pub=$10 AND master_pub=$11;", +           11, NULL); + +  /* Used in #postgres_get_reserve_info() */ +  PREPARE ("auditor_reserves_select", +           "SELECT" +           " reserve_balance_val" +           ",reserve_balance_frac" +           ",reserve_balance_curr" +           ",withdraw_fee_balance_val" +           ",withdraw_fee_balance_frac" +           ",withdraw_fee_balance_curr" +           ",expiration_date" +	   ",last_reserve_in_serial_id" +           ",last_reserve_out_serial_id" +           " FROM auditor_reserves" +           " WHERE reserve_pub=$1 AND master_pub=$2;", +           2, NULL); + +  /* Used in #postgres_insert_reserve_summary() */ +  PREPARE ("auditor_reserve_balance_insert", +           "INSERT INTO auditor_reserve_balance" +	   "(master_pub" +	   ",reserve_balance_val" +           ",reserve_balance_frac" +           ",reserve_balance_curr" +           ",withdraw_fee_balance_val" +           ",withdraw_fee_balance_frac" +           ",withdraw_fee_balance_curr" +           ") VALUES ($1,$2,$3,$4,$5,$6,$7)", +           7, NULL); + +  /* Used in #postgres_update_reserve_summary() */ +  PREPARE ("auditor_reserve_balance_update", +           "UPDATE auditor_reserve_balance SET" +	   " reserve_balance_val=$1" +           ",reserve_balance_frac=$2" +           ",reserve_balance_curr=$3" +           ",withdraw_fee_balance_val=$4" +           ",withdraw_fee_balance_frac=$5" +           ",withdraw_fee_balance_curr=$6" +           " WHERE master_pub=$7;", +           7, NULL); + +  /* Used in #postgres_get_reserve_summary() */ +  PREPARE ("auditor_reserve_balance_select", +           "SELECT" +	   " reserve_balance_val" +           ",reserve_balance_frac" +           ",reserve_balance_curr" +           ",withdraw_fee_balance_val" +           ",withdraw_fee_balance_frac" +           ",withdraw_fee_balance_curr" +           " FROM auditor_reserve_balance" +           " WHERE master_pub=$1;", +           1, NULL); + +  /* Used in #postgres_insert_denomination_balance() */ +  PREPARE ("denomination_pending_insert", +           "INSERT INTO denomination_pending " +	   "(denom_pub_hash" +           ",denom_balance_val" +           ",denom_balance_frac" +           ",denom_balance_curr" +           ",deposit_fee_balance_val" +           ",deposit_fee_balance_frac" +           ",deposit_fee_balance_curr" +           ",melt_fee_balance_val" +           ",melt_fee_balance_frac" +           ",melt_fee_balance_curr" +           ",refund_fee_balance_val" +           ",refund_fee_balance_frac" +           ",refund_fee_balance_curr" +           ",last_reserve_out_serial_id" +           ",last_deposit_serial_id" +	   ",last_melt_serial_id" +	   ",last_refund_serial_id" +           ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17);", +           17, NULL); + +  /* Used in #postgres_update_denomination_balance() */ +  PREPARE ("denomination_pending_update", +           "UPDATE denomination_pending SET" +           " denom_balance_val=$1" +           ",denom_balance_frac=$2" +           ",denom_balance_curr=$3" +           ",deposit_fee_balance_val=$4" +           ",deposit_fee_balance_frac=$5" +           ",deposit_fee_balance_curr=$6" +           ",melt_fee_balance_val=$7" +           ",melt_fee_balance_frac=$8" +           ",melt_fee_balance_curr=$9" +           ",refund_fee_balance_val=$10" +           ",refund_fee_balance_frac=$11" +           ",refund_fee_balance_curr=$12" +           ",last_reserve_out_serial_id=$13" +           ",last_deposit_serial_id=$14" +	   ",last_melt_serial_id=$15" +	   ",last_refund_serial_id=$16" +           " WHERE denom_pub_hash=$17", +           18, NULL); + +  /* Used in #postgres_get_denomination_balance() */ +  PREPARE ("denomination_pending_select", +           "SELECT" +           " denom_balance_val" +           ",denom_balance_frac" +           ",denom_balance_curr" +           ",deposit_fee_balance_val" +           ",deposit_fee_balance_frac" +           ",deposit_fee_balance_curr" +           ",melt_fee_balance_val" +           ",melt_fee_balance_frac" +           ",melt_fee_balance_curr" +           ",refund_fee_balance_val" +           ",refund_fee_balance_frac" +           ",refund_fee_balance_curr" +           ",last_reserve_out_serial_id" +           ",last_deposit_serial_id" +	   ",last_melt_serial_id" +	   ",last_refund_serial_id" +           " FROM denomination_pending" +           " WHERE denom_pub_hash=$1", +           1, NULL); + +  /* Used in #postgres_insert_denomination_summary() */ +  PREPARE ("total_liabilities_insert", +           "INSERT INTO total_liabilities " +	   "(master_pub" +	   ",denom_balance_val" +           ",denom_balance_frac" +           ",denom_balance_curr" +           ",deposit_fee_balance_val" +           ",deposit_fee_balance_frac" +           ",deposit_fee_balance_curr" +           ",melt_fee_balance_val" +           ",melt_fee_balance_frac" +           ",melt_fee_balance_curr" +           ",refund_fee_balance_val" +           ",refund_fee_balance_frac" +           ",refund_fee_balance_curr" +           ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);", +           13, NULL); + +  /* Used in #postgres_update_denomination_summary() */ +  PREPARE ("total_liabilities_update", +           "UPDATE total_liabilities SET" +	   " denom_balance_val=$1" +           ",denom_balance_frac=$2" +           ",denom_balance_curr=$3" +           ",deposit_fee_balance_val=$4" +           ",deposit_fee_balance_frac=$5" +           ",deposit_fee_balance_curr=$6" +           ",melt_fee_balance_val=$7" +           ",melt_fee_balance_frac=$8" +           ",melt_fee_balance_curr=$9" +           ",refund_fee_balance_val=$10" +           ",refund_fee_balance_frac=$11" +           ",refund_fee_balance_curr=$12" +           " WHERE master_pub=$13;", +           13, NULL); + +  /* Used in #postgres_get_denomination_summary() */ +  PREPARE ("total_liabilities_select", +           "SELECT" +	   " denom_balance_val" +           ",denom_balance_frac" +           ",denom_balance_curr" +           ",deposit_fee_balance_val" +           ",deposit_fee_balance_frac" +           ",deposit_fee_balance_curr" +           ",melt_fee_balance_val" +           ",melt_fee_balance_frac" +           ",melt_fee_balance_curr" +           ",refund_fee_balance_val" +           ",refund_fee_balance_frac" +           ",refund_fee_balance_curr" +           " FROM total_liabilities" +           " WHERE master_pub=$1;", +           1, NULL); + +  /* Used in #postgres_insert_risk_summary() */ +  PREPARE ("total_risk_insert", +           "INSERT INTO total_risk" +	   "(master_pub" +	   ",risk_val" +           ",risk_frac" +           ",risk_curr" +           ") VALUES ($1,$2,$3,$4);", +           4, NULL); + +  /* Used in #postgres_update_risk_summary() */ +  PREPARE ("total_risk_update", +           "UPDATE total_risk SET " +	   " risk_val=$1" +           ",risk_frac=$2" +           ",risk_curr=$3" +           " WHERE master_pub=$4;", +           4, NULL); + +  /* Used in #postgres_get_risk_summary() */ +  PREPARE ("total_risk_select", +           "SELECT" +	   " risk_val" +           ",risk_frac" +           ",risk_curr" +           " FROM  total_risk" +           " WHERE master_pub=$1;", +           1, NULL); + + +  /* Used in #postgres_insert_historic_denom_revenue() */ +  PREPARE ("historic_denomination_revenue_insert", +           "INSERT INTO historic_denomination_revenue" +	   "(master_pub" +	   ",denom_pub_hash" +	   ",revenue_timestamp" +	   ",revenue_balance_val" +           ",revenue_balance_frac" +           ",revenue_balance_curr" +           ",deposit_fee_balance_val" +           ",deposit_fee_balance_frac" +           ",deposit_fee_balance_curr" +           ",melt_fee_balance_val" +           ",melt_fee_balance_frac" +           ",melt_fee_balance_curr" +           ",refund_fee_balance_val" +           ",refund_fee_balance_frac" +           ",refund_fee_balance_curr" +           ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15);", +           15, NULL); + +  /* Used in #postgres_select_historic_denom_revenue() */ +  PREPARE ("historic_denomination_revenue_select", +           "SELECT" +	   " denom_pub_hash" +	   ",revenue_timestamp" +	   ",revenue_balance_val" +           ",revenue_balance_frac" +           ",revenue_balance_curr" +           ",deposit_fee_balance_val" +           ",deposit_fee_balance_frac" +           ",deposit_fee_balance_curr" +           ",melt_fee_balance_val" +           ",melt_fee_balance_frac" +           ",melt_fee_balance_curr" +           ",refund_fee_balance_val" +           ",refund_fee_balance_frac" +           ",refund_fee_balance_curr" +           " FROM historic_denomination_revenue" +           " WHERE master_pub=$1;", +           1, NULL); + +  /* Used in #postgres_insert_historic_losses() */ +  PREPARE ("historic_losses_insert", +           "INSERT INTO historic_losses" +	   "(master_pub" +	   ",denom_pub_hash" +	   ",loss_timestamp" +	   ",loss_balance_val" +           ",loss_balance_frac" +           ",loss_balance_curr" +           ") VALUES ($1,$2,$3,$4,$5,$6);", +           6, NULL); + +  /* Used in #postgres_select_historic_losses() */ +  PREPARE ("historic_losses_select", +           "SELECT" +	   " denom_pub_hash" +	   ",loss_timestamp" +	   ",loss_balance_val" +           ",loss_balance_frac" +           ",loss_balance_curr" +           " FROM historic_losses" +           " WHERE master_pub=$1;", +           1, NULL); + +  /* Used in #postgres_insert_historic_reserve_revenue() */ +  PREPARE ("historic_reserve_summary_insert", +           "INSERT INTO historic_reserve_summary" +	   "(master_pub" +	   ",start_date" +	   ",end_date" +	   ",reserve_profits_val" +           ",reserve_profits_frac" +           ",reserve_profits_curr" +           ") VALUES ($1,$2,$3,$4,$5,$6);", +           6, NULL); + +  /* Used in #postgres_select_historic_reserve_revenue() */ +  PREPARE ("historic_reserve_summary_select", +           "SELECT" +	   " start_date" +	   ",end_date" +	   ",reserve_profits_val" +           ",reserve_profits_frac" +           ",reserve_profits_curr" +           " FROM historic_reserve_summary" +           " WHERE master_pub=$1;", +           1, NULL); + +  /* Used in #postgres_insert_predicted_result() */ +  PREPARE ("predicted_result_insert", +           "INSERT INTO predicted_result" +	   "(master_pub" +	   ",balance_val" +           ",balance_frac" +           ",balance_curr" +           ") VALUES ($1,$2,$3,$4);", +           4, NULL); + +  /* Used in #postgres_update_predicted_result() */ +  PREPARE ("predicted_result_update", +           "UPDATE predicted_result SET" +	   " balance_val=$1" +           ",balance_frac=$2" +           ",balance_curr=$3" +           " WHERE master_pub=$4;", +           4, NULL); + +  /* Used in #postgres_get_predicted_balance() */ +  PREPARE ("predicted_result_select", +           "SELECT" +	   " balance_val" +           ",balance_frac" +           ",balance_curr" +           " FROM predicted_result" +           " WHERE master_pub=$1;", +           1, NULL); +    return GNUNET_OK;  #undef PREPARE  } @@ -743,8 +1186,55 @@ postgres_insert_denomination_info (void *cls,                                     struct TALER_AUDITORDB_Session *session,                                     const struct TALER_DenominationKeyValidityPS *issue)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (&issue->denom_hash), +    GNUNET_PQ_query_param_auto_from_type (&issue->master), + +    GNUNET_PQ_query_param_auto_from_type (&issue->start), +    GNUNET_PQ_query_param_auto_from_type (&issue->expire_withdraw), +    GNUNET_PQ_query_param_auto_from_type (&issue->expire_deposit), +    GNUNET_PQ_query_param_auto_from_type (&issue->expire_legal), + +    TALER_PQ_query_param_amount_nbo (&issue->value), +    TALER_PQ_query_param_amount_nbo (&issue->fee_withdraw), +    TALER_PQ_query_param_amount_nbo (&issue->fee_deposit), +    TALER_PQ_query_param_amount_nbo (&issue->fee_refresh), +    TALER_PQ_query_param_amount_nbo (&issue->fee_refund), + +    GNUNET_PQ_query_param_end +  }; + +  /* check fees match coin currency */ +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency_nbo (&issue->value, +                                                &issue->fee_withdraw)); +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency_nbo (&issue->value, +                                                &issue->fee_deposit)); +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency_nbo (&issue->value, +                                                &issue->fee_refresh)); +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency_nbo (&issue->value, +                                               &issue->fee_refund)); + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "auditor_denominations_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -762,11 +1252,265 @@ static int  postgres_select_denomination_info (void *cls,                                     struct TALER_AUDITORDB_Session *session,                                     const struct TALER_MasterPublicKeyP *master_pub, -                                   void *cb, /* FIXME: type! */ +                                   TALER_AUDITORDB_DenominationInfoDataCallback cb,                                     void *cb_cls)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "auditor_denominations_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int ret = GNUNET_OK; +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_select_denomination_info() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  for (int i = 0; i < nrows; i++) +  { +    struct TALER_DenominationKeyValidityPS issue = { .master = *master_pub }; + +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &issue.denom_hash), + +      GNUNET_PQ_result_spec_auto_from_type ("valid_from", &issue.start), +      GNUNET_PQ_result_spec_auto_from_type ("expire_withdraw", &issue.expire_withdraw), +      GNUNET_PQ_result_spec_auto_from_type ("expire_deposit", &issue.expire_deposit), +      GNUNET_PQ_result_spec_auto_from_type ("expire_legal", &issue.expire_legal), + +      TALER_PQ_result_spec_amount_nbo ("coin", &issue.value), +      TALER_PQ_result_spec_amount_nbo ("fee_withdraw", &issue.fee_withdraw), +      TALER_PQ_result_spec_amount_nbo ("fee_deposit", &issue.fee_deposit), +      TALER_PQ_result_spec_amount_nbo ("fee_refresh", &issue.fee_refresh), +      TALER_PQ_result_spec_amount_nbo ("fee_refund", &issue.fee_refund), + +      GNUNET_PQ_result_spec_end +    }; +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, rs, 0)) +    { +      GNUNET_break (0); +      PQclear (result); +      return GNUNET_SYSERR; +    } +    ret = cb (cb_cls, +              &issue); +    switch (ret) +    { +    case GNUNET_OK: +      break; + +    default: +      i = nrows; +    } +  } +  PQclear (result); +  return ret; +} + + +/** + * Insert information about the auditor's progress with an exchange's + * data. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to use + * @param master_pub master key of the exchange + * @param last_reserve_in_serial_id serial ID of the last reserve_in transfer the auditor processed + * @param last_reserve_out_serial_id serial ID of the last withdraw the auditor processed + * @param last_deposit_serial_id serial ID of the last deposit the auditor processed + * @param last_melt_serial_id serial ID of the last refresh the auditor processed + * @param last_prewire_serial_id serial ID of the last prewire transfer the auditor processed + * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure + */ +int +postgres_insert_auditor_progress (void *cls, +                                  struct TALER_AUDITORDB_Session *session, +                                  const struct TALER_MasterPublicKeyP *master_pub, +                                  uint64_t last_reserve_in_serial_id, +                                  uint64_t last_reserve_out_serial_id, +                                  uint64_t last_deposit_serial_id, +                                  uint64_t last_melt_serial_id, +                                  uint64_t last_refund_serial_id, +                                  uint64_t last_prewire_serial_id) +{ +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_uint64 (&last_reserve_in_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_reserve_out_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_deposit_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_melt_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_refund_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_prewire_serial_id), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "auditor_progress_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret; +} + + +/** + * Update information about the progress of the auditor.  There + * must be an existing record for the exchange. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to use + * @param master_pub master key of the exchange + * @param last_reserve_in_serial_id serial ID of the last reserve_in transfer the auditor processed + * @param last_reserve_out_serial_id serial ID of the last withdraw the auditor processed + * @param last_deposit_serial_id serial ID of the last deposit the auditor processed + * @param last_melt_serial_id serial ID of the last refresh the auditor processed + * @param last_prewire_serial_id serial ID of the last prewire transfer the auditor processed + * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure + */ +int +postgres_update_auditor_progress (void *cls, +                                  struct TALER_AUDITORDB_Session *session, +                                  const struct TALER_MasterPublicKeyP *master_pub, +                                  uint64_t last_reserve_in_serial_id, +                                  uint64_t last_reserve_out_serial_id, +                                  uint64_t last_deposit_serial_id, +                                  uint64_t last_melt_serial_id, +                                  uint64_t last_refund_serial_id, +                                  uint64_t last_prewire_serial_id) +{ +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_uint64 (&last_reserve_in_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_reserve_out_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_deposit_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_melt_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_refund_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_prewire_serial_id), + +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "auditor_progress_update", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret; +} + + +/** + * Get information about the progress of the auditor. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to use + * @param master_pub master key of the exchange + * @param[out] last_reserve_in_serial_id serial ID of the last reserve_in transfer the auditor processed + * @param[out] last_reserve_out_serial_id serial ID of the last withdraw the auditor processed + * @param[out] last_deposit_serial_id serial ID of the last deposit the auditor processed + * @param[out] last_melt_serial_id serial ID of the last refresh the auditor processed + * @param[out] last_prewire_serial_id serial ID of the last prewire transfer the auditor processed + * @return #GNUNET_OK on success; #GNUNET_SYSERR on failure; + *         #GNUNET_NO if we have no records for the @a master_pub + */ +int +postgres_get_auditor_progress (void *cls, +                               struct TALER_AUDITORDB_Session *session, +                               const struct TALER_MasterPublicKeyP *master_pub, +                               uint64_t *last_reserve_in_serial_id, +                               uint64_t *last_reserve_out_serial_id, +                               uint64_t *last_deposit_serial_id, +                               uint64_t *last_melt_serial_id, +                               uint64_t *last_refund_serial_id, +                               uint64_t *last_prewire_serial_id) +{ +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "auditor_progress_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_get_auditor_progress() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  GNUNET_assert (1 == nrows); + +  struct GNUNET_PQ_ResultSpec rs[] = { +    GNUNET_PQ_result_spec_uint64 ("last_reserve_in_serial_id", last_reserve_in_serial_id), +    GNUNET_PQ_result_spec_uint64 ("last_reserve_out_serial_id", last_reserve_out_serial_id), +    GNUNET_PQ_result_spec_uint64 ("last_deposit_serial_id", last_deposit_serial_id), +    GNUNET_PQ_result_spec_uint64 ("last_melt_serial_id", last_melt_serial_id), +    GNUNET_PQ_result_spec_uint64 ("last_refund_serial_id", last_refund_serial_id), +    GNUNET_PQ_result_spec_uint64 ("last_prewire_serial_id", last_prewire_serial_id), + +    GNUNET_PQ_result_spec_end +  }; +  if (GNUNET_OK != +      GNUNET_PQ_extract_result (result, rs, 0)) +  { +    GNUNET_break (0); +    PQclear (result); +    return GNUNET_SYSERR; +  } +  PQclear (result); +  return GNUNET_OK;  } @@ -799,8 +1543,42 @@ postgres_insert_reserve_info (void *cls,                                uint64_t last_reserve_in_serial_id,                                uint64_t last_reserve_out_serial_id)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (reserve_pub), +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    TALER_PQ_query_param_amount (reserve_balance), +    TALER_PQ_query_param_amount (withdraw_fee_balance), + +    GNUNET_PQ_query_param_auto_from_type (&expiration_date), + +    GNUNET_PQ_query_param_uint64 (&last_reserve_in_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_reserve_out_serial_id), + +    GNUNET_PQ_query_param_end +  }; + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (reserve_balance, +                                            withdraw_fee_balance)); + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "auditor_reserves_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -833,8 +1611,42 @@ postgres_update_reserve_info (void *cls,                                uint64_t last_reserve_in_serial_id,                                uint64_t last_reserve_out_serial_id)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    TALER_PQ_query_param_amount (reserve_balance), +    TALER_PQ_query_param_amount (withdraw_fee_balance), + +    GNUNET_PQ_query_param_auto_from_type (&expiration_date), + +    GNUNET_PQ_query_param_uint64 (&last_reserve_in_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_reserve_out_serial_id), + +    GNUNET_PQ_query_param_auto_from_type (reserve_pub), +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (reserve_balance, +                                            withdraw_fee_balance)); + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "auditor_reserves_update", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -867,8 +1679,54 @@ postgres_get_reserve_info (void *cls,                             uint64_t *last_reserve_in_serial_id,                             uint64_t *last_reserve_out_serial_id)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (reserve_pub), +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "auditor_reserves_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_get_reserve_info() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  GNUNET_assert (1 == nrows); + +  struct GNUNET_PQ_ResultSpec rs[] = { +    TALER_PQ_result_spec_amount ("reserve_balance", reserve_balance), +    TALER_PQ_result_spec_amount ("withdraw_fee_balance", withdraw_fee_balance), + +    GNUNET_PQ_result_spec_auto_from_type ("expiration_date", expiration_date), + +    GNUNET_PQ_result_spec_uint64 ("last_reserve_in_serial_id", last_reserve_in_serial_id), +    GNUNET_PQ_result_spec_uint64 ("last_reserve_out_serial_id", last_reserve_out_serial_id), + +    GNUNET_PQ_result_spec_end +  }; +  if (GNUNET_OK != +      GNUNET_PQ_extract_result (result, rs, 0)) +  { +    GNUNET_break (0); +    PQclear (result); +    return GNUNET_SYSERR; +  } +  PQclear (result); +  return GNUNET_OK;  } @@ -891,8 +1749,36 @@ postgres_insert_reserve_summary (void *cls,                                   const struct TALER_Amount *reserve_balance,                                   const struct TALER_Amount *withdraw_fee_balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    TALER_PQ_query_param_amount (reserve_balance), +    TALER_PQ_query_param_amount (withdraw_fee_balance), + +    GNUNET_PQ_query_param_end +  }; + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (reserve_balance, +                                            withdraw_fee_balance)); + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "auditor_reserve_balance_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -915,8 +1801,32 @@ postgres_update_reserve_summary (void *cls,                                   const struct TALER_Amount *reserve_balance,                                   const struct TALER_Amount *withdraw_fee_balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    TALER_PQ_query_param_amount (reserve_balance), +    TALER_PQ_query_param_amount (withdraw_fee_balance), + +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "auditor_reserve_balance_update", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -939,8 +1849,48 @@ postgres_get_reserve_summary (void *cls,                                struct TALER_Amount *reserve_balance,                                struct TALER_Amount *withdraw_fee_balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "auditor_reserve_balance_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_get_reserve_summary() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  GNUNET_assert (1 == nrows); + +  struct GNUNET_PQ_ResultSpec rs[] = { +    TALER_PQ_result_spec_amount ("reserve_balance", reserve_balance), +    TALER_PQ_result_spec_amount ("withdraw_fee_balance", withdraw_fee_balance), + +    GNUNET_PQ_result_spec_end +  }; +  if (GNUNET_OK != +      GNUNET_PQ_extract_result (result, rs, 0)) +  { +    GNUNET_break (0); +    PQclear (result); +    return GNUNET_SYSERR; +  } +  PQclear (result); +  return GNUNET_OK;  } @@ -978,8 +1928,51 @@ postgres_insert_denomination_balance (void *cls,                                        uint64_t last_melt_serial_id,                                        uint64_t last_refund_serial_id)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + +    TALER_PQ_query_param_amount (denom_balance), +    TALER_PQ_query_param_amount (deposit_fee_balance), +    TALER_PQ_query_param_amount (melt_fee_balance), +    TALER_PQ_query_param_amount (refund_fee_balance), + +    GNUNET_PQ_query_param_uint64 (&last_reserve_out_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_deposit_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_melt_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_refund_serial_id), + +    GNUNET_PQ_query_param_end +  }; + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (denom_balance, +                                            deposit_fee_balance)); + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (denom_balance, +                                            melt_fee_balance)); + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (denom_balance, +                                            refund_fee_balance)); + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "denomination_pending_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1017,8 +2010,39 @@ postgres_update_denomination_balance (void *cls,                                        uint64_t last_melt_serial_id,                                        uint64_t last_refund_serial_id)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    TALER_PQ_query_param_amount (denom_balance), +    TALER_PQ_query_param_amount (deposit_fee_balance), +    TALER_PQ_query_param_amount (melt_fee_balance), +    TALER_PQ_query_param_amount (refund_fee_balance), + +    GNUNET_PQ_query_param_uint64 (&last_reserve_out_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_deposit_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_melt_serial_id), +    GNUNET_PQ_query_param_uint64 (&last_refund_serial_id), + +    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "denomination_pending_update", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1055,8 +2079,55 @@ postgres_get_denomination_balance (void *cls,                                     uint64_t *last_melt_serial_id,                                     uint64_t *last_refund_serial_id)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "denomination_pending_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_get_denomination_balance() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  GNUNET_assert (1 == nrows); + +  struct GNUNET_PQ_ResultSpec rs[] = { +    TALER_PQ_result_spec_amount ("denom_balance", denom_balance), +    TALER_PQ_result_spec_amount ("deposit_fee_balance", deposit_fee_balance), +    TALER_PQ_result_spec_amount ("melt_fee_balance", melt_fee_balance), +    TALER_PQ_result_spec_amount ("refund_fee_balance", refund_fee_balance), + +    GNUNET_PQ_result_spec_uint64 ("last_reserve_out_serial_id", last_reserve_out_serial_id), +    GNUNET_PQ_result_spec_uint64 ("last_deposit_serial_id", last_deposit_serial_id), +    GNUNET_PQ_result_spec_uint64 ("last_melt_serial_id", last_melt_serial_id), +    GNUNET_PQ_result_spec_uint64 ("last_refund_serial_id", last_refund_serial_id), + +    GNUNET_PQ_result_spec_end +  }; +  if (GNUNET_OK != +      GNUNET_PQ_extract_result (result, rs, 0)) +  { +    GNUNET_break (0); +    PQclear (result); +    return GNUNET_SYSERR; +  } +  PQclear (result); +  return GNUNET_OK;  } @@ -1082,8 +2153,46 @@ postgres_insert_denomination_summary (void *cls,                                        const struct TALER_Amount *melt_fee_balance,                                        const struct TALER_Amount *refund_fee_balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    TALER_PQ_query_param_amount (denom_balance), +    TALER_PQ_query_param_amount (deposit_fee_balance), +    TALER_PQ_query_param_amount (melt_fee_balance), +    TALER_PQ_query_param_amount (refund_fee_balance), + +    GNUNET_PQ_query_param_end +  }; + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (denom_balance, +                                            deposit_fee_balance)); + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (denom_balance, +                                            melt_fee_balance)); + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (denom_balance, +                                            refund_fee_balance)); + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "total_liabilities_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1109,8 +2218,34 @@ postgres_update_denomination_summary (void *cls,                                        const struct TALER_Amount *melt_fee_balance,                                        const struct TALER_Amount *refund_fee_balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    TALER_PQ_query_param_amount (denom_balance), +    TALER_PQ_query_param_amount (deposit_fee_balance), +    TALER_PQ_query_param_amount (melt_fee_balance), +    TALER_PQ_query_param_amount (refund_fee_balance), + +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "total_liabilities_update", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1136,8 +2271,50 @@ postgres_get_denomination_summary (void *cls,                                     struct TALER_Amount *melt_fee_balance,                                     struct TALER_Amount *refund_fee_balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "total_liabilities_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_get_denomination_summary() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  GNUNET_assert (1 == nrows); + +  struct GNUNET_PQ_ResultSpec rs[] = { +    TALER_PQ_result_spec_amount ("denom_balance", denom_balance), +    TALER_PQ_result_spec_amount ("deposit_fee_balance", deposit_fee_balance), +    TALER_PQ_result_spec_amount ("melt_fee_balance", melt_fee_balance), +    TALER_PQ_result_spec_amount ("refund_fee_balance", refund_fee_balance), + +    GNUNET_PQ_result_spec_end +  }; +  if (GNUNET_OK != +      GNUNET_PQ_extract_result (result, rs, 0)) +  { +    GNUNET_break (0); +    PQclear (result); +    return GNUNET_SYSERR; +  } +  PQclear (result); +  return GNUNET_OK;  } @@ -1157,8 +2334,31 @@ postgres_insert_risk_summary (void *cls,                                const struct TALER_MasterPublicKeyP *master_pub,                                const struct TALER_Amount *risk)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    TALER_PQ_query_param_amount (risk), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "total_risk_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1178,8 +2378,31 @@ postgres_update_risk_summary (void *cls,                                const struct TALER_MasterPublicKeyP *master_pub,                                const struct TALER_Amount *risk)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    TALER_PQ_query_param_amount (risk), + +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "total_risk_update", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1199,8 +2422,47 @@ postgres_get_risk_summary (void *cls,                             const struct TALER_MasterPublicKeyP *master_pub,                             struct TALER_Amount *risk)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "total_risk_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_get_risk_summary() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  GNUNET_assert (1 == nrows); + +  struct GNUNET_PQ_ResultSpec rs[] = { +    TALER_PQ_result_spec_amount ("risk", risk), + +    GNUNET_PQ_result_spec_end +  }; +  if (GNUNET_OK != +      GNUNET_PQ_extract_result (result, rs, 0)) +  { +    GNUNET_break (0); +    PQclear (result); +    return GNUNET_SYSERR; +  } +  PQclear (result); +  return GNUNET_OK;  } @@ -1232,8 +2494,49 @@ postgres_insert_historic_denom_revenue (void *cls,                                          const struct TALER_Amount *melt_fee_balance,                                          const struct TALER_Amount *refund_fee_balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), +    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + +    GNUNET_PQ_query_param_auto_from_type (&revenue_timestamp), + +    TALER_PQ_query_param_amount (revenue_balance), +    TALER_PQ_query_param_amount (deposit_fee_balance), +    TALER_PQ_query_param_amount (melt_fee_balance), +    TALER_PQ_query_param_amount (refund_fee_balance), + +    GNUNET_PQ_query_param_end +  }; + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (revenue_balance, +                                            deposit_fee_balance)); + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (revenue_balance, +                                            melt_fee_balance)); + +  GNUNET_assert (GNUNET_YES == +                 TALER_amount_cmp_currency (revenue_balance, +                                            refund_fee_balance)); + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "historic_denomination_revenue_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1252,11 +2555,82 @@ static int  postgres_select_historic_denom_revenue (void *cls,                                          struct TALER_AUDITORDB_Session *session,                                          const struct TALER_MasterPublicKeyP *master_pub, -                                        void *cb, /* FIXME: fix type */ +                                        TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb,                                          void *cb_cls)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "historic_denomination_revenue_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int ret = GNUNET_OK; +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_select_historic_denom_revenue() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  for (int i = 0; i < nrows; i++) +  { +    struct GNUNET_HashCode denom_pub_hash; +    struct GNUNET_TIME_Absolute revenue_timestamp; +    struct TALER_Amount revenue_balance; +    struct TALER_Amount deposit_fee_balance; +    struct TALER_Amount melt_fee_balance; +    struct TALER_Amount refund_fee_balance; + +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &denom_pub_hash), + +      GNUNET_PQ_result_spec_auto_from_type ("revenue_timestamp", &revenue_timestamp), + +      TALER_PQ_result_spec_amount ("revenue_balance", &revenue_balance), +      TALER_PQ_result_spec_amount ("deposit_fee_balance", &deposit_fee_balance), +      TALER_PQ_result_spec_amount ("melt_fee_balance", &melt_fee_balance), +      TALER_PQ_result_spec_amount ("refund_fee_balance", &refund_fee_balance), + +      GNUNET_PQ_result_spec_end +    }; +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, rs, 0)) +    { +      GNUNET_break (0); +      PQclear (result); +      return GNUNET_SYSERR; +    } + +    ret = cb (cb_cls, +              &denom_pub_hash, +              revenue_timestamp, +              &revenue_balance, +              &deposit_fee_balance, +              &melt_fee_balance, +              &refund_fee_balance); +    switch (ret) +    { +    case GNUNET_OK: +      break; + +    default: +      i = nrows; +    } +  } +  PQclear (result); +  return ret;  } @@ -1283,8 +2657,34 @@ postgres_insert_historic_losses (void *cls,                                   struct GNUNET_TIME_Absolute loss_timestamp,                                   const struct TALER_Amount *loss_balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), +    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash), + +    GNUNET_PQ_query_param_auto_from_type (&loss_timestamp), + +    TALER_PQ_query_param_amount (loss_balance), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "historic_losses_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1303,11 +2703,72 @@ static int  postgres_select_historic_losses (void *cls,                                   struct TALER_AUDITORDB_Session *session,                                   const struct TALER_MasterPublicKeyP *master_pub, -                                 void *cb, /* FIXME: fix type */ +                                 TALER_AUDITORDB_HistoricLossesDataCallback cb,                                   void *cb_cls)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "historic_losses_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int ret = GNUNET_OK; +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_select_historic_losses() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  for (int i = 0; i < nrows; i++) +  { +    struct GNUNET_HashCode denom_pub_hash; +    struct GNUNET_TIME_Absolute loss_timestamp; +    struct TALER_Amount loss_balance; + +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", &denom_pub_hash), + +      GNUNET_PQ_result_spec_auto_from_type ("loss_timestamp", &loss_timestamp), + +      TALER_PQ_result_spec_amount ("loss_balance", &loss_balance), + +      GNUNET_PQ_result_spec_end +    }; +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, rs, 0)) +    { +      GNUNET_break (0); +      PQclear (result); +      return GNUNET_SYSERR; +    } +    ret = cb (cb_cls, +              &denom_pub_hash, +              loss_timestamp, +              &loss_balance); +    switch (ret) +    { +    case GNUNET_OK: +      break; + +    default: +      i = nrows; +    } +  } +  PQclear (result); +  return ret;  } @@ -1330,8 +2791,34 @@ postgres_insert_historic_reserve_revenue (void *cls,                                            struct GNUNET_TIME_Absolute end_time,                                            const struct TALER_Amount *reserve_profits)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_auto_from_type (&start_time), +    GNUNET_PQ_query_param_auto_from_type (&end_time), + +    TALER_PQ_query_param_amount (reserve_profits), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "historic_reserve_summary_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1349,11 +2836,71 @@ static int  postgres_select_historic_reserve_revenue (void *cls,                                            struct TALER_AUDITORDB_Session *session,                                            const struct TALER_MasterPublicKeyP *master_pub, -                                          void *cb, /* FIXME: type */ +                                          TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb,                                            void *cb_cls)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "historic_reserve_summary_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int ret = GNUNET_OK; +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_select_historic_reserve_revenue() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  for (int i = 0; i < nrows; i++) +  { +    struct GNUNET_TIME_Absolute start_date; +    struct GNUNET_TIME_Absolute end_date; +    struct TALER_Amount reserve_profits; + +    struct GNUNET_PQ_ResultSpec rs[] = { +      GNUNET_PQ_result_spec_auto_from_type ("start_date", &start_date), +      GNUNET_PQ_result_spec_auto_from_type ("end_date", &end_date), + +      TALER_PQ_result_spec_amount ("reserve_profits", &reserve_profits), + +      GNUNET_PQ_result_spec_end +    }; +    if (GNUNET_OK != +        GNUNET_PQ_extract_result (result, rs, 0)) +    { +      GNUNET_break (0); +      PQclear (result); +      return GNUNET_SYSERR; +    } +    ret = cb (cb_cls, +              start_date, +              end_date, +              &reserve_profits); +    switch (ret) +    { +    case GNUNET_OK: +      break; + +    default: +      i = nrows; +    } +  } +  PQclear (result); +  return ret;  } @@ -1373,8 +2920,30 @@ postgres_insert_predicted_result (void *cls,                                    const struct TALER_MasterPublicKeyP *master_pub,                                    const struct TALER_Amount *balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), +    TALER_PQ_query_param_amount (balance), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "predicted_result_insert", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1394,8 +2963,30 @@ postgres_update_predicted_result (void *cls,                                    const struct TALER_MasterPublicKeyP *master_pub,                                    const struct TALER_Amount *balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  PGresult *result; +  int ret; + +  struct GNUNET_PQ_QueryParam params[] = { +    TALER_PQ_query_param_amount (balance), +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; + +  result = GNUNET_PQ_exec_prepared (session->conn, +                                   "predicted_result_update", +                                   params); +  if (PGRES_COMMAND_OK != PQresultStatus (result)) +  { +    ret = GNUNET_SYSERR; +    BREAK_DB_ERR (result); +  } +  else +  { +    ret = GNUNET_OK; +  } +  PQclear (result); +  return ret;  } @@ -1415,8 +3006,47 @@ postgres_get_predicted_balance (void *cls,                                  const struct TALER_MasterPublicKeyP *master_pub,                                  struct TALER_Amount *balance)  { -  GNUNET_break (0); // FIXME: not implemented -  return GNUNET_SYSERR; +  struct GNUNET_PQ_QueryParam params[] = { +    GNUNET_PQ_query_param_auto_from_type (master_pub), + +    GNUNET_PQ_query_param_end +  }; +  PGresult *result; +  result = GNUNET_PQ_exec_prepared (session->conn, +                                    "predicted_result_select", +                                    params); +  if (PGRES_TUPLES_OK != +      PQresultStatus (result)) +  { +    BREAK_DB_ERR (result); +    PQclear (result); +    return GNUNET_SYSERR; +  } + +  int nrows = PQntuples (result); +  if (0 == nrows) +  { +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "postgres_get_predicted_balance() returned 0 matching rows\n"); +    PQclear (result); +    return GNUNET_NO; +  } +  GNUNET_assert (1 == nrows); + +  struct GNUNET_PQ_ResultSpec rs[] = { +    TALER_PQ_result_spec_amount ("balance", balance), + +    GNUNET_PQ_result_spec_end +  }; +  if (GNUNET_OK != +      GNUNET_PQ_extract_result (result, rs, 0)) +  { +    GNUNET_break (0); +    PQclear (result); +    return GNUNET_SYSERR; +  } +  PQclear (result); +  return GNUNET_OK;  } @@ -1472,32 +3102,46 @@ libtaler_plugin_auditordb_postgres_init (void *cls)    plugin->commit = &postgres_commit;    plugin->rollback = &postgres_rollback;    plugin->gc = &postgres_gc; -  plugin->get_predicted_balance = &postgres_get_predicted_balance; -  plugin->update_predicted_result = &postgres_update_predicted_result; -  plugin->insert_predicted_result = &postgres_insert_predicted_result; -  plugin->select_historic_reserve_revenue = &postgres_select_historic_reserve_revenue; -  plugin->insert_historic_reserve_revenue = &postgres_insert_historic_reserve_revenue; -  plugin->select_historic_losses = &postgres_select_historic_losses; -  plugin->insert_historic_losses = &postgres_insert_historic_losses; -  plugin->select_historic_denom_revenue = &postgres_select_historic_denom_revenue; -  plugin->insert_historic_denom_revenue = &postgres_insert_historic_denom_revenue; -  plugin->get_risk_summary = &postgres_get_risk_summary; -  plugin->update_risk_summary = &postgres_update_risk_summary; -  plugin->insert_risk_summary = &postgres_insert_risk_summary; -  plugin->get_denomination_summary = &postgres_get_denomination_summary; -  plugin->update_denomination_summary = &postgres_update_denomination_summary; -  plugin->insert_denomination_summary = &postgres_insert_denomination_summary; -  plugin->get_denomination_balance = &postgres_get_denomination_balance; -  plugin->update_denomination_balance = &postgres_update_denomination_balance; -  plugin->insert_denomination_balance = &postgres_insert_denomination_balance; -  plugin->get_reserve_summary = &postgres_get_reserve_summary; -  plugin->update_reserve_summary = &postgres_update_reserve_summary; -  plugin->insert_reserve_summary = &postgres_insert_reserve_summary; + +  plugin->select_denomination_info = &postgres_select_denomination_info; +  plugin->insert_denomination_info = &postgres_insert_denomination_info; + +  plugin->get_auditor_progress = &postgres_get_auditor_progress; +  plugin->update_auditor_progress = &postgres_update_auditor_progress; +  plugin->insert_auditor_progress = &postgres_insert_auditor_progress; +    plugin->get_reserve_info = &postgres_get_reserve_info;    plugin->update_reserve_info = &postgres_update_reserve_info;    plugin->insert_reserve_info = &postgres_insert_reserve_info; -  plugin->select_denomination_info = &postgres_select_denomination_info; -  plugin->insert_denomination_info = &postgres_insert_denomination_info; + +  plugin->get_reserve_summary = &postgres_get_reserve_summary; +  plugin->update_reserve_summary = &postgres_update_reserve_summary; +  plugin->insert_reserve_summary = &postgres_insert_reserve_summary; + +  plugin->get_denomination_balance = &postgres_get_denomination_balance; +  plugin->update_denomination_balance = &postgres_update_denomination_balance; +  plugin->insert_denomination_balance = &postgres_insert_denomination_balance; + +  plugin->get_denomination_summary = &postgres_get_denomination_summary; +  plugin->update_denomination_summary = &postgres_update_denomination_summary; +  plugin->insert_denomination_summary = &postgres_insert_denomination_summary; + +  plugin->get_risk_summary = &postgres_get_risk_summary; +  plugin->update_risk_summary = &postgres_update_risk_summary; +  plugin->insert_risk_summary = &postgres_insert_risk_summary; + +  plugin->select_historic_denom_revenue = &postgres_select_historic_denom_revenue; +  plugin->insert_historic_denom_revenue = &postgres_insert_historic_denom_revenue; + +  plugin->select_historic_losses = &postgres_select_historic_losses; +  plugin->insert_historic_losses = &postgres_insert_historic_losses; + +  plugin->select_historic_reserve_revenue = &postgres_select_historic_reserve_revenue; +  plugin->insert_historic_reserve_revenue = &postgres_insert_historic_reserve_revenue; + +  plugin->get_predicted_balance = &postgres_get_predicted_balance; +  plugin->update_predicted_result = &postgres_update_predicted_result; +  plugin->insert_predicted_result = &postgres_insert_predicted_result;    return plugin;  } diff --git a/src/auditordb/test-auditor-db-postgres.conf b/src/auditordb/test-auditor-db-postgres.conf new file mode 100644 index 00000000..5c1e7fbc --- /dev/null +++ b/src/auditordb/test-auditor-db-postgres.conf @@ -0,0 +1,7 @@ +[auditor] +# Which database backend do we use for the auditor? +DB = postgres + +[auditordb-postgres] +# Argument for Postgres for how to connect to the database. +DB_CONN_STR = "postgres:///talercheck" diff --git a/src/auditordb/test_auditordb.c b/src/auditordb/test_auditordb.c new file mode 100644 index 00000000..93c27938 --- /dev/null +++ b/src/auditordb/test_auditordb.c @@ -0,0 +1,798 @@ +/* +  This file is part of TALER +  Copyright (C) 2016 GNUnet e.V. and INRIA + +  TALER is free software; you can redistribute it and/or modify it under the +  terms of the GNU General Public License as published by the Free Software +  Foundation; either version 3, or (at your option) any later version. + +  TALER is distributed in the hope that it will be useful, but WITHOUT ANY +  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +  A PARTICULAR PURPOSE.  See the GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License along with +  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file auditordb/test_auditordb.c + * @brief test cases for DB interaction functions + * @author Gabor X Toth + */ +#include "platform.h" +#include "taler_auditordb_lib.h" +#include "taler_auditordb_plugin.h" + + +/** + * Global result from the testcase. + */ +static int result = -1; + +/** + * Report line of error if @a cond is true, and jump to label "drop". + */ +#define FAILIF(cond)                              \ +    do {                                          \ +        if (!(cond)){ break;}                     \ +        GNUNET_break (0);                         \ +        goto drop;                                \ +  } while (0) + + +/** + * Initializes @a ptr with random data. + */ +#define RND_BLK(ptr)                                                    \ +  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr)) + +/** + * Initializes @a ptr with zeros. + */ +#define ZR_BLK(ptr) \ +  memset (ptr, 0, sizeof (*ptr)) + + +/** + * Currency we use. + */ +#define CURRENCY "EUR" + +/** + * Database plugin under test. + */ +static struct TALER_AUDITORDB_Plugin *plugin; + + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure with config + */ +static void +run (void *cls) +{ +  struct GNUNET_CONFIGURATION_Handle *cfg = cls; +  struct TALER_AUDITORDB_Session *session; + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "loading database plugin\n"); + +  if (NULL == +      (plugin = TALER_AUDITORDB_plugin_load (cfg))) +  { +    result = 77; +    return; +  } + +  (void) plugin->drop_tables (plugin->cls); +  if (GNUNET_OK != +      plugin->create_tables (plugin->cls)) +  { +    result = 77; +    goto drop; +  } +  if (NULL == +      (session = plugin->get_session (plugin->cls))) +  { +    result = 77; +    goto drop; +  } + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "initializing\n"); + +  struct TALER_Amount value, fee_withdraw, fee_deposit, fee_refresh, fee_refund; + +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":1.000010", +                                         &value)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000011", +                                         &fee_withdraw)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000012", +                                         &fee_deposit)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000013", +                                         &fee_refresh)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":0.000014", +                                         &fee_refund)); + +  struct TALER_MasterPublicKeyP master_pub; +  struct TALER_ReservePublicKeyP reserve_pub; +  struct GNUNET_HashCode rnd_hash; +  RND_BLK (&master_pub); +  RND_BLK (&reserve_pub); +  RND_BLK (&rnd_hash); + +  struct TALER_DenominationPrivateKey denom_priv; +  struct TALER_DenominationPublicKey denom_pub; +  struct GNUNET_HashCode denom_pub_hash; +  denom_priv.rsa_private_key = GNUNET_CRYPTO_rsa_private_key_create (1024); +  denom_pub.rsa_public_key = GNUNET_CRYPTO_rsa_private_key_get_public (denom_priv.rsa_private_key); +  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key, &denom_pub_hash); + +  struct GNUNET_TIME_Absolute now, past, future, date; +  now = GNUNET_TIME_absolute_get (); +  past = GNUNET_TIME_absolute_subtract (now, +                                        GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, +                                                                       4)); +  future = GNUNET_TIME_absolute_add (now, +                                     GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, +                                                                  4)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_denomination_info\n"); + +  struct TALER_DenominationKeyValidityPS issue = { 0 }; +  issue.master = master_pub; +  issue.denom_hash = denom_pub_hash; + +  issue.start = GNUNET_TIME_absolute_hton (now); +  issue.expire_withdraw = GNUNET_TIME_absolute_hton +    (GNUNET_TIME_absolute_add (now, +                               GNUNET_TIME_UNIT_HOURS)); +  issue.expire_deposit = GNUNET_TIME_absolute_hton +      (GNUNET_TIME_absolute_add +       (now, +        GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 2))); +  issue.expire_legal = GNUNET_TIME_absolute_hton +      (GNUNET_TIME_absolute_add +       (now, +        GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 3))); +  TALER_amount_hton (&issue.value, &value); +  TALER_amount_hton (&issue.fee_withdraw, &fee_withdraw); +  TALER_amount_hton (&issue.fee_deposit, &fee_deposit); +  TALER_amount_hton (&issue.fee_refresh, &fee_refresh); +  TALER_amount_hton (&issue.fee_refund, &fee_refund); + +  FAILIF (GNUNET_OK != +          plugin->insert_denomination_info (plugin->cls, +                                            session, +                                            &issue)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: select_denomination_info\n"); + +  int +  select_denomination_info_result (void *cls, +                                   const struct TALER_DenominationKeyValidityPS *issue2) +  { +    const struct TALER_DenominationKeyValidityPS *issue1 = cls; + +    if (0 != memcmp (issue1, issue2, sizeof (*issue2))) +    { +      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                  "select_denomination_info_result: issue does not match\n"); +      GNUNET_break (0); +      return GNUNET_SYSERR; +    } +    return GNUNET_OK; +  } + +  FAILIF (GNUNET_OK != +          plugin->select_denomination_info (plugin->cls, +                                            session, +                                            &master_pub, +                                            select_denomination_info_result, +                                            &issue)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_auditor_progress\n"); + +  uint64_t +      last_reserve_in_serial_id = 1234, +      last_reserve_out_serial_id = 5678, +      last_deposit_serial_id = 123, +      last_melt_serial_id = 456, +      last_refund_serial_id = 789, +      last_prewire_serial_id = 555, + +      last_reserve_in_serial_id2 = 0, +      last_reserve_out_serial_id2 = 0, +      last_deposit_serial_id2 = 0, +      last_melt_serial_id2 = 0, +      last_refund_serial_id2 = 0, +      last_prewire_serial_id2 = 0; + +  FAILIF (GNUNET_OK != +          plugin->insert_auditor_progress (plugin->cls, +                                           session, +                                           &master_pub, +                                           last_reserve_in_serial_id, +                                           last_reserve_out_serial_id, +                                           last_deposit_serial_id, +                                           last_melt_serial_id, +                                           last_refund_serial_id, +                                           last_prewire_serial_id)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: update_auditor_progress\n"); + +  last_reserve_in_serial_id++; +  last_reserve_out_serial_id++; +  last_deposit_serial_id2++; +  last_melt_serial_id2++; +  last_refund_serial_id2++; +  last_prewire_serial_id2++; + +  FAILIF (GNUNET_OK != +          plugin->update_auditor_progress (plugin->cls, +                                           session, +                                           &master_pub, +                                           last_reserve_in_serial_id, +                                           last_reserve_out_serial_id, +                                           last_deposit_serial_id, +                                           last_melt_serial_id, +                                           last_refund_serial_id, +                                           last_prewire_serial_id)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: get_auditor_progress\n"); + +  FAILIF (GNUNET_OK != +          plugin->get_auditor_progress (plugin->cls, +                                        session, +                                        &master_pub, +                                        &last_reserve_in_serial_id2, +                                        &last_reserve_out_serial_id2, +                                        &last_deposit_serial_id2, +                                        &last_melt_serial_id2, +                                        &last_refund_serial_id2, +                                        &last_prewire_serial_id2)); + +  FAILIF (last_reserve_in_serial_id2 != last_reserve_in_serial_id +          || last_reserve_out_serial_id2 != last_reserve_out_serial_id +          || last_deposit_serial_id2 != last_deposit_serial_id +          || last_melt_serial_id2 != last_melt_serial_id +          || last_refund_serial_id2 != last_refund_serial_id +          || last_prewire_serial_id2 != last_prewire_serial_id); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_reserve_info\n"); + +  struct TALER_Amount reserve_balance, withdraw_fee_balance; +  struct TALER_Amount reserve_balance2 = {}, withdraw_fee_balance2 = {}; + +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":12.345678", +                                         &reserve_balance)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":23.456789", +                                         &withdraw_fee_balance)); + +  FAILIF (GNUNET_OK != +          plugin->insert_reserve_info (plugin->cls, +                                       session, +                                       &reserve_pub, +                                       &master_pub, +                                       &reserve_balance, +                                       &withdraw_fee_balance, +                                       past, +                                       last_reserve_in_serial_id, +                                       last_reserve_out_serial_id)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: update_reserve_info\n"); + +  last_reserve_in_serial_id++; +  last_reserve_out_serial_id++; + +  FAILIF (GNUNET_OK != +          plugin->update_reserve_info (plugin->cls, +                                       session, +                                       &reserve_pub, +                                       &master_pub, +                                       &reserve_balance, +                                       &withdraw_fee_balance, +                                       future, +                                       last_reserve_in_serial_id, +                                       last_reserve_out_serial_id)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: get_reserve_info\n"); + +  FAILIF (GNUNET_OK != +          plugin->get_reserve_info (plugin->cls, +                                    session, +                                    &reserve_pub, +                                    &master_pub, +                                    &reserve_balance2, +                                    &withdraw_fee_balance2, +                                    &date, +                                    &last_reserve_in_serial_id2, +                                    &last_reserve_out_serial_id2)); + +  FAILIF (0 != memcmp (&date, &future, sizeof (future)) +          || 0 != memcmp (&reserve_balance2, &reserve_balance, sizeof (reserve_balance)) +          || 0 != memcmp (&withdraw_fee_balance2, &withdraw_fee_balance, sizeof (withdraw_fee_balance)) +          || last_reserve_in_serial_id2 != last_reserve_in_serial_id +          || last_reserve_out_serial_id2 != last_reserve_out_serial_id); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_reserve_summary\n"); + +  FAILIF (GNUNET_OK != +          plugin->insert_reserve_summary (plugin->cls, +                                          session, +                                          &master_pub, +                                          &withdraw_fee_balance, +                                          &reserve_balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: update_reserve_summary\n"); + +  FAILIF (GNUNET_OK != +          plugin->update_reserve_summary (plugin->cls, +                                          session, +                                          &master_pub, +                                          &reserve_balance, +                                          &withdraw_fee_balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: get_reserve_summary\n"); + +  ZR_BLK (&reserve_balance2); +  ZR_BLK (&withdraw_fee_balance2); + +  FAILIF (GNUNET_OK != +          plugin->get_reserve_summary (plugin->cls, +                                       session, +                                       &master_pub, +                                       &reserve_balance2, +                                       &withdraw_fee_balance2)); + +  FAILIF (0 != memcmp (&reserve_balance2, &reserve_balance, sizeof (reserve_balance)) +          || 0 != memcmp (&withdraw_fee_balance2, &withdraw_fee_balance, sizeof (withdraw_fee_balance))); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_denomination_balance\n"); + +  struct TALER_Amount denom_balance, deposit_fee_balance, melt_fee_balance, refund_fee_balance; +  struct TALER_Amount denom_balance2, deposit_fee_balance2, melt_fee_balance2, refund_fee_balance2; + +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":12.345678", +                                         &denom_balance)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":23.456789", +                                         &deposit_fee_balance)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":34.567890", +                                         &melt_fee_balance)); +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":45.678901", +                                         &refund_fee_balance)); + +  FAILIF (GNUNET_OK != +          plugin->insert_denomination_balance (plugin->cls, +                                               session, +                                               &denom_pub_hash, +                                               &refund_fee_balance, +                                               &melt_fee_balance, +                                               &deposit_fee_balance, +                                               &denom_balance, +                                               last_reserve_out_serial_id, +                                               last_deposit_serial_id, +                                               last_melt_serial_id, +                                               last_refund_serial_id)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: update_denomination_balance\n"); + +  last_reserve_out_serial_id++; +  last_deposit_serial_id++; +  last_melt_serial_id++; +  last_refund_serial_id++; + +  FAILIF (GNUNET_OK != +          plugin->update_denomination_balance (plugin->cls, +                                               session, +                                               &denom_pub_hash, +                                               &denom_balance, +                                               &deposit_fee_balance, +                                               &melt_fee_balance, +                                               &refund_fee_balance, +                                               last_reserve_out_serial_id, +                                               last_deposit_serial_id, +                                               last_melt_serial_id, +                                               last_refund_serial_id)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: get_denomination_balance\n"); + +  FAILIF (GNUNET_OK != +          plugin->get_denomination_balance (plugin->cls, +                                            session, +                                            &denom_pub_hash, +                                            &denom_balance2, +                                            &deposit_fee_balance2, +                                            &melt_fee_balance2, +                                            &refund_fee_balance2, +                                            &last_reserve_out_serial_id2, +                                            &last_deposit_serial_id2, +                                            &last_melt_serial_id2, +                                            &last_refund_serial_id2)); + +  FAILIF (0 != memcmp (&denom_balance2, &denom_balance, sizeof (denom_balance)) +          || 0 != memcmp (&deposit_fee_balance2, &deposit_fee_balance, sizeof (deposit_fee_balance)) +          || 0 != memcmp (&melt_fee_balance2, &melt_fee_balance, sizeof (melt_fee_balance)) +          || 0 != memcmp (&refund_fee_balance2, &refund_fee_balance, sizeof (refund_fee_balance)) +          || last_reserve_out_serial_id2 != last_reserve_out_serial_id +          || last_deposit_serial_id2 != last_deposit_serial_id +          || last_melt_serial_id2 != last_melt_serial_id +          || last_refund_serial_id2 != last_refund_serial_id); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_denomination_summary\n"); + +  FAILIF (GNUNET_OK != +          plugin->insert_denomination_summary (plugin->cls, +                                               session, +                                               &master_pub, +                                               &refund_fee_balance, +                                               &melt_fee_balance, +                                               &deposit_fee_balance, +                                               &denom_balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: update_denomination_summary\n"); + +  FAILIF (GNUNET_OK != +          plugin->update_denomination_summary (plugin->cls, +                                               session, +                                               &master_pub, +                                               &denom_balance, +                                               &deposit_fee_balance, +                                               &melt_fee_balance, +                                               &refund_fee_balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: get_denomination_summary\n"); + +  ZR_BLK (&denom_balance2); +  ZR_BLK (&deposit_fee_balance2); +  ZR_BLK (&melt_fee_balance2); +  ZR_BLK (&refund_fee_balance2); + +  FAILIF (GNUNET_OK != +          plugin->get_denomination_summary (plugin->cls, +                                            session, +                                            &master_pub, +                                            &denom_balance2, +                                            &deposit_fee_balance2, +                                            &melt_fee_balance2, +                                            &refund_fee_balance2)); + +  FAILIF (0 != memcmp (&denom_balance2, &denom_balance, sizeof (denom_balance)) +          || 0 != memcmp (&deposit_fee_balance2, &deposit_fee_balance, sizeof (deposit_fee_balance)) +          || 0 != memcmp (&melt_fee_balance2, &melt_fee_balance, sizeof (melt_fee_balance)) +          || 0 != memcmp (&refund_fee_balance2, &refund_fee_balance, sizeof (refund_fee_balance))); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_risk_summary\n"); + +  struct TALER_Amount balance, balance2; + +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":13.57986", +                                         &balance)); + +  FAILIF (GNUNET_OK != +          plugin->insert_risk_summary (plugin->cls, +                                       session, +                                       &master_pub, +                                       &balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: update_risk_summary\n"); + +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":57.310986", +                                         &balance)); + +  FAILIF (GNUNET_OK != +          plugin->update_risk_summary (plugin->cls, +                                       session, +                                       &master_pub, +                                       &balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: get_risk_summary\n"); + +  FAILIF (GNUNET_OK != +          plugin->get_risk_summary (plugin->cls, +                                    session, +                                    &master_pub, +                                    &balance2)); + +  FAILIF (0 != memcmp (&balance2, &balance, sizeof (balance))); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_historic_denom_revenue\n"); + +  FAILIF (GNUNET_OK != +          plugin->insert_historic_denom_revenue (plugin->cls, +                                                 session, +                                                 &master_pub, +                                                 &denom_pub_hash, +                                                 past, +                                                 &balance, +                                                 &deposit_fee_balance, +                                                 &melt_fee_balance, +                                                 &refund_fee_balance)); + +  FAILIF (GNUNET_OK != +          plugin->insert_historic_denom_revenue (plugin->cls, +                                                 session, +                                                 &master_pub, +                                                 &rnd_hash, +                                                 now, +                                                 &balance, +                                                 &deposit_fee_balance, +                                                 &melt_fee_balance, +                                                 &refund_fee_balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: select_historic_denom_revenue\n"); + +  int +  select_historic_denom_revenue_result (void *cls, +                                        const struct GNUNET_HashCode *denom_pub_hash2, +                                        struct GNUNET_TIME_Absolute revenue_timestamp2, +                                        const struct TALER_Amount *revenue_balance2, +                                        const struct TALER_Amount *deposit_fee_balance2, +                                        const struct TALER_Amount *melt_fee_balance2, +                                        const struct TALER_Amount *refund_fee_balance2) +  { +    static int n = 0; + +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "select_historic_denom_revenue_result: row %u\n", n); + +    if (2 <= n++ +        || cls != NULL +        || (0 != memcmp (&revenue_timestamp2, &past, sizeof (past)) +            && 0 != memcmp (&revenue_timestamp2, &now, sizeof (now))) +        || (0 != memcmp (denom_pub_hash2, &denom_pub_hash, sizeof (denom_pub_hash)) +            && 0 != memcmp (denom_pub_hash2, &rnd_hash, sizeof (rnd_hash))) +        || 0 != memcmp (revenue_balance2, &balance, sizeof (balance)) +        || 0 != memcmp (deposit_fee_balance2, &deposit_fee_balance, sizeof (deposit_fee_balance)) +        || 0 != memcmp (melt_fee_balance2, &melt_fee_balance, sizeof (melt_fee_balance)) +        || 0 != memcmp (refund_fee_balance2, &refund_fee_balance, sizeof (refund_fee_balance))) +    { +        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "select_historic_denom_revenue_result: result does not match\n"); +        GNUNET_break (0); +        return GNUNET_SYSERR; +    } +    return GNUNET_OK; +  } + +  FAILIF (GNUNET_OK != +          plugin->select_historic_denom_revenue (plugin->cls, +                                                 session, +                                                 &master_pub, +                                                 select_historic_denom_revenue_result, +                                                 NULL)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_historic_losses\n"); + +  FAILIF (GNUNET_OK != +          plugin->insert_historic_losses (plugin->cls, +                                          session, +                                          &master_pub, +                                          &denom_pub_hash, +                                          past, +                                          &balance)); + +  FAILIF (GNUNET_OK != +          plugin->insert_historic_losses (plugin->cls, +                                          session, +                                          &master_pub, +                                          &rnd_hash, +                                          past, +                                          &balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: select_historic_losses\n"); + +  int +  select_historic_losses_result (void *cls, +                                 const struct GNUNET_HashCode *denom_pub_hash2, +                                 struct GNUNET_TIME_Absolute loss_timestamp2, +                                 const struct TALER_Amount *loss_balance2) +  { +    static int n = 0; + +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "select_historic_losses_result: row %u\n", n); + +    if (2 <= n++ +        || cls != NULL +        || (0 != memcmp (&loss_timestamp2, &past, sizeof (past)) +            && 0 != memcmp (&loss_timestamp2, &now, sizeof (now))) +        || (0 != memcmp (denom_pub_hash2, &denom_pub_hash, sizeof (denom_pub_hash)) +            && 0 != memcmp (denom_pub_hash2, &rnd_hash, sizeof (rnd_hash))) +        || 0 != memcmp (loss_balance2, &balance, sizeof (balance))) +    { +        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "select_historic_denom_revenue_result: result does not match\n"); +        GNUNET_break (0); +        return GNUNET_SYSERR; +    } +    return GNUNET_OK; +  } + +  FAILIF (GNUNET_OK != +          plugin->select_historic_losses (plugin->cls, +                                          session, +                                          &master_pub, +                                          select_historic_losses_result, +                                          NULL)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_historic_reserve_revenue\n"); + +  struct TALER_Amount reserve_profits; +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":56.789012", +                                         &reserve_profits)); + +  FAILIF (GNUNET_OK != +          plugin->insert_historic_reserve_revenue (plugin->cls, +                                                   session, +                                                   &master_pub, +                                                   past, +                                                   future, +                                                   &reserve_profits)); + +  FAILIF (GNUNET_OK != +          plugin->insert_historic_reserve_revenue (plugin->cls, +                                                   session, +                                                   &master_pub, +                                                   now, +                                                   future, +                                                   &reserve_profits)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: select_historic_reserve_revenue\n"); + +  int +  select_historic_reserve_revenue_result (void *cls, +                                          struct GNUNET_TIME_Absolute start_time2, +                                          struct GNUNET_TIME_Absolute end_time2, +                                          const struct TALER_Amount *reserve_profits2) +  { +    static int n = 0; + +    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, +                "select_historic_reserve_revenue_result: row %u\n", n); + +    if (2 <= n++ +        || cls != NULL +        || (0 != memcmp (&start_time2, &past, sizeof (past)) +            && 0 != memcmp (&start_time2, &now, sizeof (now))) +        || 0 != memcmp (&end_time2, &future, sizeof (future)) +        || 0 != memcmp (reserve_profits2, &reserve_profits, sizeof (reserve_profits))) +    { +        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                "select_historic_reserve_revenue_result: result does not match\n"); +        GNUNET_break (0); +        return GNUNET_SYSERR; +    } +    return GNUNET_OK; +  } + +  FAILIF (GNUNET_OK != +          plugin->select_historic_reserve_revenue (plugin->cls, +                                                   session, +                                                   &master_pub, +                                                   select_historic_reserve_revenue_result, +                                                   NULL)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: insert_predicted_result\n"); + +  FAILIF (GNUNET_OK != +          plugin->insert_predicted_result (plugin->cls, +                                           session, +                                           &master_pub, +                                           &balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: update_predicted_result\n"); + +  GNUNET_assert (GNUNET_OK == +                 TALER_string_to_amount (CURRENCY ":78.901234", +                                         &balance)); + +  FAILIF (GNUNET_OK != +          plugin->update_predicted_result (plugin->cls, +                                           session, +                                           &master_pub, +                                           &balance)); + +  GNUNET_log (GNUNET_ERROR_TYPE_INFO, +              "Test: get_predicted_balance\n"); + +  FAILIF (GNUNET_OK != +          plugin->get_predicted_balance (plugin->cls, +                                         session, +                                         &master_pub, +                                         &balance2)); + +  FAILIF (0 != memcmp (&balance2, &balance, sizeof (balance))); + +  result = 0; + +drop: + +  GNUNET_break (GNUNET_OK == +                plugin->drop_tables (plugin->cls)); +  TALER_AUDITORDB_plugin_unload (plugin); +  plugin = NULL; +} + + +int +main (int argc, +      char *const argv[]) +{ +  const char *plugin_name; +  char *config_filename; +  char *testname; +  struct GNUNET_CONFIGURATION_Handle *cfg; + +  result = -1; +  if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) +  { +    GNUNET_break (0); +    return -1; +  } +  GNUNET_log_setup (argv[0], +                    "WARNING", +                    NULL); +  plugin_name++; +  (void) GNUNET_asprintf (&testname, +                          "test-auditor-db-%s", plugin_name); +  (void) GNUNET_asprintf (&config_filename, +                          "%s.conf", testname); +  cfg = GNUNET_CONFIGURATION_create (); +  if (GNUNET_OK != +      GNUNET_CONFIGURATION_parse (cfg, +                                  config_filename)) +  { +    GNUNET_break (0); +    GNUNET_free (config_filename); +    GNUNET_free (testname); +    return 2; +  } +  GNUNET_SCHEDULER_run (&run, cfg); +  GNUNET_CONFIGURATION_destroy (cfg); +  GNUNET_free (config_filename); +  GNUNET_free (testname); +  return result; +} | 
