summaryrefslogtreecommitdiff
path: root/src/exchangedb
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchangedb')
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c150
-rw-r--r--src/exchangedb/test_exchangedb.c96
-rw-r--r--src/exchangedb/test_exchangedb_fees.c6
3 files changed, 245 insertions, 7 deletions
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 36ae3e54e..847746412 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -383,6 +383,9 @@ postgres_create_tables (void *cls)
",wire_fee_val INT8 NOT NULL"
",wire_fee_frac INT4 NOT NULL"
",wire_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
+ ",closing_fee_val INT8 NOT NULL"
+ ",closing_fee_frac INT4 NOT NULL"
+ ",closing_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL"
",master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)"
",PRIMARY KEY (wire_method, start_date)" /* this combo must be unique */
");"),
@@ -1170,6 +1173,9 @@ postgres_prepare (PGconn *db_conn)
",wire_fee_val"
",wire_fee_frac"
",wire_fee_curr"
+ ",closing_fee_val"
+ ",closing_fee_frac"
+ ",closing_fee_curr"
",master_sig"
" FROM wire_fee"
" WHERE wire_method=$1"
@@ -1185,10 +1191,13 @@ postgres_prepare (PGconn *db_conn)
",wire_fee_val"
",wire_fee_frac"
",wire_fee_curr"
+ ",closing_fee_val"
+ ",closing_fee_frac"
+ ",closing_fee_curr"
",master_sig"
") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);",
- 7),
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);",
+ 19),
/* Used in #postgres_store_wire_transfer_out */
GNUNET_PQ_make_prepare ("insert_wire_out",
"INSERT INTO wire_out "
@@ -3033,6 +3042,128 @@ postgres_insert_refund (void *cls,
/**
+ * Closure for #get_refunds_cb().
+ */
+struct SelectRefundContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_RefundCoinCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Set to #GNUNET_SYSERR on error.
+ */
+ int status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct SelectRefundContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+get_refunds_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SelectRefundContext *srctx = cls;
+
+ for (unsigned int i=0;i<num_results;i++)
+ {
+ struct TALER_MerchantPublicKeyP merchant_pub;
+ struct TALER_MerchantSignatureP merchant_sig;
+ struct GNUNET_HashCode h_contract;
+ uint64_t rtransaction_id;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_Amount refund_fee;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+ &merchant_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
+ &merchant_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &h_contract),
+ GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
+ &rtransaction_id),
+ TALER_PQ_result_spec_amount ("amount_with_fee",
+ &amount_with_fee),
+ TALER_PQ_result_spec_amount ("fee_refund",
+ &refund_fee),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ srctx->status = GNUNET_SYSERR;
+ return;
+ }
+ if (GNUNET_OK !=
+ srctx->cb (srctx->cb_cls,
+ &merchant_pub,
+ &merchant_sig,
+ &h_contract,
+ rtransaction_id,
+ &amount_with_fee,
+ &refund_fee))
+ return;
+ }
+}
+
+
+/**
+ * Select refunds by @a coin_pub.
+ *
+ * @param cls closure of plugin
+ * @param session database handle to use
+ * @param coin_pub coin to get refunds for
+ * @param cb function to call for each refund found
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_select_refunds_by_coin (void *cls,
+ struct TALER_EXCHANGEDB_Session *session,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ TALER_EXCHANGEDB_RefundCoinCallback cb,
+ void *cb_cls)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct SelectRefundContext srctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .status = GNUNET_OK
+ };
+
+ qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
+ "get_refunds_by_coin",
+ params,
+ &get_refunds_cb,
+ &srctx);
+ if (GNUNET_SYSERR == srctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
+
+
+/**
* Lookup refresh melt commitment data under the given @a rc.
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
@@ -4234,6 +4365,7 @@ postgres_insert_aggregation_tracking (void *cls,
* @param[out] start_date when does the fee go into effect
* @param[out] end_date when does the fee end being valid
* @param[out] wire_fee how high is the wire transfer fee
+ * @param[out] closing_fee how high is the closing fee
* @param[out] master_sig signature over the above by the exchange master key
* @return status of the transaction
*/
@@ -4245,6 +4377,7 @@ postgres_get_wire_fee (void *cls,
struct GNUNET_TIME_Absolute *start_date,
struct GNUNET_TIME_Absolute *end_date,
struct TALER_Amount *wire_fee,
+ struct TALER_Amount *closing_fee,
struct TALER_MasterSignatureP *master_sig)
{
struct GNUNET_PQ_QueryParam params[] = {
@@ -4256,6 +4389,7 @@ postgres_get_wire_fee (void *cls,
TALER_PQ_result_spec_absolute_time ("start_date", start_date),
TALER_PQ_result_spec_absolute_time ("end_date", end_date),
TALER_PQ_result_spec_amount ("wire_fee", wire_fee),
+ TALER_PQ_result_spec_amount ("closing_fee", closing_fee),
GNUNET_PQ_result_spec_auto_from_type ("master_sig", master_sig),
GNUNET_PQ_result_spec_end
};
@@ -4276,6 +4410,7 @@ postgres_get_wire_fee (void *cls,
* @param start_date when does the fee go into effect
* @param end_date when does the fee end being valid
* @param wire_fee how high is the wire transfer fee
+ * @param closing_fee how high is the closing fee
* @param master_sig signature over the above by the exchange master key
* @return transaction status code
*/
@@ -4286,6 +4421,7 @@ postgres_insert_wire_fee (void *cls,
struct GNUNET_TIME_Absolute start_date,
struct GNUNET_TIME_Absolute end_date,
const struct TALER_Amount *wire_fee,
+ const struct TALER_Amount *closing_fee,
const struct TALER_MasterSignatureP *master_sig)
{
struct GNUNET_PQ_QueryParam params[] = {
@@ -4293,10 +4429,12 @@ postgres_insert_wire_fee (void *cls,
TALER_PQ_query_param_absolute_time (&start_date),
TALER_PQ_query_param_absolute_time (&end_date),
TALER_PQ_query_param_amount (wire_fee),
+ TALER_PQ_query_param_amount (closing_fee),
GNUNET_PQ_query_param_auto_from_type (master_sig),
GNUNET_PQ_query_param_end
};
struct TALER_Amount wf;
+ struct TALER_Amount cf;
struct TALER_MasterSignatureP sig;
struct GNUNET_TIME_Absolute sd;
struct GNUNET_TIME_Absolute ed;
@@ -4309,6 +4447,7 @@ postgres_insert_wire_fee (void *cls,
&sd,
&ed,
&wf,
+ &cf,
&sig);
if (qs < 0)
return qs;
@@ -4327,6 +4466,12 @@ postgres_insert_wire_fee (void *cls,
GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR;
}
+ if (0 != TALER_amount_cmp (closing_fee,
+ &cf))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
if ( (sd.abs_value_us != start_date.abs_value_us) ||
(ed.abs_value_us != end_date.abs_value_us) )
{
@@ -6236,6 +6381,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
plugin->iterate_matching_deposits = &postgres_iterate_matching_deposits;
plugin->insert_deposit = &postgres_insert_deposit;
plugin->insert_refund = &postgres_insert_refund;
+ plugin->select_refunds_by_coin = &postgres_select_refunds_by_coin;
plugin->insert_melt = &postgres_insert_melt;
plugin->get_melt = &postgres_get_melt;
plugin->insert_refresh_reveal = &postgres_insert_refresh_reveal;
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 5891a08a0..a0eb50f08 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -1062,10 +1062,12 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
struct GNUNET_TIME_Absolute start_date;
struct GNUNET_TIME_Absolute end_date;
struct TALER_Amount wire_fee;
+ struct TALER_Amount closing_fee;
struct TALER_MasterSignatureP master_sig;
struct GNUNET_TIME_Absolute sd;
struct GNUNET_TIME_Absolute ed;
struct TALER_Amount fee;
+ struct TALER_Amount fee2;
struct TALER_MasterSignatureP ms;
start_date = GNUNET_TIME_absolute_get ();
@@ -1075,6 +1077,9 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (CURRENCY ":1.424242",
&wire_fee));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (CURRENCY ":2.424242",
+ &closing_fee));
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
&master_sig,
sizeof (master_sig));
@@ -1085,6 +1090,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
start_date,
end_date,
&wire_fee,
+ &closing_fee,
&master_sig))
{
GNUNET_break (0);
@@ -1097,6 +1103,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
start_date,
end_date,
&wire_fee,
+ &closing_fee,
&master_sig))
{
GNUNET_break (0);
@@ -1112,6 +1119,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
&sd,
&ed,
&fee,
+ &fee2,
&ms))
{
GNUNET_break (0);
@@ -1125,6 +1133,7 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
&sd,
&ed,
&fee,
+ &fee2,
&ms))
{
GNUNET_break (0);
@@ -1134,6 +1143,8 @@ test_wire_fees (struct TALER_EXCHANGEDB_Session *session)
(ed.abs_value_us != end_date.abs_value_us) ||
(0 != TALER_amount_cmp (&fee,
&wire_fee)) ||
+ (0 != TALER_amount_cmp (&fee2,
+ &closing_fee)) ||
(0 != memcmp (&ms,
&master_sig,
sizeof (ms))) )
@@ -1394,6 +1405,72 @@ wire_missing_cb (void *cls,
/**
+ * Callback invoked with information about refunds applicable
+ * to a particular coin.
+ *
+ * @param cls closure with the `struct TALER_EXCHANGEDB_Refund *` we expect to get
+ * @param merchant_pub public key of merchant who authorized refund
+ * @param merchant_sig signature of merchant authorizing refund
+ * @param h_contract hash of contract being refunded
+ * @param rtransaction_id refund transaction ID
+ * @param amount_with_fee amount being refunded
+ * @param refund_fee fee the exchange keeps for the refund processing
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static int
+check_refund_cb (void *cls,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_MerchantSignatureP *merchant_sig,
+ const struct GNUNET_HashCode *h_contract,
+ uint64_t rtransaction_id,
+ const struct TALER_Amount *amount_with_fee,
+ const struct TALER_Amount *refund_fee)
+{
+ const struct TALER_EXCHANGEDB_Refund *refund = cls;
+
+ if (0 != memcmp (merchant_pub,
+ &refund->merchant_pub,
+ sizeof (struct TALER_MerchantPublicKeyP)))
+ {
+ GNUNET_break (0);
+ result = 66;
+ }
+ if (0 != memcmp (merchant_sig,
+ &refund->merchant_sig,
+ sizeof (struct TALER_MerchantSignatureP)))
+ {
+ GNUNET_break (0);
+ result = 66;
+ }
+ if (0 != memcmp (h_contract,
+ &refund->h_contract_terms,
+ sizeof (struct GNUNET_HashCode)))
+ {
+ GNUNET_break (0);
+ result = 66;
+ }
+ if (rtransaction_id != refund->rtransaction_id)
+ {
+ GNUNET_break (0);
+ result = 66;
+ }
+ if (0 != TALER_amount_cmp (amount_with_fee,
+ &refund->refund_amount))
+ {
+ GNUNET_break (0);
+ result = 66;
+ }
+ if (0 != TALER_amount_cmp (refund_fee,
+ &refund->refund_fee))
+ {
+ GNUNET_break (0);
+ result = 66;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
* Main function that will be run by the scheduler.
*
* @param cls closure with config
@@ -1890,14 +1967,20 @@ run (void *cls)
refund.merchant_pub = deposit.merchant_pub;
RND_BLK (&refund.merchant_sig);
refund.h_contract_terms = deposit.h_contract_terms;
- refund.rtransaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX);
+ refund.rtransaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+ UINT64_MAX);
refund.refund_amount = deposit.amount_with_fee;
refund.refund_fee = fee_refund;
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
plugin->insert_refund (plugin->cls,
session,
&refund));
-
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ plugin->select_refunds_by_coin (plugin->cls,
+ session,
+ &refund.coin.coin_pub,
+ &check_refund_cb,
+ &refund));
/* test payback / revocation */
RND_BLK (&master_sig);
@@ -2127,9 +2210,11 @@ main (int argc,
NULL);
plugin_name++;
(void) GNUNET_asprintf (&testname,
- "test-exchange-db-%s", plugin_name);
+ "test-exchange-db-%s",
+ plugin_name);
(void) GNUNET_asprintf (&config_filename,
- "%s.conf", testname);
+ "%s.conf",
+ testname);
cfg = GNUNET_CONFIGURATION_create ();
if (GNUNET_OK !=
GNUNET_CONFIGURATION_parse (cfg,
@@ -2140,7 +2225,8 @@ main (int argc,
GNUNET_free (testname);
return 2;
}
- GNUNET_SCHEDULER_run (&run, cfg);
+ GNUNET_SCHEDULER_run (&run,
+ cfg);
GNUNET_CONFIGURATION_destroy (cfg);
GNUNET_free (config_filename);
GNUNET_free (testname);
diff --git a/src/exchangedb/test_exchangedb_fees.c b/src/exchangedb/test_exchangedb_fees.c
index 2bee77452..0c9eceaf1 100644
--- a/src/exchangedb/test_exchangedb_fees.c
+++ b/src/exchangedb/test_exchangedb_fees.c
@@ -86,6 +86,9 @@ main (int argc,
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:1.0",
&af->wire_fee));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("EUR:1.0",
+ &af->closing_fee));
sign_af (af,
priv);
n = GNUNET_new (struct TALER_EXCHANGEDB_AggregateFees);
@@ -94,6 +97,9 @@ main (int argc,
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount ("EUR:0.1",
&n->wire_fee));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("EUR:0.1",
+ &n->closing_fee));
sign_af (n,
priv);
af->next = n;