insert_exchange_wire_fee.c (4942B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2022 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file src/backenddb/insert_exchange_wire_fee.c 18 * @brief Implementation of the insert_exchange_wire_fee function for Postgres 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" 22 #include <taler/taler_pq_lib.h> 23 #include "merchant-database/insert_exchange_wire_fee.h" 24 #include "helper.h" 25 26 27 enum GNUNET_DB_QueryStatus 28 TALER_MERCHANTDB_insert_exchange_wire_fee ( 29 struct TALER_MERCHANTDB_PostgresContext *pg, 30 const struct TALER_MasterPublicKeyP *master_pub, 31 const struct GNUNET_HashCode *h_wire_method, 32 const struct TALER_WireFeeSet *fees, 33 struct GNUNET_TIME_Timestamp start_date, 34 struct GNUNET_TIME_Timestamp end_date, 35 const struct TALER_MasterSignatureP *master_sig) 36 { 37 struct GNUNET_PQ_QueryParam params[] = { 38 GNUNET_PQ_query_param_auto_from_type (master_pub), 39 GNUNET_PQ_query_param_auto_from_type (h_wire_method), 40 TALER_PQ_query_param_amount_with_currency (pg->conn, 41 &fees->wire), 42 TALER_PQ_query_param_amount_with_currency (pg->conn, 43 &fees->closing), 44 GNUNET_PQ_query_param_timestamp (&start_date), 45 GNUNET_PQ_query_param_timestamp (&end_date), 46 GNUNET_PQ_query_param_auto_from_type (master_sig), 47 GNUNET_PQ_query_param_end 48 }; 49 bool inserted; 50 bool identical; 51 struct GNUNET_PQ_ResultSpec rs[] = { 52 GNUNET_PQ_result_spec_bool ("inserted", 53 &inserted), 54 GNUNET_PQ_result_spec_bool ("identical", 55 &identical), 56 GNUNET_PQ_result_spec_end 57 }; 58 enum GNUNET_DB_QueryStatus qs; 59 60 /* no preflight check here, run in its own transaction by the caller */ 61 /* Note: a bare 'ON CONFLICT DO NOTHING' would silently discard a 62 *changed* fee for an existing (master_pub, h_wire_method, 63 start_date), leaving us computing with the stale one. The CTE 64 therefore also reports whether the row that is already there is the 65 one we were asked to store; if it is not, the exchange contradicted 66 a fee it signed earlier and the caller must not proceed. */ 67 PREPARE (pg, 68 "insert_exchange_wire_fee", 69 "WITH ins AS (" 70 " INSERT INTO merchant.merchant_exchange_wire_fees" 71 " (master_pub" 72 " ,h_wire_method" 73 " ,wire_fee" 74 " ,closing_fee" 75 " ,start_date" 76 " ,end_date" 77 " ,master_sig)" 78 " VALUES " 79 " ($1, $2, $3, $4, $5, $6, $7)" 80 " ON CONFLICT (master_pub,h_wire_method,start_date)" 81 " DO NOTHING" 82 " RETURNING 1)" 83 "SELECT" 84 " EXISTS (SELECT 1 FROM ins) AS inserted" 85 ",EXISTS (SELECT 1" 86 " FROM merchant.merchant_exchange_wire_fees" 87 " WHERE master_pub=$1" 88 " AND h_wire_method=$2" 89 " AND start_date=$5" 90 " AND end_date=$6" 91 " AND wire_fee=$3" 92 " AND closing_fee=$4" 93 " AND master_sig=$7) AS identical"); 94 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 95 "Storing wire fee for %s starting at %s of %s\n", 96 TALER_B2S (master_pub), 97 GNUNET_TIME_timestamp2s (start_date), 98 TALER_amount2s (&fees->wire)); 99 qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, 100 "insert_exchange_wire_fee", 101 params, 102 rs); 103 if (qs < 0) 104 return qs; 105 GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); 106 if (inserted) 107 return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; 108 if (identical) 109 return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; 110 /* FIXME: should properly distinguish this error from 111 actual database failures; change signature of function eventually! */ 112 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 113 "Exchange %s signed a different wire fee for the same wire method and start date %s; keeping the fee we already have on file\n", 114 TALER_B2S (master_pub), 115 GNUNET_TIME_timestamp2s (start_date)); 116 GNUNET_break (0); 117 return GNUNET_DB_STATUS_HARD_ERROR; 118 }