From 7ff58c3d8f2351c57142b4b65ab75304f355fc4f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 5 Mar 2022 14:36:49 +0100 Subject: [PATCH] refactor /wire to include logic to return the wad fee (for W2W payments) --- .../taler-helper-auditor-aggregation.c | 21 +-- src/auditor/taler-helper-auditor-reserves.c | 6 +- src/benchmark/taler-aggregator-benchmark.c | 9 +- src/exchange-tools/taler-exchange-offline.c | 41 +++-- src/exchange/taler-exchange-aggregator.c | 12 +- src/exchange/taler-exchange-closer.c | 8 +- ...aler-exchange-httpd_management_wire_fees.c | 43 ++--- .../taler-exchange-httpd_transfers_get.c | 12 +- src/exchange/taler-exchange-httpd_wire.c | 12 +- src/exchangedb/exchange-0001.sql | 23 +++ src/exchangedb/irbt_callbacks.c | 31 +++- src/exchangedb/lrbt_callbacks.c | 58 ++++++- src/exchangedb/plugin_exchangedb_postgres.c | 161 +++++++++--------- src/exchangedb/test_exchangedb.c | 31 ++-- src/include/taler_crypto_lib.h | 36 +++- src/include/taler_exchange_service.h | 14 +- src/include/taler_exchangedb_plugin.h | 110 +++++++++--- src/include/taler_signatures.h | 10 +- src/include/taler_testing_lib.h | 5 +- .../exchange_api_management_set_wire_fee.c | 11 +- src/lib/exchange_api_wire.c | 20 ++- src/testing/test_auditor_api.c | 1 + src/testing/test_exchange_api.c | 1 + .../test_exchange_api_keys_cherry_picking.c | 1 + src/testing/test_exchange_management_api.c | 5 + src/testing/test_kyc_api.c | 1 + src/testing/test_taler_exchange_aggregator.c | 1 + src/testing/test_taler_exchange_wirewatch.c | 1 + .../testing_api_cmd_offline_sign_fees.c | 10 +- src/testing/testing_api_cmd_set_wire_fee.c | 25 ++- src/testing/testing_api_cmd_wire.c | 2 +- src/util/offline_signatures.c | 20 +-- src/util/util.c | 40 +++++ 33 files changed, 504 insertions(+), 278 deletions(-) diff --git a/src/auditor/taler-helper-auditor-aggregation.c b/src/auditor/taler-helper-auditor-aggregation.c index 33c51731d..da10ae760 100644 --- a/src/auditor/taler-helper-auditor-aggregation.c +++ b/src/auditor/taler-helper-auditor-aggregation.c @@ -305,14 +305,9 @@ struct WireFeeInfo struct GNUNET_TIME_Timestamp end_date; /** - * How high is the wire fee. + * How high are the wire fees. */ - struct TALER_Amount wire_fee; - - /** - * How high is the closing fee. - */ - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; }; @@ -911,7 +906,7 @@ get_wire_fee (struct AggregationContext *ac, GNUNET_TIME_timestamp_cmp (pos->end_date, >, timestamp) ) - return &pos->wire_fee; + return &pos->fees.wire; if (GNUNET_TIME_timestamp_cmp (pos->start_date, >, timestamp)) @@ -926,8 +921,7 @@ get_wire_fee (struct AggregationContext *ac, timestamp, &wfi->start_date, &wfi->end_date, - &wfi->wire_fee, - &wfi->closing_fee, + &wfi->fees, &master_sig)) { GNUNET_break (0); @@ -944,8 +938,7 @@ get_wire_fee (struct AggregationContext *ac, method, wfi->start_date, wfi->end_date, - &wfi->wire_fee, - &wfi->closing_fee, + &wfi->fees, &TALER_ARL_master_pub, &master_sig)) { @@ -958,7 +951,7 @@ get_wire_fee (struct AggregationContext *ac, /* Established fee, keep in sorted list */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wire fee is %s starting at %s\n", - TALER_amount2s (&wfi->wire_fee), + TALER_amount2s (&wfi->fees.wire), GNUNET_TIME_timestamp2s (wfi->start_date)); if ( (NULL == pos) || (NULL == pos->prev) ) @@ -999,7 +992,7 @@ get_wire_fee (struct AggregationContext *ac, TALER_JSON_pack_time_abs_human ("time", wfi->end_date.abs_time))); } - return &wfi->wire_fee; + return &wfi->fees.wire; } diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c index f14a39995..f34f0c467 100644 --- a/src/auditor/taler-helper-auditor-reserves.c +++ b/src/auditor/taler-helper-auditor-reserves.c @@ -862,7 +862,7 @@ get_closing_fee (const char *receiver_account, struct TALER_MasterSignatureP master_sig; struct GNUNET_TIME_Timestamp start_date; struct GNUNET_TIME_Timestamp end_date; - struct TALER_Amount wire_fee; + struct TALER_WireFeeSet fees; char *method; method = TALER_payto_get_method (receiver_account); @@ -875,8 +875,7 @@ get_closing_fee (const char *receiver_account, atime, &start_date, &end_date, - &wire_fee, - fee, + &fees, &master_sig)) { char *diag; @@ -892,6 +891,7 @@ get_closing_fee (const char *receiver_account, GNUNET_free (method); return GNUNET_SYSERR; } + *fee = fees.closing; GNUNET_free (method); return GNUNET_OK; } diff --git a/src/benchmark/taler-aggregator-benchmark.c b/src/benchmark/taler-aggregator-benchmark.c index 1437dafa3..046be3212 100644 --- a/src/benchmark/taler-aggregator-benchmark.c +++ b/src/benchmark/taler-aggregator-benchmark.c @@ -574,7 +574,7 @@ run (void *cls, } { - struct TALER_Amount wire_fee; + struct TALER_WireFeeSet fees; struct TALER_MasterSignatureP master_sig; unsigned int year; struct GNUNET_TIME_Timestamp ws; @@ -585,7 +585,9 @@ run (void *cls, { ws = GNUNET_TIME_absolute_to_timestamp (GNUNET_TIME_year_to_time (y - 1)); we = GNUNET_TIME_absolute_to_timestamp (GNUNET_TIME_year_to_time (y)); - make_amount (0, 5, &wire_fee); + make_amount (0, 5, &fees.wire); + make_amount (0, 5, &fees.wad); + make_amount (0, 5, &fees.closing); memset (&master_sig, 0, sizeof (master_sig)); @@ -594,8 +596,7 @@ run (void *cls, "x-taler-bank", ws, we, - &wire_fee, - &wire_fee, + &fees, &master_sig)) { GNUNET_break (0); diff --git a/src/exchange-tools/taler-exchange-offline.c b/src/exchange-tools/taler-exchange-offline.c index 0c1e84ddb..7cbb20e80 100644 --- a/src/exchange-tools/taler-exchange-offline.c +++ b/src/exchange-tools/taler-exchange-offline.c @@ -1491,8 +1491,7 @@ upload_wire_fee (const char *exchange_url, struct WireFeeRequest *wfr; const char *err_name; unsigned int err_line; - struct TALER_Amount wire_fee; - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; struct GNUNET_TIME_Timestamp start_time; struct GNUNET_TIME_Timestamp end_time; struct GNUNET_JSON_Specification spec[] = { @@ -1500,10 +1499,13 @@ upload_wire_fee (const char *exchange_url, &wire_method), TALER_JSON_spec_amount ("wire_fee", currency, - &wire_fee), + &fees.wire), + TALER_JSON_spec_amount ("wad_fee", + currency, + &fees.wad), TALER_JSON_spec_amount ("closing_fee", currency, - &closing_fee), + &fees.closing), GNUNET_JSON_spec_timestamp ("start_time", &start_time), GNUNET_JSON_spec_timestamp ("end_time", @@ -1539,8 +1541,7 @@ upload_wire_fee (const char *exchange_url, wire_method, start_time, end_time, - &wire_fee, - &closing_fee, + &fees, &master_sig, &wire_fee_cb, wfr); @@ -2360,8 +2361,8 @@ do_del_wire (char *const *args) * Set wire fees for the given year. * * @param args the array of command-line arguments to process next; - * args[0] must be the year, args[1] the wire fee and args[2] - * the closing fee. + * args[0] must be the year, args[1] the wire method, args[2] the wire fee and args[3] + * the closing fee and args[4] the wad fee. */ static void do_set_wire_fee (char *const *args) @@ -2369,8 +2370,7 @@ do_set_wire_fee (char *const *args) struct TALER_MasterSignatureP master_sig; char dummy; unsigned int year; - struct TALER_Amount wire_fee; - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; struct GNUNET_TIME_Timestamp start_time; struct GNUNET_TIME_Timestamp end_time; @@ -2386,6 +2386,7 @@ do_set_wire_fee (char *const *args) (NULL == args[1]) || (NULL == args[2]) || (NULL == args[3]) || + (NULL == args[4]) || ( (1 != sscanf (args[0], "%u%c", &year, @@ -2394,13 +2395,16 @@ do_set_wire_fee (char *const *args) args[0])) ) || (GNUNET_OK != TALER_string_to_amount (args[2], - &wire_fee)) || + &fees.wire)) || (GNUNET_OK != TALER_string_to_amount (args[3], - &closing_fee)) ) + &fees.closing)) || + (GNUNET_OK != + TALER_string_to_amount (args[4], + &fees.wad)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "You must use YEAR, METHOD, WIRE-FEE and CLOSING-FEE as arguments for this subcommand\n"); + "You must use YEAR, METHOD, WIRE-FEE, CLOSING-FEE and WAD-FEE as arguments for this subcommand\n"); test_shutdown (); global_ret = EXIT_INVALIDARGUMENT; return; @@ -2419,8 +2423,7 @@ do_set_wire_fee (char *const *args) TALER_exchange_offline_wire_fee_sign (args[1], start_time, end_time, - &wire_fee, - &closing_fee, + &fees, &master_priv, &master_sig); output_operation (OP_SET_WIRE_FEE, @@ -2432,12 +2435,14 @@ do_set_wire_fee (char *const *args) GNUNET_JSON_pack_timestamp ("end_time", end_time), TALER_JSON_pack_amount ("wire_fee", - &wire_fee), + &fees.wire), + TALER_JSON_pack_amount ("wad_fee", + &fees.wad), TALER_JSON_pack_amount ("closing_fee", - &closing_fee), + &fees.closing), GNUNET_JSON_pack_data_auto ("master_sig", &master_sig))); - next (args + 4); + next (args + 5); } diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c index 40653f9b9..abab347fe 100644 --- a/src/exchange/taler-exchange-aggregator.c +++ b/src/exchange/taler-exchange-aggregator.c @@ -43,7 +43,7 @@ struct AggregationUnit struct TALER_MerchantPublicKeyP merchant_pub; /** - * Total amount to be transferred, before subtraction of @e wire_fee and rounding down. + * Total amount to be transferred, before subtraction of @e fees.wire and rounding down. */ struct TALER_Amount total_amount; @@ -55,7 +55,7 @@ struct AggregationUnit /** * Wire fee we charge for @e wp at @e execution_time. */ - struct TALER_Amount wire_fee; + struct TALER_WireFeeSet fees; /** * Wire transfer identifier we use. @@ -454,7 +454,6 @@ deposit_cb (void *cls, /* make sure we have current fees */ au->execution_time = GNUNET_TIME_timestamp_get (); { - struct TALER_Amount closing_fee; struct GNUNET_TIME_Timestamp start_date; struct GNUNET_TIME_Timestamp end_date; struct TALER_MasterSignatureP master_sig; @@ -465,8 +464,7 @@ deposit_cb (void *cls, au->execution_time, &start_date, &end_date, - &au->wire_fee, - &closing_fee, + &au->fees, &master_sig); if (0 >= qs) { @@ -482,7 +480,7 @@ deposit_cb (void *cls, "Aggregator starts aggregation for deposit %llu to %s with wire fee %s\n", (unsigned long long) row_id, TALER_B2S (&au->wtid), - TALER_amount2s (&au->wire_fee)); + TALER_amount2s (&au->fees.wire)); qs = db_plugin->insert_aggregation_tracking (db_plugin->cls, &au->wtid, row_id); @@ -820,7 +818,7 @@ run_aggregation (void *cls) if ( (0 >= TALER_amount_subtract (&au_active.final_amount, &au_active.total_amount, - &au_active.wire_fee)) || + &au_active.fees.wire)) || (GNUNET_SYSERR == TALER_amount_round_down (&au_active.final_amount, ¤cy_round_unit)) || diff --git a/src/exchange/taler-exchange-closer.c b/src/exchange/taler-exchange-closer.c index 3847e05b2..92ba7babb 100644 --- a/src/exchange/taler-exchange-closer.c +++ b/src/exchange/taler-exchange-closer.c @@ -217,6 +217,7 @@ expired_reserve_cb (void *cls, struct TALER_WireTransferIdentifierRawP wtid; struct TALER_Amount amount_without_fee; struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; enum TALER_AmountArithmeticResult ret; enum GNUNET_DB_QueryStatus qs; const struct TALER_EXCHANGEDB_AccountInfo *wa; @@ -241,10 +242,9 @@ expired_reserve_cb (void *cls, return GNUNET_DB_STATUS_HARD_ERROR; } - /* lookup `closing_fee` from time of actual reserve expiration + /* lookup `fees` from time of actual reserve expiration (we may be lagging behind!) */ { - struct TALER_Amount wire_fee; struct GNUNET_TIME_Timestamp start_date; struct GNUNET_TIME_Timestamp end_date; struct TALER_MasterSignatureP master_sig; @@ -255,8 +255,7 @@ expired_reserve_cb (void *cls, expiration_date, &start_date, &end_date, - &wire_fee, - &closing_fee, + &fees, &master_sig); if (0 >= qs) { @@ -269,6 +268,7 @@ expired_reserve_cb (void *cls, } /* calculate transfer amount */ + closing_fee = fees.closing; ret = TALER_amount_subtract (&amount_without_fee, left, &closing_fee); diff --git a/src/exchange/taler-exchange-httpd_management_wire_fees.c b/src/exchange/taler-exchange-httpd_management_wire_fees.c index c14500e8d..1e96353ca 100644 --- a/src/exchange/taler-exchange-httpd_management_wire_fees.c +++ b/src/exchange/taler-exchange-httpd_management_wire_fees.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020, 2021 Taler Systems SA + Copyright (C) 2020, 2021, 2022 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -58,14 +58,9 @@ struct AddFeeContext struct GNUNET_TIME_Timestamp end_time; /** - * Wire fee amount. + * Wire fee amounts. */ - struct TALER_Amount wire_fee; - - /** - * Closing fee amount. - */ - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; }; @@ -91,16 +86,14 @@ add_fee (void *cls, { struct AddFeeContext *afc = cls; enum GNUNET_DB_QueryStatus qs; - struct TALER_Amount wire_fee; - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; qs = TEH_plugin->lookup_wire_fee_by_time ( TEH_plugin->cls, afc->wire_method, afc->start_time, afc->end_time, - &wire_fee, - &closing_fee); + &fees); if (qs < 0) { if (GNUNET_DB_STATUS_SOFT_ERROR == qs) @@ -115,13 +108,10 @@ add_fee (void *cls, if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs) { if ( (GNUNET_OK == - TALER_amount_is_valid (&wire_fee)) && + TALER_amount_is_valid (&fees.wire)) && (0 == - TALER_amount_cmp (&wire_fee, - &afc->wire_fee)) && - (0 == - TALER_amount_cmp (&closing_fee, - &afc->closing_fee)) ) + TALER_wire_fee_set_cmp (&fees, + &afc->fees)) ) { /* this will trigger the 'success' response */ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; @@ -142,8 +132,7 @@ add_fee (void *cls, afc->wire_method, afc->start_time, afc->end_time, - &afc->wire_fee, - &afc->closing_fee, + &afc->fees, &afc->master_sig); if (qs < 0) { @@ -175,12 +164,15 @@ TEH_handler_management_post_wire_fees ( &afc.start_time), GNUNET_JSON_spec_timestamp ("fee_end", &afc.end_time), - TALER_JSON_spec_amount ("closing_fee", - TEH_currency, - &afc.closing_fee), TALER_JSON_spec_amount ("wire_fee", TEH_currency, - &afc.wire_fee), + &afc.fees.wire), + TALER_JSON_spec_amount ("closing_fee", + TEH_currency, + &afc.fees.closing), + TALER_JSON_spec_amount ("wad_fee", + TEH_currency, + &afc.fees.wad), GNUNET_JSON_spec_end () }; @@ -201,8 +193,7 @@ TEH_handler_management_post_wire_fees ( afc.wire_method, afc.start_time, afc.end_time, - &afc.wire_fee, - &afc.closing_fee, + &afc.fees, &TEH_master_public_key, &afc.master_sig)) { diff --git a/src/exchange/taler-exchange-httpd_transfers_get.c b/src/exchange/taler-exchange-httpd_transfers_get.c index 5b914c417..0a4b1f541 100644 --- a/src/exchange/taler-exchange-httpd_transfers_get.c +++ b/src/exchange/taler-exchange-httpd_transfers_get.c @@ -211,9 +211,9 @@ struct WtidTransactionContext struct TALER_MerchantPublicKeyP merchant_pub; /** - * Wire fee applicable at @e exec_time. + * Wire fees applicable at @e exec_time. */ - struct TALER_Amount wire_fee; + struct TALER_WireFeeSet fees; /** * Execution time of the wire transfer @@ -401,7 +401,6 @@ get_transfer_deposits (void *cls, struct GNUNET_TIME_Timestamp wire_fee_start_date; struct GNUNET_TIME_Timestamp wire_fee_end_date; struct TALER_MasterSignatureP wire_fee_master_sig; - struct TALER_Amount closing_fee; /* resetting to NULL/0 in case transaction was repeated after serialization failure */ @@ -457,8 +456,7 @@ get_transfer_deposits (void *cls, ctx->exec_time, &wire_fee_start_date, &wire_fee_end_date, - &ctx->wire_fee, - &closing_fee, + &ctx->fees, &wire_fee_master_sig); GNUNET_free (wire_method); } @@ -478,7 +476,7 @@ get_transfer_deposits (void *cls, if (0 > TALER_amount_subtract (&ctx->total, &ctx->total, - &ctx->wire_fee)) + &ctx->fees.wire)) { GNUNET_break (0); *mhd_ret = TALER_MHD_reply_with_error (connection, @@ -528,7 +526,7 @@ TEH_handler_transfers_get (struct TEH_RequestContext *rc, &ctx.total, &ctx.merchant_pub, ctx.payto_uri, - &ctx.wire_fee, + &ctx.fees.wire, ctx.exec_time, ctx.wdd_head); free_ctx (&ctx); diff --git a/src/exchange/taler-exchange-httpd_wire.c b/src/exchange/taler-exchange-httpd_wire.c index e80c775ef..e1adde22a 100644 --- a/src/exchange/taler-exchange-httpd_wire.c +++ b/src/exchange/taler-exchange-httpd_wire.c @@ -200,8 +200,7 @@ add_wire_account (void *cls, * Add information about a wire account to @a cls. * * @param cls a `json_t *` array to expand with wire account details - * @param wire_fee the wire fee we charge - * @param closing_fee the closing fee we charge + * @param fees the wire fees we charge * @param start_date from when are these fees valid (start date) * @param end_date until when are these fees valid (end date, exclusive) * @param master_sig master key signature affirming that this is the correct @@ -209,8 +208,7 @@ add_wire_account (void *cls, */ static void add_wire_fee (void *cls, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, struct GNUNET_TIME_Timestamp start_date, struct GNUNET_TIME_Timestamp end_date, const struct TALER_MasterSignatureP *master_sig) @@ -222,9 +220,11 @@ add_wire_fee (void *cls, a, GNUNET_JSON_PACK ( TALER_JSON_pack_amount ("wire_fee", - wire_fee), + &fees->wire), + TALER_JSON_pack_amount ("wad_fee", + &fees->wad), TALER_JSON_pack_amount ("closing_fee", - closing_fee), + &fees->closing), GNUNET_JSON_pack_timestamp ("start_date", start_date), GNUNET_JSON_pack_timestamp ("end_date", diff --git a/src/exchangedb/exchange-0001.sql b/src/exchangedb/exchange-0001.sql index 3331eada2..a3996d120 100644 --- a/src/exchangedb/exchange-0001.sql +++ b/src/exchangedb/exchange-0001.sql @@ -835,6 +835,8 @@ CREATE TABLE IF NOT EXISTS wire_fee ,wire_fee_frac INT4 NOT NULL ,closing_fee_val INT8 NOT NULL ,closing_fee_frac INT4 NOT NULL + ,wad_fee_val INT8 NOT NULL + ,wad_fee_frac INT4 NOT NULL ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64) ,PRIMARY KEY (wire_method, start_date) ); @@ -848,6 +850,27 @@ CREATE INDEX IF NOT EXISTS wire_fee_by_end_date_index (end_date); +CREATE TABLE IF NOT EXISTS global_fee + (global_fee_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE + ,start_date INT8 NOT NULL + ,end_date INT8 NOT NULL + ,history_fee_val INT8 NOT NULL + ,history_fee_frac INT4 NOT NULL + ,kyc_fee_val INT8 NOT NULL + ,kyc_fee_frac INT4 NOT NULL + ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64) + ,PRIMARY KEY (start_date) + ); +COMMENT ON TABLE global_fee + IS 'list of the global fees of this exchange, by date'; +COMMENT ON COLUMN global_fee.global_fee_serial + IS 'needed for exchange-auditor replication logic'; + +CREATE INDEX IF NOT EXISTS global_fee_by_end_date_index + ON global_fee + (end_date); + + CREATE TABLE IF NOT EXISTS recoup (recoup_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY -- UNIQUE ,known_coin_id INT8 NOT NULL -- REFERENCES known_coins (known_coin_id) diff --git a/src/exchangedb/irbt_callbacks.c b/src/exchangedb/irbt_callbacks.c index deab3cfca..ae4863436 100644 --- a/src/exchangedb/irbt_callbacks.c +++ b/src/exchangedb/irbt_callbacks.c @@ -635,8 +635,9 @@ irbt_cb_table_wire_fee (struct PostgresClosure *pg, GNUNET_PQ_query_param_string (td->details.wire_fee.wire_method), GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.start_date), GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.end_date), - TALER_PQ_query_param_amount (&td->details.wire_fee.wire_fee), - TALER_PQ_query_param_amount (&td->details.wire_fee.closing_fee), + TALER_PQ_query_param_amount (&td->details.wire_fee.fees.wire), + TALER_PQ_query_param_amount (&td->details.wire_fee.fees.closing), + TALER_PQ_query_param_amount (&td->details.wire_fee.fees.wad), GNUNET_PQ_query_param_auto_from_type (&td->details.wire_fee.master_sig), GNUNET_PQ_query_param_end }; @@ -647,6 +648,32 @@ irbt_cb_table_wire_fee (struct PostgresClosure *pg, } +/** + * Function called with wire_fee records to insert into table. + * + * @param pg plugin context + * @param td record to insert + */ +static enum GNUNET_DB_QueryStatus +irbt_cb_table_global_fee (struct PostgresClosure *pg, + const struct TALER_EXCHANGEDB_TableData *td) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&td->serial), + GNUNET_PQ_query_param_timestamp (&td->details.global_fee.start_date), + GNUNET_PQ_query_param_timestamp (&td->details.global_fee.end_date), + TALER_PQ_query_param_amount (&td->details.global_fee.fees.history), + TALER_PQ_query_param_amount (&td->details.global_fee.fees.kyc), + GNUNET_PQ_query_param_auto_from_type (&td->details.wire_fee.master_sig), + GNUNET_PQ_query_param_end + }; + + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "insert_into_table_global_fee", + params); +} + + /** * Function called with recoup records to insert into table. * diff --git a/src/exchangedb/lrbt_callbacks.c b/src/exchangedb/lrbt_callbacks.c index 7f1d2fdb9..233ecbc1f 100644 --- a/src/exchangedb/lrbt_callbacks.c +++ b/src/exchangedb/lrbt_callbacks.c @@ -1173,9 +1173,11 @@ lrbt_cb_table_wire_fee (void *cls, GNUNET_PQ_result_spec_timestamp ("end_date", &td.details.wire_fee.end_date), TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", - &td.details.wire_fee.wire_fee), + &td.details.wire_fee.fees.wire), TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &td.details.wire_fee.closing_fee), + &td.details.wire_fee.fees.closing), + TALER_PQ_RESULT_SPEC_AMOUNT ("wad_fee", + &td.details.wire_fee.fees.wad), GNUNET_PQ_result_spec_auto_from_type ("master_sig", &td.details.wire_fee.master_sig), GNUNET_PQ_result_spec_end @@ -1197,6 +1199,58 @@ lrbt_cb_table_wire_fee (void *cls, } +/** + * Function called with wire_fee table entries. + * + * @param cls closure + * @param result the postgres result + * @param num_results the number of results in @a result + */ +static void +lrbt_cb_table_global_fee (void *cls, + PGresult *result, + unsigned int num_results) +{ + struct LookupRecordsByTableContext *ctx = cls; + struct PostgresClosure *pg = ctx->pg; + struct TALER_EXCHANGEDB_TableData td = { + .table = TALER_EXCHANGEDB_RT_GLOBAL_FEE + }; + + for (unsigned int i = 0; ierror = true; + return; + } + ctx->cb (ctx->cb_cls, + &td); + GNUNET_PQ_cleanup_result (rs); + } +} + + /** * Function called with recoup table entries. * diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 9a3229f47..cdc383bf2 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -1347,6 +1347,8 @@ prepare_statements (struct PostgresClosure *pg) ",wire_fee_frac" ",closing_fee_val" ",closing_fee_frac" + ",wad_fee_val" + ",wad_fee_frac" ",master_sig" " FROM wire_fee" " WHERE wire_method=$1" @@ -1364,10 +1366,12 @@ prepare_statements (struct PostgresClosure *pg) ",wire_fee_frac" ",closing_fee_val" ",closing_fee_frac" + ",wad_fee_val" + ",wad_fee_frac" ",master_sig" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8);", - 8), + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);", + 10), /* Used in #postgres_store_wire_transfer_out */ GNUNET_PQ_make_prepare ( "insert_wire_out", @@ -1826,6 +1830,8 @@ prepare_statements (struct PostgresClosure *pg) ",wire_fee_frac" ",closing_fee_val" ",closing_fee_frac" + ",wad_fee_val" + ",wad_fee_frac" ",start_date" ",end_date" ",master_sig" @@ -1936,6 +1942,8 @@ prepare_statements (struct PostgresClosure *pg) ",wire_fee_frac" ",closing_fee_val" ",closing_fee_frac" + ",wad_fee_val" + ",wad_fee_frac" " FROM wire_fee" " WHERE wire_method=$1" " AND end_date > $2" @@ -2421,6 +2429,8 @@ prepare_statements (struct PostgresClosure *pg) ",wire_fee_frac" ",closing_fee_val" ",closing_fee_frac" + ",wad_fee_val" + ",wad_fee_frac" ",master_sig" " FROM wire_fee" " WHERE wire_fee_serial > $1" @@ -2711,10 +2721,12 @@ prepare_statements (struct PostgresClosure *pg) ",wire_fee_frac" ",closing_fee_val" ",closing_fee_frac" + ",wad_fee_val" + ",wad_fee_frac" ",master_sig" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9);", - 9), + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);", + 11), GNUNET_PQ_make_prepare ( "insert_into_table_recoup", "INSERT INTO recoup" @@ -7554,8 +7566,7 @@ postgres_insert_aggregation_tracking ( * @param date for which date do we want the fee? * @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] fees how high are the wire fees * @param[out] master_sig signature over the above by the exchange master key * @return status of the transaction */ @@ -7565,8 +7576,7 @@ postgres_get_wire_fee (void *cls, struct GNUNET_TIME_Timestamp date, struct GNUNET_TIME_Timestamp *start_date, struct GNUNET_TIME_Timestamp *end_date, - struct TALER_Amount *wire_fee, - struct TALER_Amount *closing_fee, + struct TALER_WireFeeSet *fees, struct TALER_MasterSignatureP *master_sig) { struct PostgresClosure *pg = cls; @@ -7576,11 +7586,18 @@ postgres_get_wire_fee (void *cls, GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("start_date", start_date), - GNUNET_PQ_result_spec_timestamp ("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_timestamp ("start_date", + start_date), + GNUNET_PQ_result_spec_timestamp ("end_date", + end_date), + TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", + &fees->wire), + TALER_PQ_RESULT_SPEC_AMOUNT ("wad_fee", + &fees->wad), + TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", + &fees->closing), + GNUNET_PQ_result_spec_auto_from_type ("master_sig", + master_sig), GNUNET_PQ_result_spec_end }; @@ -7598,8 +7615,7 @@ postgres_get_wire_fee (void *cls, * @param type type of wire transfer this fee applies for * @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 fees how high are the wire fees * @param master_sig signature over the above by the exchange master key * @return transaction status code */ @@ -7608,8 +7624,7 @@ postgres_insert_wire_fee (void *cls, const char *type, struct GNUNET_TIME_Timestamp start_date, struct GNUNET_TIME_Timestamp end_date, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterSignatureP *master_sig) { struct PostgresClosure *pg = cls; @@ -7617,13 +7632,13 @@ postgres_insert_wire_fee (void *cls, GNUNET_PQ_query_param_string (type), GNUNET_PQ_query_param_timestamp (&start_date), GNUNET_PQ_query_param_timestamp (&end_date), - TALER_PQ_query_param_amount (wire_fee), - TALER_PQ_query_param_amount (closing_fee), + TALER_PQ_query_param_amount (&fees->wire), + TALER_PQ_query_param_amount (&fees->closing), + TALER_PQ_query_param_amount (&fees->wad), GNUNET_PQ_query_param_auto_from_type (master_sig), GNUNET_PQ_query_param_end }; - struct TALER_Amount wf; - struct TALER_Amount cf; + struct TALER_WireFeeSet wx; struct TALER_MasterSignatureP sig; struct GNUNET_TIME_Timestamp sd; struct GNUNET_TIME_Timestamp ed; @@ -7634,8 +7649,7 @@ postgres_insert_wire_fee (void *cls, start_date, &sd, &ed, - &wf, - &cf, + &wx, &sig); if (qs < 0) return qs; @@ -7647,14 +7661,9 @@ postgres_insert_wire_fee (void *cls, GNUNET_break (0); return GNUNET_DB_STATUS_HARD_ERROR; } - if (0 != TALER_amount_cmp (wire_fee, - &wf)) - { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - if (0 != TALER_amount_cmp (closing_fee, - &cf)) + if (0 != + TALER_wire_fee_set_cmp (fees, + &wx)) { GNUNET_break (0); return GNUNET_DB_STATUS_HARD_ERROR; @@ -10230,15 +10239,16 @@ get_wire_fees_cb (void *cls, for (unsigned int i = 0; i < num_results; i++) { struct TALER_MasterSignatureP master_sig; - struct TALER_Amount wire_fee; - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; struct GNUNET_TIME_Timestamp start_date; struct GNUNET_TIME_Timestamp end_date; struct GNUNET_PQ_ResultSpec rs[] = { TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee", - &wire_fee), + &fees.wire), TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee", - &closing_fee), + &fees.closing), + TALER_PQ_RESULT_SPEC_AMOUNT ("wad_fee", + &fees.wad), GNUNET_PQ_result_spec_timestamp ("start_date", &start_date), GNUNET_PQ_result_spec_timestamp ("end_date", @@ -10258,8 +10268,7 @@ get_wire_fees_cb (void *cls, return; } ctx->cb (ctx->cb_cls, - &wire_fee, - &closing_fee, + &fees, start_date, end_date, &master_sig); @@ -10604,16 +10613,10 @@ struct WireFeeLookupContext { /** - * Set to the wire fee. Set to invalid if fees conflict over + * Set to the wire fees. Set to invalid if fees conflict over * the given time period. */ - struct TALER_Amount *wire_fee; - - /** - * Set to the closing fee. Set to invalid if fees conflict over - * the given time period. - */ - struct TALER_Amount *closing_fee; + struct TALER_WireFeeSet *fees; /** * Plugin context. @@ -10640,13 +10643,14 @@ wire_fee_by_time_helper (void *cls, for (unsigned int i = 0; iwire_fee, + memset (wlc->fees, 0, - sizeof (struct TALER_Amount)); - memset (wlc->closing_fee, - 0, - sizeof (struct TALER_Amount)); + sizeof (struct TALER_WireFeeSet)); return; } if (0 == i) { - *wlc->wire_fee = wf; - *wlc->closing_fee = cf; + *wlc->fees = fs; continue; } - if ( (GNUNET_YES != - TALER_amount_cmp_currency (&wf, - wlc->wire_fee)) || - (GNUNET_YES != - TALER_amount_cmp_currency (&cf, - wlc->closing_fee)) || - (0 != - TALER_amount_cmp (&wf, - wlc->wire_fee)) || - (0 != - TALER_amount_cmp (&cf, - wlc->closing_fee)) ) + if (0 != + TALER_wire_fee_set_cmp (&fs, + wlc->fees)) { /* invalidate */ - memset (wlc->wire_fee, + memset (wlc->fees, 0, - sizeof (struct TALER_Amount)); - memset (wlc->closing_fee, - 0, - sizeof (struct TALER_Amount)); + sizeof (struct TALER_WireFeeSet)); return; } } @@ -10700,7 +10688,7 @@ wire_fee_by_time_helper (void *cls, /** * Lookup information about known wire fees. Finds all applicable * fees in the given range. If they are identical, returns the - * respective @a wire_fee and @a closing_fee. If any of the fees + * respective @a fees. If any of the fees * differ between @a start_time and @a end_time, the transaction * succeeds BUT returns an invalid amount for both fees. * @@ -10708,11 +10696,8 @@ wire_fee_by_time_helper (void *cls, * @param wire_method the wire method to lookup fees for * @param start_time starting time of fee * @param end_time end time of fee - * @param[out] wire_fee wire fee for that time period; if - * different wire fee exists within this time - * period, an 'invalid' amount is returned. - * @param[out] closing_fee wire fee for that time period; if - * different wire fee exists within this time + * @param[out] fees wire fees for that time period; if + * different fees exists within this time * period, an 'invalid' amount is returned. * @return transaction status code */ @@ -10722,8 +10707,7 @@ postgres_lookup_wire_fee_by_time ( const char *wire_method, struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Timestamp end_time, - struct TALER_Amount *wire_fee, - struct TALER_Amount *closing_fee) + struct TALER_WireFeeSet *fees) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_QueryParam params[] = { @@ -10733,9 +10717,8 @@ postgres_lookup_wire_fee_by_time ( GNUNET_PQ_query_param_end }; struct WireFeeLookupContext wlc = { - .wire_fee = wire_fee, - .closing_fee = closing_fee, - .pg = pg, + .fees = fees, + .pg = pg }; return GNUNET_PQ_eval_prepared_multi_select (pg->conn, @@ -10834,6 +10817,9 @@ postgres_lookup_serial_by_table (void *cls, case TALER_EXCHANGEDB_RT_WIRE_FEE: statement = "select_serial_by_table_wire_fee"; break; + case TALER_EXCHANGEDB_RT_GLOBAL_FEE: + statement = "select_serial_by_table_global_fee"; + break; case TALER_EXCHANGEDB_RT_RECOUP: statement = "select_serial_by_table_recoup"; break; @@ -11003,6 +10989,10 @@ postgres_lookup_records_by_table (void *cls, statement = "select_above_serial_by_table_wire_fee"; rh = &lrbt_cb_table_wire_fee; break; + case TALER_EXCHANGEDB_RT_GLOBAL_FEE: + statement = "select_above_serial_by_table_global_fee"; + rh = &lrbt_cb_table_global_fee; + break; case TALER_EXCHANGEDB_RT_RECOUP: statement = "select_above_serial_by_table_recoup"; rh = &lrbt_cb_table_recoup; @@ -11138,6 +11128,9 @@ postgres_insert_records_by_table (void *cls, case TALER_EXCHANGEDB_RT_WIRE_FEE: rh = &irbt_cb_table_wire_fee; break; + case TALER_EXCHANGEDB_RT_GLOBAL_FEE: + rh = &irbt_cb_table_global_fee; + break; case TALER_EXCHANGEDB_RT_RECOUP: rh = &irbt_cb_table_recoup; break; diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c index 10390b7fc..012cac645 100644 --- a/src/exchangedb/test_exchangedb.c +++ b/src/exchangedb/test_exchangedb.c @@ -915,23 +915,24 @@ test_wire_fees (void) { struct GNUNET_TIME_Timestamp start_date; struct GNUNET_TIME_Timestamp end_date; - struct TALER_Amount wire_fee; - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; struct TALER_MasterSignatureP master_sig; struct GNUNET_TIME_Timestamp sd; struct GNUNET_TIME_Timestamp ed; - struct TALER_Amount fee; - struct TALER_Amount fee2; + struct TALER_WireFeeSet fees2; struct TALER_MasterSignatureP ms; start_date = GNUNET_TIME_timestamp_get (); end_date = GNUNET_TIME_relative_to_timestamp (GNUNET_TIME_UNIT_MINUTES); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":1.424242", - &wire_fee)); + &fees.wire)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount (CURRENCY ":2.424242", - &closing_fee)); + &fees.closing)); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (CURRENCY ":3.424242", + &fees.wad)); GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &master_sig, sizeof (master_sig)); @@ -940,8 +941,7 @@ test_wire_fees (void) "wire-method", start_date, end_date, - &wire_fee, - &closing_fee, + &fees, &master_sig)) { GNUNET_break (0); @@ -952,8 +952,7 @@ test_wire_fees (void) "wire-method", start_date, end_date, - &wire_fee, - &closing_fee, + &fees, &master_sig)) { GNUNET_break (0); @@ -967,8 +966,7 @@ test_wire_fees (void) end_date, &sd, &ed, - &fee, - &fee2, + &fees2, &ms)) { GNUNET_break (0); @@ -980,8 +978,7 @@ test_wire_fees (void) start_date, &sd, &ed, - &fee, - &fee2, + &fees2, &ms)) { GNUNET_break (0); @@ -993,10 +990,8 @@ test_wire_fees (void) (GNUNET_TIME_timestamp_cmp (ed, !=, end_date)) || - (0 != TALER_amount_cmp (&fee, - &wire_fee)) || - (0 != TALER_amount_cmp (&fee2, - &closing_fee)) || + (0 != TALER_wire_fee_set_cmp (&fees, + &fees2)) || (0 != GNUNET_memcmp (&ms, &master_sig)) ) { diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 1beada699..40f407b66 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -830,6 +830,18 @@ TALER_global_fee_set_ntoh (struct TALER_GlobalFeeSet *fees, const struct TALER_GlobalFeeSetNBOP *nbo); +/** + * Compare global fee sets. + * + * @param f1 first set to compare + * @param f2 second set to compare + * @return 0 if sets are equal + */ +int +TALER_global_fee_set_cmp (const struct TALER_GlobalFeeSet *f1, + const struct TALER_GlobalFeeSet *f2); + + /** * Convert wire fee set from host to network byte order. * @@ -852,6 +864,18 @@ TALER_wire_fee_set_ntoh (struct TALER_WireFeeSet *fees, const struct TALER_WireFeeSetNBOP *nbo); +/** + * Compare wire fee sets. + * + * @param f1 first set to compare + * @param f2 second set to compare + * @return 0 if sets are equal + */ +int +TALER_wire_fee_set_cmp (const struct TALER_WireFeeSet *f1, + const struct TALER_WireFeeSet *f2); + + /** * Hash @a rsa. * @@ -3231,8 +3255,7 @@ TALER_auditor_denom_validity_verify ( * @param payment_method the payment method * @param start_time when do the fees start to apply * @param end_time when do the fees start to apply - * @param wire_fee the wire fee - * @param closing_fee the closing fee + * @param fees the wire fees * @param master_priv private key to sign with * @param[out] master_sig where to write the signature */ @@ -3241,8 +3264,7 @@ TALER_exchange_offline_wire_fee_sign ( const char *payment_method, struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Timestamp end_time, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -3253,8 +3275,7 @@ TALER_exchange_offline_wire_fee_sign ( * @param payment_method the payment method * @param start_time when do the fees start to apply * @param end_time when do the fees start to apply - * @param wire_fee the wire fee - * @param closing_fee the closing fee + * @param fees the wire fees * @param master_pub public key to verify against * @param master_sig the signature the signature * @return #GNUNET_OK if the signature is valid @@ -3264,8 +3285,7 @@ TALER_exchange_offline_wire_fee_verify ( const char *payment_method, struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Timestamp end_time, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 88be1ee32..00115e12a 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -642,13 +642,7 @@ struct TALER_EXCHANGE_WireAggregateFees /** * Fee to be paid whenever the exchange wires funds to the merchant. */ - struct TALER_Amount wire_fee; - - /** - * Fee to be paid when the exchange closes a reserve and wires funds - * back to a customer. - */ - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; /** * Time when this fee goes into effect (inclusive) @@ -3501,8 +3495,7 @@ struct TALER_EXCHANGE_ManagementSetWireFeeHandle; * @param wire_method for which wire method are fees provided * @param validity_start start date for the provided wire fees * @param validity_end end date for the provided wire fees - * @param wire_fee the wire fee for this time period - * @param closing_fee the closing fee for this time period + * @param fees the wire fees for this time period * @param master_sig signature affirming the wire fees; * of purpose #TALER_SIGNATURE_MASTER_WIRE_FEES * @param cb function to call with the exchange's result @@ -3516,8 +3509,7 @@ TALER_EXCHANGE_management_set_wire_fees ( const char *wire_method, struct GNUNET_TIME_Timestamp validity_start, struct GNUNET_TIME_Timestamp validity_end, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterSignatureP *master_sig, TALER_EXCHANGE_ManagementWireEnableCallback cb, void *cb_cls); diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 878cfe2f2..d890cd0ba 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -168,6 +168,7 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_WIRE_OUT, TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING, TALER_EXCHANGEDB_RT_WIRE_FEE, + TALER_EXCHANGEDB_RT_GLOBAL_FEE, TALER_EXCHANGEDB_RT_RECOUP, TALER_EXCHANGEDB_RT_RECOUP_REFRESH, TALER_EXCHANGEDB_RT_EXTENSIONS, @@ -384,11 +385,18 @@ struct TALER_EXCHANGEDB_TableData char *wire_method; struct GNUNET_TIME_Timestamp start_date; struct GNUNET_TIME_Timestamp end_date; - struct TALER_Amount wire_fee; - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; struct TALER_MasterSignatureP master_sig; } wire_fee; + struct + { + struct GNUNET_TIME_Timestamp start_date; + struct GNUNET_TIME_Timestamp end_date; + struct TALER_GlobalFeeSet fees; + struct TALER_MasterSignatureP master_sig; + } global_fee; + struct { uint64_t known_coin_id; @@ -1899,8 +1907,7 @@ typedef void * Provide information about wire fees. * * @param cls closure - * @param wire_fee the wire fee we charge - * @param closing_fee the closing fee we charge + * @param fees the wire fees we charge * @param start_date from when are these fees valid (start date) * @param end_date until when are these fees valid (end date, exclusive) * @param master_sig master key signature affirming that this is the correct @@ -1909,8 +1916,26 @@ typedef void typedef void (*TALER_EXCHANGEDB_WireFeeCallback)( void *cls, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Provide information about global fees. + * + * @param cls closure + * @param fees the global fees we charge + * @param start_date from when are these fees valid (start date) + * @param end_date until when are these fees valid (end date, exclusive) + * @param master_sig master key signature affirming that this is the correct + * fee (of purpose #TALER_SIGNATURE_MASTER_GLOBAL_FEES) + */ +typedef void +(*TALER_EXCHANGEDB_GlobalFeeCallback)( + void *cls, + const struct TALER_GlobalFeeSet *fees, struct GNUNET_TIME_Timestamp start_date, struct GNUNET_TIME_Timestamp end_date, const struct TALER_MasterSignatureP *master_sig); @@ -3256,8 +3281,7 @@ struct TALER_EXCHANGEDB_Plugin * @param wire_method which wire method is the fee about? * @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 fees how high is are the wire fees * @param master_sig signature over the above by the exchange master key * @return transaction status code */ @@ -3266,11 +3290,28 @@ struct TALER_EXCHANGEDB_Plugin const char *wire_method, struct GNUNET_TIME_Timestamp start_date, struct GNUNET_TIME_Timestamp end_date, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterSignatureP *master_sig); + /** + * Insert global fee set into database. + * + * @param cls closure + * @param start_date when does the fee go into effect + * @param end_date when does the fee end being valid + * @param fees how high is are the global fees + * @param master_sig signature over the above by the exchange master key + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_global_fee)(void *cls, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_GlobalFeeSet *fees, + const struct TALER_MasterSignatureP *master_sig); + + /** * Obtain wire fee from database. * @@ -3279,8 +3320,7 @@ struct TALER_EXCHANGEDB_Plugin * @param date for which date do we want the fee? * @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] fees how high are the wire fees * @param[out] master_sig signature over the above by the exchange master key * @return query status of the transaction */ @@ -3290,11 +3330,31 @@ struct TALER_EXCHANGEDB_Plugin struct GNUNET_TIME_Timestamp date, struct GNUNET_TIME_Timestamp *start_date, struct GNUNET_TIME_Timestamp *end_date, - struct TALER_Amount *wire_fee, - struct TALER_Amount *closing_fee, + struct TALER_WireFeeSet *fees, struct TALER_MasterSignatureP *master_sig); + /** + * Obtain global fees from database. + * + * @param cls closure + * @param date for which date do we want the fee? + * @param[out] start_date when does the fee go into effect + * @param[out] end_date when does the fee end being valid + * @param[out] fees how high are the global fees + * @param[out] master_sig signature over the above by the exchange master key + * @return query status of the transaction + */ + enum GNUNET_DB_QueryStatus + (*get_global_fee)(void *cls, + const char *type, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_GlobalFeeSet *fees, + struct TALER_MasterSignatureP *master_sig); + + /** * Obtain information about expired reserves and their * remaining balances. @@ -3874,6 +3934,20 @@ struct TALER_EXCHANGEDB_Plugin void *cb_cls); + /** + * Obtain information about the global fee structure of the exchange. + * + * @param cls closure + * @param cb function to call on each account + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_global_fees)(void *cls, + TALER_EXCHANGEDB_GlobalFeeCallback cb, + void *cb_cls); + + /** * Store information about a revoked online signing key. * @@ -4012,10 +4086,7 @@ struct TALER_EXCHANGEDB_Plugin * @param wire_method the wire method to lookup fees for * @param start_time starting time of fee * @param end_time end time of fee - * @param[out] wire_fee wire fee for that time period; if - * different wire fee exists within this time - * period, an 'invalid' amount is returned. - * @param[out] closing_fee wire fee for that time period; if + * @param[out] fees set to wire fees for that time period; if * different wire fee exists within this time * period, an 'invalid' amount is returned. * @return transaction status code @@ -4026,8 +4097,7 @@ struct TALER_EXCHANGEDB_Plugin const char *wire_method, struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Timestamp end_time, - struct TALER_Amount *wire_fee, - struct TALER_Amount *closing_fee); + struct TALER_WireFeeSet *fees); /** diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index ed985938b..77a234218 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -1244,14 +1244,10 @@ struct TALER_MasterWireFeePS struct GNUNET_TIME_TimestampNBO end_date; /** - * Fee charged to the merchant per wire transfer. + * Fees charged for wire transfers using the + * given wire method. */ - struct TALER_AmountNBO wire_fee; - - /** - * Closing fee charged when we wire back funds of a reserve. - */ - struct TALER_AmountNBO closing_fee; + struct TALER_WireFeeSetNBOP fees; }; diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index 081a93478..5d5cff49d 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -2107,6 +2107,7 @@ TALER_TESTING_cmd_set_wire_fee (const char *label, const char *wire_method, const char *wire_fee, const char *closing_fee, + const char *wad_fee, unsigned int expected_http_status, bool bad_sig); @@ -2180,13 +2181,15 @@ TALER_TESTING_cmd_exec_offline_sign_keys (const char *label, * @param config_filename configuration filename. * @param wire_fee the wire fee to affirm (for the current year) * @param closing_fee the closing fee to affirm (for the current year) + * @param wad_fee the wad fee to affirm * @return the command */ struct TALER_TESTING_Command TALER_TESTING_cmd_exec_offline_sign_fees (const char *label, const char *config_filename, const char *wire_fee, - const char *closing_fee); + const char *closing_fee, + const char *wad_fee); /** diff --git a/src/lib/exchange_api_management_set_wire_fee.c b/src/lib/exchange_api_management_set_wire_fee.c index 807c6723a..cd32a4833 100644 --- a/src/lib/exchange_api_management_set_wire_fee.c +++ b/src/lib/exchange_api_management_set_wire_fee.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020-2021 Taler Systems SA + Copyright (C) 2020-2022 Taler Systems SA 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 @@ -129,8 +129,7 @@ TALER_EXCHANGE_management_set_wire_fees ( const char *wire_method, struct GNUNET_TIME_Timestamp validity_start, struct GNUNET_TIME_Timestamp validity_end, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterSignatureP *master_sig, TALER_EXCHANGE_ManagementWireEnableCallback cb, void *cb_cls) @@ -163,9 +162,11 @@ TALER_EXCHANGE_management_set_wire_fees ( GNUNET_JSON_pack_timestamp ("fee_end", validity_end), TALER_JSON_pack_amount ("closing_fee", - closing_fee), + &fees->closing), + TALER_JSON_pack_amount ("wad_fee", + &fees->wad), TALER_JSON_pack_amount ("wire_fee", - wire_fee)); + &fees->wire)); eh = TALER_EXCHANGE_curl_easy_get_ (swfh->url); GNUNET_assert (NULL != eh); if (GNUNET_OK != diff --git a/src/lib/exchange_api_wire.c b/src/lib/exchange_api_wire.c index 453b576b1..0390623fa 100644 --- a/src/lib/exchange_api_wire.c +++ b/src/lib/exchange_api_wire.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2020 Taler Systems SA + Copyright (C) 2014-2022 Taler Systems SA 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 @@ -144,9 +144,11 @@ parse_fees (json_t *fees) GNUNET_JSON_spec_fixed_auto ("sig", &wa->master_sig), TALER_JSON_spec_amount_any ("wire_fee", - &wa->wire_fee), + &wa->fees.wire), + TALER_JSON_spec_amount_any ("wad_fee", + &wa->fees.wad), TALER_JSON_spec_amount_any ("closing_fee", - &wa->closing_fee), + &wa->fees.closing), GNUNET_JSON_spec_timestamp ("start_date", &wa->start_date), GNUNET_JSON_spec_timestamp ("end_date", @@ -230,8 +232,10 @@ handle_wire_finished (void *cls, struct FeeMap *fm; const struct TALER_EXCHANGE_Keys *key_state; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_json ("accounts", &accounts), - GNUNET_JSON_spec_json ("fees", &fees), + GNUNET_JSON_spec_json ("accounts", + &accounts), + GNUNET_JSON_spec_json ("fees", + &fees), GNUNET_JSON_spec_end () }; @@ -277,8 +281,10 @@ handle_wire_finished (void *cls, struct TALER_EXCHANGE_WireAccount *wa = &was[i]; json_t *account; struct GNUNET_JSON_Specification spec_account[] = { - GNUNET_JSON_spec_string ("payto_uri", &wa->payto_uri), - GNUNET_JSON_spec_fixed_auto ("master_sig", &wa->master_sig), + GNUNET_JSON_spec_string ("payto_uri", + &wa->payto_uri), + GNUNET_JSON_spec_fixed_auto ("master_sig", + &wa->master_sig), GNUNET_JSON_spec_end () }; char *method; diff --git a/src/testing/test_auditor_api.c b/src/testing/test_auditor_api.c index 9ab78664d..e103697e5 100644 --- a/src/testing/test_auditor_api.c +++ b/src/testing/test_auditor_api.c @@ -651,6 +651,7 @@ run (void *cls, TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", config_file, "EUR:0.01", + "EUR:0.01", "EUR:0.01"), TALER_TESTING_cmd_auditor_add ("add-auditor-OK", MHD_HTTP_NO_CONTENT, diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c index 46419193d..f3a9fdd53 100644 --- a/src/testing/test_exchange_api.c +++ b/src/testing/test_exchange_api.c @@ -1169,6 +1169,7 @@ run (void *cls, TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", config_file, "EUR:0.01", + "EUR:0.01", "EUR:0.01"), TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys", 1), diff --git a/src/testing/test_exchange_api_keys_cherry_picking.c b/src/testing/test_exchange_api_keys_cherry_picking.c index 63114c60c..25bdad06d 100644 --- a/src/testing/test_exchange_api_keys_cherry_picking.c +++ b/src/testing/test_exchange_api_keys_cherry_picking.c @@ -69,6 +69,7 @@ run (void *cls, TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", config_file, "EUR:0.01", + "EUR:0.01", "EUR:0.01"), TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys", config_file), diff --git a/src/testing/test_exchange_management_api.c b/src/testing/test_exchange_management_api.c index 71251a57f..9fe5cf595 100644 --- a/src/testing/test_exchange_management_api.c +++ b/src/testing/test_exchange_management_api.c @@ -85,30 +85,35 @@ run (void *cls, "foo-method", "EUR:1", "EUR:5", + "EUR:3", MHD_HTTP_NO_CONTENT, false), TALER_TESTING_cmd_set_wire_fee ("set-fee-conflicting", "foo-method", "EUR:1", "EUR:1", + "EUR:3", MHD_HTTP_CONFLICT, false), TALER_TESTING_cmd_set_wire_fee ("set-fee-bad-signature", "bar-method", "EUR:1", "EUR:1", + "EUR:3", MHD_HTTP_FORBIDDEN, true), TALER_TESTING_cmd_set_wire_fee ("set-fee-other-method", "bar-method", "EUR:1", "EUR:1", + "EUR:3", MHD_HTTP_NO_CONTENT, false), TALER_TESTING_cmd_set_wire_fee ("set-fee-idempotent", "bar-method", "EUR:1", "EUR:1", + "EUR:3", MHD_HTTP_NO_CONTENT, false), TALER_TESTING_cmd_wire_add ("add-wire-account", diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c index 3a8286462..669101d88 100644 --- a/src/testing/test_kyc_api.c +++ b/src/testing/test_kyc_api.c @@ -210,6 +210,7 @@ run (void *cls, TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", CONFIG_FILE, "EUR:0.01", + "EUR:0.01", "EUR:0.01"), TALER_TESTING_cmd_auditor_add ("add-auditor-OK", MHD_HTTP_NO_CONTENT, diff --git a/src/testing/test_taler_exchange_aggregator.c b/src/testing/test_taler_exchange_aggregator.c index bf28375b2..ce0c73404 100644 --- a/src/testing/test_taler_exchange_aggregator.c +++ b/src/testing/test_taler_exchange_aggregator.c @@ -99,6 +99,7 @@ run (void *cls, TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", config_filename, "EUR:0.01", + "EUR:0.01", "EUR:0.01"), // check no aggregation happens on a empty database CMD_EXEC_AGGREGATOR ("run-aggregator-on-empty-db", diff --git a/src/testing/test_taler_exchange_wirewatch.c b/src/testing/test_taler_exchange_wirewatch.c index 30c2cf27f..ad5151e2d 100644 --- a/src/testing/test_taler_exchange_wirewatch.c +++ b/src/testing/test_taler_exchange_wirewatch.c @@ -85,6 +85,7 @@ run (void *cls, TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees", config_filename, "EUR:0.01", + "EUR:0.01", "EUR:0.01"), TALER_TESTING_cmd_auditor_add ("add-auditor-OK", MHD_HTTP_NO_CONTENT, diff --git a/src/testing/testing_api_cmd_offline_sign_fees.c b/src/testing/testing_api_cmd_offline_sign_fees.c index 95f52a00b..8cf9fffe4 100644 --- a/src/testing/testing_api_cmd_offline_sign_fees.c +++ b/src/testing/testing_api_cmd_offline_sign_fees.c @@ -51,6 +51,11 @@ struct OfflineSignState */ const char *wire_fee_s; + /** + * The wad fee to sign. + */ + const char *wad_fee_s; + /** * The closing fee to sign. */ @@ -86,6 +91,7 @@ offlinesign_run (void *cls, "x-taler-bank", ks->wire_fee_s, ks->closing_fee_s, + ks->wad_fee_s, "upload", NULL); if (NULL == ks->offlinesign_proc) @@ -157,13 +163,15 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_exec_offline_sign_fees (const char *label, const char *config_filename, const char *wire_fee, - const char *closing_fee) + const char *closing_fee, + const char *wad_fee) { struct OfflineSignState *ks; ks = GNUNET_new (struct OfflineSignState); ks->config_filename = config_filename; ks->wire_fee_s = wire_fee; + ks->wad_fee_s = wad_fee; ks->closing_fee_s = closing_fee; { struct TALER_TESTING_Command cmd = { diff --git a/src/testing/testing_api_cmd_set_wire_fee.c b/src/testing/testing_api_cmd_set_wire_fee.c index b458d10c1..8eb993878 100644 --- a/src/testing/testing_api_cmd_set_wire_fee.c +++ b/src/testing/testing_api_cmd_set_wire_fee.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020 Taler Systems SA + Copyright (C) 2020, 2022 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -60,6 +60,11 @@ struct WireFeeState */ const char *closing_fee; + /** + * Wad fee amount to use. + */ + const char *wad_fee; + /** * Expected HTTP response code. */ @@ -121,8 +126,7 @@ wire_add_run (void *cls, struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Timestamp start_time; struct GNUNET_TIME_Timestamp end_time; - struct TALER_Amount wire_fee; - struct TALER_Amount closing_fee; + struct TALER_WireFeeSet fees; (void) cmd; ds->is = is; @@ -135,10 +139,13 @@ wire_add_run (void *cls, GNUNET_TIME_UNIT_HOURS)); if ( (GNUNET_OK != TALER_string_to_amount (ds->closing_fee, - &closing_fee)) || + &fees.closing)) || + (GNUNET_OK != + TALER_string_to_amount (ds->wad_fee, + &fees.wad)) || (GNUNET_OK != TALER_string_to_amount (ds->wire_fee, - &wire_fee)) ) + &fees.wire)) ) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); @@ -156,8 +163,7 @@ wire_add_run (void *cls, TALER_exchange_offline_wire_fee_sign (ds->wire_method, start_time, end_time, - &wire_fee, - &closing_fee, + &fees, &is->master_priv, &master_sig); } @@ -167,8 +173,7 @@ wire_add_run (void *cls, ds->wire_method, start_time, end_time, - &wire_fee, - &closing_fee, + &fees, &master_sig, &wire_add_cb, ds); @@ -212,6 +217,7 @@ TALER_TESTING_cmd_set_wire_fee (const char *label, const char *wire_method, const char *wire_fee, const char *closing_fee, + const char *wad_fee, unsigned int expected_http_status, bool bad_sig) { @@ -223,6 +229,7 @@ TALER_TESTING_cmd_set_wire_fee (const char *label, ds->wire_method = wire_method; ds->wire_fee = wire_fee; ds->closing_fee = closing_fee; + ds->wad_fee = wad_fee; { struct TALER_TESTING_Command cmd = { .cls = ds, diff --git a/src/testing/testing_api_cmd_wire.c b/src/testing/testing_api_cmd_wire.c index 66d018c79..4b0a177b5 100644 --- a/src/testing/testing_api_cmd_wire.c +++ b/src/testing/testing_api_cmd_wire.c @@ -119,7 +119,7 @@ wire_cb (void *cls, NULL != waf; waf = waf->next) { - if (0 != TALER_amount_cmp (&waf->wire_fee, + if (0 != TALER_amount_cmp (&waf->fees.wire, &expected_fee)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, diff --git a/src/util/offline_signatures.c b/src/util/offline_signatures.c index 5aef4ac3e..2a358bbf1 100644 --- a/src/util/offline_signatures.c +++ b/src/util/offline_signatures.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2020, 2021 Taler Systems SA + Copyright (C) 2020-2022 Taler Systems SA 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 @@ -415,8 +415,7 @@ TALER_exchange_offline_wire_fee_sign ( const char *payment_method, struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Timestamp end_time, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig) { @@ -430,10 +429,8 @@ TALER_exchange_offline_wire_fee_sign ( GNUNET_CRYPTO_hash (payment_method, strlen (payment_method) + 1, &kv.h_wire_method); - TALER_amount_hton (&kv.wire_fee, - wire_fee); - TALER_amount_hton (&kv.closing_fee, - closing_fee); + TALER_wire_fee_set_hton (&kv.fees, + fees); GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv, &kv, &master_sig->eddsa_signature); @@ -445,8 +442,7 @@ TALER_exchange_offline_wire_fee_verify ( const char *payment_method, struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Timestamp end_time, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig) { @@ -460,10 +456,8 @@ TALER_exchange_offline_wire_fee_verify ( GNUNET_CRYPTO_hash (payment_method, strlen (payment_method) + 1, &wf.h_wire_method); - TALER_amount_hton (&wf.wire_fee, - wire_fee); - TALER_amount_hton (&wf.closing_fee, - closing_fee); + TALER_wire_fee_set_hton (&wf.fees, + fees); return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES, &wf, diff --git a/src/util/util.c b/src/util/util.c index 6dfd65574..33b0a77cc 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -124,6 +124,46 @@ TALER_wire_fee_set_ntoh (struct TALER_WireFeeSet *fees, } +int +TALER_global_fee_set_cmp (const struct TALER_GlobalFeeSet *f1, + const struct TALER_GlobalFeeSet *f2) +{ + int ret; + + ret = TALER_amount_cmp (&f1->history, + &f2->history); + if (0 != ret) + return ret; + ret = TALER_amount_cmp (&f1->kyc, + &f2->kyc); + if (0 != ret) + return ret; + return 0; +} + + +int +TALER_wire_fee_set_cmp (const struct TALER_WireFeeSet *f1, + const struct TALER_WireFeeSet *f2) +{ + int ret; + + ret = TALER_amount_cmp (&f1->wire, + &f2->wire); + if (0 != ret) + return ret; + ret = TALER_amount_cmp (&f1->closing, + &f2->closing); + if (0 != ret) + return ret; + ret = TALER_amount_cmp (&f1->wad, + &f2->wad); + if (0 != ret) + return ret; + return 0; +} + + enum GNUNET_GenericReturnValue TALER_denom_fee_check_currency ( const char *currency,