/* This file is part of TALER Copyright (C) 2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, see */ /** * @file backenddb/pg_lookup_pickup.c * @brief Implementation of the lookup_pickup function for Postgres * @author Iván Ávalos */ #include "platform.h" #include #include #include #include "pg_lookup_pickup.h" #include "pg_helper.h" /** * Closure for #lookup_signatures_cb(). */ struct LookupSignaturesContext { /** * Length of the @e sigs array */ unsigned int sigs_length; /** * Where to store the signatures. */ struct TALER_BlindedDenominationSignature *sigs; }; /** * Function to be called with the results of a SELECT statement * that has returned @a num_results results about accounts. * * @param[in,out] cls of type `struct LookupSignaturesContext *` * @param result the postgres result * @param num_results the number of results in @a result */ static void lookup_signatures_cb (void *cls, PGresult *result, unsigned int num_results) { struct LookupSignaturesContext *lsc = cls; for (unsigned int i = 0; i < num_results; i++) { uint32_t offset; struct TALER_BlindedDenominationSignature bsig; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_uint32 ("coin_offset", &offset), TALER_PQ_result_spec_blinded_denom_sig ("blind_sig", &bsig), GNUNET_PQ_result_spec_end }; if (GNUNET_OK != GNUNET_PQ_extract_result (result, rs, i)) { GNUNET_break (0); return; } if (offset >= lsc->sigs_length) { GNUNET_break_op (0); GNUNET_PQ_cleanup_result (rs); continue; } /* Must be NULL due to UNIQUE constraint on offset and requirement that client launched us with 'sigs' pre-initialized to NULL. */ lsc->sigs[offset] = bsig; } } enum GNUNET_DB_QueryStatus TMH_PG_lookup_pickup (void *cls, const char *instance_id, const struct TALER_RewardIdentifierP *reward_id, const struct TALER_PickupIdentifierP *pickup_id, char **exchange_url, struct TALER_ReservePrivateKeyP *reserve_priv, unsigned int sigs_length, struct TALER_BlindedDenominationSignature sigs[]) { struct PostgresClosure *pg = cls; uint64_t pickup_serial; { struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_string (instance_id), GNUNET_PQ_query_param_auto_from_type (reward_id), GNUNET_PQ_query_param_auto_from_type (pickup_id), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_string ("exchange_url", exchange_url), GNUNET_PQ_result_spec_auto_from_type ("reserve_priv", reserve_priv), GNUNET_PQ_result_spec_uint64 ("pickup_serial", &pickup_serial), GNUNET_PQ_result_spec_end }; enum GNUNET_DB_QueryStatus qs; check_connection (pg); PREPARE (pg, "lookup_pickup", "SELECT" " exchange_url" ",reserve_priv" ",pickup_serial" " FROM merchant_reward_pickups" " JOIN merchant_rewards USING (reward_serial)" " JOIN merchant_reward_reserves USING (reserve_serial)" " JOIN merchant_reward_reserve_keys USING (reserve_serial)" " WHERE pickup_id = $3" " AND reward_id = $2" " AND merchant_serial =" " (SELECT merchant_serial" " FROM merchant_instances" " WHERE merchant_id=$1)"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "lookup_pickup", params, rs); if (qs <= 0) return qs; } { struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&pickup_serial), GNUNET_PQ_query_param_end }; struct LookupSignaturesContext lsc = { .sigs_length = sigs_length, .sigs = sigs }; PREPARE (pg, "lookup_pickup_signatures", "SELECT" " coin_offset" ",blind_sig" " FROM merchant_reward_pickup_signatures" " WHERE pickup_serial = $1"); return GNUNET_PQ_eval_prepared_multi_select (pg->conn, "lookup_pickup_signatures", params, &lookup_signatures_cb, &lsc); } }