pg_lookup_wire_transfer.c (6079B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2022-2024 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 exchangedb/pg_lookup_wire_transfer.c 18 * @brief Implementation of the lookup_wire_transfer function for Postgres 19 * @author Christian Grothoff 20 */ 21 #include "taler/platform.h" 22 #include "taler/taler_error_codes.h" 23 #include "taler/taler_dbevents.h" 24 #include "taler/taler_pq_lib.h" 25 #include "pg_lookup_wire_transfer.h" 26 #include "pg_helper.h" 27 28 /** 29 * Closure for #handle_wt_result. 30 */ 31 struct WireTransferResultContext 32 { 33 /** 34 * Function to call on each result. 35 */ 36 TALER_EXCHANGEDB_AggregationDataCallback cb; 37 38 /** 39 * Closure for @e cb. 40 */ 41 void *cb_cls; 42 43 /** 44 * Plugin context. 45 */ 46 struct PostgresClosure *pg; 47 48 /** 49 * Set to #GNUNET_SYSERR on serious errors. 50 */ 51 enum GNUNET_GenericReturnValue status; 52 }; 53 54 55 /** 56 * Function to be called with the results of a SELECT statement 57 * that has returned @a num_results results. Helper function 58 * for #TEH_PG_lookup_wire_transfer(). 59 * 60 * @param cls closure of type `struct WireTransferResultContext *` 61 * @param result the postgres result 62 * @param num_results the number of results in @a result 63 */ 64 static void 65 handle_wt_result (void *cls, 66 PGresult *result, 67 unsigned int num_results) 68 { 69 struct WireTransferResultContext *ctx = cls; 70 struct PostgresClosure *pg = ctx->pg; 71 72 for (unsigned int i = 0; i<num_results; i++) 73 { 74 uint64_t rowid; 75 struct TALER_PrivateContractHashP h_contract_terms; 76 struct TALER_CoinSpendPublicKeyP coin_pub; 77 struct TALER_FullPaytoHashP h_payto; 78 struct TALER_MerchantPublicKeyP merchant_pub; 79 struct GNUNET_TIME_Timestamp exec_time; 80 struct TALER_Amount amount_with_fee; 81 struct TALER_Amount deposit_fee; 82 struct TALER_DenominationPublicKey denom_pub; 83 struct TALER_FullPayto payto_uri; 84 struct GNUNET_PQ_ResultSpec rs[] = { 85 GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", 86 &rowid), 87 GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", 88 &h_contract_terms), 89 GNUNET_PQ_result_spec_string ("payto_uri", 90 &payto_uri.full_payto), 91 GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto", 92 &h_payto), 93 TALER_PQ_result_spec_denom_pub ("denom_pub", 94 &denom_pub), 95 GNUNET_PQ_result_spec_auto_from_type ("coin_pub", 96 &coin_pub), 97 GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", 98 &merchant_pub), 99 GNUNET_PQ_result_spec_timestamp ("execution_date", 100 &exec_time), 101 TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", 102 &amount_with_fee), 103 TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", 104 &deposit_fee), 105 GNUNET_PQ_result_spec_end 106 }; 107 108 if (GNUNET_OK != 109 GNUNET_PQ_extract_result (result, 110 rs, 111 i)) 112 { 113 GNUNET_break (0); 114 ctx->status = GNUNET_SYSERR; 115 return; 116 } 117 ctx->cb (ctx->cb_cls, 118 rowid, 119 &merchant_pub, 120 payto_uri, 121 &h_payto, 122 exec_time, 123 &h_contract_terms, 124 &denom_pub, 125 &coin_pub, 126 &amount_with_fee, 127 &deposit_fee); 128 GNUNET_PQ_cleanup_result (rs); 129 } 130 } 131 132 133 enum GNUNET_DB_QueryStatus 134 TEH_PG_lookup_wire_transfer ( 135 void *cls, 136 const struct TALER_WireTransferIdentifierRawP *wtid, 137 TALER_EXCHANGEDB_AggregationDataCallback cb, 138 void *cb_cls) 139 { 140 struct PostgresClosure *pg = cls; 141 struct GNUNET_PQ_QueryParam params[] = { 142 GNUNET_PQ_query_param_auto_from_type (wtid), 143 GNUNET_PQ_query_param_end 144 }; 145 struct WireTransferResultContext ctx = { 146 .cb = cb, 147 .cb_cls = cb_cls, 148 .pg = pg, 149 .status = GNUNET_OK 150 }; 151 enum GNUNET_DB_QueryStatus qs; 152 153 PREPARE (pg, 154 "lookup_transactions", 155 "SELECT" 156 " aggregation_serial_id" 157 ",bdep.h_contract_terms" 158 ",payto_uri" 159 ",wt.wire_target_h_payto" 160 ",kc.coin_pub" 161 ",bdep.merchant_pub" 162 ",wire_out.execution_date" 163 ",cdep.amount_with_fee" 164 ",denom.fee_deposit" 165 ",denom.denom_pub" 166 " FROM aggregation_tracking" 167 " JOIN batch_deposits bdep" 168 " USING (batch_deposit_serial_id)" 169 " JOIN coin_deposits cdep" 170 " USING (batch_deposit_serial_id)" 171 " JOIN wire_targets wt" 172 " USING (wire_target_h_payto)" 173 " JOIN known_coins kc" 174 " USING (coin_pub)" 175 " JOIN denominations denom" 176 " USING (denominations_serial)" 177 " JOIN wire_out" 178 " USING (wtid_raw)" 179 " WHERE wtid_raw=$1;"); 180 qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, 181 "lookup_transactions", 182 params, 183 &handle_wt_result, 184 &ctx); 185 if (GNUNET_OK != ctx.status) 186 return GNUNET_DB_STATUS_HARD_ERROR; 187 return qs; 188 }