get_deposit_confirmations.c (7376B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2022-2023 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 /** 18 * @file get_deposit_confirmations.c 19 * @brief Low-level (statement-level) Postgres database access for the exchange 20 * @author Christian Grothoff 21 */ 22 #include "taler/taler_pq_lib.h" 23 #include "auditor-database/get_deposit_confirmations.h" 24 #include "pg_helper.h" 25 26 27 /** 28 * Closure for #deposit_confirmation_cb(). 29 */ 30 struct DepositConfirmationContext 31 { 32 33 /** 34 * Function to call for each deposit confirmation. 35 */ 36 TALER_AUDITORDB_DepositConfirmationCallback cb; 37 38 /** 39 * Closure for @e cb 40 */ 41 void *cb_cls; 42 43 /** 44 * Plugin context. 45 */ 46 struct TALER_AUDITORDB_PostgresContext *pg; 47 48 /** 49 * Query status to return. 50 */ 51 enum GNUNET_DB_QueryStatus qs; 52 }; 53 54 55 /** 56 * Helper function for #TALER_AUDITORDB_get_deposit_confirmations(). 57 * To be called with the results of a SELECT statement 58 * that has returned @a num_results results. 59 * 60 * @param cls closure of type `struct DepositConfirmationContext *` 61 * @param result the postgres result 62 * @param num_results the number of results in @a result 63 */ 64 static void 65 deposit_confirmation_cb (void *cls, 66 PGresult *result, 67 unsigned int num_results) 68 { 69 struct DepositConfirmationContext *dcc = cls; 70 struct TALER_AUDITORDB_PostgresContext *pg = dcc->pg; 71 72 for (unsigned int i = 0; i < num_results; i++) 73 { 74 struct TALER_AUDITORDB_DepositConfirmation dc = { 0 }; 75 struct TALER_CoinSpendPublicKeyP *coin_pubs = NULL; 76 struct TALER_CoinSpendSignatureP *coin_sigs = NULL; 77 size_t num_pubs = 0; 78 size_t num_sigs = 0; 79 struct GNUNET_PQ_ResultSpec rs[] = { 80 GNUNET_PQ_result_spec_uint64 ("row_id", 81 &dc.row_id), 82 GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms", 83 &dc.h_contract_terms), 84 GNUNET_PQ_result_spec_auto_from_type ("h_policy", 85 &dc.h_policy), 86 GNUNET_PQ_result_spec_auto_from_type ("h_wire", 87 &dc.h_wire), 88 GNUNET_PQ_result_spec_timestamp ("exchange_timestamp", 89 &dc.exchange_timestamp), 90 GNUNET_PQ_result_spec_timestamp ("refund_deadline", 91 &dc.refund_deadline), 92 GNUNET_PQ_result_spec_timestamp ("wire_deadline", 93 &dc.wire_deadline), 94 TALER_PQ_RESULT_SPEC_AMOUNT ("total_without_fee", 95 &dc.total_without_fee), 96 GNUNET_PQ_result_spec_auto_array_from_type (pg->conn, 97 "coin_pubs", 98 &num_pubs, 99 coin_pubs), 100 GNUNET_PQ_result_spec_auto_array_from_type (pg->conn, 101 "coin_sigs", 102 &num_sigs, 103 coin_sigs), 104 GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", 105 &dc.merchant), 106 GNUNET_PQ_result_spec_auto_from_type ("exchange_sig", 107 &dc.exchange_sig), 108 GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", 109 &dc.exchange_pub), 110 GNUNET_PQ_result_spec_auto_from_type ("master_sig", 111 &dc.master_sig), 112 GNUNET_PQ_result_spec_bool ("suppressed", 113 &dc.suppressed), 114 GNUNET_PQ_result_spec_end 115 }; 116 enum GNUNET_GenericReturnValue rval; 117 118 if (GNUNET_OK != 119 GNUNET_PQ_extract_result (result, 120 rs, 121 i)) 122 { 123 GNUNET_break (0); 124 dcc->qs = GNUNET_DB_STATUS_HARD_ERROR; 125 return; 126 } 127 if (num_sigs != num_pubs) 128 { 129 GNUNET_break (0); 130 dcc->qs = GNUNET_DB_STATUS_HARD_ERROR; 131 GNUNET_PQ_cleanup_result (rs); 132 return; 133 } 134 dcc->qs = i + 1; 135 dc.coin_pubs = coin_pubs; 136 dc.coin_sigs = coin_sigs; 137 dc.num_coins = num_sigs; 138 rval = dcc->cb (dcc->cb_cls, 139 &dc); 140 GNUNET_PQ_cleanup_result (rs); 141 if (GNUNET_OK != rval) 142 break; 143 } 144 } 145 146 147 enum GNUNET_DB_QueryStatus 148 TALER_AUDITORDB_get_deposit_confirmations ( 149 struct TALER_AUDITORDB_PostgresContext *pg, 150 int64_t limit, 151 uint64_t offset, 152 bool return_suppressed, 153 TALER_AUDITORDB_DepositConfirmationCallback cb, 154 void *cb_cls) 155 { 156 uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit); 157 struct GNUNET_PQ_QueryParam params[] = { 158 GNUNET_PQ_query_param_uint64 (&offset), 159 GNUNET_PQ_query_param_bool (return_suppressed), 160 GNUNET_PQ_query_param_uint64 (&plimit), 161 GNUNET_PQ_query_param_end 162 }; 163 struct DepositConfirmationContext dcc = { 164 .cb = cb, 165 .cb_cls = cb_cls, 166 .pg = pg 167 }; 168 enum GNUNET_DB_QueryStatus qs; 169 170 PREPARE (pg, 171 "auditor_deposit_confirmation_select_desc", 172 "SELECT" 173 " row_id" 174 ",h_contract_terms" 175 ",h_policy" 176 ",h_wire" 177 ",exchange_timestamp" 178 ",wire_deadline" 179 ",refund_deadline" 180 ",total_without_fee" 181 ",coin_pubs" 182 ",coin_sigs" 183 ",merchant_pub" 184 ",exchange_sig" 185 ",exchange_pub" 186 ",master_sig" 187 ",suppressed" 188 " FROM auditor_deposit_confirmations" 189 " WHERE (row_id < $1)" 190 " AND ($2 OR NOT suppressed)" 191 " ORDER BY row_id DESC" 192 " LIMIT $3" 193 ); 194 PREPARE (pg, 195 "auditor_deposit_confirmation_select_asc", 196 "SELECT" 197 " row_id" 198 ",h_contract_terms" 199 ",h_policy" 200 ",h_wire" 201 ",exchange_timestamp" 202 ",wire_deadline" 203 ",refund_deadline" 204 ",total_without_fee" 205 ",coin_pubs" 206 ",coin_sigs" 207 ",merchant_pub" 208 ",exchange_sig" 209 ",exchange_pub" 210 ",master_sig" 211 ",suppressed" 212 " FROM auditor_deposit_confirmations" 213 " WHERE (row_id > $1)" 214 " AND ($2 OR NOT suppressed)" 215 " ORDER BY row_id ASC" 216 " LIMIT $3" 217 ); 218 qs = GNUNET_PQ_eval_prepared_multi_select ( 219 pg->conn, 220 (limit > 0) 221 ? "auditor_deposit_confirmation_select_asc" 222 : "auditor_deposit_confirmation_select_desc", 223 params, 224 &deposit_confirmation_cb, 225 &dcc); 226 if (qs > 0) 227 return dcc.qs; 228 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs); 229 return qs; 230 }