From a4d99f229a0a9c1e0c94c7e4ee5bfd8986b796a3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 6 May 2016 12:55:44 +0200 Subject: implement logic to store refund data into postgres database --- src/exchangedb/plugin_exchangedb_postgres.c | 171 +++++++++++++++++++++++----- 1 file changed, 144 insertions(+), 27 deletions(-) (limited to 'src/exchangedb') diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index b189b7a17..4dee4b54c 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -366,6 +366,25 @@ postgres_create_tables (void *cls) ",PRIMARY KEY (session_hash, oldcoin_index)" /* a coin can be used only once in a refresh session */ ") "); + /* Table with information about coins that have been refunded. (Technically + one of the deposit operations that a coin was involved with is refunded.)*/ + SQLEXEC("CREATE TABLE IF NOT EXISTS refunds " + "(coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub)" + ",merchant_pub BYTEA NOT NULL CHECK(LENGTH(merchant_pub)=32)" + ",merchant_sig BYTEA NOT NULL CHECK(LENGTH(merchant_pub)=64)" + ",h_contract BYTEA NOT NULL CHECK(LENGTH(merchant_pub)=64)" + ",transaction_id INT8 NOT NULL" + ",rtransaction_id INT8 NOT NULL" + ",amount_with_fee_val INT8 NOT NULL" + ",amount_with_fee_frac INT4 NOT NULL" + ",amount_with_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" + ",refund_fee_val INT8 NOT NULL" + ",refund_fee_frac INT4 NOT NULL" + ",refund_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" + ",PRIMARY KEY (coin_pub, merchant_pub, transaction_id, rtransaction_id)" /* this combo must be unique, and we usually select by coin_pub */ + ") "); + + /* Table with information about the desired denominations to be created during a refresh operation; contains the denomination key for each of the coins (for a given refresh session) */ @@ -892,6 +911,26 @@ postgres_prepare (PGconn *db_conn) " $11, $12, $13, $14, $15, $16, $17, $18);", 18, NULL); + /* Used in #postgres_insert_refund() to store refund information */ + PREPARE ("insert_refund", + "INSERT INTO refunds " + "(coin_pub " + ",merchant_pub " + ",merchant_sig " + ",h_contract " + ",transaction_id " + ",rtransaction_id " + ",amount_with_fee_val " + ",amount_with_fee_frac " + ",amount_with_fee_curr " + ",refund_fee_val " + ",refund_fee_frac " + ",refund_fee_curr " + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," + " $11, $12);", + 12, NULL); + /* Fetch an existing deposit request, used to ensure idempotency during /deposit processing. Used in #postgres_have_deposit(). */ PREPARE ("get_deposit", @@ -995,6 +1034,17 @@ postgres_prepare (PGconn *db_conn) " WHERE serial_id=$1", 1, NULL); + /* Used in #postgres_test_deposit_done() */ + PREPARE ("test_deposit_done", + "SELECT done" + " FROM deposits" + " WHERE coin_pub=$1" + " AND transaction_id=$2" + " AND merchant_pub=$3" + " AND h_contract=$4" + " AND h_wire=$5", + 5, NULL); + /* Used in #postgres_get_coin_transactions() to obtain information about how a coin has been spend with /deposit requests. */ PREPARE ("get_deposit_with_coin_pub", @@ -2191,8 +2241,50 @@ postgres_test_deposit_done (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct TALER_EXCHANGEDB_Deposit *deposit) { - GNUNET_break (0); // not implemented - return GNUNET_SYSERR; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub), + GNUNET_PQ_query_param_uint64 (&deposit->transaction_id), + GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub), + GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract), + GNUNET_PQ_query_param_auto_from_type (&deposit->h_wire), + GNUNET_PQ_query_param_end + }; + PGresult *result; + + result = GNUNET_PQ_exec_prepared (session->conn, + "test_deposit_done", + params); + if (PGRES_TUPLES_OK != + PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + if (0 == PQntuples (result)) + { + PQclear (result); + return GNUNET_SYSERR; + } + + { + /* NOTE: maybe wrong type for a 'boolean' */ + uint32_t done; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint32 ("done", + &done), + 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 (done ? GNUNET_YES : GNUNET_NO); + } } @@ -2449,29 +2541,26 @@ postgres_insert_deposit (void *cls, { PGresult *result; int ret; - - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub), - GNUNET_PQ_query_param_rsa_public_key (deposit->coin.denom_pub.rsa_public_key), - GNUNET_PQ_query_param_rsa_signature (deposit->coin.denom_sig.rsa_signature), - GNUNET_PQ_query_param_uint64 (&deposit->transaction_id), - TALER_PQ_query_param_amount (&deposit->amount_with_fee), - TALER_PQ_query_param_amount (&deposit->deposit_fee), - GNUNET_PQ_query_param_absolute_time (&deposit->timestamp), - GNUNET_PQ_query_param_absolute_time (&deposit->refund_deadline), - GNUNET_PQ_query_param_absolute_time (&deposit->wire_deadline), - GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub), - GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract), - GNUNET_PQ_query_param_auto_from_type (&deposit->h_wire), - GNUNET_PQ_query_param_auto_from_type (&deposit->csig), - TALER_PQ_query_param_json (deposit->wire), - GNUNET_PQ_query_param_end - }; - result = GNUNET_PQ_exec_prepared (session->conn, - "insert_deposit", - params); - } + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub), + GNUNET_PQ_query_param_rsa_public_key (deposit->coin.denom_pub.rsa_public_key), + GNUNET_PQ_query_param_rsa_signature (deposit->coin.denom_sig.rsa_signature), + GNUNET_PQ_query_param_uint64 (&deposit->transaction_id), + TALER_PQ_query_param_amount (&deposit->amount_with_fee), + TALER_PQ_query_param_amount (&deposit->deposit_fee), + GNUNET_PQ_query_param_absolute_time (&deposit->timestamp), + GNUNET_PQ_query_param_absolute_time (&deposit->refund_deadline), + GNUNET_PQ_query_param_absolute_time (&deposit->wire_deadline), + GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub), + GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract), + GNUNET_PQ_query_param_auto_from_type (&deposit->h_wire), + GNUNET_PQ_query_param_auto_from_type (&deposit->csig), + TALER_PQ_query_param_json (deposit->wire), + GNUNET_PQ_query_param_end + }; + result = GNUNET_PQ_exec_prepared (session->conn, + "insert_deposit", + params); if (PGRES_COMMAND_OK != PQresultStatus (result)) { BREAK_DB_ERR (result); @@ -2499,8 +2588,36 @@ postgres_insert_refund (void *cls, struct TALER_EXCHANGEDB_Session *session, const struct TALER_EXCHANGEDB_Refund *refund) { - GNUNET_break (0); // not implemented - return GNUNET_SYSERR; + PGresult *result; + int ret; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->merchant_pub), + GNUNET_PQ_query_param_auto_from_type (&refund->merchant_sig), + GNUNET_PQ_query_param_auto_from_type (&refund->h_contract), + GNUNET_PQ_query_param_uint64 (&refund->transaction_id), + GNUNET_PQ_query_param_uint64 (&refund->rtransaction_id), + TALER_PQ_query_param_amount (&refund->refund_amount), + TALER_PQ_query_param_amount (&refund->refund_fee), + GNUNET_PQ_query_param_end + }; + GNUNET_assert (GNUNET_YES == + TALER_amount_cmp_currency (&refund->refund_amount, + &refund->refund_fee)); + result = GNUNET_PQ_exec_prepared (session->conn, + "insert_refund", + params); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + ret = GNUNET_SYSERR; + BREAK_DB_ERR (result); + } + else + { + ret = GNUNET_OK; + } + PQclear (result); + return ret; } -- cgit v1.2.3