pg_add_policy_fulfillment_proof.c (5462B)
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/pg_add_policy_fulfillment_proof.c 18 * @brief Implementation of the add_policy_fulfillment_proof 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_add_policy_fulfillment_proof.h" 26 #include "pg_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 TEH_PG_add_policy_fulfillment_proof ( 52 void *cls, 53 struct TALER_PolicyFulfillmentTransactionData *fulfillment) 54 { 55 enum GNUNET_DB_QueryStatus qs; 56 struct PostgresClosure *pg = cls; 57 size_t count = fulfillment->details_count; 58 /* FIXME[Oec]: this seems to be prone to VLA attacks */ 59 struct GNUNET_HashCode hcs[GNUNET_NZL (count)]; 60 61 /* Create the sorted policy_hash_codes */ 62 { 63 size_t idx[GNUNET_NZL (count)]; 64 for (size_t i = 0; i < count; i++) 65 idx[i] = i; 66 67 /* Sort the indices according to the hash codes of the corresponding 68 * details. */ 69 qsort_r (idx, 70 count, 71 sizeof(size_t), 72 hash_code_cmp, 73 fulfillment->details); 74 75 /* Finally, concatenate all hash_codes in sorted order */ 76 for (size_t i = 0; i < count; i++) 77 hcs[i] = fulfillment->details[idx[i]].hash_code; 78 } 79 80 81 /* Now, add the proof to the policy_fulfillments table, retrieve the 82 * record_id */ 83 { 84 struct GNUNET_PQ_QueryParam params[] = { 85 GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp), 86 TALER_PQ_query_param_json (fulfillment->proof), 87 GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof), 88 TALER_PQ_query_param_array_hash_code (count, hcs, pg->conn), 89 GNUNET_PQ_query_param_end 90 }; 91 struct GNUNET_PQ_ResultSpec rs[] = { 92 GNUNET_PQ_result_spec_uint64 ("fulfillment_id", 93 &fulfillment->fulfillment_id), 94 GNUNET_PQ_result_spec_end 95 }; 96 97 PREPARE (pg, 98 "insert_proof_into_policy_fulfillments", 99 "INSERT INTO policy_fulfillments" 100 "(fulfillment_timestamp" 101 ",fulfillment_proof" 102 ",h_fulfillment_proof" 103 ",policy_hash_codes" 104 ") VALUES ($1, $2::TEXT::JSON, $3, $4)" 105 " ON CONFLICT DO NOTHING;"); 106 qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, 107 "insert_proof_into_policy_fulfillments", 108 params, 109 rs); 110 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) 111 return qs; 112 } 113 114 /* Now, set the states of each entry corresponding to the hash_codes in 115 * policy_details accordingly */ 116 for (size_t i = 0; i < count; i++) 117 { 118 struct TALER_PolicyDetails *pos = &fulfillment->details[i]; 119 { 120 struct GNUNET_PQ_QueryParam params[] = { 121 GNUNET_PQ_query_param_auto_from_type (&pos->hash_code), 122 GNUNET_PQ_query_param_timestamp (&pos->deadline), 123 TALER_PQ_query_param_amount (pg->conn, 124 &pos->commitment), 125 TALER_PQ_query_param_amount (pg->conn, 126 &pos->accumulated_total), 127 TALER_PQ_query_param_amount (pg->conn, 128 &pos->policy_fee), 129 TALER_PQ_query_param_amount (pg->conn, 130 &pos->transferable_amount), 131 GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state), 132 GNUNET_PQ_query_param_end 133 }; 134 135 PREPARE (pg, 136 "update_policy_details", 137 "UPDATE policy_details SET" 138 " deadline=$2" 139 ",commitment=$3" 140 ",accumulated_total=$4" 141 ",fee=$5" 142 ",transferable=$6" 143 ",fulfillment_state=$7" 144 " WHERE policy_hash_code=$1;"); 145 qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, 146 "update_policy_details", 147 params); 148 if (qs < 0) 149 return qs; 150 } 151 } 152 153 /* 154 * FIXME[oec]-#7999: When all policies of a deposit are fulfilled, 155 * unblock it and trigger a wire-transfer. 156 */ 157 158 return qs; 159 }