add_policy_fulfillment_proof.c (5533B)
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 exchangedb/add_policy_fulfillment_proof.c 18 * @brief Implementation of the add_policy_fulfillment_proof function for Postgres 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" /* UNNECESSARY? */ 22 #include "taler/taler_error_codes.h" /* UNNECESSARY? */ 23 #include "taler/taler_dbevents.h" /* UNNECESSARY? */ 24 #include "taler/taler_pq_lib.h" 25 #include "exchange-database/add_policy_fulfillment_proof.h" 26 #include "helper.h" 27 28 29 /** 30 * Compares two indices into an array of hash codes according to 31 * GNUNET_CRYPTO_hash_cmp of the content at those index positions. 32 * 33 * Used in a call qsort_t in order to generate sorted policy_hash_codes. 34 */ 35 static int 36 hash_code_cmp ( 37 const void *hc1, 38 const void *hc2, 39 void *arg) 40 { 41 size_t i1 = *(size_t *) hc1; 42 size_t i2 = *(size_t *) hc2; 43 const struct TALER_PolicyDetails *d = arg; 44 45 return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code, 46 &d[i2].hash_code); 47 } 48 49 50 enum GNUNET_DB_QueryStatus 51 TALER_EXCHANGEDB_add_policy_fulfillment_proof ( 52 struct TALER_EXCHANGEDB_PostgresContext *pg, 53 struct TALER_PolicyFulfillmentTransactionData *fulfillment) 54 { 55 enum GNUNET_DB_QueryStatus qs; 56 size_t count = fulfillment->details_count; 57 /* FIXME[Oec]: this seems to be prone to VLA attacks */ 58 struct GNUNET_HashCode hcs[GNUNET_NZL (count)]; 59 60 /* Create the sorted policy_hash_codes */ 61 { 62 size_t idx[GNUNET_NZL (count)]; 63 for (size_t i = 0; i < count; i++) 64 idx[i] = i; 65 66 /* Sort the indices according to the hash codes of the corresponding 67 * details. */ 68 qsort_r (idx, 69 count, 70 sizeof(size_t), 71 hash_code_cmp, 72 fulfillment->details); 73 74 /* Finally, concatenate all hash_codes in sorted order */ 75 for (size_t i = 0; i < count; i++) 76 hcs[i] = fulfillment->details[idx[i]].hash_code; 77 } 78 79 80 /* Now, add the proof to the policy_fulfillments table, retrieve the 81 * record_id */ 82 { 83 struct GNUNET_PQ_QueryParam params[] = { 84 GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp), 85 TALER_PQ_query_param_json (fulfillment->proof), 86 GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof), 87 TALER_PQ_query_param_array_hash_code (count, hcs, pg->conn), 88 GNUNET_PQ_query_param_end 89 }; 90 struct GNUNET_PQ_ResultSpec rs[] = { 91 GNUNET_PQ_result_spec_uint64 ("fulfillment_id", 92 &fulfillment->fulfillment_id), 93 GNUNET_PQ_result_spec_end 94 }; 95 96 PREPARE (pg, 97 "insert_proof_into_policy_fulfillments", 98 "INSERT INTO policy_fulfillments" 99 "(fulfillment_timestamp" 100 ",fulfillment_proof" 101 ",h_fulfillment_proof" 102 ",policy_hash_codes" 103 ") VALUES ($1, $2::TEXT::JSON, $3, $4)" 104 " ON CONFLICT DO NOTHING;"); 105 qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, 106 "insert_proof_into_policy_fulfillments", 107 params, 108 rs); 109 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) 110 return qs; 111 } 112 113 /* Now, set the states of each entry corresponding to the hash_codes in 114 * policy_details accordingly */ 115 for (size_t i = 0; i < count; i++) 116 { 117 struct TALER_PolicyDetails *pos = &fulfillment->details[i]; 118 { 119 struct GNUNET_PQ_QueryParam params[] = { 120 GNUNET_PQ_query_param_auto_from_type (&pos->hash_code), 121 GNUNET_PQ_query_param_timestamp (&pos->deadline), 122 TALER_PQ_query_param_amount (pg->conn, 123 &pos->commitment), 124 TALER_PQ_query_param_amount (pg->conn, 125 &pos->accumulated_total), 126 TALER_PQ_query_param_amount (pg->conn, 127 &pos->policy_fee), 128 TALER_PQ_query_param_amount (pg->conn, 129 &pos->transferable_amount), 130 GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state), 131 GNUNET_PQ_query_param_end 132 }; 133 134 PREPARE (pg, 135 "update_policy_details", 136 "UPDATE policy_details SET" 137 " deadline=$2" 138 ",commitment=$3" 139 ",accumulated_total=$4" 140 ",fee=$5" 141 ",transferable=$6" 142 ",fulfillment_state=$7" 143 " WHERE policy_hash_code=$1;"); 144 qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, 145 "update_policy_details", 146 params); 147 if (qs < 0) 148 return qs; 149 } 150 } 151 152 /* 153 * FIXME[oec]-#7999: When all policies of a deposit are fulfilled, 154 * unblock it and trigger a wire-transfer. 155 */ 156 157 return qs; 158 }