From 38876c503ff53f7adf44bc82be4fec3ae9b02d01 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 15 Oct 2022 16:19:14 +0200 Subject: -refactor DB for reserve history/status routines --- src/exchangedb/plugin_exchangedb_postgres.c | 1033 +-------------------------- 1 file changed, 5 insertions(+), 1028 deletions(-) (limited to 'src/exchangedb/plugin_exchangedb_postgres.c') diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 940523b76..af441d95d 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -34,6 +34,7 @@ #include "pg_do_reserve_open.h" #include "pg_get_coin_transactions.h" #include "pg_get_expired_reserves.h" +#include "pg_get_reserve_history.h" #include "pg_get_unfinished_close_requests.h" #include "pg_insert_close_request.h" #include "pg_insert_records_by_table.h" @@ -684,72 +685,8 @@ prepare_statements (struct PostgresClosure *pg) " ORDER BY reserve_in_serial_id;"), /* Used in #postgres_get_reserve_history() to obtain inbound transactions for a reserve */ - GNUNET_PQ_make_prepare ( - "reserves_in_get_transactions", - /* - "SELECT" - " wire_reference" - ",credit_val" - ",credit_frac" - ",execution_date" - ",payto_uri AS sender_account_details" - " FROM reserves_in" - " JOIN wire_targets" - " ON (wire_source_h_payto = wire_target_h_payto)" - " WHERE reserve_pub=$1;", - */ - "WITH ri AS MATERIALIZED ( " - " SELECT * " - " FROM reserves_in " - " WHERE reserve_pub = $1 " - ") " - "SELECT " - " wire_reference " - " ,credit_val " - " ,credit_frac " - " ,execution_date " - " ,payto_uri AS sender_account_details " - "FROM wire_targets " - "JOIN ri " - " ON (wire_target_h_payto = wire_source_h_payto) " - "WHERE wire_target_h_payto = ( " - " SELECT wire_source_h_payto FROM ri " - "); "), /* Used in #postgres_get_reserve_status() to obtain inbound transactions for a reserve */ - GNUNET_PQ_make_prepare ( - "reserves_in_get_transactions_truncated", - /* - "SELECT" - " wire_reference" - ",credit_val" - ",credit_frac" - ",execution_date" - ",payto_uri AS sender_account_details" - " FROM reserves_in" - " JOIN wire_targets" - " ON (wire_source_h_payto = wire_target_h_payto)" - " WHERE reserve_pub=$1" - " AND execution_date>=$2;", - */ - "WITH ri AS MATERIALIZED ( " - " SELECT * " - " FROM reserves_in " - " WHERE reserve_pub = $1 " - ") " - "SELECT " - " wire_reference " - " ,credit_val " - " ,credit_frac " - " ,execution_date " - " ,payto_uri AS sender_account_details " - "FROM wire_targets " - "JOIN ri " - " ON (wire_target_h_payto = wire_source_h_payto) " - "WHERE execution_date >= $2" - " AND wire_target_h_payto = ( " - " SELECT wire_source_h_payto FROM ri " - "); "), /* Used in #postgres_do_withdraw() to store the signature of a blinded coin with the blinded coin's details before returning it during /reserve/withdraw. We store @@ -879,108 +816,7 @@ prepare_statements (struct PostgresClosure *pg) " JOIN denominations denom" " USING (denominations_serial)" " WHERE h_blind_ev=$1;"), - /* Used during #postgres_get_reserve_history() to - obtain all of the /reserve/withdraw operations that - have been performed on a given reserve. (i.e. to - demonstrate double-spending) */ - GNUNET_PQ_make_prepare ( - "get_reserves_out", - /* - "SELECT" - " ro.h_blind_ev" - ",denom.denom_pub_hash" - ",ro.denom_sig" - ",ro.reserve_sig" - ",ro.execution_date" - ",ro.amount_with_fee_val" - ",ro.amount_with_fee_frac" - ",denom.fee_withdraw_val" - ",denom.fee_withdraw_frac" - " FROM reserves res" - " JOIN reserves_out_by_reserve ror" - " ON (res.reserve_uuid = ror.reserve_uuid)" - " JOIN reserves_out ro" - " ON (ro.h_blind_ev = ror.h_blind_ev)" - " JOIN denominations denom" - " ON (ro.denominations_serial = denom.denominations_serial)" - " WHERE res.reserve_pub=$1;", - */ - "WITH robr AS MATERIALIZED ( " - " SELECT h_blind_ev " - " FROM reserves_out_by_reserve " - " WHERE reserve_uuid= ( " - " SELECT reserve_uuid " - " FROM reserves " - " WHERE reserve_pub = $1 " - " ) " - ") SELECT " - " ro.h_blind_ev " - " ,denom.denom_pub_hash " - " ,ro.denom_sig " - " ,ro.reserve_sig " - " ,ro.execution_date " - " ,ro.amount_with_fee_val " - " ,ro.amount_with_fee_frac " - " ,denom.fee_withdraw_val " - " ,denom.fee_withdraw_frac " - "FROM robr " - "JOIN reserves_out ro " - " ON (ro.h_blind_ev = robr.h_blind_ev) " - "JOIN denominations denom " - " ON (ro.denominations_serial = denom.denominations_serial);"), - /* Used during #postgres_get_reserve_status() to - obtain all of the /reserve/withdraw operations that - have been performed on a given reserve. (i.e. to - demonstrate double-spending) */ - GNUNET_PQ_make_prepare ( - "get_reserves_out_truncated", - /* - "SELECT" - " ro.h_blind_ev" - ",denom.denom_pub_hash" - ",ro.denom_sig" - ",ro.reserve_sig" - ",ro.execution_date" - ",ro.amount_with_fee_val" - ",ro.amount_with_fee_frac" - ",denom.fee_withdraw_val" - ",denom.fee_withdraw_frac" - " FROM reserves res" - " JOIN reserves_out_by_reserve ror" - " ON (res.reserve_uuid = ror.reserve_uuid)" - " JOIN reserves_out ro" - " ON (ro.h_blind_ev = ror.h_blind_ev)" - " JOIN denominations denom" - " ON (ro.denominations_serial = denom.denominations_serial)" - " WHERE res.reserve_pub=$1" - " AND execution_date>=$2;", - */ - "WITH robr AS MATERIALIZED ( " - " SELECT h_blind_ev " - " FROM reserves_out_by_reserve " - " WHERE reserve_uuid= ( " - " SELECT reserve_uuid " - " FROM reserves " - " WHERE reserve_pub = $1 " - " ) " - ") SELECT " - " ro.h_blind_ev " - " ,denom.denom_pub_hash " - " ,ro.denom_sig " - " ,ro.reserve_sig " - " ,ro.execution_date " - " ,ro.amount_with_fee_val " - " ,ro.amount_with_fee_frac " - " ,denom.fee_withdraw_val " - " ,denom.fee_withdraw_frac " - "FROM robr " - "JOIN reserves_out ro " - " ON (ro.h_blind_ev = robr.h_blind_ev) " - "JOIN denominations denom " - " ON (ro.denominations_serial = denom.denominations_serial)" - " WHERE ro.execution_date>=$2;"), /* Used in #postgres_select_withdrawals_above_serial_id() */ - GNUNET_PQ_make_prepare ( "get_reserve_balance", "SELECT" @@ -2030,203 +1866,6 @@ prepare_statements (struct PostgresClosure *pg) " USING (reserve_pub)" " WHERE close_uuid>=$1" " ORDER BY close_uuid ASC;"), - /* Used in #postgres_get_reserve_history() to obtain recoup transactions - for a reserve - query optimization should be disabled i.e. - BEGIN; SET LOCAL join_collapse_limit=1; query; COMMIT; */ - GNUNET_PQ_make_prepare ( - "recoup_by_reserve", - /* - "SELECT" - " recoup.coin_pub" - ",recoup.coin_sig" - ",recoup.coin_blind" - ",recoup.amount_val" - ",recoup.amount_frac" - ",recoup.recoup_timestamp" - ",denominations.denom_pub_hash" - ",known_coins.denom_sig" - " FROM denominations" - " JOIN (known_coins" - " JOIN recoup " - " ON (recoup.coin_pub = known_coins.coin_pub))" - " ON (known_coins.denominations_serial = denominations.denominations_serial)" - " WHERE recoup.coin_pub" - " IN (SELECT coin_pub" - " FROM recoup_by_reserve" - " JOIN (reserves_out" - " JOIN (reserves_out_by_reserve" - " JOIN reserves" - " ON (reserves.reserve_uuid = reserves_out_by_reserve.reserve_uuid))" - " ON (reserves_out_by_reserve.h_blind_ev = reserves_out.h_blind_ev))" - " ON (recoup_by_reserve.reserve_out_serial_id = reserves_out.reserve_out_serial_id)" - " WHERE reserves.reserve_pub=$1);", - */ - "SELECT robr.coin_pub " - " ,robr.coin_sig " - " ,robr.coin_blind " - " ,robr.amount_val " - " ,robr.amount_frac " - " ,robr.recoup_timestamp " - " ,denominations.denom_pub_hash " - " ,robr.denom_sig " - "FROM denominations " - " JOIN exchange_do_recoup_by_reserve($1) robr" - " USING (denominations_serial);"), - /* Used in #postgres_get_reserve_status() to obtain recoup transactions - for a reserve - query optimization should be disabled i.e. - BEGIN; SET LOCAL join_collapse_limit=1; query; COMMIT; */ - GNUNET_PQ_make_prepare ( - "recoup_by_reserve_truncated", - /* - "SELECT" - " recoup.coin_pub" - ",recoup.coin_sig" - ",recoup.coin_blind" - ",recoup.amount_val" - ",recoup.amount_frac" - ",recoup.recoup_timestamp" - ",denominations.denom_pub_hash" - ",known_coins.denom_sig" - " FROM denominations" - " JOIN (known_coins" - " JOIN recoup " - " ON (recoup.coin_pub = known_coins.coin_pub))" - " ON (known_coins.denominations_serial = denominations.denominations_serial)" - " WHERE recoup_timestamp>=$2" - " AND recoup.coin_pub" - " IN (SELECT coin_pub" - " FROM recoup_by_reserve" - " JOIN (reserves_out" - " JOIN (reserves_out_by_reserve" - " JOIN reserves" - " ON (reserves.reserve_uuid = reserves_out_by_reserve.reserve_uuid))" - " ON (reserves_out_by_reserve.h_blind_ev = reserves_out.h_blind_ev))" - " ON (recoup_by_reserve.reserve_out_serial_id = reserves_out.reserve_out_serial_id)" - " WHERE reserves.reserve_pub=$1);", - */ - "SELECT robr.coin_pub " - " ,robr.coin_sig " - " ,robr.coin_blind " - " ,robr.amount_val " - " ,robr.amount_frac " - " ,robr.recoup_timestamp " - " ,denominations.denom_pub_hash " - " ,robr.denom_sig " - "FROM denominations " - " JOIN exchange_do_recoup_by_reserve($1) robr" - " USING (denominations_serial)" - " WHERE recoup_timestamp>=$2;"), - /* Used in #postgres_get_reserve_history() */ - GNUNET_PQ_make_prepare ( - "close_by_reserve", - "SELECT" - " amount_val" - ",amount_frac" - ",closing_fee_val" - ",closing_fee_frac" - ",execution_date" - ",payto_uri AS receiver_account" - ",wtid" - " FROM reserves_close" - " JOIN wire_targets" - " USING (wire_target_h_payto)" - " WHERE reserve_pub=$1;"), - /* Used in #postgres_get_reserve_status() */ - GNUNET_PQ_make_prepare ( - "close_by_reserve_truncated", - "SELECT" - " amount_val" - ",amount_frac" - ",closing_fee_val" - ",closing_fee_frac" - ",execution_date" - ",payto_uri AS receiver_account" - ",wtid" - " FROM reserves_close" - " JOIN wire_targets" - " USING (wire_target_h_payto)" - " WHERE reserve_pub=$1" - " AND execution_date>=$2;"), - /* Used in #postgres_get_reserve_history() */ - GNUNET_PQ_make_prepare ( - "merge_by_reserve", - "SELECT" - " pr.amount_with_fee_val" - ",pr.amount_with_fee_frac" - ",pr.balance_val" - ",pr.balance_frac" - ",pr.purse_fee_val" - ",pr.purse_fee_frac" - ",pr.h_contract_terms" - ",pr.merge_pub" - ",am.reserve_sig" - ",pm.purse_pub" - ",pm.merge_timestamp" - ",pr.purse_expiration" - ",pr.age_limit" - ",pr.flags" - " FROM purse_merges pm" - " JOIN purse_requests pr" - " USING (purse_pub)" - " JOIN account_merges am" - " ON (am.purse_pub = pm.purse_pub AND" - " am.reserve_pub = pm.reserve_pub)" - " WHERE pm.reserve_pub=$1" - " AND pm.partner_serial_id=0" /* must be local! */ - " AND pr.finished" - " AND NOT pr.refunded;"), - /* Used in #postgres_get_reserve_status() */ - GNUNET_PQ_make_prepare ( - "merge_by_reserve_truncated", - "SELECT" - " pr.amount_with_fee_val" - ",pr.amount_with_fee_frac" - ",pr.balance_val" - ",pr.balance_frac" - ",pr.purse_fee_val" - ",pr.purse_fee_frac" - ",pr.h_contract_terms" - ",pr.merge_pub" - ",am.reserve_sig" - ",pm.purse_pub" - ",pm.merge_timestamp" - ",pr.purse_expiration" - ",pr.age_limit" - ",pr.flags" - " FROM purse_merges pm" - " JOIN purse_requests pr" - " USING (purse_pub)" - " JOIN account_merges am" - " ON (am.purse_pub = pm.purse_pub AND" - " am.reserve_pub = pm.reserve_pub)" - " WHERE pm.reserve_pub=$1" - " AND pm.merge_timestamp >= $2" - " AND pm.partner_serial_id=0" /* must be local! */ - " AND pr.finished" - " AND NOT pr.refunded;"), - /* Used in #postgres_get_reserve_history() */ - GNUNET_PQ_make_prepare ( - "history_by_reserve", - "SELECT" - " history_fee_val" - ",history_fee_frac" - ",request_timestamp" - ",reserve_sig" - " FROM history_requests" - " WHERE reserve_pub=$1;"), - /* Used in #postgres_get_reserve_status() */ - GNUNET_PQ_make_prepare ( - "history_by_reserve_truncated", - "SELECT" - " history_fee_val" - ",history_fee_frac" - ",request_timestamp" - ",reserve_sig" - " FROM history_requests" - " WHERE reserve_pub=$1" - " AND request_timestamp>=$2;"), - /* Used in #postgres_get_coin_transactions() to obtain recoup transactions - for a coin */ /* Used in #postgres_get_reserve_by_h_blind() */ GNUNET_PQ_make_prepare ( "reserve_by_h_blind", @@ -4871,670 +4510,6 @@ postgres_do_recoup_refresh ( } -/** - * Closure for callbacks invoked via #postgres_get_reserve_history. - */ -struct ReserveHistoryContext -{ - - /** - * Which reserve are we building the history for? - */ - const struct TALER_ReservePublicKeyP *reserve_pub; - - /** - * Where we build the history. - */ - struct TALER_EXCHANGEDB_ReserveHistory *rh; - - /** - * Tail of @e rh list. - */ - struct TALER_EXCHANGEDB_ReserveHistory *rh_tail; - - /** - * Plugin context. - */ - struct PostgresClosure *pg; - - /** - * Sum of all credit transactions. - */ - struct TALER_Amount balance_in; - - /** - * Sum of all debit transactions. - */ - struct TALER_Amount balance_out; - - /** - * Set to #GNUNET_SYSERR on serious internal errors during - * the callbacks. - */ - enum GNUNET_GenericReturnValue status; -}; - - -/** - * Append and return a fresh element to the reserve - * history kept in @a rhc. - * - * @param rhc where the history is kept - * @return the fresh element that was added - */ -static struct TALER_EXCHANGEDB_ReserveHistory * -append_rh (struct ReserveHistoryContext *rhc) -{ - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - tail = GNUNET_new (struct TALER_EXCHANGEDB_ReserveHistory); - if (NULL != rhc->rh_tail) - { - rhc->rh_tail->next = tail; - rhc->rh_tail = tail; - } - else - { - rhc->rh_tail = tail; - rhc->rh = tail; - } - return tail; -} - - -/** - * Add bank transfers to result set for #postgres_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_bank_to_exchange (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct PostgresClosure *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_BankTransfer *bt; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - bt = GNUNET_new (struct TALER_EXCHANGEDB_BankTransfer); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("wire_reference", - &bt->wire_reference), - TALER_PQ_RESULT_SPEC_AMOUNT ("credit", - &bt->amount), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &bt->execution_date), - GNUNET_PQ_result_spec_string ("sender_account_details", - &bt->sender_account_details), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (bt); - rhc->status = GNUNET_SYSERR; - return; - } - } - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_in, - &rhc->balance_in, - &bt->amount)); - bt->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE; - tail->details.bank = bt; - } /* end of 'while (0 < rows)' */ -} - - -/** - * Add coin withdrawals to result set for #postgres_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_withdraw_coin (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct PostgresClosure *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_CollectableBlindcoin *cbc; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - cbc = GNUNET_new (struct TALER_EXCHANGEDB_CollectableBlindcoin); - { - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev", - &cbc->h_coin_envelope), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &cbc->denom_pub_hash), - TALER_PQ_result_spec_blinded_denom_sig ("denom_sig", - &cbc->sig), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &cbc->reserve_sig), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &cbc->amount_with_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw", - &cbc->withdraw_fee), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (cbc); - rhc->status = GNUNET_SYSERR; - return; - } - } - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_out, - &rhc->balance_out, - &cbc->amount_with_fee)); - cbc->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_WITHDRAW_COIN; - tail->details.withdraw = cbc; - } -} - - -/** - * Add recoups to result set for #postgres_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_recoup (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct PostgresClosure *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_Recoup *recoup; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - recoup = GNUNET_new (struct TALER_EXCHANGEDB_Recoup); - { - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &recoup->value), - GNUNET_PQ_result_spec_auto_from_type ("coin_pub", - &recoup->coin.coin_pub), - GNUNET_PQ_result_spec_auto_from_type ("coin_blind", - &recoup->coin_blind), - GNUNET_PQ_result_spec_auto_from_type ("coin_sig", - &recoup->coin_sig), - GNUNET_PQ_result_spec_timestamp ("recoup_timestamp", - &recoup->timestamp), - GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash", - &recoup->coin.denom_pub_hash), - TALER_PQ_result_spec_denom_sig ( - "denom_sig", - &recoup->coin.denom_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (recoup); - rhc->status = GNUNET_SYSERR; - return; - } - } - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_in, - &rhc->balance_in, - &recoup->value)); - recoup->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_RECOUP_COIN; - tail->details.recoup = recoup; - } /* end of 'while (0 < rows)' */ -} - - -/** - * Add exchange-to-bank transfers to result set for - * #postgres_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_exchange_to_bank (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct PostgresClosure *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_ClosingTransfer *closing; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - closing = GNUNET_new (struct TALER_EXCHANGEDB_ClosingTransfer); - { - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("amount", - &closing->amount), - TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &closing->closing_fee), - GNUNET_PQ_result_spec_timestamp ("execution_date", - &closing->execution_date), - GNUNET_PQ_result_spec_string ("receiver_account", - &closing->receiver_account_details), - GNUNET_PQ_result_spec_auto_from_type ("wtid", - &closing->wtid), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (closing); - rhc->status = GNUNET_SYSERR; - return; - } - } - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_out, - &rhc->balance_out, - &closing->amount)); - closing->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK; - tail->details.closing = closing; - } /* end of 'while (0 < rows)' */ -} - - -/** - * Add purse merge transfers to result set for - * #postgres_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_p2p_merge (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct PostgresClosure *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_PurseMerge *merge; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - merge = GNUNET_new (struct TALER_EXCHANGEDB_PurseMerge); - { - uint32_t flags32; - struct TALER_Amount balance; - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee", - &merge->purse_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("balance", - &balance), - TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", - &merge->amount_with_fee), - GNUNET_PQ_result_spec_timestamp ("merge_timestamp", - &merge->merge_timestamp), - GNUNET_PQ_result_spec_timestamp ("purse_expiration", - &merge->purse_expiration), - GNUNET_PQ_result_spec_uint32 ("age_limit", - &merge->min_age), - GNUNET_PQ_result_spec_uint32 ("flags", - &flags32), - GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", - &merge->h_contract_terms), - GNUNET_PQ_result_spec_auto_from_type ("merge_pub", - &merge->merge_pub), - GNUNET_PQ_result_spec_auto_from_type ("purse_pub", - &merge->purse_pub), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &merge->reserve_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (merge); - rhc->status = GNUNET_SYSERR; - return; - } - merge->flags = (enum TALER_WalletAccountMergeFlags) flags32; - if ( (! GNUNET_TIME_absolute_is_future ( - merge->merge_timestamp.abs_time)) && - (-1 != TALER_amount_cmp (&balance, - &merge->amount_with_fee)) ) - merge->merged = true; - } - if (merge->merged) - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_in, - &rhc->balance_in, - &merge->amount_with_fee)); - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_out, - &rhc->balance_out, - &merge->purse_fee)); - merge->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_PURSE_MERGE; - tail->details.merge = merge; - } -} - - -/** - * Add paid for history requests to result set for - * #postgres_get_reserve_history. - * - * @param cls a `struct ReserveHistoryContext *` - * @param result SQL result - * @param num_results number of rows in @a result - */ -static void -add_history_requests (void *cls, - PGresult *result, - unsigned int num_results) -{ - struct ReserveHistoryContext *rhc = cls; - struct PostgresClosure *pg = rhc->pg; - - while (0 < num_results) - { - struct TALER_EXCHANGEDB_HistoryRequest *history; - struct TALER_EXCHANGEDB_ReserveHistory *tail; - - history = GNUNET_new (struct TALER_EXCHANGEDB_HistoryRequest); - { - struct GNUNET_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee", - &history->history_fee), - GNUNET_PQ_result_spec_timestamp ("request_timestamp", - &history->request_timestamp), - GNUNET_PQ_result_spec_auto_from_type ("reserve_sig", - &history->reserve_sig), - GNUNET_PQ_result_spec_end - }; - - if (GNUNET_OK != - GNUNET_PQ_extract_result (result, - rs, - --num_results)) - { - GNUNET_break (0); - GNUNET_free (history); - rhc->status = GNUNET_SYSERR; - return; - } - } - GNUNET_assert (0 <= - TALER_amount_add (&rhc->balance_out, - &rhc->balance_out, - &history->history_fee)); - history->reserve_pub = *rhc->reserve_pub; - tail = append_rh (rhc); - tail->type = TALER_EXCHANGEDB_RO_HISTORY_REQUEST; - tail->details.history = history; - } -} - - -/** - * Get all of the transaction history associated with the specified - * reserve. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param reserve_pub public key of the reserve - * @param[out] balance set to the reserve balance - * @param[out] rhp set to known transaction history (NULL if reserve is unknown) - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_get_reserve_history (void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_Amount *balance, - struct TALER_EXCHANGEDB_ReserveHistory **rhp) -{ - struct PostgresClosure *pg = cls; - struct ReserveHistoryContext rhc; - struct - { - /** - * Name of the prepared statement to run. - */ - const char *statement; - /** - * Function to use to process the results. - */ - GNUNET_PQ_PostgresResultHandler cb; - } work[] = { - /** #TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE */ - { "reserves_in_get_transactions", - add_bank_to_exchange }, - /** #TALER_EXCHANGEDB_RO_WITHDRAW_COIN */ - { "get_reserves_out", - &add_withdraw_coin }, - /** #TALER_EXCHANGEDB_RO_RECOUP_COIN */ - { "recoup_by_reserve", - &add_recoup }, - /** #TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK */ - { "close_by_reserve", - &add_exchange_to_bank }, - /** #TALER_EXCHANGEDB_RO_PURSE_MERGE */ - { "merge_by_reserve", - &add_p2p_merge }, - /** #TALER_EXCHANGEDB_RO_HISTORY_REQUEST */ - { "history_by_reserve", - &add_history_requests }, - /* List terminator */ - { NULL, - NULL } - }; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_end - }; - - rhc.reserve_pub = reserve_pub; - rhc.rh = NULL; - rhc.rh_tail = NULL; - rhc.pg = pg; - rhc.status = GNUNET_OK; - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &rhc.balance_in)); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &rhc.balance_out)); - qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; /* make static analysis happy */ - for (unsigned int i = 0; NULL != work[i].cb; i++) - { - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - work[i].statement, - params, - work[i].cb, - &rhc); - if ( (0 > qs) || - (GNUNET_OK != rhc.status) ) - break; - } - if ( (qs < 0) || - (rhc.status != GNUNET_OK) ) - { - TEH_COMMON_free_reserve_history (cls, - rhc.rh); - rhc.rh = NULL; - if (qs >= 0) - { - /* status == SYSERR is a very hard error... */ - qs = GNUNET_DB_STATUS_HARD_ERROR; - } - } - *rhp = rhc.rh; - GNUNET_assert (0 <= - TALER_amount_subtract (balance, - &rhc.balance_in, - &rhc.balance_out)); - return qs; -} - - -/** - * Get a truncated transaction history associated with the specified - * reserve. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param reserve_pub public key of the reserve - * @param[out] balance_in set to the total of inbound - * transactions in the returned history - * @param[out] balance_out set to the total of outbound - * transactions in the returned history - * @param[out] rhp set to known transaction history (NULL if reserve is unknown) - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -postgres_get_reserve_status (void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_Amount *balance_in, - struct TALER_Amount *balance_out, - struct TALER_EXCHANGEDB_ReserveHistory **rhp) -{ - struct PostgresClosure *pg = cls; - struct ReserveHistoryContext rhc; - struct - { - /** - * Name of the prepared statement to run. - */ - const char *statement; - /** - * Function to use to process the results. - */ - GNUNET_PQ_PostgresResultHandler cb; - } work[] = { - /** #TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE */ - { "reserves_in_get_transactions_truncated", - add_bank_to_exchange }, - /** #TALER_EXCHANGEDB_RO_WITHDRAW_COIN */ - { "get_reserves_out_truncated", - &add_withdraw_coin }, - /** #TALER_EXCHANGEDB_RO_RECOUP_COIN */ - { "recoup_by_reserve_truncated", - &add_recoup }, - /** #TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK */ - { "close_by_reserve_truncated", - &add_exchange_to_bank }, - /** #TALER_EXCHANGEDB_RO_PURSE_MERGE */ - { "merge_by_reserve_truncated", - &add_p2p_merge }, - /** #TALER_EXCHANGEDB_RO_HISTORY_REQUEST */ - { "history_by_reserve_truncated", - &add_history_requests }, - /* List terminator */ - { NULL, - NULL } - }; - enum GNUNET_DB_QueryStatus qs; - struct GNUNET_TIME_Absolute timelimit; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (reserve_pub), - GNUNET_PQ_query_param_absolute_time (&timelimit), - GNUNET_PQ_query_param_end - }; - - timelimit = GNUNET_TIME_absolute_subtract ( - GNUNET_TIME_absolute_get (), - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_WEEKS, - 5)); - rhc.reserve_pub = reserve_pub; - rhc.rh = NULL; - rhc.rh_tail = NULL; - rhc.pg = pg; - rhc.status = GNUNET_OK; - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &rhc.balance_in)); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (pg->currency, - &rhc.balance_out)); - qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; /* make static analysis happy */ - for (unsigned int i = 0; NULL != work[i].cb; i++) - { - qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, - work[i].statement, - params, - work[i].cb, - &rhc); - if ( (0 > qs) || - (GNUNET_OK != rhc.status) ) - break; - } - if ( (qs < 0) || - (rhc.status != GNUNET_OK) ) - { - TEH_COMMON_free_reserve_history (cls, - rhc.rh); - rhc.rh = NULL; - if (qs >= 0) - { - /* status == SYSERR is a very hard error... */ - qs = GNUNET_DB_STATUS_HARD_ERROR; - } - } - *rhp = rhc.rh; - *balance_in = rhc.balance_in; - *balance_out = rhc.balance_out; - return qs; -} - - /** * Get the balance of the specified reserve. * @@ -14139,8 +13114,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) plugin->do_recoup = &postgres_do_recoup; plugin->do_recoup_refresh = &postgres_do_recoup_refresh; plugin->get_reserve_balance = &postgres_get_reserve_balance; - plugin->get_reserve_history = &postgres_get_reserve_history; - plugin->get_reserve_status = &postgres_get_reserve_status; plugin->count_known_coins = &postgres_count_known_coins; plugin->ensure_coin_known = &postgres_ensure_coin_known; plugin->get_known_coin = &postgres_get_known_coin; @@ -14352,6 +13325,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) = &TEH_PG_get_coin_transactions; plugin->get_expired_reserves = &TEH_PG_get_expired_reserves; + plugin->get_reserve_history + = &TEH_PG_get_reserve_history; + plugin->get_reserve_status + = &TEH_PG_get_reserve_status; plugin->get_unfinished_close_requests = &TEH_PG_get_unfinished_close_requests; plugin->insert_records_by_table -- cgit v1.2.3