commit 7c45caa6664b4f0a699f639397f79f12399bb655
parent db32aebefcdc19b5f7e045f712bb481ce29a072c
Author: Christian Grothoff <grothoff@gnunet.org>
Date: Sun, 12 Apr 2026 19:10:39 +0200
remove pg_ prefix
Diffstat:
417 files changed, 30703 insertions(+), 30703 deletions(-)
diff --git a/src/auditordb/pg_template.sh b/src/auditordb/template.sh
diff --git a/src/exchangedb/abort_shard.c b/src/exchangedb/abort_shard.c
@@ -0,0 +1,49 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/abort_shard.c
+ * @brief Implementation of the abort_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/abort_shard.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_abort_shard (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *job_name,
+ uint64_t start_row,
+ uint64_t end_row)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_uint64 (&start_row),
+ GNUNET_PQ_query_param_uint64 (&end_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "abort_shard",
+ "UPDATE work_shards"
+ " SET last_attempt=0"
+ " WHERE job_name=$1"
+ " AND start_row=$2"
+ " AND end_row=$3;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "abort_shard",
+ params);
+}
diff --git a/src/exchangedb/activate_signing_key.c b/src/exchangedb/activate_signing_key.c
@@ -0,0 +1,54 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/activate_signing_key.c
+ * @brief Implementation of the activate_signing_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/activate_signing_key.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_activate_signing_key (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ const struct TALER_EXCHANGEDB_SignkeyMetaData *meta,
+ const struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam iparams[] = {
+ GNUNET_PQ_query_param_auto_from_type (exchange_pub),
+ GNUNET_PQ_query_param_timestamp (&meta->start),
+ GNUNET_PQ_query_param_timestamp (&meta->expire_sign),
+ GNUNET_PQ_query_param_timestamp (&meta->expire_legal),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_signkey",
+ "INSERT INTO exchange_sign_keys "
+ "(exchange_pub"
+ ",valid_from"
+ ",expire_sign"
+ ",expire_legal"
+ ",master_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_signkey",
+ iparams);
+}
diff --git a/src/exchangedb/add_denomination_key.c b/src/exchangedb/add_denomination_key.c
@@ -0,0 +1,83 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/add_denomination_key.c
+ * @brief Implementation of the add_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/add_denomination_key.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_add_denomination_key (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
+ const struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam iparams[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+ TALER_PQ_query_param_denom_pub (denom_pub),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_timestamp (&meta->start),
+ GNUNET_PQ_query_param_timestamp (&meta->expire_withdraw),
+ GNUNET_PQ_query_param_timestamp (&meta->expire_deposit),
+ GNUNET_PQ_query_param_timestamp (&meta->expire_legal),
+ TALER_PQ_query_param_amount (pg->conn,
+ &meta->value),
+ TALER_PQ_query_param_amount (pg->conn,
+ &meta->fees.withdraw),
+ TALER_PQ_query_param_amount (pg->conn,
+ &meta->fees.deposit),
+ TALER_PQ_query_param_amount (pg->conn,
+ &meta->fees.refresh),
+ TALER_PQ_query_param_amount (pg->conn,
+ &meta->fees.refund),
+ GNUNET_PQ_query_param_uint32 (&meta->age_mask.bits),
+ GNUNET_PQ_query_param_end
+ };
+
+ /* Sanity check: ensure fees match coin currency */
+ GNUNET_assert (GNUNET_YES ==
+ TALER_denom_fee_check_currency (meta->value.currency,
+ &meta->fees));
+ PREPARE (pg,
+ "denomination_insert",
+ "INSERT INTO denominations "
+ "(denom_pub_hash"
+ ",denom_pub"
+ ",master_sig"
+ ",valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin" /* value of this denom */
+ ",fee_withdraw"
+ ",fee_deposit"
+ ",fee_refresh"
+ ",fee_refund"
+ ",age_mask"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
+ " $11, $12, $13);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "denomination_insert",
+ iparams);
+}
diff --git a/src/exchangedb/add_policy_fulfillment_proof.c b/src/exchangedb/add_policy_fulfillment_proof.c
@@ -0,0 +1,158 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/add_policy_fulfillment_proof.c
+ * @brief Implementation of the add_policy_fulfillment_proof function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h" /* UNNECESSARY? */
+#include "taler/taler_error_codes.h" /* UNNECESSARY? */
+#include "taler/taler_dbevents.h" /* UNNECESSARY? */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/add_policy_fulfillment_proof.h"
+#include "helper.h"
+
+
+/**
+ * Compares two indices into an array of hash codes according to
+ * GNUNET_CRYPTO_hash_cmp of the content at those index positions.
+ *
+ * Used in a call qsort_t in order to generate sorted policy_hash_codes.
+ */
+static int
+hash_code_cmp (
+ const void *hc1,
+ const void *hc2,
+ void *arg)
+{
+ size_t i1 = *(size_t *) hc1;
+ size_t i2 = *(size_t *) hc2;
+ const struct TALER_PolicyDetails *d = arg;
+
+ return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code,
+ &d[i2].hash_code);
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_add_policy_fulfillment_proof (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct TALER_PolicyFulfillmentTransactionData *fulfillment)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ size_t count = fulfillment->details_count;
+ /* FIXME[Oec]: this seems to be prone to VLA attacks */
+ struct GNUNET_HashCode hcs[GNUNET_NZL (count)];
+
+ /* Create the sorted policy_hash_codes */
+ {
+ size_t idx[GNUNET_NZL (count)];
+ for (size_t i = 0; i < count; i++)
+ idx[i] = i;
+
+ /* Sort the indices according to the hash codes of the corresponding
+ * details. */
+ qsort_r (idx,
+ count,
+ sizeof(size_t),
+ hash_code_cmp,
+ fulfillment->details);
+
+ /* Finally, concatenate all hash_codes in sorted order */
+ for (size_t i = 0; i < count; i++)
+ hcs[i] = fulfillment->details[idx[i]].hash_code;
+ }
+
+
+ /* Now, add the proof to the policy_fulfillments table, retrieve the
+ * record_id */
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp),
+ TALER_PQ_query_param_json (fulfillment->proof),
+ GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof),
+ TALER_PQ_query_param_array_hash_code (count, hcs, pg->conn),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
+ &fulfillment->fulfillment_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "insert_proof_into_policy_fulfillments",
+ "INSERT INTO policy_fulfillments"
+ "(fulfillment_timestamp"
+ ",fulfillment_proof"
+ ",h_fulfillment_proof"
+ ",policy_hash_codes"
+ ") VALUES ($1, $2::TEXT::JSON, $3, $4)"
+ " ON CONFLICT DO NOTHING;");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "insert_proof_into_policy_fulfillments",
+ params,
+ rs);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ return qs;
+ }
+
+ /* Now, set the states of each entry corresponding to the hash_codes in
+ * policy_details accordingly */
+ for (size_t i = 0; i < count; i++)
+ {
+ struct TALER_PolicyDetails *pos = &fulfillment->details[i];
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&pos->hash_code),
+ GNUNET_PQ_query_param_timestamp (&pos->deadline),
+ TALER_PQ_query_param_amount (pg->conn,
+ &pos->commitment),
+ TALER_PQ_query_param_amount (pg->conn,
+ &pos->accumulated_total),
+ TALER_PQ_query_param_amount (pg->conn,
+ &pos->policy_fee),
+ TALER_PQ_query_param_amount (pg->conn,
+ &pos->transferable_amount),
+ GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "update_policy_details",
+ "UPDATE policy_details SET"
+ " deadline=$2"
+ ",commitment=$3"
+ ",accumulated_total=$4"
+ ",fee=$5"
+ ",transferable=$6"
+ ",fulfillment_state=$7"
+ " WHERE policy_hash_code=$1;");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "update_policy_details",
+ params);
+ if (qs < 0)
+ return qs;
+ }
+ }
+
+ /*
+ * FIXME[oec]-#7999: When all policies of a deposit are fulfilled,
+ * unblock it and trigger a wire-transfer.
+ */
+
+ return qs;
+}
diff --git a/src/exchangedb/aggregate.c b/src/exchangedb/aggregate.c
@@ -0,0 +1,201 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/aggregate.c
+ * @brief Implementation of the aggregate function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/compute_shard.h"
+#include "taler/exchange-database/aggregate.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_aggregate (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPaytoHashP *h_payto,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ struct TALER_Amount *total)
+{
+ uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (merchant_pub);
+ struct GNUNET_TIME_Absolute now = {0};
+ uint64_t sum_deposit_value;
+ uint64_t sum_deposit_frac;
+ uint64_t sum_refund_value;
+ uint64_t sum_refund_frac;
+ uint64_t sum_fee_value;
+ uint64_t sum_fee_frac;
+ enum GNUNET_DB_QueryStatus qs;
+ struct TALER_Amount sum_deposit;
+ struct TALER_Amount sum_refund;
+ struct TALER_Amount sum_fee;
+ struct TALER_Amount delta;
+
+ now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
+ pg->aggregator_shift);
+ PREPARE (pg,
+ "aggregate",
+ "WITH bdep AS (" /* restrict to our merchant and account and mark as done */
+ " UPDATE batch_deposits"
+ " SET done=TRUE"
+ " WHERE NOT (done OR policy_blocked)" /* only actually executable deposits */
+ " AND refund_deadline<$1"
+ " AND shard=$5" /* only for efficiency, merchant_pub is what we really filter by */
+ " AND merchant_pub=$2" /* filter by target merchant */
+ " AND wire_target_h_payto=$3" /* merchant could have a 2nd bank account */
+ " RETURNING"
+ " batch_deposit_serial_id)"
+ " ,cdep AS ("
+ " SELECT"
+ " coin_deposit_serial_id"
+ " ,batch_deposit_serial_id"
+ " ,coin_pub"
+ " ,amount_with_fee AS amount"
+ " FROM coin_deposits"
+ " WHERE batch_deposit_serial_id IN (SELECT batch_deposit_serial_id FROM bdep))"
+ " ,ref AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */
+ " SELECT"
+ " amount_with_fee AS refund"
+ " ,coin_pub"
+ " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */
+ " FROM refunds"
+ " WHERE coin_pub IN (SELECT coin_pub FROM cdep)"
+ " AND batch_deposit_serial_id IN (SELECT batch_deposit_serial_id FROM bdep))"
+ " ,ref_by_coin AS (" /* total up refunds by coin */
+ " SELECT"
+ " SUM((ref.refund).val) AS sum_refund_val"
+ " ,SUM((ref.refund).frac) AS sum_refund_frac"
+ " ,coin_pub"
+ " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */
+ " FROM ref"
+ " GROUP BY coin_pub, batch_deposit_serial_id)"
+ " ,norm_ref_by_coin AS (" /* normalize */
+ " SELECT"
+ " sum_refund_val + sum_refund_frac / 100000000 AS norm_refund_val"
+ " ,sum_refund_frac % 100000000 AS norm_refund_frac"
+ " ,coin_pub"
+ " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */
+ " FROM ref_by_coin)"
+ " ,fully_refunded_coins AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */
+ " SELECT"
+ " cdep.coin_pub"
+ " FROM norm_ref_by_coin norm"
+ " JOIN cdep"
+ " ON (norm.coin_pub = cdep.coin_pub"
+ " AND norm.batch_deposit_serial_id = cdep.batch_deposit_serial_id"
+ " AND norm.norm_refund_val = (cdep.amount).val"
+ " AND norm.norm_refund_frac = (cdep.amount).frac))"
+ " ,fees AS (" /* find deposit fees for not fully refunded deposits */
+ " SELECT"
+ " denom.fee_deposit AS fee"
+ " ,cs.batch_deposit_serial_id" /* ensures we get the fee for each coin, not once per denomination */
+ " FROM cdep cs"
+ " JOIN known_coins kc" /* NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */
+ " USING (coin_pub)"
+ " JOIN denominations denom"
+ " USING (denominations_serial)"
+ " WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins))"
+ " ,dummy AS (" /* add deposits to aggregation_tracking */
+ " INSERT INTO aggregation_tracking"
+ " (batch_deposit_serial_id"
+ " ,wtid_raw)"
+ " SELECT batch_deposit_serial_id,$4"
+ " FROM bdep)"
+ "SELECT" /* calculate totals (deposits, refunds and fees) */
+ " CAST(COALESCE(SUM((cdep.amount).val),0) AS INT8) AS sum_deposit_value"
+ /* cast needed, otherwise we get NUMBER */
+ " ,COALESCE(SUM((cdep.amount).frac),0) AS sum_deposit_fraction" /* SUM over INT returns INT8 */
+ " ,CAST(COALESCE(SUM((ref.refund).val),0) AS INT8) AS sum_refund_value"
+ " ,COALESCE(SUM((ref.refund).frac),0) AS sum_refund_fraction"
+ " ,CAST(COALESCE(SUM((fees.fee).val),0) AS INT8) AS sum_fee_value"
+ " ,COALESCE(SUM((fees.fee).frac),0) AS sum_fee_fraction"
+ " FROM cdep "
+ " FULL OUTER JOIN ref ON (FALSE)" /* We just want all sums */
+ " FULL OUTER JOIN fees ON (FALSE);");
+
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_uint64 (&deposit_shard),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("sum_deposit_value",
+ &sum_deposit_value),
+ GNUNET_PQ_result_spec_uint64 ("sum_deposit_fraction",
+ &sum_deposit_frac),
+ GNUNET_PQ_result_spec_uint64 ("sum_refund_value",
+ &sum_refund_value),
+ GNUNET_PQ_result_spec_uint64 ("sum_refund_fraction",
+ &sum_refund_frac),
+ GNUNET_PQ_result_spec_uint64 ("sum_fee_value",
+ &sum_fee_value),
+ GNUNET_PQ_result_spec_uint64 ("sum_fee_fraction",
+ &sum_fee_frac),
+ GNUNET_PQ_result_spec_end
+ };
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "aggregate",
+ params,
+ rs);
+ }
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return qs;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pg->currency,
+ total));
+ return qs;
+ }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pg->currency,
+ &sum_deposit));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pg->currency,
+ &sum_refund));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pg->currency,
+ &sum_fee));
+ sum_deposit.value = sum_deposit_frac / TALER_AMOUNT_FRAC_BASE
+ + sum_deposit_value;
+ sum_deposit.fraction = sum_deposit_frac % TALER_AMOUNT_FRAC_BASE;
+ sum_refund.value = sum_refund_frac / TALER_AMOUNT_FRAC_BASE
+ + sum_refund_value;
+ sum_refund.fraction = sum_refund_frac % TALER_AMOUNT_FRAC_BASE;
+ sum_fee.value = sum_fee_frac / TALER_AMOUNT_FRAC_BASE
+ + sum_fee_value;
+ sum_fee.fraction = sum_fee_frac % TALER_AMOUNT_FRAC_BASE; \
+ GNUNET_assert (0 <=
+ TALER_amount_subtract (&delta,
+ &sum_deposit,
+ &sum_refund));
+ GNUNET_assert (0 <=
+ TALER_amount_subtract (total,
+ &delta,
+ &sum_fee));
+ return qs;
+}
diff --git a/src/exchangedb/batch_ensure_coin_known.c b/src/exchangedb/batch_ensure_coin_known.c
@@ -0,0 +1,457 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/batch_ensure_coin_known.c
+ * @brief Implementation of the batch_ensure_coin_known function for Postgres
+ * @author Christian Grothoff
+ *
+ * FIXME-#9373: use the array support for postgres to simplify this code!
+ *
+ */
+#include "taler/taler_exchangedb_lib.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/batch_ensure_coin_known.h"
+#include "helper.h"
+
+
+static enum GNUNET_DB_QueryStatus
+insert1 (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinPublicInfo coin[1],
+ struct TALER_EXCHANGEDB_CoinInfo result[1])
+{
+ enum GNUNET_DB_QueryStatus qs;
+ bool is_denom_pub_hash_null = false;
+ bool is_age_hash_null = false;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash),
+ GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment),
+ TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("existed",
+ &result[0].existed),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+ &result[0].known_coin_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &result[0].denom_hash),
+ &is_denom_pub_hash_null),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &result[0].h_age_commitment),
+ &is_age_hash_null),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "batch1_known_coin",
+ "SELECT"
+ " existed1 AS existed"
+ ",known_coin_id1 AS known_coin_id"
+ ",denom_pub_hash1 AS denom_hash"
+ ",age_commitment_hash1 AS h_age_commitment"
+ " FROM exchange_do_batch1_known_coin"
+ " ($1, $2, $3, $4);"
+ );
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "batch1_known_coin",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ return qs;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break (0); /* should be impossible */
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break; /* continued below */
+ }
+
+ if ( (! is_denom_pub_hash_null) &&
+ (0 != GNUNET_memcmp (&result[0].denom_hash,
+ &coin->denom_pub_hash)) )
+ {
+ GNUNET_break_op (0);
+ result[0].denom_conflict = true;
+ }
+
+ if ( (! is_denom_pub_hash_null) &&
+ (0 != GNUNET_memcmp (&result[0].denom_hash,
+ &coin[0].denom_pub_hash)) )
+ {
+ GNUNET_break_op (0);
+ result[0].denom_conflict = true;
+ }
+
+ result[0].age_conflict = TALER_AgeCommitmentHashP_NoConflict;
+
+ if (is_age_hash_null != coin[0].no_age_commitment)
+ {
+ if (is_age_hash_null)
+ {
+ GNUNET_break_op (0);
+ result[0].age_conflict = TALER_AgeCommitmentHashP_NullExpected;
+ }
+ else
+ {
+ GNUNET_break_op (0);
+ result[0].age_conflict = TALER_AgeCommitmentHashP_ValueExpected;
+ }
+ }
+ else if ( (! is_age_hash_null) &&
+ (0 != GNUNET_memcmp (&result[0].h_age_commitment,
+ &coin[0].h_age_commitment)) )
+ {
+ GNUNET_break_op (0);
+ result[0].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers;
+ }
+
+ return qs;
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert2 (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinPublicInfo coin[2],
+ struct TALER_EXCHANGEDB_CoinInfo result[2])
+{
+ enum GNUNET_DB_QueryStatus qs;
+ bool is_denom_pub_hash_null[2] = {false, false};
+ bool is_age_hash_null[2] = {false, false};
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash),
+ GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment),
+ TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
+
+ GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash),
+ GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment),
+ TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("existed",
+ &result[0].existed),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+ &result[0].known_coin_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &result[0].denom_hash),
+ &is_denom_pub_hash_null[0]),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &result[0].h_age_commitment),
+ &is_age_hash_null[0]),
+ GNUNET_PQ_result_spec_bool ("existed2",
+ &result[1].existed),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id2",
+ &result[1].known_coin_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2",
+ &result[1].denom_hash),
+ &is_denom_pub_hash_null[1]),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2",
+ &result[1].h_age_commitment),
+ &is_age_hash_null[1]),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "batch2_known_coin",
+ "SELECT"
+ " existed1 AS existed"
+ ",known_coin_id1 AS known_coin_id"
+ ",denom_pub_hash1 AS denom_hash"
+ ",age_commitment_hash1 AS h_age_commitment"
+ ",existed2 AS existed2"
+ ",known_coin_id2 AS known_coin_id2"
+ ",denom_pub_hash2 AS denom_hash2"
+ ",age_commitment_hash2 AS h_age_commitment2"
+ " FROM exchange_do_batch2_known_coin"
+ " ($1, $2, $3, $4, $5, $6, $7, $8);"
+ );
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "batch2_known_coin",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ return qs;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break (0); /* should be impossible */
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break; /* continued below */
+ }
+
+ for (int i = 0; i < 2; i++)
+ {
+ if ( (! is_denom_pub_hash_null[i]) &&
+ (0 != GNUNET_memcmp (&result[i].denom_hash,
+ &coin[i].denom_pub_hash)) )
+ {
+ GNUNET_break_op (0);
+ result[i].denom_conflict = true;
+ }
+
+ result[i].age_conflict = TALER_AgeCommitmentHashP_NoConflict;
+
+ if (is_age_hash_null[i] != coin[i].no_age_commitment)
+ {
+ if (is_age_hash_null[i])
+ {
+ GNUNET_break_op (0);
+ result[i].age_conflict = TALER_AgeCommitmentHashP_NullExpected;
+ }
+ else
+ {
+ GNUNET_break_op (0);
+ result[i].age_conflict = TALER_AgeCommitmentHashP_ValueExpected;
+ }
+ }
+ else if ( (! is_age_hash_null[i]) &&
+ (0 != GNUNET_memcmp (&result[i].h_age_commitment,
+ &coin[i].h_age_commitment)) )
+ {
+ GNUNET_break_op (0);
+ result[i].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers;
+ }
+ }
+
+ return qs;
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert4 (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinPublicInfo coin[4],
+ struct TALER_EXCHANGEDB_CoinInfo result[4])
+{
+ enum GNUNET_DB_QueryStatus qs;
+ bool is_denom_pub_hash_null[4] = {false, false, false, false};
+ bool is_age_hash_null[4] = {false, false, false, false};
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash),
+ GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment),
+ TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
+
+ GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash),
+ GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment),
+ TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
+
+ GNUNET_PQ_query_param_auto_from_type (&coin[2].coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&coin[2].denom_pub_hash),
+ GNUNET_PQ_query_param_auto_from_type (&coin[2].h_age_commitment),
+ TALER_PQ_query_param_denom_sig (&coin[2].denom_sig),
+
+ GNUNET_PQ_query_param_auto_from_type (&coin[3].coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&coin[3].denom_pub_hash),
+ GNUNET_PQ_query_param_auto_from_type (&coin[3].h_age_commitment),
+ TALER_PQ_query_param_denom_sig (&coin[3].denom_sig),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("existed",
+ &result[0].existed),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+ &result[0].known_coin_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &result[0].denom_hash),
+ &is_denom_pub_hash_null[0]),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &result[0].h_age_commitment),
+ &is_age_hash_null[0]),
+ GNUNET_PQ_result_spec_bool ("existed2",
+ &result[1].existed),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id2",
+ &result[1].known_coin_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2",
+ &result[1].denom_hash),
+ &is_denom_pub_hash_null[1]),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2",
+ &result[1].h_age_commitment),
+ &is_age_hash_null[1]),
+ GNUNET_PQ_result_spec_bool ("existed3",
+ &result[2].existed),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id3",
+ &result[2].known_coin_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash3",
+ &result[2].denom_hash),
+ &is_denom_pub_hash_null[2]),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash3",
+ &result[2].h_age_commitment),
+ &is_age_hash_null[2]),
+ GNUNET_PQ_result_spec_bool ("existed4",
+ &result[3].existed),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id4",
+ &result[3].known_coin_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash4",
+ &result[3].denom_hash),
+ &is_denom_pub_hash_null[3]),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash4",
+ &result[3].h_age_commitment),
+ &is_age_hash_null[3]),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "batch4_known_coin",
+ "SELECT"
+ " existed1 AS existed"
+ ",known_coin_id1 AS known_coin_id"
+ ",denom_pub_hash1 AS denom_hash"
+ ",age_commitment_hash1 AS h_age_commitment"
+ ",existed2 AS existed2"
+ ",known_coin_id2 AS known_coin_id2"
+ ",denom_pub_hash2 AS denom_hash2"
+ ",age_commitment_hash2 AS h_age_commitment2"
+ ",existed3 AS existed3"
+ ",known_coin_id3 AS known_coin_id3"
+ ",denom_pub_hash3 AS denom_hash3"
+ ",age_commitment_hash3 AS h_age_commitment3"
+ ",existed4 AS existed4"
+ ",known_coin_id4 AS known_coin_id4"
+ ",denom_pub_hash4 AS denom_hash4"
+ ",age_commitment_hash4 AS h_age_commitment4"
+ " FROM exchange_do_batch2_known_coin"
+ " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);"
+ );
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "batch4_known_coin",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ return qs;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break (0); /* should be impossible */
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break; /* continued below */
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ if ( (! is_denom_pub_hash_null[i]) &&
+ (0 != GNUNET_memcmp (&result[i].denom_hash,
+ &coin[i].denom_pub_hash)) )
+ {
+ GNUNET_break_op (0);
+ result[i].denom_conflict = true;
+ }
+
+ result[i].age_conflict = TALER_AgeCommitmentHashP_NoConflict;
+
+ if (is_age_hash_null[i] != coin[i].no_age_commitment)
+ {
+ if (is_age_hash_null[i])
+ {
+ GNUNET_break_op (0);
+ result[i].age_conflict = TALER_AgeCommitmentHashP_NullExpected;
+ }
+ else
+ {
+ GNUNET_break_op (0);
+ result[i].age_conflict = TALER_AgeCommitmentHashP_ValueExpected;
+ }
+ }
+ else if ( (! is_age_hash_null[i]) &&
+ (0 != GNUNET_memcmp (&result[i].h_age_commitment,
+ &coin[i].h_age_commitment)) )
+ {
+ GNUNET_break_op (0);
+ result[i].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers;
+ }
+ }
+
+ return qs;
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_batch_ensure_coin_known (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinPublicInfo *coin,
+ struct TALER_EXCHANGEDB_CoinInfo *result,
+ unsigned int coin_length,
+ unsigned int batch_size)
+{
+ enum GNUNET_DB_QueryStatus qs = 0;
+ unsigned int i = 0;
+
+ while ( (qs >= 0) &&
+ (i < coin_length) )
+ {
+ unsigned int bs = GNUNET_MIN (batch_size,
+ coin_length - i);
+ if (bs >= 4)
+ {
+ qs = insert4 (pg,
+ &coin[i],
+ &result[i]);
+ i += 4;
+ continue;
+ }
+ switch (bs)
+ {
+ case 3:
+ case 2:
+ qs = insert2 (pg,
+ &coin[i],
+ &result[i]);
+ i += 2;
+ break;
+ case 1:
+ qs = insert1 (pg,
+ &coin[i],
+ &result[i]);
+ i += 1;
+ break;
+ case 0:
+ GNUNET_assert (0);
+ break;
+ }
+ } /* end while */
+ if (qs < 0)
+ return qs;
+ return i;
+}
diff --git a/src/exchangedb/begin_revolving_shard.c b/src/exchangedb/begin_revolving_shard.c
@@ -0,0 +1,258 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/begin_revolving_shard.c
+ * @brief Implementation of the begin_revolving_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/begin_revolving_shard.h"
+#include "taler/exchange-database/commit.h"
+#include "helper.h"
+#include "taler/exchange-database/start.h"
+#include "taler/exchange-database/rollback.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_begin_revolving_shard (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *job_name,
+ uint32_t shard_size,
+ uint32_t shard_limit,
+ uint32_t *start_row,
+ uint32_t *end_row)
+{
+
+ GNUNET_assert (shard_limit <= 1U + (uint32_t) INT_MAX);
+ GNUNET_assert (shard_limit > 0);
+ GNUNET_assert (shard_size > 0);
+ for (unsigned int retries = 0; retries<3; retries++)
+ {
+ if (GNUNET_OK !=
+ TALER_EXCHANGEDB_start (pg,
+ "begin_revolving_shard"))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+
+ /* First, find last 'end_row' */
+ {
+ enum GNUNET_DB_QueryStatus qs;
+ uint32_t last_end;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint32 ("end_row",
+ &last_end),
+ GNUNET_PQ_result_spec_end
+ };
+ /* Used in #postgres_begin_revolving_shard() */
+ PREPARE (pg,
+ "get_last_revolving_shard",
+ "SELECT"
+ " end_row"
+ " FROM revolving_work_shards"
+ " WHERE job_name=$1"
+ " ORDER BY end_row DESC"
+ " LIMIT 1;");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_last_revolving_shard",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ *start_row = 1U + last_end;
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ *start_row = 0; /* base-case: no shards yet */
+ break; /* continued below */
+ }
+ } /* get_last_shard */
+
+ if (*start_row < shard_limit)
+ {
+ /* Claim fresh shard */
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_TIME_Absolute now;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_uint32 (start_row),
+ GNUNET_PQ_query_param_uint32 (end_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ *end_row = GNUNET_MIN (shard_limit,
+ *start_row + shard_size - 1);
+ now = GNUNET_TIME_absolute_get ();
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Trying to claim shard %llu-%llu\n",
+ (unsigned long long) *start_row,
+ (unsigned long long) *end_row);
+
+ /* Used in #postgres_claim_revolving_shard() */
+ PREPARE (pg,
+ "create_revolving_shard",
+ "INSERT INTO revolving_work_shards"
+ "(job_name"
+ ",last_attempt"
+ ",start_row"
+ ",end_row"
+ ",active"
+ ") VALUES "
+ "($1, $2, $3, $4, TRUE);");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "create_revolving_shard",
+ params);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* continued below (with commit) */
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* someone else got this shard already,
+ try again */
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ }
+ } /* end create fresh reovlving shard */
+ else
+ {
+ /* claim oldest existing shard */
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint32 ("start_row",
+ start_row),
+ GNUNET_PQ_result_spec_uint32 ("end_row",
+ end_row),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_open_revolving_shard",
+ "SELECT"
+ " start_row"
+ ",end_row"
+ " FROM revolving_work_shards"
+ " WHERE job_name=$1"
+ " AND active=FALSE"
+ " ORDER BY last_attempt ASC"
+ " LIMIT 1;");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_open_revolving_shard",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* no open shards available */
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ {
+ enum GNUNET_DB_QueryStatus qsz;
+ struct GNUNET_TIME_Timestamp now;
+ struct GNUNET_PQ_QueryParam iparams[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_uint32 (start_row),
+ GNUNET_PQ_query_param_uint32 (end_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ now = GNUNET_TIME_timestamp_get ();
+ PREPARE (pg,
+ "reclaim_revolving_shard",
+ "UPDATE revolving_work_shards"
+ " SET last_attempt=$2"
+ " ,active=TRUE"
+ " WHERE job_name=$1"
+ " AND start_row=$3"
+ " AND end_row=$4");
+ qsz = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "reclaim_revolving_shard",
+ iparams);
+ switch (qsz)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break; /* continue with commit */
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break (0); /* logic error, should be impossible */
+ TALER_EXCHANGEDB_rollback (pg);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ }
+ break; /* continue with commit */
+ }
+ } /* end claim oldest existing shard */
+
+ /* commit */
+ {
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = TALER_EXCHANGEDB_commit (pg);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ }
+ } /* retry 'for' loop */
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+}
diff --git a/src/exchangedb/begin_shard.c b/src/exchangedb/begin_shard.c
@@ -0,0 +1,262 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/begin_shard.c
+ * @brief Implementation of the begin_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/begin_shard.h"
+#include "helper.h"
+#include "taler/exchange-database/start.h"
+#include "taler/exchange-database/rollback.h"
+#include "taler/exchange-database/commit.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_begin_shard (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *job_name,
+ struct GNUNET_TIME_Relative delay,
+ uint64_t shard_size,
+ uint64_t *start_row,
+ uint64_t *end_row)
+{
+
+ for (unsigned int retries = 0; retries<10; retries++)
+ {
+ if (GNUNET_OK !=
+ TALER_EXCHANGEDB_start (pg,
+ "begin_shard"))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+
+ {
+ struct GNUNET_TIME_Absolute past;
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_absolute_time (&past),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("start_row",
+ start_row),
+ GNUNET_PQ_result_spec_uint64 ("end_row",
+ end_row),
+ GNUNET_PQ_result_spec_end
+ };
+
+ past = GNUNET_TIME_absolute_get ();
+ PREPARE (pg,
+ "get_open_shard",
+ "SELECT"
+ " start_row"
+ ",end_row"
+ " FROM work_shards"
+ " WHERE job_name=$1"
+ " AND completed=FALSE"
+ " AND last_attempt<$2"
+ " ORDER BY last_attempt ASC"
+ " LIMIT 1;");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_open_shard",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on getting open shard\n");
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ {
+ enum GNUNET_DB_QueryStatus qsz;
+ struct GNUNET_TIME_Absolute now;
+ struct GNUNET_PQ_QueryParam iparams[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_uint64 (start_row),
+ GNUNET_PQ_query_param_uint64 (end_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ now = GNUNET_TIME_relative_to_absolute (delay);
+ PREPARE (pg,
+ "reclaim_shard",
+ "UPDATE work_shards"
+ " SET last_attempt=$2"
+ " WHERE job_name=$1"
+ " AND start_row=$3"
+ " AND end_row=$4");
+ qsz = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "reclaim_shard",
+ iparams);
+ switch (qsz)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qsz;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on claiming open shard\n");
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ goto commit;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break (0); /* logic error, should be impossible */
+ TALER_EXCHANGEDB_rollback (pg);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ }
+ break; /* actually unreachable */
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ break; /* continued below */
+ }
+ } /* get_open_shard */
+
+ /* No open shard, find last 'end_row' */
+ {
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("end_row",
+ start_row),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_last_shard",
+ "SELECT"
+ " end_row"
+ " FROM work_shards"
+ " WHERE job_name=$1"
+ " ORDER BY end_row DESC"
+ " LIMIT 1;");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_last_shard",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on getting last shard\n");
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ *start_row = 0; /* base-case: no shards yet */
+ break; /* continued below */
+ }
+ *end_row = *start_row + shard_size;
+ } /* get_last_shard */
+
+ /* Claim fresh shard */
+ {
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_TIME_Absolute now;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_uint64 (start_row),
+ GNUNET_PQ_query_param_uint64 (end_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ now = GNUNET_TIME_relative_to_absolute (delay);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Trying to claim shard (%llu-%llu]\n",
+ (unsigned long long) *start_row,
+ (unsigned long long) *end_row);
+
+ PREPARE (pg,
+ "claim_next_shard",
+ "INSERT INTO work_shards"
+ "(job_name"
+ ",last_attempt"
+ ",start_row"
+ ",end_row"
+ ") VALUES "
+ "($1, $2, $3, $4);");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "claim_next_shard",
+ params);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on claiming next shard\n");
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ /* continued below */
+ break;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* someone else got this shard already,
+ try again */
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ }
+ } /* claim_next_shard */
+
+ /* commit */
+commit:
+ {
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = TALER_EXCHANGEDB_commit (pg);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on commit for beginning shard\n");
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Claimed new shard\n");
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ }
+ } /* retry 'for' loop */
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+}
diff --git a/src/exchangedb/clear_aml_lock.c b/src/exchangedb/clear_aml_lock.c
@@ -0,0 +1,45 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/clear_aml_lock.c
+ * @brief Implementation of the clear_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/clear_aml_lock.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_clear_aml_lock (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "clear_aml_lock",
+ "UPDATE kyc_targets"
+ " SET aml_program_lock_timeout=NULL"
+ " WHERE h_normalized_payto=$1");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "clear_aml_lock",
+ params);
+}
diff --git a/src/exchangedb/commit.c b/src/exchangedb/commit.c
@@ -0,0 +1,52 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/commit.c
+ * @brief Implementation of the commit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/commit.h"
+#include "helper.h"
+
+
+/**
+ * Commit the current transaction of a database connection.
+ *
+ * @param pg the database context
+ * @return final transaction status
+ */
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_commit (struct TALER_EXCHANGEDB_PostgresContext *pg)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_break (NULL != pg->transaction_name);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Committing transaction `%s'\n",
+ pg->transaction_name);
+ PREPARE (pg,
+ "do_commit",
+ "COMMIT");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "do_commit",
+ params);
+ pg->transaction_name = NULL;
+ return qs;
+}
diff --git a/src/exchangedb/complete_shard.c b/src/exchangedb/complete_shard.c
@@ -0,0 +1,52 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/complete_shard.c
+ * @brief Implementation of the complete_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/complete_shard.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_complete_shard (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *job_name,
+ uint64_t start_row,
+ uint64_t end_row)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_uint64 (&start_row),
+ GNUNET_PQ_query_param_uint64 (&end_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Completing shard %llu-%llu\n",
+ (unsigned long long) start_row,
+ (unsigned long long) end_row);
+ PREPARE (pg,
+ "complete_shard",
+ "UPDATE work_shards"
+ " SET completed=TRUE"
+ " WHERE job_name=$1"
+ " AND start_row=$2"
+ " AND end_row=$3");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "complete_shard",
+ params);
+}
diff --git a/src/exchangedb/compute_shard.c b/src/exchangedb/compute_shard.c
@@ -0,0 +1,46 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/compute_shard.c
+ * @brief Implementation of the compute_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/exchange-database/compute_shard.h"
+#include "helper.h"
+
+
+uint64_t
+TALER_EXCHANGEDB_compute_shard (const struct TALER_MerchantPublicKeyP *
+ merchant_pub)
+{
+ uint32_t res;
+
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CRYPTO_hkdf_gnunet (
+ &res,
+ sizeof (res),
+ merchant_pub,
+ sizeof (*merchant_pub),
+ "VOID",
+ 4));
+ /* interpret hash result as NBO for platform independence,
+ convert to HBO and map to [0..2^31-1] range */
+ res = ntohl (res);
+ if (res > INT32_MAX)
+ res += INT32_MIN;
+ GNUNET_assert (res <= INT32_MAX);
+ return (uint64_t) res;
+}
diff --git a/src/exchangedb/count_known_coins.c b/src/exchangedb/count_known_coins.c
@@ -0,0 +1,59 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/count_known_coins.c
+ * @brief Implementation of the count_known_coins function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/count_known_coins.h"
+#include "helper.h"
+
+long long
+TALER_EXCHANGEDB_count_known_coins (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct
+ TALER_DenominationHashP *denom_pub_hash)
+{
+ uint64_t count;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("count",
+ &count),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+
+ PREPARE (pg,
+ "count_known_coins",
+ "SELECT"
+ " COUNT(*) AS count"
+ " FROM known_coins"
+ " WHERE denominations_serial="
+ " (SELECT denominations_serial"
+ " FROM denominations"
+ " WHERE denom_pub_hash=$1);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "count_known_coins",
+ params,
+ rs);
+ if (0 > qs)
+ return (long long) qs;
+ return (long long) count;
+}
diff --git a/src/exchangedb/create_aggregation_transient.c b/src/exchangedb/create_aggregation_transient.c
@@ -0,0 +1,61 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/create_aggregation_transient.c
+ * @brief Implementation of the create_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/create_aggregation_transient.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_create_aggregation_transient (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPaytoHashP *h_payto,
+ const char *exchange_account_section,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ uint64_t kyc_requirement_row,
+ const struct TALER_Amount *total)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (pg->conn,
+ total),
+ GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
+ GNUNET_PQ_query_param_string (exchange_account_section),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "create_aggregation_transient",
+ "INSERT INTO aggregation_transient"
+ " (amount"
+ " ,merchant_pub"
+ " ,wire_target_h_payto"
+ " ,legitimization_requirement_serial_id"
+ " ,exchange_account_section"
+ " ,wtid_raw)"
+ " VALUES ($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "create_aggregation_transient",
+ params);
+}
diff --git a/src/exchangedb/create_tables.c b/src/exchangedb/create_tables.c
@@ -0,0 +1,78 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/create_tables.c
+ * @brief Implementation of the create_tables function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/create_tables.h"
+#include "helper.h"
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGEDB_create_tables (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ bool support_partitions,
+ uint32_t num_partitions)
+{
+ struct GNUNET_PQ_Context *conn;
+ enum GNUNET_GenericReturnValue ret;
+ struct GNUNET_PQ_QueryParam params[] = {
+ support_partitions
+ ? GNUNET_PQ_query_param_uint32 (&num_partitions)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+ "exchangedb-postgres",
+ "exchange-",
+ es,
+ NULL);
+ if (NULL == conn)
+ return GNUNET_SYSERR;
+ ret = GNUNET_PQ_exec_sql (conn,
+ "procedures");
+ GNUNET_break (GNUNET_OK == ret);
+ if (GNUNET_OK == ret)
+ {
+ struct GNUNET_PQ_Context *tconn;
+
+ tconn = pg->conn;
+ pg->prep_gen++;
+ pg->conn = conn;
+ PREPARE (pg,
+ "create_tables",
+ "SELECT"
+ " exchange_do_create_tables"
+ " ($1::INTEGER);");
+ pg->conn = tconn;
+ if (0 >
+ GNUNET_PQ_eval_prepared_non_select (conn,
+ "create_tables",
+ params))
+ {
+ GNUNET_break (0);
+ ret = GNUNET_SYSERR;
+ }
+ }
+ GNUNET_PQ_disconnect (conn);
+ return ret;
+}
diff --git a/src/exchangedb/delete_aggregation_transient.c b/src/exchangedb/delete_aggregation_transient.c
@@ -0,0 +1,46 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/delete_aggregation_transient.c
+ * @brief Implementation of the delete_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/delete_aggregation_transient.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_delete_aggregation_transient (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPaytoHashP *h_payto,
+ const struct TALER_WireTransferIdentifierRawP *wtid)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "delete_aggregation_transient",
+ "DELETE FROM aggregation_transient"
+ " WHERE wire_target_h_payto=$1"
+ " AND wtid_raw=$2");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "delete_aggregation_transient",
+ params);
+}
diff --git a/src/exchangedb/delete_shard_locks.c b/src/exchangedb/delete_shard_locks.c
@@ -0,0 +1,37 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/delete_shard_locks.c
+ * @brief Implementation of the delete_shard_locks function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/exchange-database/delete_shard_locks.h"
+#include "helper.h"
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGEDB_delete_shard_locks (struct TALER_EXCHANGEDB_PostgresContext *pg
+ )
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("DELETE FROM work_shards;"),
+ GNUNET_PQ_make_execute ("DELETE FROM revolving_work_shards;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ return GNUNET_PQ_exec_statements (pg->conn,
+ es);
+}
diff --git a/src/exchangedb/disable_rules.c b/src/exchangedb/disable_rules.c
@@ -0,0 +1,57 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/disable_rules.c
+ * @brief Implementation of the disable_rules function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/disable_rules.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_disable_rules (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *schema)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (schema),
+ GNUNET_PQ_query_param_end
+ };
+ bool found;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("out_found",
+ &found),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "call_exchange_drop_customization",
+ "SELECT out_found"
+ " FROM exchange_drop_customization"
+ " ($1);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_exchange_drop_customization",
+ params,
+ rs);
+ if (qs < 0)
+ return qs;
+ if (found)
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+}
diff --git a/src/exchangedb/do_check_deposit_idempotent.c b/src/exchangedb/do_check_deposit_idempotent.c
@@ -0,0 +1,109 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_deposit.c
+ * @brief Implementation of the do_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_check_deposit_idempotent.h"
+#include "helper.h"
+#include "taler/exchange-database/compute_shard.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_check_deposit_idempotent (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_BatchDeposit *bd,
+ struct GNUNET_TIME_Timestamp *exchange_timestamp,
+ bool *is_idempotent)
+{
+ uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&bd->merchant_pub);
+ const struct TALER_CoinSpendPublicKeyP *coin_pubs[GNUNET_NZL (bd->num_cdis)];
+ const struct TALER_CoinSpendSignatureP *coin_sigs[GNUNET_NZL (bd->num_cdis)];
+ struct TALER_Amount amounts_with_fee[GNUNET_NZL (bd->num_cdis)];
+ struct TALER_NormalizedPaytoHashP h_normalized_payto;
+ struct GNUNET_PQ_QueryParam params[] = {
+ /* data for batch_deposits */
+ GNUNET_PQ_query_param_uint64 (&deposit_shard),
+ GNUNET_PQ_query_param_auto_from_type (&bd->merchant_pub),
+ GNUNET_PQ_query_param_timestamp (&bd->wallet_timestamp),
+ GNUNET_PQ_query_param_timestamp (exchange_timestamp),
+ GNUNET_PQ_query_param_timestamp (&bd->refund_deadline),
+ GNUNET_PQ_query_param_timestamp (&bd->wire_deadline),
+ GNUNET_PQ_query_param_auto_from_type (&bd->h_contract_terms),
+ (bd->no_wallet_data_hash)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (&bd->wallet_data_hash),
+ GNUNET_PQ_query_param_auto_from_type (&bd->wire_salt),
+ GNUNET_PQ_query_param_auto_from_type (&bd->wire_target_h_payto),
+ (0 == bd->policy_details_serial_id)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_uint64 (&bd->policy_details_serial_id),
+ GNUNET_PQ_query_param_bool (bd->policy_blocked),
+ /* arrays for coin_deposits */
+ GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
+ coin_pubs,
+ pg->conn),
+ GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
+ coin_sigs,
+ pg->conn),
+ TALER_PQ_query_param_array_amount (bd->num_cdis,
+ amounts_with_fee,
+ pg->conn),
+ GNUNET_PQ_query_param_end
+ };
+ bool no_time;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+ exchange_timestamp),
+ &no_time),
+ GNUNET_PQ_result_spec_bool ("is_idempotent",
+ is_idempotent),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ TALER_full_payto_normalize_and_hash (bd->receiver_wire_account,
+ &h_normalized_payto);
+ for (unsigned int i = 0; i < bd->num_cdis; i++)
+ {
+ const struct TALER_EXCHANGEDB_CoinDepositInformation *cdi
+ = &bd->cdis[i];
+
+ amounts_with_fee[i] = cdi->amount_with_fee;
+ coin_pubs[i] = &cdi->coin.coin_pub;
+ coin_sigs[i] = &cdi->csig;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Do deposit %u = %s\n",
+ i,
+ TALER_B2S (&cdi->coin.coin_pub));
+ }
+ PREPARE (pg,
+ "call_check_deposit_idempotent",
+ "SELECT "
+ " out_exchange_timestamp AS exchange_timestamp"
+ ",out_is_idempotent AS is_idempotent"
+ " FROM exchange_do_check_deposit_idempotent"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_check_deposit_idempotent",
+ params,
+ rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ return qs;
+}
diff --git a/src/exchangedb/do_deposit.c b/src/exchangedb/do_deposit.c
@@ -0,0 +1,171 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-2026 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_deposit.c
+ * @brief Implementation of the do_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_deposit.h"
+#include "helper.h"
+#include "taler/exchange-database/compute_shard.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_deposit (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_BatchDeposit *bd,
+ const struct TALER_Amount deposit_fees[],
+ struct GNUNET_TIME_Timestamp *exchange_timestamp,
+ struct TALER_Amount *accumulated_total_without_fee,
+ bool *balance_ok,
+ uint32_t *bad_balance_index,
+ bool *ctr_conflict)
+{
+ uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&bd->merchant_pub);
+ const struct TALER_CoinSpendPublicKeyP *coin_pubs[GNUNET_NZL (bd->num_cdis)];
+ const struct TALER_CoinSpendSignatureP *coin_sigs[GNUNET_NZL (bd->num_cdis)];
+ struct TALER_Amount amounts_with_fee[GNUNET_NZL (bd->num_cdis)];
+ struct TALER_Amount total_amount;
+ struct TALER_Amount total_without_fee;
+ struct TALER_NormalizedPaytoHashP h_normalized_payto;
+ struct GNUNET_PQ_QueryParam params[] = {
+ /* data for batch_deposits */
+ GNUNET_PQ_query_param_uint64 (&deposit_shard),
+ GNUNET_PQ_query_param_auto_from_type (&bd->merchant_pub),
+ GNUNET_PQ_query_param_auto_from_type (&bd->merchant_sig),
+ GNUNET_PQ_query_param_timestamp (&bd->wallet_timestamp),
+ GNUNET_PQ_query_param_timestamp (exchange_timestamp),
+ GNUNET_PQ_query_param_timestamp (&bd->refund_deadline),
+ GNUNET_PQ_query_param_timestamp (&bd->wire_deadline),
+ GNUNET_PQ_query_param_auto_from_type (&bd->h_contract_terms),
+ (bd->no_wallet_data_hash)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (&bd->wallet_data_hash),
+ GNUNET_PQ_query_param_auto_from_type (&bd->wire_salt),
+ GNUNET_PQ_query_param_auto_from_type (&bd->wire_target_h_payto),
+ GNUNET_PQ_query_param_auto_from_type (&h_normalized_payto),
+ (0 == bd->policy_details_serial_id)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_uint64 (&bd->policy_details_serial_id),
+ GNUNET_PQ_query_param_bool (bd->policy_blocked),
+ /* to create entry in wire_targets */
+ GNUNET_PQ_query_param_string (bd->receiver_wire_account.full_payto),
+ /* arrays for coin_deposits */
+ GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
+ coin_pubs,
+ pg->conn),
+ GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
+ coin_sigs,
+ pg->conn),
+ TALER_PQ_query_param_array_amount (bd->num_cdis,
+ amounts_with_fee,
+ pg->conn),
+ TALER_PQ_query_param_array_amount (bd->num_cdis,
+ deposit_fees,
+ pg->conn),
+ TALER_PQ_query_param_amount (pg->conn,
+ &total_amount),
+ TALER_PQ_query_param_amount (pg->conn,
+ &total_without_fee),
+ GNUNET_PQ_query_param_bool (TALER_payto_is_wallet (
+ bd->receiver_wire_account.full_payto)),
+ NULL == bd->extra_wire_subject_metadata
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (bd->extra_wire_subject_metadata),
+ GNUNET_PQ_query_param_end
+ };
+ bool no_time;
+ bool no_amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+ exchange_timestamp),
+ &no_time),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total_without_fee",
+ accumulated_total_without_fee),
+ &no_amount),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint32 ("insufficient_balance_coin_index",
+ bad_balance_index),
+ balance_ok),
+ GNUNET_PQ_result_spec_bool ("conflicted",
+ ctr_conflict),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_assert (0 < bd->num_cdis);
+ TALER_full_payto_normalize_and_hash (bd->receiver_wire_account,
+ &h_normalized_payto);
+ for (unsigned int i = 0; i < bd->num_cdis; i++)
+ {
+ const struct TALER_EXCHANGEDB_CoinDepositInformation *cdi
+ = &bd->cdis[i];
+
+ if (0 == i)
+ {
+ total_amount = cdi->amount_with_fee;
+ total_without_fee = cdi->amount_with_fee;
+ }
+ else
+ {
+ GNUNET_assert (0 <=
+ TALER_amount_add (&total_amount,
+ &total_amount,
+ &cdi->amount_with_fee));
+ GNUNET_assert (0 <=
+ TALER_amount_add (&total_without_fee,
+ &total_without_fee,
+ &cdi->amount_with_fee));
+ }
+ GNUNET_assert (0 <=
+ TALER_amount_subtract (
+ &total_without_fee,
+ &total_without_fee,
+ &deposit_fees[i]));
+
+ amounts_with_fee[i] = cdi->amount_with_fee;
+ coin_pubs[i] = &cdi->coin.coin_pub;
+ coin_sigs[i] = &cdi->csig;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Do deposit %u = %s\n",
+ i,
+ TALER_B2S (&cdi->coin.coin_pub));
+ }
+ PREPARE (pg,
+ "call_deposit",
+ "SELECT "
+ " out_exchange_timestamp AS exchange_timestamp"
+ ",out_accumulated_total_without_fee AS accumulated_total_without_fee"
+ ",out_insufficient_balance_coin_index AS insufficient_balance_coin_index"
+ ",out_conflict AS conflicted"
+ " FROM exchange_do_deposit"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10"
+ ",$11,$12,$13,$14,$15,$16,$17,$18,$19,$20"
+ ",$21,$22,$23);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_deposit",
+ params,
+ rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ if (no_amount)
+ memset (accumulated_total_without_fee,
+ 0,
+ sizeof (struct TALER_Amount));
+ return qs;
+}
diff --git a/src/exchangedb/do_purse_delete.c b/src/exchangedb/do_purse_delete.c
@@ -0,0 +1,60 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_purse_delete.c
+ * @brief Implementation of the do_purse_delete function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_purse_delete.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_purse_delete (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PurseContractSignatureP *purse_sig,
+ bool *decided,
+ bool *found)
+{
+ struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (purse_sig),
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("decided",
+ decided),
+ GNUNET_PQ_result_spec_bool ("found",
+ found),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "call_purse_delete",
+ "SELECT "
+ " out_decided AS decided"
+ ",out_found AS found"
+ " FROM exchange_do_purse_delete"
+ " ($1,$2,$3);");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_purse_delete",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_purse_deposit.c b/src/exchangedb/do_purse_deposit.c
@@ -0,0 +1,86 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_purse_deposit.c
+ * @brief Implementation of the do_purse_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_purse_deposit.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_purse_deposit (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_Amount *amount,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ const struct TALER_Amount *amount_minus_fee,
+ bool *balance_ok,
+ bool *too_late,
+ bool *conflict)
+{
+ struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
+ struct GNUNET_TIME_Timestamp reserve_expiration;
+ uint64_t partner_id = 0; /* FIXME #7271: WAD support... */
+ struct GNUNET_PQ_QueryParam params[] = {
+ (0 == partner_id)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_uint64 (&partner_id),
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ amount),
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (coin_sig),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ amount_minus_fee),
+ GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("balance_ok",
+ balance_ok),
+ GNUNET_PQ_result_spec_bool ("too_late",
+ too_late),
+ GNUNET_PQ_result_spec_bool ("conflict",
+ conflict),
+ GNUNET_PQ_result_spec_end
+ };
+
+ reserve_expiration
+ = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+ pg->legal_reserve_expiration_time));
+
+ PREPARE (pg,
+ "call_purse_deposit",
+ "SELECT "
+ " out_balance_ok AS balance_ok"
+ ",out_conflict AS conflict"
+ ",out_late AS too_late"
+ " FROM exchange_do_purse_deposit"
+ " ($1,$2,$3,$4,$5,$6,$7,$8);");
+
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_purse_deposit",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_purse_merge.c b/src/exchangedb/do_purse_merge.c
@@ -0,0 +1,87 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_purse_merge.c
+ * @brief Implementation of the do_purse_merge function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_purse_merge.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_purse_merge (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PurseMergeSignatureP *merge_sig,
+ const struct GNUNET_TIME_Timestamp merge_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ const char *partner_url,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ bool *no_partner,
+ bool *no_balance,
+ bool *in_conflict)
+{
+ struct TALER_NormalizedPaytoHashP h_payto;
+ struct GNUNET_TIME_Timestamp expiration
+ = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (merge_sig),
+ GNUNET_PQ_query_param_timestamp (&merge_timestamp),
+ GNUNET_PQ_query_param_auto_from_type (reserve_sig),
+ (NULL == partner_url)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (partner_url),
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (&h_payto),
+ GNUNET_PQ_query_param_timestamp (&expiration),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("no_partner",
+ no_partner),
+ GNUNET_PQ_result_spec_bool ("no_balance",
+ no_balance),
+ GNUNET_PQ_result_spec_bool ("conflict",
+ in_conflict),
+ GNUNET_PQ_result_spec_end
+ };
+
+ {
+ struct TALER_NormalizedPayto payto_uri;
+
+ payto_uri = TALER_reserve_make_payto (pg->exchange_url,
+ reserve_pub);
+ TALER_normalized_payto_hash (payto_uri,
+ &h_payto);
+ GNUNET_free (payto_uri.normalized_payto);
+ }
+ PREPARE (pg,
+ "call_purse_merge",
+ "SELECT"
+ " out_no_partner AS no_partner"
+ ",out_no_balance AS no_balance"
+ ",out_conflict AS conflict"
+ " FROM exchange_do_purse_merge"
+ " ($1, $2, $3, $4, $5, $6, $7, $8);");
+
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_purse_merge",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_recoup.c b/src/exchangedb/do_recoup.c
@@ -0,0 +1,81 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_recoup.c
+ * @brief Implementation of the do_recoup function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_recoup.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_recoup (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ uint64_t withdraw_id,
+ const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ uint64_t known_coin_id,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ struct GNUNET_TIME_Timestamp *recoup_timestamp,
+ bool *recoup_ok,
+ bool *internal_failure)
+{
+ struct GNUNET_TIME_Timestamp reserve_gc
+ = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
+ struct GNUNET_TIME_Timestamp reserve_expiration
+ = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_uint64 (&withdraw_id),
+ GNUNET_PQ_query_param_auto_from_type (coin_bks),
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_uint64 (&known_coin_id),
+ GNUNET_PQ_query_param_auto_from_type (coin_sig),
+ GNUNET_PQ_query_param_timestamp (&reserve_gc),
+ GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+ GNUNET_PQ_query_param_timestamp (recoup_timestamp),
+ GNUNET_PQ_query_param_end
+ };
+ bool is_null;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ recoup_timestamp),
+ &is_null),
+ GNUNET_PQ_result_spec_bool ("recoup_ok",
+ recoup_ok),
+ GNUNET_PQ_result_spec_bool ("internal_failure",
+ internal_failure),
+ GNUNET_PQ_result_spec_end
+ };
+
+
+ PREPARE (pg,
+ "call_recoup",
+ "SELECT "
+ " out_recoup_timestamp AS recoup_timestamp"
+ ",out_recoup_ok AS recoup_ok"
+ ",out_internal_failure AS internal_failure"
+ " FROM exchange_do_recoup_to_reserve"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_recoup",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_recoup_refresh.c b/src/exchangedb/do_recoup_refresh.c
@@ -0,0 +1,76 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_recoup_refresh.c
+ * @brief Implementation of the do_recoup_refresh function for Postgres
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_recoup_refresh.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_do_recoup_refresh (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+ uint64_t refresh_id,
+ const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ uint64_t known_coin_id,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ struct GNUNET_TIME_Timestamp *recoup_timestamp,
+ bool *recoup_ok,
+ bool *internal_failure)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (old_coin_pub),
+ GNUNET_PQ_query_param_uint64 (&refresh_id),
+ GNUNET_PQ_query_param_auto_from_type (coin_bks),
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_uint64 (&known_coin_id),
+ GNUNET_PQ_query_param_auto_from_type (coin_sig),
+ GNUNET_PQ_query_param_timestamp (recoup_timestamp),
+ GNUNET_PQ_query_param_end
+ };
+ bool is_null;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ recoup_timestamp),
+ &is_null),
+ GNUNET_PQ_result_spec_bool ("recoup_ok",
+ recoup_ok),
+ GNUNET_PQ_result_spec_bool ("internal_failure",
+ internal_failure),
+ GNUNET_PQ_result_spec_end
+ };
+
+
+ PREPARE (pg,
+ "call_recoup_refresh",
+ "SELECT "
+ " out_recoup_timestamp AS recoup_timestamp"
+ ",out_recoup_ok AS recoup_ok"
+ ",out_internal_failure AS internal_failure"
+ " FROM exchange_do_recoup_to_coin"
+ " ($1,$2,$3,$4,$5,$6,$7);");
+
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_recoup_refresh",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_refresh.c b/src/exchangedb/do_refresh.c
@@ -0,0 +1,138 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_refresh.c
+ * @brief Implementation of the do_refresh function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/taler_exchangedb_lib.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_refresh.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_refresh (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh,
+ const struct GNUNET_TIME_Timestamp *timestamp,
+ bool *found,
+ uint32_t *noreveal_index,
+ bool *zombie_required,
+ bool *nonce_reuse,
+ bool *balance_ok,
+ struct TALER_Amount *coin_balance)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
+ GNUNET_PQ_query_param_timestamp (timestamp),
+ GNUNET_PQ_query_param_auto_from_type (&refresh->refresh_seed), /* 3 */
+ (refresh->is_v27_refresh)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_array_auto_from_type (refresh->num_coins,
+ refresh->transfer_pubs,
+ pg->conn),
+ GNUNET_PQ_query_param_auto_from_type (&refresh->planchets_h),
+ TALER_PQ_query_param_amount (pg->conn, /* 6 */
+ &refresh->amount_with_fee),
+ (refresh->no_blinding_seed)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (&refresh->blinding_seed),
+ (0 < refresh->num_cs_r_values)
+ ? TALER_PQ_query_param_array_cs_r_pub (refresh->num_cs_r_values,
+ refresh->cs_r_values,
+ pg->conn)
+ : GNUNET_PQ_query_param_null (),
+ (0 < refresh->num_cs_r_values)
+ ? GNUNET_PQ_query_param_uint64 (&refresh->cs_r_choices) /* 9 */
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_auto_from_type (&refresh->selected_h),
+ TALER_PQ_query_param_array_blinded_denom_sig (refresh->num_coins,
+ refresh->denom_sigs,
+ pg->conn),
+ GNUNET_PQ_query_param_array_uint64 (refresh->num_coins, /* 12 */
+ refresh->denom_serials,
+ pg->conn),
+ GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig),
+ GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index), /* 15 */
+ GNUNET_PQ_query_param_bool (*zombie_required),
+ GNUNET_PQ_query_param_end
+ };
+ bool coin_found;
+ bool no_noreveal_index;
+ bool no_coin_balance;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("coin_found",
+ &coin_found),
+ GNUNET_PQ_result_spec_bool ("balance_ok",
+ balance_ok),
+ GNUNET_PQ_result_spec_bool ("zombie_required",
+ zombie_required),
+ GNUNET_PQ_result_spec_bool ("nonce_reuse",
+ nonce_reuse),
+ GNUNET_PQ_result_spec_bool ("found",
+ found),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint32 ("noreveal_index",
+ noreveal_index),
+ &no_noreveal_index),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_RESULT_SPEC_AMOUNT ("coin_balance",
+ coin_balance),
+ &no_coin_balance),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "call_refresh",
+ "SELECT "
+ " out_coin_found AS coin_found"
+ ",out_balance_ok AS balance_ok"
+ ",out_zombie_bad AS zombie_required"
+ ",out_nonce_reuse AS nonce_reuse"
+ ",out_idempotent AS found"
+ ",out_noreveal_index AS noreveal_index"
+ ",out_coin_balance AS coin_balance"
+ " FROM exchange_do_refresh"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_refresh",
+ params,
+ rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ return qs;
+ }
+ if (! coin_found)
+ {
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ if (*found && no_noreveal_index)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (! balance_ok && no_coin_balance)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ return qs;
+}
diff --git a/src/exchangedb/do_refund.c b/src/exchangedb/do_refund.c
@@ -0,0 +1,91 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_refund.c
+ * @brief Implementation of the do_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_refund.h"
+#include "helper.h"
+#include "taler/exchange-database/compute_shard.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_refund (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_Refund *refund,
+ const struct TALER_Amount *deposit_fee,
+ uint64_t known_coin_id,
+ bool *not_found,
+ bool *refund_ok,
+ bool *gone,
+ bool *conflict)
+{
+ uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&refund->details.
+ merchant_pub);
+ struct TALER_Amount amount_without_fee;
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (pg->conn,
+ &refund->details.refund_amount),
+ TALER_PQ_query_param_amount (pg->conn,
+ &amount_without_fee),
+ TALER_PQ_query_param_amount (pg->conn,
+ deposit_fee),
+ GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
+ GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
+ GNUNET_PQ_query_param_uint64 (&deposit_shard),
+ GNUNET_PQ_query_param_uint64 (&known_coin_id),
+ GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
+ GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("not_found",
+ not_found),
+ GNUNET_PQ_result_spec_bool ("refund_ok",
+ refund_ok),
+ GNUNET_PQ_result_spec_bool ("gone",
+ gone),
+ GNUNET_PQ_result_spec_bool ("conflict",
+ conflict),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (0 >
+ TALER_amount_subtract (&amount_without_fee,
+ &refund->details.refund_amount,
+ &refund->details.refund_fee))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ PREPARE (pg,
+ "call_refund",
+ "SELECT "
+ " out_not_found AS not_found"
+ ",out_refund_ok AS refund_ok"
+ ",out_gone AS gone"
+ ",out_conflict AS conflict"
+ " FROM exchange_do_refund"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_refund",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_reserve_open.c b/src/exchangedb/do_reserve_open.c
@@ -0,0 +1,97 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file do_reserve_open.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_reserve_open.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_reserve_open (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *total_paid,
+ const struct TALER_Amount *reserve_payment,
+ uint32_t min_purse_limit,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ struct GNUNET_TIME_Timestamp desired_expiration,
+ struct GNUNET_TIME_Timestamp now,
+ const struct TALER_Amount *open_fee,
+ bool *no_funds,
+ struct TALER_Amount *reserve_balance,
+ struct TALER_Amount *open_cost,
+ struct GNUNET_TIME_Timestamp *final_expiration)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ total_paid),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ reserve_payment),
+ GNUNET_PQ_query_param_uint32 (&min_purse_limit),
+ GNUNET_PQ_query_param_uint32 (&pg->def_purse_limit),
+ GNUNET_PQ_query_param_auto_from_type (reserve_sig),
+ GNUNET_PQ_query_param_timestamp (&desired_expiration),
+ GNUNET_PQ_query_param_relative_time (&pg->legal_reserve_expiration_time),
+ GNUNET_PQ_query_param_timestamp (&now),
+ TALER_PQ_query_param_amount (pg->conn,
+ open_fee),
+ GNUNET_PQ_query_param_end
+ };
+ bool no_reserve = true;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_amount ("out_open_cost",
+ pg->currency,
+ open_cost),
+ TALER_PQ_result_spec_amount ("out_reserve_balance",
+ pg->currency,
+ reserve_balance),
+ GNUNET_PQ_result_spec_timestamp ("out_final_expiration",
+ final_expiration),
+ GNUNET_PQ_result_spec_bool ("out_no_reserve",
+ &no_reserve),
+ GNUNET_PQ_result_spec_bool ("out_no_funds",
+ no_funds),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "do_reserve_open",
+ "SELECT "
+ " out_open_cost"
+ ",out_final_expiration"
+ ",out_no_funds"
+ ",out_no_reserve"
+ ",out_reserve_balance"
+ " FROM exchange_do_reserve_open"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "do_reserve_open",
+ params,
+ rs);
+ if (qs <= 0)
+ return qs;
+ if (no_reserve)
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ return qs;
+}
diff --git a/src/exchangedb/do_reserve_purse.c b/src/exchangedb/do_reserve_purse.c
@@ -0,0 +1,118 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_reserve_purse.c
+ * @brief Implementation of the do_reserve_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_reserve_purse.h"
+#include "helper.h"
+
+
+/**
+ * Function called insert request to merge a purse into a reserve by the
+ * respective purse merge key. The purse must not have been merged into a
+ * different reserve.
+ *
+ * @param pg the database context
+ * @param purse_pub purse to merge
+ * @param merge_sig signature affirming the merge
+ * @param merge_timestamp time of the merge
+ * @param reserve_sig signature of the reserve affirming the merge
+ * @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota
+ * @param reserve_pub public key of the reserve to credit
+ * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
+ * @param[out] no_reserve set to true if @a reserve_pub is not a known reserve
+ * @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_reserve_purse (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PurseMergeSignatureP *merge_sig,
+ const struct GNUNET_TIME_Timestamp merge_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ const struct TALER_Amount *purse_fee,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ bool *in_conflict,
+ bool *no_reserve,
+ bool *insufficient_funds)
+{
+ struct TALER_Amount zero_fee;
+ struct TALER_NormalizedPaytoHashP h_payto;
+ struct GNUNET_TIME_Timestamp reserve_expiration
+ = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+ pg->idle_reserve_expiration_time));
+ struct GNUNET_TIME_Timestamp reserve_gc
+ = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+ pg->legal_reserve_expiration_time));
+
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (merge_sig),
+ GNUNET_PQ_query_param_timestamp (&merge_timestamp),
+ GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+ GNUNET_PQ_query_param_timestamp (&reserve_gc),
+ GNUNET_PQ_query_param_auto_from_type (reserve_sig),
+ GNUNET_PQ_query_param_bool (NULL == purse_fee),
+ TALER_PQ_query_param_amount (pg->conn,
+ NULL == purse_fee
+ ? &zero_fee
+ : purse_fee),
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (&h_payto),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("insufficient_funds",
+ insufficient_funds),
+ GNUNET_PQ_result_spec_bool ("conflict",
+ in_conflict),
+ GNUNET_PQ_result_spec_bool ("no_reserve",
+ no_reserve),
+ GNUNET_PQ_result_spec_end
+ };
+
+ {
+ struct TALER_NormalizedPayto payto_uri;
+
+ payto_uri = TALER_reserve_make_payto (pg->exchange_url,
+ reserve_pub);
+ TALER_normalized_payto_hash (payto_uri,
+ &h_payto);
+ GNUNET_free (payto_uri.normalized_payto);
+ }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pg->currency,
+ &zero_fee));
+ PREPARE (pg,
+ "call_reserve_purse",
+ "SELECT"
+ " out_no_funds AS insufficient_funds"
+ ",out_no_reserve AS no_reserve"
+ ",out_conflict AS conflict"
+ " FROM exchange_do_reserve_purse"
+ " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
+
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_reserve_purse",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_withdraw.c b/src/exchangedb/do_withdraw.c
@@ -0,0 +1,140 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023-2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/do_withdraw.c
+ * @brief Implementation of the do_withdraw function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/taler_exchangedb_lib.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/do_withdraw.h"
+#include "helper.h"
+#include <gnunet/gnunet_time_lib.h>
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_do_withdraw (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_Withdraw *withdraw,
+ const struct GNUNET_TIME_Timestamp *timestamp,
+ bool *balance_ok,
+ struct TALER_Amount *reserve_balance,
+ bool *age_ok,
+ uint16_t *required_age,
+ uint32_t *reserve_birthday,
+ bool *idempotent,
+ uint16_t *noreveal_index,
+ bool *nonce_reuse)
+{
+ struct GNUNET_TIME_Timestamp gc;
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (pg->conn,
+ &withdraw->amount_with_fee),
+ GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_sig),
+ GNUNET_PQ_query_param_timestamp (timestamp),
+ GNUNET_PQ_query_param_timestamp (&gc),
+ GNUNET_PQ_query_param_auto_from_type (&withdraw->planchets_h),
+ (withdraw->age_proof_required)
+ ? GNUNET_PQ_query_param_uint16 (&withdraw->max_age)
+ : GNUNET_PQ_query_param_null (),
+ (withdraw->age_proof_required)
+ ? GNUNET_PQ_query_param_uint16 (&withdraw->noreveal_index)
+ : GNUNET_PQ_query_param_null (),
+ (withdraw->age_proof_required)
+ ? GNUNET_PQ_query_param_auto_from_type (&withdraw->selected_h)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_array_uint64 (withdraw->num_coins,
+ withdraw->denom_serials,
+ pg->conn),
+ TALER_PQ_query_param_array_blinded_denom_sig (withdraw->num_coins,
+ withdraw->denom_sigs,
+ pg->conn),
+ (withdraw->no_blinding_seed)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (&withdraw->blinding_seed),
+ (withdraw->no_blinding_seed)
+ ? GNUNET_PQ_query_param_null ()
+ : TALER_PQ_query_param_array_cs_r_pub (withdraw->num_cs_r_values,
+ withdraw->cs_r_values,
+ pg->conn),
+ (withdraw->no_blinding_seed)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_uint64 (&withdraw->cs_r_choices),
+ GNUNET_PQ_query_param_end
+ };
+ bool reserve_found;
+ bool no_noreveal_index;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("out_reserve_found",
+ &reserve_found),
+ GNUNET_PQ_result_spec_bool ("out_balance_ok",
+ balance_ok),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("out_reserve_balance",
+ reserve_balance),
+ GNUNET_PQ_result_spec_bool ("out_age_ok",
+ age_ok),
+ GNUNET_PQ_result_spec_uint16 ("out_required_age",
+ required_age),
+ GNUNET_PQ_result_spec_uint32 ("out_reserve_birthday",
+ reserve_birthday),
+ GNUNET_PQ_result_spec_bool ("out_idempotent",
+ idempotent),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint16 ("out_noreveal_index",
+ noreveal_index),
+ &no_noreveal_index),
+ GNUNET_PQ_result_spec_bool ("out_nonce_reuse",
+ nonce_reuse),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_assert ((! withdraw->no_blinding_seed) ||
+ (0 == withdraw->num_cs_r_values));
+
+ gc = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (timestamp->abs_time,
+ pg->legal_reserve_expiration_time));
+ PREPARE (pg,
+ "call_withdraw",
+ "SELECT "
+ " out_reserve_found"
+ ",out_balance_ok"
+ ",out_reserve_balance"
+ ",out_age_ok"
+ ",out_required_age"
+ ",out_reserve_birthday"
+ ",out_idempotent"
+ ",out_noreveal_index"
+ ",out_nonce_reuse"
+ " FROM exchange_do_withdraw"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_withdraw",
+ params,
+ rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+
+ if (0 > qs)
+ return qs;
+ if (! reserve_found)
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ if ((withdraw->age_proof_required) &&
+ (idempotent && no_noreveal_index))
+ GNUNET_break (0);
+ return qs;
+}
diff --git a/src/exchangedb/drain_kyc_alert.c b/src/exchangedb/drain_kyc_alert.c
@@ -0,0 +1,55 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/drain_kyc_alert.c
+ * @brief Implementation of the drain_kyc_alert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/drain_kyc_alert.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_drain_kyc_alert (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint32_t trigger_type,
+ struct TALER_NormalizedPaytoHashP *h_payto)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint32 (&trigger_type),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("h_payto",
+ h_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "drain_kyc_alert",
+ "DELETE FROM kyc_alerts"
+ " WHERE trigger_type=$1"
+ " AND h_payto = "
+ " (SELECT h_payto "
+ " FROM kyc_alerts"
+ " WHERE trigger_type=$1"
+ " LIMIT 1)"
+ " RETURNING h_payto;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "drain_kyc_alert",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/drop_tables.c b/src/exchangedb/drop_tables.c
@@ -0,0 +1,54 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/drop_tables.c
+ * @brief Implementation of the drop_tables function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/drop_tables.h"
+#include "helper.h"
+
+
+/**
+ * Drop all Taler tables. This should only be used by testcases.
+ *
+ * @param pg the database context
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGEDB_drop_tables (struct TALER_EXCHANGEDB_PostgresContext *pg)
+{
+ struct GNUNET_PQ_Context *conn;
+ enum GNUNET_GenericReturnValue ret;
+
+ if (NULL != pg->conn)
+ {
+ GNUNET_PQ_disconnect (pg->conn);
+ pg->conn = NULL;
+ }
+ conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+ "exchangedb-postgres",
+ NULL,
+ NULL,
+ NULL);
+ if (NULL == conn)
+ return GNUNET_SYSERR;
+ ret = GNUNET_PQ_exec_sql (conn,
+ "drop");
+ GNUNET_PQ_disconnect (conn);
+ return ret;
+}
diff --git a/src/exchangedb/enable_rules.c b/src/exchangedb/enable_rules.c
@@ -0,0 +1,74 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/enable_rules.c
+ * @brief Implementation of the enable_rules function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/enable_rules.h"
+#include "helper.h"
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGEDB_enable_rules (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *schema)
+{
+ struct GNUNET_PQ_Context *conn;
+ enum GNUNET_GenericReturnValue ret;
+ char *sp;
+
+ GNUNET_asprintf (&sp,
+ "SET search_path TO %s,exchange;",
+ schema);
+ {
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_try_execute (sp),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+ char *schemadash;
+
+ GNUNET_asprintf (&schemadash,
+ "%s-",
+ schema);
+ conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+ "exchangedb-postgres",
+ schemadash,
+ es,
+ NULL);
+ GNUNET_free (schemadash);
+ }
+ GNUNET_free (sp);
+ if (NULL == conn)
+ return GNUNET_SYSERR;
+ {
+ char *procfile;
+
+ GNUNET_asprintf (&procfile,
+ "%s-procedures",
+ schema);
+ ret = GNUNET_PQ_exec_sql (conn,
+ procfile);
+ /* $SCHEMA-procedures MAY not exist, so only check for hard error */
+ GNUNET_break (GNUNET_SYSERR != ret);
+ if (GNUNET_NO == ret)
+ ret = GNUNET_OK;
+ GNUNET_free (procfile);
+ }
+ GNUNET_PQ_disconnect (conn);
+ return ret;
+}
diff --git a/src/exchangedb/ensure_coin_known.c b/src/exchangedb/ensure_coin_known.c
@@ -0,0 +1,166 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/ensure_coin_known.c
+ * @brief Implementation of the ensure_coin_known function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_exchangedb_lib.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/ensure_coin_known.h"
+#include "helper.h"
+
+
+enum TALER_EXCHANGEDB_CoinKnownStatus
+TALER_EXCHANGEDB_ensure_coin_known (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinPublicInfo *coin,
+ uint64_t *known_coin_id,
+ struct TALER_DenominationHashP *denom_hash,
+ struct TALER_AgeCommitmentHashP *h_age_commitment)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ bool existed;
+ bool no_denom_pub_hash;
+ bool no_age_commitment_hash;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash),
+ coin->no_age_commitment
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (&coin->h_age_commitment),
+ TALER_PQ_query_param_denom_sig (&coin->denom_sig),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("existed",
+ &existed),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+ known_coin_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ denom_hash),
+ &no_denom_pub_hash),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ h_age_commitment),
+ &no_age_commitment_hash),
+ GNUNET_PQ_result_spec_end
+ };
+
+ /*
+ See also:
+ https://stackoverflow.com/questions/34708509/how-to-use-returning-with-on-conflict-in-postgresql/37543015#37543015
+ */
+ PREPARE (pg,
+ "insert_known_coin",
+ "WITH dd"
+ " (denominations_serial"
+ " ,coin"
+ " ) AS ("
+ " SELECT "
+ " denominations_serial"
+ " ,coin"
+ " FROM denominations"
+ " WHERE denom_pub_hash=$2"
+ " ), input_rows"
+ " (coin_pub) AS ("
+ " VALUES ($1::BYTEA)"
+ " ), ins AS ("
+ " INSERT INTO known_coins "
+ " (coin_pub"
+ " ,denominations_serial"
+ " ,age_commitment_hash"
+ " ,denom_sig"
+ " ,remaining"
+ " ) SELECT "
+ " $1"
+ " ,denominations_serial"
+ " ,$3"
+ " ,$4"
+ " ,coin"
+ " FROM dd"
+ " ON CONFLICT DO NOTHING" /* CONFLICT on (coin_pub) */
+ " RETURNING "
+ " known_coin_id"
+ " ) "
+ "SELECT "
+ " FALSE AS existed"
+ " ,known_coin_id"
+ " ,NULL AS denom_pub_hash"
+ " ,NULL AS age_commitment_hash"
+ " FROM ins "
+ "UNION ALL "
+ "SELECT "
+ " TRUE AS existed"
+ " ,known_coin_id"
+ " ,denom_pub_hash"
+ " ,kc.age_commitment_hash"
+ " FROM input_rows"
+ " JOIN known_coins kc USING (coin_pub)"
+ " JOIN denominations USING (denominations_serial)"
+ " LIMIT 1");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "insert_known_coin",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return TALER_EXCHANGEDB_CKS_HARD_FAIL;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ GNUNET_break (0); /* should be impossible */
+ return TALER_EXCHANGEDB_CKS_HARD_FAIL;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ if (! existed)
+ return TALER_EXCHANGEDB_CKS_ADDED;
+ break; /* continued below */
+ }
+
+ if ( (! no_denom_pub_hash) &&
+ (0 != GNUNET_memcmp (denom_hash,
+ &coin->denom_pub_hash)) )
+ {
+ GNUNET_break_op (0);
+ return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT;
+ }
+
+ if (no_age_commitment_hash != coin->no_age_commitment)
+ {
+ if (no_age_commitment_hash)
+ {
+ GNUNET_break_op (0);
+ return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL;
+ }
+ else
+ {
+ GNUNET_break_op (0);
+ return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL;
+ }
+ }
+ else if ( (! no_age_commitment_hash) &&
+ (0 != GNUNET_memcmp (h_age_commitment,
+ &coin->h_age_commitment)) )
+ {
+ GNUNET_break_op (0);
+ return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS;
+ }
+
+ return TALER_EXCHANGEDB_CKS_PRESENT;
+}
diff --git a/src/exchangedb/event_listen.c b/src/exchangedb/event_listen.c
@@ -0,0 +1,49 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/event_listen.c
+ * @brief Implementation of the event_listen function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_dbevents.h"
+#include "taler/exchange-database/event_listen.h"
+#include "helper.h"
+
+/**
+ * Register callback to be invoked on events of type @a es.
+ *
+ * @param pg the database context
+ * @param timeout how long until to generate a timeout event
+ * @param es specification of the event to listen for
+ * @param cb function to call when the event happens, possibly
+ * multiple times (until cancel is invoked)
+ * @param cb_cls closure for @a cb
+ * @return handle useful to cancel the listener
+ */
+struct GNUNET_DB_EventHandler *
+TALER_EXCHANGEDB_event_listen (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct GNUNET_TIME_Relative timeout,
+ const struct GNUNET_DB_EventHeaderP *es,
+ GNUNET_DB_EventCallback cb,
+ void *cb_cls)
+{
+
+ return GNUNET_PQ_event_listen (pg->conn,
+ es,
+ timeout,
+ cb,
+ cb_cls);
+}
diff --git a/src/exchangedb/event_listen_cancel.c b/src/exchangedb/event_listen_cancel.c
@@ -0,0 +1,34 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/event_listen_cancel.c
+ * @brief Implementation of the event_listen_cancel function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/exchange-database/event_listen_cancel.h"
+#include "helper.h"
+
+
+void
+TALER_TALER_EXCHANGEDB_event_listen_cancel (struct
+ TALER_EXCHANGEDB_PostgresContext *pg
+ ,
+ struct GNUNET_DB_EventHandler *eh)
+
+{
+ (void) pg;
+ GNUNET_PQ_event_listen_cancel (eh);
+}
diff --git a/src/exchangedb/event_notify.c b/src/exchangedb/event_notify.c
@@ -0,0 +1,37 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/event_notify.c
+ * @brief Implementation of the event_notify function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_dbevents.h"
+#include "taler/exchange-database/event_notify.h"
+#include "helper.h"
+
+
+void
+TALER_EXCHANGEDB_event_notify (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct GNUNET_DB_EventHeaderP *es,
+ const void *extra,
+ size_t extra_size)
+{
+
+ GNUNET_PQ_event_notify (pg->conn,
+ es,
+ extra,
+ extra_size);
+}
diff --git a/src/exchangedb/expire_purse.c b/src/exchangedb/expire_purse.c
@@ -0,0 +1,65 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/expire_purse.c
+ * @brief Implementation of the expire_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/expire_purse.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_expire_purse (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct GNUNET_TIME_Absolute start_time,
+ struct GNUNET_TIME_Absolute end_time)
+{
+ struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_absolute_time (&start_time),
+ GNUNET_PQ_query_param_absolute_time (&end_time),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_end
+ };
+ bool found = false;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("found",
+ &found),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+
+ PREPARE (pg,
+ "call_expire_purse",
+ "SELECT "
+ " out_found AS found"
+ " FROM exchange_do_expire_purse"
+ " ($1,$2,$3);");
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_expire_purse",
+ params,
+ rs);
+ if (qs < 0)
+ return qs;
+ GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
+ return found
+ ? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
+ : GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+}
diff --git a/src/exchangedb/find_aggregation_transient.c b/src/exchangedb/find_aggregation_transient.c
@@ -0,0 +1,69 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/find_aggregation_transient.c
+ * @brief Implementation of the find_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/find_aggregation_transient.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_find_aggregation_transient (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct TALER_FullPayto *payto_uri,
+ struct TALER_WireTransferIdentifierRawP *wtid,
+ struct TALER_MerchantPublicKeyP *merchant_pub,
+ struct TALER_Amount *total)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+ merchant_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+ wtid),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri->full_payto),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ total),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "find_transient_aggregations",
+ "SELECT"
+ " atr.amount"
+ " ,atr.wtid_raw"
+ " ,atr.merchant_pub"
+ " ,wt.payto_uri"
+ " FROM wire_targets wt"
+ " JOIN aggregation_transient atr"
+ " USING (wire_target_h_payto)"
+ " WHERE wt.h_normalized_payto=$1"
+ " LIMIT 1;"); /* Note: there should really be only 1 match */
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "find_transient_aggregations",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/gc.c b/src/exchangedb/gc.c
@@ -0,0 +1,75 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/gc.c
+ * @brief Implementation of the gc function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/gc.h"
+#include "helper.h"
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGEDB_gc (struct TALER_EXCHANGEDB_PostgresContext *pg)
+{
+ struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+ struct GNUNET_TIME_Absolute long_ago;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_absolute_time (&long_ago),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_Context *conn;
+ enum GNUNET_GenericReturnValue ret;
+
+ /* Keep wire fees for 10 years, that should always
+ be enough _and_ they are tiny so it does not
+ matter to make this tight */
+ long_ago = GNUNET_TIME_absolute_subtract (
+ now,
+ GNUNET_TIME_relative_multiply (
+ GNUNET_TIME_UNIT_YEARS,
+ 10));
+ {
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+ struct GNUNET_PQ_PreparedStatement ps[] = {
+ GNUNET_PQ_make_prepare ("run_gc",
+ "CALL"
+ " exchange_do_gc"
+ " ($1,$2);"),
+ GNUNET_PQ_PREPARED_STATEMENT_END
+ };
+
+ conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+ "exchangedb-postgres",
+ NULL,
+ es,
+ ps);
+ }
+ if (NULL == conn)
+ return GNUNET_SYSERR;
+ ret = GNUNET_OK;
+ if (0 > GNUNET_PQ_eval_prepared_non_select (conn,
+ "run_gc",
+ params))
+ ret = GNUNET_SYSERR;
+ GNUNET_PQ_disconnect (conn);
+ return ret;
+}
diff --git a/src/exchangedb/get_coin_denomination.c b/src/exchangedb/get_coin_denomination.c
@@ -0,0 +1,65 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_coin_denomination.c
+ * @brief Implementation of the get_coin_denomination function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_coin_denomination.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_coin_denomination (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ uint64_t *known_coin_id,
+ struct TALER_DenominationHashP *denom_hash)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ denom_hash),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+ known_coin_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting coin denomination of coin %s\n",
+ TALER_B2S (coin_pub));
+
+ /* Used in #postgres_get_coin_denomination() to fetch
+ the denomination public key hash for
+ a coin known to the exchange. */
+ PREPARE (pg,
+ "get_coin_denomination",
+ "SELECT"
+ " denominations.denom_pub_hash"
+ ",known_coin_id"
+ " FROM known_coins"
+ " JOIN denominations USING (denominations_serial)"
+ " WHERE coin_pub=$1"
+ " FOR SHARE;");
+
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_coin_denomination",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_coin_transactions.c b/src/exchangedb/get_coin_transactions.c
@@ -0,0 +1,1184 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file get_coin_transactions.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_exchangedb_lib.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_coin_transactions.h"
+#include "helper.h"
+#include "taler/exchange-database/start_read_committed.h"
+#include "taler/exchange-database/commit.h"
+#include "taler/exchange-database/rollback.h"
+
+
+/**
+ * How often do we re-try when encountering DB serialization issues?
+ * (We are read-only, so can only happen due to concurrent insert,
+ * which should be very rare.)
+ */
+#define RETRIES 3
+
+/**
+ * Closure for callbacks called from #TALER_EXCHANGEDB_get_coin_transactions()
+ */
+struct CoinHistoryContext
+{
+ /**
+ * Head of the coin's history list.
+ */
+ struct TALER_EXCHANGEDB_TransactionList *head;
+
+ /**
+ * Public key of the coin we are building the history for.
+ */
+ const struct TALER_CoinSpendPublicKeyP *coin_pub;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Our current offset in the coin history.
+ */
+ uint64_t chid;
+
+ /**
+ * Set to 'true' if the transaction failed.
+ */
+ bool failed;
+
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_coin_deposit (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_DepositListEntry *deposit;
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+ uint64_t serial_id;
+
+ deposit = GNUNET_new (struct TALER_EXCHANGEDB_DepositListEntry);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &deposit->amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &deposit->deposit_fee),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &deposit->h_denom_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &deposit->h_age_commitment),
+ &deposit->no_age_commitment),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("wallet_data_hash",
+ &deposit->wallet_data_hash),
+ &deposit->no_wallet_data_hash),
+ GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
+ &deposit->timestamp),
+ GNUNET_PQ_result_spec_timestamp ("refund_deadline",
+ &deposit->refund_deadline),
+ GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+ &deposit->wire_deadline),
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+ &deposit->merchant_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &deposit->h_contract_terms),
+ GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+ &deposit->wire_salt),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &deposit->receiver_wire_account.full_payto
+ ),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &deposit->csig),
+ GNUNET_PQ_result_spec_uint64 ("coin_deposit_serial_id",
+ &serial_id),
+ GNUNET_PQ_result_spec_auto_from_type ("done",
+ &deposit->done),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ GNUNET_free (deposit);
+ chc->failed = true;
+ return;
+ }
+ }
+ tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
+ tl->next = chc->head;
+ tl->type = TALER_EXCHANGEDB_TT_DEPOSIT;
+ tl->details.deposit = deposit;
+ tl->serial_id = serial_id;
+ tl->coin_history_id = chc->chid;
+ chc->head = tl;
+ }
+}
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_coin_purse_deposit (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_PurseDepositListEntry *deposit;
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+ uint64_t serial_id;
+
+ deposit = GNUNET_new (struct TALER_EXCHANGEDB_PurseDepositListEntry);
+ {
+ bool not_finished;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &deposit->amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &deposit->deposit_fee),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &deposit->purse_pub),
+ GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
+ &serial_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("partner_base_url",
+ &deposit->exchange_base_url),
+ NULL),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &deposit->coin_sig),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &deposit->h_age_commitment),
+ &deposit->no_age_commitment),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_bool ("refunded",
+ &deposit->refunded),
+ ¬_finished),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &deposit->h_denom_pub),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ GNUNET_free (deposit);
+ chc->failed = true;
+ return;
+ }
+ if (not_finished)
+ deposit->refunded = false;
+ /* double-check for all-zeros age commitment */
+ if (! deposit->no_age_commitment)
+ deposit->no_age_commitment
+ = GNUNET_is_zero (&deposit->h_age_commitment);
+ }
+ tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
+ tl->next = chc->head;
+ tl->type = TALER_EXCHANGEDB_TT_PURSE_DEPOSIT;
+ tl->details.purse_deposit = deposit;
+ tl->serial_id = serial_id;
+ tl->coin_history_id = chc->chid;
+ chc->head = tl;
+ }
+}
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_coin_melt (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_MeltListEntry *melt;
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+ uint64_t serial_id;
+
+ melt = GNUNET_new (struct TALER_EXCHANGEDB_MeltListEntry);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("rc",
+ &melt->rc),
+ /* oldcoin_index not needed */
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &melt->h_denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
+ &melt->coin_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("refresh_seed",
+ &melt->refresh_seed),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
+ &melt->blinding_seed),
+ &melt->no_blinding_seed),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &melt->amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+ &melt->melt_fee),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &melt->h_age_commitment),
+ &melt->no_age_commitment),
+ GNUNET_PQ_result_spec_uint64 ("refresh_id",
+ &serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ GNUNET_free (melt);
+ chc->failed = true;
+ return;
+ }
+ }
+ tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
+ tl->next = chc->head;
+ tl->type = TALER_EXCHANGEDB_TT_MELT;
+ tl->details.melt = melt;
+ tl->serial_id = serial_id;
+ tl->coin_history_id = chc->chid;
+ chc->head = tl;
+ }
+}
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_coin_refund (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_RefundListEntry *refund;
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+ uint64_t serial_id;
+
+ refund = GNUNET_new (struct TALER_EXCHANGEDB_RefundListEntry);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+ &refund->merchant_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
+ &refund->merchant_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &refund->h_contract_terms),
+ GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
+ &refund->rtransaction_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &refund->refund_amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+ &refund->refund_fee),
+ GNUNET_PQ_result_spec_uint64 ("refund_serial_id",
+ &serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ GNUNET_free (refund);
+ chc->failed = true;
+ return;
+ }
+ }
+ tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
+ tl->next = chc->head;
+ tl->type = TALER_EXCHANGEDB_TT_REFUND;
+ tl->details.refund = refund;
+ tl->serial_id = serial_id;
+ tl->coin_history_id = chc->chid;
+ chc->head = tl;
+ }
+}
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_coin_purse_decision (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_PurseRefundListEntry *prefund;
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+ uint64_t serial_id;
+
+ prefund = GNUNET_new (struct TALER_EXCHANGEDB_PurseRefundListEntry);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &prefund->purse_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &prefund->refund_amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+ &prefund->refund_fee),
+ GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id",
+ &serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ GNUNET_free (prefund);
+ chc->failed = true;
+ return;
+ }
+ }
+ tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
+ tl->next = chc->head;
+ tl->type = TALER_EXCHANGEDB_TT_PURSE_REFUND;
+ tl->details.purse_refund = prefund;
+ tl->serial_id = serial_id;
+ tl->coin_history_id = chc->chid;
+ chc->head = tl;
+ }
+}
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_old_coin_recoup (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup;
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+ uint64_t serial_id;
+
+ recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &recoup->coin.coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &recoup->coin_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+ &recoup->coin_blind),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &recoup->value),
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ &recoup->timestamp),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &recoup->coin.denom_pub_hash),
+ TALER_PQ_result_spec_denom_sig ("denom_sig",
+ &recoup->coin.denom_sig),
+ GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
+ &serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ GNUNET_free (recoup);
+ chc->failed = true;
+ return;
+ }
+ recoup->old_coin_pub = *chc->coin_pub;
+ }
+ tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
+ tl->next = chc->head;
+ tl->type = TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER;
+ tl->details.old_coin_recoup = recoup;
+ tl->serial_id = serial_id;
+ tl->coin_history_id = chc->chid;
+ chc->head = tl;
+ }
+}
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_coin_recoup (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_RecoupListEntry *recoup;
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+ uint64_t serial_id;
+
+ recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupListEntry);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &recoup->reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &recoup->coin_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &recoup->h_denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+ &recoup->coin_blind),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &recoup->value),
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ &recoup->timestamp),
+ GNUNET_PQ_result_spec_uint64 ("recoup_uuid",
+ &serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ GNUNET_free (recoup);
+ chc->failed = true;
+ return;
+ }
+ }
+ tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
+ tl->next = chc->head;
+ tl->type = TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW;
+ tl->details.recoup = recoup;
+ tl->serial_id = serial_id;
+ tl->coin_history_id = chc->chid;
+ chc->head = tl;
+ }
+}
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_coin_recoup_refresh (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup;
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+ uint64_t serial_id;
+
+ recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+ &recoup->old_coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &recoup->coin_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+ &recoup->coin_blind),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &recoup->value),
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ &recoup->timestamp),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &recoup->coin.denom_pub_hash),
+ TALER_PQ_result_spec_denom_sig ("denom_sig",
+ &recoup->coin.denom_sig),
+ GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
+ &serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ GNUNET_free (recoup);
+ chc->failed = true;
+ return;
+ }
+ recoup->coin.coin_pub = *chc->coin_pub;
+ }
+ tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
+ tl->next = chc->head;
+ tl->type = TALER_EXCHANGEDB_TT_RECOUP_REFRESH;
+ tl->details.recoup_refresh = recoup;
+ tl->serial_id = serial_id;
+ tl->coin_history_id = chc->chid;
+ chc->head = tl;
+ }
+}
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+add_coin_reserve_open (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_ReserveOpenListEntry *role;
+ struct TALER_EXCHANGEDB_TransactionList *tl;
+ uint64_t serial_id;
+
+ role = GNUNET_new (struct TALER_EXCHANGEDB_ReserveOpenListEntry);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ &role->reserve_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &role->coin_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("contribution",
+ &role->coin_contribution),
+ GNUNET_PQ_result_spec_uint64 ("reserve_open_deposit_uuid",
+ &serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ GNUNET_free (role);
+ chc->failed = true;
+ return;
+ }
+ }
+ tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
+ tl->next = chc->head;
+ tl->type = TALER_EXCHANGEDB_TT_RESERVE_OPEN;
+ tl->details.reserve_open = role;
+ tl->serial_id = serial_id;
+ tl->coin_history_id = chc->chid;
+ chc->head = tl;
+ }
+}
+
+
+/**
+ * Work we need to do.
+ */
+struct Work
+{
+ /**
+ * Name of the table.
+ */
+ const char *table;
+
+ /**
+ * SQL prepared statement name.
+ */
+ const char *statement;
+
+ /**
+ * Function to call to handle the result(s).
+ */
+ GNUNET_PQ_PostgresResultHandler cb;
+};
+
+
+/**
+ * We found a coin history entry. Lookup details
+ * from the respective table and store in @a cls.
+ *
+ * @param[in,out] cls a `struct CoinHistoryContext`
+ * @param result a coin history entry result set
+ * @param num_results total number of results in @a results
+ */
+static void
+handle_history_entry (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
+ static const struct Work work[] = {
+ [TALER_EXCHANGEDB_TT_DEPOSIT] =
+ { "coin_deposits",
+ "get_deposit_with_coin_pub",
+ &add_coin_deposit },
+ [TALER_EXCHANGEDB_TT_MELT] =
+ { "refresh",
+ "get_refresh_by_coin",
+ &add_coin_melt },
+ [TALER_EXCHANGEDB_TT_PURSE_DEPOSIT] =
+ { "purse_deposits",
+ "get_purse_deposit_by_coin_pub",
+ &add_coin_purse_deposit },
+ [TALER_EXCHANGEDB_TT_PURSE_REFUND] =
+ { "purse_decision",
+ "get_purse_decision_by_coin_pub",
+ &add_coin_purse_decision },
+ [TALER_EXCHANGEDB_TT_REFUND] =
+ { "refunds",
+ "get_refunds_by_coin",
+ &add_coin_refund },
+ [TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW] =
+ { "recoup",
+ "recoup_by_coin",
+ &add_coin_recoup },
+ [TALER_EXCHANGEDB_TT_RECOUP_REFRESH] =
+ { "recoup_refresh::NEW",
+ "recoup_by_refreshed_coin",
+ &add_coin_recoup_refresh },
+ [TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER] =
+ { "recoup_refresh::OLD",
+ "recoup_by_old_coin",
+ &add_old_coin_recoup },
+ [TALER_EXCHANGEDB_TT_RESERVE_OPEN] =
+ { "reserves_open_deposits",
+ "reserve_open_by_coin",
+ &add_coin_reserve_open },
+ { NULL, NULL, NULL }
+ };
+ char *table_name;
+ uint64_t serial_id;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("table_name",
+ &table_name),
+ GNUNET_PQ_result_spec_uint64 ("serial_id",
+ &serial_id),
+ GNUNET_PQ_result_spec_uint64 ("coin_history_serial_id",
+ &chc->chid),
+ GNUNET_PQ_result_spec_end
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (chc->coin_pub),
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ enum GNUNET_DB_QueryStatus qs;
+ bool found = false;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ chc->failed = true;
+ return;
+ }
+
+ for (unsigned int s = 0;
+ NULL != work[s].statement;
+ s++)
+ {
+ if (0 != strcmp (table_name,
+ work[s].table))
+ continue;
+ found = true;
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ work[s].statement,
+ params,
+ work[s].cb,
+ chc);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Coin %s had %d transactions at %llu in table %s\n",
+ TALER_B2S (chc->coin_pub),
+ (int) qs,
+ (unsigned long long) serial_id,
+ table_name);
+ if (0 > qs)
+ chc->failed = true;
+ break;
+ }
+ if (! found)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Coin history includes unsupported table `%s`\n",
+ table_name);
+ chc->failed = true;
+ }
+ GNUNET_PQ_cleanup_result (rs);
+ if (chc->failed)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_coin_transactions (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ bool begin_transaction,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ uint64_t start_off,
+ uint64_t etag_in,
+ uint64_t *etag_out,
+ struct TALER_Amount *balance,
+ struct TALER_DenominationHashP *h_denom_pub,
+ struct TALER_EXCHANGEDB_TransactionList **tlp)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam lparams[] = {
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_uint64 (&start_off),
+ GNUNET_PQ_query_param_end
+ };
+ struct CoinHistoryContext chc = {
+ .head = NULL,
+ .coin_pub = coin_pub,
+ .pg = pg
+ };
+
+ *tlp = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Getting transactions for coin %s\n",
+ TALER_B2S (coin_pub));
+ PREPARE (pg,
+ "get_coin_history_etag_balance",
+ "SELECT"
+ " ch.coin_history_serial_id"
+ ",kc.remaining"
+ ",denom.denom_pub_hash"
+ " FROM coin_history ch"
+ " JOIN known_coins kc"
+ " USING (coin_pub)"
+ " JOIN denominations denom"
+ " USING (denominations_serial)"
+ " WHERE coin_pub=$1"
+ " ORDER BY coin_history_serial_id DESC"
+ " LIMIT 1;");
+ PREPARE (pg,
+ "get_coin_history",
+ "SELECT"
+ " table_name"
+ ",serial_id"
+ ",coin_history_serial_id"
+ " FROM coin_history"
+ " WHERE coin_pub=$1"
+ " AND coin_history_serial_id > $2"
+ " ORDER BY coin_history_serial_id DESC;");
+ PREPARE (pg,
+ "get_deposit_with_coin_pub",
+ "SELECT"
+ " cdep.amount_with_fee"
+ ",denoms.fee_deposit"
+ ",denoms.denom_pub_hash"
+ ",kc.age_commitment_hash"
+ ",bdep.wallet_timestamp"
+ ",bdep.refund_deadline"
+ ",bdep.wire_deadline"
+ ",bdep.merchant_pub"
+ ",bdep.h_contract_terms"
+ ",bdep.wallet_data_hash"
+ ",bdep.wire_salt"
+ ",wt.payto_uri"
+ ",cdep.coin_sig"
+ ",cdep.coin_deposit_serial_id"
+ ",bdep.done"
+ " FROM coin_deposits cdep"
+ " JOIN batch_deposits bdep"
+ " USING (batch_deposit_serial_id)"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " JOIN known_coins kc"
+ " ON (kc.coin_pub = cdep.coin_pub)"
+ " JOIN denominations denoms"
+ " USING (denominations_serial)"
+ " WHERE cdep.coin_pub=$1"
+ " AND cdep.coin_deposit_serial_id=$2;");
+ PREPARE (pg,
+ "get_refresh_by_coin",
+ "SELECT"
+ " rc"
+ ",refresh_seed"
+ ",blinding_seed"
+ ",old_coin_sig"
+ ",amount_with_fee"
+ ",denoms.denom_pub_hash"
+ ",denoms.fee_refresh"
+ ",kc.age_commitment_hash"
+ ",refresh_id"
+ " FROM refresh"
+ " JOIN known_coins kc"
+ " ON (refresh.old_coin_pub = kc.coin_pub)"
+ " JOIN denominations denoms"
+ " USING (denominations_serial)"
+ " WHERE old_coin_pub=$1"
+ " AND refresh_id=$2;");
+ PREPARE (pg,
+ "get_purse_deposit_by_coin_pub",
+ "SELECT"
+ " partner_base_url"
+ ",pd.amount_with_fee"
+ ",denoms.fee_deposit"
+ ",denoms.denom_pub_hash"
+ ",pd.purse_pub"
+ ",kc.age_commitment_hash"
+ ",pd.coin_sig"
+ ",pd.purse_deposit_serial_id"
+ ",pdes.refunded"
+ " FROM purse_deposits pd"
+ " LEFT JOIN partners"
+ " USING (partner_serial_id)"
+ " JOIN purse_requests pr"
+ " USING (purse_pub)"
+ " LEFT JOIN purse_decision pdes"
+ " USING (purse_pub)"
+ " JOIN known_coins kc"
+ " ON (pd.coin_pub = kc.coin_pub)"
+ " JOIN denominations denoms"
+ " USING (denominations_serial)"
+ " WHERE pd.purse_deposit_serial_id=$2"
+ " AND pd.coin_pub=$1;");
+ PREPARE (pg,
+ "get_purse_decision_by_coin_pub",
+ "SELECT"
+ " pdes.purse_pub"
+ ",pd.amount_with_fee"
+ ",denom.fee_refund"
+ ",pdes.purse_decision_serial_id"
+ " FROM purse_decision pdes"
+ " JOIN purse_deposits pd"
+ " USING (purse_pub)"
+ " JOIN known_coins kc"
+ " ON (pd.coin_pub = kc.coin_pub)"
+ " JOIN denominations denom"
+ " USING (denominations_serial)"
+ " WHERE pd.coin_pub=$1"
+ " AND pdes.purse_decision_serial_id=$2"
+ " AND pdes.refunded;");
+ PREPARE (pg,
+ "get_refunds_by_coin",
+ "SELECT"
+ " bdep.merchant_pub"
+ ",ref.merchant_sig"
+ ",bdep.h_contract_terms"
+ ",ref.rtransaction_id"
+ ",ref.amount_with_fee"
+ ",denom.fee_refund"
+ ",ref.refund_serial_id"
+ " FROM refunds ref"
+ " JOIN coin_deposits cdep"
+ " ON (ref.coin_pub = cdep.coin_pub AND ref.batch_deposit_serial_id = cdep.batch_deposit_serial_id)"
+ " JOIN batch_deposits bdep"
+ " ON (ref.batch_deposit_serial_id = bdep.batch_deposit_serial_id)"
+ " JOIN known_coins kc"
+ " ON (ref.coin_pub = kc.coin_pub)"
+ " JOIN denominations denom"
+ " USING (denominations_serial)"
+ " WHERE ref.coin_pub=$1"
+ " AND ref.refund_serial_id=$2;");
+ PREPARE (pg,
+ "recoup_by_old_coin",
+ "SELECT"
+ " coins.coin_pub"
+ ",rr.coin_sig"
+ ",rr.coin_blind"
+ ",rr.amount"
+ ",rr.recoup_timestamp"
+ ",denoms.denom_pub_hash"
+ ",coins.denom_sig"
+ ",rr.recoup_refresh_uuid"
+ " FROM recoup_refresh rr"
+ " JOIN known_coins coins"
+ " USING (coin_pub)"
+ " JOIN denominations denoms"
+ " USING (denominations_serial)"
+ " WHERE recoup_refresh_uuid=$2"
+ " AND refresh_id IN"
+ " (SELECT refresh_id"
+ " FROM refresh"
+ " WHERE refresh.old_coin_pub=$1);");
+ PREPARE (pg,
+ "recoup_by_coin",
+ "SELECT"
+ " res.reserve_pub"
+ ",denoms.denom_pub_hash"
+ ",rcp.coin_sig"
+ ",rcp.coin_blind"
+ ",rcp.amount"
+ ",rcp.recoup_timestamp"
+ ",rcp.recoup_uuid"
+ " FROM recoup rcp"
+ " JOIN withdraw ro"
+ " USING (withdraw_id)"
+ " JOIN reserves res"
+ " USING (reserve_pub)"
+ " JOIN known_coins coins"
+ " USING (coin_pub)"
+ " JOIN denominations denoms"
+ " ON (denoms.denominations_serial = coins.denominations_serial)"
+ " WHERE rcp.recoup_uuid=$2"
+ " AND coins.coin_pub=$1;");
+ /* Used to obtain recoup transactions
+ for a refreshed coin */
+ PREPARE (pg,
+ "recoup_by_refreshed_coin",
+ "SELECT"
+ " old_coins.coin_pub AS old_coin_pub"
+ ",rr.coin_sig"
+ ",rr.coin_blind"
+ ",rr.amount"
+ ",rr.recoup_timestamp"
+ ",denoms.denom_pub_hash"
+ ",coins.denom_sig"
+ ",recoup_refresh_uuid"
+ " FROM recoup_refresh rr"
+ " JOIN refresh rfc"
+ " ON (rr.refresh_id = rfc.refresh_id)"
+ " JOIN known_coins old_coins"
+ " ON (rfc.old_coin_pub = old_coins.coin_pub)"
+ " JOIN known_coins coins"
+ " ON (rr.coin_pub = coins.coin_pub)"
+ " JOIN denominations denoms"
+ " ON (denoms.denominations_serial = coins.denominations_serial)"
+ " WHERE rr.recoup_refresh_uuid=$2"
+ " AND coins.coin_pub=$1;");
+ PREPARE (pg,
+ "reserve_open_by_coin",
+ "SELECT"
+ " reserve_open_deposit_uuid"
+ ",coin_sig"
+ ",reserve_sig"
+ ",contribution"
+ " FROM reserves_open_deposits"
+ " WHERE coin_pub=$1"
+ " AND reserve_open_deposit_uuid=$2;");
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ " --- landed here 1\n");
+ for (unsigned int i = 0; i<RETRIES; i++)
+ {
+ enum GNUNET_DB_QueryStatus qs;
+ uint64_t end;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("coin_history_serial_id",
+ &end),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ h_denom_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("remaining",
+ balance),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (begin_transaction)
+ {
+ if (GNUNET_OK !=
+ TALER_TALER_EXCHANGEDB_start_read_committed (pg,
+ "get-coin-transactions"))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ }
+ /* First only check the last item, to see if
+ we even need to iterate */
+ qs = GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "get_coin_history_etag_balance",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ if (begin_transaction)
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ if (begin_transaction)
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ if (begin_transaction)
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ *etag_out = end;
+ if (end == etag_in)
+ return qs;
+ }
+ /* We indeed need to iterate over the history */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Current ETag for coin %s is %llu\n",
+ TALER_B2S (coin_pub),
+ (unsigned long long) end);
+
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "get_coin_history",
+ lparams,
+ &handle_history_entry,
+ &chc);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ if (begin_transaction)
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ if (begin_transaction)
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ default:
+ break;
+ }
+ if (chc.failed)
+ {
+ if (begin_transaction)
+ TALER_EXCHANGEDB_rollback (pg);
+ TALER_EXCHANGEDB_free_coin_transaction_list (chc.head);
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+ }
+ if (! begin_transaction)
+ {
+ *tlp = chc.head;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ qs = TALER_EXCHANGEDB_commit (pg);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ TALER_EXCHANGEDB_free_coin_transaction_list (chc.head);
+ chc.head = NULL;
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TALER_EXCHANGEDB_free_coin_transaction_list (chc.head);
+ chc.head = NULL;
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ *tlp = chc.head;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ " --- landed here 2\n");
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+}
diff --git a/src/exchangedb/get_denomination_by_serial.c b/src/exchangedb/get_denomination_by_serial.c
@@ -0,0 +1,87 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_denomination_by_serial.c
+ * @brief Implementation of the get_denomination_by_serial function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_denomination_by_serial.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_denomination_by_serial (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t denom_serial,
+ struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&denom_serial),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &issue->signature),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &issue->denom_hash),
+ GNUNET_PQ_result_spec_timestamp ("valid_from",
+ &issue->start),
+ GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
+ &issue->expire_withdraw),
+ GNUNET_PQ_result_spec_timestamp ("expire_deposit",
+ &issue->expire_deposit),
+ GNUNET_PQ_result_spec_timestamp ("expire_legal",
+ &issue->expire_legal),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+ &issue->value),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+ &issue->fees.withdraw),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &issue->fees.deposit),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+ &issue->fees.refresh),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+ &issue->fees.refund),
+ GNUNET_PQ_result_spec_uint32 ("age_mask",
+ &issue->age_mask.bits),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "denomination_get_by_serial",
+ "SELECT"
+ " master_sig"
+ ",denom_pub_hash"
+ ",valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin" /* value of this denom */
+ ",fee_withdraw"
+ ",fee_deposit"
+ ",fee_refresh"
+ ",fee_refund"
+ ",age_mask"
+ " FROM denominations"
+ " WHERE denominations_serial=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "denomination_get_by_serial",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_denomination_info.c b/src/exchangedb/get_denomination_info.c
@@ -0,0 +1,96 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022,2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_denomination_info.c
+ * @brief Implementation of the get_denomination_info function for Postgres
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_denomination_info.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_denomination_info (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ uint64_t *denom_serial,
+ struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ uint64_t serial;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("denominations_serial",
+ &serial),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &issue->signature),
+ GNUNET_PQ_result_spec_timestamp ("valid_from",
+ &issue->start),
+ GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
+ &issue->expire_withdraw),
+ GNUNET_PQ_result_spec_timestamp ("expire_deposit",
+ &issue->expire_deposit),
+ GNUNET_PQ_result_spec_timestamp ("expire_legal",
+ &issue->expire_legal),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+ &issue->value),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+ &issue->fees.withdraw),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &issue->fees.deposit),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+ &issue->fees.refresh),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+ &issue->fees.refund),
+ GNUNET_PQ_result_spec_uint32 ("age_mask",
+ &issue->age_mask.bits),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "denomination_get",
+ "SELECT"
+ " denominations_serial"
+ ",master_sig"
+ ",valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin" /* value of this denom */
+ ",fee_withdraw"
+ ",fee_deposit"
+ ",fee_refresh"
+ ",fee_refund"
+ ",age_mask"
+ " FROM denominations"
+ " WHERE denom_pub_hash=$1;");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "denomination_get",
+ params,
+ rs);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ return qs;
+ issue->denom_hash = *denom_pub_hash;
+ if (NULL != denom_serial)
+ *denom_serial = serial;
+ return qs;
+}
diff --git a/src/exchangedb/get_denomination_revocation.c b/src/exchangedb/get_denomination_revocation.c
@@ -0,0 +1,59 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_denomination_revocation.c
+ * @brief Implementation of the get_denomination_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_denomination_revocation.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_denomination_revocation (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ struct TALER_MasterSignatureP *master_sig,
+ uint64_t *rowid)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ master_sig),
+ GNUNET_PQ_result_spec_uint64 ("denom_revocations_serial_id",
+ rowid),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "denomination_revocation_get",
+ "SELECT"
+ " master_sig"
+ ",denom_revocations_serial_id"
+ " FROM denomination_revocations"
+ " WHERE denominations_serial="
+ " (SELECT denominations_serial"
+ " FROM denominations"
+ " WHERE denom_pub_hash=$1);");
+
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "denomination_revocation_get",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_drain_profit.c b/src/exchangedb/get_drain_profit.c
@@ -0,0 +1,72 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_drain_profit.c
+ * @brief Implementation of the get_drain_profit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_drain_profit.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_drain_profit (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ uint64_t *serial,
+ char **account_section,
+ struct TALER_FullPayto *payto_uri,
+ struct GNUNET_TIME_Timestamp *request_timestamp,
+ struct TALER_Amount *amount,
+ struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("profit_drain_serial_id",
+ serial),
+ GNUNET_PQ_result_spec_string ("account_section",
+ account_section),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri->full_payto),
+ GNUNET_PQ_result_spec_timestamp ("trigger_date",
+ request_timestamp),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ amount),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_profit_drain",
+ "SELECT"
+ " profit_drain_serial_id"
+ ",account_section"
+ ",payto_uri"
+ ",trigger_date"
+ ",amount"
+ ",master_sig"
+ " FROM profit_drains"
+ " WHERE wtid=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_profit_drain",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_expired_reserves.c b/src/exchangedb/get_expired_reserves.c
@@ -0,0 +1,169 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file get_expired_reserves.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_expired_reserves.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #reserve_expired_cb().
+ */
+struct ExpiredReserveContext
+{
+ /**
+ * Function to call for each expired reserve.
+ */
+ TALER_EXCHANGEDB_ReserveExpiredCallback rec;
+
+ /**
+ * Closure to give to @e rec.
+ */
+ void *rec_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on error.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_expired_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ExpiredReserveContext *erc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = erc->pg;
+ enum GNUNET_GenericReturnValue ret = GNUNET_OK;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_TIME_Timestamp exp_date;
+ struct TALER_FullPayto account_details;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_Amount remaining_balance;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ &exp_date),
+ GNUNET_PQ_result_spec_string ("account_details",
+ &account_details.full_payto),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ TALER_PQ_result_spec_amount ("current_balance",
+ pg->currency,
+ &remaining_balance),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ret = GNUNET_SYSERR;
+ break;
+ }
+ ret = erc->rec (erc->rec_cls,
+ &reserve_pub,
+ &remaining_balance,
+ account_details,
+ exp_date,
+ 0);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+ erc->status = ret;
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_expired_reserves (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct GNUNET_TIME_Timestamp now,
+ TALER_EXCHANGEDB_ReserveExpiredCallback rec,
+ void *rec_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_end
+ };
+ struct ExpiredReserveContext ectx = {
+ .rec = rec,
+ .rec_cls = rec_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "get_expired_reserves",
+ "WITH ed AS MATERIALIZED ( "
+ " SELECT expiration_date"
+ " ,wire_source_h_payto"
+ " ,current_balance"
+ " ,r.reserve_pub"
+ " FROM reserves r"
+ " JOIN reserves_in"
+ " USING (reserve_pub)"
+ " WHERE expiration_date <= $1 "
+ " AND ((current_balance).val != 0 OR (current_balance).frac != 0) "
+ " ORDER BY expiration_date ASC "
+ " LIMIT 1 "
+ ") "
+ "SELECT"
+ " wt.payto_uri AS account_details"
+ " ,ed.expiration_date"
+ " ,ed.reserve_pub"
+ " ,ed.current_balance"
+ " FROM wire_targets wt"
+ " JOIN ed"
+ " ON (ed.wire_source_h_payto=wt.wire_target_h_payto);");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "get_expired_reserves",
+ params,
+ &reserve_expired_cb,
+ &ectx);
+ switch (ectx.status)
+ {
+ case GNUNET_SYSERR:
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ case GNUNET_NO:
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+ case GNUNET_OK:
+ break;
+ }
+ return qs;
+}
diff --git a/src/exchangedb/get_extension_manifest.c b/src/exchangedb/get_extension_manifest.c
@@ -0,0 +1,64 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_extension_manifest.c
+ * @brief Implementation of the get_extension_manifest function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_extension_manifest.h"
+#include "helper.h"
+
+/**
+ * Function called to get the manifest of an extension
+ * (age-restriction, policy_extension_...)
+ *
+ * @param pg the database context
+ * @param extension_name the name of the extension
+ * @param[out] manifest JSON object of the manifest as string
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_extension_manifest (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *extension_name,
+ char **manifest)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (extension_name),
+ GNUNET_PQ_query_param_end
+ };
+ bool is_null;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("manifest",
+ manifest),
+ &is_null),
+ GNUNET_PQ_result_spec_end
+ };
+
+ *manifest = NULL;
+ PREPARE (pg,
+ "get_extension_manifest",
+ "SELECT"
+ " manifest"
+ " FROM extensions"
+ " WHERE name=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_extension_manifest",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_global_fee.c b/src/exchangedb/get_global_fee.c
@@ -0,0 +1,85 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_global_fee.c
+ * @brief Implementation of the get_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_global_fee.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct GNUNET_TIME_Timestamp date,
+ struct GNUNET_TIME_Timestamp *start_date,
+ struct GNUNET_TIME_Timestamp *end_date,
+ struct TALER_GlobalFeeSet *fees,
+ struct GNUNET_TIME_Relative *purse_timeout,
+ struct GNUNET_TIME_Relative *history_expiration
+ ,
+ uint32_t *purse_account_limit,
+ struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&date),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("start_date",
+ start_date),
+ GNUNET_PQ_result_spec_timestamp ("end_date",
+ end_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
+ &fees->history),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
+ &fees->account),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
+ &fees->purse),
+ GNUNET_PQ_result_spec_relative_time ("purse_timeout",
+ purse_timeout),
+ GNUNET_PQ_result_spec_relative_time ("history_expiration",
+ history_expiration),
+ GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
+ purse_account_limit),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_global_fee",
+ "SELECT "
+ " start_date"
+ ",end_date"
+ ",history_fee"
+ ",account_fee"
+ ",purse_fee"
+ ",purse_timeout"
+ ",history_expiration"
+ ",purse_account_limit"
+ ",master_sig"
+ " FROM global_fee"
+ " WHERE start_date <= $1"
+ " AND end_date > $1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_global_fee",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_global_fees.c b/src/exchangedb/get_global_fees.c
@@ -0,0 +1,164 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_global_fees.c
+ * @brief Implementation of the get_global_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_global_fees.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #global_fees_cb().
+ */
+struct GlobalFeeContext
+{
+ /**
+ * Function to call for each global fee block.
+ */
+ TALER_EXCHANGEDB_GlobalFeeCallback cb;
+
+ /**
+ * Closure to give to @e rec.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on error.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+global_fees_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GlobalFeeContext *gctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = gctx->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_GlobalFeeSet fees;
+ struct GNUNET_TIME_Relative purse_timeout;
+ struct GNUNET_TIME_Relative history_expiration;
+ uint32_t purse_account_limit;
+ struct GNUNET_TIME_Timestamp start_date;
+ struct GNUNET_TIME_Timestamp end_date;
+ struct TALER_MasterSignatureP master_sig;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("start_date",
+ &start_date),
+ GNUNET_PQ_result_spec_timestamp ("end_date",
+ &end_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
+ &fees.history),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
+ &fees.account),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
+ &fees.purse),
+ GNUNET_PQ_result_spec_relative_time ("purse_timeout",
+ &purse_timeout),
+ GNUNET_PQ_result_spec_relative_time ("history_expiration",
+ &history_expiration),
+ GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
+ &purse_account_limit),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ gctx->status = GNUNET_SYSERR;
+ break;
+ }
+ gctx->cb (gctx->cb_cls,
+ &fees,
+ purse_timeout,
+ history_expiration,
+ purse_account_limit,
+ start_date,
+ end_date,
+ &master_sig);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_get_global_fees (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ TALER_EXCHANGEDB_GlobalFeeCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_TIME_Timestamp date
+ = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_subtract (
+ GNUNET_TIME_absolute_get (),
+ GNUNET_TIME_UNIT_YEARS));
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&date),
+ GNUNET_PQ_query_param_end
+ };
+ struct GlobalFeeContext gctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+
+ PREPARE (pg,
+ "get_global_fees",
+ "SELECT "
+ " start_date"
+ ",end_date"
+ ",history_fee"
+ ",account_fee"
+ ",purse_fee"
+ ",purse_timeout"
+ ",history_expiration"
+ ",purse_account_limit"
+ ",master_sig"
+ " FROM global_fee"
+ " WHERE start_date >= $1");
+ return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "get_global_fees",
+ params,
+ &global_fees_cb,
+ &gctx);
+}
diff --git a/src/exchangedb/get_known_coin.c b/src/exchangedb/get_known_coin.c
@@ -0,0 +1,64 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_known_coin.c
+ * @brief Implementation of the get_known_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_known_coin.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_known_coin (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinSpendPublicKeyP *
+ coin_pub,
+ struct TALER_CoinPublicInfo *coin_info)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &coin_info->denom_pub_hash),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &coin_info->h_age_commitment),
+ &coin_info->no_age_commitment),
+ TALER_PQ_result_spec_denom_sig ("denom_sig",
+ &coin_info->denom_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting known coin data for coin %s\n",
+ TALER_B2S (coin_pub));
+ coin_info->coin_pub = *coin_pub;
+ PREPARE (pg,
+ "get_known_coin",
+ "SELECT"
+ " denominations.denom_pub_hash"
+ ",age_commitment_hash"
+ ",denom_sig"
+ " FROM known_coins"
+ " JOIN denominations USING (denominations_serial)"
+ " WHERE coin_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_known_coin",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_kyc_rules.c b/src/exchangedb/get_kyc_rules.c
@@ -0,0 +1,124 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_kyc_rules.c
+ * @brief Implementation of the get_kyc_rules function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_kyc_rules.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_kyc_rules (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ bool *no_account_pub,
+ union TALER_AccountPublicKeyP *account_pub,
+ bool *no_reserve_pub,
+ struct TALER_ReservePublicKeyP *reserve_pub,
+ json_t **jrules)
+{
+ struct GNUNET_TIME_Timestamp now
+ = GNUNET_TIME_timestamp_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_timestamp (&now),
+ NULL != merchant_pub
+ ? GNUNET_PQ_query_param_auto_from_type (merchant_pub)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("target_pub",
+ account_pub),
+ no_account_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ reserve_pub),
+ no_reserve_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json ("jnew_rules",
+ jrules),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+
+ *jrules = NULL;
+ *no_account_pub = true;
+ *no_reserve_pub = true;
+ memset (account_pub,
+ 0,
+ sizeof (*account_pub));
+ memset (reserve_pub,
+ 0,
+ sizeof (*reserve_pub));
+ PREPARE (pg,
+ "get_kyc_rules",
+ "SELECT"
+ " out_target_pub AS target_pub"
+ " ,out_jnew_rules::TEXT AS jnew_rules"
+ " ,out_reserve_pub AS reserve_pub"
+ " FROM exchange_do_get_kyc_rules ($1,$2,$3);");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "get_kyc_rules",
+ params,
+ rs);
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_get_kyc_rules2 (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ json_t **jrules)
+{
+ struct GNUNET_TIME_Timestamp now
+ = GNUNET_TIME_timestamp_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json ("jnew_rules",
+ jrules),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+
+ *jrules = NULL;
+ PREPARE (pg,
+ "get_kyc_rules2",
+ "SELECT"
+ " jnew_rules::TEXT"
+ " FROM legitimization_outcomes"
+ " WHERE h_payto=$1"
+ " AND expiration_time >= $2"
+ " AND is_active"
+ " ORDER BY expiration_time DESC"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "get_kyc_rules2",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_old_coin_by_h_blind.c b/src/exchangedb/get_old_coin_by_h_blind.c
@@ -0,0 +1,60 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_old_coin_by_h_blind.c
+ * @brief Implementation of the get_old_coin_by_h_blind function for Postgres
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_old_coin_by_h_blind.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_old_coin_by_h_blind (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_BlindedCoinHashP *h_blind_ev,
+ struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+ uint64_t *refresh_id)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_blind_ev),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+ old_coin_pub),
+ GNUNET_PQ_result_spec_uint64 ("refresh_id",
+ refresh_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ /* Used in #postgres_get_old_coin_by_h_blind() */
+ PREPARE (pg,
+ "old_coin_by_h_blind",
+ "SELECT"
+ " okc.coin_pub AS old_coin_pub"
+ ",refresh_id"
+ " FROM refresh "
+ " JOIN known_coins okc ON (refresh.old_coin_pub = okc.coin_pub)"
+ " WHERE $1=ANY(h_blind_evs)"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "old_coin_by_h_blind",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_pending_kyc_requirement_process.c b/src/exchangedb/get_pending_kyc_requirement_process.c
@@ -0,0 +1,62 @@
+/*
+ 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_pending_kyc_requirement_process.c
+ * @brief Implementation of the get_pending_kyc_requirement_process function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_pending_kyc_requirement_process.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_pending_kyc_requirement_process (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const char *provider_name,
+ char **redirect_url)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (provider_name),
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("redirect_url",
+ redirect_url),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+
+ *redirect_url = NULL;
+ PREPARE (pg,
+ "get_pending_kyc_requirement_process",
+ "SELECT"
+ " redirect_url"
+ " FROM legitimization_processes"
+ " WHERE provider_name=$1"
+ " AND h_payto=$2"
+ " AND NOT finished"
+ " ORDER BY start_time DESC"
+ " LIMIT 1");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "get_pending_kyc_requirement_process",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_policy_details.c b/src/exchangedb/get_policy_details.c
@@ -0,0 +1,60 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_policy_details.c
+ * @brief Implementation of the get_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_policy_details.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_policy_details (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct GNUNET_HashCode *hc,
+ struct TALER_PolicyDetails *details)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (hc),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("deadline",
+ &details->deadline),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("commitment",
+ &details->commitment),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
+ &details->accumulated_total),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee",
+ &details->policy_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount",
+ &details->transferable_amount),
+ GNUNET_PQ_result_spec_auto_from_type ("state",
+ &details->fulfillment_state),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id",
+ &details->policy_fulfillment_id),
+ &details->no_policy_fulfillment_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_policy_details",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_purse_deposit.c b/src/exchangedb/get_purse_deposit.c
@@ -0,0 +1,80 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_purse_deposit.c
+ * @brief Implementation of the get_purse_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_purse_deposit.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_purse_deposit (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ struct TALER_Amount *amount,
+ struct TALER_DenominationHashP *h_denom_pub,
+ struct TALER_AgeCommitmentHashP *phac,
+ struct TALER_CoinSpendSignatureP *coin_sig,
+ char **partner_url)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_end
+ };
+ bool is_null;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ h_denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ phac),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ coin_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ amount),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("partner_base_url",
+ partner_url),
+ &is_null),
+ GNUNET_PQ_result_spec_end
+ };
+
+ *partner_url = NULL;
+ PREPARE (pg,
+ "select_purse_deposit_by_coin_pub",
+ "SELECT "
+ " coin_sig"
+ ",amount_with_fee"
+ ",denom_pub_hash"
+ ",age_commitment_hash"
+ ",partner_base_url"
+ " FROM purse_deposits"
+ " LEFT JOIN partners"
+ " USING (partner_serial_id)"
+ " JOIN known_coins kc"
+ " USING (coin_pub)"
+ " JOIN denominations"
+ " USING (denominations_serial)"
+ " WHERE purse_pub=$1"
+ " AND coin_pub=$2;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "select_purse_deposit_by_coin_pub",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_purse_request.c b/src/exchangedb/get_purse_request.c
@@ -0,0 +1,75 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/template.c
+ * @brief Implementation of the template function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_purse_request.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_purse_request (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ struct TALER_PurseMergePublicKeyP *merge_pub,
+ struct GNUNET_TIME_Timestamp *purse_expiration,
+ struct TALER_PrivateContractHashP *h_contract_terms,
+ uint32_t *age_limit,
+ struct TALER_Amount *target_amount,
+ struct TALER_Amount *balance,
+ struct TALER_PurseContractSignatureP *purse_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("merge_pub",
+ merge_pub),
+ GNUNET_PQ_result_spec_timestamp ("purse_expiration",
+ purse_expiration),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ h_contract_terms),
+ GNUNET_PQ_result_spec_uint32 ("age_limit",
+ age_limit),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ target_amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ balance),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
+ purse_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_purse_request",
+ "SELECT "
+ " merge_pub"
+ ",purse_expiration"
+ ",h_contract_terms"
+ ",age_limit"
+ ",amount_with_fee"
+ ",balance"
+ ",purse_sig"
+ " FROM purse_requests"
+ " WHERE purse_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_purse_request",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_ready_deposit.c b/src/exchangedb/get_ready_deposit.c
@@ -0,0 +1,78 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_ready_deposit.c
+ * @brief Implementation of the get_ready_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_ready_deposit.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_ready_deposit (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t start_shard_row,
+ uint64_t end_shard_row,
+ struct TALER_MerchantPublicKeyP *
+ merchant_pub,
+ struct TALER_FullPayto *payto_uri,
+ char **extra_wire_subject_metadata)
+{
+ struct GNUNET_TIME_Absolute now
+ = GNUNET_TIME_absolute_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_uint64 (&start_shard_row),
+ GNUNET_PQ_query_param_uint64 (&end_shard_row),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+ merchant_pub),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri->full_payto),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("extra_wire_subject_metadata",
+ extra_wire_subject_metadata),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+ const char *query = "deposits_get_ready";
+
+ *extra_wire_subject_metadata = NULL;
+ PREPARE (pg,
+ query,
+ "SELECT"
+ " wts.payto_uri"
+ ",bdep.merchant_pub"
+ ",bdep.extra_wire_subject_metadata"
+ " FROM batch_deposits bdep"
+ " JOIN wire_targets wts"
+ " USING (wire_target_h_payto)"
+ " WHERE NOT (bdep.done OR bdep.policy_blocked)"
+ " AND bdep.wire_deadline<=$1"
+ " AND bdep.shard >= $2"
+ " AND bdep.shard <= $3"
+ " ORDER BY "
+ " bdep.wire_deadline ASC"
+ " ,bdep.shard ASC"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ query,
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_refresh.c b/src/exchangedb/get_refresh.c
@@ -0,0 +1,205 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_refresh.c
+ * @brief Implementation of the get_refresh function for Postgres
+ * @author get_refresh
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_refresh.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_RefreshCommitmentP *rc,
+ struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh
+ )
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (rc),
+ GNUNET_PQ_query_param_end
+ };
+ bool no_cs_r_values;
+ bool no_cs_r_choices;
+ bool no_transfer_pubs;
+ size_t num_denom_sigs;
+ size_t num_transfer_pubs;
+ struct TALER_BlindedDenominationSignature *denom_sigs = NULL;
+ struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values = NULL;
+ struct TALER_TransferPublicKeyP *transfer_pubs = NULL;
+ uint64_t *denom_serials = NULL;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &refresh->amount_with_fee),
+ GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+ &refresh->coin.coin_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &refresh->coin.h_age_commitment),
+ &refresh->coin.no_age_commitment),
+ GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
+ &refresh->coin_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("refresh_seed",
+ &refresh->refresh_seed),
+ GNUNET_PQ_result_spec_uint32 ("noreveal_index",
+ &refresh->noreveal_index),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
+ &refresh->blinding_seed),
+ &refresh->no_blinding_seed),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_array_cs_r_pub (pg->conn,
+ "cs_r_values",
+ &refresh->num_cs_r_values,
+ &cs_r_values),
+ &no_cs_r_values),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("cs_r_choices",
+ &refresh->cs_r_choices),
+ &no_cs_r_choices),
+ GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
+ &refresh->planchets_h),
+ GNUNET_PQ_result_spec_auto_from_type ("selected_h",
+ &refresh->selected_h),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_array_fixed_size (pg->conn,
+ "transfer_pubs",
+ sizeof(*transfer_pubs),
+ &num_transfer_pubs,
+ (void **) &transfer_pubs),
+ &no_transfer_pubs),
+ GNUNET_PQ_result_spec_array_uint64 (pg->conn,
+ "denom_serials",
+ &refresh->num_coins,
+ &denom_serials),
+ TALER_PQ_result_spec_array_blinded_denom_sig (pg->conn,
+ "denom_sigs",
+ &num_denom_sigs,
+ &denom_sigs),
+ GNUNET_PQ_result_spec_bool ("revealed",
+ &refresh->revealed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ memset (&refresh->coin.denom_sig,
+ 0,
+ sizeof (refresh->coin.denom_sig));
+ PREPARE (pg,
+ "get_refresh",
+ "SELECT"
+ " amount_with_fee"
+ ",old_coin_pub"
+ ",kc.age_commitment_hash AS age_commitment_hash"
+ ",old_coin_sig"
+ ",refresh_seed"
+ ",noreveal_index"
+ ",blinding_seed"
+ ",cs_r_values"
+ ",cs_r_choices"
+ ",planchets_h"
+ ",transfer_pubs"
+ ",selected_h"
+ ",denom_serials"
+ ",denom_sigs"
+ ",revealed"
+ " FROM refresh"
+ " JOIN known_coins kc"
+ " ON (old_coin_pub = kc.coin_pub)"
+ " WHERE rc = $1;"
+ );
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_refresh",
+ params,
+ rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ GNUNET_PQ_cleanup_result (rs);
+ return qs;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ GNUNET_PQ_cleanup_result (rs);
+ return qs;
+ }
+ if (refresh->num_coins != num_denom_sigs)
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "got inconsistent number of entries in refresh from DB: "
+ "num_coins=%ld, num_denom_sigs=%ld\n",
+ refresh->num_coins,
+ num_denom_sigs);
+ GNUNET_PQ_cleanup_result (rs);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (no_transfer_pubs)
+ {
+ refresh->is_v27_refresh = true;
+ refresh->transfer_pubs = NULL;
+ }
+ else
+ {
+ if (num_transfer_pubs != refresh->num_coins)
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "got inconsistent number of transfer_pubs in refresh from DB: "
+ "num_coins=%ld, num_transfer_pubs=%ld\n",
+ refresh->num_coins,
+ num_transfer_pubs);
+ GNUNET_PQ_cleanup_result (rs);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ refresh->is_v27_refresh = false;
+ refresh->transfer_pubs = transfer_pubs;
+ }
+ if (refresh->no_blinding_seed != no_cs_r_values)
+ {
+ GNUNET_break (0);
+ GNUNET_PQ_cleanup_result (rs);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (no_cs_r_choices != no_cs_r_values)
+ {
+ GNUNET_break (0);
+ GNUNET_PQ_cleanup_result (rs);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (no_cs_r_values)
+ {
+ refresh->cs_r_values = NULL;
+ refresh->num_cs_r_values = 0;
+ }
+ if (refresh->coin.no_age_commitment)
+ memset (&refresh->coin.h_age_commitment,
+ 0,
+ sizeof(refresh->coin.h_age_commitment));
+ refresh->rc = *rc;
+ /* move the result arrays */
+ refresh->denom_sigs = denom_sigs;
+ refresh->denom_serials = denom_serials;
+ refresh->cs_r_values = cs_r_values;
+ transfer_pubs = NULL;
+ denom_sigs = NULL;
+ denom_serials = NULL;
+ cs_r_values = NULL;
+ GNUNET_PQ_cleanup_result (rs);
+ return qs;
+}
diff --git a/src/exchangedb/get_reserve_balance.c b/src/exchangedb/get_reserve_balance.c
@@ -0,0 +1,65 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_reserve_balance.c
+ * @brief Implementation of the get_reserve_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_reserve_balance.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_reserve_balance (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ struct TALER_Amount *balance,
+ struct TALER_FullPayto *origin_account)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_amount ("current_balance",
+ pg->currency,
+ balance),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &origin_account->full_payto),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+
+ origin_account->full_payto = NULL;
+ PREPARE (pg,
+ "get_reserve_balance",
+ "SELECT"
+ " r.current_balance"
+ " ,wt.payto_uri"
+ " FROM reserves r"
+ " LEFT JOIN reserves_in ri"
+ " USING (reserve_pub)"
+ " LEFT JOIN wire_targets wt"
+ " ON (wt.wire_target_h_payto = ri.wire_source_h_payto)"
+ " WHERE r.reserve_pub=$1"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_reserve_balance",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_reserve_by_h_planchets.c b/src/exchangedb/get_reserve_by_h_planchets.c
@@ -0,0 +1,58 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022,2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_reserve_by_h_planchets.c
+ * @brief Implementation of the get_reserve_by_h_planchets function for Postgres
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_reserve_by_h_planchets.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_reserve_by_h_planchets (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_HashBlindedPlanchetsP *h_planchets,
+ struct TALER_ReservePublicKeyP *reserve_pub,
+ uint64_t *withdraw_serial_id)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_planchets),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ reserve_pub),
+ GNUNET_PQ_result_spec_uint64 ("withdraw_id",
+ withdraw_serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+ /* Used in #postgres_get_reserve_by_h_planchets() */
+ PREPARE (pg,
+ "reserve_by_h_planchets",
+ "SELECT"
+ " reserve_pub"
+ ",withdraw_id"
+ " FROM withdraw"
+ " WHERE planchets_h=$1"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "reserve_by_h_planchets",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_reserve_history.c b/src/exchangedb/get_reserve_history.c
@@ -0,0 +1,994 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file get_reserve_history.c
+ * @brief Obtain (parts of) the history of a reserve.
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_reserve_history.h"
+#include "taler/exchange-database/start_read_committed.h"
+#include "taler/exchange-database/commit.h"
+#include "taler/exchange-database/rollback.h"
+#include "helper.h"
+
+/**
+ * How often do we re-try when encountering DB serialization issues?
+ * (We are read-only, so can only happen due to concurrent insert,
+ * which should be very rare.)
+ */
+#define RETRIES 3
+
+
+/**
+ * Closure for callbacks invoked via #TALER_EXCHANGEDB_get_reserve_history().
+ */
+struct ReserveHistoryContext
+{
+
+ /**
+ * Which reserve are we building the history for?
+ */
+ const struct TALER_ReservePublicKeyP *reserve_pub;
+
+ /**
+ * Where we build the history.
+ */
+ struct TALER_EXCHANGEDB_ReserveHistory *rh;
+
+ /**
+ * Tail of @e rh list.
+ */
+ struct TALER_EXCHANGEDB_ReserveHistory *rh_tail;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Sum of all credit transactions.
+ */
+ struct TALER_Amount balance_in;
+
+ /**
+ * Sum of all debit transactions.
+ */
+ struct TALER_Amount balance_out;
+
+ /**
+ * Current reserve_history_serial_id being processed,
+ * set before each sub-table callback.
+ */
+ uint64_t current_history_offset;
+
+ /**
+ * Set to true on serious internal errors during
+ * the callbacks.
+ */
+ bool failed;
+};
+
+
+/**
+ * Append and return a fresh element to the reserve
+ * history kept in @a rhc.
+ *
+ * @param rhc where the history is kept
+ * @return the fresh element that was added
+ */
+static struct TALER_EXCHANGEDB_ReserveHistory *
+append_rh (struct ReserveHistoryContext *rhc)
+{
+ struct TALER_EXCHANGEDB_ReserveHistory *tail;
+
+ tail = GNUNET_new (struct TALER_EXCHANGEDB_ReserveHistory);
+ tail->history_offset = rhc->current_history_offset;
+ if (NULL != rhc->rh_tail)
+ {
+ rhc->rh_tail->next = tail;
+ rhc->rh_tail = tail;
+ }
+ else
+ {
+ rhc->rh_tail = tail;
+ rhc->rh = tail;
+ }
+ return tail;
+}
+
+
+/**
+ * Add bank transfers to result set for #TALER_EXCHANGEDB_get_reserve_history.
+ *
+ * @param cls a `struct ReserveHistoryContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+add_bank_to_exchange (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
+
+ while (0 < num_results)
+ {
+ struct TALER_EXCHANGEDB_BankTransfer *bt;
+ struct TALER_EXCHANGEDB_ReserveHistory *tail;
+
+ bt = GNUNET_new (struct TALER_EXCHANGEDB_BankTransfer);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("wire_reference",
+ &bt->wire_reference),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
+ &bt->amount),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ &bt->execution_date),
+ GNUNET_PQ_result_spec_string ("sender_account_details",
+ &bt->sender_account_details.full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ --num_results))
+ {
+ GNUNET_break (0);
+ GNUNET_free (bt);
+ rhc->failed = true;
+ return;
+ }
+ }
+ GNUNET_assert (0 <=
+ TALER_amount_add (&rhc->balance_in,
+ &rhc->balance_in,
+ &bt->amount));
+ bt->reserve_pub = *rhc->reserve_pub;
+ tail = append_rh (rhc);
+ tail->type = TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE;
+ tail->details.bank = bt;
+ } /* end of 'while (0 < rows)' */
+}
+
+
+/**
+ * Add coin withdrawals to result set for #TALER_EXCHANGEDB_get_reserve_history.
+ *
+ * @param cls a `struct ReserveHistoryContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+add_withdraw (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
+
+ while (0 < num_results)
+ {
+ struct TALER_EXCHANGEDB_Withdraw *wd;
+ struct TALER_EXCHANGEDB_ReserveHistory *tail;
+
+ wd = GNUNET_new (struct TALER_EXCHANGEDB_Withdraw);
+ {
+ bool no_noreveal_index;
+ bool no_max_age;
+ bool no_selected_h;
+ size_t num_denom_hs;
+ size_t num_denom_serials;
+ uint64_t *my_denom_serials = NULL;
+ struct TALER_DenominationHashP *my_denom_pub_hashes = NULL;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
+ &wd->planchets_h),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ &wd->reserve_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &wd->amount_with_fee),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint16 ("max_age",
+ &wd->max_age),
+ &no_max_age),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint16 ("noreveal_index",
+ &wd->noreveal_index),
+ &no_noreveal_index),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
+ &wd->blinding_seed),
+ &wd->no_blinding_seed),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("selected_h",
+ &wd->selected_h),
+ &no_selected_h),
+ TALER_PQ_result_spec_array_denom_hash (pg->conn,
+ "denom_pub_hashes",
+ &num_denom_hs,
+ &my_denom_pub_hashes),
+ GNUNET_PQ_result_spec_array_uint64 (pg->conn,
+ "denom_serials",
+ &num_denom_serials,
+ &my_denom_serials),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ --num_results))
+ {
+ GNUNET_break (0);
+ GNUNET_free (wd);
+ rhc->failed = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+
+ if (num_denom_hs != num_denom_serials)
+ {
+ GNUNET_break (0);
+ GNUNET_free (wd);
+ rhc->failed = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+
+ if ((no_noreveal_index != no_max_age) ||
+ (no_noreveal_index != no_selected_h))
+ {
+ GNUNET_break (0);
+ GNUNET_free (wd);
+ rhc->failed = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ wd->age_proof_required = ! no_max_age;
+ wd->num_coins = num_denom_serials;
+ wd->reserve_pub = *rhc->reserve_pub;
+ wd->denom_serials = my_denom_serials;
+ wd->denom_pub_hashes = my_denom_pub_hashes;
+ /* prevent cleanup from destroying our actual result */
+ my_denom_serials = NULL;
+ my_denom_pub_hashes = NULL;
+ GNUNET_PQ_cleanup_result (rs);
+ }
+
+ tail = append_rh (rhc);
+ tail->type = TALER_EXCHANGEDB_RO_WITHDRAW_COINS;
+ tail->details.withdraw = wd;
+ }
+}
+
+
+/**
+ * Add recoups to result set for #TALER_EXCHANGEDB_get_reserve_history.
+ *
+ * @param cls a `struct ReserveHistoryContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+add_recoup (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
+
+ while (0 < num_results)
+ {
+ struct TALER_EXCHANGEDB_Recoup *recoup;
+ struct TALER_EXCHANGEDB_ReserveHistory *tail;
+
+ recoup = GNUNET_new (struct TALER_EXCHANGEDB_Recoup);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &recoup->value),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &recoup->coin.coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+ &recoup->coin_blind),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &recoup->coin_sig),
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ &recoup->timestamp),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &recoup->coin.denom_pub_hash),
+ TALER_PQ_result_spec_denom_sig (
+ "denom_sig",
+ &recoup->coin.denom_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ --num_results))
+ {
+ GNUNET_break (0);
+ GNUNET_free (recoup);
+ rhc->failed = true;
+ return;
+ }
+ }
+ GNUNET_assert (0 <=
+ TALER_amount_add (&rhc->balance_in,
+ &rhc->balance_in,
+ &recoup->value));
+ recoup->reserve_pub = *rhc->reserve_pub;
+ tail = append_rh (rhc);
+ tail->type = TALER_EXCHANGEDB_RO_RECOUP_COIN;
+ tail->details.recoup = recoup;
+ } /* end of 'while (0 < rows)' */
+}
+
+
+/**
+ * Add exchange-to-bank transfers to result set for
+ * #TALER_EXCHANGEDB_get_reserve_history.
+ *
+ * @param cls a `struct ReserveHistoryContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+add_exchange_to_bank (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
+
+ while (0 < num_results)
+ {
+ struct TALER_EXCHANGEDB_ClosingTransfer *closing;
+ struct TALER_EXCHANGEDB_ReserveHistory *tail;
+
+ closing = GNUNET_new (struct TALER_EXCHANGEDB_ClosingTransfer);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &closing->amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
+ &closing->closing_fee),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ &closing->execution_date),
+ GNUNET_PQ_result_spec_string ("receiver_account",
+ &closing->receiver_account_details.
+ full_payto),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid",
+ &closing->wtid),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ --num_results))
+ {
+ GNUNET_break (0);
+ GNUNET_free (closing);
+ rhc->failed = true;
+ return;
+ }
+ }
+ GNUNET_assert (0 <=
+ TALER_amount_add (&rhc->balance_out,
+ &rhc->balance_out,
+ &closing->amount));
+ closing->reserve_pub = *rhc->reserve_pub;
+ tail = append_rh (rhc);
+ tail->type = TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK;
+ tail->details.closing = closing;
+ } /* end of 'while (0 < rows)' */
+}
+
+
+/**
+ * Add purse merge transfers to result set for
+ * #TALER_EXCHANGEDB_get_reserve_history.
+ *
+ * @param cls a `struct ReserveHistoryContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+add_p2p_merge (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
+
+ while (0 < num_results)
+ {
+ struct TALER_EXCHANGEDB_PurseMerge *merge;
+ struct TALER_EXCHANGEDB_ReserveHistory *tail;
+
+ merge = GNUNET_new (struct TALER_EXCHANGEDB_PurseMerge);
+ {
+ uint32_t flags32;
+ struct TALER_Amount balance;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
+ &merge->purse_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ &balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &merge->amount_with_fee),
+ GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
+ &merge->merge_timestamp),
+ GNUNET_PQ_result_spec_timestamp ("purse_expiration",
+ &merge->purse_expiration),
+ GNUNET_PQ_result_spec_uint32 ("age_limit",
+ &merge->min_age),
+ GNUNET_PQ_result_spec_uint32 ("flags",
+ &flags32),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &merge->h_contract_terms),
+ GNUNET_PQ_result_spec_auto_from_type ("merge_pub",
+ &merge->merge_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &merge->purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ &merge->reserve_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ --num_results))
+ {
+ GNUNET_break (0);
+ GNUNET_free (merge);
+ rhc->failed = true;
+ return;
+ }
+ merge->flags = (enum TALER_WalletAccountMergeFlags) flags32;
+ if ( (! GNUNET_TIME_absolute_is_future (
+ merge->merge_timestamp.abs_time)) &&
+ (-1 != TALER_amount_cmp (&balance,
+ &merge->amount_with_fee)) )
+ merge->merged = true;
+ }
+ if (merge->merged)
+ GNUNET_assert (0 <=
+ TALER_amount_add (&rhc->balance_in,
+ &rhc->balance_in,
+ &merge->amount_with_fee));
+ GNUNET_assert (0 <=
+ TALER_amount_add (&rhc->balance_out,
+ &rhc->balance_out,
+ &merge->purse_fee));
+ merge->reserve_pub = *rhc->reserve_pub;
+ tail = append_rh (rhc);
+ tail->type = TALER_EXCHANGEDB_RO_PURSE_MERGE;
+ tail->details.merge = merge;
+ }
+}
+
+
+/**
+ * Add paid for history requests to result set for
+ * #TALER_EXCHANGEDB_get_reserve_history.
+ *
+ * @param cls a `struct ReserveHistoryContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+add_open_requests (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
+
+ while (0 < num_results)
+ {
+ struct TALER_EXCHANGEDB_OpenRequest *orq;
+ struct TALER_EXCHANGEDB_ReserveHistory *tail;
+
+ orq = GNUNET_new (struct TALER_EXCHANGEDB_OpenRequest);
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("open_fee",
+ &orq->open_fee),
+ GNUNET_PQ_result_spec_timestamp ("request_timestamp",
+ &orq->request_timestamp),
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ &orq->reserve_expiration),
+ GNUNET_PQ_result_spec_uint32 ("requested_purse_limit",
+ &orq->purse_limit),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ &orq->reserve_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ --num_results))
+ {
+ GNUNET_break (0);
+ GNUNET_free (orq);
+ rhc->failed = true;
+ return;
+ }
+ }
+ GNUNET_assert (0 <=
+ TALER_amount_add (&rhc->balance_out,
+ &rhc->balance_out,
+ &orq->open_fee));
+ orq->reserve_pub = *rhc->reserve_pub;
+ tail = append_rh (rhc);
+ tail->type = TALER_EXCHANGEDB_RO_OPEN_REQUEST;
+ tail->details.open_request = orq;
+ }
+}
+
+
+/**
+ * Add paid for history requests to result set for
+ * #TALER_EXCHANGEDB_get_reserve_history.
+ *
+ * @param cls a `struct ReserveHistoryContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+add_close_requests (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+
+ while (0 < num_results)
+ {
+ struct TALER_EXCHANGEDB_CloseRequest *crq;
+ struct TALER_EXCHANGEDB_ReserveHistory *tail;
+
+ crq = GNUNET_new (struct TALER_EXCHANGEDB_CloseRequest);
+ {
+ struct TALER_FullPayto payto_uri;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("close_timestamp",
+ &crq->request_timestamp),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri.full_payto),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ &crq->reserve_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ --num_results))
+ {
+ GNUNET_break (0);
+ GNUNET_free (crq);
+ rhc->failed = true;
+ return;
+ }
+ TALER_full_payto_hash (payto_uri,
+ &crq->target_account_h_payto);
+ GNUNET_free (payto_uri.full_payto);
+ }
+ crq->reserve_pub = *rhc->reserve_pub;
+ tail = append_rh (rhc);
+ tail->type = TALER_EXCHANGEDB_RO_CLOSE_REQUEST;
+ tail->details.close_request = crq;
+ }
+}
+
+
+/**
+ * Add reserve history entries found.
+ *
+ * @param cls a `struct ReserveHistoryContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+handle_history_entry (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ static const struct
+ {
+ /**
+ * Table with reserve history entry we are responsible for.
+ */
+ const char *table;
+ /**
+ * Name of the prepared statement to run.
+ */
+ const char *statement;
+ /**
+ * Function to use to process the results.
+ */
+ GNUNET_PQ_PostgresResultHandler cb;
+ } work[] = {
+ /** #TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE */
+ { "reserves_in",
+ "reserves_in_get_transactions",
+ add_bank_to_exchange },
+ /** #TALER_EXCHANGEDB_RO_WITHDRAW_COINS */
+ { "withdraw",
+ "get_withdraw_details",
+ &add_withdraw },
+ /** #TALER_EXCHANGEDB_RO_RECOUP_COIN */
+ { "recoup",
+ "recoup_by_reserve",
+ &add_recoup },
+ /** #TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK */
+ { "reserves_close",
+ "close_by_reserve",
+ &add_exchange_to_bank },
+ /** #TALER_EXCHANGEDB_RO_PURSE_MERGE */
+ { "purse_decision",
+ "merge_by_reserve",
+ &add_p2p_merge },
+ /** #TALER_EXCHANGEDB_RO_OPEN_REQUEST */
+ { "reserves_open_requests",
+ "open_request_by_reserve",
+ &add_open_requests },
+ /** #TALER_EXCHANGEDB_RO_CLOSE_REQUEST */
+ { "close_requests",
+ "close_request_by_reserve",
+ &add_close_requests },
+ /* List terminator */
+ { NULL, NULL, NULL }
+ };
+ struct ReserveHistoryContext *rhc = cls;
+ char *table_name;
+ uint64_t serial_id;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("table_name",
+ &table_name),
+ GNUNET_PQ_result_spec_uint64 ("serial_id",
+ &serial_id),
+ GNUNET_PQ_result_spec_uint64 ("reserve_history_serial_id",
+ &rhc->current_history_offset),
+ GNUNET_PQ_result_spec_end
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (rhc->reserve_pub),
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ while (0 < num_results--)
+ {
+ enum GNUNET_DB_QueryStatus qs;
+ bool found = false;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ num_results))
+ {
+ GNUNET_break (0);
+ rhc->failed = true;
+ return;
+ }
+
+ for (unsigned int i = 0;
+ NULL != work[i].cb;
+ i++)
+ {
+ if (0 != strcmp (table_name,
+ work[i].table))
+ continue;
+ found = true;
+ qs = GNUNET_PQ_eval_prepared_multi_select (rhc->pg->conn,
+ work[i].statement,
+ params,
+ work[i].cb,
+ rhc);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Reserve %s had %d transactions at %llu in table %s\n",
+ TALER_B2S (rhc->reserve_pub),
+ (int) qs,
+ (unsigned long long) serial_id,
+ table_name);
+ if (0 >= qs)
+ rhc->failed = true;
+ break;
+ }
+ if (! found)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Reserve history includes unsupported table `%s`\n",
+ table_name);
+ rhc->failed = true;
+ }
+ GNUNET_PQ_cleanup_result (rs);
+ if (rhc->failed)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_reserve_history (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ uint64_t start_off,
+ uint64_t etag_in,
+ uint64_t *etag_out,
+ struct TALER_Amount *balance,
+ struct TALER_EXCHANGEDB_ReserveHistory **rhp)
+{
+ struct ReserveHistoryContext rhc = {
+ .pg = pg,
+ .reserve_pub = reserve_pub
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_QueryParam lparams[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_uint64 (&start_off),
+ GNUNET_PQ_query_param_end
+ };
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pg->currency,
+ &rhc.balance_in));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (pg->currency,
+ &rhc.balance_out));
+
+ *rhp = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting transactions for reserve %s\n",
+ TALER_B2S (reserve_pub));
+ PREPARE (pg,
+ "get_reserve_history_etag",
+ "SELECT"
+ " his.reserve_history_serial_id"
+ ",r.current_balance"
+ " FROM reserve_history his"
+ " JOIN reserves r USING (reserve_pub)"
+ " WHERE his.reserve_pub=$1"
+ " ORDER BY reserve_history_serial_id DESC"
+ " LIMIT 1;");
+ PREPARE (pg,
+ "get_reserve_history",
+ "SELECT"
+ " table_name"
+ ",serial_id"
+ ",reserve_history_serial_id"
+ " FROM reserve_history"
+ " WHERE reserve_pub=$1"
+ " AND reserve_history_serial_id > $2"
+ " ORDER BY reserve_history_serial_id DESC;");
+ PREPARE (pg,
+ "reserves_in_get_transactions",
+ "SELECT"
+ " ri.wire_reference"
+ ",ri.credit"
+ ",ri.execution_date"
+ ",wt.payto_uri AS sender_account_details"
+ " FROM reserves_in ri"
+ " JOIN wire_targets wt"
+ " ON (wire_source_h_payto = wire_target_h_payto)"
+ " WHERE ri.reserve_pub=$1"
+ " AND ri.reserve_in_serial_id=$2;");
+ PREPARE (pg,
+ "get_withdraw_details",
+ "SELECT"
+ " planchets_h"
+ ",amount_with_fee"
+ ",reserve_sig"
+ ",max_age"
+ ",noreveal_index"
+ ",selected_h"
+ ",blinding_seed"
+ ",denom_serials"
+ ",ARRAY("
+ " SELECT denominations.denom_pub_hash FROM ("
+ " SELECT UNNEST(denom_serials) AS id,"
+ " generate_subscripts(denom_serials, 1) AS nr" /* for order */
+ " ) AS denoms"
+ " LEFT JOIN denominations ON denominations.denominations_serial=denoms.id"
+ ") AS denom_pub_hashes"
+ " FROM withdraw "
+ " WHERE withdraw_id=$2"
+ " AND reserve_pub=$1;");
+ PREPARE (pg,
+ "recoup_by_reserve",
+ "SELECT"
+ " rec.coin_pub"
+ ",rec.coin_sig"
+ ",rec.coin_blind"
+ ",rec.amount"
+ ",rec.recoup_timestamp"
+ ",denom.denom_pub_hash"
+ ",kc.denom_sig"
+ " FROM recoup rec"
+ " JOIN withdraw ro"
+ " USING (withdraw_id)"
+ " JOIN reserves res"
+ " USING (reserve_pub)"
+ " JOIN known_coins kc"
+ " USING (coin_pub)"
+ " JOIN denominations denom"
+ " ON (denom.denominations_serial = kc.denominations_serial)"
+ " WHERE rec.recoup_uuid=$2"
+ " AND res.reserve_pub=$1;");
+ PREPARE (pg,
+ "close_by_reserve",
+ "SELECT"
+ " rc.amount"
+ ",rc.closing_fee"
+ ",rc.execution_date"
+ ",wt.payto_uri AS receiver_account"
+ ",rc.wtid"
+ " FROM reserves_close rc"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " WHERE reserve_pub=$1"
+ " AND close_uuid=$2;");
+ PREPARE (pg,
+ "merge_by_reserve",
+ "SELECT"
+ " pr.amount_with_fee"
+ ",pr.balance"
+ ",pr.purse_fee"
+ ",pr.h_contract_terms"
+ ",pr.merge_pub"
+ ",am.reserve_sig"
+ ",pm.purse_pub"
+ ",pm.merge_timestamp"
+ ",pr.purse_expiration"
+ ",pr.age_limit"
+ ",pr.flags"
+ " FROM purse_decision pdes"
+ " JOIN purse_requests pr"
+ " ON (pr.purse_pub = pdes.purse_pub)"
+ " JOIN purse_merges pm"
+ " ON (pm.purse_pub = pdes.purse_pub)"
+ " JOIN account_merges am"
+ " ON (am.purse_pub = pm.purse_pub AND"
+ " am.reserve_pub = pm.reserve_pub)"
+ " WHERE pdes.purse_decision_serial_id=$2"
+ " AND pm.reserve_pub=$1"
+ " AND COALESCE(pm.partner_serial_id,0)=0" /* must be local! */
+ " AND NOT pdes.refunded;");
+ PREPARE (pg,
+ "open_request_by_reserve",
+ "SELECT"
+ " reserve_payment"
+ ",request_timestamp"
+ ",expiration_date"
+ ",requested_purse_limit"
+ ",reserve_sig"
+ " FROM reserves_open_requests"
+ " WHERE reserve_pub=$1"
+ " AND open_request_uuid=$2;");
+ PREPARE (pg,
+ "close_request_by_reserve",
+ "SELECT"
+ " close_timestamp"
+ ",payto_uri"
+ ",reserve_sig"
+ " FROM close_requests"
+ " WHERE reserve_pub=$1"
+ " AND close_request_serial_id=$2;");
+
+ for (unsigned int i = 0; i<RETRIES; i++)
+ {
+ enum GNUNET_DB_QueryStatus qs;
+ uint64_t end;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("reserve_history_serial_id",
+ &end),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
+ balance),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ TALER_TALER_EXCHANGEDB_start_read_committed (pg,
+ "get-reserve-transactions")
+ )
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ /* First only check the last item, to see if
+ we even need to iterate */
+ qs = GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "get_reserve_history_etag",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ *etag_out = end;
+ if (end == etag_in)
+ return qs;
+ }
+ /* We indeed need to iterate over the history */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Current ETag for reserve %s is %llu\n",
+ TALER_B2S (reserve_pub),
+ (unsigned long long) end);
+
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "get_reserve_history",
+ lparams,
+ &handle_history_entry,
+ &rhc);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ TALER_EXCHANGEDB_rollback (pg);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TALER_EXCHANGEDB_rollback (pg);
+ continue;
+ default:
+ break;
+ }
+ if (rhc.failed)
+ {
+ TALER_EXCHANGEDB_rollback (pg);
+ TALER_EXCHANGEDB_free_reserve_history (rhc.rh);
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+ }
+ qs = TALER_EXCHANGEDB_commit (pg);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ TALER_EXCHANGEDB_free_reserve_history (rhc.rh);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TALER_EXCHANGEDB_free_reserve_history (rhc.rh);
+ rhc.rh = NULL;
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ *rhp = rhc.rh;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ }
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+}
diff --git a/src/exchangedb/get_signature_for_known_coin.c b/src/exchangedb/get_signature_for_known_coin.c
@@ -0,0 +1,59 @@
+/*
+ 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_signature_for_known_coin.c
+ * @brief Implementation of the get_signature_for_known_coin function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_signature_for_known_coin.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_signature_for_known_coin (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ struct TALER_DenominationPublicKey *denom_pub,
+ struct TALER_DenominationSignature *denom_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ denom_pub),
+ TALER_PQ_result_spec_denom_sig ("denom_sig",
+ denom_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting denomination and signature for (potentially) known coin %s\n",
+ TALER_B2S (coin_pub));
+ PREPARE (pg,
+ "get_signature_for_known_coin",
+ "SELECT"
+ " denominations.denom_pub"
+ ",denom_sig"
+ " FROM known_coins"
+ " JOIN denominations USING (denominations_serial)"
+ " WHERE coin_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_signature_for_known_coin",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_unfinished_close_requests.c b/src/exchangedb/get_unfinished_close_requests.c
@@ -0,0 +1,162 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file get_unfinished_close_requests.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_unfinished_close_requests.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #reserve_close_cb().
+ */
+struct CloseReserveContext
+{
+ /**
+ * Function to call for each to be closed reserve.
+ */
+ TALER_EXCHANGEDB_ReserveExpiredCallback rec;
+
+ /**
+ * Closure to give to @e rec.
+ */
+ void *rec_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on error.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CloseReserveContext *erc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = erc->pg;
+ enum GNUNET_GenericReturnValue ret = GNUNET_OK;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_TIME_Timestamp exp_date;
+ struct TALER_FullPayto account_details;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_Amount remaining_balance;
+ uint64_t close_request_row;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ &exp_date),
+ GNUNET_PQ_result_spec_string ("account_details",
+ &account_details.full_payto),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("close",
+ &remaining_balance),
+ GNUNET_PQ_result_spec_uint64 ("close_request_serial_id",
+ &close_request_row),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ret = GNUNET_SYSERR;
+ break;
+ }
+ ret = erc->rec (erc->rec_cls,
+ &reserve_pub,
+ &remaining_balance,
+ account_details,
+ exp_date,
+ close_request_row);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+ erc->status = ret;
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_unfinished_close_requests (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ TALER_EXCHANGEDB_ReserveExpiredCallback rec,
+ void *rec_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct CloseReserveContext ectx = {
+ .rec = rec,
+ .rec_cls = rec_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "get_unfinished_close_requests",
+ "UPDATE close_requests AS rc"
+ " SET done=TRUE"
+ " WHERE NOT done"
+ " RETURNING"
+ " reserve_pub"
+ " ,close_request_serial_id"
+ " ,close_timestamp AS expiration_date"
+ " ,close"
+ " ,(SELECT payto_uri"
+ " FROM reserves_in ri"
+ " JOIN wire_targets wt"
+ " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)"
+ " WHERE ri.reserve_pub=rc.reserve_pub)"
+ " AS account_details;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "get_unfinished_close_requests",
+ params,
+ &reserve_cb,
+ &ectx);
+ switch (ectx.status)
+ {
+ case GNUNET_SYSERR:
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ case GNUNET_NO:
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+ case GNUNET_OK:
+ break;
+ }
+ return qs;
+}
diff --git a/src/exchangedb/get_wire_accounts.c b/src/exchangedb/get_wire_accounts.c
@@ -0,0 +1,179 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_wire_accounts.c
+ * @brief Implementation of the get_wire_accounts function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_wire_accounts.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #get_wire_accounts_cb().
+ */
+struct GetWireAccountsContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_WireAccountCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Flag set to #GNUNET_OK as long as everything is fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct MissingWireContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_wire_accounts_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GetWireAccountsContext *ctx = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_FullPayto payto_uri;
+ char *conversion_url = NULL;
+ char *open_banking_gateway = NULL;
+ char *wire_transfer_gateway = NULL;
+ json_t *debit_restrictions = NULL;
+ json_t *credit_restrictions = NULL;
+ struct TALER_MasterSignatureP master_sig;
+ char *bank_label = NULL;
+ int64_t priority;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri.full_payto),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("conversion_url",
+ &conversion_url),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("open_banking_gateway",
+ &open_banking_gateway),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("wire_transfer_gateway",
+ &wire_transfer_gateway),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("bank_label",
+ &bank_label),
+ NULL),
+ GNUNET_PQ_result_spec_int64 ("priority",
+ &priority),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json ("debit_restrictions",
+ &debit_restrictions),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json ("credit_restrictions",
+ &credit_restrictions),
+ NULL),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ if (NULL == debit_restrictions)
+ {
+ debit_restrictions = json_array ();
+ GNUNET_assert (NULL != debit_restrictions);
+ }
+ if (NULL == credit_restrictions)
+ {
+ credit_restrictions = json_array ();
+ GNUNET_assert (NULL != credit_restrictions);
+ }
+ ctx->cb (ctx->cb_cls,
+ payto_uri,
+ conversion_url,
+ open_banking_gateway,
+ wire_transfer_gateway,
+ debit_restrictions,
+ credit_restrictions,
+ &master_sig,
+ bank_label,
+ priority);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_wire_accounts (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ TALER_EXCHANGEDB_WireAccountCallback cb,
+ void *cb_cls)
+{
+ struct GetWireAccountsContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .status = GNUNET_OK
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "get_wire_accounts",
+ "SELECT"
+ " payto_uri"
+ ",conversion_url"
+ ",open_banking_gateway"
+ ",wire_transfer_gateway"
+ ",debit_restrictions::TEXT"
+ ",credit_restrictions::TEXT"
+ ",master_sig"
+ ",bank_label"
+ ",priority"
+ " FROM wire_accounts"
+ " WHERE is_active");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "get_wire_accounts",
+ params,
+ &get_wire_accounts_cb,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/get_wire_fee.c b/src/exchangedb/get_wire_fee.c
@@ -0,0 +1,74 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_wire_fee.c
+ * @brief Implementation of the get_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_wire_fee.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_wire_fee (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *type,
+ struct GNUNET_TIME_Timestamp date,
+ uint64_t *rowid,
+ struct GNUNET_TIME_Timestamp *start_date,
+ struct GNUNET_TIME_Timestamp *end_date,
+ struct TALER_WireFeeSet *fees,
+ struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (type),
+ GNUNET_PQ_query_param_timestamp (&date),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("wire_fee_serial",
+ rowid),
+ GNUNET_PQ_result_spec_timestamp ("start_date",
+ start_date),
+ GNUNET_PQ_result_spec_timestamp ("end_date",
+ end_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
+ &fees->wire),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
+ &fees->closing),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_wire_fee",
+ "SELECT"
+ " wire_fee_serial"
+ ",start_date"
+ ",end_date"
+ ",wire_fee"
+ ",closing_fee"
+ ",master_sig"
+ " FROM wire_fee"
+ " WHERE wire_method=$1"
+ " AND start_date <= $2"
+ " AND end_date > $2;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_wire_fee",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_wire_fees.c b/src/exchangedb/get_wire_fees.c
@@ -0,0 +1,144 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_wire_fees.c
+ * @brief Implementation of the get_wire_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_wire_fees.h"
+#include "helper.h"
+
+/**
+ * Closure for #get_wire_fees_cb().
+ */
+struct GetWireFeesContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_WireFeeCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Flag set to #GNUNET_OK as long as everything is fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct GetWireFeesContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_wire_fees_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GetWireFeesContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_MasterSignatureP master_sig;
+ struct TALER_WireFeeSet fees;
+ struct GNUNET_TIME_Timestamp start_date;
+ struct GNUNET_TIME_Timestamp end_date;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
+ &fees.wire),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
+ &fees.closing),
+ GNUNET_PQ_result_spec_timestamp ("start_date",
+ &start_date),
+ GNUNET_PQ_result_spec_timestamp ("end_date",
+ &end_date),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &fees,
+ start_date,
+ end_date,
+ &master_sig);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_get_wire_fees (struct TALER_EXCHANGEDB_PostgresContext *
+ pg,
+ const char *wire_method,
+ TALER_EXCHANGEDB_WireFeeCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (wire_method),
+ GNUNET_PQ_query_param_end
+ };
+ struct GetWireFeesContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "get_wire_fees",
+ "SELECT"
+ " wire_fee"
+ ",closing_fee"
+ ",start_date"
+ ",end_date"
+ ",master_sig"
+ " FROM wire_fee"
+ " WHERE wire_method=$1");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "get_wire_fees",
+ params,
+ &get_wire_fees_cb,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/get_wire_hash_for_contract.c b/src/exchangedb/get_wire_hash_for_contract.c
@@ -0,0 +1,77 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_wire_hash_for_contract.c
+ * @brief Implementation of the get_wire_hash_for_contract function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/taler_exchangedb_lib.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_wire_hash_for_contract.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_wire_hash_for_contract (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ struct TALER_MerchantWireHashP *h_wire)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_end
+ };
+ struct TALER_FullPayto payto_uri;
+ struct TALER_WireSaltP wire_salt;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+ &wire_salt),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri.full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ /* check if the necessary records exist and get them */
+ PREPARE (pg,
+ "get_wire_hash_for_contract",
+ "SELECT"
+ " bdep.wire_salt"
+ " ,wt.payto_uri"
+ " FROM coin_deposits"
+ " JOIN batch_deposits bdep"
+ " USING (batch_deposit_serial_id)"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " WHERE bdep.merchant_pub=$1"
+ " AND bdep.h_contract_terms=$2");
+ /* NOTE: above query might be more efficient if we computed the shard
+ from the merchant_pub and included that in the query */
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_wire_hash_for_contract",
+ params,
+ rs);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ TALER_merchant_wire_signature_hash (payto_uri,
+ &wire_salt,
+ h_wire);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+ return qs;
+}
diff --git a/src/exchangedb/get_withdraw.c b/src/exchangedb/get_withdraw.c
@@ -0,0 +1,191 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/get_withdraw.c
+ * @brief Implementation of the get_withdraw function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/get_withdraw.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_get_withdraw (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_HashBlindedPlanchetsP *wch,
+ struct TALER_EXCHANGEDB_Withdraw *wd)
+{
+ enum GNUNET_DB_QueryStatus ret;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (wch),
+ GNUNET_PQ_query_param_end
+ };
+ struct TALER_BlindedDenominationSignature *my_denom_sigs = NULL;
+ uint64_t *my_denom_serials = NULL;
+ struct GNUNET_CRYPTO_CSPublicRPairP *my_cs_r_values = NULL;
+ size_t num_sigs = 0;
+ size_t num_coins = 0;
+ size_t num_cs_r_values = 0;
+ bool no_noreveal_index;
+ bool no_max_age;
+ bool no_selected_h;
+ bool no_blinding_seed;
+ bool no_cs_r_values;
+ bool no_cs_r_choices;
+
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
+ &wd->planchets_h),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ &wd->reserve_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &wd->reserve_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint16 ("max_age",
+ &wd->max_age),
+ &no_max_age),
+ TALER_PQ_result_spec_amount ("amount_with_fee",
+ pg->currency,
+ &wd->amount_with_fee),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint16 ("noreveal_index",
+ &wd->noreveal_index),
+ &no_noreveal_index),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("selected_h",
+ &wd->selected_h),
+ &no_selected_h),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
+ &wd->blinding_seed),
+ &no_blinding_seed),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_array_cs_r_pub (
+ pg->conn,
+ "cs_r_values",
+ &num_cs_r_values,
+ &my_cs_r_values),
+ &no_cs_r_values),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("cs_r_choices",
+ &wd->cs_r_choices),
+ &no_cs_r_choices),
+ TALER_PQ_result_spec_array_blinded_denom_sig (
+ pg->conn,
+ "denom_sigs",
+ &num_sigs,
+ &my_denom_sigs),
+ GNUNET_PQ_result_spec_array_uint64 (
+ pg->conn,
+ "denom_serials",
+ &num_coins,
+ &my_denom_serials),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_withdraw",
+ "SELECT"
+ " planchets_h"
+ ",blinding_seed"
+ ",reserve_sig"
+ ",reserve_pub"
+ ",max_age"
+ ",amount_with_fee"
+ ",noreveal_index"
+ ",selected_h"
+ ",blinding_seed"
+ ",cs_r_values"
+ ",cs_r_choices"
+ ",denom_sigs"
+ ",denom_serials"
+ " FROM withdraw"
+ " WHERE planchets_h=$1;");
+ ret = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_withdraw",
+ params,
+ rs);
+ if (0 > ret)
+ {
+ GNUNET_break (0);
+ GNUNET_PQ_cleanup_result (rs);
+ return ret;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret)
+ {
+ GNUNET_PQ_cleanup_result (rs);
+ return ret;
+ }
+
+ if ((no_max_age != no_noreveal_index) ||
+ (no_max_age != no_selected_h))
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "got inconsistent state for max_age, noreveal_index and planchets_h in DB: "
+ "no_max_age=%s, no_noreveal_index=%s, no_selected_h=%s\n",
+ no_max_age ? "true" : "false",
+ no_noreveal_index ? "true" : "false",
+ no_selected_h ? "true" : "false");
+ GNUNET_PQ_cleanup_result (rs);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (no_blinding_seed != no_cs_r_values)
+ {
+ GNUNET_break (0);
+ GNUNET_PQ_cleanup_result (rs);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (no_cs_r_choices != no_cs_r_values)
+ {
+ GNUNET_break (0);
+ GNUNET_PQ_cleanup_result (rs);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (num_coins != num_sigs)
+ {
+ GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "got inconsistent number of entries in withdraw from DB: "
+ "num_coins=%ld, num_sigs=%ld\n",
+ num_coins,
+ num_sigs);
+ GNUNET_PQ_cleanup_result (rs);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ wd->age_proof_required = ! no_max_age;
+ if (no_cs_r_values)
+ {
+ wd->cs_r_values = NULL;
+ wd->num_cs_r_values = 0;
+ wd->cs_r_choices = 0;
+ }
+ wd->denom_sigs = my_denom_sigs;
+ wd->num_coins = num_coins;
+ wd->denom_serials = my_denom_serials;
+ wd->cs_r_values = my_cs_r_values;
+ wd->num_cs_r_values = num_cs_r_values;
+ /* ensure cleanup_result does not trash data we care about */
+ my_denom_sigs = NULL;
+ my_denom_serials = NULL;
+ my_cs_r_values = NULL;
+ num_sigs = 0;
+ num_coins = 0;
+ num_cs_r_values = 0;
+ GNUNET_PQ_cleanup_result (rs);
+ return ret;
+}
diff --git a/src/exchangedb/have_deposit2.c b/src/exchangedb/have_deposit2.c
@@ -0,0 +1,113 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/have_deposit2.c
+ * @brief Implementation of the have_deposit2 function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/have_deposit2.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_have_deposit2 (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const struct TALER_MerchantWireHashP *h_wire,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_MerchantPublicKeyP *merchant,
+ struct GNUNET_TIME_Timestamp refund_deadline,
+ struct TALER_Amount *deposit_fee,
+ struct GNUNET_TIME_Timestamp *exchange_timestamp)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_auto_from_type (merchant),
+ GNUNET_PQ_query_param_end
+ };
+ struct TALER_EXCHANGEDB_Deposit deposit2;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &deposit2.amount_with_fee),
+ GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
+ &deposit2.timestamp),
+ GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+ exchange_timestamp),
+ GNUNET_PQ_result_spec_timestamp ("refund_deadline",
+ &deposit2.refund_deadline),
+ GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+ &deposit2.wire_deadline),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ deposit_fee),
+ GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+ &deposit2.wire_salt),
+ GNUNET_PQ_result_spec_string ("receiver_wire_account",
+ &deposit2.receiver_wire_account.full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ struct TALER_MerchantWireHashP h_wire2;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting deposits for coin %s\n",
+ TALER_B2S (coin_pub));
+ PREPARE (pg,
+ "get_deposit",
+ "SELECT"
+ " cdep.amount_with_fee"
+ ",denominations.fee_deposit"
+ ",bdep.wallet_timestamp"
+ ",bdep.exchange_timestamp"
+ ",bdep.refund_deadline"
+ ",bdep.wire_deadline"
+ ",bdep.h_contract_terms"
+ ",bdep.wire_salt"
+ ",wt.payto_uri AS receiver_wire_account"
+ " FROM coin_deposits cdep"
+ " JOIN batch_deposits bdep USING (batch_deposit_serial_id)"
+ " JOIN known_coins kc ON (kc.coin_pub = cdep.coin_pub)"
+ " JOIN denominations USING (denominations_serial)"
+ " JOIN wire_targets wt USING (wire_target_h_payto)"
+ " WHERE cdep.coin_pub=$1"
+ " AND bdep.merchant_pub=$3"
+ " AND bdep.h_contract_terms=$2;");
+ /* Note: query might be made more efficient if we computed the 'shard'
+ from merchant_pub and included that as a constraint on bdep! */
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_deposit",
+ params,
+ rs);
+ if (0 >= qs)
+ return qs;
+ TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account,
+ &deposit2.wire_salt,
+ &h_wire2);
+ GNUNET_free (deposit2.receiver_wire_account.full_payto);
+ /* Now we check that the other information in @a deposit
+ also matches, and if not report inconsistencies. */
+ if ( (GNUNET_TIME_timestamp_cmp (refund_deadline,
+ !=,
+ deposit2.refund_deadline)) ||
+ (0 != GNUNET_memcmp (h_wire,
+ &h_wire2) ) )
+ {
+ /* Inconsistencies detected! Does not match! */
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+}
diff --git a/src/exchangedb/inject_auditor_triggers.c b/src/exchangedb/inject_auditor_triggers.c
@@ -0,0 +1,55 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/inject_auditor_triggers.c
+ * @brief Implementation of the inject_auditor_triggers function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/gc.h"
+#include "helper.h"
+#include "taler/exchange-database/inject_auditor_triggers.h"
+
+
+/**
+ * Function called to inject auditor triggers into the
+ * database, triggering the real-time auditor upon
+ * relevant INSERTs.
+ *
+ * @param pg the database context
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR on DB errors
+ */
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGEDB_inject_auditor_triggers (struct
+ TALER_EXCHANGEDB_PostgresContext *pg)
+{
+ struct GNUNET_PQ_Context *conn;
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+ "exchangedb-postgres",
+ "auditor-triggers-",
+ es,
+ NULL);
+ if (NULL == conn)
+ return GNUNET_SYSERR;
+ GNUNET_PQ_disconnect (conn);
+ return GNUNET_OK;
+}
diff --git a/src/exchangedb/insert_active_legitimization_measure.c b/src/exchangedb/insert_active_legitimization_measure.c
@@ -0,0 +1,58 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_active_legitimization_measure.c
+ * @brief Implementation of the insert_active_legitimization_measure function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_active_legitimization_measure.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_active_legitimization_measure (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AccountAccessTokenP *access_token,
+ const json_t *jmeasures,
+ uint64_t *legitimization_measure_serial_id)
+{
+ struct GNUNET_TIME_Timestamp now
+ = GNUNET_TIME_timestamp_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (access_token),
+ GNUNET_PQ_query_param_timestamp (&now),
+ TALER_PQ_query_param_json (jmeasures),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("out_legitimization_measure_serial_id",
+ legitimization_measure_serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "do_insert_active_legitimization_measure",
+ "SELECT"
+ " out_legitimization_measure_serial_id"
+ " FROM exchange_do_insert_active_legitimization_measure"
+ "($1, $2, $3::TEXT::JSONB);");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "do_insert_active_legitimization_measure",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/insert_aml_decision.c b/src/exchangedb/insert_aml_decision.c
@@ -0,0 +1,185 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2023, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_aml_decision.c
+ * @brief Implementation of the insert_aml_decision function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_aml_decision.h"
+#include "helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_aml_decision (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPayto payto_uri,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Timestamp decision_time,
+ struct GNUNET_TIME_Timestamp expiration_time,
+ const json_t *properties,
+ const json_t *new_rules,
+ bool to_investigate,
+ const char *new_measure_name,
+ const json_t *jmeasures,
+ const char *justification,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ const struct TALER_AmlOfficerSignatureP *decider_sig,
+ size_t num_events,
+ const char *events[static num_events],
+ const char *form_name,
+ size_t enc_attributes_size,
+ const void *enc_attributes,
+ struct GNUNET_HashCode *attributes_hash,
+ struct GNUNET_TIME_Timestamp attributes_expiration_time,
+ bool *invalid_officer,
+ bool *unknown_account,
+ struct GNUNET_TIME_Timestamp *last_date,
+ uint64_t *legitimization_measure_serial_id,
+ bool *is_wallet)
+{
+ struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = *h_payto
+ };
+ struct TALER_FullPaytoHashP h_full_payto;
+ char *notify_s
+ = GNUNET_PQ_get_event_notify_channel (&rep.header);
+ bool account_unknown;
+ struct GNUNET_PQ_QueryParam params[] = {
+ /* $1: in_payto_uri */
+ NULL == payto_uri.full_payto
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (payto_uri.full_payto),
+ /* $2: in_h_normalized_payto */
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ /* $3: in_h_full_payto */
+ NULL == payto_uri.full_payto
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (&h_full_payto),
+ /* $4: in_decision_time */
+ GNUNET_PQ_query_param_timestamp (&decision_time),
+ /* $5: in_expiration_time*/
+ GNUNET_PQ_query_param_timestamp (&expiration_time),
+ /* $6: in_properties */
+ NULL != properties
+ ? TALER_PQ_query_param_json (properties)
+ : GNUNET_PQ_query_param_null (),
+ /* $7: in_kyc_attributes_enc */
+ NULL != enc_attributes
+ ? GNUNET_PQ_query_param_fixed_size (enc_attributes,
+ enc_attributes_size)
+ : GNUNET_PQ_query_param_null (),
+ /* $8: in_kyc_attributes_hash */
+ NULL != attributes_hash
+ ? GNUNET_PQ_query_param_auto_from_type (attributes_hash)
+ : GNUNET_PQ_query_param_null (),
+ /* $9: in_kyc_attributes_expiration */
+ GNUNET_PQ_query_param_timestamp (&attributes_expiration_time),
+ /* $10: in_new_rules */
+ TALER_PQ_query_param_json (new_rules),
+ /* $11: in_to_investigate */
+ GNUNET_PQ_query_param_bool (to_investigate),
+ /* $12: in_new_measure_name */
+ NULL != new_measure_name
+ ? GNUNET_PQ_query_param_string (new_measure_name)
+ : GNUNET_PQ_query_param_null (),
+ /* $13: in_jmeasures */
+ NULL != jmeasures
+ ? TALER_PQ_query_param_json (jmeasures)
+ : GNUNET_PQ_query_param_null (),
+ /* $14: in_justification */
+ NULL != justification
+ ? GNUNET_PQ_query_param_string (justification)
+ : GNUNET_PQ_query_param_null (),
+ /* $15: in_decider_pub */
+ NULL != decider_pub
+ ? GNUNET_PQ_query_param_auto_from_type (decider_pub)
+ : GNUNET_PQ_query_param_null (),
+ /* $16: in_decider_sig */
+ NULL != decider_sig
+ ? GNUNET_PQ_query_param_auto_from_type (decider_sig)
+ : GNUNET_PQ_query_param_null (),
+ /* $17: in_notify_s*/
+ GNUNET_PQ_query_param_string (notify_s),
+ /* $18: ina_events */
+ GNUNET_PQ_query_param_array_ptrs_string (num_events,
+ events,
+ pg->conn),
+ (NULL == form_name)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (form_name),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("out_invalid_officer",
+ invalid_officer),
+ GNUNET_PQ_result_spec_bool ("out_account_unknown",
+ unknown_account),
+ GNUNET_PQ_result_spec_timestamp ("out_last_date",
+ last_date),
+ GNUNET_PQ_result_spec_uint64 ("out_legitimization_measure_serial_id",
+ legitimization_measure_serial_id),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_bool ("out_is_wallet",
+ is_wallet),
+ &account_unknown),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ *is_wallet = false;
+ GNUNET_assert ( ( (NULL == decider_pub) &&
+ (NULL == decider_sig) &&
+ (NULL == justification) ) ||
+ ( (NULL != decider_pub) &&
+ (NULL != decider_sig) &&
+ (NULL != justification) ) );
+
+ if (NULL != payto_uri.full_payto)
+ TALER_full_payto_hash (payto_uri,
+ &h_full_payto);
+ PREPARE (pg,
+ "do_insert_aml_decision",
+ "SELECT"
+ " out_invalid_officer"
+ ",out_account_unknown"
+ ",out_last_date"
+ ",out_legitimization_measure_serial_id"
+ ",out_is_wallet"
+ " FROM exchange_do_insert_aml_decision"
+ "($1,$2,$3,$4,$5,$6::TEXT::JSONB,$7,$8,$9,$10::TEXT::JSONB"
+ ",$11,$12,$13::TEXT::JSONB,$14,$15,$16,$17,$18,$19);");
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Inserting LEGI OUTCOME from AML decision with notification on %s\n",
+ notify_s);
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "do_insert_aml_decision",
+ params,
+ rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ GNUNET_free (notify_s);
+ GNUNET_PQ_event_do_poll (pg->conn);
+ if (qs <= 0)
+ return qs;
+ if (account_unknown)
+ {
+ GNUNET_assert ((*invalid_officer) || (*unknown_account));
+ }
+ return qs;
+}
diff --git a/src/exchangedb/insert_aml_officer.c b/src/exchangedb/insert_aml_officer.c
@@ -0,0 +1,62 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_aml_officer.c
+ * @brief Implementation of the insert_aml_officer function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_aml_officer.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_aml_officer (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ const struct TALER_MasterSignatureP *master_sig,
+ const char *decider_name,
+ bool is_active,
+ bool read_only,
+ struct GNUNET_TIME_Timestamp last_change,
+ struct GNUNET_TIME_Timestamp *previous_change)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (decider_pub),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_string (decider_name),
+ GNUNET_PQ_query_param_bool (is_active),
+ GNUNET_PQ_query_param_bool (read_only),
+ GNUNET_PQ_query_param_timestamp (&last_change),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("out_last_change",
+ previous_change),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "do_insert_aml_staff",
+ "SELECT"
+ " out_last_change"
+ " FROM exchange_do_insert_aml_officer"
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "do_insert_aml_staff",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/insert_aml_program_failure.c b/src/exchangedb/insert_aml_program_failure.c
@@ -0,0 +1,66 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_aml_program_failure.c
+ * @brief Implementation of the insert_aml_program_failure function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_aml_program_failure.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_aml_program_failure (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t process_row,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const char *error_message,
+ enum TALER_ErrorCode ec)
+{
+ uint32_t ec32 = (uint32_t) ec;
+ struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = *h_payto
+ };
+ struct GNUNET_TIME_Timestamp now
+ = GNUNET_TIME_timestamp_get ();
+ char *kyc_completed_notify_s
+ = GNUNET_PQ_get_event_notify_channel (&rep.header);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&process_row),
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_uint32 (&ec32),
+ GNUNET_PQ_query_param_string (error_message),
+ GNUNET_PQ_query_param_string (kyc_completed_notify_s),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "insert_aml_program_failure",
+ "SELECT out_update"
+ " FROM exchange_do_insert_aml_program_failure"
+ " ($1, $2, $3, $4, $5, $6);");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_aml_program_failure",
+ params);
+ GNUNET_free (kyc_completed_notify_s);
+ return qs;
+}
diff --git a/src/exchangedb/insert_auditor.c b/src/exchangedb/insert_auditor.c
@@ -0,0 +1,55 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_auditor.c
+ * @brief Implementation of the insert_auditor function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_auditor.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_auditor (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AuditorPublicKeyP *
+ auditor_pub,
+ const char *auditor_url,
+ const char *auditor_name,
+ struct GNUNET_TIME_Timestamp start_date)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+ GNUNET_PQ_query_param_string (auditor_name),
+ GNUNET_PQ_query_param_string (auditor_url),
+ GNUNET_PQ_query_param_timestamp (&start_date),
+ GNUNET_PQ_query_param_end
+ };
+
+ /* used in #postgres_insert_auditor() */
+ PREPARE (pg,
+ "insert_auditor",
+ "INSERT INTO auditors "
+ "(auditor_pub"
+ ",auditor_name"
+ ",auditor_url"
+ ",is_active"
+ ",last_change"
+ ") VALUES "
+ "($1, $2, $3, true, $4);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_auditor",
+ params);
+}
diff --git a/src/exchangedb/insert_auditor_denom_sig.c b/src/exchangedb/insert_auditor_denom_sig.c
@@ -0,0 +1,58 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_auditor_denom_sig.c
+ * @brief Implementation of the insert_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_auditor_denom_sig.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_insert_auditor_denom_sig (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ const struct TALER_AuditorSignatureP *auditor_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+ GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+ GNUNET_PQ_query_param_auto_from_type (auditor_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_auditor_denom_sig",
+ "WITH ax AS"
+ " (SELECT auditor_uuid"
+ " FROM auditors"
+ " WHERE auditor_pub=$1)"
+ "INSERT INTO auditor_denom_sigs "
+ "(auditor_uuid"
+ ",denominations_serial"
+ ",auditor_sig"
+ ") SELECT ax.auditor_uuid, denominations_serial, $3 "
+ " FROM denominations"
+ " CROSS JOIN ax"
+ " WHERE denom_pub_hash=$2"
+ " ON CONFLICT DO NOTHING;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_auditor_denom_sig",
+ params);
+}
diff --git a/src/exchangedb/insert_close_request.c b/src/exchangedb/insert_close_request.c
@@ -0,0 +1,64 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file insert_close_request.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_close_request.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_close_request (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_FullPayto payto_uri,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ struct GNUNET_TIME_Timestamp request_timestamp,
+ const struct TALER_Amount *balance,
+ const struct TALER_Amount *closing_fee)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_timestamp (&request_timestamp),
+ GNUNET_PQ_query_param_auto_from_type (reserve_sig),
+ TALER_PQ_query_param_amount (pg->conn,
+ balance),
+ TALER_PQ_query_param_amount (pg->conn,
+ closing_fee),
+ GNUNET_PQ_query_param_string (payto_uri.full_payto),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_account_close",
+ "INSERT INTO close_requests"
+ "(reserve_pub"
+ ",close_timestamp"
+ ",reserve_sig"
+ ",close"
+ ",close_fee"
+ ",payto_uri"
+ ")"
+ "VALUES "
+ "($1, $2, $3, $4, $5, $6)"
+ " ON CONFLICT DO NOTHING;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_account_close",
+ params);
+}
diff --git a/src/exchangedb/insert_contract.c b/src/exchangedb/insert_contract.c
@@ -0,0 +1,89 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_contract.c
+ * @brief Implementation of the insert_contract function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_contract.h"
+#include "taler/exchange-database/select_contract_by_purse.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_contract (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_EncryptedContract *econtract,
+ bool *in_conflict)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (&econtract->contract_pub),
+ GNUNET_PQ_query_param_fixed_size (econtract->econtract,
+ econtract->econtract_size),
+ GNUNET_PQ_query_param_auto_from_type (&econtract->econtract_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ *in_conflict = false;
+ /* Used in #postgres_insert_contract() */
+ PREPARE (pg,
+ "insert_contract",
+ "INSERT INTO contracts"
+ " (purse_pub"
+ " ,pub_ckey"
+ " ,e_contract"
+ " ,contract_sig"
+ " ,purse_expiration"
+ " ) SELECT "
+ " $1, $2, $3, $4, purse_expiration"
+ " FROM purse_requests"
+ " WHERE purse_pub=$1"
+ " ON CONFLICT DO NOTHING;");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_contract",
+ params);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
+ return qs;
+ {
+ struct TALER_EncryptedContract econtract2;
+
+ qs = TALER_TALER_EXCHANGEDB_select_contract_by_purse (pg,
+ purse_pub,
+ &econtract2);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if ( (0 == GNUNET_memcmp (&econtract->contract_pub,
+ &econtract2.contract_pub)) &&
+ (econtract2.econtract_size ==
+ econtract->econtract_size) &&
+ (0 == memcmp (econtract2.econtract,
+ econtract->econtract,
+ econtract->econtract_size)) )
+ {
+ GNUNET_free (econtract2.econtract);
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ GNUNET_free (econtract2.econtract);
+ *in_conflict = true;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+}
diff --git a/src/exchangedb/insert_denomination_info.c b/src/exchangedb/insert_denomination_info.c
@@ -0,0 +1,98 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_denomination_info.c
+ * @brief Implementation of the insert_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_denomination_info.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_denomination_info (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
+{
+ struct TALER_DenominationHashP denom_hash;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&issue->denom_hash),
+ TALER_PQ_query_param_denom_pub (denom_pub),
+ GNUNET_PQ_query_param_auto_from_type (&issue->signature),
+ GNUNET_PQ_query_param_timestamp (&issue->start),
+ GNUNET_PQ_query_param_timestamp (&issue->expire_withdraw),
+ GNUNET_PQ_query_param_timestamp (&issue->expire_deposit),
+ GNUNET_PQ_query_param_timestamp (&issue->expire_legal),
+ TALER_PQ_query_param_amount (pg->conn,
+ &issue->value),
+ TALER_PQ_query_param_amount (pg->conn,
+ &issue->fees.withdraw),
+ TALER_PQ_query_param_amount (pg->conn,
+ &issue->fees.deposit),
+ TALER_PQ_query_param_amount (pg->conn,
+ &issue->fees.refresh),
+ TALER_PQ_query_param_amount (pg->conn,
+ &issue->fees.refund),
+ GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.bits),
+ GNUNET_PQ_query_param_end
+ };
+
+ GNUNET_assert (denom_pub->age_mask.bits ==
+ issue->age_mask.bits);
+ TALER_denom_pub_hash (denom_pub,
+ &denom_hash);
+ GNUNET_assert (0 ==
+ GNUNET_memcmp (&denom_hash,
+ &issue->denom_hash));
+ GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
+ issue->start.abs_time));
+ GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
+ issue->expire_withdraw.abs_time));
+ GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
+ issue->expire_deposit.abs_time));
+ GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
+ issue->expire_legal.abs_time));
+ /* check fees match denomination currency */
+ GNUNET_assert (GNUNET_YES ==
+ TALER_denom_fee_check_currency (
+ issue->value.currency,
+ &issue->fees));
+ PREPARE (pg,
+ "denomination_insert",
+ "INSERT INTO denominations "
+ "(denom_pub_hash"
+ ",denom_pub"
+ ",master_sig"
+ ",valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin" /* value of this denom */
+ ",fee_withdraw"
+ ",fee_deposit"
+ ",fee_refresh"
+ ",fee_refund"
+ ",age_mask"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
+ " $11, $12, $13);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "denomination_insert",
+ params);
+}
diff --git a/src/exchangedb/insert_denomination_revocation.c b/src/exchangedb/insert_denomination_revocation.c
@@ -0,0 +1,50 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_denomination_revocation.c
+ * @brief Implementation of the insert_denomination_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_denomination_revocation.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_denomination_revocation (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ const struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ /* Used in #postgres_insert_denomination_revocation() */
+ PREPARE (pg,
+ "denomination_revocation_insert",
+ "INSERT INTO denomination_revocations "
+ "(denominations_serial"
+ ",master_sig"
+ ") SELECT denominations_serial,$2"
+ " FROM denominations"
+ " WHERE denom_pub_hash=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "denomination_revocation_insert",
+ params);
+}
diff --git a/src/exchangedb/insert_drain_profit.c b/src/exchangedb/insert_drain_profit.c
@@ -0,0 +1,60 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_drain_profit.c
+ * @brief Implementation of the insert_drain_profit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_drain_profit.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_drain_profit (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const char *account_section,
+ const struct TALER_FullPayto payto_uri,
+ struct GNUNET_TIME_Timestamp request_timestamp,
+ const struct TALER_Amount *amount,
+ const struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_string (account_section),
+ GNUNET_PQ_query_param_string (payto_uri.full_payto),
+ GNUNET_PQ_query_param_timestamp (&request_timestamp),
+ TALER_PQ_query_param_amount (pg->conn,
+ amount),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "drain_profit_insert",
+ "INSERT INTO profit_drains "
+ "(wtid"
+ ",account_section"
+ ",payto_uri"
+ ",trigger_date"
+ ",amount"
+ ",master_sig"
+ ") VALUES ($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "drain_profit_insert",
+ params);
+}
diff --git a/src/exchangedb/insert_global_fee.c b/src/exchangedb/insert_global_fee.c
@@ -0,0 +1,137 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_global_fee.c
+ * @brief Implementation of the insert_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_global_fee.h"
+#include "helper.h"
+#include "taler/exchange-database/get_global_fee.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct GNUNET_TIME_Timestamp start_date,
+ struct GNUNET_TIME_Timestamp end_date,
+ const struct TALER_GlobalFeeSet *fees,
+ struct GNUNET_TIME_Relative purse_timeout,
+ struct GNUNET_TIME_Relative
+ history_expiration,
+ uint32_t purse_account_limit,
+ const struct TALER_MasterSignatureP *
+ master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&start_date),
+ GNUNET_PQ_query_param_timestamp (&end_date),
+ TALER_PQ_query_param_amount (pg->conn,
+ &fees->history),
+ TALER_PQ_query_param_amount (pg->conn,
+ &fees->account),
+ TALER_PQ_query_param_amount (pg->conn,
+ &fees->purse),
+ GNUNET_PQ_query_param_relative_time (&purse_timeout),
+ GNUNET_PQ_query_param_relative_time (&history_expiration),
+ GNUNET_PQ_query_param_uint32 (&purse_account_limit),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_end
+ };
+ struct TALER_GlobalFeeSet wx;
+ struct TALER_MasterSignatureP sig;
+ struct GNUNET_TIME_Timestamp sd;
+ struct GNUNET_TIME_Timestamp ed;
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_TIME_Relative pt;
+ struct GNUNET_TIME_Relative he;
+ uint32_t pal;
+
+ qs = TALER_EXCHANGEDB_get_global_fee (pg,
+ start_date,
+ &sd,
+ &ed,
+ &wx,
+ &pt,
+ &he,
+ &pal,
+ &sig);
+ if (qs < 0)
+ return qs;
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ if (0 != GNUNET_memcmp (&sig,
+ master_sig))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (0 !=
+ TALER_global_fee_set_cmp (fees,
+ &wx))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if ( (GNUNET_TIME_timestamp_cmp (sd,
+ !=,
+ start_date)) ||
+ (GNUNET_TIME_timestamp_cmp (ed,
+ !=,
+ end_date)) )
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if ( (GNUNET_TIME_relative_cmp (purse_timeout,
+ !=,
+ pt)) ||
+ (GNUNET_TIME_relative_cmp (history_expiration,
+ !=,
+ he)) )
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (purse_account_limit != pal)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ /* equal record already exists */
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+
+ /* Used in #postgres_insert_global_fee */
+ PREPARE (pg,
+ "insert_global_fee",
+ "INSERT INTO global_fee "
+ "(start_date"
+ ",end_date"
+ ",history_fee"
+ ",account_fee"
+ ",purse_fee"
+ ",purse_timeout"
+ ",history_expiration"
+ ",purse_account_limit"
+ ",master_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_global_fee",
+ params);
+}
diff --git a/src/exchangedb/insert_kyc_failure.c b/src/exchangedb/insert_kyc_failure.c
@@ -0,0 +1,90 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_kyc_failure.c
+ * @brief Implementation of the insert_kyc_failure function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h" /* UNNECESSARY? */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h" /* UNNECESSARY? */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_kyc_failure.h"
+#include "helper.h"
+#include "taler/exchange-database/event_notify.h" /* UNNECESSARY? */
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_kyc_failure (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t process_row,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const char *provider_name,
+ const char *provider_account_id,
+ const char *provider_legitimization_id,
+ const char *error_message,
+ enum TALER_ErrorCode ec)
+{
+ uint32_t ec32 = (uint32_t) ec;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&process_row),
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ NULL != provider_name
+ ? GNUNET_PQ_query_param_string (provider_name)
+ : GNUNET_PQ_query_param_null (),
+ NULL != provider_account_id
+ ? GNUNET_PQ_query_param_string (provider_account_id)
+ : GNUNET_PQ_query_param_null (),
+ NULL != provider_legitimization_id
+ ? GNUNET_PQ_query_param_string (provider_legitimization_id)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_uint32 (&ec32),
+ GNUNET_PQ_query_param_string (error_message),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "insert_kyc_failure",
+ "UPDATE legitimization_processes"
+ " SET"
+ " finished=TRUE"
+ " ,provider_user_id=$4"
+ " ,provider_legitimization_id=$5"
+ " ,error_code=$6"
+ " ,error_message=$7"
+ " WHERE h_payto=$2"
+ " AND legitimization_process_serial_id=$1"
+ " AND provider_name=$3;");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_kyc_failure",
+ params);
+ if (qs > 0)
+ {
+ /* FIXME-#9419: might want to do this eventually in the same transaction... */
+ struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = *h_payto
+ };
+
+ TALER_EXCHANGEDB_event_notify (pg,
+ &rep.header,
+ NULL,
+ 0);
+ }
+ return qs;
+}
diff --git a/src/exchangedb/insert_kyc_requirement_process.c b/src/exchangedb/insert_kyc_requirement_process.c
@@ -0,0 +1,85 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_kyc_requirement_process.c
+ * @brief Implementation of the insert_kyc_requirement_process function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_kyc_requirement_process.h"
+#include "helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_kyc_requirement_process (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ uint32_t measure_index,
+ uint64_t legitimization_measure_serial_id,
+ const char *provider_name,
+ const char *provider_account_id,
+ const char *provider_legitimization_id,
+ uint64_t *process_row)
+{
+ struct GNUNET_TIME_Absolute now
+ = GNUNET_TIME_absolute_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_string (provider_name),
+ (NULL != provider_account_id)
+ ? GNUNET_PQ_query_param_string (provider_account_id)
+ : GNUNET_PQ_query_param_null (),
+ (NULL != provider_legitimization_id)
+ ? GNUNET_PQ_query_param_string (provider_legitimization_id)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id),
+ GNUNET_PQ_query_param_uint32 (&measure_index),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("legitimization_process_serial_id",
+ process_row),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "insert_kyc_requirement_process",
+ "INSERT INTO legitimization_processes"
+ " (h_payto"
+ " ,start_time"
+ " ,provider_name"
+ " ,provider_user_id"
+ " ,provider_legitimization_id"
+ " ,legitimization_measure_serial_id"
+ " ,measure_index"
+ " ) VALUES "
+ " ($1, $2, $3, $4, $5, $6, $7)"
+ " ON CONFLICT (legitimization_measure_serial_id,measure_index)"
+ " DO UPDATE"
+ " SET h_payto=$1"
+ " ,start_time=$2"
+ " ,provider_name=$3"
+ " ,provider_user_id=$4"
+ " ,provider_legitimization_id=$5"
+ " RETURNING legitimization_process_serial_id");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "insert_kyc_requirement_process",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/insert_partner.c b/src/exchangedb/insert_partner.c
@@ -0,0 +1,67 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_partner.c
+ * @brief Implementation of the insert_partner function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_partner.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_partner (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_MasterPublicKeyP *master_pub
+ ,
+ struct GNUNET_TIME_Timestamp start_date,
+ struct GNUNET_TIME_Timestamp end_date,
+ struct GNUNET_TIME_Relative wad_frequency,
+ const struct TALER_Amount *wad_fee,
+ const char *partner_base_url,
+ const struct TALER_MasterSignatureP *master_sig
+ )
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (master_pub),
+ GNUNET_PQ_query_param_timestamp (&start_date),
+ GNUNET_PQ_query_param_timestamp (&end_date),
+ GNUNET_PQ_query_param_relative_time (&wad_frequency),
+ TALER_PQ_query_param_amount (pg->conn,
+ wad_fee),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_string (partner_base_url),
+ GNUNET_PQ_query_param_end
+ };
+
+
+ PREPARE (pg,
+ "insert_partner",
+ "INSERT INTO partners"
+ " (partner_master_pub"
+ " ,start_date"
+ " ,end_date"
+ " ,wad_frequency"
+ " ,wad_fee"
+ " ,master_sig"
+ " ,partner_base_url"
+ " ) VALUES "
+ " ($1, $2, $3, $4, $5, $6, $7)"
+ " ON CONFLICT DO NOTHING;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_partner",
+ params);
+}
diff --git a/src/exchangedb/insert_purse_request.c b/src/exchangedb/insert_purse_request.c
@@ -0,0 +1,122 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_purse_request.c
+ * @brief Implementation of the insert_purse_request function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_purse_request.h"
+#include "taler/exchange-database/get_purse_request.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_purse_request (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PurseMergePublicKeyP *merge_pub,
+ struct GNUNET_TIME_Timestamp purse_expiration,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ uint32_t age_limit,
+ enum TALER_WalletAccountMergeFlags flags,
+ const struct TALER_Amount *purse_fee,
+ const struct TALER_Amount *amount,
+ const struct TALER_PurseContractSignatureP *purse_sig,
+ bool *in_conflict)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
+ uint32_t flags32 = (uint32_t) flags;
+ bool in_reserve_quota = (TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA
+ == (flags & TALER_WAMF_MERGE_MODE_MASK));
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (merge_pub),
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_timestamp (&purse_expiration),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_uint32 (&age_limit),
+ GNUNET_PQ_query_param_uint32 (&flags32),
+ GNUNET_PQ_query_param_bool (in_reserve_quota),
+ TALER_PQ_query_param_amount (pg->conn,
+ amount),
+ TALER_PQ_query_param_amount (pg->conn,
+ purse_fee),
+ GNUNET_PQ_query_param_auto_from_type (purse_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ *in_conflict = false;
+ PREPARE (pg,
+ "insert_purse_request",
+ "INSERT INTO purse_requests"
+ " (purse_pub"
+ " ,merge_pub"
+ " ,purse_creation"
+ " ,purse_expiration"
+ " ,h_contract_terms"
+ " ,age_limit"
+ " ,flags"
+ " ,in_reserve_quota"
+ " ,amount_with_fee"
+ " ,purse_fee"
+ " ,purse_sig"
+ " ) VALUES "
+ " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)"
+ " ON CONFLICT DO NOTHING;");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_purse_request",
+ params);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
+ return qs;
+ {
+ struct TALER_PurseMergePublicKeyP merge_pub2;
+ struct GNUNET_TIME_Timestamp purse_expiration2;
+ struct TALER_PrivateContractHashP h_contract_terms2;
+ uint32_t age_limit2;
+ struct TALER_Amount amount2;
+ struct TALER_Amount balance;
+ struct TALER_PurseContractSignatureP purse_sig2;
+
+ qs = TALER_EXCHANGEDB_get_purse_request (pg,
+ purse_pub,
+ &merge_pub2,
+ &purse_expiration2,
+ &h_contract_terms2,
+ &age_limit2,
+ &amount2,
+ &balance,
+ &purse_sig2);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if ( (age_limit2 == age_limit) &&
+ (0 == TALER_amount_cmp (amount,
+ &amount2)) &&
+ (0 == GNUNET_memcmp (&h_contract_terms2,
+ h_contract_terms)) &&
+ (0 == GNUNET_memcmp (&merge_pub2,
+ merge_pub)) )
+ {
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ *in_conflict = true;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+}
diff --git a/src/exchangedb/insert_records_by_table.c b/src/exchangedb/insert_records_by_table.c
@@ -0,0 +1,2453 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2020-2025 Taler Systems SA
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet 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
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file exchangedb/insert_records_by_table.c
+ * @brief replicate_records_by_table implementation
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_records_by_table.h"
+#include "helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+/**
+ * Signature of helper functions of #TALER_EXCHANGEDB_insert_records_by_table().
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ * @return transaction status code
+ */
+typedef enum GNUNET_DB_QueryStatus
+(*InsertRecordCallback)(struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td);
+
+
+/**
+ * Function called with denominations records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_denominations (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct TALER_DenominationHashP denom_hash;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&denom_hash),
+ GNUNET_PQ_query_param_uint32 (
+ &td->details.denominations.denom_type),
+ GNUNET_PQ_query_param_uint32 (
+ &td->details.denominations.age_mask),
+ TALER_PQ_query_param_denom_pub (
+ &td->details.denominations.denom_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.denominations.master_sig),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.denominations.valid_from),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.denominations.expire_withdraw),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.denominations.expire_deposit),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.denominations.expire_legal),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.denominations.coin),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.denominations.fees.withdraw),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.denominations.fees.deposit),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.denominations.fees.refresh),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.denominations.fees.refund),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_denominations",
+ "INSERT INTO denominations"
+ "(denominations_serial"
+ ",denom_pub_hash"
+ ",denom_type"
+ ",age_mask"
+ ",denom_pub"
+ ",master_sig"
+ ",valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin"
+ ",fee_withdraw"
+ ",fee_deposit"
+ ",fee_refresh"
+ ",fee_refund"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
+ " $11, $12, $13, $14, $15);");
+
+ TALER_denom_pub_hash (
+ &td->details.denominations.denom_pub,
+ &denom_hash);
+
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_denominations",
+ params);
+}
+
+
+/**
+ * Function called with denomination_revocations records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_denomination_revocations (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.denomination_revocations.master_sig),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.denomination_revocations.denominations_serial),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_denomination_revocations",
+ "INSERT INTO denomination_revocations"
+ "(denom_revocations_serial_id"
+ ",master_sig"
+ ",denominations_serial"
+ ") VALUES "
+ "($1, $2, $3);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_denomination_revocations",
+ params);
+}
+
+
+/**
+ * Function called with wire target records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wire_targets (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct TALER_NormalizedPaytoHashP normalized_payto_hash;
+ struct TALER_FullPaytoHashP full_payto_hash;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&full_payto_hash),
+ GNUNET_PQ_query_param_auto_from_type (&normalized_payto_hash),
+ GNUNET_PQ_query_param_string (
+ td->details.wire_targets.full_payto_uri.full_payto),
+ GNUNET_PQ_query_param_end
+ };
+
+ TALER_full_payto_hash (
+ td->details.wire_targets.full_payto_uri,
+ &full_payto_hash);
+ TALER_full_payto_normalize_and_hash (
+ td->details.wire_targets.full_payto_uri,
+ &normalized_payto_hash);
+ PREPARE (pg,
+ "insert_into_table_wire_targets",
+ "INSERT INTO wire_targets"
+ "(wire_target_serial_id"
+ ",wire_target_h_payto"
+ ",h_normalized_payto"
+ ",payto_uri"
+ ") VALUES "
+ "($1, $2, $3, $4);");
+ return GNUNET_PQ_eval_prepared_non_select (
+ pg->conn,
+ "insert_into_table_wire_targets",
+ params);
+}
+
+
+/**
+ * Function called with kyc target records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_kyc_targets (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.kyc_targets.h_normalized_payto),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.kyc_targets.access_token),
+ td->details.kyc_targets.no_account
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (
+ &td->details.kyc_targets.target_pub),
+ GNUNET_PQ_query_param_bool (
+ td->details.kyc_targets.is_wallet),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_kyc_targets",
+ "INSERT INTO kyc_targets"
+ "(kyc_target_serial_id"
+ ",h_normalized_payto"
+ ",access_token"
+ ",target_pub"
+ ",is_wallet"
+ ") VALUES "
+ "($1, $2, $3, $4, $5);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_kyc_targets",
+ params);
+}
+
+
+/**
+ * Function called with records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_legitimization_measures (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.legitimization_measures.target_token),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.legitimization_measures.start_time),
+ TALER_PQ_query_param_json (
+ td->details.legitimization_measures.measures),
+ GNUNET_PQ_query_param_uint32 (
+ &td->details.legitimization_measures.display_priority),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_legitimization_measures",
+ "INSERT INTO legitimization_measures"
+ "(legitimization_measure_serial_id"
+ ",access_token"
+ ",start_time"
+ ",jmeasures"
+ ",display_priority"
+ ") VALUES "
+ "($1, $2, $3, $4::TEXT::JSONB, $5);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_legitimization_measures",
+ params);
+}
+
+
+/**
+ * Function called with records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_legitimization_outcomes (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.legitimization_outcomes.h_payto),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.legitimization_outcomes.decision_time),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.legitimization_outcomes.expiration_time),
+ TALER_PQ_query_param_json (
+ td->details.legitimization_outcomes.properties),
+ GNUNET_PQ_query_param_bool (
+ td->details.legitimization_outcomes.to_investigate),
+ TALER_PQ_query_param_json (
+ td->details.legitimization_outcomes.new_rules),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_legitimization_outcomes",
+ "INSERT INTO legitimization_outcomes"
+ "(outcome_serial_id"
+ ",h_payto"
+ ",decision_time"
+ ",expiration_time"
+ ",jproperties"
+ ",to_investigate"
+ ",jnew_rules"
+ ") VALUES "
+ "($1, $2, $3, $4, $5::TEXT::JSONB, $6, $7::TEXT::JSONB);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_legitimization_outcomes",
+ params);
+}
+
+
+/**
+ * Function called with records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_legitimization_processes (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.legitimization_processes.h_payto),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.legitimization_processes.start_time),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.legitimization_processes.expiration_time),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.legitimization_processes.legitimization_measure_serial_id),
+ GNUNET_PQ_query_param_uint32 (
+ &td->details.legitimization_processes.measure_index),
+ GNUNET_PQ_query_param_string (
+ td->details.legitimization_processes.provider_name),
+ GNUNET_PQ_query_param_string (
+ td->details.legitimization_processes.provider_user_id),
+ GNUNET_PQ_query_param_string (
+ td->details.legitimization_processes.provider_legitimization_id),
+ GNUNET_PQ_query_param_string (
+ td->details.legitimization_processes.redirect_url),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_legitimization_processes",
+ "INSERT INTO legitimization_processes"
+ "(legitimization_process_serial_id"
+ ",h_payto"
+ ",start_time"
+ ",expiration_time"
+ ",legitimization_measure_serial_id"
+ ",measure_index"
+ ",provider_name"
+ ",provider_user_id"
+ ",provider_legitimization_id"
+ ",redirect_url"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_legitimization_processes",
+ params);
+}
+
+
+/**
+ * Function called with reserves records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.reserves.reserve_pub),
+ GNUNET_PQ_query_param_timestamp (&td->details.reserves.expiration_date),
+ GNUNET_PQ_query_param_timestamp (&td->details.reserves.gc_date),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_reserves",
+ "INSERT INTO reserves"
+ "(reserve_uuid"
+ ",reserve_pub"
+ ",expiration_date"
+ ",gc_date"
+ ") VALUES "
+ "($1, $2, $3, $4);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_reserves",
+ params);
+}
+
+
+/**
+ * Function called with reserves_in records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves_in (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (&td->details.reserves_in.wire_reference),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.reserves_in.credit),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.reserves_in.sender_account_h_payto),
+ GNUNET_PQ_query_param_string (
+ td->details.reserves_in.exchange_account_section),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.reserves_in.execution_date),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.reserves_in.reserve_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_reserves_in",
+ "INSERT INTO reserves_in"
+ "(reserve_in_serial_id"
+ ",wire_reference"
+ ",credit"
+ ",wire_source_h_payto"
+ ",exchange_account_section"
+ ",execution_date"
+ ",reserve_pub"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_reserves_in",
+ params);
+}
+
+
+/**
+ * Function called with kycauth_in records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_kycauths_in (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (&td->details.kycauth_in.wire_reference),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.reserves_in.credit),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.reserves_in.sender_account_h_payto),
+ GNUNET_PQ_query_param_string (
+ td->details.reserves_in.exchange_account_section),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.reserves_in.execution_date),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.kycauth_in.account_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_kycauth_in",
+ "INSERT INTO kycauths_in"
+ "(kycauth_in_serial_id"
+ ",wire_reference"
+ ",credit"
+ ",wire_source_h_payto"
+ ",exchange_account_section"
+ ",execution_date"
+ ",account_pub"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_kycauth_in",
+ params);
+}
+
+
+/**
+ * Function called with reserves_open_requests records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves_open_requests (struct TALER_EXCHANGEDB_PostgresContext *
+ pg,
+ const struct
+ TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.reserves_open_requests.expiration_date),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.reserves_open_requests.reserve_sig),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.reserves_open_requests.reserve_payment),
+ GNUNET_PQ_query_param_uint32 (
+ &td->details.reserves_open_requests.requested_purse_limit),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_reserves_open_requests",
+ "INSERT INTO reserves_open_requests"
+ "(open_request_uuid"
+ ",reserve_pub"
+ ",request_timestamp"
+ ",expiration_date"
+ ",reserve_sig"
+ ",reserve_payment"
+ ",requested_purse_limit"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_reserves_open_requests",
+ params);
+}
+
+
+/**
+ * Function called with reserves_open_requests records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves_open_deposits (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.reserves_open_deposits.coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.reserves_open_deposits.coin_sig),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.reserves_open_deposits.reserve_sig),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.reserves_open_deposits.contribution),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_reserves_open_deposits",
+ "INSERT INTO reserves_open_deposits"
+ "(reserve_open_deposit_uuid"
+ ",reserve_sig"
+ ",reserve_pub"
+ ",coin_pub"
+ ",coin_sig"
+ ",contribution"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_reserves_open_deposits",
+ params);
+}
+
+
+/**
+ * Function called with reserves_close records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves_close (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.reserves_close.execution_date),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.reserves_close.wtid),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.reserves_close.sender_account_h_payto),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.reserves_close.amount),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.reserves_close.closing_fee),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.reserves_close.reserve_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_reserves_close",
+ "INSERT INTO reserves_close"
+ "(close_uuid"
+ ",execution_date"
+ ",wtid"
+ ",wire_target_h_payto"
+ ",amount"
+ ",closing_fee"
+ ",reserve_pub"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_reserves_close",
+ params);
+}
+
+
+/**
+ * Function called with auditors records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_auditors (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.auditors.auditor_pub),
+ GNUNET_PQ_query_param_string (td->details.auditors.auditor_name),
+ GNUNET_PQ_query_param_string (td->details.auditors.auditor_url),
+ GNUNET_PQ_query_param_bool (td->details.auditors.is_active),
+ GNUNET_PQ_query_param_timestamp (&td->details.auditors.last_change),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_auditors",
+ "INSERT INTO auditors"
+ "(auditor_uuid"
+ ",auditor_pub"
+ ",auditor_name"
+ ",auditor_url"
+ ",is_active"
+ ",last_change"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_auditors",
+ params);
+}
+
+
+/**
+ * Function called with auditor_denom_sigs records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_auditor_denom_sigs (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (&td->details.auditor_denom_sigs.auditor_uuid),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.auditor_denom_sigs.denominations_serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.auditor_denom_sigs.auditor_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_auditor_denom_sigs",
+ "INSERT INTO auditor_denom_sigs"
+ "(auditor_denom_serial"
+ ",auditor_uuid"
+ ",denominations_serial"
+ ",auditor_sig"
+ ") VALUES "
+ "($1, $2, $3, $4);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_auditor_denom_sigs",
+ params);
+}
+
+
+/**
+ * Function called with exchange_sign_keys records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_exchange_sign_keys (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.exchange_sign_keys.exchange_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.exchange_sign_keys.master_sig),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.exchange_sign_keys.meta.start),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.exchange_sign_keys.meta.expire_sign),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.exchange_sign_keys.meta.expire_legal),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_exchange_sign_keys",
+ "INSERT INTO exchange_sign_keys"
+ "(esk_serial"
+ ",exchange_pub"
+ ",master_sig"
+ ",valid_from"
+ ",expire_sign"
+ ",expire_legal"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_exchange_sign_keys",
+ params);
+}
+
+
+/**
+ * Function called with signkey_revocations records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_signkey_revocations (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (&td->details.signkey_revocations.esk_serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.signkey_revocations.master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_signkey_revocations",
+ "INSERT INTO signkey_revocations"
+ "(signkey_revocations_serial_id"
+ ",esk_serial"
+ ",master_sig"
+ ") VALUES "
+ "($1, $2, $3);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_signkey_revocations",
+ params);
+}
+
+
+/**
+ * Function called with known_coins records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_known_coins (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.known_coins.coin_pub),
+ TALER_PQ_query_param_denom_sig (
+ &td->details.known_coins.denom_sig),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.known_coins.denominations_serial),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_known_coins",
+ "INSERT INTO known_coins"
+ "(known_coin_id"
+ ",coin_pub"
+ ",denom_sig"
+ ",denominations_serial"
+ ") VALUES "
+ "($1, $2, $3, $4);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_known_coins",
+ params);
+}
+
+
+/**
+ * Function called with refresh records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.refresh.rc),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.refresh.execution_date),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.refresh.amount_with_fee),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.refresh.old_coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.refresh.old_coin_sig),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.refresh.refresh_seed),
+ GNUNET_PQ_query_param_uint32 (
+ &td->details.refresh.noreveal_index),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.refresh.planchets_h),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.refresh.selected_h),
+ td->details.refresh.no_blinding_seed
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (
+ &td->details.refresh.blinding_seed),
+ td->details.refresh.no_blinding_seed
+ ? GNUNET_PQ_query_param_null ()
+ : TALER_PQ_query_param_array_cs_r_pub (
+ td->details.refresh.num_cs_r_values,
+ td->details.refresh.cs_r_values,
+ pg->conn),
+ td->details.refresh.no_blinding_seed
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_uint64 (
+ &td->details.refresh.cs_r_choices),
+ GNUNET_PQ_query_param_array_uint64 (
+ td->details.refresh.num_coins,
+ td->details.refresh.denom_serials,
+ pg->conn),
+ TALER_PQ_query_param_array_blinded_denom_sig (
+ td->details.refresh.num_coins,
+ td->details.refresh.denom_sigs,
+ pg->conn),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_refresh",
+ "INSERT INTO refresh"
+ "(refresh_id"
+ ",rc"
+ ",execution_date"
+ ",amount_with_fee"
+ ",old_coin_pub"
+ ",old_coin_sig"
+ ",refresh_seed"
+ ",noreveal_index"
+ ",planchets_h"
+ ",selected_h"
+ ",blinding_seed"
+ ",cs_r_values"
+ ",cs_r_choices"
+ ",denom_serials"
+ ",denom_sigs"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6,$7,$8,$9,$10,$11,$12,$13,$14,$15);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_refresh",
+ params);
+}
+
+
+/**
+ * Function called with batch deposits records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_batch_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (&td->details.batch_deposits.shard),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.batch_deposits.merchant_pub),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.batch_deposits.wallet_timestamp),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.batch_deposits.exchange_timestamp),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.batch_deposits.refund_deadline),
+ GNUNET_PQ_query_param_timestamp (&td->details.batch_deposits.wire_deadline),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.batch_deposits.h_contract_terms),
+ td->details.batch_deposits.no_wallet_data_hash
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (
+ &td->details.batch_deposits.wallet_data_hash),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.batch_deposits.wire_salt),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.batch_deposits.wire_target_h_payto),
+ td->details.batch_deposits.no_policy_details
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_uint64 (
+ &td->details.batch_deposits.policy_details_serial_id),
+ GNUNET_PQ_query_param_bool (td->details.batch_deposits.policy_blocked),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.batch_deposits.total_amount),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.batch_deposits.total_without_fee),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.batch_deposits.merchant_sig),
+ GNUNET_PQ_query_param_bool (td->details.batch_deposits.done),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_batch_deposits",
+ "INSERT INTO batch_deposits"
+ "(batch_deposit_serial_id"
+ ",shard"
+ ",merchant_pub"
+ ",wallet_timestamp"
+ ",exchange_timestamp"
+ ",refund_deadline"
+ ",wire_deadline"
+ ",h_contract_terms"
+ ",wallet_data_hash"
+ ",wire_salt"
+ ",wire_target_h_payto"
+ ",policy_details_serial_id"
+ ",policy_blocked"
+ ",total_amount"
+ ",total_without_fee"
+ ",merchant_sig"
+ ",done"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
+ " $11, $12, $13, $14, $15, $16, $17);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_batch_deposits",
+ params);
+}
+
+
+/**
+ * Function called with deposits records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_coin_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.coin_deposits.batch_deposit_serial_id),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.coin_deposits.coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.coin_deposits.coin_sig),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.coin_deposits.amount_with_fee),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_coin_deposits",
+ "INSERT INTO coin_deposits"
+ "(coin_deposit_serial_id"
+ ",batch_deposit_serial_id"
+ ",coin_pub"
+ ",coin_sig"
+ ",amount_with_fee"
+ ") VALUES "
+ "($1, $2, $3, $4, $5);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_coin_deposits",
+ params);
+}
+
+
+/**
+ * Function called with refunds records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_refunds (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.refunds.coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.refunds.merchant_sig),
+ GNUNET_PQ_query_param_uint64 (&td->details.refunds.rtransaction_id),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.refunds.amount_with_fee),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.refunds.batch_deposit_serial_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_refunds",
+ "INSERT INTO refunds"
+ "(refund_serial_id"
+ ",coin_pub"
+ ",merchant_sig"
+ ",rtransaction_id"
+ ",amount_with_fee"
+ ",batch_deposit_serial_id"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_refunds",
+ params);
+}
+
+
+/**
+ * Function called with wire_out records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wire_out (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_timestamp (&td->details.wire_out.execution_date),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.wire_out.wtid_raw),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wire_out.wire_target_h_payto),
+ GNUNET_PQ_query_param_string (
+ td->details.wire_out.exchange_account_section),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wire_out.amount),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_wire_out",
+ "INSERT INTO wire_out"
+ "(wireout_uuid"
+ ",execution_date"
+ ",wtid_raw"
+ ",wire_target_h_payto"
+ ",exchange_account_section"
+ ",amount"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_wire_out",
+ params);
+}
+
+
+/**
+ * Function called with aggregation_tracking records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_aggregation_tracking (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.aggregation_tracking.batch_deposit_serial_id),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.aggregation_tracking.wtid_raw),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_aggregation_tracking",
+ "INSERT INTO aggregation_tracking"
+ "(aggregation_serial_id"
+ ",batch_deposit_serial_id"
+ ",wtid_raw"
+ ") VALUES "
+ "($1, $2, $3);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_aggregation_tracking",
+ params);
+}
+
+
+/**
+ * Function called with wire_fee records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wire_fee (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_string (td->details.wire_fee.wire_method),
+ GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.start_date),
+ GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.end_date),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wire_fee.fees.wire),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wire_fee.fees.closing),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.wire_fee.master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_wire_fee",
+ "INSERT INTO wire_fee"
+ "(wire_fee_serial"
+ ",wire_method"
+ ",start_date"
+ ",end_date"
+ ",wire_fee"
+ ",closing_fee"
+ ",master_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_wire_fee",
+ params);
+}
+
+
+/**
+ * Function called with wire_fee records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (
+ &td->serial),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.global_fee.start_date),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.global_fee.end_date),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.global_fee.fees.history),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.global_fee.fees.account),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.global_fee.fees.purse),
+ GNUNET_PQ_query_param_relative_time (
+ &td->details.global_fee.purse_timeout),
+ GNUNET_PQ_query_param_relative_time (
+ &td->details.global_fee.history_expiration),
+ GNUNET_PQ_query_param_uint32 (
+ &td->details.global_fee.purse_account_limit),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.global_fee.master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_global_fee",
+ "INSERT INTO global_fee"
+ "(global_fee_serial"
+ ",start_date"
+ ",end_date"
+ ",history_fee"
+ ",account_fee"
+ ",purse_fee"
+ ",purse_timeout"
+ ",history_expiration"
+ ",purse_account_limit"
+ ",master_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_global_fee",
+ params);
+}
+
+
+/**
+ * Function called with recoup records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_recoup (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.recoup.coin_sig),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.recoup.coin_blind),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.recoup.amount),
+ GNUNET_PQ_query_param_timestamp (&td->details.recoup.timestamp),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.recoup.coin_pub),
+ GNUNET_PQ_query_param_uint64 (&td->details.recoup.withdraw_serial_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_recoup",
+ "INSERT INTO recoup"
+ "(recoup_uuid"
+ ",coin_sig"
+ ",coin_blind"
+ ",amount"
+ ",recoup_timestamp"
+ ",coin_pub"
+ ",withdraw_serial_id"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_recoup",
+ params);
+}
+
+
+/**
+ * Function called with recoup_refresh records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_recoup_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.recoup_refresh.coin_sig),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.recoup_refresh.coin_blind),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.recoup_refresh.amount),
+ GNUNET_PQ_query_param_timestamp (&td->details.recoup_refresh.timestamp),
+ GNUNET_PQ_query_param_uint64 (&td->details.recoup_refresh.known_coin_id),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.recoup.coin_pub),
+ GNUNET_PQ_query_param_uint64 (&td->details.recoup_refresh.rrc_serial),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_recoup_refresh",
+ "INSERT INTO recoup_refresh"
+ "(recoup_refresh_uuid"
+ ",coin_sig"
+ ",coin_blind"
+ ",amount"
+ ",recoup_timestamp"
+ ",known_coin_id"
+ ",coin_pub"
+ ",rrc_serial"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_recoup_refresh",
+ params);
+}
+
+
+/**
+ * Function called with extensions records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_extensions (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_string (td->details.extensions.name),
+ NULL == td->details.extensions.manifest ?
+ GNUNET_PQ_query_param_null () :
+ GNUNET_PQ_query_param_string (td->details.extensions.manifest),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_extensions",
+ "INSERT INTO extensions"
+ "(extension_id"
+ ",name"
+ ",manifest"
+ ") VALUES "
+ "($1, $2, $3);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_extensions",
+ params);
+}
+
+
+/**
+ * Function called with policy_details records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_policy_details (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.policy_details.hash_code),
+ (td->details.policy_details.no_policy_json)
+ ? GNUNET_PQ_query_param_null ()
+ : TALER_PQ_query_param_json (td->details.policy_details.policy_json),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.policy_details.commitment),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.policy_details.accumulated_total),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.policy_details.fee),
+ TALER_PQ_query_param_amount (pg->conn,
+ &td->details.policy_details.transferable),
+ GNUNET_PQ_query_param_timestamp (&td->details.policy_details.deadline),
+ GNUNET_PQ_query_param_uint16 (
+ &td->details.policy_details.fulfillment_state),
+ (td->details.policy_details.no_fulfillment_id)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_uint64 (
+ &td->details.policy_details.fulfillment_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_policy_details",
+ "INSERT INTO policy_details"
+ "(policy_details_serial_id"
+ ",policy_hash_code"
+ ",policy_json"
+ ",deadline"
+ ",commitment"
+ ",accumulated_total"
+ ",fee"
+ ",transferable"
+ ",fulfillment_state"
+ ",fulfillment_id"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_policy_details",
+ params);
+}
+
+
+/**
+ * Function called with policy_fulfillment records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_policy_fulfillments (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.policy_fulfillments.fulfillment_timestamp),
+ (NULL == td->details.policy_fulfillments.fulfillment_proof)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (
+ td->details.policy_fulfillments.fulfillment_proof),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.policy_fulfillments.h_fulfillment_proof),
+ GNUNET_PQ_query_param_fixed_size (
+ td->details.policy_fulfillments.policy_hash_codes,
+ td->details.policy_fulfillments.policy_hash_codes_count),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_policy_fulfillments",
+ "INSERT INTO policy_fulfillments "
+ "(fulfillment_id"
+ ",fulfillment_timestamp"
+ ",fulfillment_proof"
+ ",h_fulfillment_proof"
+ ",policy_hash_codes"
+ ") VALUES "
+ "($1, $2, $3::TEXT::JSONB, $4, $5);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_policy_fulfillments",
+ params);
+}
+
+
+/**
+ * Function called with purse_requests records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_requests (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.purse_requests.purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.purse_requests.merge_pub),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.purse_requests.purse_creation),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.purse_requests.purse_expiration),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.purse_requests.h_contract_terms),
+ GNUNET_PQ_query_param_uint32 (&td->details.purse_requests.age_limit),
+ GNUNET_PQ_query_param_uint32 (&td->details.purse_requests.flags),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.purse_requests.amount_with_fee),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.purse_requests.purse_fee),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.purse_requests.purse_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_purse_requests",
+ "INSERT INTO purse_requests"
+ "(purse_requests_serial_id"
+ ",purse_pub"
+ ",merge_pub"
+ ",purse_creation"
+ ",purse_expiration"
+ ",h_contract_terms"
+ ",age_limit"
+ ",flags"
+ ",amount_with_fee"
+ ",purse_fee"
+ ",purse_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_purse_requests",
+ params);
+}
+
+
+/**
+ * Function called with purse_decision records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_decision (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.purse_decision.purse_pub),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.purse_decision.action_timestamp),
+ GNUNET_PQ_query_param_bool (
+ td->details.purse_decision.refunded),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_purse_refunds",
+ "INSERT INTO purse_refunds"
+ "(purse_refunds_serial_id"
+ ",purse_pub"
+ ",action_timestamp"
+ ",refunded"
+ ") VALUES "
+ "($1, $2, $3, $4);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_purse_decision",
+ params);
+}
+
+
+/**
+ * Function called with purse_merges records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_merges (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (&td->details.purse_merges.partner_serial_id),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.purse_merges.reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.purse_merges.purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.purse_merges.merge_sig),
+ GNUNET_PQ_query_param_timestamp (&td->details.purse_merges.merge_timestamp),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_purse_merges",
+ "INSERT INTO purse_merges"
+ "(purse_merge_request_serial_id"
+ ",partner_serial_id"
+ ",reserve_pub"
+ ",purse_pub"
+ ",merge_sig"
+ ",merge_timestamp"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_purse_merges",
+ params);
+}
+
+
+/**
+ * Function called with purse_deposits records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.purse_deposits.partner_serial_id),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.purse_deposits.purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.purse_deposits.coin_pub),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.purse_deposits.amount_with_fee),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.purse_deposits.coin_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_purse_deposits",
+ "INSERT INTO purse_deposits"
+ "(purse_deposit_serial_id"
+ ",partner_serial_id"
+ ",purse_pub"
+ ",coin_pub"
+ ",amount_with_fee"
+ ",coin_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_purse_deposits",
+ params);
+}
+
+
+/**
+x * Function called with account_mergers records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_account_mergers (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.account_merges.reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.account_merges.reserve_sig),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.account_merges.purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.account_merges.wallet_h_payto),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_account_merges",
+ "INSERT INTO account_merges"
+ "(account_merge_request_serial_id"
+ ",reserve_pub"
+ ",reserve_sig"
+ ",purse_pub"
+ ",wallet_h_payto"
+ ") VALUES "
+ "($1, $2, $3, $4, $5);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_account_merges",
+ params);
+}
+
+
+/**
+ * Function called with history_requests records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_history_requests (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.history_requests.reserve_pub),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.history_requests.request_timestamp),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.history_requests.reserve_sig),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.history_requests.history_fee),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_history_requests",
+ "INSERT INTO history_requests"
+ "(history_request_serial_id"
+ ",reserve_pub"
+ ",request_timestamp"
+ ",reserve_sig"
+ ",history_fee"
+ ") VALUES "
+ "($1, $2, $3, $4, $5);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_history_requests",
+ params);
+}
+
+
+/**
+ * Function called with close_requests records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_close_requests (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.close_requests.reserve_pub),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.close_requests.close_timestamp),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.close_requests.reserve_sig),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.close_requests.close),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.close_requests.close_fee),
+ GNUNET_PQ_query_param_string (
+ td->details.close_requests.payto_uri.full_payto),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_close_requests",
+ "INSERT INTO close_requests"
+ "(close_request_serial_id"
+ ",reserve_pub"
+ ",close_timestamp"
+ ",reserve_sig"
+ ",close"
+ ",close_fee"
+ ",payto_uri"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_close_requests",
+ params);
+}
+
+
+/**
+ * Function called with wads_out records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wads_out (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.wads_out.wad_id),
+ GNUNET_PQ_query_param_uint64 (&td->details.wads_out.partner_serial_id),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wads_out.amount),
+ GNUNET_PQ_query_param_timestamp (&td->details.wads_out.execution_time),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_wads_out",
+ "INSERT INTO wads_out"
+ "(wad_out_serial_id"
+ ",wad_id"
+ ",partner_serial_id"
+ ",amount"
+ ",execution_time"
+ ") VALUES "
+ "($1, $2, $3, $4, $5);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_wads_out",
+ params);
+}
+
+
+/**
+ * Function called with wads_out_entries records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wads_out_entries (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.wads_out_entries.wad_out_serial_id),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_out_entries.reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_out_entries.purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_out_entries.h_contract),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.wads_out_entries.purse_expiration),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.wads_out_entries.merge_timestamp),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wads_out_entries.amount_with_fee),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wads_out_entries.wad_fee),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wads_out_entries.deposit_fees),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_out_entries.reserve_sig),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_out_entries.purse_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_wad_out_entries",
+ "INSERT INTO wad_out_entries"
+ "(wad_out_entry_serial_id"
+ ",wad_out_serial_id"
+ ",reserve_pub"
+ ",purse_pub"
+ ",h_contract"
+ ",purse_expiration"
+ ",merge_timestamp"
+ ",amount_with_fee"
+ ",wad_fee"
+ ",deposit_fees"
+ ",reserve_sig"
+ ",purse_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_wads_out_entries",
+ params);
+}
+
+
+/**
+ * Function called with wads_in records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wads_in (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (&td->details.wads_in.wad_id),
+ GNUNET_PQ_query_param_string (td->details.wads_in.origin_exchange_url),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wads_in.amount),
+ GNUNET_PQ_query_param_timestamp (&td->details.wads_in.arrival_time),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_wads_in",
+ "INSERT INTO wads_in"
+ "(wad_in_serial_id"
+ ",wad_id"
+ ",origin_exchange_url"
+ ",amount"
+ ",arrival_time"
+ ") VALUES "
+ "($1, $2, $3, $4, $5);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_wads_in",
+ params);
+}
+
+
+/**
+ * Function called with wads_in_entries records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wads_in_entries (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_in_entries.reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_in_entries.purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_in_entries.h_contract),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.wads_in_entries.purse_expiration),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.wads_in_entries.merge_timestamp),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wads_in_entries.amount_with_fee),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wads_in_entries.wad_fee),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.wads_in_entries.deposit_fees),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_in_entries.reserve_sig),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.wads_in_entries.purse_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_wad_in_entries",
+ "INSERT INTO wad_in_entries"
+ "(wad_in_entry_serial_id"
+ ",wad_in_serial_id"
+ ",reserve_pub"
+ ",purse_pub"
+ ",h_contract"
+ ",purse_expiration"
+ ",merge_timestamp"
+ ",amount_with_fee"
+ ",wad_fee"
+ ",deposit_fees"
+ ",reserve_sig"
+ ",purse_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_wads_in_entries",
+ params);
+}
+
+
+/**
+ * Function called with profit_drains records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_profit_drains (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.profit_drains.wtid),
+ GNUNET_PQ_query_param_string (
+ td->details.profit_drains.account_section),
+ GNUNET_PQ_query_param_string (
+ td->details.profit_drains.payto_uri.full_payto),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.profit_drains.trigger_date),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.profit_drains.amount),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.profit_drains.master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_profit_drains",
+ "INSERT INTO profit_drains"
+ "(profit_drain_serial_id"
+ ",wtid"
+ ",account_section"
+ ",payto_uri"
+ ",trigger_date"
+ ",amount"
+ ",master_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_profit_drains",
+ params);
+}
+
+
+/**
+ * Function called with aml_staff records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_aml_staff (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.aml_staff.decider_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.aml_staff.master_sig),
+ GNUNET_PQ_query_param_string (
+ td->details.aml_staff.decider_name),
+ GNUNET_PQ_query_param_bool (
+ td->details.aml_staff.is_active),
+ GNUNET_PQ_query_param_bool (
+ td->details.aml_staff.read_only),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.aml_staff.last_change),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_aml_staff",
+ "INSERT INTO aml_staff"
+ "(aml_staff_uuid"
+ ",decider_pub"
+ ",master_sig"
+ ",decider_name"
+ ",is_active"
+ ",read_only"
+ ",last_change"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_aml_staff",
+ params);
+}
+
+
+/**
+ * Function called with kyc_attributes records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_kyc_attributes (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.kyc_attributes.h_payto),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.kyc_attributes.legitimization_serial),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.kyc_attributes.collection_time),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.kyc_attributes.expiration_time),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.kyc_attributes.trigger_outcome_serial),
+ GNUNET_PQ_query_param_fixed_size (
+ &td->details.kyc_attributes.encrypted_attributes,
+ td->details.kyc_attributes.encrypted_attributes_size),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_kyc_attributes",
+ "INSERT INTO kyc_attributes"
+ "(kyc_attributes_serial_id"
+ ",h_payto"
+ ",legitimization_serial"
+ ",collection_time"
+ ",expiration_time"
+ ",trigger_outcome_serial"
+ ",encrypted_attributes"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_kyc_attributes",
+ params);
+}
+
+
+/**
+ * Function called with aml_history records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_aml_history (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.aml_history.h_payto),
+ GNUNET_PQ_query_param_uint64 (
+ &td->details.aml_history.outcome_serial_id),
+ GNUNET_PQ_query_param_string (
+ td->details.aml_history.justification),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.aml_history.decider_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.aml_history.decider_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_aml_history",
+ "INSERT INTO aml_history"
+ "(aml_history_serial_id"
+ ",h_payto"
+ ",outcome_serial_id"
+ ",justification"
+ ",decider_pub"
+ ",decider_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_aml_history",
+ params);
+}
+
+
+/**
+ * Function called with kyc_event records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_kyc_events (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.kyc_events.event_timestamp),
+ GNUNET_PQ_query_param_string (
+ td->details.kyc_events.event_type),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_kyc_events",
+ "INSERT INTO kyc_events"
+ "(kyc_event_serial_id"
+ ",event_timestamp"
+ ",event_type"
+ ") VALUES "
+ "($1, $2, $3);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_kyc_events",
+ params);
+}
+
+
+/**
+ * Function called with purse_deletion records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_deletion (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.purse_deletion.purse_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.purse_deletion.purse_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_into_table_purse_deletion",
+ "INSERT INTO purse_deletion"
+ "(purse_deletion_serial_id"
+ ",purse_pub"
+ ",purse_sig"
+ ") VALUES "
+ "($1, $2, $3);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_purse_deletion",
+ params);
+}
+
+
+/**
+ * Function called with withdraw records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_withdraw (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_TableData *td)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&td->serial),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.withdraw.planchets_h),
+ GNUNET_PQ_query_param_timestamp (
+ &td->details.withdraw.execution_date),
+ TALER_PQ_query_param_amount (
+ pg->conn,
+ &td->details.withdraw.amount_with_fee),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.withdraw.reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (
+ &td->details.withdraw.reserve_sig),
+ td->details.withdraw.age_proof_required
+ ? GNUNET_PQ_query_param_uint16 (
+ &td->details.withdraw.max_age)
+ : GNUNET_PQ_query_param_null (),
+ td->details.withdraw.age_proof_required
+ ? GNUNET_PQ_query_param_uint16 (
+ &td->details.withdraw.noreveal_index)
+ : GNUNET_PQ_query_param_null (),
+ td->details.withdraw.age_proof_required
+ ? GNUNET_PQ_query_param_auto_from_type (
+ &td->details.withdraw.selected_h)
+ : GNUNET_PQ_query_param_null (),
+ td->details.withdraw.no_blinding_seed
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (
+ &td->details.withdraw.blinding_seed),
+ (0 < td->details.withdraw.num_cs_r_values)
+ ? TALER_PQ_query_param_array_cs_r_pub (
+ td->details.withdraw.num_cs_r_values,
+ td->details.withdraw.cs_r_values,
+ pg->conn)
+ : GNUNET_PQ_query_param_null (),
+ (0 < td->details.withdraw.num_cs_r_values)
+ ? GNUNET_PQ_query_param_uint64 (
+ &td->details.withdraw.cs_r_choices)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_array_uint64 (
+ td->details.withdraw.num_coins,
+ td->details.withdraw.denom_serials,
+ pg->conn),
+ TALER_PQ_query_param_array_blinded_denom_sig (
+ td->details.withdraw.num_coins,
+ td->details.withdraw.denom_sigs,
+ pg->conn),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "insert_into_table_withdraw",
+ "INSERT INTO withdraw"
+ "(withdraw_id"
+ ",planchets_h"
+ ",execution_date"
+ ",amount_with_fee"
+ ",reserve_pub"
+ ",reserve_sig"
+ ",max_age"
+ ",noreveal_index"
+ ",selected_h"
+ ",blinding_seed"
+ ",cs_r_values"
+ ",cs_r_choices"
+ ",denom_serials"
+ ",denom_sigs"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14);");
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_into_table_withdraw",
+ params);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ return qs;
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_records_by_table (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct
+ TALER_EXCHANGEDB_TableData *td)
+{
+ InsertRecordCallback rh = NULL;
+
+ switch (td->table)
+ {
+ case TALER_EXCHANGEDB_RT_DENOMINATIONS:
+ rh = &irbt_cb_table_denominations;
+ break;
+ case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS:
+ rh = &irbt_cb_table_denomination_revocations;
+ break;
+ case TALER_EXCHANGEDB_RT_WIRE_TARGETS:
+ rh = &irbt_cb_table_wire_targets;
+ break;
+ case TALER_EXCHANGEDB_RT_KYC_TARGETS:
+ rh = &irbt_cb_table_kyc_targets;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES:
+ rh = &irbt_cb_table_reserves;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_IN:
+ rh = &irbt_cb_table_reserves_in;
+ break;
+ case TALER_EXCHANGEDB_RT_KYCAUTHS_IN:
+ rh = &irbt_cb_table_kycauths_in;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_CLOSE:
+ rh = &irbt_cb_table_reserves_close;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS:
+ rh = &irbt_cb_table_reserves_open_requests;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
+ rh = &irbt_cb_table_reserves_open_deposits;
+ break;
+ case TALER_EXCHANGEDB_RT_AUDITORS:
+ rh = &irbt_cb_table_auditors;
+ break;
+ case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS:
+ rh = &irbt_cb_table_auditor_denom_sigs;
+ break;
+ case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS:
+ rh = &irbt_cb_table_exchange_sign_keys;
+ break;
+ case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS:
+ rh = &irbt_cb_table_signkey_revocations;
+ break;
+ case TALER_EXCHANGEDB_RT_KNOWN_COINS:
+ rh = &irbt_cb_table_known_coins;
+ break;
+ case TALER_EXCHANGEDB_RT_REFRESH:
+ rh = &irbt_cb_table_refresh;
+ break;
+ case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS:
+ rh = &irbt_cb_table_batch_deposits;
+ break;
+ case TALER_EXCHANGEDB_RT_COIN_DEPOSITS:
+ rh = &irbt_cb_table_coin_deposits;
+ break;
+ case TALER_EXCHANGEDB_RT_REFUNDS:
+ rh = &irbt_cb_table_refunds;
+ break;
+ case TALER_EXCHANGEDB_RT_WIRE_OUT:
+ rh = &irbt_cb_table_wire_out;
+ break;
+ case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING:
+ rh = &irbt_cb_table_aggregation_tracking;
+ break;
+ case TALER_EXCHANGEDB_RT_WIRE_FEE:
+ rh = &irbt_cb_table_wire_fee;
+ break;
+ case TALER_EXCHANGEDB_RT_GLOBAL_FEE:
+ rh = &irbt_cb_table_global_fee;
+ break;
+ case TALER_EXCHANGEDB_RT_RECOUP:
+ rh = &irbt_cb_table_recoup;
+ break;
+ case TALER_EXCHANGEDB_RT_RECOUP_REFRESH:
+ rh = &irbt_cb_table_recoup_refresh;
+ break;
+ case TALER_EXCHANGEDB_RT_EXTENSIONS:
+ rh = &irbt_cb_table_extensions;
+ break;
+ case TALER_EXCHANGEDB_RT_POLICY_DETAILS:
+ rh = &irbt_cb_table_policy_details;
+ break;
+ case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS:
+ rh = &irbt_cb_table_policy_fulfillments;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
+ rh = &irbt_cb_table_purse_requests;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_DECISION:
+ rh = &irbt_cb_table_purse_decision;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_MERGES:
+ rh = &irbt_cb_table_purse_merges;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS:
+ rh = &irbt_cb_table_purse_deposits;
+ break;
+ case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES:
+ rh = &irbt_cb_table_account_mergers;
+ break;
+ case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS:
+ rh = &irbt_cb_table_history_requests;
+ break;
+ case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS:
+ rh = &irbt_cb_table_close_requests;
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_OUT:
+ rh = &irbt_cb_table_wads_out;
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES:
+ rh = &irbt_cb_table_wads_out_entries;
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_IN:
+ rh = &irbt_cb_table_wads_in;
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES:
+ rh = &irbt_cb_table_wads_in_entries;
+ break;
+ case TALER_EXCHANGEDB_RT_PROFIT_DRAINS:
+ rh = &irbt_cb_table_profit_drains;
+ break;
+ case TALER_EXCHANGEDB_RT_AML_STAFF:
+ rh = &irbt_cb_table_aml_staff;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_DELETION:
+ rh = &irbt_cb_table_purse_deletion;
+ break;
+ case TALER_EXCHANGEDB_RT_WITHDRAW:
+ rh = &irbt_cb_table_withdraw;
+ break;
+ case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES:
+ rh = &irbt_cb_table_legitimization_measures;
+ break;
+ case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES:
+ rh = &irbt_cb_table_legitimization_outcomes;
+ break;
+ case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES:
+ rh = &irbt_cb_table_legitimization_processes;
+ break;
+ case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES:
+ rh = &irbt_cb_table_kyc_attributes;
+ break;
+ case TALER_EXCHANGEDB_RT_AML_HISTORY:
+ rh = &irbt_cb_table_aml_history;
+ break;
+ case TALER_EXCHANGEDB_RT_KYC_EVENTS:
+ rh = &irbt_cb_table_kyc_events;
+ break;
+ }
+ if (NULL == rh)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ return rh (pg,
+ td);
+}
+
+
+/* end of insert_records_by_table.c */
diff --git a/src/exchangedb/insert_refund.c b/src/exchangedb/insert_refund.c
@@ -0,0 +1,62 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_refund.c
+ * @brief Implementation of the insert_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_refund.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_refund (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_Refund *refund)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
+ GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
+ GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
+ GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
+ TALER_PQ_query_param_amount (pg->conn,
+ &refund->details.refund_amount),
+ GNUNET_PQ_query_param_end
+ };
+
+ GNUNET_assert (GNUNET_YES ==
+ TALER_amount_cmp_currency (&refund->details.refund_amount,
+ &refund->details.refund_fee));
+ PREPARE (pg,
+ "insert_refund",
+ "INSERT INTO refunds "
+ "(coin_pub"
+ ",batch_deposit_serial_id"
+ ",merchant_sig"
+ ",rtransaction_id"
+ ",amount_with_fee"
+ ") SELECT $1, cdep.batch_deposit_serial_id, $3, $5, $6"
+ " FROM coin_deposits cdep"
+ " JOIN batch_deposits bdep USING (batch_deposit_serial_id)"
+ " WHERE coin_pub=$1"
+ " AND h_contract_terms=$4"
+ " AND merchant_pub=$2");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_refund",
+ params);
+}
diff --git a/src/exchangedb/insert_reserve_closed.c b/src/exchangedb/insert_reserve_closed.c
@@ -0,0 +1,109 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_reserve_closed.c
+ * @brief Implementation of the insert_reserve_closed function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_reserve_closed.h"
+#include "helper.h"
+#include "taler/exchange-database/reserves_get.h"
+#include "taler/exchange-database/reserves_update.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_reserve_closed (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ struct GNUNET_TIME_Timestamp execution_date,
+ const struct TALER_FullPayto receiver_account,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const struct TALER_Amount *amount_with_fee,
+ const struct TALER_Amount *closing_fee,
+ uint64_t close_request_row)
+{
+ struct TALER_EXCHANGEDB_Reserve reserve;
+ enum GNUNET_DB_QueryStatus qs;
+ struct TALER_FullPaytoHashP h_payto;
+
+ TALER_full_payto_hash (receiver_account,
+ &h_payto);
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_timestamp (&execution_date),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_auto_from_type (&h_payto),
+ TALER_PQ_query_param_amount (pg->conn,
+ amount_with_fee),
+ TALER_PQ_query_param_amount (pg->conn,
+ closing_fee),
+ GNUNET_PQ_query_param_uint64 (&close_request_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "reserves_close_insert",
+ "INSERT INTO reserves_close "
+ "(reserve_pub"
+ ",execution_date"
+ ",wtid"
+ ",wire_target_h_payto"
+ ",amount"
+ ",closing_fee"
+ ",close_request_row"
+ ") VALUES ($1, $2, $3, $4, $5, $6, $7);");
+
+ qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "reserves_close_insert",
+ params);
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ return qs;
+
+ /* update reserve balance */
+ reserve.pub = *reserve_pub;
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ (qs = TALER_EXCHANGEDB_reserves_get (pg,
+ &reserve)))
+ {
+ /* Existence should have been checked before we got here... */
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+ }
+ {
+ enum TALER_AmountArithmeticResult ret;
+
+ ret = TALER_amount_subtract (&reserve.balance,
+ &reserve.balance,
+ amount_with_fee);
+ if (ret < 0)
+ {
+ /* The reserve history was checked to make sure there is enough of a balance
+ left before we tried this; however, concurrent operations may have changed
+ the situation by now. We should re-try the transaction. */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Closing of reserve `%s' refused due to balance mismatch. Retrying.\n",
+ TALER_B2S (reserve_pub));
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
+ }
+ return TALER_EXCHANGEDB_reserves_update (pg,
+ &reserve);
+}
diff --git a/src/exchangedb/insert_reserve_open_deposit.c b/src/exchangedb/insert_reserve_open_deposit.c
@@ -0,0 +1,63 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file insert_reserve_open_deposit.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_reserve_open_deposit.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_reserve_open_deposit (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinPublicInfo *cpi,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ uint64_t known_coin_id,
+ const struct TALER_Amount *coin_total,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ bool *insufficient_funds)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&cpi->coin_pub),
+ GNUNET_PQ_query_param_uint64 (&known_coin_id),
+ GNUNET_PQ_query_param_auto_from_type (coin_sig),
+ GNUNET_PQ_query_param_auto_from_type (reserve_sig),
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ TALER_PQ_query_param_amount (pg->conn,
+ coin_total),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("out_insufficient_funds",
+ insufficient_funds),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "insert_reserve_open_deposit",
+ "SELECT "
+ " out_insufficient_funds"
+ " FROM exchange_do_reserve_open_deposit"
+ " ($1,$2,$3,$4,$5,$6);");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "insert_reserve_open_deposit",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/insert_sanction_list_hit.c b/src/exchangedb/insert_sanction_list_hit.c
@@ -0,0 +1,90 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_sanction_list_hit.c
+ * @brief Implementation of the insert_sanction_list_hit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_sanction_list_hit.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_sanction_list_hit (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ bool to_investigate,
+ const json_t *new_rules,
+ const json_t *account_properties,
+ unsigned int num_events,
+ const char **events)
+{
+ struct GNUNET_TIME_Timestamp never
+ = GNUNET_TIME_UNIT_FOREVER_TS;
+ struct GNUNET_TIME_Timestamp now
+ = GNUNET_TIME_timestamp_get ();
+ struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = *h_payto
+ };
+ char *notify_s
+ = GNUNET_PQ_get_event_notify_channel (&rep.header);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_timestamp (&never),
+ NULL != account_properties
+ ? TALER_PQ_query_param_json (account_properties)
+ : GNUNET_PQ_query_param_null (),
+ NULL != new_rules
+ ? TALER_PQ_query_param_json (new_rules)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_bool (to_investigate),
+ GNUNET_PQ_query_param_string (notify_s),
+ GNUNET_PQ_query_param_array_ptrs_string (num_events,
+ events,
+ pg->conn),
+ GNUNET_PQ_query_param_end
+ };
+ uint64_t outcome_serial_id;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("outcome_serial_id",
+ &outcome_serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "do_insert_sanction_list_hit",
+ "SELECT"
+ " out_outcome_serial_id AS outcome_serial_id"
+ " FROM exchange_do_insert_sanction_list_hit"
+ "($1,$2,$3,$4::TEXT::JSONB,$5::TEXT::JSONB,$6,$7,$8);");
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Inserting LEGI OUTCOME from sanction list hit\n");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "do_insert_sanction_list_hit",
+ params,
+ rs);
+ (void) outcome_serial_id;
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ GNUNET_free (notify_s);
+ GNUNET_PQ_event_do_poll (pg->conn);
+ return qs;
+}
diff --git a/src/exchangedb/insert_signkey_revocation.c b/src/exchangedb/insert_signkey_revocation.c
@@ -0,0 +1,49 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_signkey_revocation.c
+ * @brief Implementation of the insert_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_signkey_revocation.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_signkey_revocation (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ const struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (exchange_pub),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+
+ PREPARE (pg,
+ "insert_signkey_revocation",
+ "INSERT INTO signkey_revocations "
+ "(esk_serial"
+ ",master_sig"
+ ") SELECT esk_serial, $2 "
+ " FROM exchange_sign_keys"
+ " WHERE exchange_pub=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_signkey_revocation",
+ params);
+}
diff --git a/src/exchangedb/insert_successor_measure.c b/src/exchangedb/insert_successor_measure.c
@@ -0,0 +1,84 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2023, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_successor_measure.c
+ * @brief Implementation of the insert_succesor_measure function for Postgres
+ * @author Florian Dold
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_successor_measure.h"
+#include "helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_successor_measure (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Timestamp decision_time,
+ const char *new_measure_name,
+ const json_t *jmeasures,
+ bool *unknown_account,
+ struct GNUNET_TIME_Timestamp *last_date)
+{
+ struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = *h_payto
+ };
+ /* We're reverting back to default rules => never expires.*/
+ struct GNUNET_TIME_Timestamp expiration_time = {
+ .abs_time = GNUNET_TIME_UNIT_FOREVER_ABS,
+ };
+ char *notify_s
+ = GNUNET_PQ_get_event_notify_channel (&rep.header);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_timestamp (&decision_time),
+ GNUNET_PQ_query_param_timestamp (&expiration_time),
+ NULL != new_measure_name
+ ? GNUNET_PQ_query_param_string (new_measure_name)
+ : GNUNET_PQ_query_param_null (),
+ NULL != jmeasures
+ ? TALER_PQ_query_param_json (jmeasures)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("out_account_unknown",
+ unknown_account),
+ GNUNET_PQ_result_spec_timestamp ("out_last_date",
+ last_date),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "do_insert_successor_measure",
+ "SELECT"
+ " out_account_unknown"
+ ",out_last_date"
+ ",out_legitimization_measure_serial_id"
+ " FROM exchange_do_insert_successor_measure"
+ "($1, $2, $3, $4, $5::TEXT::JSONB);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "do_insert_successor_measure",
+ params,
+ rs);
+ GNUNET_free (notify_s);
+ GNUNET_PQ_event_do_poll (pg->conn);
+ return qs;
+}
diff --git a/src/exchangedb/insert_wire.c b/src/exchangedb/insert_wire.c
@@ -0,0 +1,81 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2023, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_wire.c
+ * @brief Implementation of the insert_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_wire.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_insert_wire (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPayto payto_uri,
+ const char *conversion_url,
+ const char *open_banking_gateway,
+ const char *wire_transfer_gateway,
+ const json_t *debit_restrictions,
+ const json_t *credit_restrictions,
+ struct GNUNET_TIME_Timestamp start_date,
+ const struct TALER_MasterSignatureP *master_sig,
+ const char *bank_label,
+ int64_t priority)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (payto_uri.full_payto),
+ NULL == conversion_url
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (conversion_url),
+ TALER_PQ_query_param_json (debit_restrictions),
+ TALER_PQ_query_param_json (credit_restrictions),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_timestamp (&start_date),
+ NULL == bank_label
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (bank_label),
+ GNUNET_PQ_query_param_int64 (&priority),
+ NULL == open_banking_gateway
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (open_banking_gateway),
+ NULL == wire_transfer_gateway
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (wire_transfer_gateway),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_wire",
+ "INSERT INTO wire_accounts "
+ "(payto_uri"
+ ",conversion_url"
+ ",debit_restrictions"
+ ",credit_restrictions"
+ ",master_sig"
+ ",is_active"
+ ",last_change"
+ ",bank_label"
+ ",priority"
+ ",open_banking_gateway"
+ ",wire_transfer_gateway"
+ ") VALUES "
+ "($1,$2,$3::TEXT::JSONB,$4::TEXT::JSONB,$5,true,$6,$7,$8,$9,$10);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_wire",
+ params);
+}
diff --git a/src/exchangedb/insert_wire_fee.c b/src/exchangedb/insert_wire_fee.c
@@ -0,0 +1,108 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/insert_wire_fee.c
+ * @brief Implementation of the insert_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/insert_wire_fee.h"
+#include "helper.h"
+#include "taler/exchange-database/get_wire_fee.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_insert_wire_fee (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *type,
+ struct GNUNET_TIME_Timestamp start_date,
+ struct GNUNET_TIME_Timestamp end_date,
+ const struct TALER_WireFeeSet *fees,
+ const struct TALER_MasterSignatureP *
+ master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (type),
+ GNUNET_PQ_query_param_timestamp (&start_date),
+ GNUNET_PQ_query_param_timestamp (&end_date),
+ TALER_PQ_query_param_amount (pg->conn,
+ &fees->wire),
+ TALER_PQ_query_param_amount (pg->conn,
+ &fees->closing),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_end
+ };
+ struct TALER_WireFeeSet wx;
+ struct TALER_MasterSignatureP sig;
+ struct GNUNET_TIME_Timestamp sd;
+ struct GNUNET_TIME_Timestamp ed;
+ enum GNUNET_DB_QueryStatus qs;
+ uint64_t rowid;
+
+ qs = TALER_EXCHANGEDB_get_wire_fee (pg,
+ type,
+ start_date,
+ &rowid,
+ &sd,
+ &ed,
+ &wx,
+ &sig);
+ if (qs < 0)
+ return qs;
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ if (0 != GNUNET_memcmp (&sig,
+ master_sig))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if (0 !=
+ TALER_wire_fee_set_cmp (fees,
+ &wx))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ if ( (GNUNET_TIME_timestamp_cmp (sd,
+ !=,
+ start_date)) ||
+ (GNUNET_TIME_timestamp_cmp (ed,
+ !=,
+ end_date)) )
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ /* equal record already exists */
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+
+ PREPARE (pg,
+ "insert_wire_fee",
+ "INSERT INTO wire_fee "
+ "(wire_method"
+ ",start_date"
+ ",end_date"
+ ",wire_fee"
+ ",closing_fee"
+ ",master_sig"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_wire_fee",
+ params);
+}
diff --git a/src/exchangedb/iterate_active_auditors.c b/src/exchangedb/iterate_active_auditors.c
@@ -0,0 +1,120 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/iterate_active_auditors.c
+ * @brief Implementation of the iterate_active_auditors function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/iterate_active_auditors.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #auditors_cb_helper()
+ */
+struct AuditorsIteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_AuditorsCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+};
+
+
+/**
+ * Helper function for #TALER_EXCHANGEDB_iterate_active_auditors().
+ * Calls the callback with each auditor.
+ *
+ * @param cls a `struct SignkeysIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+auditors_cb_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AuditorsIteratorContext *dic = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_AuditorPublicKeyP auditor_pub;
+ char *auditor_url;
+ char *auditor_name;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
+ &auditor_pub),
+ GNUNET_PQ_result_spec_string ("auditor_url",
+ &auditor_url),
+ GNUNET_PQ_result_spec_string ("auditor_name",
+ &auditor_name),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ dic->cb (dic->cb_cls,
+ &auditor_pub,
+ auditor_url,
+ auditor_name);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_iterate_active_auditors (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ TALER_EXCHANGEDB_AuditorsCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct AuditorsIteratorContext dic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ };
+
+ PREPARE (pg,
+ "select_auditors",
+ "SELECT"
+ " auditor_pub"
+ ",auditor_url"
+ ",auditor_name"
+ " FROM auditors"
+ " WHERE"
+ " is_active;");
+
+ return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "select_auditors",
+ params,
+ &auditors_cb_helper,
+ &dic);
+}
diff --git a/src/exchangedb/iterate_active_signkeys.c b/src/exchangedb/iterate_active_signkeys.c
@@ -0,0 +1,142 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/iterate_active_signkeys.c
+ * @brief Implementation of the iterate_active_signkeys function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/iterate_active_signkeys.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #signkeys_cb_helper()
+ */
+struct SignkeysIteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_ActiveSignkeysCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+};
+
+
+/**
+ * Helper function for #TALER_EXCHANGEDB_iterate_active_signkeys().
+ * Calls the callback with each signkey.
+ *
+ * @param cls a `struct SignkeysIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+signkeys_cb_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SignkeysIteratorContext *dic = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_SignkeyMetaData meta;
+ struct TALER_ExchangePublicKeyP exchange_pub;
+ struct TALER_MasterSignatureP master_sig;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &master_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
+ &exchange_pub),
+ GNUNET_PQ_result_spec_timestamp ("valid_from",
+ &meta.start),
+ GNUNET_PQ_result_spec_timestamp ("expire_sign",
+ &meta.expire_sign),
+ GNUNET_PQ_result_spec_timestamp ("expire_legal",
+ &meta.expire_legal),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ dic->cb (dic->cb_cls,
+ &exchange_pub,
+ &meta,
+ &master_sig);
+ }
+}
+
+
+/**
+ * Function called to invoke @a cb on every non-revoked exchange signing key
+ * that has been signed by the master key. Revoked and (for signing!)
+ * expired keys are skipped. Runs in its own read-only transaction.
+ *
+ * @param pg the database context
+ * @param cb function to call on each signing key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_iterate_active_signkeys (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ TALER_EXCHANGEDB_ActiveSignkeysCallback
+ cb,
+ void *cb_cls)
+{
+ struct GNUNET_TIME_Absolute now = {0};
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_end
+ };
+ struct SignkeysIteratorContext dic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ };
+
+ PREPARE (pg,
+ "select_signkeys",
+ "SELECT"
+ " master_sig"
+ ",exchange_pub"
+ ",valid_from"
+ ",expire_sign"
+ ",expire_legal"
+ " FROM exchange_sign_keys esk"
+ " WHERE"
+ " expire_sign > $1"
+ " AND NOT EXISTS "
+ " (SELECT esk_serial "
+ " FROM signkey_revocations skr"
+ " WHERE esk.esk_serial = skr.esk_serial);");
+ now = GNUNET_TIME_absolute_get ();
+ return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "select_signkeys",
+ params,
+ &signkeys_cb_helper,
+ &dic);
+}
diff --git a/src/exchangedb/iterate_auditor_denominations.c b/src/exchangedb/iterate_auditor_denominations.c
@@ -0,0 +1,117 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/iterate_auditor_denominations.c
+ * @brief Implementation of the iterate_auditor_denominations function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/iterate_auditor_denominations.h"
+#include "helper.h"
+
+/**
+ * Closure for #auditor_denoms_cb_helper()
+ */
+struct AuditorDenomsIteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_AuditorDenominationsCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+};
+
+
+/**
+ * Helper function for #TALER_EXCHANGEDB_iterate_auditor_denominations().
+ * Calls the callback with each auditor and denomination pair.
+ *
+ * @param cls a `struct AuditorDenomsIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+auditor_denoms_cb_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AuditorDenomsIteratorContext *dic = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_AuditorPublicKeyP auditor_pub;
+ struct TALER_DenominationHashP h_denom_pub;
+ struct TALER_AuditorSignatureP auditor_sig;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
+ &auditor_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &h_denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("auditor_sig",
+ &auditor_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ dic->cb (dic->cb_cls,
+ &auditor_pub,
+ &h_denom_pub,
+ &auditor_sig);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_iterate_auditor_denominations (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ TALER_EXCHANGEDB_AuditorDenominationsCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct AuditorDenomsIteratorContext dic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ };
+ /* Used in #postgres_iterate_auditor_denominations() */
+ PREPARE (pg,
+ "select_auditor_denoms",
+ "SELECT"
+ " auditors.auditor_pub"
+ ",denominations.denom_pub_hash"
+ ",auditor_denom_sigs.auditor_sig"
+ " FROM auditor_denom_sigs"
+ " JOIN auditors USING (auditor_uuid)"
+ " JOIN denominations USING (denominations_serial)"
+ " WHERE auditors.is_active;");
+ return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "select_auditor_denoms",
+ params,
+ &auditor_denoms_cb_helper,
+ &dic);
+}
diff --git a/src/exchangedb/iterate_denomination_info.c b/src/exchangedb/iterate_denomination_info.c
@@ -0,0 +1,185 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/iterate_denomination_info.c
+ * @brief Implementation of the iterate_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/iterate_denomination_info.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #domination_cb_helper()
+ */
+struct DenomIteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_DenominationCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+};
+
+
+/**
+ * Helper function for #TALER_EXCHANGEDB_iterate_denomination_info().
+ * Calls the callback with each denomination key.
+ *
+ * @param cls a `struct DenomIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+domination_cb_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct DenomIteratorContext *dic = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dic->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
+ struct TALER_DenominationPublicKey denom_pub;
+ struct TALER_DenominationHashP denom_hash;
+ uint64_t denom_serial;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("denominations_serial",
+ &denom_serial),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &issue.signature),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &denom_hash),
+ GNUNET_PQ_result_spec_timestamp ("valid_from",
+ &issue.start),
+ GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
+ &issue.expire_withdraw),
+ GNUNET_PQ_result_spec_timestamp ("expire_deposit",
+ &issue.expire_deposit),
+ GNUNET_PQ_result_spec_timestamp ("expire_legal",
+ &issue.expire_legal),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+ &issue.value),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+ &issue.fees.withdraw),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &issue.fees.deposit),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+ &issue.fees.refresh),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+ &issue.fees.refund),
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ &denom_pub),
+ GNUNET_PQ_result_spec_uint32 ("age_mask",
+ &issue.age_mask.bits),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ /* Unfortunately we have to carry the age mask in both, the
+ * TALER_DenominationPublicKey and
+ * TALER_EXCHANGEDB_DenominationKeyInformation at different times.
+ * Here we use _both_ so let's make sure the values are the same. */
+ denom_pub.age_mask = issue.age_mask;
+ TALER_denom_pub_hash (&denom_pub,
+ &issue.denom_hash);
+ if (0 !=
+ GNUNET_memcmp (&issue.denom_hash,
+ &denom_hash))
+ {
+ GNUNET_break (0);
+ }
+ else
+ {
+ dic->cb (dic->cb_cls,
+ denom_serial,
+ &denom_pub,
+ &issue);
+ }
+ TALER_denom_pub_free (&denom_pub);
+ }
+}
+
+
+/**
+ * Fetch information about all known denomination keys.
+ *
+ * @param pg the database context
+ * @param cb function to call on each denomination key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_iterate_denomination_info (struct
+ TALER_EXCHANGEDB_PostgresContext *pg
+ ,
+ TALER_EXCHANGEDB_DenominationCallback
+ cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct DenomIteratorContext dic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg
+ };
+
+ PREPARE (pg,
+ "denomination_iterate",
+ "SELECT"
+ " denominations_serial"
+ ",master_sig"
+ ",denom_pub_hash"
+ ",valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin" /* value of this denom */
+ ",fee_withdraw"
+ ",fee_deposit"
+ ",fee_refresh"
+ ",fee_refund"
+ ",denom_pub"
+ ",age_mask"
+ " FROM denominations;");
+ return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "denomination_iterate",
+ params,
+ &domination_cb_helper,
+ &dic);
+}
diff --git a/src/exchangedb/iterate_denominations.c b/src/exchangedb/iterate_denominations.c
@@ -0,0 +1,175 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/iterate_denominations.c
+ * @brief Implementation of the iterate_denominations function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/iterate_denominations.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #dominations_cb_helper()
+ */
+struct DenomsIteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_DenominationsCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+};
+
+
+/**
+ * Helper function for #TALER_EXCHANGEDB_iterate_denominations().
+ * Calls the callback with each denomination key.
+ *
+ * @param cls a `struct DenomsIteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+dominations_cb_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct DenomsIteratorContext *dic = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dic->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0};
+ struct TALER_DenominationPublicKey denom_pub = {0};
+ struct TALER_MasterSignatureP master_sig = {0};
+ struct TALER_DenominationHashP h_denom_pub = {0};
+ bool revoked;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("denominations_serial",
+ &meta.serial),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &master_sig),
+ GNUNET_PQ_result_spec_bool ("revoked",
+ &revoked),
+ GNUNET_PQ_result_spec_timestamp ("valid_from",
+ &meta.start),
+ GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
+ &meta.expire_withdraw),
+ GNUNET_PQ_result_spec_timestamp ("expire_deposit",
+ &meta.expire_deposit),
+ GNUNET_PQ_result_spec_timestamp ("expire_legal",
+ &meta.expire_legal),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+ &meta.value),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+ &meta.fees.withdraw),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &meta.fees.deposit),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+ &meta.fees.refresh),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+ &meta.fees.refund),
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ &denom_pub),
+ GNUNET_PQ_result_spec_uint32 ("age_mask",
+ &meta.age_mask.bits),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ /* make sure the mask information is the same */
+ denom_pub.age_mask = meta.age_mask;
+
+ TALER_denom_pub_hash (&denom_pub,
+ &h_denom_pub);
+ dic->cb (dic->cb_cls,
+ &denom_pub,
+ &h_denom_pub,
+ &meta,
+ &master_sig,
+ revoked);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_iterate_denominations (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ TALER_EXCHANGEDB_DenominationsCallback
+ cb,
+ void *cb_cls)
+{
+ struct GNUNET_TIME_Absolute now
+ = GNUNET_TIME_absolute_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_end
+ };
+ struct DenomsIteratorContext dic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg
+ };
+
+ PREPARE (pg,
+ "select_denominations",
+ "SELECT"
+ " denominations_serial"
+ ",denominations.master_sig"
+ ",denom_revocations_serial_id IS NOT NULL AS revoked"
+ ",valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin" /* value of this denom */
+ ",fee_withdraw"
+ ",fee_deposit"
+ ",fee_refresh"
+ ",fee_refund"
+ ",denom_type"
+ ",age_mask"
+ ",denom_pub"
+ " FROM denominations"
+ " LEFT JOIN "
+ " denomination_revocations USING (denominations_serial)"
+ " WHERE expire_deposit > $1;");
+ return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "select_denominations",
+ params,
+ &dominations_cb_helper,
+ &dic);
+}
diff --git a/src/exchangedb/iterate_kyc_reference.c b/src/exchangedb/iterate_kyc_reference.c
@@ -0,0 +1,126 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file iterate_kyc_reference.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/iterate_kyc_reference.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #iterate_kyc_reference_cb()
+ */
+struct IteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_LegitimizationProcessCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+};
+
+
+/**
+ * Helper function for #TALER_EXCHANGEDB_iterate_kyc_reference().
+ * Calls the callback with each denomination key.
+ *
+ * @param cls a `struct IteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+iterate_kyc_reference_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct IteratorContext *ic = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ char *kyc_provider_name_name;
+ char *provider_user_id;
+ char *legitimization_id;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("provider_name",
+ &kyc_provider_name_name),
+ GNUNET_PQ_result_spec_string ("provider_user_id",
+ &provider_user_id),
+ GNUNET_PQ_result_spec_string ("provider_legitimization_id",
+ &legitimization_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ ic->cb (ic->cb_cls,
+ kyc_provider_name_name,
+ provider_user_id,
+ legitimization_id);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_iterate_kyc_reference (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_LegitimizationProcessCallback lpc,
+ void *lpc_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_end
+ };
+ struct IteratorContext ic = {
+ .cb = lpc,
+ .cb_cls = lpc_cls,
+ .pg = pg
+ };
+
+ PREPARE (pg,
+ "iterate_kyc_reference",
+ "SELECT "
+ " provider_name"
+ ",provider_user_id"
+ ",provider_legitimization_id"
+ " FROM legitimization_processes"
+ " WHERE h_payto=$1;");
+ return GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "iterate_kyc_reference",
+ params,
+ &iterate_kyc_reference_cb,
+ &ic);
+}
diff --git a/src/exchangedb/iterate_reserve_close_info.c b/src/exchangedb/iterate_reserve_close_info.c
@@ -0,0 +1,127 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file iterate_reserve_close_info.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/iterate_reserve_close_info.h"
+#include "helper.h"
+
+/**
+ * Closure for #iterate_reserve_close_info_cb()
+ */
+struct IteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_KYCLOGIC_KycAmountCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+};
+
+
+/**
+ * Helper function for #TALER_EXCHANGEDB_iterate_reserve_close_info().
+ * Calls the callback with each denomination key.
+ *
+ * @param cls a `struct IteratorContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+iterate_reserve_close_info_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct IteratorContext *ic = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ic->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_Amount amount;
+ struct GNUNET_TIME_Absolute ts;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_absolute_time ("execution_date",
+ &ts),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ ic->cb (ic->cb_cls,
+ &amount,
+ ts);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_iterate_reserve_close_info (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_KYCLOGIC_KycAmountCallback kac,
+ void *kac_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_absolute_time (&time_limit),
+ GNUNET_PQ_query_param_end
+ };
+ struct IteratorContext ic = {
+ .cb = kac,
+ .cb_cls = kac_cls,
+ .pg = pg
+ };
+
+ PREPARE (pg,
+ "iterate_reserve_close_info",
+ "SELECT amount"
+ " ,execution_date"
+ " FROM reserves_close"
+ " WHERE wire_target_h_payto IN ("
+ " SELECT wire_target_h_payto"
+ " FROM wire_targets"
+ " WHERE h_normalized_payto=$1"
+ " )"
+ " AND execution_date >= $2"
+ " ORDER BY execution_date DESC");
+ return GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "iterate_reserve_close_info",
+ params,
+ &iterate_reserve_close_info_cb,
+ &ic);
+}
diff --git a/src/exchangedb/kyc_provider_account_lookup.c b/src/exchangedb/kyc_provider_account_lookup.c
@@ -0,0 +1,66 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/kyc_provider_account_lookup.c
+ * @brief Implementation of the kyc_provider_account_lookup function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/kyc_provider_account_lookup.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_kyc_provider_account_lookup (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *provider_name,
+ const char *provider_legitimization_id,
+ struct TALER_NormalizedPaytoHashP *h_payto,
+ bool *is_wallet,
+ uint64_t *process_row)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (provider_legitimization_id),
+ GNUNET_PQ_query_param_string (provider_name),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("h_payto",
+ h_payto),
+ GNUNET_PQ_result_spec_bool ("is_wallet",
+ is_wallet),
+ GNUNET_PQ_result_spec_uint64 ("legitimization_process_serial_id",
+ process_row),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_wire_target_by_legitimization_id",
+ "SELECT "
+ " lp.h_payto"
+ ",kt.is_wallet"
+ ",lp.legitimization_process_serial_id"
+ " FROM legitimization_processes lp"
+ " JOIN kyc_targets kt"
+ " ON (lp.h_payto = kt.h_normalized_payto)"
+ " WHERE provider_legitimization_id=$1"
+ " AND provider_name=$2;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "get_wire_target_by_legitimization_id",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/kycauth_in_insert.c b/src/exchangedb/kycauth_in_insert.c
@@ -0,0 +1,78 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/kycauth_in_insert.c
+ * @brief Implementation of the kycauth_in_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/kycauth_in_insert.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_kycauth_in_insert (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const union TALER_AccountPublicKeyP *account_pub,
+ const struct TALER_Amount *credit_amount,
+ struct GNUNET_TIME_Timestamp execution_date,
+ const struct TALER_FullPayto debit_account_uri,
+ const char *section_name,
+ uint64_t serial_id)
+{
+ struct TALER_NormalizedPaytoHashP h_normalized_payto;
+ struct TALER_FullPaytoHashP h_full_payto;
+
+ TALER_full_payto_hash (debit_account_uri,
+ &h_full_payto);
+ TALER_full_payto_normalize_and_hash (debit_account_uri,
+ &h_normalized_payto);
+ {
+ struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = h_normalized_payto
+ };
+ char *notify_s
+ = GNUNET_PQ_get_event_notify_channel (&rep.header);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ TALER_PQ_query_param_amount (pg->conn,
+ credit_amount),
+ GNUNET_PQ_query_param_auto_from_type (&h_full_payto),
+ GNUNET_PQ_query_param_auto_from_type (&h_normalized_payto),
+ GNUNET_PQ_query_param_string (debit_account_uri.full_payto),
+ GNUNET_PQ_query_param_string (section_name),
+ GNUNET_PQ_query_param_timestamp (&execution_date),
+ GNUNET_PQ_query_param_string (notify_s),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "kycauth_in_insert",
+ "CALL"
+ " exchange_do_kycauth_in_insert"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
+ qs = GNUNET_PQ_eval_prepared_non_select (
+ pg->conn,
+ "kycauth_in_insert",
+ params);
+ GNUNET_free (notify_s);
+ return qs;
+ }
+}
diff --git a/src/exchangedb/lookup_active_legitimization.c b/src/exchangedb/lookup_active_legitimization.c
@@ -0,0 +1,62 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_pending_legitimization.c
+ * @brief Implementation of the lookup_pending_legitimization function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_active_legitimization.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_active_legitimization (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t legitimization_process_serial_id,
+ uint32_t *measure_index,
+ json_t **jmeasures)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&legitimization_process_serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_json (
+ "jmeasures",
+ jmeasures),
+ GNUNET_PQ_result_spec_uint32 (
+ "measure_index",
+ measure_index),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "lookup_active_legitimization",
+ "SELECT "
+ " lm.jmeasures::TEXT"
+ ",lp.measure_index"
+ " FROM legitimization_processes lp"
+ " JOIN legitimization_measures lm"
+ " USING (legitimization_measure_serial_id)"
+ " WHERE lp.legitimization_process_serial_id=$1"
+ " AND NOT lm.is_finished;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "lookup_active_legitimization",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_aml_file_number.c b/src/exchangedb/lookup_aml_file_number.c
@@ -0,0 +1,59 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_aml_file_number.c
+ * @brief Implementation of the lookup_aml_file_number function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_aml_file_number.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_aml_file_number (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ uint64_t *kyc_target_row,
+ bool *is_wallet)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "kyc_target_serial_id",
+ kyc_target_row),
+ GNUNET_PQ_result_spec_bool (
+ "is_wallet",
+ is_wallet),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "lookup_aml_file_number",
+ "SELECT "
+ " kyc_target_serial_id"
+ ",is_wallet"
+ " FROM kyc_targets"
+ " WHERE h_normalized_payto=$1");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "lookup_aml_file_number",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_aml_history.c b/src/exchangedb/lookup_aml_history.c
@@ -0,0 +1,200 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_aml_history.c
+ * @brief Implementation of the lookup_aml_history function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_aml_history.h"
+#include "helper.h"
+
+
+/**
+ * Closure for callbacks called from #TALER_EXCHANGEDB_lookup_aml_history()
+ */
+struct AmlHistoryContext
+{
+
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_AmlHistoryCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to 'true' if the transaction failed.
+ */
+ bool failed;
+
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct AmlHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_aml_entry (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AmlHistoryContext *ahc = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t outcome_serial_id;
+ struct GNUNET_TIME_Timestamp decision_time;
+ char *justification;
+ struct TALER_AmlOfficerPublicKeyP decider_pub;
+ json_t *jproperties;
+ json_t *jnew_rules = NULL;
+ bool to_investigate;
+ bool is_active;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("outcome_serial_id",
+ &outcome_serial_id),
+ GNUNET_PQ_result_spec_timestamp ("decision_time",
+ &decision_time),
+ GNUNET_PQ_result_spec_string ("justification",
+ &justification),
+ GNUNET_PQ_result_spec_auto_from_type ("decider_pub",
+ &decider_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json ("jproperties",
+ &jproperties),
+ NULL),
+ TALER_PQ_result_spec_json ("jnew_rules",
+ &jnew_rules),
+ GNUNET_PQ_result_spec_bool ("to_investigate",
+ &to_investigate),
+ GNUNET_PQ_result_spec_bool ("is_active",
+ &is_active),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ahc->failed = true;
+ return;
+ }
+ ahc->cb (ahc->cb_cls,
+ outcome_serial_id,
+ decision_time,
+ justification,
+ &decider_pub,
+ jproperties,
+ jnew_rules,
+ to_investigate,
+ is_active);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_aml_history (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ uint64_t offset,
+ int64_t limit,
+ TALER_EXCHANGEDB_AmlHistoryCallback cb,
+ void *cb_cls)
+{
+ struct AmlHistoryContext ahc = {
+ .pg = pg,
+ .cb = cb,
+ .cb_cls = cb_cls
+ };
+ uint64_t ulimit = (limit < 0) ? (-limit) : limit;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "lookup_aml_history_desc",
+ "SELECT"
+ " lo.decision_time"
+ ",lo.outcome_serial_id"
+ ",ah.justification"
+ ",ah.decider_pub"
+ ",lo.jproperties::TEXT"
+ ",lo.jnew_rules::TEXT"
+ ",lo.to_investigate"
+ ",lo.is_active"
+ " FROM aml_history ah"
+ " JOIN legitimization_outcomes lo"
+ " USING (outcome_serial_id)"
+ " WHERE ah.h_payto=$1"
+ " AND lo.outcome_serial_id < $2"
+ " ORDER BY outcome_serial_id DESC"
+ " LIMIT $3;");
+ PREPARE (pg,
+ "lookup_aml_history_asc",
+ "SELECT"
+ " lo.decision_time"
+ ",lo.outcome_serial_id"
+ ",ah.justification"
+ ",ah.decider_pub"
+ ",lo.jproperties::TEXT"
+ ",lo.jnew_rules::TEXT"
+ ",lo.to_investigate"
+ ",lo.is_active"
+ " FROM aml_history ah"
+ " JOIN legitimization_outcomes lo"
+ " USING (outcome_serial_id)"
+ " WHERE ah.h_payto=$1"
+ " AND lo.outcome_serial_id > $2"
+ " ORDER BY outcome_serial_id ASC"
+ " LIMIT $3;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ (limit < 0)
+ ? "lookup_aml_history_desc"
+ : "lookup_aml_history_asc",
+ params,
+ &handle_aml_entry,
+ &ahc);
+ if (qs <= 0)
+ return qs;
+ if (ahc.failed)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ return qs;
+}
diff --git a/src/exchangedb/lookup_aml_officer.c b/src/exchangedb/lookup_aml_officer.c
@@ -0,0 +1,68 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_aml_officer.c
+ * @brief Implementation of the lookup_aml_officer function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_aml_officer.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_aml_officer (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ struct TALER_MasterSignatureP *master_sig,
+ char **decider_name,
+ bool *is_active,
+ bool *read_only,
+ struct GNUNET_TIME_Absolute *last_change)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (decider_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ master_sig),
+ GNUNET_PQ_result_spec_string ("decider_name",
+ decider_name),
+ GNUNET_PQ_result_spec_bool ("is_active",
+ is_active),
+ GNUNET_PQ_result_spec_bool ("read_only",
+ read_only),
+ GNUNET_PQ_result_spec_absolute_time ("last_change",
+ last_change),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "lookup_aml_officer",
+ "SELECT "
+ " master_sig"
+ ",decider_name"
+ ",is_active"
+ ",read_only"
+ ",last_change"
+ " FROM aml_staff"
+ " WHERE decider_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "lookup_aml_officer",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_auditor_status.c b/src/exchangedb/lookup_auditor_status.c
@@ -0,0 +1,57 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_auditor_status.c
+ * @brief Implementation of the lookup_auditor_status function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_auditor_status.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_auditor_status (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ char **auditor_url,
+ bool *enabled)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("auditor_url",
+ auditor_url),
+ GNUNET_PQ_result_spec_bool ("is_active",
+ enabled),
+ GNUNET_PQ_result_spec_end
+ };
+
+ /* Used in #postgres_lookup_auditor_status() */
+ PREPARE (pg,
+ "lookup_auditor_status",
+ "SELECT"
+ " auditor_url"
+ ",is_active"
+ " FROM auditors"
+ " WHERE auditor_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_auditor_status",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_auditor_timestamp.c b/src/exchangedb/lookup_auditor_timestamp.c
@@ -0,0 +1,53 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_auditor_timestamp.c
+ * @brief Implementation of the lookup_auditor_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_auditor_timestamp.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_auditor_timestamp (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ struct GNUNET_TIME_Timestamp *last_date)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("last_change",
+ last_date),
+ GNUNET_PQ_result_spec_end
+ };
+
+ /* Used in #postgres_lookup_auditor_timestamp() */
+ PREPARE (pg,
+ "lookup_auditor_timestamp",
+ "SELECT"
+ " last_change"
+ " FROM auditors"
+ " WHERE auditor_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_auditor_timestamp",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_completed_legitimization.c b/src/exchangedb/lookup_completed_legitimization.c
@@ -0,0 +1,95 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_completed_legitimization.c
+ * @brief Implementation of the lookup_pending_legitimization function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_completed_legitimization.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_completed_legitimization (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t legitimization_measure_serial_id,
+ uint32_t measure_index,
+ struct TALER_AccountAccessTokenP *access_token,
+ struct TALER_NormalizedPaytoHashP *h_payto,
+ bool *is_wallet,
+ json_t **jmeasures,
+ bool *is_finished,
+ size_t *encrypted_attributes_len,
+ void **encrypted_attributes
+ )
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id),
+ GNUNET_PQ_query_param_uint32 (&measure_index),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_json (
+ "jmeasures",
+ jmeasures),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_normalized_payto",
+ h_payto),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "access_token",
+ access_token),
+ GNUNET_PQ_result_spec_bool (
+ "is_finished",
+ is_finished),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_variable_size (
+ "encrypted_attributes",
+ encrypted_attributes,
+ encrypted_attributes_len),
+ NULL),
+ GNUNET_PQ_result_spec_bool (
+ "is_wallet",
+ is_wallet),
+ GNUNET_PQ_result_spec_end
+ };
+
+ *encrypted_attributes_len = 0;
+ *encrypted_attributes = NULL;
+ PREPARE (pg,
+ "lookup_completed_legitimization",
+ "SELECT "
+ " lm.jmeasures::TEXT"
+ ",kt.h_normalized_payto"
+ ",kt.is_wallet"
+ ",lm.access_token"
+ ",lm.is_finished"
+ ",ka.encrypted_attributes"
+ " FROM legitimization_measures lm"
+ " JOIN kyc_targets kt"
+ " ON (lm.access_token = kt.access_token)"
+ " LEFT JOIN legitimization_processes lp"
+ " ON (lm.legitimization_measure_serial_id = lp.legitimization_measure_serial_id)"
+ " LEFT JOIN kyc_attributes ka"
+ " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)"
+ " WHERE lm.legitimization_measure_serial_id=$1"
+ " AND lp.measure_index=$2;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "lookup_completed_legitimization",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_denomination_key.c b/src/exchangedb/lookup_denomination_key.c
@@ -0,0 +1,79 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_denomination_key.c
+ * @brief Implementation of the lookup_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_denomination_key.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_denomination_key (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("valid_from",
+ &meta->start),
+ GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
+ &meta->expire_withdraw),
+ GNUNET_PQ_result_spec_timestamp ("expire_deposit",
+ &meta->expire_deposit),
+ GNUNET_PQ_result_spec_timestamp ("expire_legal",
+ &meta->expire_legal),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
+ &meta->value),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
+ &meta->fees.withdraw),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &meta->fees.deposit),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
+ &meta->fees.refresh),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
+ &meta->fees.refund),
+ GNUNET_PQ_result_spec_uint32 ("age_mask",
+ &meta->age_mask.bits),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "lookup_denomination_key",
+ "SELECT"
+ " valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin"
+ ",fee_withdraw"
+ ",fee_deposit"
+ ",fee_refresh"
+ ",fee_refund"
+ ",age_mask"
+ " FROM denominations"
+ " WHERE denom_pub_hash=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_denomination_key",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_global_fee_by_time.c b/src/exchangedb/lookup_global_fee_by_time.c
@@ -0,0 +1,180 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_global_fee_by_time.c
+ * @brief Implementation of the lookup_global_fee_by_time function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_global_fee_by_time.h"
+#include "helper.h"
+
+/**
+ * Closure for #global_fee_by_time_helper()
+ */
+struct GlobalFeeLookupContext
+{
+
+ /**
+ * Set to the wire fees. Set to invalid if fees conflict over
+ * the given time period.
+ */
+ struct TALER_GlobalFeeSet *fees;
+
+ /**
+ * Set to timeout of unmerged purses
+ */
+ struct GNUNET_TIME_Relative *purse_timeout;
+
+ /**
+ * Set to history expiration for reserves.
+ */
+ struct GNUNET_TIME_Relative *history_expiration;
+
+ /**
+ * Set to number of free purses per account.
+ */
+ uint32_t *purse_account_limit;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+};
+
+
+/**
+ * Helper function for #TALER_EXCHANGEDB_lookup_global_fee_by_time().
+ * Calls the callback with each denomination key.
+ *
+ * @param cls a `struct GlobalFeeLookupContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+global_fee_by_time_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GlobalFeeLookupContext *wlc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = wlc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_GlobalFeeSet fs;
+ struct GNUNET_TIME_Relative purse_timeout;
+ struct GNUNET_TIME_Relative history_expiration;
+ uint32_t purse_account_limit;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
+ &fs.history),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
+ &fs.account),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
+ &fs.purse),
+ GNUNET_PQ_result_spec_relative_time ("purse_timeout",
+ &purse_timeout),
+ GNUNET_PQ_result_spec_relative_time ("history_expiration",
+ &history_expiration),
+ GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
+ &purse_account_limit),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ /* invalidate */
+ memset (wlc->fees,
+ 0,
+ sizeof (struct TALER_GlobalFeeSet));
+ return;
+ }
+ if (0 == i)
+ {
+ *wlc->fees = fs;
+ *wlc->purse_timeout = purse_timeout;
+ *wlc->history_expiration = history_expiration;
+ *wlc->purse_account_limit = purse_account_limit;
+ continue;
+ }
+ if ( (0 !=
+ TALER_global_fee_set_cmp (&fs,
+ wlc->fees)) ||
+ (purse_account_limit != *wlc->purse_account_limit) ||
+ (GNUNET_TIME_relative_cmp (purse_timeout,
+ !=,
+ *wlc->purse_timeout)) ||
+ (GNUNET_TIME_relative_cmp (history_expiration,
+ !=,
+ *wlc->history_expiration)) )
+ {
+ /* invalidate */
+ memset (wlc->fees,
+ 0,
+ sizeof (struct TALER_GlobalFeeSet));
+ return;
+ }
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_global_fee_by_time (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Timestamp end_time,
+ struct TALER_GlobalFeeSet *fees,
+ struct GNUNET_TIME_Relative *purse_timeout,
+ struct GNUNET_TIME_Relative *history_expiration,
+ uint32_t *purse_account_limit)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&start_time),
+ GNUNET_PQ_query_param_timestamp (&end_time),
+ GNUNET_PQ_query_param_end
+ };
+ struct GlobalFeeLookupContext wlc = {
+ .fees = fees,
+ .purse_timeout = purse_timeout,
+ .history_expiration = history_expiration,
+ .purse_account_limit = purse_account_limit,
+ .pg = pg
+ };
+
+ PREPARE (pg,
+ "lookup_global_fee_by_time",
+ "SELECT"
+ " history_fee"
+ ",account_fee"
+ ",purse_fee"
+ ",purse_timeout"
+ ",history_expiration"
+ ",purse_account_limit"
+ " FROM global_fee"
+ " WHERE end_date > $1"
+ " AND start_date < $2;");
+ return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "lookup_global_fee_by_time",
+ params,
+ &global_fee_by_time_helper,
+ &wlc);
+}
diff --git a/src/exchangedb/lookup_h_payto_by_access_token.c b/src/exchangedb/lookup_h_payto_by_access_token.c
@@ -0,0 +1,59 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_h_payto_by_access_token.c
+ * @brief Implementation of the lookup_h_payto_by_access_token function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_h_payto_by_access_token.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_h_payto_by_access_token (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AccountAccessTokenP *access_token,
+ struct TALER_NormalizedPaytoHashP *h_payto,
+ bool *is_wallet)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (access_token),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_normalized_payto",
+ h_payto),
+ GNUNET_PQ_result_spec_bool (
+ "is_wallet",
+ is_wallet),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "lookup_h_payto_by_access_token",
+ "SELECT "
+ " h_normalized_payto"
+ " ,is_wallet"
+ " FROM kyc_targets"
+ " WHERE (access_token = $1);");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "lookup_h_payto_by_access_token",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_kyc_history.c b/src/exchangedb/lookup_kyc_history.c
@@ -0,0 +1,192 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_kyc_history.c
+ * @brief Implementation of the lookup_kyc_history function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_kyc_history.h"
+#include "helper.h"
+
+/**
+ * Closure for callbacks called from #TALER_EXCHANGEDB_lookup_kyc_history()
+ */
+struct KycHistoryContext
+{
+
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_KycHistoryCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to 'true' if the transaction failed.
+ */
+ bool failed;
+
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct KycHistoryContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_kyc_entry (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycHistoryContext *khc = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ char *provider_name = NULL;
+ bool finished;
+ uint32_t error_code;
+ char *error_message = NULL;
+ char *provider_user_id = NULL;
+ char *provider_legitimization_id = NULL;
+ struct GNUNET_TIME_Timestamp collection_time;
+ struct GNUNET_TIME_Absolute expiration_time
+ = GNUNET_TIME_UNIT_ZERO_ABS;
+ void *encrypted_attributes;
+ size_t encrypted_attributes_len;
+
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("provider_name",
+ &provider_name),
+ NULL),
+ GNUNET_PQ_result_spec_bool ("finished",
+ &finished),
+ GNUNET_PQ_result_spec_uint32 ("error_code",
+ &error_code),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("error_message",
+ &error_message),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("provider_user_id",
+ &provider_user_id),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("provider_legitimization_id",
+ &provider_legitimization_id),
+ NULL),
+ GNUNET_PQ_result_spec_timestamp ("collection_time",
+ &collection_time),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_absolute_time ("expiration_time",
+ &expiration_time),
+ NULL),
+ GNUNET_PQ_result_spec_variable_size ("encrypted_attributes",
+ &encrypted_attributes,
+ &encrypted_attributes_len),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ khc->failed = true;
+ return;
+ }
+ khc->cb (khc->cb_cls,
+ provider_name,
+ finished,
+ (enum TALER_ErrorCode) error_code,
+ error_message,
+ provider_user_id,
+ provider_legitimization_id,
+ collection_time,
+ expiration_time,
+ encrypted_attributes_len,
+ encrypted_attributes);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_kyc_history (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_KycHistoryCallback cb,
+ void *cb_cls)
+{
+ struct KycHistoryContext khc = {
+ .pg = pg,
+ .cb = cb,
+ .cb_cls = cb_cls
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "lookup_kyc_history",
+ "SELECT"
+ " lp.provider_name"
+ ",lp.finished"
+ ",lp.error_code"
+ ",lp.error_message"
+ ",lp.provider_user_id"
+ ",lp.provider_legitimization_id"
+ ",ka.collection_time"
+ ",ka.expiration_time"
+ ",ka.encrypted_attributes"
+ " FROM kyc_attributes ka"
+ " JOIN legitimization_processes lp"
+ " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)"
+ " WHERE ka.h_payto=$1"
+ " ORDER BY ka.collection_time DESC;");
+
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "lookup_kyc_history",
+ params,
+ &handle_kyc_entry,
+ &khc);
+ if (qs <= 0)
+ return qs;
+ if (khc.failed)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ return qs;
+}
diff --git a/src/exchangedb/lookup_kyc_process_by_account.c b/src/exchangedb/lookup_kyc_process_by_account.c
@@ -0,0 +1,90 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_kyc_process_by_account.c
+ * @brief Implementation of the lookup_kyc_process_by_account function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_kyc_process_by_account.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_kyc_process_by_account (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *provider_name,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ uint64_t *process_row,
+ struct GNUNET_TIME_Absolute *expiration,
+ char **provider_account_id,
+ char **provider_legitimization_id,
+ bool *is_wallet)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_string (provider_name),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "legitimization_process_serial_id",
+ process_row),
+ GNUNET_PQ_result_spec_absolute_time (
+ "expiration_time",
+ expiration),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string (
+ "provider_user_id",
+ provider_account_id),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string (
+ "provider_legitimization_id",
+ provider_legitimization_id),
+ NULL),
+ GNUNET_PQ_result_spec_bool (
+ "is_wallet",
+ is_wallet),
+ GNUNET_PQ_result_spec_end
+ };
+
+ *provider_account_id = NULL;
+ *provider_legitimization_id = NULL;
+ PREPARE (pg,
+ "lookup_kyc_process_by_account",
+ "SELECT "
+ " lp.legitimization_process_serial_id"
+ ",lp.expiration_time"
+ ",lp.provider_user_id"
+ ",lp.provider_legitimization_id"
+ ",kt.is_wallet"
+ " FROM legitimization_processes lp"
+ " JOIN kyc_targets kt"
+ " ON (lp.h_payto = kt.h_normalized_payto)"
+ " WHERE h_payto=$1"
+ " AND provider_name=$2"
+ " AND NOT finished"
+ /* Note: there *should* only be one unfinished
+ match, so this is just to be safe(r): */
+ " ORDER BY lp.expiration_time DESC"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "lookup_kyc_process_by_account",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_kyc_requirement_by_row.c b/src/exchangedb/lookup_kyc_requirement_by_row.c
@@ -0,0 +1,109 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_kyc_requirement_by_row.c
+ * @brief Implementation of the lookup_kyc_requirement_by_row function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_kyc_requirement_by_row.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_kyc_requirement_by_row (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const union TALER_AccountPublicKeyP *account_pub,
+ enum GNUNET_GenericReturnValue *is_wallet,
+ struct TALER_AccountAccessTokenP *access_token,
+ uint64_t *rule_gen,
+ json_t **jrules,
+ bool *aml_review,
+ bool *kyc_required)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_auto_from_type (account_pub),
+ GNUNET_PQ_query_param_end
+ };
+ bool bis_wallet;
+ bool bis_wallet_unknown;
+ bool not_found;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("access_token",
+ access_token),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ /* can be NULL due to LEFT JOIN */
+ TALER_PQ_result_spec_json ("jrules",
+ jrules),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ /* can be NULL due to LEFT JOIN */
+ GNUNET_PQ_result_spec_bool ("is_wallet",
+ &bis_wallet),
+ &bis_wallet_unknown),
+ GNUNET_PQ_result_spec_allow_null (
+ /* can be NULL due to LEFT JOIN */
+ GNUNET_PQ_result_spec_bool ("aml_review",
+ aml_review),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("rule_gen",
+ rule_gen),
+ NULL),
+ GNUNET_PQ_result_spec_bool ("kyc_required",
+ kyc_required),
+ GNUNET_PQ_result_spec_bool ("not_found",
+ ¬_found),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ *jrules = NULL;
+ *aml_review = false;
+ *is_wallet = GNUNET_SYSERR;
+ *rule_gen = 0;
+ memset (access_token,
+ 0,
+ sizeof (*access_token));
+ PREPARE (pg,
+ "lookup_kyc_requirement_by_row",
+ "SELECT "
+ " out_access_token AS access_token"
+ ",out_jrules::TEXT AS jrules"
+ ",out_is_wallet AS is_wallet"
+ ",out_not_found AS not_found"
+ ",out_aml_review AS aml_review"
+ ",out_kyc_required AS kyc_required"
+ ",out_rule_gen AS rule_gen"
+ " FROM exchange_do_lookup_kyc_requirement_by_row"
+ " ($1, $2);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "lookup_kyc_requirement_by_row",
+ params,
+ rs);
+ if (qs <= 0)
+ return qs;
+ if (! bis_wallet_unknown)
+ *is_wallet = (bis_wallet) ? GNUNET_YES : GNUNET_NO;
+ if (not_found)
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ return qs;
+}
diff --git a/src/exchangedb/lookup_kyc_status_by_token.c b/src/exchangedb/lookup_kyc_status_by_token.c
@@ -0,0 +1,61 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_kyc_status_by_token.c
+ * @brief Implementation of the lookup_kyc_status_by_token function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_kyc_status_by_token.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_kyc_status_by_token (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AccountAccessTokenP *access_token,
+ uint64_t *row,
+ json_t **jmeasures)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (access_token),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "legitimization_measure_serial_id",
+ row),
+ TALER_PQ_result_spec_json (
+ "jmeasures",
+ jmeasures),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "lookup_kyc_status_by_token",
+ "SELECT"
+ " legitimization_measure_serial_id"
+ ",jmeasures::TEXT"
+ " FROM legitimization_measures"
+ " WHERE access_token=$1"
+ " AND NOT is_finished"
+ " ORDER BY display_priority DESC"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_kyc_status_by_token",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_pending_legitimization.c b/src/exchangedb/lookup_pending_legitimization.c
@@ -0,0 +1,76 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_pending_legitimization.c
+ * @brief Implementation of the lookup_pending_legitimization function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_pending_legitimization.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_pending_legitimization (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t legitimization_measure_serial_id,
+ struct TALER_AccountAccessTokenP *access_token,
+ struct TALER_NormalizedPaytoHashP *h_payto,
+ json_t **jmeasures,
+ bool *is_finished,
+ bool *is_wallet)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_json (
+ "jmeasures",
+ jmeasures),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_normalized_payto",
+ h_payto),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "access_token",
+ access_token),
+ GNUNET_PQ_result_spec_bool (
+ "is_finished",
+ is_finished),
+ GNUNET_PQ_result_spec_bool (
+ "is_wallet",
+ is_wallet),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "lookup_pending_legitimization",
+ "SELECT "
+ " lm.jmeasures::TEXT"
+ ",kt.h_normalized_payto"
+ ",kt.is_wallet"
+ ",lm.access_token"
+ ",lm.is_finished"
+ " FROM legitimization_measures lm"
+ " JOIN kyc_targets kt"
+ " USING (access_token)"
+ " WHERE lm.legitimization_measure_serial_id=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "lookup_pending_legitimization",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_records_by_table.c b/src/exchangedb/lookup_records_by_table.c
@@ -0,0 +1,3802 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2020-2025 Taler Systems SA
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet 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
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @file exchangedb/lookup_records_by_table.c
+ * @brief implementation of lookup_records_by_table
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_records_by_table.h"
+#include "helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+/**
+ * Closure for callbacks used by #postgres_lookup_records_by_table.
+ */
+struct LookupRecordsByTableContext
+{
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_ReplicationCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Set to true on errors.
+ */
+ bool error;
+};
+
+
+/**
+ * Function called with denominations table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_denominations (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_DENOMINATIONS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_uint32 (
+ "denom_type",
+ &td.details.denominations.denom_type),
+ GNUNET_PQ_result_spec_uint32 (
+ "age_mask",
+ &td.details.denominations.age_mask),
+ TALER_PQ_result_spec_denom_pub (
+ "denom_pub",
+ &td.details.denominations.denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "master_sig",
+ &td.details.denominations.master_sig),
+ GNUNET_PQ_result_spec_timestamp (
+ "valid_from",
+ &td.details.denominations.valid_from),
+ GNUNET_PQ_result_spec_timestamp (
+ "expire_withdraw",
+ &td.details.denominations.
+ expire_withdraw),
+ GNUNET_PQ_result_spec_timestamp (
+ "expire_deposit",
+ &td.details.denominations.
+ expire_deposit),
+ GNUNET_PQ_result_spec_timestamp (
+ "expire_legal",
+ &td.details.denominations.expire_legal),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "coin",
+ &td.details.denominations.coin),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "fee_withdraw",
+ &td.details.denominations.fees.withdraw),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "fee_deposit",
+ &td.details.denominations.fees.deposit),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "fee_refresh",
+ &td.details.denominations.fees.refresh),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "fee_refund",
+ &td.details.denominations.fees.refund),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with denomination_revocations table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_denomination_revocations (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_uint64 (
+ "denominations_serial",
+ &td.details.denomination_revocations.denominations_serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "master_sig",
+ &td.details.denomination_revocations.master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with wire_targets table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_wire_targets (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_WIRE_TARGETS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_string (
+ "payto_uri",
+ &td.details.wire_targets.full_payto_uri.full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with wire_targets table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_kyc_targets (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_KYC_TARGETS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_normalized_payto",
+ &td.details.kyc_targets.h_normalized_payto),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "access_token",
+ &td.details.kyc_targets.access_token),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type (
+ "target_pub",
+ &td.details.kyc_targets.target_pub),
+ &td.details.kyc_targets.no_account),
+ GNUNET_PQ_result_spec_bool (
+ "is_wallet",
+ &td.details.kyc_targets.is_wallet),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with reserves table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_reserves (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_RESERVES
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &td.details.reserves.reserve_pub),
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ &td.details.reserves.expiration_date),
+ GNUNET_PQ_result_spec_timestamp ("gc_date",
+ &td.details.reserves.gc_date),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with reserves_in table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_reserves_in (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_RESERVES_IN
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.reserves_in.reserve_pub),
+ GNUNET_PQ_result_spec_uint64 (
+ "wire_reference",
+ &td.details.reserves_in.wire_reference),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "credit",
+ &td.details.reserves_in.credit),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wire_source_h_payto",
+ &td.details.reserves_in.sender_account_h_payto),
+ GNUNET_PQ_result_spec_string (
+ "exchange_account_section",
+ &td.details.reserves_in.exchange_account_section),
+ GNUNET_PQ_result_spec_timestamp (
+ "execution_date",
+ &td.details.reserves_in.execution_date),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with kycauth_in table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_kycauth_in (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_KYCAUTHS_IN
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "account_pub",
+ &td.details.kycauth_in.account_pub),
+ GNUNET_PQ_result_spec_uint64 (
+ "wire_reference",
+ &td.details.kycauth_in.wire_reference),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "credit",
+ &td.details.kycauth_in.credit),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wire_source_h_payto",
+ &td.details.kycauth_in.sender_account_h_payto),
+ GNUNET_PQ_result_spec_string (
+ "exchange_account_section",
+ &td.details.kycauth_in.exchange_account_section),
+ GNUNET_PQ_result_spec_timestamp (
+ "execution_date",
+ &td.details.kycauth_in.execution_date),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with reserves_close table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_reserves_close (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_RESERVES_CLOSE
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.reserves_close.reserve_pub),
+ GNUNET_PQ_result_spec_timestamp (
+ "execution_date",
+ &td.details.reserves_close.execution_date),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wtid",
+ &td.details.reserves_close.wtid),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wire_target_h_payto",
+ &td.details.reserves_close.sender_account_h_payto),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount",
+ &td.details.reserves_close.amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "closing_fee",
+ &td.details.reserves_close.closing_fee),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with reserves_open_requests table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_reserves_open_requests (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.reserves_open_requests.reserve_pub),
+ GNUNET_PQ_result_spec_timestamp (
+ "request_timestamp",
+ &td.details.reserves_open_requests.request_timestamp),
+ GNUNET_PQ_result_spec_timestamp (
+ "expiration_date",
+ &td.details.reserves_open_requests.expiration_date),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_sig",
+ &td.details.reserves_open_requests.reserve_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "reserve_payment",
+ &td.details.reserves_open_requests.reserve_payment),
+ GNUNET_PQ_result_spec_uint32 (
+ "requested_purse_limit",
+ &td.details.reserves_open_requests.requested_purse_limit),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with reserves_open_deposits table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_reserves_open_deposits (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_sig",
+ &td.details.reserves_open_deposits.reserve_sig),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.reserves_open_deposits.reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_pub",
+ &td.details.reserves_open_deposits.coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_sig",
+ &td.details.reserves_open_deposits.coin_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "contribution",
+ &td.details.reserves_open_deposits.contribution),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with auditors table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_auditors (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_AUDITORS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
+ &td.details.auditors.auditor_pub),
+ GNUNET_PQ_result_spec_string ("auditor_url",
+ &td.details.auditors.auditor_url),
+ GNUNET_PQ_result_spec_string ("auditor_name",
+ &td.details.auditors.auditor_name),
+ GNUNET_PQ_result_spec_bool ("is_active",
+ &td.details.auditors.is_active),
+ GNUNET_PQ_result_spec_timestamp ("last_change",
+ &td.details.auditors.last_change),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with auditor_denom_sigs table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_auditor_denom_sigs (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_uint64 (
+ "auditor_uuid",
+ &td.details.auditor_denom_sigs.auditor_uuid),
+ GNUNET_PQ_result_spec_uint64 (
+ "denominations_serial",
+ &td.details.auditor_denom_sigs.denominations_serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "auditor_sig",
+ &td.details.auditor_denom_sigs.auditor_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with exchange_sign_keys table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_exchange_sign_keys (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
+ &td.details.exchange_sign_keys.
+ exchange_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &td.details.exchange_sign_keys.
+ master_sig),
+ GNUNET_PQ_result_spec_timestamp ("valid_from",
+ &td.details.exchange_sign_keys.meta.
+ start),
+ GNUNET_PQ_result_spec_timestamp ("expire_sign",
+ &td.details.exchange_sign_keys.meta.
+ expire_sign),
+ GNUNET_PQ_result_spec_timestamp ("expire_legal",
+ &td.details.exchange_sign_keys.meta.
+ expire_legal),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with signkey_revocations table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_signkey_revocations (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_uint64 ("esk_serial",
+ &td.details.signkey_revocations.esk_serial),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &td.details.signkey_revocations.
+ master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with known_coins table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_known_coins (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_KNOWN_COINS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_pub",
+ &td.details.known_coins.coin_pub),
+ TALER_PQ_result_spec_denom_sig (
+ "denom_sig",
+ &td.details.known_coins.denom_sig),
+ GNUNET_PQ_result_spec_uint64 (
+ "denominations_serial",
+ &td.details.known_coins.denominations_serial),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with refresh table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_refresh (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_REFRESH
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ bool no_cs_r_values;
+ bool no_cs_r_choices;
+ size_t num_denom_sigs;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "rc",
+ &td.details.refresh.rc),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "execution_date",
+ &td.details.refresh.execution_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount_with_fee",
+ &td.details.refresh.amount_with_fee),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "old_coin_pub",
+ &td.details.refresh.old_coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "old_coin_sig",
+ &td.details.refresh.old_coin_sig),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "refresh_seed",
+ &td.details.refresh.refresh_seed),
+ GNUNET_PQ_result_spec_uint32 (
+ "noreveal_index",
+ &td.details.refresh.noreveal_index),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "planchets_h",
+ &td.details.refresh.planchets_h),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "selected_h",
+ &td.details.refresh.selected_h),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type (
+ "blinding_seed",
+ &td.details.refresh.blinding_seed),
+ &td.details.refresh.no_blinding_seed),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_array_cs_r_pub (
+ pg->conn,
+ "cs_r_values",
+ &td.details.refresh.num_cs_r_values,
+ &td.details.refresh.cs_r_values),
+ &no_cs_r_values),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 (
+ "cs_r_choices",
+ &td.details.refresh.cs_r_choices),
+ &no_cs_r_choices),
+ GNUNET_PQ_result_spec_array_uint64 (
+ pg->conn,
+ "denom_serials",
+ &td.details.refresh.num_coins,
+ &td.details.refresh.denom_serials),
+ TALER_PQ_result_spec_array_blinded_denom_sig (
+ pg->conn,
+ "denom_sigs",
+ &num_denom_sigs,
+ &td.details.refresh.denom_sigs),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with batch deposits table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_batch_deposits (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_BATCH_DEPOSITS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_uint64 (
+ "shard",
+ &td.details.batch_deposits.shard),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "merchant_pub",
+ &td.details.batch_deposits.merchant_pub),
+ GNUNET_PQ_result_spec_timestamp (
+ "wallet_timestamp",
+ &td.details.batch_deposits.wallet_timestamp),
+ GNUNET_PQ_result_spec_timestamp (
+ "exchange_timestamp",
+ &td.details.batch_deposits.exchange_timestamp),
+ GNUNET_PQ_result_spec_timestamp (
+ "refund_deadline",
+ &td.details.batch_deposits.refund_deadline),
+ GNUNET_PQ_result_spec_timestamp (
+ "wire_deadline",
+ &td.details.batch_deposits.wire_deadline),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_contract_terms",
+ &td.details.batch_deposits.h_contract_terms),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wallet_data_hash",
+ &td.details.batch_deposits.wallet_data_hash),
+ &td.details.batch_deposits.no_wallet_data_hash),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wire_salt",
+ &td.details.batch_deposits.wire_salt),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wire_target_h_payto",
+ &td.details.batch_deposits.wire_target_h_payto),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 (
+ "policy_details_serial_id",
+ &td.details.batch_deposits.policy_details_serial_id),
+ &td.details.batch_deposits.no_policy_details),
+ GNUNET_PQ_result_spec_bool (
+ "policy_blocked",
+ &td.details.batch_deposits.policy_blocked),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "total_amount",
+ &td.details.batch_deposits.total_amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "total_without_fee",
+ &td.details.batch_deposits.total_without_fee),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "merchant_sig",
+ &td.details.batch_deposits.merchant_sig),
+ GNUNET_PQ_result_spec_bool (
+ "done",
+ &td.details.batch_deposits.done),
+ GNUNET_PQ_result_spec_end
+ };
+
+ td.details.batch_deposits.policy_details_serial_id = 0;
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with coin deposits table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_coin_deposits (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_COIN_DEPOSITS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_uint64 (
+ "batch_deposit_serial_id",
+ &td.details.coin_deposits.batch_deposit_serial_id),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_pub",
+ &td.details.coin_deposits.coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_sig",
+ &td.details.coin_deposits.coin_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount_with_fee",
+ &td.details.coin_deposits.amount_with_fee),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with refunds table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_refunds (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_REFUNDS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_pub",
+ &td.details.refunds.coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "merchant_sig",
+ &td.details.refunds.merchant_sig),
+ GNUNET_PQ_result_spec_uint64 (
+ "rtransaction_id",
+ &td.details.refunds.rtransaction_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount_with_fee",
+ &td.details.refunds.amount_with_fee),
+ GNUNET_PQ_result_spec_uint64 (
+ "batch_deposit_serial_id",
+ &td.details.refunds.batch_deposit_serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with wire_out table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_wire_out (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_WIRE_OUT
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_timestamp (
+ "execution_date",
+ &td.details.wire_out.execution_date),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wtid_raw",
+ &td.details.wire_out.wtid_raw),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wire_target_h_payto",
+ &td.details.wire_out.wire_target_h_payto),
+ GNUNET_PQ_result_spec_string (
+ "exchange_account_section",
+ &td.details.wire_out.exchange_account_section),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount",
+ &td.details.wire_out.amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with aggregation_tracking table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_aggregation_tracking (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_uint64 (
+ "batch_deposit_serial_id",
+ &td.details.aggregation_tracking.batch_deposit_serial_id),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wtid_raw",
+ &td.details.aggregation_tracking.wtid_raw),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with wire_fee table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_wire_fee (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_WIRE_FEE
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_string ("wire_method",
+ &td.details.wire_fee.wire_method),
+ GNUNET_PQ_result_spec_timestamp ("start_date",
+ &td.details.wire_fee.start_date),
+ GNUNET_PQ_result_spec_timestamp ("end_date",
+ &td.details.wire_fee.end_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
+ &td.details.wire_fee.fees.wire),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
+ &td.details.wire_fee.fees.closing),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &td.details.wire_fee.master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with wire_fee table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_global_fee (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_GLOBAL_FEE
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_timestamp (
+ "start_date",
+ &td.details.global_fee.start_date),
+ GNUNET_PQ_result_spec_timestamp (
+ "end_date",
+ &td.details.global_fee.end_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "history_fee",
+ &td.details.global_fee.fees.history),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "account_fee",
+ &td.details.global_fee.fees.account),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "purse_fee",
+ &td.details.global_fee.fees.purse),
+ GNUNET_PQ_result_spec_relative_time (
+ "purse_timeout",
+ &td.details.global_fee.purse_timeout),
+ GNUNET_PQ_result_spec_relative_time (
+ "history_expiration",
+ &td.details.global_fee.history_expiration),
+ GNUNET_PQ_result_spec_uint32 (
+ "purse_account_limit",
+ &td.details.global_fee.purse_account_limit),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "master_sig",
+ &td.details.global_fee.master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with recoup table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_recoup (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_RECOUP
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &td.details.recoup.coin_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+ &td.details.recoup.coin_blind),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &td.details.recoup.amount),
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ &td.details.recoup.timestamp),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_pub",
+ &td.details.recoup.coin_pub),
+ GNUNET_PQ_result_spec_uint64 ("withdraw_serial_id",
+ &td.details.recoup.withdraw_serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with recoup_refresh table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_recoup_refresh (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_RECOUP_REFRESH
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &td.details.recoup_refresh.coin_sig)
+ ,
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_blind",
+ &td.details.recoup_refresh.coin_blind),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &td.details.recoup_refresh.amount),
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ &td.details.recoup_refresh.timestamp),
+ GNUNET_PQ_result_spec_uint64 ("known_coin_id",
+ &td.details.recoup_refresh.known_coin_id),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_pub",
+ &td.details.recoup_refresh.coin_pub),
+ GNUNET_PQ_result_spec_uint64 ("rrc_serial",
+ &td.details.recoup_refresh.rrc_serial),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with extensions table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_extensions (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_EXTENSIONS
+ };
+ bool no_manifest = false;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("extension_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_string ("name",
+ &td.details.extensions.name),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("manifest",
+ &td.details.extensions.manifest),
+ &no_manifest),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with policy_details table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_policy_details (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_POLICY_DETAILS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type ("hash_code",
+ &td.details.policy_details.
+ hash_code),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json ("policy_json",
+ &td.details.policy_details.
+ policy_json),
+ &td.details.policy_details.no_policy_json),
+ GNUNET_PQ_result_spec_timestamp ("deadline",
+ &td.details.policy_details.
+ deadline),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("commitment",
+ &td.details.policy_details.
+ commitment),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
+ &td.details.policy_details.
+ accumulated_total),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee",
+ &td.details.policy_details.
+ fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("transferable",
+ &td.details.policy_details.
+ transferable),
+ GNUNET_PQ_result_spec_uint16 ("fulfillment_state",
+ &td.details.policy_details.
+ fulfillment_state),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
+ &td.details.policy_details.
+ fulfillment_id),
+ &td.details.policy_details.no_fulfillment_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with policy_fulfillments table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_policy_fulfillments (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ bool no_proof = false;
+ bool no_timestamp = false;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_timestamp ("fulfillment_timestamp",
+ &td.details.policy_fulfillments.
+ fulfillment_timestamp),
+ &no_timestamp),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("fulfillment_proof",
+ &td.details.policy_fulfillments.
+ fulfillment_proof),
+ &no_proof),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with purse_requests table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_purse_requests (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_PURSE_REQUESTS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "purse_requests_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_pub",
+ &td.details.purse_requests.purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "merge_pub",
+ &td.details.purse_requests.merge_pub),
+ GNUNET_PQ_result_spec_timestamp (
+ "purse_creation",
+ &td.details.purse_requests.purse_creation),
+ GNUNET_PQ_result_spec_timestamp (
+ "purse_expiration",
+ &td.details.purse_requests.purse_expiration),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_contract_terms",
+ &td.details.purse_requests.h_contract_terms),
+ GNUNET_PQ_result_spec_uint32 (
+ "age_limit",
+ &td.details.purse_requests.age_limit),
+ GNUNET_PQ_result_spec_uint32 (
+ "flags",
+ &td.details.purse_requests.flags),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount_with_fee",
+ &td.details.purse_requests.amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "purse_fee",
+ &td.details.purse_requests.purse_fee),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_sig",
+ &td.details.purse_requests.purse_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with purse_decision table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_purse_decision (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_PURSE_DECISION
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "purse_refunds_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_pub",
+ &td.details.purse_decision.purse_pub),
+ GNUNET_PQ_result_spec_timestamp (
+ "action_timestamp",
+ &td.details.purse_decision.action_timestamp),
+ GNUNET_PQ_result_spec_bool (
+ "refunded",
+ &td.details.purse_decision.refunded),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with purse_merges table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_purse_merges (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_PURSE_MERGES
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "purse_merge_request_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_uint64 (
+ "partner_serial_id",
+ &td.details.purse_merges.partner_serial_id),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.purse_merges.reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_pub",
+ &td.details.purse_merges.purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "merge_sig",
+ &td.details.purse_merges.merge_sig),
+ GNUNET_PQ_result_spec_timestamp (
+ "merge_timestamp",
+ &td.details.purse_merges.merge_timestamp),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with purse_deposits table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_purse_deposits (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_PURSE_DEPOSITS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "purse_deposit_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_uint64 (
+ "partner_serial_id",
+ &td.details.purse_deposits.partner_serial_id),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_pub",
+ &td.details.purse_deposits.purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_pub",
+ &td.details.purse_deposits.coin_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount_with_fee",
+ &td.details.purse_deposits.amount_with_fee),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "coin_sig",
+ &td.details.purse_deposits.coin_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with account_merges table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_account_merges (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_ACCOUNT_MERGES
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "account_merge_request_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.account_merges.reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_sig",
+ &td.details.account_merges.reserve_sig),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_pub",
+ &td.details.account_merges.purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wallet_h_payto",
+ &td.details.account_merges.wallet_h_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with history_requests table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_history_requests (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_HISTORY_REQUESTS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "history_request_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.history_requests.reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_sig",
+ &td.details.history_requests.reserve_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "history_fee",
+ &td.details.history_requests.history_fee),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with close_requests table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_close_requests (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_CLOSE_REQUESTS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "close_request_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.close_requests.reserve_pub),
+ GNUNET_PQ_result_spec_timestamp (
+ "close_timestamp",
+ &td.details.close_requests.close_timestamp),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_sig",
+ &td.details.close_requests.reserve_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "close",
+ &td.details.close_requests.close),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "close_fee",
+ &td.details.close_requests.close_fee),
+ GNUNET_PQ_result_spec_string (
+ "payto_uri",
+ &td.details.close_requests.payto_uri.full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with wads_out table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_wads_out (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_WADS_OUT
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "wad_out_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wad_id",
+ &td.details.wads_out.wad_id),
+ GNUNET_PQ_result_spec_uint64 (
+ "partner_serial_id",
+ &td.details.wads_out.partner_serial_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount",
+ &td.details.wads_out.amount),
+ GNUNET_PQ_result_spec_timestamp (
+ "execution_time",
+ &td.details.wads_out.execution_time),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with wads_out_entries table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_wads_out_entries (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "wad_out_entry_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.wads_out_entries.reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_pub",
+ &td.details.wads_out_entries.purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_contract",
+ &td.details.wads_out_entries.h_contract),
+ GNUNET_PQ_result_spec_timestamp (
+ "purse_expiration",
+ &td.details.wads_out_entries.purse_expiration),
+ GNUNET_PQ_result_spec_timestamp (
+ "merge_timestamp",
+ &td.details.wads_out_entries.merge_timestamp),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount_with_fee",
+ &td.details.wads_out_entries.amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "wad_fee",
+ &td.details.wads_out_entries.wad_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "deposit_fees",
+ &td.details.wads_out_entries.deposit_fees),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_sig",
+ &td.details.wads_out_entries.reserve_sig),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_sig",
+ &td.details.wads_out_entries.purse_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with wads_in table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_wads_in (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_WADS_IN
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "wad_in_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wad_id",
+ &td.details.wads_in.wad_id),
+ GNUNET_PQ_result_spec_string (
+ "origin_exchange_url",
+ &td.details.wads_in.origin_exchange_url),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount",
+ &td.details.wads_in.amount),
+ GNUNET_PQ_result_spec_timestamp (
+ "arrival_time",
+ &td.details.wads_in.arrival_time),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with wads_in_entries table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_wads_in_entries (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "wad_in_entry_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.wads_in_entries.reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_pub",
+ &td.details.wads_in_entries.purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_contract",
+ &td.details.wads_in_entries.h_contract),
+ GNUNET_PQ_result_spec_timestamp (
+ "purse_expiration",
+ &td.details.wads_in_entries.purse_expiration),
+ GNUNET_PQ_result_spec_timestamp (
+ "merge_timestamp",
+ &td.details.wads_in_entries.merge_timestamp),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount_with_fee",
+ &td.details.wads_in_entries.amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "wad_fee",
+ &td.details.wads_in_entries.wad_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "deposit_fees",
+ &td.details.wads_in_entries.deposit_fees),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_sig",
+ &td.details.wads_in_entries.reserve_sig),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_sig",
+ &td.details.wads_in_entries.purse_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with profit_drains table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_profit_drains (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_PROFIT_DRAINS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "profit_drain_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wtid",
+ &td.details.profit_drains.wtid),
+ GNUNET_PQ_result_spec_string (
+ "account_section",
+ &td.details.profit_drains.account_section),
+ GNUNET_PQ_result_spec_string (
+ "payto_uri",
+ &td.details.profit_drains.payto_uri.full_payto),
+ GNUNET_PQ_result_spec_timestamp (
+ "trigger_date",
+ &td.details.profit_drains.trigger_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount",
+ &td.details.profit_drains.amount),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "master_sig",
+ &td.details.profit_drains.master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with aml_staff table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_aml_staff (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_AML_STAFF
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "aml_staff_uuid",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "decider_pub",
+ &td.details.aml_staff.decider_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "master_sig",
+ &td.details.aml_staff.master_sig),
+ GNUNET_PQ_result_spec_string (
+ "decider_name",
+ &td.details.aml_staff.decider_name),
+ GNUNET_PQ_result_spec_bool (
+ "is_active",
+ &td.details.aml_staff.is_active),
+ GNUNET_PQ_result_spec_bool (
+ "read_only",
+ &td.details.aml_staff.read_only),
+ GNUNET_PQ_result_spec_timestamp (
+ "last_change",
+ &td.details.aml_staff.last_change),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with purse_deletion table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_purse_deletion (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_PURSE_DELETION
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "purse_deletion_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_sig",
+ &td.details.purse_deletion.purse_sig),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "purse_pub",
+ &td.details.purse_deletion.purse_pub),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with withdraw table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_withdraw (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_WITHDRAW
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ bool no_max_age;
+ bool no_noreveal_index;
+ bool no_selected_h;
+ bool no_cs_r_values;
+ bool no_cs_r_choices;
+ size_t num_sigs;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "withdraw_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "planchets_h",
+ &td.details.withdraw.planchets_h),
+ GNUNET_PQ_result_spec_timestamp (
+ "execution_date",
+ &td.details.withdraw.execution_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT (
+ "amount_with_fee",
+ &td.details.withdraw.amount_with_fee),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_pub",
+ &td.details.withdraw.reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "reserve_sig",
+ &td.details.withdraw.reserve_sig),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint16 (
+ "max_age",
+ &td.details.withdraw.max_age),
+ &no_max_age),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint16 (
+ "noreveal_index",
+ &td.details.withdraw.noreveal_index),
+ &no_noreveal_index),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type (
+ "selected_h",
+ &td.details.withdraw.selected_h),
+ &no_selected_h),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type (
+ "blinding_seed",
+ &td.details.withdraw.blinding_seed),
+ &td.details.withdraw.no_blinding_seed),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_array_cs_r_pub (
+ pg->conn,
+ "cs_r_values",
+ &td.details.withdraw.num_cs_r_values,
+ &td.details.withdraw.cs_r_values),
+ &no_cs_r_values),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 (
+ "cs_r_choices",
+ &td.details.withdraw.cs_r_choices),
+ &no_cs_r_choices),
+ GNUNET_PQ_result_spec_array_uint64 (
+ pg->conn,
+ "denom_serials",
+ &td.details.withdraw.num_coins,
+ &td.details.withdraw.denom_serials),
+ TALER_PQ_result_spec_array_blinded_denom_sig (
+ pg->conn,
+ "denom_sigs",
+ &num_sigs,
+ &td.details.withdraw.denom_sigs),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ if (num_sigs != td.details.withdraw.num_coins)
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ if (no_max_age != no_noreveal_index)
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ if (no_max_age != no_selected_h)
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ if (no_cs_r_values != no_cs_r_choices)
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ if (no_cs_r_values != td.details.withdraw.no_blinding_seed)
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ td.details.withdraw.age_proof_required = ! no_max_age;
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with legitimization_measures table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_legitimization_measures (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "access_token",
+ &td.details.legitimization_measures.target_token),
+ GNUNET_PQ_result_spec_timestamp (
+ "start_time",
+ &td.details.legitimization_measures.start_time),
+ TALER_PQ_result_spec_json (
+ "jmeasures",
+ &td.details.legitimization_measures.measures),
+ GNUNET_PQ_result_spec_uint32 (
+ "display_priority",
+ &td.details.legitimization_measures.display_priority),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with legitimization_outcomes table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_legitimization_outcomes (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_payto",
+ &td.details.legitimization_outcomes.h_payto),
+ GNUNET_PQ_result_spec_timestamp (
+ "decision_time",
+ &td.details.legitimization_outcomes.decision_time),
+ GNUNET_PQ_result_spec_timestamp (
+ "expiration_time",
+ &td.details.legitimization_outcomes.expiration_time),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json (
+ "jproperties",
+ &td.details.legitimization_outcomes.properties),
+ NULL),
+ GNUNET_PQ_result_spec_bool (
+ "to_investigate_id",
+ &td.details.legitimization_outcomes.to_investigate),
+ TALER_PQ_result_spec_json (
+ "jnew_rules",
+ &td.details.legitimization_outcomes.new_rules),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with legitimization_processes table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_legitimization_processes (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_payto",
+ &td.details.legitimization_processes.h_payto),
+ GNUNET_PQ_result_spec_timestamp (
+ "start_time",
+ &td.details.legitimization_processes.start_time),
+ GNUNET_PQ_result_spec_timestamp (
+ "expiration_time",
+ &td.details.legitimization_processes.expiration_time),
+ GNUNET_PQ_result_spec_uint64 (
+ "legitimization_measure_serial_id",
+ &td.details.legitimization_processes.legitimization_measure_serial_id),
+ GNUNET_PQ_result_spec_uint32 (
+ "measure_index",
+ &td.details.legitimization_processes.measure_index),
+ GNUNET_PQ_result_spec_string (
+ "provider_name",
+ &td.details.legitimization_processes.provider_name),
+ GNUNET_PQ_result_spec_string (
+ "provider_user_id",
+ &td.details.legitimization_processes.provider_user_id),
+ GNUNET_PQ_result_spec_string (
+ "provider_legitimization_id",
+ &td.details.legitimization_processes.provider_legitimization_id),
+ GNUNET_PQ_result_spec_string (
+ "redirect_url",
+ &td.details.legitimization_processes.redirect_url),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with kyc_attributes table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_kyc_attributes (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "kyc_attributes_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_payto",
+ &td.details.kyc_attributes.h_payto),
+ GNUNET_PQ_result_spec_uint64 (
+ "legitimization_serial",
+ &td.details.kyc_attributes.legitimization_serial),
+ GNUNET_PQ_result_spec_timestamp (
+ "collection_time",
+ &td.details.kyc_attributes.collection_time),
+ GNUNET_PQ_result_spec_timestamp (
+ "expiration_time",
+ &td.details.kyc_attributes.expiration_time),
+ GNUNET_PQ_result_spec_uint64 (
+ "trigger_outcome_serial",
+ &td.details.kyc_attributes.trigger_outcome_serial),
+ GNUNET_PQ_result_spec_variable_size (
+ "encrypted_attributes",
+ &td.details.kyc_attributes.encrypted_attributes,
+ &td.details.kyc_attributes.encrypted_attributes_size),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with aml_history table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_aml_history (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_AML_HISTORY
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "aml_history_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "h_payto",
+ &td.details.aml_history.h_payto),
+ GNUNET_PQ_result_spec_uint64 (
+ "outcome_serial_id",
+ &td.details.aml_history.outcome_serial_id),
+ GNUNET_PQ_result_spec_string (
+ "justification",
+ &td.details.aml_history.justification),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "decider_pub",
+ &td.details.aml_history.decider_pub),
+ GNUNET_PQ_result_spec_auto_from_type (
+ "decider_sig",
+ &td.details.aml_history.decider_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Function called with kyc_events table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_kyc_events (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct TALER_EXCHANGEDB_TableData td = {
+ .table = TALER_EXCHANGEDB_RT_KYC_EVENTS
+ };
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "kyc_event_serial_id",
+ &td.serial),
+ GNUNET_PQ_result_spec_timestamp (
+ "event_timestamp",
+ &td.details.kyc_events.event_timestamp),
+ GNUNET_PQ_result_spec_string (
+ "event_type",
+ &td.details.kyc_events.event_type),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->error = true;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &td);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Assign statement to @a n and PREPARE
+ * @a sql under name @a n.
+ */
+#define XPREPARE(n,sql) \
+ statement = n; \
+ PREPARE (pg, n, sql);
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_records_by_table (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ enum TALER_EXCHANGEDB_ReplicatedTable table,
+ uint64_t serial,
+ TALER_EXCHANGEDB_ReplicationCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial),
+ GNUNET_PQ_query_param_end
+ };
+ struct LookupRecordsByTableContext ctx = {
+ .pg = pg,
+ .cb = cb,
+ .cb_cls = cb_cls
+ };
+ GNUNET_PQ_PostgresResultHandler rh = NULL;
+ const char *statement = NULL;
+ enum GNUNET_DB_QueryStatus qs;
+
+ switch (table)
+ {
+ case TALER_EXCHANGEDB_RT_DENOMINATIONS:
+ XPREPARE ("select_above_serial_by_table_denominations",
+ "SELECT"
+ " denominations_serial AS serial"
+ ",denom_type"
+ ",denom_pub"
+ ",master_sig"
+ ",valid_from"
+ ",expire_withdraw"
+ ",expire_deposit"
+ ",expire_legal"
+ ",coin"
+ ",fee_withdraw"
+ ",fee_deposit"
+ ",fee_refresh"
+ ",fee_refund"
+ ",age_mask"
+ " FROM denominations"
+ " WHERE denominations_serial > $1"
+ " ORDER BY denominations_serial ASC;");
+ rh = &lrbt_cb_table_denominations;
+ break;
+ case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS:
+ XPREPARE ("select_above_serial_by_table_denomination_revocations",
+ "SELECT"
+ " denom_revocations_serial_id AS serial"
+ ",master_sig"
+ ",denominations_serial"
+ " FROM denomination_revocations"
+ " WHERE denom_revocations_serial_id > $1"
+ " ORDER BY denom_revocations_serial_id ASC;");
+ rh = &lrbt_cb_table_denomination_revocations;
+ break;
+ case TALER_EXCHANGEDB_RT_WIRE_TARGETS:
+ XPREPARE ("select_above_serial_by_table_wire_targets",
+ "SELECT"
+ " wire_target_serial_id AS serial"
+ ",payto_uri"
+ " FROM wire_targets"
+ " WHERE wire_target_serial_id > $1"
+ " ORDER BY wire_target_serial_id ASC;");
+ rh = &lrbt_cb_table_wire_targets;
+ break;
+ case TALER_EXCHANGEDB_RT_KYC_TARGETS:
+ XPREPARE ("select_above_serial_by_table_kyc_targets",
+ "SELECT"
+ " kyc_target_serial_id AS serial"
+ ",h_normalized_payto"
+ ",access_token"
+ ",target_pub"
+ ",is_wallet"
+ " FROM kyc_targets"
+ " WHERE kyc_target_serial_id > $1"
+ " ORDER BY kyc_target_serial_id ASC;");
+ rh = &lrbt_cb_table_kyc_targets;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES:
+ XPREPARE ("select_above_serial_by_table_reserves",
+ "SELECT"
+ " reserve_uuid AS serial"
+ ",reserve_pub"
+ ",expiration_date"
+ ",gc_date"
+ " FROM reserves"
+ " WHERE reserve_uuid > $1"
+ " ORDER BY reserve_uuid ASC;");
+ rh = &lrbt_cb_table_reserves;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_IN:
+ XPREPARE ("select_above_serial_by_table_reserves_in",
+ "SELECT"
+ " reserve_in_serial_id AS serial"
+ ",reserve_pub"
+ ",wire_reference"
+ ",credit"
+ ",wire_source_h_payto"
+ ",exchange_account_section"
+ ",execution_date"
+ " FROM reserves_in"
+ " WHERE reserve_in_serial_id > $1"
+ " ORDER BY reserve_in_serial_id ASC;");
+ rh = &lrbt_cb_table_reserves_in;
+ break;
+ case TALER_EXCHANGEDB_RT_KYCAUTHS_IN:
+ XPREPARE ("select_above_serial_by_table_kycauth_in",
+ "SELECT"
+ " kycauth_in_serial_id AS serial"
+ ",account_pub"
+ ",wire_reference"
+ ",credit"
+ ",wire_source_h_payto"
+ ",exchange_account_section"
+ ",execution_date"
+ " FROM kycauths_in"
+ " WHERE kycauth_in_serial_id > $1"
+ " ORDER BY kycauth_in_serial_id ASC;");
+ rh = &lrbt_cb_table_kycauth_in;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_CLOSE:
+ XPREPARE ("select_above_serial_by_table_reserves_close",
+ "SELECT"
+ " close_uuid AS serial"
+ ",reserve_pub"
+ ",execution_date"
+ ",wtid"
+ ",wire_target_h_payto"
+ ",amount"
+ ",closing_fee"
+ " FROM reserves_close"
+ " WHERE close_uuid > $1"
+ " ORDER BY close_uuid ASC;");
+ rh = &lrbt_cb_table_reserves_close;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS:
+ XPREPARE ("select_above_serial_by_table_reserves_open_requests",
+ "SELECT"
+ " open_request_uuid AS serial"
+ ",reserve_pub"
+ ",request_timestamp"
+ ",expiration_date"
+ ",reserve_sig"
+ ",reserve_payment"
+ ",requested_purse_limit"
+ " FROM reserves_open_requests"
+ " WHERE open_request_uuid > $1"
+ " ORDER BY open_request_uuid ASC;");
+ rh = &lrbt_cb_table_reserves_open_requests;
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
+ XPREPARE ("select_above_serial_by_table_reserves_open_deposits",
+ "SELECT"
+ " reserves_open_deposit_uuid AS serial"
+ ",reserve_sig"
+ ",reserve_pub"
+ ",coin_pub"
+ ",coin_sig"
+ ",contribution"
+ " FROM reserves_open_deposits"
+ " WHERE reserves_open_deposit_uuid > $1"
+ " ORDER BY reserves_open_deposit_uuid ASC;");
+ rh = &lrbt_cb_table_reserves_open_deposits;
+ break;
+ case TALER_EXCHANGEDB_RT_AUDITORS:
+ XPREPARE ("select_above_serial_by_table_auditors",
+ "SELECT"
+ " auditor_uuid AS serial"
+ ",auditor_pub"
+ ",auditor_name"
+ ",auditor_url"
+ ",is_active"
+ ",last_change"
+ " FROM auditors"
+ " WHERE auditor_uuid > $1"
+ " ORDER BY auditor_uuid ASC;");
+ rh = &lrbt_cb_table_auditors;
+ break;
+ case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS:
+ XPREPARE ("select_above_serial_by_table_auditor_denom_sigs",
+ "SELECT"
+ " auditor_denom_serial AS serial"
+ ",auditor_uuid"
+ ",denominations_serial"
+ ",auditor_sig"
+ " FROM auditor_denom_sigs"
+ " WHERE auditor_denom_serial > $1"
+ " ORDER BY auditor_denom_serial ASC;");
+ rh = &lrbt_cb_table_auditor_denom_sigs;
+ break;
+ case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS:
+ XPREPARE ("select_above_serial_by_table_exchange_sign_keys",
+ "SELECT"
+ " esk_serial AS serial"
+ ",exchange_pub"
+ ",master_sig"
+ ",valid_from"
+ ",expire_sign"
+ ",expire_legal"
+ " FROM exchange_sign_keys"
+ " WHERE esk_serial > $1"
+ " ORDER BY esk_serial ASC;");
+ rh = &lrbt_cb_table_exchange_sign_keys;
+ break;
+ case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS:
+ XPREPARE ("select_above_serial_by_table_signkey_revocations",
+ "SELECT"
+ " signkey_revocations_serial_id AS serial"
+ ",esk_serial"
+ ",master_sig"
+ " FROM signkey_revocations"
+ " WHERE signkey_revocations_serial_id > $1"
+ " ORDER BY signkey_revocations_serial_id ASC;");
+ rh = &lrbt_cb_table_signkey_revocations;
+ break;
+ case TALER_EXCHANGEDB_RT_KNOWN_COINS:
+ XPREPARE ("select_above_serial_by_table_known_coins",
+ "SELECT"
+ " known_coin_id AS serial"
+ ",coin_pub"
+ ",denom_sig"
+ ",denominations_serial"
+ " FROM known_coins"
+ " WHERE known_coin_id > $1"
+ " ORDER BY known_coin_id ASC;");
+ rh = &lrbt_cb_table_known_coins;
+ break;
+ case TALER_EXCHANGEDB_RT_REFRESH:
+ XPREPARE ("select_above_serial_by_table_refresh",
+ "SELECT"
+ " refresh_id AS serial"
+ ",rc"
+ ",execution_date"
+ ",amount_with_fee"
+ ",old_coin_pub"
+ ",old_coin_sig"
+ ",refresh_seed"
+ ",noreveal_index"
+ ",planchets_h"
+ ",selected_h"
+ ",blinding_seed"
+ ",cs_r_values"
+ ",cs_r_choices"
+ ",denom_serials"
+ ",denom_sigs"
+ " FROM refresh"
+ " WHERE refresh_id > $1"
+ " ORDER BY refresh_id ASC;");
+ rh = &lrbt_cb_table_refresh;
+ break;
+ case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS:
+ XPREPARE ("select_above_serial_by_table_batch_deposits",
+ "SELECT"
+ " batch_deposit_serial_id AS serial"
+ ",shard"
+ ",merchant_pub"
+ ",wallet_timestamp"
+ ",exchange_timestamp"
+ ",refund_deadline"
+ ",wire_deadline"
+ ",h_contract_terms"
+ ",wallet_data_hash"
+ ",wire_salt"
+ ",wire_target_h_payto"
+ ",policy_details_serial_id"
+ ",policy_blocked"
+ ",total_amount"
+ ",total_without_fee"
+ ",merchant_sig"
+ ",done"
+ " FROM batch_deposits"
+ " WHERE batch_deposit_serial_id > $1"
+ " ORDER BY batch_deposit_serial_id ASC;");
+ rh = &lrbt_cb_table_batch_deposits;
+ break;
+ case TALER_EXCHANGEDB_RT_COIN_DEPOSITS:
+ XPREPARE ("select_above_serial_by_table_coin_deposits",
+ "SELECT"
+ " coin_deposit_serial_id AS serial"
+ ",batch_deposit_serial_id"
+ ",coin_pub"
+ ",coin_sig"
+ ",amount_with_fee"
+ " FROM coin_deposits"
+ " WHERE coin_deposit_serial_id > $1"
+ " ORDER BY coin_deposit_serial_id ASC;");
+ rh = &lrbt_cb_table_coin_deposits;
+ break;
+ case TALER_EXCHANGEDB_RT_REFUNDS:
+ XPREPARE ("select_above_serial_by_table_refunds",
+ "SELECT"
+ " refund_serial_id AS serial"
+ ",coin_pub"
+ ",merchant_sig"
+ ",rtransaction_id"
+ ",amount_with_fee"
+ ",batch_deposit_serial_id"
+ " FROM refunds"
+ " WHERE refund_serial_id > $1"
+ " ORDER BY refund_serial_id ASC;");
+ rh = &lrbt_cb_table_refunds;
+ break;
+ case TALER_EXCHANGEDB_RT_WIRE_OUT:
+ XPREPARE ("select_above_serial_by_table_wire_out",
+ "SELECT"
+ " wireout_uuid AS serial"
+ ",execution_date"
+ ",wtid_raw"
+ ",wire_target_h_payto"
+ ",exchange_account_section"
+ ",amount"
+ " FROM wire_out"
+ " WHERE wireout_uuid > $1"
+ " ORDER BY wireout_uuid ASC;");
+ rh = &lrbt_cb_table_wire_out;
+ break;
+ case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING:
+ XPREPARE ("select_above_serial_by_table_aggregation_tracking",
+ "SELECT"
+ " aggregation_serial_id AS serial"
+ ",batch_deposit_serial_id"
+ ",wtid_raw"
+ " FROM aggregation_tracking"
+ " WHERE aggregation_serial_id > $1"
+ " ORDER BY aggregation_serial_id ASC;");
+ rh = &lrbt_cb_table_aggregation_tracking;
+ break;
+ case TALER_EXCHANGEDB_RT_WIRE_FEE:
+ XPREPARE ("select_above_serial_by_table_wire_fee",
+ "SELECT"
+ " wire_fee_serial AS serial"
+ ",wire_method"
+ ",start_date"
+ ",end_date"
+ ",wire_fee"
+ ",closing_fee"
+ ",master_sig"
+ " FROM wire_fee"
+ " WHERE wire_fee_serial > $1"
+ " ORDER BY wire_fee_serial ASC;");
+ rh = &lrbt_cb_table_wire_fee;
+ break;
+ case TALER_EXCHANGEDB_RT_GLOBAL_FEE:
+ XPREPARE ("select_above_serial_by_table_global_fee",
+ "SELECT"
+ " global_fee_serial AS serial"
+ ",start_date"
+ ",end_date"
+ ",history_fee"
+ ",account_fee"
+ ",purse_fee"
+ ",purse_timeout"
+ ",history_expiration"
+ ",purse_account_limit"
+ ",master_sig"
+ " FROM global_fee"
+ " WHERE global_fee_serial > $1"
+ " ORDER BY global_fee_serial ASC;");
+ rh = &lrbt_cb_table_global_fee;
+ break;
+ case TALER_EXCHANGEDB_RT_RECOUP:
+ XPREPARE ("select_above_serial_by_table_recoup",
+ "SELECT"
+ " recoup_uuid AS serial"
+ ",coin_sig"
+ ",coin_blind"
+ ",amount"
+ ",recoup_timestamp"
+ ",coin_pub"
+ ",reserve_out_serial_id"
+ " FROM recoup"
+ " WHERE recoup_uuid > $1"
+ " ORDER BY recoup_uuid ASC;");
+ rh = &lrbt_cb_table_recoup;
+ break;
+ case TALER_EXCHANGEDB_RT_RECOUP_REFRESH:
+ XPREPARE ("select_above_serial_by_table_recoup_refresh",
+ "SELECT"
+ " recoup_refresh_uuid AS serial"
+ ",coin_sig"
+ ",coin_blind"
+ ",amount"
+ ",recoup_timestamp"
+ ",coin_pub"
+ ",known_coin_id"
+ ",rrc_serial"
+ " FROM recoup_refresh"
+ " WHERE recoup_refresh_uuid > $1"
+ " ORDER BY recoup_refresh_uuid ASC;");
+ rh = &lrbt_cb_table_recoup_refresh;
+ break;
+ case TALER_EXCHANGEDB_RT_EXTENSIONS:
+ // FIXME: this seems broken! -- where is the SQL!?
+ statement = "select_above_serial_by_table_extensions";
+ rh = &lrbt_cb_table_extensions;
+ break;
+ case TALER_EXCHANGEDB_RT_POLICY_DETAILS:
+ // FIXME: this seems broken! -- where is the SQL!?
+ statement = "select_above_serial_by_table_policy_details";
+ rh = &lrbt_cb_table_policy_details;
+ break;
+ case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS:
+ // FIXME: this seems broken! -- where is the SQL!?
+ statement = "select_above_serial_by_table_policy_fulfillments";
+ rh = &lrbt_cb_table_policy_fulfillments;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
+ XPREPARE ("select_above_serial_by_table_purse_requests",
+ "SELECT"
+ " purse_requests_serial_id"
+ ",purse_pub"
+ ",merge_pub"
+ ",purse_creation"
+ ",purse_expiration"
+ ",h_contract_terms"
+ ",age_limit"
+ ",flags"
+ ",amount_with_fee"
+ ",purse_fee"
+ ",purse_sig"
+ " FROM purse_requests"
+ " WHERE purse_requests_serial_id > $1"
+ " ORDER BY purse_requests_serial_id ASC;");
+ rh = &lrbt_cb_table_purse_requests;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_DECISION:
+ XPREPARE ("select_above_serial_by_table_purse_decision",
+ "SELECT"
+ " purse_decision_serial_id"
+ ",action_timestamp"
+ ",refunded"
+ ",purse_pub"
+ " FROM purse_decision"
+ " WHERE purse_decision_serial_id > $1"
+ " ORDER BY purse_decision_serial_id ASC;");
+ rh = &lrbt_cb_table_purse_decision;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_MERGES:
+ XPREPARE ("select_above_serial_by_table_purse_merges",
+ "SELECT"
+ " purse_merge_request_serial_id"
+ ",partner_serial_id"
+ ",reserve_pub"
+ ",purse_pub"
+ ",merge_sig"
+ ",merge_timestamp"
+ " FROM purse_merges"
+ " WHERE purse_merge_request_serial_id > $1"
+ " ORDER BY purse_merge_request_serial_id ASC;");
+ rh = &lrbt_cb_table_purse_merges;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS:
+ XPREPARE ("select_above_serial_by_table_purse_deposits",
+ "SELECT"
+ " purse_deposit_serial_id"
+ ",partner_serial_id"
+ ",purse_pub"
+ ",coin_pub"
+ ",amount_with_fee"
+ ",coin_sig"
+ " FROM purse_deposits"
+ " WHERE purse_deposit_serial_id > $1"
+ " ORDER BY purse_deposit_serial_id ASC;");
+ rh = &lrbt_cb_table_purse_deposits;
+ break;
+ case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES:
+ XPREPARE ("select_above_serial_by_table_account_merges",
+ "SELECT"
+ " account_merge_request_serial_id"
+ ",reserve_pub"
+ ",reserve_sig"
+ ",purse_pub"
+ ",wallet_h_payto"
+ " FROM account_merges"
+ " WHERE account_merge_request_serial_id > $1"
+ " ORDER BY account_merge_request_serial_id ASC;");
+ rh = &lrbt_cb_table_account_merges;
+ break;
+ case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS:
+ XPREPARE ("select_above_serial_by_table_history_requests",
+ "SELECT"
+ " history_request_serial_id"
+ ",reserve_pub"
+ ",request_timestamp"
+ ",reserve_sig"
+ ",history_fee"
+ " FROM history_requests"
+ " WHERE history_request_serial_id > $1"
+ " ORDER BY history_request_serial_id ASC;");
+ rh = &lrbt_cb_table_history_requests;
+ break;
+ case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS:
+ XPREPARE ("select_above_serial_by_table_close_requests",
+ "SELECT"
+ " close_request_serial_id"
+ ",reserve_pub"
+ ",close_timestamp"
+ ",reserve_sig"
+ ",close"
+ " FROM close_requests"
+ " WHERE close_request_serial_id > $1"
+ " ORDER BY close_request_serial_id ASC;");
+ rh = &lrbt_cb_table_close_requests;
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_OUT:
+ XPREPARE ("select_above_serial_by_table_wads_out",
+ "SELECT"
+ " wad_out_serial_id"
+ ",wad_id"
+ ",partner_serial_id"
+ ",amount"
+ ",execution_time"
+ " FROM wads_out"
+ " WHERE wad_out_serial_id > $1"
+ " ORDER BY wad_out_serial_id ASC;");
+ rh = &lrbt_cb_table_wads_out;
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES:
+ XPREPARE ("select_above_serial_by_table_wads_out_entries",
+ "SELECT"
+ " wad_out_entry_serial_id"
+ ",reserve_pub"
+ ",purse_pub"
+ ",h_contract"
+ ",purse_expiration"
+ ",merge_timestamp"
+ ",amount_with_fee"
+ ",wad_fee"
+ ",deposit_fees"
+ ",reserve_sig"
+ ",purse_sig"
+ " FROM wad_out_entries"
+ " WHERE wad_out_entry_serial_id > $1"
+ " ORDER BY wad_out_entry_serial_id ASC;");
+ rh = &lrbt_cb_table_wads_out_entries;
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_IN:
+ XPREPARE ("select_above_serial_by_table_wads_in",
+ "SELECT"
+ " wad_in_serial_id"
+ ",wad_id"
+ ",origin_exchange_url"
+ ",amount"
+ ",arrival_time"
+ " FROM wads_in"
+ " WHERE wad_in_serial_id > $1"
+ " ORDER BY wad_in_serial_id ASC;");
+ rh = &lrbt_cb_table_wads_in;
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES:
+ XPREPARE ("select_above_serial_by_table_wads_in_entries",
+ "SELECT"
+ " wad_in_entry_serial_id"
+ ",reserve_pub"
+ ",purse_pub"
+ ",h_contract"
+ ",purse_expiration"
+ ",merge_timestamp"
+ ",amount_with_fee"
+ ",wad_fee"
+ ",deposit_fees"
+ ",reserve_sig"
+ ",purse_sig"
+ " FROM wad_in_entries"
+ " WHERE wad_in_entry_serial_id > $1"
+ " ORDER BY wad_in_entry_serial_id ASC;");
+ rh = &lrbt_cb_table_wads_in_entries;
+ break;
+ case TALER_EXCHANGEDB_RT_PROFIT_DRAINS:
+ XPREPARE ("select_above_serial_by_table_profit_drains",
+ "SELECT"
+ " profit_drain_serial_id"
+ ",wtid"
+ ",account_section"
+ ",payto_uri"
+ ",trigger_date"
+ ",amount"
+ ",master_sig"
+ " FROM profit_drains"
+ " WHERE profit_drain_serial_id > $1"
+ " ORDER BY profit_drain_serial_id ASC;");
+ rh = &lrbt_cb_table_profit_drains;
+ break;
+
+ case TALER_EXCHANGEDB_RT_AML_STAFF:
+ XPREPARE ("select_above_serial_by_table_aml_staff",
+ "SELECT"
+ " aml_staff_uuid"
+ ",decider_pub"
+ ",master_sig"
+ ",decider_name"
+ ",is_active"
+ ",read_only"
+ ",last_change"
+ " FROM aml_staff"
+ " WHERE aml_staff_uuid > $1"
+ " ORDER BY aml_staff_uuid ASC;");
+ rh = &lrbt_cb_table_aml_staff;
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_DELETION:
+ XPREPARE ("select_above_serial_by_table_purse_deletion",
+ "SELECT"
+ " purse_deletion_serial_id"
+ ",purse_pub"
+ ",purse_sig"
+ " FROM purse_deletion"
+ " WHERE purse_deletion_serial_id > $1"
+ " ORDER BY purse_deletion_serial_id ASC;");
+ rh = &lrbt_cb_table_purse_deletion;
+ break;
+ case TALER_EXCHANGEDB_RT_WITHDRAW:
+ XPREPARE ("select_above_serial_by_table_withdraw",
+ "SELECT"
+ " withdraw_id"
+ ",planchets_h"
+ ",execution_date"
+ ",amount_with_fee"
+ ",reserve_pub"
+ ",reserve_sig"
+ ",max_age"
+ ",noreveal_index"
+ ",selected_h"
+ ",blinding_seed"
+ ",cs_r_values"
+ ",cs_r_choices"
+ ",denom_serials"
+ ",denom_sigs"
+ " FROM withdraw"
+ " WHERE withdraw_id > $1"
+ " ORDER BY withdraw_id ASC;");
+ rh = &lrbt_cb_table_withdraw;
+ break;
+ case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES:
+ XPREPARE ("select_above_serial_by_table_legitimization_measures",
+ "SELECT"
+ " legitimization_measure_serial_id AS serial"
+ ",access_token"
+ ",start_time"
+ ",jmeasures::TEXT"
+ ",display_priority"
+ " FROM legitimization_measures"
+ " WHERE legitimization_measure_serial_id > $1"
+ " ORDER BY legitimization_measure_serial_id ASC;");
+ rh = &lrbt_cb_table_legitimization_measures;
+ break;
+ case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES:
+ XPREPARE ("select_above_serial_by_table_legitimization_outcomes",
+ "SELECT"
+ " outcome_serial_id AS serial"
+ ",h_payto"
+ ",decision_time"
+ ",expiration_time"
+ ",jproperties::TEXT"
+ ",to_investigate"
+ ",jnew_rules::TEXT"
+ " FROM legitimization_outcomes"
+ " WHERE outcome_serial_id > $1"
+ " ORDER BY outcome_serial_id ASC;");
+ rh = &lrbt_cb_table_legitimization_outcomes;
+ break;
+ case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES:
+ XPREPARE ("select_above_serial_by_table_legitimization_processes",
+ "SELECT"
+ " legitimization_process_serial_id AS serial"
+ ",h_payto"
+ ",start_time"
+ ",expiration_time"
+ ",legitimization_measure_serial_id"
+ ",measure_index"
+ ",provider_name"
+ ",provider_user_id"
+ ",provider_legitimization_id"
+ ",redirect_url"
+ " FROM legitimization_processes"
+ " WHERE legitimization_process_serial_id > $1"
+ " ORDER BY legitimization_process_serial_id ASC;");
+ rh = &lrbt_cb_table_legitimization_processes;
+ break;
+ case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES:
+ XPREPARE ("select_above_serial_by_table_kyc_attributes",
+ "SELECT"
+ " kyc_attributes_serial_id"
+ ",h_payto"
+ ",legitimization_serial"
+ ",collection_time"
+ ",expiration_time"
+ ",trigger_outcome_serial"
+ ",encrypted_attributes"
+ " FROM kyc_attributes"
+ " WHERE kyc_attributes_serial_id > $1"
+ " ORDER BY kyc_attributes_serial_id ASC;");
+ rh = &lrbt_cb_table_kyc_attributes;
+ break;
+ case TALER_EXCHANGEDB_RT_AML_HISTORY:
+ XPREPARE ("select_above_serial_by_table_aml_history",
+ "SELECT"
+ " aml_history_serial_id"
+ ",h_payto"
+ ",outcome_serial_id"
+ ",justification"
+ ",decider_pub"
+ ",decider_sig"
+ " FROM aml_history"
+ " WHERE aml_history_serial_id > $1"
+ " ORDER BY aml_history_serial_id ASC;");
+ rh = &lrbt_cb_table_aml_history;
+ break;
+ case TALER_EXCHANGEDB_RT_KYC_EVENTS:
+ XPREPARE ("select_above_serial_by_table_kyc_events",
+ "SELECT"
+ " kyc_event_serial_id AS serial"
+ ",event_timestamp"
+ ",event_type"
+ " FROM kyc_events"
+ " WHERE kyc_event_serial_id > $1"
+ " ORDER BY kyc_event_serial_id ASC;");
+ rh = &lrbt_cb_table_kyc_events;
+ break;
+ }
+ if (NULL == rh)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ statement,
+ params,
+ rh,
+ &ctx);
+ if (qs < 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to run `%s'\n",
+ statement);
+ return qs;
+ }
+ if (ctx.error)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ return qs;
+}
+
+
+#undef XPREPARE
+
+/* end of lookup_records_by_table.c */
diff --git a/src/exchangedb/lookup_rules_by_access_token.c b/src/exchangedb/lookup_rules_by_access_token.c
@@ -0,0 +1,66 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_rules_by_access_token.c
+ * @brief Implementation of the lookup_rules_by_access_token function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_rules_by_access_token.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_rules_by_access_token (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ json_t **jnew_rules,
+ uint64_t *rowid)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json (
+ "jnew_rules",
+ jnew_rules),
+ NULL),
+ GNUNET_PQ_result_spec_uint64 (
+ "row_id",
+ rowid),
+ GNUNET_PQ_result_spec_end
+ };
+
+ *jnew_rules = NULL;
+ PREPARE (pg,
+ "lookup_rules_by_access_token",
+ "SELECT"
+ " jnew_rules::TEXT"
+ ",outcome_serial_id AS row_id"
+ " FROM legitimization_outcomes"
+ " WHERE h_payto=$1"
+ " AND is_active"
+ " ORDER BY expiration_time DESC,"
+ " outcome_serial_id DESC"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "lookup_rules_by_access_token",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_serial_by_table.c b/src/exchangedb/lookup_serial_by_table.c
@@ -0,0 +1,465 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file lookup_serial_by_table.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_serial_by_table.h"
+#include "helper.h"
+
+
+/**
+ * Assign statement to @a n and PREPARE
+ * @a sql under name @a n.
+ */
+#define XPREPARE(n,sql) \
+ statement = n; \
+ PREPARE (pg, n, sql);
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_serial_by_table (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ enum TALER_EXCHANGEDB_ReplicatedTable
+ table,
+ uint64_t *serial)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial",
+ serial),
+ GNUNET_PQ_result_spec_end
+ };
+ const char *statement = NULL;
+
+ switch (table)
+ {
+ case TALER_EXCHANGEDB_RT_DENOMINATIONS:
+ XPREPARE ("select_serial_by_table_denominations",
+ "SELECT"
+ " denominations_serial AS serial"
+ " FROM denominations"
+ " ORDER BY denominations_serial DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS:
+ XPREPARE ("select_serial_by_table_denomination_revocations",
+ "SELECT"
+ " denom_revocations_serial_id AS serial"
+ " FROM denomination_revocations"
+ " ORDER BY denom_revocations_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_WIRE_TARGETS:
+ XPREPARE ("select_serial_by_table_wire_targets",
+ "SELECT"
+ " wire_target_serial_id AS serial"
+ " FROM wire_targets"
+ " ORDER BY wire_target_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_KYC_TARGETS:
+ XPREPARE ("select_serial_by_table_kyc_targets",
+ "SELECT"
+ " kyc_target_serial_id AS serial"
+ " FROM kyc_targets"
+ " ORDER BY kyc_target_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES:
+ XPREPARE ("select_serial_by_table_reserves",
+ "SELECT"
+ " reserve_uuid AS serial"
+ " FROM reserves"
+ " ORDER BY reserve_uuid DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_IN:
+ XPREPARE ("select_serial_by_table_reserves_in",
+ "SELECT"
+ " reserve_in_serial_id AS serial"
+ " FROM reserves_in"
+ " ORDER BY reserve_in_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_KYCAUTHS_IN:
+ XPREPARE ("select_serial_by_table_kycauths_in",
+ "SELECT"
+ " kycauth_in_serial_id AS serial"
+ " FROM kycauths_in"
+ " ORDER BY kycauths_in_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_CLOSE:
+ XPREPARE ("select_serial_by_table_reserves_close",
+ "SELECT"
+ " close_uuid AS serial"
+ " FROM reserves_close"
+ " ORDER BY close_uuid DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS:
+ XPREPARE ("select_serial_by_table_reserves_open_requests",
+ "SELECT"
+ " open_request_uuid AS serial"
+ " FROM reserves_open_requests"
+ " ORDER BY open_request_uuid DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
+ XPREPARE ("select_serial_by_table_reserves_open_deposits",
+ "SELECT"
+ " reserve_open_deposit_uuid AS serial"
+ " FROM reserves_open_deposits"
+ " ORDER BY reserve_open_deposit_uuid DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_AUDITORS:
+ XPREPARE ("select_serial_by_table_auditors",
+ "SELECT"
+ " auditor_uuid AS serial"
+ " FROM auditors"
+ " ORDER BY auditor_uuid DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS:
+ XPREPARE ("select_serial_by_table_auditor_denom_sigs",
+ "SELECT"
+ " auditor_denom_serial AS serial"
+ " FROM auditor_denom_sigs"
+ " ORDER BY auditor_denom_serial DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS:
+ XPREPARE ("select_serial_by_table_exchange_sign_keys",
+ "SELECT"
+ " esk_serial AS serial"
+ " FROM exchange_sign_keys"
+ " ORDER BY esk_serial DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS:
+ XPREPARE ("select_serial_by_table_signkey_revocations",
+ "SELECT"
+ " signkey_revocations_serial_id AS serial"
+ " FROM signkey_revocations"
+ " ORDER BY signkey_revocations_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_KNOWN_COINS:
+ XPREPARE ("select_serial_by_table_known_coins",
+ "SELECT"
+ " known_coin_id AS serial"
+ " FROM known_coins"
+ " ORDER BY known_coin_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_REFRESH:
+ XPREPARE ("select_serial_by_table_refresh",
+ "SELECT"
+ " refresh_id AS serial"
+ " FROM refresh"
+ " ORDER BY refresh_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS:
+ XPREPARE ("select_serial_by_table_batch_deposits",
+ "SELECT"
+ " batch_deposit_serial_id AS serial"
+ " FROM batch_deposits"
+ " ORDER BY batch_deposit_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_COIN_DEPOSITS:
+ XPREPARE ("select_serial_by_table_coin_deposits",
+ "SELECT"
+ " coin_deposit_serial_id AS serial"
+ " FROM coin_deposits"
+ " ORDER BY coin_deposit_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_REFUNDS:
+ XPREPARE ("select_serial_by_table_refunds",
+ "SELECT"
+ " refund_serial_id AS serial"
+ " FROM refunds"
+ " ORDER BY refund_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_WIRE_OUT:
+ XPREPARE ("select_serial_by_table_wire_out",
+ "SELECT"
+ " wireout_uuid AS serial"
+ " FROM wire_out"
+ " ORDER BY wireout_uuid DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING:
+ XPREPARE ("select_serial_by_table_aggregation_tracking",
+ "SELECT"
+ " aggregation_serial_id AS serial"
+ " FROM aggregation_tracking"
+ " ORDER BY aggregation_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_WIRE_FEE:
+ XPREPARE ("select_serial_by_table_wire_fee",
+ "SELECT"
+ " wire_fee_serial AS serial"
+ " FROM wire_fee"
+ " ORDER BY wire_fee_serial DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_GLOBAL_FEE:
+ XPREPARE ("select_serial_by_table_global_fee",
+ "SELECT"
+ " global_fee_serial AS serial"
+ " FROM global_fee"
+ " ORDER BY global_fee_serial DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_RECOUP:
+ XPREPARE ("select_serial_by_table_recoup",
+ "SELECT"
+ " recoup_uuid AS serial"
+ " FROM recoup"
+ " ORDER BY recoup_uuid DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_RECOUP_REFRESH:
+ XPREPARE ("select_serial_by_table_recoup_refresh",
+ "SELECT"
+ " recoup_refresh_uuid AS serial"
+ " FROM recoup_refresh"
+ " ORDER BY recoup_refresh_uuid DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_EXTENSIONS:
+ XPREPARE ("select_serial_by_table_extensions",
+ "SELECT"
+ " extension_id AS serial"
+ " FROM extensions"
+ " ORDER BY extension_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_POLICY_DETAILS:
+ XPREPARE ("select_serial_by_table_policy_details",
+ "SELECT"
+ " policy_details_serial_id AS serial"
+ " FROM policy_details"
+ " ORDER BY policy_details_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS:
+ XPREPARE ("select_serial_by_table_policy_fulfillments",
+ "SELECT"
+ " fulfillment_id AS serial"
+ " FROM policy_fulfillments"
+ " ORDER BY fulfillment_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
+ XPREPARE ("select_serial_by_table_purse_requests",
+ "SELECT"
+ " purse_requests_serial_id AS serial"
+ " FROM purse_requests"
+ " ORDER BY purse_requests_serial_id DESC"
+ " LIMIT 1;")
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_DECISION:
+ XPREPARE ("select_serial_by_table_purse_decision",
+ "SELECT"
+ " purse_decision_serial_id AS serial"
+ " FROM purse_decision"
+ " ORDER BY purse_decision_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_MERGES:
+ XPREPARE ("select_serial_by_table_purse_merges",
+ "SELECT"
+ " purse_merge_request_serial_id AS serial"
+ " FROM purse_merges"
+ " ORDER BY purse_merge_request_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS:
+ XPREPARE ("select_serial_by_table_purse_deposits",
+ "SELECT"
+ " purse_deposit_serial_id AS serial"
+ " FROM purse_deposits"
+ " ORDER BY purse_deposit_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES:
+ XPREPARE ("select_serial_by_table_account_merges",
+ "SELECT"
+ " account_merge_request_serial_id AS serial"
+ " FROM account_merges"
+ " ORDER BY account_merge_request_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS:
+ XPREPARE ("select_serial_by_table_history_requests",
+ "SELECT"
+ " history_request_serial_id AS serial"
+ " FROM history_requests"
+ " ORDER BY history_request_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS:
+ XPREPARE ("select_serial_by_table_close_requests",
+ "SELECT"
+ " close_request_serial_id AS serial"
+ " FROM close_requests"
+ " ORDER BY close_request_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_OUT:
+ XPREPARE ("select_serial_by_table_wads_out",
+ "SELECT"
+ " wad_out_serial_id AS serial"
+ " FROM wads_out"
+ " ORDER BY wad_out_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES:
+ XPREPARE ("select_serial_by_table_wads_out_entries",
+ "SELECT"
+ " wad_out_entry_serial_id AS serial"
+ " FROM wad_out_entries"
+ " ORDER BY wad_out_entry_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_IN:
+ XPREPARE ("select_serial_by_table_wads_in",
+ "SELECT"
+ " wad_in_serial_id AS serial"
+ " FROM wads_in"
+ " ORDER BY wad_in_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES:
+ XPREPARE ("select_serial_by_table_wads_in_entries",
+ "SELECT"
+ " wad_in_entry_serial_id AS serial"
+ " FROM wad_in_entries"
+ " ORDER BY wad_in_entry_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_PROFIT_DRAINS:
+ XPREPARE ("select_serial_by_table_profit_drains",
+ "SELECT"
+ " profit_drain_serial_id AS serial"
+ " FROM profit_drains"
+ " ORDER BY profit_drain_serial_id DESC"
+ " LIMIT 1;");
+ statement = "select_serial_by_table_profit_drains";
+ break;
+ case TALER_EXCHANGEDB_RT_AML_STAFF:
+ XPREPARE ("select_serial_by_table_aml_staff",
+ "SELECT"
+ " aml_staff_uuid AS serial"
+ " FROM aml_staff"
+ " ORDER BY aml_staff_uuid DESC"
+ " LIMIT 1;");
+ statement = "select_serial_by_table_aml_staff";
+ break;
+ case TALER_EXCHANGEDB_RT_PURSE_DELETION:
+ XPREPARE ("select_serial_by_table_purse_deletion",
+ "SELECT"
+ " purse_deletion_serial_id AS serial"
+ " FROM purse_deletion"
+ " ORDER BY purse_deletion_serial_id DESC"
+ " LIMIT 1;");
+ statement = "select_serial_by_table_purse_deletion";
+ break;
+ case TALER_EXCHANGEDB_RT_WITHDRAW:
+ XPREPARE ("select_serial_by_table_withdraw",
+ "SELECT"
+ " withdraw_id AS serial"
+ " FROM withdraw"
+ " ORDER BY withdraw_id DESC"
+ " LIMIT 1;");
+ statement = "select_serial_by_table_withdraw";
+ break;
+ case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES:
+ XPREPARE ("select_serial_by_table_legitimization_measures",
+ "SELECT"
+ " legitimization_measure_serial_id AS serial"
+ " FROM legitimization_measures"
+ " ORDER BY legitimization_measure_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES:
+ XPREPARE ("select_serial_by_table_legitimization_outcomes",
+ "SELECT"
+ " outcome_serial_id AS serial"
+ " FROM legitimization_outcomes"
+ " ORDER BY outcome_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES:
+ XPREPARE ("select_serial_by_table_legitimization_processes",
+ "SELECT"
+ " legitimization_process_serial_id AS serial"
+ " FROM legitimization_processes"
+ " ORDER BY legitimization_process_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES:
+ XPREPARE ("select_serial_by_table_kyc_attributes",
+ "SELECT"
+ " kyc_attributes_serial_id AS serial"
+ " FROM kyc_attributes"
+ " ORDER BY kyc_attributes_serial_id DESC"
+ " LIMIT 1;");
+ statement = "select_serial_by_table_kyc_attributes";
+ break;
+ case TALER_EXCHANGEDB_RT_AML_HISTORY:
+ XPREPARE ("select_serial_by_table_aml_history",
+ "SELECT"
+ " aml_history_serial_id AS serial"
+ " FROM aml_history"
+ " ORDER BY aml_history_serial_id DESC"
+ " LIMIT 1;");
+ statement = "select_serial_by_table_aml_history";
+ break;
+ case TALER_EXCHANGEDB_RT_KYC_EVENTS:
+ XPREPARE ("select_serial_by_table_kyc_events",
+ "SELECT"
+ " kyc_event_serial_id AS serial"
+ " FROM kyc_events"
+ " ORDER BY kyc_event_serial_id DESC"
+ " LIMIT 1;");
+ break;
+ }
+ if (NULL == statement)
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ statement,
+ params,
+ rs);
+}
+
+
+#undef XPREPARE
diff --git a/src/exchangedb/lookup_signing_key.c b/src/exchangedb/lookup_signing_key.c
@@ -0,0 +1,60 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_signing_key.c
+ * @brief Implementation of the lookup_signing_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_signing_key.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_signing_key (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ struct TALER_EXCHANGEDB_SignkeyMetaData *meta)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (exchange_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("valid_from",
+ &meta->start),
+ GNUNET_PQ_result_spec_timestamp ("expire_sign",
+ &meta->expire_sign),
+ GNUNET_PQ_result_spec_timestamp ("expire_legal",
+ &meta->expire_legal),
+ GNUNET_PQ_result_spec_end
+ };
+
+
+ PREPARE (pg,
+ "lookup_signing_key",
+ "SELECT"
+ " valid_from"
+ ",expire_sign"
+ ",expire_legal"
+ " FROM exchange_sign_keys"
+ " WHERE exchange_pub=$1");
+
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_signing_key",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_signkey_revocation.c b/src/exchangedb/lookup_signkey_revocation.c
@@ -0,0 +1,55 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_signkey_revocation.c
+ * @brief Implementation of the lookup_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_signkey_revocation.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_signkey_revocation (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (exchange_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "lookup_signkey_revocation",
+ "SELECT "
+ " master_sig"
+ " FROM signkey_revocations"
+ " WHERE esk_serial="
+ " (SELECT esk_serial"
+ " FROM exchange_sign_keys"
+ " WHERE exchange_pub=$1);");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_signkey_revocation",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_transfer_by_deposit.c b/src/exchangedb/lookup_transfer_by_deposit.c
@@ -0,0 +1,220 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_transfer_by_deposit.c
+ * @brief Implementation of the lookup_transfer_by_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_transfer_by_deposit.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_transfer_by_deposit (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const struct TALER_MerchantWireHashP *h_wire,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ bool *pending,
+ struct TALER_WireTransferIdentifierRawP *wtid,
+ struct GNUNET_TIME_Timestamp *exec_time,
+ struct TALER_Amount *amount_with_fee,
+ struct TALER_Amount *deposit_fee,
+ struct TALER_EXCHANGEDB_KycStatus *kyc,
+ union TALER_AccountPublicKeyP *account_pub)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+ GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct TALER_FullPayto payto_uri;
+ struct TALER_WireSaltP wire_salt;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+ wtid),
+ GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+ &wire_salt),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri.full_payto),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ exec_time),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ deposit_fee),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("target_pub",
+ account_pub),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+
+ memset (kyc,
+ 0,
+ sizeof (*kyc));
+ /* check if the aggregation record exists and get it */
+ PREPARE (pg,
+ "lookup_deposit_wtid",
+ "SELECT"
+ " atr.wtid_raw"
+ ",wire_out.execution_date"
+ ",cdep.amount_with_fee"
+ ",bdep.wire_salt"
+ ",wt.payto_uri"
+ ",kt.target_pub"
+ ",denom.fee_deposit"
+ " FROM coin_deposits cdep"
+ " JOIN batch_deposits bdep"
+ " USING (batch_deposit_serial_id)"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ /* kyc_targets might not match; then target_pub will be NULL */
+ " LEFT JOIN kyc_targets kt"
+ " USING (h_normalized_payto)"
+ " JOIN aggregation_tracking atr"
+ " ON (cdep.batch_deposit_serial_id = atr.batch_deposit_serial_id)"
+ " JOIN known_coins kc"
+ " ON (kc.coin_pub = cdep.coin_pub)"
+ " JOIN denominations denom"
+ " USING (denominations_serial)"
+ " JOIN wire_out"
+ " USING (wtid_raw)"
+ " WHERE cdep.coin_pub=$1"
+ " AND bdep.merchant_pub=$3"
+ " AND bdep.h_contract_terms=$2");
+ /* NOTE: above query might be more efficient if we computed the shard
+ from the merchant_pub and included that in the query */
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_deposit_wtid",
+ params,
+ rs);
+ if (0 > qs)
+ return qs;
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ struct TALER_MerchantWireHashP wh;
+
+ TALER_merchant_wire_signature_hash (payto_uri,
+ &wire_salt,
+ &wh);
+ if (0 ==
+ GNUNET_memcmp (&wh,
+ h_wire))
+ {
+ *pending = false;
+ kyc->ok = true;
+ GNUNET_PQ_cleanup_result (rs);
+ return qs;
+ }
+ qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ GNUNET_PQ_cleanup_result (rs);
+ }
+ *pending = true;
+ memset (wtid,
+ 0,
+ sizeof (*wtid));
+ GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "lookup_deposit_wtid returned 0 matching rows\n");
+ {
+ /* Check if transaction exists in deposits, so that we just
+ do not have a WTID yet. In that case, return without wtid
+ (by setting 'pending' true). */
+ struct GNUNET_PQ_ResultSpec rs2[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+ &wire_salt),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri.full_payto),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ deposit_fee),
+ GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+ exec_time),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("legitimization_requirement_serial_id",
+ &kyc->requirement_row),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("target_pub",
+ account_pub),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_deposit_without_wtid",
+ "SELECT"
+ " bdep.wire_salt"
+ ",wt.payto_uri"
+ ",cdep.amount_with_fee"
+ ",denom.fee_deposit"
+ ",bdep.wire_deadline"
+ ",agt.legitimization_requirement_serial_id"
+ ",kt.target_pub"
+ " FROM coin_deposits cdep"
+ " JOIN batch_deposits bdep"
+ " USING (batch_deposit_serial_id)"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ /* kyc_targets might not match; then target_pub will be NULL */
+ " LEFT JOIN kyc_targets kt"
+ " USING (h_normalized_payto)"
+ " JOIN known_coins kc"
+ " ON (kc.coin_pub = cdep.coin_pub)"
+ " JOIN denominations denom"
+ " USING (denominations_serial)"
+ " LEFT JOIN aggregation_transient agt "
+ " ON ( (bdep.wire_target_h_payto = agt.wire_target_h_payto) AND"
+ " (bdep.merchant_pub = agt.merchant_pub) )"
+ " WHERE cdep.coin_pub=$1"
+ " AND bdep.merchant_pub=$3"
+ " AND bdep.h_contract_terms=$2"
+ " LIMIT 1;");
+ /* NOTE: above query might be more efficient if we computed the shard
+ from the merchant_pub and included that in the query */
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_deposit_without_wtid",
+ params,
+ rs2);
+ if (0 > qs)
+ return qs;
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ struct TALER_MerchantWireHashP wh;
+
+ TALER_merchant_wire_signature_hash (payto_uri,
+ &wire_salt,
+ &wh);
+ if (0 !=
+ GNUNET_memcmp (&wh,
+ h_wire))
+ {
+ GNUNET_PQ_cleanup_result (rs2);
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ GNUNET_PQ_cleanup_result (rs2);
+ if (0 == kyc->requirement_row)
+ kyc->ok = true; /* technically: unknown */
+ }
+ return qs;
+ }
+}
diff --git a/src/exchangedb/lookup_wire_fee_by_time.c b/src/exchangedb/lookup_wire_fee_by_time.c
@@ -0,0 +1,152 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_wire_fee_by_time.c
+ * @brief Implementation of the lookup_wire_fee_by_time function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_wire_fee_by_time.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #wire_fee_by_time_helper()
+ */
+struct WireFeeLookupContext
+{
+
+ /**
+ * Set to the wire fees. Set to invalid if fees conflict over
+ * the given time period.
+ */
+ struct TALER_WireFeeSet *fees;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+};
+
+
+/**
+ * Helper function for #TALER_EXCHANGEDB_lookup_wire_fee_by_time().
+ * Calls the callback with the wire fee structure.
+ *
+ * @param cls a `struct WireFeeLookupContext`
+ * @param result db results
+ * @param num_results number of results in @a result
+ */
+static void
+wire_fee_by_time_helper (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireFeeLookupContext *wlc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = wlc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_WireFeeSet fs;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
+ &fs.wire),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
+ &fs.closing),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ /* invalidate */
+ memset (wlc->fees,
+ 0,
+ sizeof (struct TALER_WireFeeSet));
+ return;
+ }
+ if (0 == i)
+ {
+ *wlc->fees = fs;
+ continue;
+ }
+ if (0 !=
+ TALER_wire_fee_set_cmp (&fs,
+ wlc->fees))
+ {
+ /* invalidate */
+ memset (wlc->fees,
+ 0,
+ sizeof (struct TALER_WireFeeSet));
+ return;
+ }
+ }
+}
+
+
+/**
+ * Lookup information about known wire fees. Finds all applicable
+ * fees in the given range. If they are identical, returns the
+ * respective @a fees. If any of the fees
+ * differ between @a start_time and @a end_time, the transaction
+ * succeeds BUT returns an invalid amount for both fees.
+ *
+ * @param pg the database context
+ * @param wire_method the wire method to lookup fees for
+ * @param start_time starting time of fee
+ * @param end_time end time of fee
+ * @param[out] fees wire fees for that time period; if
+ * different fees exists within this time
+ * period, an 'invalid' amount is returned.
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_wire_fee_by_time (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *wire_method,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Timestamp end_time,
+ struct TALER_WireFeeSet *fees)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (wire_method),
+ GNUNET_PQ_query_param_timestamp (&start_time),
+ GNUNET_PQ_query_param_timestamp (&end_time),
+ GNUNET_PQ_query_param_end
+ };
+ struct WireFeeLookupContext wlc = {
+ .fees = fees,
+ .pg = pg
+ };
+
+ PREPARE (pg,
+ "lookup_wire_fee_by_time",
+ "SELECT"
+ " wire_fee"
+ ",closing_fee"
+ " FROM wire_fee"
+ " WHERE wire_method=$1"
+ " AND end_date > $2"
+ " AND start_date < $3;");
+ return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "lookup_wire_fee_by_time",
+ params,
+ &wire_fee_by_time_helper,
+ &wlc);
+}
diff --git a/src/exchangedb/lookup_wire_timestamp.c b/src/exchangedb/lookup_wire_timestamp.c
@@ -0,0 +1,52 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_wire_timestamp.c
+ * @brief Implementation of the lookup_wire_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_wire_timestamp.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_wire_timestamp (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPayto payto_uri,
+ struct GNUNET_TIME_Timestamp *last_date)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (payto_uri.full_payto),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("last_change",
+ last_date),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "lookup_wire_timestamp",
+ "SELECT"
+ " last_change"
+ " FROM wire_accounts"
+ " WHERE payto_uri=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "lookup_wire_timestamp",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/lookup_wire_transfer.c b/src/exchangedb/lookup_wire_transfer.c
@@ -0,0 +1,184 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/lookup_wire_transfer.c
+ * @brief Implementation of the lookup_wire_transfer function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/lookup_wire_transfer.h"
+#include "helper.h"
+
+/**
+ * Closure for #handle_wt_result.
+ */
+struct WireTransferResultContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_AggregationDataCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on serious errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results. Helper function
+ * for #TALER_EXCHANGEDB_lookup_wire_transfer().
+ *
+ * @param cls closure of type `struct WireTransferResultContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_wt_result (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireTransferResultContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct TALER_PrivateContractHashP h_contract_terms;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_FullPaytoHashP h_payto;
+ struct TALER_MerchantPublicKeyP merchant_pub;
+ struct GNUNET_TIME_Timestamp exec_time;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_Amount deposit_fee;
+ struct TALER_DenominationPublicKey denom_pub;
+ struct TALER_FullPayto payto_uri;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &h_contract_terms),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri.full_payto),
+ GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
+ &h_payto),
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ &denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+ &merchant_pub),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ &exec_time),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &deposit_fee),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ rowid,
+ &merchant_pub,
+ payto_uri,
+ &h_payto,
+ exec_time,
+ &h_contract_terms,
+ &denom_pub,
+ &coin_pub,
+ &amount_with_fee,
+ &deposit_fee);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_lookup_wire_transfer (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ TALER_EXCHANGEDB_AggregationDataCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_end
+ };
+ struct WireTransferResultContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "lookup_transactions",
+ "SELECT"
+ " aggregation_serial_id"
+ ",bdep.h_contract_terms"
+ ",payto_uri"
+ ",wt.wire_target_h_payto"
+ ",kc.coin_pub"
+ ",bdep.merchant_pub"
+ ",wire_out.execution_date"
+ ",cdep.amount_with_fee"
+ ",denom.fee_deposit"
+ ",denom.denom_pub"
+ " FROM aggregation_tracking"
+ " JOIN batch_deposits bdep"
+ " USING (batch_deposit_serial_id)"
+ " JOIN coin_deposits cdep"
+ " USING (batch_deposit_serial_id)"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " JOIN known_coins kc"
+ " USING (coin_pub)"
+ " JOIN denominations denom"
+ " USING (denominations_serial)"
+ " JOIN wire_out"
+ " USING (wtid_raw)"
+ " WHERE wtid_raw=$1;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "lookup_transactions",
+ params,
+ &handle_wt_result,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/mark_refresh_reveal_success.c b/src/exchangedb/mark_refresh_reveal_success.c
@@ -0,0 +1,45 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/mark_refresh_reveal_success.c
+ * @brief Implementation of the mark_refresh_reveal_success function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/mark_refresh_reveal_success.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_mark_refresh_reveal_success (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_RefreshCommitmentP *rc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (rc),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "mark_refresh_reveal_success",
+ "UPDATE refresh"
+ " SET revealed=true"
+ " WHERE rc = $1");
+
+ return GNUNET_PQ_eval_prepared_non_select (
+ pg->conn,
+ "mark_refresh_reveal_success",
+ params);
+}
diff --git a/src/exchangedb/meson.build b/src/exchangedb/meson.build
@@ -78,214 +78,214 @@ libtalerexchangedb = library(
'free_coin_transaction_list.c',
'free_reserve_history.c',
'persist_aml_program_result.c',
- 'pg_abort_shard.c',
- 'pg_activate_signing_key.c',
- 'pg_add_denomination_key.c',
- 'pg_add_policy_fulfillment_proof.c',
- 'pg_aggregate.c',
- 'pg_batch_ensure_coin_known.c',
- 'pg_begin_revolving_shard.c',
- 'pg_begin_shard.c',
+ 'abort_shard.c',
+ 'activate_signing_key.c',
+ 'add_denomination_key.c',
+ 'add_policy_fulfillment_proof.c',
+ 'aggregate.c',
+ 'batch_ensure_coin_known.c',
+ 'begin_revolving_shard.c',
+ 'begin_shard.c',
'pg.c',
- 'pg_clear_aml_lock.c',
- 'pg_commit.c',
- 'pg_complete_shard.c',
- 'pg_compute_shard.c',
- 'pg_count_known_coins.c',
- 'pg_create_aggregation_transient.c',
- 'pg_create_tables.c',
- 'pg_delete_aggregation_transient.c',
- 'pg_delete_shard_locks.c',
- 'pg_disable_rules.c',
- 'pg_do_check_deposit_idempotent.c',
- 'pg_do_deposit.c',
- 'pg_do_purse_delete.c',
- 'pg_do_purse_deposit.c',
- 'pg_do_purse_merge.c',
- 'pg_do_recoup.c',
- 'pg_do_recoup_refresh.c',
- 'pg_do_refresh.c',
- 'pg_do_refund.c',
- 'pg_do_reserve_open.c',
- 'pg_do_reserve_purse.c',
- 'pg_do_withdraw.c',
- 'pg_drain_kyc_alert.c',
- 'pg_drop_tables.c',
- 'pg_enable_rules.c',
- 'pg_ensure_coin_known.c',
- 'pg_event_listen.c',
- 'pg_event_listen_cancel.c',
- 'pg_event_notify.c',
- 'pg_expire_purse.c',
- 'pg_find_aggregation_transient.c',
- 'pg_gc.c',
- 'pg_get_coin_denomination.c',
- 'pg_get_coin_transactions.c',
- 'pg_get_denomination_by_serial.c',
- 'pg_get_denomination_info.c',
- 'pg_get_denomination_revocation.c',
- 'pg_get_drain_profit.c',
- 'pg_get_expired_reserves.c',
- 'pg_get_extension_manifest.c',
- 'pg_get_global_fee.c',
- 'pg_get_global_fees.c',
- 'pg_get_known_coin.c',
- 'pg_get_kyc_rules.c',
- 'pg_get_old_coin_by_h_blind.c',
- 'pg_get_pending_kyc_requirement_process.c',
- 'pg_get_policy_details.c',
- 'pg_get_purse_deposit.c',
- 'pg_get_purse_request.c',
- 'pg_get_ready_deposit.c',
- 'pg_get_refresh.c',
- 'pg_get_reserve_balance.c',
- 'pg_get_reserve_by_h_planchets.c',
- 'pg_get_reserve_history.c',
- 'pg_get_signature_for_known_coin.c',
- 'pg_get_unfinished_close_requests.c',
- 'pg_get_wire_accounts.c',
- 'pg_get_wire_fee.c',
- 'pg_get_wire_fees.c',
- 'pg_get_wire_hash_for_contract.c',
- 'pg_get_withdraw.c',
- 'pg_have_deposit2.c',
- 'pg_inject_auditor_triggers.c',
- 'pg_insert_active_legitimization_measure.c',
- 'pg_insert_aml_decision.c',
- 'pg_insert_aml_officer.c',
- 'pg_insert_aml_program_failure.c',
- 'pg_insert_auditor.c',
- 'pg_insert_auditor_denom_sig.c',
- 'pg_insert_close_request.c',
- 'pg_insert_contract.c',
- 'pg_insert_denomination_info.c',
- 'pg_insert_denomination_revocation.c',
- 'pg_insert_drain_profit.c',
- 'pg_insert_global_fee.c',
- 'pg_insert_kyc_failure.c',
- 'pg_insert_kyc_requirement_process.c',
- 'pg_insert_partner.c',
- 'pg_insert_purse_request.c',
- 'pg_insert_records_by_table.c',
- 'pg_insert_refund.c',
- 'pg_insert_reserve_closed.c',
- 'pg_insert_reserve_open_deposit.c',
- 'pg_insert_sanction_list_hit.c',
- 'pg_insert_signkey_revocation.c',
- 'pg_insert_successor_measure.c',
- 'pg_insert_wire.c',
- 'pg_insert_wire_fee.c',
- 'pg_iterate_active_auditors.c',
- 'pg_iterate_active_signkeys.c',
- 'pg_iterate_auditor_denominations.c',
- 'pg_iterate_denomination_info.c',
- 'pg_iterate_denominations.c',
- 'pg_iterate_kyc_reference.c',
- 'pg_iterate_reserve_close_info.c',
- 'pg_kycauth_in_insert.c',
- 'pg_kyc_provider_account_lookup.c',
- 'pg_lookup_active_legitimization.c',
- 'pg_lookup_aml_file_number.c',
- 'pg_lookup_aml_history.c',
- 'pg_lookup_aml_officer.c',
- 'pg_lookup_auditor_status.c',
- 'pg_lookup_auditor_timestamp.c',
- 'pg_lookup_completed_legitimization.c',
- 'pg_lookup_denomination_key.c',
- 'pg_lookup_global_fee_by_time.c',
- 'pg_lookup_h_payto_by_access_token.c',
- 'pg_lookup_kyc_history.c',
- 'pg_lookup_kyc_process_by_account.c',
- 'pg_lookup_kyc_requirement_by_row.c',
- 'pg_lookup_kyc_status_by_token.c',
- 'pg_lookup_pending_legitimization.c',
- 'pg_lookup_records_by_table.c',
- 'pg_lookup_rules_by_access_token.c',
- 'pg_lookup_serial_by_table.c',
- 'pg_lookup_signing_key.c',
- 'pg_lookup_signkey_revocation.c',
- 'pg_lookup_transfer_by_deposit.c',
- 'pg_lookup_wire_fee_by_time.c',
- 'pg_lookup_wire_timestamp.c',
- 'pg_lookup_wire_transfer.c',
- 'pg_mark_refresh_reveal_success.c',
- 'pg_persist_kyc_attributes.c',
- 'pg_persist_policy_details.c',
- 'pg_preflight.c',
- 'pg_profit_drains_get_pending.c',
- 'pg_profit_drains_set_finished.c',
- 'pg_release_revolving_shard.c',
- 'pg_reserves_get.c',
- 'pg_reserves_get_origin.c',
- 'pg_reserves_in_insert.c',
- 'pg_reserves_update.c',
- 'pg_rollback.c',
- 'pg_select_account_merges_above_serial_id.c',
- 'pg_select_aggregation_amounts_for_kyc_check.c',
- 'pg_select_aggregations_above_serial.c',
- 'pg_select_aggregation_transient.c',
- 'pg_select_all_kyc_attributes.c',
- 'pg_select_all_purse_decisions_above_serial_id.c',
- 'pg_select_all_purse_deletions_above_serial_id.c',
- 'pg_select_aml_attributes.c',
- 'pg_select_aml_decisions.c',
- 'pg_select_aml_measures.c',
- 'pg_select_aml_statistics.c',
- 'pg_select_auditor_denom_sig.c',
- 'pg_select_batch_deposits_missing_wire.c',
- 'pg_select_coin_deposits_above_serial_id.c',
- 'pg_select_contract_by_purse.c',
- 'pg_select_contract.c',
- 'pg_select_deposit_amounts_for_kyc_check.c',
- 'pg_select_exchange_credit_transfers.c',
- 'pg_select_exchange_debit_transfers.c',
- 'pg_select_exchange_kycauth_transfers.c',
- 'pg_select_kyc_accounts.c',
- 'pg_select_kyc_attributes.c',
- 'pg_select_merge_amounts_for_kyc_check.c',
- 'pg_select_purse_by_merge_pub.c',
- 'pg_select_purse.c',
- 'pg_select_purse_decisions_above_serial_id.c',
- 'pg_select_purse_deposits_above_serial_id.c',
- 'pg_select_purse_deposits_by_purse.c',
- 'pg_select_purse_merge.c',
- 'pg_select_purse_merges_above_serial_id.c',
- 'pg_select_purse_requests_above_serial_id.c',
- 'pg_select_recoup_above_serial_id.c',
- 'pg_select_recoup_refresh_above_serial_id.c',
- 'pg_select_refreshes_above_serial_id.c',
- 'pg_select_refunds_above_serial_id.c',
- 'pg_select_refunds_by_coin.c',
- 'pg_select_reserve_closed_above_serial_id.c',
- 'pg_select_reserve_close_info.c',
- 'pg_select_reserve_close_request_info.c',
- 'pg_select_reserve_open_above_serial_id.c',
- 'pg_select_reserves_in_above_serial_id_by_account.c',
- 'pg_select_reserves_in_above_serial_id.c',
- 'pg_select_wire_out_above_serial_id_by_account.c',
- 'pg_select_wire_out_above_serial_id.c',
- 'pg_select_withdrawals_above_serial_id.c',
- 'pg_select_withdraw_amounts_for_kyc_check.c',
- 'pg_set_aml_lock.c',
- 'pg_set_extension_manifest.c',
- 'pg_set_purse_balance.c',
- 'pg_start.c',
- 'pg_start_deferred_wire_out.c',
- 'pg_start_read_committed.c',
- 'pg_start_read_only.c',
- 'pg_store_wire_transfer_out.c',
- 'pg_template.c',
- 'pg_test_aml_officer.c',
- 'pg_trigger_kyc_rule_for_account.c',
- 'pg_update_aggregation_transient.c',
- 'pg_update_auditor.c',
- 'pg_update_kyc_process_by_row.c',
- 'pg_update_wire.c',
- 'pg_wad_in_insert.c',
- 'pg_wire_prepare_data_get.c',
- 'pg_wire_prepare_data_insert.c',
- 'pg_wire_prepare_data_mark_failed.c',
- 'pg_wire_prepare_data_mark_finished.c',
+ 'clear_aml_lock.c',
+ 'commit.c',
+ 'complete_shard.c',
+ 'compute_shard.c',
+ 'count_known_coins.c',
+ 'create_aggregation_transient.c',
+ 'create_tables.c',
+ 'delete_aggregation_transient.c',
+ 'delete_shard_locks.c',
+ 'disable_rules.c',
+ 'do_check_deposit_idempotent.c',
+ 'do_deposit.c',
+ 'do_purse_delete.c',
+ 'do_purse_deposit.c',
+ 'do_purse_merge.c',
+ 'do_recoup.c',
+ 'do_recoup_refresh.c',
+ 'do_refresh.c',
+ 'do_refund.c',
+ 'do_reserve_open.c',
+ 'do_reserve_purse.c',
+ 'do_withdraw.c',
+ 'drain_kyc_alert.c',
+ 'drop_tables.c',
+ 'enable_rules.c',
+ 'ensure_coin_known.c',
+ 'event_listen.c',
+ 'event_listen_cancel.c',
+ 'event_notify.c',
+ 'expire_purse.c',
+ 'find_aggregation_transient.c',
+ 'gc.c',
+ 'get_coin_denomination.c',
+ 'get_coin_transactions.c',
+ 'get_denomination_by_serial.c',
+ 'get_denomination_info.c',
+ 'get_denomination_revocation.c',
+ 'get_drain_profit.c',
+ 'get_expired_reserves.c',
+ 'get_extension_manifest.c',
+ 'get_global_fee.c',
+ 'get_global_fees.c',
+ 'get_known_coin.c',
+ 'get_kyc_rules.c',
+ 'get_old_coin_by_h_blind.c',
+ 'get_pending_kyc_requirement_process.c',
+ 'get_policy_details.c',
+ 'get_purse_deposit.c',
+ 'get_purse_request.c',
+ 'get_ready_deposit.c',
+ 'get_refresh.c',
+ 'get_reserve_balance.c',
+ 'get_reserve_by_h_planchets.c',
+ 'get_reserve_history.c',
+ 'get_signature_for_known_coin.c',
+ 'get_unfinished_close_requests.c',
+ 'get_wire_accounts.c',
+ 'get_wire_fee.c',
+ 'get_wire_fees.c',
+ 'get_wire_hash_for_contract.c',
+ 'get_withdraw.c',
+ 'have_deposit2.c',
+ 'inject_auditor_triggers.c',
+ 'insert_active_legitimization_measure.c',
+ 'insert_aml_decision.c',
+ 'insert_aml_officer.c',
+ 'insert_aml_program_failure.c',
+ 'insert_auditor.c',
+ 'insert_auditor_denom_sig.c',
+ 'insert_close_request.c',
+ 'insert_contract.c',
+ 'insert_denomination_info.c',
+ 'insert_denomination_revocation.c',
+ 'insert_drain_profit.c',
+ 'insert_global_fee.c',
+ 'insert_kyc_failure.c',
+ 'insert_kyc_requirement_process.c',
+ 'insert_partner.c',
+ 'insert_purse_request.c',
+ 'insert_records_by_table.c',
+ 'insert_refund.c',
+ 'insert_reserve_closed.c',
+ 'insert_reserve_open_deposit.c',
+ 'insert_sanction_list_hit.c',
+ 'insert_signkey_revocation.c',
+ 'insert_successor_measure.c',
+ 'insert_wire.c',
+ 'insert_wire_fee.c',
+ 'iterate_active_auditors.c',
+ 'iterate_active_signkeys.c',
+ 'iterate_auditor_denominations.c',
+ 'iterate_denomination_info.c',
+ 'iterate_denominations.c',
+ 'iterate_kyc_reference.c',
+ 'iterate_reserve_close_info.c',
+ 'kycauth_in_insert.c',
+ 'kyc_provider_account_lookup.c',
+ 'lookup_active_legitimization.c',
+ 'lookup_aml_file_number.c',
+ 'lookup_aml_history.c',
+ 'lookup_aml_officer.c',
+ 'lookup_auditor_status.c',
+ 'lookup_auditor_timestamp.c',
+ 'lookup_completed_legitimization.c',
+ 'lookup_denomination_key.c',
+ 'lookup_global_fee_by_time.c',
+ 'lookup_h_payto_by_access_token.c',
+ 'lookup_kyc_history.c',
+ 'lookup_kyc_process_by_account.c',
+ 'lookup_kyc_requirement_by_row.c',
+ 'lookup_kyc_status_by_token.c',
+ 'lookup_pending_legitimization.c',
+ 'lookup_records_by_table.c',
+ 'lookup_rules_by_access_token.c',
+ 'lookup_serial_by_table.c',
+ 'lookup_signing_key.c',
+ 'lookup_signkey_revocation.c',
+ 'lookup_transfer_by_deposit.c',
+ 'lookup_wire_fee_by_time.c',
+ 'lookup_wire_timestamp.c',
+ 'lookup_wire_transfer.c',
+ 'mark_refresh_reveal_success.c',
+ 'persist_kyc_attributes.c',
+ 'persist_policy_details.c',
+ 'preflight.c',
+ 'profit_drains_get_pending.c',
+ 'profit_drains_set_finished.c',
+ 'release_revolving_shard.c',
+ 'reserves_get.c',
+ 'reserves_get_origin.c',
+ 'reserves_in_insert.c',
+ 'reserves_update.c',
+ 'rollback.c',
+ 'select_account_merges_above_serial_id.c',
+ 'select_aggregation_amounts_for_kyc_check.c',
+ 'select_aggregations_above_serial.c',
+ 'select_aggregation_transient.c',
+ 'select_all_kyc_attributes.c',
+ 'select_all_purse_decisions_above_serial_id.c',
+ 'select_all_purse_deletions_above_serial_id.c',
+ 'select_aml_attributes.c',
+ 'select_aml_decisions.c',
+ 'select_aml_measures.c',
+ 'select_aml_statistics.c',
+ 'select_auditor_denom_sig.c',
+ 'select_batch_deposits_missing_wire.c',
+ 'select_coin_deposits_above_serial_id.c',
+ 'select_contract_by_purse.c',
+ 'select_contract.c',
+ 'select_deposit_amounts_for_kyc_check.c',
+ 'select_exchange_credit_transfers.c',
+ 'select_exchange_debit_transfers.c',
+ 'select_exchange_kycauth_transfers.c',
+ 'select_kyc_accounts.c',
+ 'select_kyc_attributes.c',
+ 'select_merge_amounts_for_kyc_check.c',
+ 'select_purse_by_merge_pub.c',
+ 'select_purse.c',
+ 'select_purse_decisions_above_serial_id.c',
+ 'select_purse_deposits_above_serial_id.c',
+ 'select_purse_deposits_by_purse.c',
+ 'select_purse_merge.c',
+ 'select_purse_merges_above_serial_id.c',
+ 'select_purse_requests_above_serial_id.c',
+ 'select_recoup_above_serial_id.c',
+ 'select_recoup_refresh_above_serial_id.c',
+ 'select_refreshes_above_serial_id.c',
+ 'select_refunds_above_serial_id.c',
+ 'select_refunds_by_coin.c',
+ 'select_reserve_closed_above_serial_id.c',
+ 'select_reserve_close_info.c',
+ 'select_reserve_close_request_info.c',
+ 'select_reserve_open_above_serial_id.c',
+ 'select_reserves_in_above_serial_id_by_account.c',
+ 'select_reserves_in_above_serial_id.c',
+ 'select_wire_out_above_serial_id_by_account.c',
+ 'select_wire_out_above_serial_id.c',
+ 'select_withdrawals_above_serial_id.c',
+ 'select_withdraw_amounts_for_kyc_check.c',
+ 'set_aml_lock.c',
+ 'set_extension_manifest.c',
+ 'set_purse_balance.c',
+ 'start.c',
+ 'start_deferred_wire_out.c',
+ 'start_read_committed.c',
+ 'start_read_only.c',
+ 'store_wire_transfer_out.c',
+ 'template.c',
+ 'test_aml_officer.c',
+ 'trigger_kyc_rule_for_account.c',
+ 'update_aggregation_transient.c',
+ 'update_auditor.c',
+ 'update_kyc_process_by_row.c',
+ 'update_wire.c',
+ 'wad_in_insert.c',
+ 'wire_prepare_data_get.c',
+ 'wire_prepare_data_insert.c',
+ 'wire_prepare_data_mark_failed.c',
+ 'wire_prepare_data_mark_finished.c',
'update_rules.c',
],
soversion: solibversions['libtalerexchangedb']['soversion'],
diff --git a/src/exchangedb/persist_kyc_attributes.c b/src/exchangedb/persist_kyc_attributes.c
@@ -0,0 +1,103 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/persist_kyc_attributes.c
+ * @brief Implementation of the persist_kyc_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/persist_kyc_attributes.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_persist_kyc_attributes (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t process_row,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const char *provider_name,
+ const char *provider_account_id,
+ const char *provider_legitimization_id,
+ uint32_t birthday,
+ struct GNUNET_TIME_Absolute expiration_time,
+ const char *form_name,
+ size_t enc_attributes_size,
+ const void *enc_attributes)
+{
+ struct GNUNET_TIME_Timestamp collection_time
+ = GNUNET_TIME_timestamp_get ();
+ struct GNUNET_TIME_Timestamp expiration
+ = GNUNET_TIME_absolute_to_timestamp (expiration_time);
+ struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = *h_payto
+ };
+ char *kyc_completed_notify_s
+ = GNUNET_PQ_get_event_notify_channel (&rep.header);
+ struct GNUNET_PQ_QueryParam params[] = {
+ (0 == process_row)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_uint64 (&process_row),
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_uint32 (&birthday),
+ GNUNET_PQ_query_param_string (provider_name),
+ (NULL == provider_account_id)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (provider_account_id),
+ (NULL == provider_legitimization_id)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (provider_legitimization_id),
+ GNUNET_PQ_query_param_timestamp (&collection_time),
+ GNUNET_PQ_query_param_absolute_time (&expiration_time),
+ GNUNET_PQ_query_param_timestamp (&expiration),
+ (NULL == enc_attributes)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_fixed_size (enc_attributes,
+ enc_attributes_size),
+ GNUNET_PQ_query_param_string (kyc_completed_notify_s),
+ (NULL == form_name)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (form_name),
+ GNUNET_PQ_query_param_end
+ };
+ bool ok;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("out_ok",
+ &ok),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Inserting KYC attributes, wake up on %s\n",
+ kyc_completed_notify_s);
+ GNUNET_break (NULL != h_payto);
+ PREPARE (pg,
+ "persist_kyc_attributes",
+ "SELECT "
+ " out_ok"
+ " FROM exchange_do_persist_kyc_attributes "
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "persist_kyc_attributes",
+ params,
+ rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ GNUNET_free (kyc_completed_notify_s);
+ GNUNET_PQ_event_do_poll (pg->conn);
+ return qs;
+}
diff --git a/src/exchangedb/persist_policy_details.c b/src/exchangedb/persist_policy_details.c
@@ -0,0 +1,74 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/persist_policy_details.c
+ * @brief Implementation of the persist_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/persist_policy_details.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_persist_policy_details (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PolicyDetails *details,
+ uint64_t *policy_details_serial_id,
+ struct TALER_Amount *accumulated_total,
+ enum TALER_PolicyFulfillmentState *fulfillment_state)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&details->hash_code),
+ TALER_PQ_query_param_json (details->policy_json),
+ GNUNET_PQ_query_param_timestamp (&details->deadline),
+ TALER_PQ_query_param_amount (pg->conn,
+ &details->commitment),
+ TALER_PQ_query_param_amount (pg->conn,
+ &details->accumulated_total),
+ TALER_PQ_query_param_amount (pg->conn,
+ &details->policy_fee),
+ TALER_PQ_query_param_amount (pg->conn,
+ &details->transferable_amount),
+ GNUNET_PQ_query_param_auto_from_type (&details->fulfillment_state),
+ (details->no_policy_fulfillment_id)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_uint64 (&details->policy_fulfillment_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id",
+ policy_details_serial_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
+ accumulated_total),
+ GNUNET_PQ_result_spec_uint32 ("fulfillment_state",
+ fulfillment_state),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "call_insert_or_update_policy_details",
+ "SELECT"
+ " out_policy_details_serial_id AS policy_details_serial_id"
+ ",out_accumulated_total AS accumulated_total"
+ ",out_fulfillment_state AS fulfillment_state"
+ " FROM exchange_do_insert_or_update_policy_details"
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9);");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "call_insert_or_update_policy_details",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/pg_abort_shard.c b/src/exchangedb/pg_abort_shard.c
@@ -1,49 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_abort_shard.c
- * @brief Implementation of the abort_shard function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/abort_shard.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_abort_shard (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *job_name,
- uint64_t start_row,
- uint64_t end_row)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_uint64 (&start_row),
- GNUNET_PQ_query_param_uint64 (&end_row),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "abort_shard",
- "UPDATE work_shards"
- " SET last_attempt=0"
- " WHERE job_name=$1"
- " AND start_row=$2"
- " AND end_row=$3;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "abort_shard",
- params);
-}
diff --git a/src/exchangedb/pg_activate_signing_key.c b/src/exchangedb/pg_activate_signing_key.c
@@ -1,54 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_activate_signing_key.c
- * @brief Implementation of the activate_signing_key function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/activate_signing_key.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_activate_signing_key (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- const struct TALER_EXCHANGEDB_SignkeyMetaData *meta,
- const struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam iparams[] = {
- GNUNET_PQ_query_param_auto_from_type (exchange_pub),
- GNUNET_PQ_query_param_timestamp (&meta->start),
- GNUNET_PQ_query_param_timestamp (&meta->expire_sign),
- GNUNET_PQ_query_param_timestamp (&meta->expire_legal),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_signkey",
- "INSERT INTO exchange_sign_keys "
- "(exchange_pub"
- ",valid_from"
- ",expire_sign"
- ",expire_legal"
- ",master_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_signkey",
- iparams);
-}
diff --git a/src/exchangedb/pg_add_denomination_key.c b/src/exchangedb/pg_add_denomination_key.c
@@ -1,83 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_add_denomination_key.c
- * @brief Implementation of the add_denomination_key function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/add_denomination_key.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_add_denomination_key (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_DenominationHashP *h_denom_pub,
- const struct TALER_DenominationPublicKey *denom_pub,
- const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
- const struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam iparams[] = {
- GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
- TALER_PQ_query_param_denom_pub (denom_pub),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_timestamp (&meta->start),
- GNUNET_PQ_query_param_timestamp (&meta->expire_withdraw),
- GNUNET_PQ_query_param_timestamp (&meta->expire_deposit),
- GNUNET_PQ_query_param_timestamp (&meta->expire_legal),
- TALER_PQ_query_param_amount (pg->conn,
- &meta->value),
- TALER_PQ_query_param_amount (pg->conn,
- &meta->fees.withdraw),
- TALER_PQ_query_param_amount (pg->conn,
- &meta->fees.deposit),
- TALER_PQ_query_param_amount (pg->conn,
- &meta->fees.refresh),
- TALER_PQ_query_param_amount (pg->conn,
- &meta->fees.refund),
- GNUNET_PQ_query_param_uint32 (&meta->age_mask.bits),
- GNUNET_PQ_query_param_end
- };
-
- /* Sanity check: ensure fees match coin currency */
- GNUNET_assert (GNUNET_YES ==
- TALER_denom_fee_check_currency (meta->value.currency,
- &meta->fees));
- PREPARE (pg,
- "denomination_insert",
- "INSERT INTO denominations "
- "(denom_pub_hash"
- ",denom_pub"
- ",master_sig"
- ",valid_from"
- ",expire_withdraw"
- ",expire_deposit"
- ",expire_legal"
- ",coin" /* value of this denom */
- ",fee_withdraw"
- ",fee_deposit"
- ",fee_refresh"
- ",fee_refund"
- ",age_mask"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
- " $11, $12, $13);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "denomination_insert",
- iparams);
-}
diff --git a/src/exchangedb/pg_add_policy_fulfillment_proof.c b/src/exchangedb/pg_add_policy_fulfillment_proof.c
@@ -1,158 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_add_policy_fulfillment_proof.c
- * @brief Implementation of the add_policy_fulfillment_proof function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/platform.h" /* UNNECESSARY? */
-#include "taler/taler_error_codes.h" /* UNNECESSARY? */
-#include "taler/taler_dbevents.h" /* UNNECESSARY? */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/add_policy_fulfillment_proof.h"
-#include "helper.h"
-
-
-/**
- * Compares two indices into an array of hash codes according to
- * GNUNET_CRYPTO_hash_cmp of the content at those index positions.
- *
- * Used in a call qsort_t in order to generate sorted policy_hash_codes.
- */
-static int
-hash_code_cmp (
- const void *hc1,
- const void *hc2,
- void *arg)
-{
- size_t i1 = *(size_t *) hc1;
- size_t i2 = *(size_t *) hc2;
- const struct TALER_PolicyDetails *d = arg;
-
- return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code,
- &d[i2].hash_code);
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_add_policy_fulfillment_proof (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct TALER_PolicyFulfillmentTransactionData *fulfillment)
-{
- enum GNUNET_DB_QueryStatus qs;
- size_t count = fulfillment->details_count;
- /* FIXME[Oec]: this seems to be prone to VLA attacks */
- struct GNUNET_HashCode hcs[GNUNET_NZL (count)];
-
- /* Create the sorted policy_hash_codes */
- {
- size_t idx[GNUNET_NZL (count)];
- for (size_t i = 0; i < count; i++)
- idx[i] = i;
-
- /* Sort the indices according to the hash codes of the corresponding
- * details. */
- qsort_r (idx,
- count,
- sizeof(size_t),
- hash_code_cmp,
- fulfillment->details);
-
- /* Finally, concatenate all hash_codes in sorted order */
- for (size_t i = 0; i < count; i++)
- hcs[i] = fulfillment->details[idx[i]].hash_code;
- }
-
-
- /* Now, add the proof to the policy_fulfillments table, retrieve the
- * record_id */
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp),
- TALER_PQ_query_param_json (fulfillment->proof),
- GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof),
- TALER_PQ_query_param_array_hash_code (count, hcs, pg->conn),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
- &fulfillment->fulfillment_id),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "insert_proof_into_policy_fulfillments",
- "INSERT INTO policy_fulfillments"
- "(fulfillment_timestamp"
- ",fulfillment_proof"
- ",h_fulfillment_proof"
- ",policy_hash_codes"
- ") VALUES ($1, $2::TEXT::JSON, $3, $4)"
- " ON CONFLICT DO NOTHING;");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "insert_proof_into_policy_fulfillments",
- params,
- rs);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- return qs;
- }
-
- /* Now, set the states of each entry corresponding to the hash_codes in
- * policy_details accordingly */
- for (size_t i = 0; i < count; i++)
- {
- struct TALER_PolicyDetails *pos = &fulfillment->details[i];
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&pos->hash_code),
- GNUNET_PQ_query_param_timestamp (&pos->deadline),
- TALER_PQ_query_param_amount (pg->conn,
- &pos->commitment),
- TALER_PQ_query_param_amount (pg->conn,
- &pos->accumulated_total),
- TALER_PQ_query_param_amount (pg->conn,
- &pos->policy_fee),
- TALER_PQ_query_param_amount (pg->conn,
- &pos->transferable_amount),
- GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "update_policy_details",
- "UPDATE policy_details SET"
- " deadline=$2"
- ",commitment=$3"
- ",accumulated_total=$4"
- ",fee=$5"
- ",transferable=$6"
- ",fulfillment_state=$7"
- " WHERE policy_hash_code=$1;");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "update_policy_details",
- params);
- if (qs < 0)
- return qs;
- }
- }
-
- /*
- * FIXME[oec]-#7999: When all policies of a deposit are fulfilled,
- * unblock it and trigger a wire-transfer.
- */
-
- return qs;
-}
diff --git a/src/exchangedb/pg_aggregate.c b/src/exchangedb/pg_aggregate.c
@@ -1,201 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_aggregate.c
- * @brief Implementation of the aggregate function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/compute_shard.h"
-#include "taler/exchange-database/aggregate.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_aggregate (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPaytoHashP *h_payto,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- struct TALER_Amount *total)
-{
- uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (merchant_pub);
- struct GNUNET_TIME_Absolute now = {0};
- uint64_t sum_deposit_value;
- uint64_t sum_deposit_frac;
- uint64_t sum_refund_value;
- uint64_t sum_refund_frac;
- uint64_t sum_fee_value;
- uint64_t sum_fee_frac;
- enum GNUNET_DB_QueryStatus qs;
- struct TALER_Amount sum_deposit;
- struct TALER_Amount sum_refund;
- struct TALER_Amount sum_fee;
- struct TALER_Amount delta;
-
- now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
- pg->aggregator_shift);
- PREPARE (pg,
- "aggregate",
- "WITH bdep AS (" /* restrict to our merchant and account and mark as done */
- " UPDATE batch_deposits"
- " SET done=TRUE"
- " WHERE NOT (done OR policy_blocked)" /* only actually executable deposits */
- " AND refund_deadline<$1"
- " AND shard=$5" /* only for efficiency, merchant_pub is what we really filter by */
- " AND merchant_pub=$2" /* filter by target merchant */
- " AND wire_target_h_payto=$3" /* merchant could have a 2nd bank account */
- " RETURNING"
- " batch_deposit_serial_id)"
- " ,cdep AS ("
- " SELECT"
- " coin_deposit_serial_id"
- " ,batch_deposit_serial_id"
- " ,coin_pub"
- " ,amount_with_fee AS amount"
- " FROM coin_deposits"
- " WHERE batch_deposit_serial_id IN (SELECT batch_deposit_serial_id FROM bdep))"
- " ,ref AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */
- " SELECT"
- " amount_with_fee AS refund"
- " ,coin_pub"
- " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */
- " FROM refunds"
- " WHERE coin_pub IN (SELECT coin_pub FROM cdep)"
- " AND batch_deposit_serial_id IN (SELECT batch_deposit_serial_id FROM bdep))"
- " ,ref_by_coin AS (" /* total up refunds by coin */
- " SELECT"
- " SUM((ref.refund).val) AS sum_refund_val"
- " ,SUM((ref.refund).frac) AS sum_refund_frac"
- " ,coin_pub"
- " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */
- " FROM ref"
- " GROUP BY coin_pub, batch_deposit_serial_id)"
- " ,norm_ref_by_coin AS (" /* normalize */
- " SELECT"
- " sum_refund_val + sum_refund_frac / 100000000 AS norm_refund_val"
- " ,sum_refund_frac % 100000000 AS norm_refund_frac"
- " ,coin_pub"
- " ,batch_deposit_serial_id" /* theoretically, coin could be in multiple refunded transactions */
- " FROM ref_by_coin)"
- " ,fully_refunded_coins AS (" /* find applicable refunds -- NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */
- " SELECT"
- " cdep.coin_pub"
- " FROM norm_ref_by_coin norm"
- " JOIN cdep"
- " ON (norm.coin_pub = cdep.coin_pub"
- " AND norm.batch_deposit_serial_id = cdep.batch_deposit_serial_id"
- " AND norm.norm_refund_val = (cdep.amount).val"
- " AND norm.norm_refund_frac = (cdep.amount).frac))"
- " ,fees AS (" /* find deposit fees for not fully refunded deposits */
- " SELECT"
- " denom.fee_deposit AS fee"
- " ,cs.batch_deposit_serial_id" /* ensures we get the fee for each coin, not once per denomination */
- " FROM cdep cs"
- " JOIN known_coins kc" /* NOTE: may do a full join on the master, maybe find a left-join way to integrate with query above to push it to the shards? */
- " USING (coin_pub)"
- " JOIN denominations denom"
- " USING (denominations_serial)"
- " WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins))"
- " ,dummy AS (" /* add deposits to aggregation_tracking */
- " INSERT INTO aggregation_tracking"
- " (batch_deposit_serial_id"
- " ,wtid_raw)"
- " SELECT batch_deposit_serial_id,$4"
- " FROM bdep)"
- "SELECT" /* calculate totals (deposits, refunds and fees) */
- " CAST(COALESCE(SUM((cdep.amount).val),0) AS INT8) AS sum_deposit_value"
- /* cast needed, otherwise we get NUMBER */
- " ,COALESCE(SUM((cdep.amount).frac),0) AS sum_deposit_fraction" /* SUM over INT returns INT8 */
- " ,CAST(COALESCE(SUM((ref.refund).val),0) AS INT8) AS sum_refund_value"
- " ,COALESCE(SUM((ref.refund).frac),0) AS sum_refund_fraction"
- " ,CAST(COALESCE(SUM((fees.fee).val),0) AS INT8) AS sum_fee_value"
- " ,COALESCE(SUM((fees.fee).frac),0) AS sum_fee_fraction"
- " FROM cdep "
- " FULL OUTER JOIN ref ON (FALSE)" /* We just want all sums */
- " FULL OUTER JOIN fees ON (FALSE);");
-
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_auto_from_type (merchant_pub),
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_uint64 (&deposit_shard),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("sum_deposit_value",
- &sum_deposit_value),
- GNUNET_PQ_result_spec_uint64 ("sum_deposit_fraction",
- &sum_deposit_frac),
- GNUNET_PQ_result_spec_uint64 ("sum_refund_value",
- &sum_refund_value),
- GNUNET_PQ_result_spec_uint64 ("sum_refund_fraction",
- &sum_refund_frac),
- GNUNET_PQ_result_spec_uint64 ("sum_fee_value",
- &sum_fee_value),
- GNUNET_PQ_result_spec_uint64 ("sum_fee_fraction",
- &sum_fee_frac),
- GNUNET_PQ_result_spec_end
- };
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "aggregate",
- params,
- rs);
- }
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- return qs;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (pg->currency,
- total));
- return qs;
- }
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (pg->currency,
- &sum_deposit));
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (pg->currency,
- &sum_refund));
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (pg->currency,
- &sum_fee));
- sum_deposit.value = sum_deposit_frac / TALER_AMOUNT_FRAC_BASE
- + sum_deposit_value;
- sum_deposit.fraction = sum_deposit_frac % TALER_AMOUNT_FRAC_BASE;
- sum_refund.value = sum_refund_frac / TALER_AMOUNT_FRAC_BASE
- + sum_refund_value;
- sum_refund.fraction = sum_refund_frac % TALER_AMOUNT_FRAC_BASE;
- sum_fee.value = sum_fee_frac / TALER_AMOUNT_FRAC_BASE
- + sum_fee_value;
- sum_fee.fraction = sum_fee_frac % TALER_AMOUNT_FRAC_BASE; \
- GNUNET_assert (0 <=
- TALER_amount_subtract (&delta,
- &sum_deposit,
- &sum_refund));
- GNUNET_assert (0 <=
- TALER_amount_subtract (total,
- &delta,
- &sum_fee));
- return qs;
-}
diff --git a/src/exchangedb/pg_batch_ensure_coin_known.c b/src/exchangedb/pg_batch_ensure_coin_known.c
@@ -1,457 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_batch_ensure_coin_known.c
- * @brief Implementation of the batch_ensure_coin_known function for Postgres
- * @author Christian Grothoff
- *
- * FIXME-#9373: use the array support for postgres to simplify this code!
- *
- */
-#include "taler/taler_exchangedb_lib.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/batch_ensure_coin_known.h"
-#include "helper.h"
-
-
-static enum GNUNET_DB_QueryStatus
-insert1 (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinPublicInfo coin[1],
- struct TALER_EXCHANGEDB_CoinInfo result[1])
-{
- enum GNUNET_DB_QueryStatus qs;
- bool is_denom_pub_hash_null = false;
- bool is_age_hash_null = false;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash),
- GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment),
- TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("existed",
- &result[0].existed),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id",
- &result[0].known_coin_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &result[0].denom_hash),
- &is_denom_pub_hash_null),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &result[0].h_age_commitment),
- &is_age_hash_null),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "batch1_known_coin",
- "SELECT"
- " existed1 AS existed"
- ",known_coin_id1 AS known_coin_id"
- ",denom_pub_hash1 AS denom_hash"
- ",age_commitment_hash1 AS h_age_commitment"
- " FROM exchange_do_batch1_known_coin"
- " ($1, $2, $3, $4);"
- );
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "batch1_known_coin",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return qs;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0); /* should be impossible */
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break; /* continued below */
- }
-
- if ( (! is_denom_pub_hash_null) &&
- (0 != GNUNET_memcmp (&result[0].denom_hash,
- &coin->denom_pub_hash)) )
- {
- GNUNET_break_op (0);
- result[0].denom_conflict = true;
- }
-
- if ( (! is_denom_pub_hash_null) &&
- (0 != GNUNET_memcmp (&result[0].denom_hash,
- &coin[0].denom_pub_hash)) )
- {
- GNUNET_break_op (0);
- result[0].denom_conflict = true;
- }
-
- result[0].age_conflict = TALER_AgeCommitmentHashP_NoConflict;
-
- if (is_age_hash_null != coin[0].no_age_commitment)
- {
- if (is_age_hash_null)
- {
- GNUNET_break_op (0);
- result[0].age_conflict = TALER_AgeCommitmentHashP_NullExpected;
- }
- else
- {
- GNUNET_break_op (0);
- result[0].age_conflict = TALER_AgeCommitmentHashP_ValueExpected;
- }
- }
- else if ( (! is_age_hash_null) &&
- (0 != GNUNET_memcmp (&result[0].h_age_commitment,
- &coin[0].h_age_commitment)) )
- {
- GNUNET_break_op (0);
- result[0].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers;
- }
-
- return qs;
-}
-
-
-static enum GNUNET_DB_QueryStatus
-insert2 (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinPublicInfo coin[2],
- struct TALER_EXCHANGEDB_CoinInfo result[2])
-{
- enum GNUNET_DB_QueryStatus qs;
- bool is_denom_pub_hash_null[2] = {false, false};
- bool is_age_hash_null[2] = {false, false};
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash),
- GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment),
- TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
-
- GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash),
- GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment),
- TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("existed",
- &result[0].existed),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id",
- &result[0].known_coin_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &result[0].denom_hash),
- &is_denom_pub_hash_null[0]),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &result[0].h_age_commitment),
- &is_age_hash_null[0]),
- GNUNET_PQ_result_spec_bool ("existed2",
- &result[1].existed),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id2",
- &result[1].known_coin_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2",
- &result[1].denom_hash),
- &is_denom_pub_hash_null[1]),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2",
- &result[1].h_age_commitment),
- &is_age_hash_null[1]),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "batch2_known_coin",
- "SELECT"
- " existed1 AS existed"
- ",known_coin_id1 AS known_coin_id"
- ",denom_pub_hash1 AS denom_hash"
- ",age_commitment_hash1 AS h_age_commitment"
- ",existed2 AS existed2"
- ",known_coin_id2 AS known_coin_id2"
- ",denom_pub_hash2 AS denom_hash2"
- ",age_commitment_hash2 AS h_age_commitment2"
- " FROM exchange_do_batch2_known_coin"
- " ($1, $2, $3, $4, $5, $6, $7, $8);"
- );
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "batch2_known_coin",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return qs;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0); /* should be impossible */
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break; /* continued below */
- }
-
- for (int i = 0; i < 2; i++)
- {
- if ( (! is_denom_pub_hash_null[i]) &&
- (0 != GNUNET_memcmp (&result[i].denom_hash,
- &coin[i].denom_pub_hash)) )
- {
- GNUNET_break_op (0);
- result[i].denom_conflict = true;
- }
-
- result[i].age_conflict = TALER_AgeCommitmentHashP_NoConflict;
-
- if (is_age_hash_null[i] != coin[i].no_age_commitment)
- {
- if (is_age_hash_null[i])
- {
- GNUNET_break_op (0);
- result[i].age_conflict = TALER_AgeCommitmentHashP_NullExpected;
- }
- else
- {
- GNUNET_break_op (0);
- result[i].age_conflict = TALER_AgeCommitmentHashP_ValueExpected;
- }
- }
- else if ( (! is_age_hash_null[i]) &&
- (0 != GNUNET_memcmp (&result[i].h_age_commitment,
- &coin[i].h_age_commitment)) )
- {
- GNUNET_break_op (0);
- result[i].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers;
- }
- }
-
- return qs;
-}
-
-
-static enum GNUNET_DB_QueryStatus
-insert4 (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinPublicInfo coin[4],
- struct TALER_EXCHANGEDB_CoinInfo result[4])
-{
- enum GNUNET_DB_QueryStatus qs;
- bool is_denom_pub_hash_null[4] = {false, false, false, false};
- bool is_age_hash_null[4] = {false, false, false, false};
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&coin[0].coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&coin[0].denom_pub_hash),
- GNUNET_PQ_query_param_auto_from_type (&coin[0].h_age_commitment),
- TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
-
- GNUNET_PQ_query_param_auto_from_type (&coin[1].coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&coin[1].denom_pub_hash),
- GNUNET_PQ_query_param_auto_from_type (&coin[1].h_age_commitment),
- TALER_PQ_query_param_denom_sig (&coin[0].denom_sig),
-
- GNUNET_PQ_query_param_auto_from_type (&coin[2].coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&coin[2].denom_pub_hash),
- GNUNET_PQ_query_param_auto_from_type (&coin[2].h_age_commitment),
- TALER_PQ_query_param_denom_sig (&coin[2].denom_sig),
-
- GNUNET_PQ_query_param_auto_from_type (&coin[3].coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&coin[3].denom_pub_hash),
- GNUNET_PQ_query_param_auto_from_type (&coin[3].h_age_commitment),
- TALER_PQ_query_param_denom_sig (&coin[3].denom_sig),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("existed",
- &result[0].existed),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id",
- &result[0].known_coin_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &result[0].denom_hash),
- &is_denom_pub_hash_null[0]),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &result[0].h_age_commitment),
- &is_age_hash_null[0]),
- GNUNET_PQ_result_spec_bool ("existed2",
- &result[1].existed),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id2",
- &result[1].known_coin_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash2",
- &result[1].denom_hash),
- &is_denom_pub_hash_null[1]),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash2",
- &result[1].h_age_commitment),
- &is_age_hash_null[1]),
- GNUNET_PQ_result_spec_bool ("existed3",
- &result[2].existed),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id3",
- &result[2].known_coin_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash3",
- &result[2].denom_hash),
- &is_denom_pub_hash_null[2]),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash3",
- &result[2].h_age_commitment),
- &is_age_hash_null[2]),
- GNUNET_PQ_result_spec_bool ("existed4",
- &result[3].existed),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id4",
- &result[3].known_coin_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash4",
- &result[3].denom_hash),
- &is_denom_pub_hash_null[3]),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash4",
- &result[3].h_age_commitment),
- &is_age_hash_null[3]),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "batch4_known_coin",
- "SELECT"
- " existed1 AS existed"
- ",known_coin_id1 AS known_coin_id"
- ",denom_pub_hash1 AS denom_hash"
- ",age_commitment_hash1 AS h_age_commitment"
- ",existed2 AS existed2"
- ",known_coin_id2 AS known_coin_id2"
- ",denom_pub_hash2 AS denom_hash2"
- ",age_commitment_hash2 AS h_age_commitment2"
- ",existed3 AS existed3"
- ",known_coin_id3 AS known_coin_id3"
- ",denom_pub_hash3 AS denom_hash3"
- ",age_commitment_hash3 AS h_age_commitment3"
- ",existed4 AS existed4"
- ",known_coin_id4 AS known_coin_id4"
- ",denom_pub_hash4 AS denom_hash4"
- ",age_commitment_hash4 AS h_age_commitment4"
- " FROM exchange_do_batch2_known_coin"
- " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);"
- );
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "batch4_known_coin",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return qs;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0); /* should be impossible */
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break; /* continued below */
- }
-
- for (int i = 0; i < 4; i++)
- {
- if ( (! is_denom_pub_hash_null[i]) &&
- (0 != GNUNET_memcmp (&result[i].denom_hash,
- &coin[i].denom_pub_hash)) )
- {
- GNUNET_break_op (0);
- result[i].denom_conflict = true;
- }
-
- result[i].age_conflict = TALER_AgeCommitmentHashP_NoConflict;
-
- if (is_age_hash_null[i] != coin[i].no_age_commitment)
- {
- if (is_age_hash_null[i])
- {
- GNUNET_break_op (0);
- result[i].age_conflict = TALER_AgeCommitmentHashP_NullExpected;
- }
- else
- {
- GNUNET_break_op (0);
- result[i].age_conflict = TALER_AgeCommitmentHashP_ValueExpected;
- }
- }
- else if ( (! is_age_hash_null[i]) &&
- (0 != GNUNET_memcmp (&result[i].h_age_commitment,
- &coin[i].h_age_commitment)) )
- {
- GNUNET_break_op (0);
- result[i].age_conflict = TALER_AgeCommitmentHashP_ValueDiffers;
- }
- }
-
- return qs;
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_batch_ensure_coin_known (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinPublicInfo *coin,
- struct TALER_EXCHANGEDB_CoinInfo *result,
- unsigned int coin_length,
- unsigned int batch_size)
-{
- enum GNUNET_DB_QueryStatus qs = 0;
- unsigned int i = 0;
-
- while ( (qs >= 0) &&
- (i < coin_length) )
- {
- unsigned int bs = GNUNET_MIN (batch_size,
- coin_length - i);
- if (bs >= 4)
- {
- qs = insert4 (pg,
- &coin[i],
- &result[i]);
- i += 4;
- continue;
- }
- switch (bs)
- {
- case 3:
- case 2:
- qs = insert2 (pg,
- &coin[i],
- &result[i]);
- i += 2;
- break;
- case 1:
- qs = insert1 (pg,
- &coin[i],
- &result[i]);
- i += 1;
- break;
- case 0:
- GNUNET_assert (0);
- break;
- }
- } /* end while */
- if (qs < 0)
- return qs;
- return i;
-}
diff --git a/src/exchangedb/pg_begin_revolving_shard.c b/src/exchangedb/pg_begin_revolving_shard.c
@@ -1,258 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_begin_revolving_shard.c
- * @brief Implementation of the begin_revolving_shard function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/begin_revolving_shard.h"
-#include "taler/exchange-database/commit.h"
-#include "helper.h"
-#include "taler/exchange-database/start.h"
-#include "taler/exchange-database/rollback.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_begin_revolving_shard (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- const char *job_name,
- uint32_t shard_size,
- uint32_t shard_limit,
- uint32_t *start_row,
- uint32_t *end_row)
-{
-
- GNUNET_assert (shard_limit <= 1U + (uint32_t) INT_MAX);
- GNUNET_assert (shard_limit > 0);
- GNUNET_assert (shard_size > 0);
- for (unsigned int retries = 0; retries<3; retries++)
- {
- if (GNUNET_OK !=
- TALER_EXCHANGEDB_start (pg,
- "begin_revolving_shard"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- /* First, find last 'end_row' */
- {
- enum GNUNET_DB_QueryStatus qs;
- uint32_t last_end;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint32 ("end_row",
- &last_end),
- GNUNET_PQ_result_spec_end
- };
- /* Used in #postgres_begin_revolving_shard() */
- PREPARE (pg,
- "get_last_revolving_shard",
- "SELECT"
- " end_row"
- " FROM revolving_work_shards"
- " WHERE job_name=$1"
- " ORDER BY end_row DESC"
- " LIMIT 1;");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_last_revolving_shard",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- *start_row = 1U + last_end;
- break;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- *start_row = 0; /* base-case: no shards yet */
- break; /* continued below */
- }
- } /* get_last_shard */
-
- if (*start_row < shard_limit)
- {
- /* Claim fresh shard */
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_TIME_Absolute now;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_uint32 (start_row),
- GNUNET_PQ_query_param_uint32 (end_row),
- GNUNET_PQ_query_param_end
- };
-
- *end_row = GNUNET_MIN (shard_limit,
- *start_row + shard_size - 1);
- now = GNUNET_TIME_absolute_get ();
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Trying to claim shard %llu-%llu\n",
- (unsigned long long) *start_row,
- (unsigned long long) *end_row);
-
- /* Used in #postgres_claim_revolving_shard() */
- PREPARE (pg,
- "create_revolving_shard",
- "INSERT INTO revolving_work_shards"
- "(job_name"
- ",last_attempt"
- ",start_row"
- ",end_row"
- ",active"
- ") VALUES "
- "($1, $2, $3, $4, TRUE);");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "create_revolving_shard",
- params);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* continued below (with commit) */
- break;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* someone else got this shard already,
- try again */
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- }
- } /* end create fresh reovlving shard */
- else
- {
- /* claim oldest existing shard */
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint32 ("start_row",
- start_row),
- GNUNET_PQ_result_spec_uint32 ("end_row",
- end_row),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_open_revolving_shard",
- "SELECT"
- " start_row"
- ",end_row"
- " FROM revolving_work_shards"
- " WHERE job_name=$1"
- " AND active=FALSE"
- " ORDER BY last_attempt ASC"
- " LIMIT 1;");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_open_revolving_shard",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* no open shards available */
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- {
- enum GNUNET_DB_QueryStatus qsz;
- struct GNUNET_TIME_Timestamp now;
- struct GNUNET_PQ_QueryParam iparams[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_timestamp (&now),
- GNUNET_PQ_query_param_uint32 (start_row),
- GNUNET_PQ_query_param_uint32 (end_row),
- GNUNET_PQ_query_param_end
- };
-
- now = GNUNET_TIME_timestamp_get ();
- PREPARE (pg,
- "reclaim_revolving_shard",
- "UPDATE revolving_work_shards"
- " SET last_attempt=$2"
- " ,active=TRUE"
- " WHERE job_name=$1"
- " AND start_row=$3"
- " AND end_row=$4");
- qsz = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "reclaim_revolving_shard",
- iparams);
- switch (qsz)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break; /* continue with commit */
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0); /* logic error, should be impossible */
- TALER_EXCHANGEDB_rollback (pg);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
- break; /* continue with commit */
- }
- } /* end claim oldest existing shard */
-
- /* commit */
- {
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TALER_EXCHANGEDB_commit (pg);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
- }
- } /* retry 'for' loop */
- return GNUNET_DB_STATUS_SOFT_ERROR;
-}
diff --git a/src/exchangedb/pg_begin_shard.c b/src/exchangedb/pg_begin_shard.c
@@ -1,262 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_begin_shard.c
- * @brief Implementation of the begin_shard function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/begin_shard.h"
-#include "helper.h"
-#include "taler/exchange-database/start.h"
-#include "taler/exchange-database/rollback.h"
-#include "taler/exchange-database/commit.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_begin_shard (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *job_name,
- struct GNUNET_TIME_Relative delay,
- uint64_t shard_size,
- uint64_t *start_row,
- uint64_t *end_row)
-{
-
- for (unsigned int retries = 0; retries<10; retries++)
- {
- if (GNUNET_OK !=
- TALER_EXCHANGEDB_start (pg,
- "begin_shard"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- {
- struct GNUNET_TIME_Absolute past;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_absolute_time (&past),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("start_row",
- start_row),
- GNUNET_PQ_result_spec_uint64 ("end_row",
- end_row),
- GNUNET_PQ_result_spec_end
- };
-
- past = GNUNET_TIME_absolute_get ();
- PREPARE (pg,
- "get_open_shard",
- "SELECT"
- " start_row"
- ",end_row"
- " FROM work_shards"
- " WHERE job_name=$1"
- " AND completed=FALSE"
- " AND last_attempt<$2"
- " ORDER BY last_attempt ASC"
- " LIMIT 1;");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_open_shard",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Serialization error on getting open shard\n");
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- {
- enum GNUNET_DB_QueryStatus qsz;
- struct GNUNET_TIME_Absolute now;
- struct GNUNET_PQ_QueryParam iparams[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_uint64 (start_row),
- GNUNET_PQ_query_param_uint64 (end_row),
- GNUNET_PQ_query_param_end
- };
-
- now = GNUNET_TIME_relative_to_absolute (delay);
- PREPARE (pg,
- "reclaim_shard",
- "UPDATE work_shards"
- " SET last_attempt=$2"
- " WHERE job_name=$1"
- " AND start_row=$3"
- " AND end_row=$4");
- qsz = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "reclaim_shard",
- iparams);
- switch (qsz)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qsz;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Serialization error on claiming open shard\n");
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- goto commit;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0); /* logic error, should be impossible */
- TALER_EXCHANGEDB_rollback (pg);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
- break; /* actually unreachable */
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- break; /* continued below */
- }
- } /* get_open_shard */
-
- /* No open shard, find last 'end_row' */
- {
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("end_row",
- start_row),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_last_shard",
- "SELECT"
- " end_row"
- " FROM work_shards"
- " WHERE job_name=$1"
- " ORDER BY end_row DESC"
- " LIMIT 1;");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_last_shard",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Serialization error on getting last shard\n");
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- *start_row = 0; /* base-case: no shards yet */
- break; /* continued below */
- }
- *end_row = *start_row + shard_size;
- } /* get_last_shard */
-
- /* Claim fresh shard */
- {
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_TIME_Absolute now;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_uint64 (start_row),
- GNUNET_PQ_query_param_uint64 (end_row),
- GNUNET_PQ_query_param_end
- };
-
- now = GNUNET_TIME_relative_to_absolute (delay);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Trying to claim shard (%llu-%llu]\n",
- (unsigned long long) *start_row,
- (unsigned long long) *end_row);
-
- PREPARE (pg,
- "claim_next_shard",
- "INSERT INTO work_shards"
- "(job_name"
- ",last_attempt"
- ",start_row"
- ",end_row"
- ") VALUES "
- "($1, $2, $3, $4);");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "claim_next_shard",
- params);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Serialization error on claiming next shard\n");
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* continued below */
- break;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* someone else got this shard already,
- try again */
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- }
- } /* claim_next_shard */
-
- /* commit */
-commit:
- {
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TALER_EXCHANGEDB_commit (pg);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Serialization error on commit for beginning shard\n");
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Claimed new shard\n");
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
- }
- } /* retry 'for' loop */
- return GNUNET_DB_STATUS_SOFT_ERROR;
-}
diff --git a/src/exchangedb/pg_clear_aml_lock.c b/src/exchangedb/pg_clear_aml_lock.c
@@ -1,45 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_clear_aml_lock.c
- * @brief Implementation of the clear_aml_lock function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/clear_aml_lock.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_clear_aml_lock (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
-
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "clear_aml_lock",
- "UPDATE kyc_targets"
- " SET aml_program_lock_timeout=NULL"
- " WHERE h_normalized_payto=$1");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "clear_aml_lock",
- params);
-}
diff --git a/src/exchangedb/pg_commit.c b/src/exchangedb/pg_commit.c
@@ -1,52 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_commit.c
- * @brief Implementation of the commit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/commit.h"
-#include "helper.h"
-
-
-/**
- * Commit the current transaction of a database connection.
- *
- * @param pg the database context
- * @return final transaction status
- */
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_commit (struct TALER_EXCHANGEDB_PostgresContext *pg)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- GNUNET_break (NULL != pg->transaction_name);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Committing transaction `%s'\n",
- pg->transaction_name);
- PREPARE (pg,
- "do_commit",
- "COMMIT");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "do_commit",
- params);
- pg->transaction_name = NULL;
- return qs;
-}
diff --git a/src/exchangedb/pg_complete_shard.c b/src/exchangedb/pg_complete_shard.c
@@ -1,52 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_complete_shard.c
- * @brief Implementation of the complete_shard function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/complete_shard.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_complete_shard (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *job_name,
- uint64_t start_row,
- uint64_t end_row)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_uint64 (&start_row),
- GNUNET_PQ_query_param_uint64 (&end_row),
- GNUNET_PQ_query_param_end
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Completing shard %llu-%llu\n",
- (unsigned long long) start_row,
- (unsigned long long) end_row);
- PREPARE (pg,
- "complete_shard",
- "UPDATE work_shards"
- " SET completed=TRUE"
- " WHERE job_name=$1"
- " AND start_row=$2"
- " AND end_row=$3");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "complete_shard",
- params);
-}
diff --git a/src/exchangedb/pg_compute_shard.c b/src/exchangedb/pg_compute_shard.c
@@ -1,46 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_compute_shard.c
- * @brief Implementation of the compute_shard function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/exchange-database/compute_shard.h"
-#include "helper.h"
-
-
-uint64_t
-TALER_EXCHANGEDB_compute_shard (const struct TALER_MerchantPublicKeyP *
- merchant_pub)
-{
- uint32_t res;
-
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CRYPTO_hkdf_gnunet (
- &res,
- sizeof (res),
- merchant_pub,
- sizeof (*merchant_pub),
- "VOID",
- 4));
- /* interpret hash result as NBO for platform independence,
- convert to HBO and map to [0..2^31-1] range */
- res = ntohl (res);
- if (res > INT32_MAX)
- res += INT32_MIN;
- GNUNET_assert (res <= INT32_MAX);
- return (uint64_t) res;
-}
diff --git a/src/exchangedb/pg_count_known_coins.c b/src/exchangedb/pg_count_known_coins.c
@@ -1,59 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_count_known_coins.c
- * @brief Implementation of the count_known_coins function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/count_known_coins.h"
-#include "helper.h"
-
-long long
-TALER_EXCHANGEDB_count_known_coins (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct
- TALER_DenominationHashP *denom_pub_hash)
-{
- uint64_t count;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("count",
- &count),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
-
- PREPARE (pg,
- "count_known_coins",
- "SELECT"
- " COUNT(*) AS count"
- " FROM known_coins"
- " WHERE denominations_serial="
- " (SELECT denominations_serial"
- " FROM denominations"
- " WHERE denom_pub_hash=$1);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "count_known_coins",
- params,
- rs);
- if (0 > qs)
- return (long long) qs;
- return (long long) count;
-}
diff --git a/src/exchangedb/pg_create_aggregation_transient.c b/src/exchangedb/pg_create_aggregation_transient.c
@@ -1,61 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_create_aggregation_transient.c
- * @brief Implementation of the create_aggregation_transient function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/create_aggregation_transient.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_create_aggregation_transient (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPaytoHashP *h_payto,
- const char *exchange_account_section,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- uint64_t kyc_requirement_row,
- const struct TALER_Amount *total)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- TALER_PQ_query_param_amount (pg->conn,
- total),
- GNUNET_PQ_query_param_auto_from_type (merchant_pub),
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
- GNUNET_PQ_query_param_string (exchange_account_section),
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "create_aggregation_transient",
- "INSERT INTO aggregation_transient"
- " (amount"
- " ,merchant_pub"
- " ,wire_target_h_payto"
- " ,legitimization_requirement_serial_id"
- " ,exchange_account_section"
- " ,wtid_raw)"
- " VALUES ($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "create_aggregation_transient",
- params);
-}
diff --git a/src/exchangedb/pg_create_tables.c b/src/exchangedb/pg_create_tables.c
@@ -1,78 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_create_tables.c
- * @brief Implementation of the create_tables function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/create_tables.h"
-#include "helper.h"
-
-
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGEDB_create_tables (struct TALER_EXCHANGEDB_PostgresContext *pg,
- bool support_partitions,
- uint32_t num_partitions)
-{
- struct GNUNET_PQ_Context *conn;
- enum GNUNET_GenericReturnValue ret;
- struct GNUNET_PQ_QueryParam params[] = {
- support_partitions
- ? GNUNET_PQ_query_param_uint32 (&num_partitions)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
- "exchangedb-postgres",
- "exchange-",
- es,
- NULL);
- if (NULL == conn)
- return GNUNET_SYSERR;
- ret = GNUNET_PQ_exec_sql (conn,
- "procedures");
- GNUNET_break (GNUNET_OK == ret);
- if (GNUNET_OK == ret)
- {
- struct GNUNET_PQ_Context *tconn;
-
- tconn = pg->conn;
- pg->prep_gen++;
- pg->conn = conn;
- PREPARE (pg,
- "create_tables",
- "SELECT"
- " exchange_do_create_tables"
- " ($1::INTEGER);");
- pg->conn = tconn;
- if (0 >
- GNUNET_PQ_eval_prepared_non_select (conn,
- "create_tables",
- params))
- {
- GNUNET_break (0);
- ret = GNUNET_SYSERR;
- }
- }
- GNUNET_PQ_disconnect (conn);
- return ret;
-}
diff --git a/src/exchangedb/pg_delete_aggregation_transient.c b/src/exchangedb/pg_delete_aggregation_transient.c
@@ -1,46 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_delete_aggregation_transient.c
- * @brief Implementation of the delete_aggregation_transient function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/delete_aggregation_transient.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_delete_aggregation_transient (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPaytoHashP *h_payto,
- const struct TALER_WireTransferIdentifierRawP *wtid)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "delete_aggregation_transient",
- "DELETE FROM aggregation_transient"
- " WHERE wire_target_h_payto=$1"
- " AND wtid_raw=$2");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "delete_aggregation_transient",
- params);
-}
diff --git a/src/exchangedb/pg_delete_shard_locks.c b/src/exchangedb/pg_delete_shard_locks.c
@@ -1,37 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_delete_shard_locks.c
- * @brief Implementation of the delete_shard_locks function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/exchange-database/delete_shard_locks.h"
-#include "helper.h"
-
-
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGEDB_delete_shard_locks (struct TALER_EXCHANGEDB_PostgresContext *pg
- )
-{
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("DELETE FROM work_shards;"),
- GNUNET_PQ_make_execute ("DELETE FROM revolving_work_shards;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- return GNUNET_PQ_exec_statements (pg->conn,
- es);
-}
diff --git a/src/exchangedb/pg_disable_rules.c b/src/exchangedb/pg_disable_rules.c
@@ -1,57 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_disable_rules.c
- * @brief Implementation of the disable_rules function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/disable_rules.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_disable_rules (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *schema)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (schema),
- GNUNET_PQ_query_param_end
- };
- bool found;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("out_found",
- &found),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "call_exchange_drop_customization",
- "SELECT out_found"
- " FROM exchange_drop_customization"
- " ($1);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_exchange_drop_customization",
- params,
- rs);
- if (qs < 0)
- return qs;
- if (found)
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-}
diff --git a/src/exchangedb/pg_do_check_deposit_idempotent.c b/src/exchangedb/pg_do_check_deposit_idempotent.c
@@ -1,109 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_deposit.c
- * @brief Implementation of the do_deposit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_check_deposit_idempotent.h"
-#include "helper.h"
-#include "taler/exchange-database/compute_shard.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_check_deposit_idempotent (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_BatchDeposit *bd,
- struct GNUNET_TIME_Timestamp *exchange_timestamp,
- bool *is_idempotent)
-{
- uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&bd->merchant_pub);
- const struct TALER_CoinSpendPublicKeyP *coin_pubs[GNUNET_NZL (bd->num_cdis)];
- const struct TALER_CoinSpendSignatureP *coin_sigs[GNUNET_NZL (bd->num_cdis)];
- struct TALER_Amount amounts_with_fee[GNUNET_NZL (bd->num_cdis)];
- struct TALER_NormalizedPaytoHashP h_normalized_payto;
- struct GNUNET_PQ_QueryParam params[] = {
- /* data for batch_deposits */
- GNUNET_PQ_query_param_uint64 (&deposit_shard),
- GNUNET_PQ_query_param_auto_from_type (&bd->merchant_pub),
- GNUNET_PQ_query_param_timestamp (&bd->wallet_timestamp),
- GNUNET_PQ_query_param_timestamp (exchange_timestamp),
- GNUNET_PQ_query_param_timestamp (&bd->refund_deadline),
- GNUNET_PQ_query_param_timestamp (&bd->wire_deadline),
- GNUNET_PQ_query_param_auto_from_type (&bd->h_contract_terms),
- (bd->no_wallet_data_hash)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (&bd->wallet_data_hash),
- GNUNET_PQ_query_param_auto_from_type (&bd->wire_salt),
- GNUNET_PQ_query_param_auto_from_type (&bd->wire_target_h_payto),
- (0 == bd->policy_details_serial_id)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (&bd->policy_details_serial_id),
- GNUNET_PQ_query_param_bool (bd->policy_blocked),
- /* arrays for coin_deposits */
- GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
- coin_pubs,
- pg->conn),
- GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
- coin_sigs,
- pg->conn),
- TALER_PQ_query_param_array_amount (bd->num_cdis,
- amounts_with_fee,
- pg->conn),
- GNUNET_PQ_query_param_end
- };
- bool no_time;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
- exchange_timestamp),
- &no_time),
- GNUNET_PQ_result_spec_bool ("is_idempotent",
- is_idempotent),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- TALER_full_payto_normalize_and_hash (bd->receiver_wire_account,
- &h_normalized_payto);
- for (unsigned int i = 0; i < bd->num_cdis; i++)
- {
- const struct TALER_EXCHANGEDB_CoinDepositInformation *cdi
- = &bd->cdis[i];
-
- amounts_with_fee[i] = cdi->amount_with_fee;
- coin_pubs[i] = &cdi->coin.coin_pub;
- coin_sigs[i] = &cdi->csig;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Do deposit %u = %s\n",
- i,
- TALER_B2S (&cdi->coin.coin_pub));
- }
- PREPARE (pg,
- "call_check_deposit_idempotent",
- "SELECT "
- " out_exchange_timestamp AS exchange_timestamp"
- ",out_is_idempotent AS is_idempotent"
- " FROM exchange_do_check_deposit_idempotent"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_check_deposit_idempotent",
- params,
- rs);
- GNUNET_PQ_cleanup_query_params_closures (params);
- return qs;
-}
diff --git a/src/exchangedb/pg_do_deposit.c b/src/exchangedb/pg_do_deposit.c
@@ -1,171 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-2026 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_deposit.c
- * @brief Implementation of the do_deposit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_deposit.h"
-#include "helper.h"
-#include "taler/exchange-database/compute_shard.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_deposit (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_BatchDeposit *bd,
- const struct TALER_Amount deposit_fees[],
- struct GNUNET_TIME_Timestamp *exchange_timestamp,
- struct TALER_Amount *accumulated_total_without_fee,
- bool *balance_ok,
- uint32_t *bad_balance_index,
- bool *ctr_conflict)
-{
- uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&bd->merchant_pub);
- const struct TALER_CoinSpendPublicKeyP *coin_pubs[GNUNET_NZL (bd->num_cdis)];
- const struct TALER_CoinSpendSignatureP *coin_sigs[GNUNET_NZL (bd->num_cdis)];
- struct TALER_Amount amounts_with_fee[GNUNET_NZL (bd->num_cdis)];
- struct TALER_Amount total_amount;
- struct TALER_Amount total_without_fee;
- struct TALER_NormalizedPaytoHashP h_normalized_payto;
- struct GNUNET_PQ_QueryParam params[] = {
- /* data for batch_deposits */
- GNUNET_PQ_query_param_uint64 (&deposit_shard),
- GNUNET_PQ_query_param_auto_from_type (&bd->merchant_pub),
- GNUNET_PQ_query_param_auto_from_type (&bd->merchant_sig),
- GNUNET_PQ_query_param_timestamp (&bd->wallet_timestamp),
- GNUNET_PQ_query_param_timestamp (exchange_timestamp),
- GNUNET_PQ_query_param_timestamp (&bd->refund_deadline),
- GNUNET_PQ_query_param_timestamp (&bd->wire_deadline),
- GNUNET_PQ_query_param_auto_from_type (&bd->h_contract_terms),
- (bd->no_wallet_data_hash)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (&bd->wallet_data_hash),
- GNUNET_PQ_query_param_auto_from_type (&bd->wire_salt),
- GNUNET_PQ_query_param_auto_from_type (&bd->wire_target_h_payto),
- GNUNET_PQ_query_param_auto_from_type (&h_normalized_payto),
- (0 == bd->policy_details_serial_id)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (&bd->policy_details_serial_id),
- GNUNET_PQ_query_param_bool (bd->policy_blocked),
- /* to create entry in wire_targets */
- GNUNET_PQ_query_param_string (bd->receiver_wire_account.full_payto),
- /* arrays for coin_deposits */
- GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
- coin_pubs,
- pg->conn),
- GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
- coin_sigs,
- pg->conn),
- TALER_PQ_query_param_array_amount (bd->num_cdis,
- amounts_with_fee,
- pg->conn),
- TALER_PQ_query_param_array_amount (bd->num_cdis,
- deposit_fees,
- pg->conn),
- TALER_PQ_query_param_amount (pg->conn,
- &total_amount),
- TALER_PQ_query_param_amount (pg->conn,
- &total_without_fee),
- GNUNET_PQ_query_param_bool (TALER_payto_is_wallet (
- bd->receiver_wire_account.full_payto)),
- NULL == bd->extra_wire_subject_metadata
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (bd->extra_wire_subject_metadata),
- GNUNET_PQ_query_param_end
- };
- bool no_time;
- bool no_amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
- exchange_timestamp),
- &no_time),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total_without_fee",
- accumulated_total_without_fee),
- &no_amount),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint32 ("insufficient_balance_coin_index",
- bad_balance_index),
- balance_ok),
- GNUNET_PQ_result_spec_bool ("conflicted",
- ctr_conflict),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- GNUNET_assert (0 < bd->num_cdis);
- TALER_full_payto_normalize_and_hash (bd->receiver_wire_account,
- &h_normalized_payto);
- for (unsigned int i = 0; i < bd->num_cdis; i++)
- {
- const struct TALER_EXCHANGEDB_CoinDepositInformation *cdi
- = &bd->cdis[i];
-
- if (0 == i)
- {
- total_amount = cdi->amount_with_fee;
- total_without_fee = cdi->amount_with_fee;
- }
- else
- {
- GNUNET_assert (0 <=
- TALER_amount_add (&total_amount,
- &total_amount,
- &cdi->amount_with_fee));
- GNUNET_assert (0 <=
- TALER_amount_add (&total_without_fee,
- &total_without_fee,
- &cdi->amount_with_fee));
- }
- GNUNET_assert (0 <=
- TALER_amount_subtract (
- &total_without_fee,
- &total_without_fee,
- &deposit_fees[i]));
-
- amounts_with_fee[i] = cdi->amount_with_fee;
- coin_pubs[i] = &cdi->coin.coin_pub;
- coin_sigs[i] = &cdi->csig;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Do deposit %u = %s\n",
- i,
- TALER_B2S (&cdi->coin.coin_pub));
- }
- PREPARE (pg,
- "call_deposit",
- "SELECT "
- " out_exchange_timestamp AS exchange_timestamp"
- ",out_accumulated_total_without_fee AS accumulated_total_without_fee"
- ",out_insufficient_balance_coin_index AS insufficient_balance_coin_index"
- ",out_conflict AS conflicted"
- " FROM exchange_do_deposit"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10"
- ",$11,$12,$13,$14,$15,$16,$17,$18,$19,$20"
- ",$21,$22,$23);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_deposit",
- params,
- rs);
- GNUNET_PQ_cleanup_query_params_closures (params);
- if (no_amount)
- memset (accumulated_total_without_fee,
- 0,
- sizeof (struct TALER_Amount));
- return qs;
-}
diff --git a/src/exchangedb/pg_do_purse_delete.c b/src/exchangedb/pg_do_purse_delete.c
@@ -1,60 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_purse_delete.c
- * @brief Implementation of the do_purse_delete function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_purse_delete.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_purse_delete (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- const struct TALER_PurseContractSignatureP *purse_sig,
- bool *decided,
- bool *found)
-{
- struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_auto_from_type (purse_sig),
- GNUNET_PQ_query_param_timestamp (&now),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("decided",
- decided),
- GNUNET_PQ_result_spec_bool ("found",
- found),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "call_purse_delete",
- "SELECT "
- " out_decided AS decided"
- ",out_found AS found"
- " FROM exchange_do_purse_delete"
- " ($1,$2,$3);");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_purse_delete",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_do_purse_deposit.c b/src/exchangedb/pg_do_purse_deposit.c
@@ -1,86 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_purse_deposit.c
- * @brief Implementation of the do_purse_deposit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_purse_deposit.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_purse_deposit (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_Amount *amount,
- const struct TALER_CoinSpendSignatureP *coin_sig,
- const struct TALER_Amount *amount_minus_fee,
- bool *balance_ok,
- bool *too_late,
- bool *conflict)
-{
- struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
- struct GNUNET_TIME_Timestamp reserve_expiration;
- uint64_t partner_id = 0; /* FIXME #7271: WAD support... */
- struct GNUNET_PQ_QueryParam params[] = {
- (0 == partner_id)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (&partner_id),
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- TALER_PQ_query_param_amount (
- pg->conn,
- amount),
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_auto_from_type (coin_sig),
- TALER_PQ_query_param_amount (
- pg->conn,
- amount_minus_fee),
- GNUNET_PQ_query_param_timestamp (&reserve_expiration),
- GNUNET_PQ_query_param_timestamp (&now),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("balance_ok",
- balance_ok),
- GNUNET_PQ_result_spec_bool ("too_late",
- too_late),
- GNUNET_PQ_result_spec_bool ("conflict",
- conflict),
- GNUNET_PQ_result_spec_end
- };
-
- reserve_expiration
- = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
- pg->legal_reserve_expiration_time));
-
- PREPARE (pg,
- "call_purse_deposit",
- "SELECT "
- " out_balance_ok AS balance_ok"
- ",out_conflict AS conflict"
- ",out_late AS too_late"
- " FROM exchange_do_purse_deposit"
- " ($1,$2,$3,$4,$5,$6,$7,$8);");
-
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_purse_deposit",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_do_purse_merge.c b/src/exchangedb/pg_do_purse_merge.c
@@ -1,87 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_purse_merge.c
- * @brief Implementation of the do_purse_merge function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_purse_merge.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_purse_merge (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- const struct TALER_PurseMergeSignatureP *merge_sig,
- const struct GNUNET_TIME_Timestamp merge_timestamp,
- const struct TALER_ReserveSignatureP *reserve_sig,
- const char *partner_url,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- bool *no_partner,
- bool *no_balance,
- bool *in_conflict)
-{
- struct TALER_NormalizedPaytoHashP h_payto;
- struct GNUNET_TIME_Timestamp expiration
- = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_auto_from_type (merge_sig),
- GNUNET_PQ_query_param_timestamp (&merge_timestamp),
- GNUNET_PQ_query_param_auto_from_type (reserve_sig),
- (NULL == partner_url)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (partner_url),
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_timestamp (&expiration),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("no_partner",
- no_partner),
- GNUNET_PQ_result_spec_bool ("no_balance",
- no_balance),
- GNUNET_PQ_result_spec_bool ("conflict",
- in_conflict),
- GNUNET_PQ_result_spec_end
- };
-
- {
- struct TALER_NormalizedPayto payto_uri;
-
- payto_uri = TALER_reserve_make_payto (pg->exchange_url,
- reserve_pub);
- TALER_normalized_payto_hash (payto_uri,
- &h_payto);
- GNUNET_free (payto_uri.normalized_payto);
- }
- PREPARE (pg,
- "call_purse_merge",
- "SELECT"
- " out_no_partner AS no_partner"
- ",out_no_balance AS no_balance"
- ",out_conflict AS conflict"
- " FROM exchange_do_purse_merge"
- " ($1, $2, $3, $4, $5, $6, $7, $8);");
-
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_purse_merge",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_do_recoup.c b/src/exchangedb/pg_do_recoup.c
@@ -1,81 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_recoup.c
- * @brief Implementation of the do_recoup function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_recoup.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_recoup (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- uint64_t withdraw_id,
- const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- uint64_t known_coin_id,
- const struct TALER_CoinSpendSignatureP *coin_sig,
- struct GNUNET_TIME_Timestamp *recoup_timestamp,
- bool *recoup_ok,
- bool *internal_failure)
-{
- struct GNUNET_TIME_Timestamp reserve_gc
- = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
- struct GNUNET_TIME_Timestamp reserve_expiration
- = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_uint64 (&withdraw_id),
- GNUNET_PQ_query_param_auto_from_type (coin_bks),
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_uint64 (&known_coin_id),
- GNUNET_PQ_query_param_auto_from_type (coin_sig),
- GNUNET_PQ_query_param_timestamp (&reserve_gc),
- GNUNET_PQ_query_param_timestamp (&reserve_expiration),
- GNUNET_PQ_query_param_timestamp (recoup_timestamp),
- GNUNET_PQ_query_param_end
- };
- bool is_null;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- recoup_timestamp),
- &is_null),
- GNUNET_PQ_result_spec_bool ("recoup_ok",
- recoup_ok),
- GNUNET_PQ_result_spec_bool ("internal_failure",
- internal_failure),
- GNUNET_PQ_result_spec_end
- };
-
-
- PREPARE (pg,
- "call_recoup",
- "SELECT "
- " out_recoup_timestamp AS recoup_timestamp"
- ",out_recoup_ok AS recoup_ok"
- ",out_internal_failure AS internal_failure"
- " FROM exchange_do_recoup_to_reserve"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_recoup",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_do_recoup_refresh.c b/src/exchangedb/pg_do_recoup_refresh.c
@@ -1,76 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_recoup_refresh.c
- * @brief Implementation of the do_recoup_refresh function for Postgres
- * @author Christian Grothoff
- * @author Özgür Kesim
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_recoup_refresh.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_do_recoup_refresh (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
- uint64_t refresh_id,
- const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- uint64_t known_coin_id,
- const struct TALER_CoinSpendSignatureP *coin_sig,
- struct GNUNET_TIME_Timestamp *recoup_timestamp,
- bool *recoup_ok,
- bool *internal_failure)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (old_coin_pub),
- GNUNET_PQ_query_param_uint64 (&refresh_id),
- GNUNET_PQ_query_param_auto_from_type (coin_bks),
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_uint64 (&known_coin_id),
- GNUNET_PQ_query_param_auto_from_type (coin_sig),
- GNUNET_PQ_query_param_timestamp (recoup_timestamp),
- GNUNET_PQ_query_param_end
- };
- bool is_null;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- recoup_timestamp),
- &is_null),
- GNUNET_PQ_result_spec_bool ("recoup_ok",
- recoup_ok),
- GNUNET_PQ_result_spec_bool ("internal_failure",
- internal_failure),
- GNUNET_PQ_result_spec_end
- };
-
-
- PREPARE (pg,
- "call_recoup_refresh",
- "SELECT "
- " out_recoup_timestamp AS recoup_timestamp"
- ",out_recoup_ok AS recoup_ok"
- ",out_internal_failure AS internal_failure"
- " FROM exchange_do_recoup_to_coin"
- " ($1,$2,$3,$4,$5,$6,$7);");
-
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_recoup_refresh",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_do_refresh.c b/src/exchangedb/pg_do_refresh.c
@@ -1,138 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_refresh.c
- * @brief Implementation of the do_refresh function for Postgres
- * @author Özgür Kesim
- */
-#include "taler/taler_exchangedb_lib.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_refresh.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_refresh (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh,
- const struct GNUNET_TIME_Timestamp *timestamp,
- bool *found,
- uint32_t *noreveal_index,
- bool *zombie_required,
- bool *nonce_reuse,
- bool *balance_ok,
- struct TALER_Amount *coin_balance)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
- GNUNET_PQ_query_param_timestamp (timestamp),
- GNUNET_PQ_query_param_auto_from_type (&refresh->refresh_seed), /* 3 */
- (refresh->is_v27_refresh)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_array_auto_from_type (refresh->num_coins,
- refresh->transfer_pubs,
- pg->conn),
- GNUNET_PQ_query_param_auto_from_type (&refresh->planchets_h),
- TALER_PQ_query_param_amount (pg->conn, /* 6 */
- &refresh->amount_with_fee),
- (refresh->no_blinding_seed)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (&refresh->blinding_seed),
- (0 < refresh->num_cs_r_values)
- ? TALER_PQ_query_param_array_cs_r_pub (refresh->num_cs_r_values,
- refresh->cs_r_values,
- pg->conn)
- : GNUNET_PQ_query_param_null (),
- (0 < refresh->num_cs_r_values)
- ? GNUNET_PQ_query_param_uint64 (&refresh->cs_r_choices) /* 9 */
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_auto_from_type (&refresh->selected_h),
- TALER_PQ_query_param_array_blinded_denom_sig (refresh->num_coins,
- refresh->denom_sigs,
- pg->conn),
- GNUNET_PQ_query_param_array_uint64 (refresh->num_coins, /* 12 */
- refresh->denom_serials,
- pg->conn),
- GNUNET_PQ_query_param_auto_from_type (&refresh->coin.coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&refresh->coin_sig),
- GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index), /* 15 */
- GNUNET_PQ_query_param_bool (*zombie_required),
- GNUNET_PQ_query_param_end
- };
- bool coin_found;
- bool no_noreveal_index;
- bool no_coin_balance;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("coin_found",
- &coin_found),
- GNUNET_PQ_result_spec_bool ("balance_ok",
- balance_ok),
- GNUNET_PQ_result_spec_bool ("zombie_required",
- zombie_required),
- GNUNET_PQ_result_spec_bool ("nonce_reuse",
- nonce_reuse),
- GNUNET_PQ_result_spec_bool ("found",
- found),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint32 ("noreveal_index",
- noreveal_index),
- &no_noreveal_index),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_RESULT_SPEC_AMOUNT ("coin_balance",
- coin_balance),
- &no_coin_balance),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "call_refresh",
- "SELECT "
- " out_coin_found AS coin_found"
- ",out_balance_ok AS balance_ok"
- ",out_zombie_bad AS zombie_required"
- ",out_nonce_reuse AS nonce_reuse"
- ",out_idempotent AS found"
- ",out_noreveal_index AS noreveal_index"
- ",out_coin_balance AS coin_balance"
- " FROM exchange_do_refresh"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_refresh",
- params,
- rs);
- GNUNET_PQ_cleanup_query_params_closures (params);
- if (0 > qs)
- {
- GNUNET_break (0);
- return qs;
- }
- if (! coin_found)
- {
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- }
- if (*found && no_noreveal_index)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (! balance_ok && no_coin_balance)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_do_refund.c b/src/exchangedb/pg_do_refund.c
@@ -1,91 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_refund.c
- * @brief Implementation of the do_refund function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_refund.h"
-#include "helper.h"
-#include "taler/exchange-database/compute_shard.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_refund (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_Refund *refund,
- const struct TALER_Amount *deposit_fee,
- uint64_t known_coin_id,
- bool *not_found,
- bool *refund_ok,
- bool *gone,
- bool *conflict)
-{
- uint64_t deposit_shard = TALER_EXCHANGEDB_compute_shard (&refund->details.
- merchant_pub);
- struct TALER_Amount amount_without_fee;
- struct GNUNET_PQ_QueryParam params[] = {
- TALER_PQ_query_param_amount (pg->conn,
- &refund->details.refund_amount),
- TALER_PQ_query_param_amount (pg->conn,
- &amount_without_fee),
- TALER_PQ_query_param_amount (pg->conn,
- deposit_fee),
- GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
- GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
- GNUNET_PQ_query_param_uint64 (&deposit_shard),
- GNUNET_PQ_query_param_uint64 (&known_coin_id),
- GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
- GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("not_found",
- not_found),
- GNUNET_PQ_result_spec_bool ("refund_ok",
- refund_ok),
- GNUNET_PQ_result_spec_bool ("gone",
- gone),
- GNUNET_PQ_result_spec_bool ("conflict",
- conflict),
- GNUNET_PQ_result_spec_end
- };
-
- if (0 >
- TALER_amount_subtract (&amount_without_fee,
- &refund->details.refund_amount,
- &refund->details.refund_fee))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- PREPARE (pg,
- "call_refund",
- "SELECT "
- " out_not_found AS not_found"
- ",out_refund_ok AS refund_ok"
- ",out_gone AS gone"
- ",out_conflict AS conflict"
- " FROM exchange_do_refund"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_refund",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_do_reserve_open.c b/src/exchangedb/pg_do_reserve_open.c
@@ -1,97 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_do_reserve_open.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_reserve_open.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_reserve_open (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_Amount *total_paid,
- const struct TALER_Amount *reserve_payment,
- uint32_t min_purse_limit,
- const struct TALER_ReserveSignatureP *reserve_sig,
- struct GNUNET_TIME_Timestamp desired_expiration,
- struct GNUNET_TIME_Timestamp now,
- const struct TALER_Amount *open_fee,
- bool *no_funds,
- struct TALER_Amount *reserve_balance,
- struct TALER_Amount *open_cost,
- struct GNUNET_TIME_Timestamp *final_expiration)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- TALER_PQ_query_param_amount (
- pg->conn,
- total_paid),
- TALER_PQ_query_param_amount (
- pg->conn,
- reserve_payment),
- GNUNET_PQ_query_param_uint32 (&min_purse_limit),
- GNUNET_PQ_query_param_uint32 (&pg->def_purse_limit),
- GNUNET_PQ_query_param_auto_from_type (reserve_sig),
- GNUNET_PQ_query_param_timestamp (&desired_expiration),
- GNUNET_PQ_query_param_relative_time (&pg->legal_reserve_expiration_time),
- GNUNET_PQ_query_param_timestamp (&now),
- TALER_PQ_query_param_amount (pg->conn,
- open_fee),
- GNUNET_PQ_query_param_end
- };
- bool no_reserve = true;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_amount ("out_open_cost",
- pg->currency,
- open_cost),
- TALER_PQ_result_spec_amount ("out_reserve_balance",
- pg->currency,
- reserve_balance),
- GNUNET_PQ_result_spec_timestamp ("out_final_expiration",
- final_expiration),
- GNUNET_PQ_result_spec_bool ("out_no_reserve",
- &no_reserve),
- GNUNET_PQ_result_spec_bool ("out_no_funds",
- no_funds),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "do_reserve_open",
- "SELECT "
- " out_open_cost"
- ",out_final_expiration"
- ",out_no_funds"
- ",out_no_reserve"
- ",out_reserve_balance"
- " FROM exchange_do_reserve_open"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "do_reserve_open",
- params,
- rs);
- if (qs <= 0)
- return qs;
- if (no_reserve)
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- return qs;
-}
diff --git a/src/exchangedb/pg_do_reserve_purse.c b/src/exchangedb/pg_do_reserve_purse.c
@@ -1,118 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_reserve_purse.c
- * @brief Implementation of the do_reserve_purse function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_reserve_purse.h"
-#include "helper.h"
-
-
-/**
- * Function called insert request to merge a purse into a reserve by the
- * respective purse merge key. The purse must not have been merged into a
- * different reserve.
- *
- * @param pg the database context
- * @param purse_pub purse to merge
- * @param merge_sig signature affirming the merge
- * @param merge_timestamp time of the merge
- * @param reserve_sig signature of the reserve affirming the merge
- * @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota
- * @param reserve_pub public key of the reserve to credit
- * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
- * @param[out] no_reserve set to true if @a reserve_pub is not a known reserve
- * @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse
- * @return transaction status code
- */
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_reserve_purse (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- const struct TALER_PurseMergeSignatureP *merge_sig,
- const struct GNUNET_TIME_Timestamp merge_timestamp,
- const struct TALER_ReserveSignatureP *reserve_sig,
- const struct TALER_Amount *purse_fee,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- bool *in_conflict,
- bool *no_reserve,
- bool *insufficient_funds)
-{
- struct TALER_Amount zero_fee;
- struct TALER_NormalizedPaytoHashP h_payto;
- struct GNUNET_TIME_Timestamp reserve_expiration
- = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
- pg->idle_reserve_expiration_time));
- struct GNUNET_TIME_Timestamp reserve_gc
- = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
- pg->legal_reserve_expiration_time));
-
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_auto_from_type (merge_sig),
- GNUNET_PQ_query_param_timestamp (&merge_timestamp),
- GNUNET_PQ_query_param_timestamp (&reserve_expiration),
- GNUNET_PQ_query_param_timestamp (&reserve_gc),
- GNUNET_PQ_query_param_auto_from_type (reserve_sig),
- GNUNET_PQ_query_param_bool (NULL == purse_fee),
- TALER_PQ_query_param_amount (pg->conn,
- NULL == purse_fee
- ? &zero_fee
- : purse_fee),
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("insufficient_funds",
- insufficient_funds),
- GNUNET_PQ_result_spec_bool ("conflict",
- in_conflict),
- GNUNET_PQ_result_spec_bool ("no_reserve",
- no_reserve),
- GNUNET_PQ_result_spec_end
- };
-
- {
- struct TALER_NormalizedPayto payto_uri;
-
- payto_uri = TALER_reserve_make_payto (pg->exchange_url,
- reserve_pub);
- TALER_normalized_payto_hash (payto_uri,
- &h_payto);
- GNUNET_free (payto_uri.normalized_payto);
- }
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (pg->currency,
- &zero_fee));
- PREPARE (pg,
- "call_reserve_purse",
- "SELECT"
- " out_no_funds AS insufficient_funds"
- ",out_no_reserve AS no_reserve"
- ",out_conflict AS conflict"
- " FROM exchange_do_reserve_purse"
- " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
-
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_reserve_purse",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_do_withdraw.c b/src/exchangedb/pg_do_withdraw.c
@@ -1,140 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2023-2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_do_withdraw.c
- * @brief Implementation of the do_withdraw function for Postgres
- * @author Özgür Kesim
- */
-#include "taler/taler_exchangedb_lib.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/do_withdraw.h"
-#include "helper.h"
-#include <gnunet/gnunet_time_lib.h>
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_do_withdraw (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_Withdraw *withdraw,
- const struct GNUNET_TIME_Timestamp *timestamp,
- bool *balance_ok,
- struct TALER_Amount *reserve_balance,
- bool *age_ok,
- uint16_t *required_age,
- uint32_t *reserve_birthday,
- bool *idempotent,
- uint16_t *noreveal_index,
- bool *nonce_reuse)
-{
- struct GNUNET_TIME_Timestamp gc;
- struct GNUNET_PQ_QueryParam params[] = {
- TALER_PQ_query_param_amount (pg->conn,
- &withdraw->amount_with_fee),
- GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_pub),
- GNUNET_PQ_query_param_auto_from_type (&withdraw->reserve_sig),
- GNUNET_PQ_query_param_timestamp (timestamp),
- GNUNET_PQ_query_param_timestamp (&gc),
- GNUNET_PQ_query_param_auto_from_type (&withdraw->planchets_h),
- (withdraw->age_proof_required)
- ? GNUNET_PQ_query_param_uint16 (&withdraw->max_age)
- : GNUNET_PQ_query_param_null (),
- (withdraw->age_proof_required)
- ? GNUNET_PQ_query_param_uint16 (&withdraw->noreveal_index)
- : GNUNET_PQ_query_param_null (),
- (withdraw->age_proof_required)
- ? GNUNET_PQ_query_param_auto_from_type (&withdraw->selected_h)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_array_uint64 (withdraw->num_coins,
- withdraw->denom_serials,
- pg->conn),
- TALER_PQ_query_param_array_blinded_denom_sig (withdraw->num_coins,
- withdraw->denom_sigs,
- pg->conn),
- (withdraw->no_blinding_seed)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (&withdraw->blinding_seed),
- (withdraw->no_blinding_seed)
- ? GNUNET_PQ_query_param_null ()
- : TALER_PQ_query_param_array_cs_r_pub (withdraw->num_cs_r_values,
- withdraw->cs_r_values,
- pg->conn),
- (withdraw->no_blinding_seed)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (&withdraw->cs_r_choices),
- GNUNET_PQ_query_param_end
- };
- bool reserve_found;
- bool no_noreveal_index;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("out_reserve_found",
- &reserve_found),
- GNUNET_PQ_result_spec_bool ("out_balance_ok",
- balance_ok),
- TALER_PQ_RESULT_SPEC_AMOUNT ("out_reserve_balance",
- reserve_balance),
- GNUNET_PQ_result_spec_bool ("out_age_ok",
- age_ok),
- GNUNET_PQ_result_spec_uint16 ("out_required_age",
- required_age),
- GNUNET_PQ_result_spec_uint32 ("out_reserve_birthday",
- reserve_birthday),
- GNUNET_PQ_result_spec_bool ("out_idempotent",
- idempotent),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint16 ("out_noreveal_index",
- noreveal_index),
- &no_noreveal_index),
- GNUNET_PQ_result_spec_bool ("out_nonce_reuse",
- nonce_reuse),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- GNUNET_assert ((! withdraw->no_blinding_seed) ||
- (0 == withdraw->num_cs_r_values));
-
- gc = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add (timestamp->abs_time,
- pg->legal_reserve_expiration_time));
- PREPARE (pg,
- "call_withdraw",
- "SELECT "
- " out_reserve_found"
- ",out_balance_ok"
- ",out_reserve_balance"
- ",out_age_ok"
- ",out_required_age"
- ",out_reserve_birthday"
- ",out_idempotent"
- ",out_noreveal_index"
- ",out_nonce_reuse"
- " FROM exchange_do_withdraw"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_withdraw",
- params,
- rs);
- GNUNET_PQ_cleanup_query_params_closures (params);
-
- if (0 > qs)
- return qs;
- if (! reserve_found)
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- if ((withdraw->age_proof_required) &&
- (idempotent && no_noreveal_index))
- GNUNET_break (0);
- return qs;
-}
diff --git a/src/exchangedb/pg_drain_kyc_alert.c b/src/exchangedb/pg_drain_kyc_alert.c
@@ -1,55 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_drain_kyc_alert.c
- * @brief Implementation of the drain_kyc_alert function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/drain_kyc_alert.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_drain_kyc_alert (struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint32_t trigger_type,
- struct TALER_NormalizedPaytoHashP *h_payto)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint32 (&trigger_type),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("h_payto",
- h_payto),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "drain_kyc_alert",
- "DELETE FROM kyc_alerts"
- " WHERE trigger_type=$1"
- " AND h_payto = "
- " (SELECT h_payto "
- " FROM kyc_alerts"
- " WHERE trigger_type=$1"
- " LIMIT 1)"
- " RETURNING h_payto;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "drain_kyc_alert",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_drop_tables.c b/src/exchangedb/pg_drop_tables.c
@@ -1,54 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_drop_tables.c
- * @brief Implementation of the drop_tables function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/drop_tables.h"
-#include "helper.h"
-
-
-/**
- * Drop all Taler tables. This should only be used by testcases.
- *
- * @param pg the database context
- * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
- */
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGEDB_drop_tables (struct TALER_EXCHANGEDB_PostgresContext *pg)
-{
- struct GNUNET_PQ_Context *conn;
- enum GNUNET_GenericReturnValue ret;
-
- if (NULL != pg->conn)
- {
- GNUNET_PQ_disconnect (pg->conn);
- pg->conn = NULL;
- }
- conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
- "exchangedb-postgres",
- NULL,
- NULL,
- NULL);
- if (NULL == conn)
- return GNUNET_SYSERR;
- ret = GNUNET_PQ_exec_sql (conn,
- "drop");
- GNUNET_PQ_disconnect (conn);
- return ret;
-}
diff --git a/src/exchangedb/pg_enable_rules.c b/src/exchangedb/pg_enable_rules.c
@@ -1,74 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_enable_rules.c
- * @brief Implementation of the enable_rules function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/enable_rules.h"
-#include "helper.h"
-
-
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGEDB_enable_rules (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *schema)
-{
- struct GNUNET_PQ_Context *conn;
- enum GNUNET_GenericReturnValue ret;
- char *sp;
-
- GNUNET_asprintf (&sp,
- "SET search_path TO %s,exchange;",
- schema);
- {
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_try_execute (sp),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
- char *schemadash;
-
- GNUNET_asprintf (&schemadash,
- "%s-",
- schema);
- conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
- "exchangedb-postgres",
- schemadash,
- es,
- NULL);
- GNUNET_free (schemadash);
- }
- GNUNET_free (sp);
- if (NULL == conn)
- return GNUNET_SYSERR;
- {
- char *procfile;
-
- GNUNET_asprintf (&procfile,
- "%s-procedures",
- schema);
- ret = GNUNET_PQ_exec_sql (conn,
- procfile);
- /* $SCHEMA-procedures MAY not exist, so only check for hard error */
- GNUNET_break (GNUNET_SYSERR != ret);
- if (GNUNET_NO == ret)
- ret = GNUNET_OK;
- GNUNET_free (procfile);
- }
- GNUNET_PQ_disconnect (conn);
- return ret;
-}
diff --git a/src/exchangedb/pg_ensure_coin_known.c b/src/exchangedb/pg_ensure_coin_known.c
@@ -1,166 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_ensure_coin_known.c
- * @brief Implementation of the ensure_coin_known function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_exchangedb_lib.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/ensure_coin_known.h"
-#include "helper.h"
-
-
-enum TALER_EXCHANGEDB_CoinKnownStatus
-TALER_EXCHANGEDB_ensure_coin_known (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinPublicInfo *coin,
- uint64_t *known_coin_id,
- struct TALER_DenominationHashP *denom_hash,
- struct TALER_AgeCommitmentHashP *h_age_commitment)
-{
- enum GNUNET_DB_QueryStatus qs;
- bool existed;
- bool no_denom_pub_hash;
- bool no_age_commitment_hash;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash),
- coin->no_age_commitment
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (&coin->h_age_commitment),
- TALER_PQ_query_param_denom_sig (&coin->denom_sig),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("existed",
- &existed),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id",
- known_coin_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- denom_hash),
- &no_denom_pub_hash),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- h_age_commitment),
- &no_age_commitment_hash),
- GNUNET_PQ_result_spec_end
- };
-
- /*
- See also:
- https://stackoverflow.com/questions/34708509/how-to-use-returning-with-on-conflict-in-postgresql/37543015#37543015
- */
- PREPARE (pg,
- "insert_known_coin",
- "WITH dd"
- " (denominations_serial"
- " ,coin"
- " ) AS ("
- " SELECT "
- " denominations_serial"
- " ,coin"
- " FROM denominations"
- " WHERE denom_pub_hash=$2"
- " ), input_rows"
- " (coin_pub) AS ("
- " VALUES ($1::BYTEA)"
- " ), ins AS ("
- " INSERT INTO known_coins "
- " (coin_pub"
- " ,denominations_serial"
- " ,age_commitment_hash"
- " ,denom_sig"
- " ,remaining"
- " ) SELECT "
- " $1"
- " ,denominations_serial"
- " ,$3"
- " ,$4"
- " ,coin"
- " FROM dd"
- " ON CONFLICT DO NOTHING" /* CONFLICT on (coin_pub) */
- " RETURNING "
- " known_coin_id"
- " ) "
- "SELECT "
- " FALSE AS existed"
- " ,known_coin_id"
- " ,NULL AS denom_pub_hash"
- " ,NULL AS age_commitment_hash"
- " FROM ins "
- "UNION ALL "
- "SELECT "
- " TRUE AS existed"
- " ,known_coin_id"
- " ,denom_pub_hash"
- " ,kc.age_commitment_hash"
- " FROM input_rows"
- " JOIN known_coins kc USING (coin_pub)"
- " JOIN denominations USING (denominations_serial)"
- " LIMIT 1");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "insert_known_coin",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- return TALER_EXCHANGEDB_CKS_HARD_FAIL;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0); /* should be impossible */
- return TALER_EXCHANGEDB_CKS_HARD_FAIL;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- if (! existed)
- return TALER_EXCHANGEDB_CKS_ADDED;
- break; /* continued below */
- }
-
- if ( (! no_denom_pub_hash) &&
- (0 != GNUNET_memcmp (denom_hash,
- &coin->denom_pub_hash)) )
- {
- GNUNET_break_op (0);
- return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT;
- }
-
- if (no_age_commitment_hash != coin->no_age_commitment)
- {
- if (no_age_commitment_hash)
- {
- GNUNET_break_op (0);
- return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL;
- }
- else
- {
- GNUNET_break_op (0);
- return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL;
- }
- }
- else if ( (! no_age_commitment_hash) &&
- (0 != GNUNET_memcmp (h_age_commitment,
- &coin->h_age_commitment)) )
- {
- GNUNET_break_op (0);
- return TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS;
- }
-
- return TALER_EXCHANGEDB_CKS_PRESENT;
-}
diff --git a/src/exchangedb/pg_event_listen.c b/src/exchangedb/pg_event_listen.c
@@ -1,49 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_event_listen.c
- * @brief Implementation of the event_listen function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_dbevents.h"
-#include "taler/exchange-database/event_listen.h"
-#include "helper.h"
-
-/**
- * Register callback to be invoked on events of type @a es.
- *
- * @param pg the database context
- * @param timeout how long until to generate a timeout event
- * @param es specification of the event to listen for
- * @param cb function to call when the event happens, possibly
- * multiple times (until cancel is invoked)
- * @param cb_cls closure for @a cb
- * @return handle useful to cancel the listener
- */
-struct GNUNET_DB_EventHandler *
-TALER_EXCHANGEDB_event_listen (struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct GNUNET_TIME_Relative timeout,
- const struct GNUNET_DB_EventHeaderP *es,
- GNUNET_DB_EventCallback cb,
- void *cb_cls)
-{
-
- return GNUNET_PQ_event_listen (pg->conn,
- es,
- timeout,
- cb,
- cb_cls);
-}
diff --git a/src/exchangedb/pg_event_listen_cancel.c b/src/exchangedb/pg_event_listen_cancel.c
@@ -1,34 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_event_listen_cancel.c
- * @brief Implementation of the event_listen_cancel function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/exchange-database/event_listen_cancel.h"
-#include "helper.h"
-
-
-void
-TALER_TALER_EXCHANGEDB_event_listen_cancel (struct
- TALER_EXCHANGEDB_PostgresContext *pg
- ,
- struct GNUNET_DB_EventHandler *eh)
-
-{
- (void) pg;
- GNUNET_PQ_event_listen_cancel (eh);
-}
diff --git a/src/exchangedb/pg_event_notify.c b/src/exchangedb/pg_event_notify.c
@@ -1,37 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_event_notify.c
- * @brief Implementation of the event_notify function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_dbevents.h"
-#include "taler/exchange-database/event_notify.h"
-#include "helper.h"
-
-
-void
-TALER_EXCHANGEDB_event_notify (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct GNUNET_DB_EventHeaderP *es,
- const void *extra,
- size_t extra_size)
-{
-
- GNUNET_PQ_event_notify (pg->conn,
- es,
- extra,
- extra_size);
-}
diff --git a/src/exchangedb/pg_expire_purse.c b/src/exchangedb/pg_expire_purse.c
@@ -1,65 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_expire_purse.c
- * @brief Implementation of the expire_purse function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/expire_purse.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_expire_purse (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct GNUNET_TIME_Absolute start_time,
- struct GNUNET_TIME_Absolute end_time)
-{
- struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_absolute_time (&start_time),
- GNUNET_PQ_query_param_absolute_time (&end_time),
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_end
- };
- bool found = false;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("found",
- &found),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
-
- PREPARE (pg,
- "call_expire_purse",
- "SELECT "
- " out_found AS found"
- " FROM exchange_do_expire_purse"
- " ($1,$2,$3);");
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_expire_purse",
- params,
- rs);
- if (qs < 0)
- return qs;
- GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
- return found
- ? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
- : GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-}
diff --git a/src/exchangedb/pg_find_aggregation_transient.c b/src/exchangedb/pg_find_aggregation_transient.c
@@ -1,69 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_find_aggregation_transient.c
- * @brief Implementation of the find_aggregation_transient function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/find_aggregation_transient.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_find_aggregation_transient (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- struct TALER_FullPayto *payto_uri,
- struct TALER_WireTransferIdentifierRawP *wtid,
- struct TALER_MerchantPublicKeyP *merchant_pub,
- struct TALER_Amount *total)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
- merchant_pub),
- GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
- wtid),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri->full_payto),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- total),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "find_transient_aggregations",
- "SELECT"
- " atr.amount"
- " ,atr.wtid_raw"
- " ,atr.merchant_pub"
- " ,wt.payto_uri"
- " FROM wire_targets wt"
- " JOIN aggregation_transient atr"
- " USING (wire_target_h_payto)"
- " WHERE wt.h_normalized_payto=$1"
- " LIMIT 1;"); /* Note: there should really be only 1 match */
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "find_transient_aggregations",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_gc.c b/src/exchangedb/pg_gc.c
@@ -1,75 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_gc.c
- * @brief Implementation of the gc function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/gc.h"
-#include "helper.h"
-
-
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGEDB_gc (struct TALER_EXCHANGEDB_PostgresContext *pg)
-{
- struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
- struct GNUNET_TIME_Absolute long_ago;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_absolute_time (&long_ago),
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_Context *conn;
- enum GNUNET_GenericReturnValue ret;
-
- /* Keep wire fees for 10 years, that should always
- be enough _and_ they are tiny so it does not
- matter to make this tight */
- long_ago = GNUNET_TIME_absolute_subtract (
- now,
- GNUNET_TIME_relative_multiply (
- GNUNET_TIME_UNIT_YEARS,
- 10));
- {
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
- struct GNUNET_PQ_PreparedStatement ps[] = {
- GNUNET_PQ_make_prepare ("run_gc",
- "CALL"
- " exchange_do_gc"
- " ($1,$2);"),
- GNUNET_PQ_PREPARED_STATEMENT_END
- };
-
- conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
- "exchangedb-postgres",
- NULL,
- es,
- ps);
- }
- if (NULL == conn)
- return GNUNET_SYSERR;
- ret = GNUNET_OK;
- if (0 > GNUNET_PQ_eval_prepared_non_select (conn,
- "run_gc",
- params))
- ret = GNUNET_SYSERR;
- GNUNET_PQ_disconnect (conn);
- return ret;
-}
diff --git a/src/exchangedb/pg_get_coin_denomination.c b/src/exchangedb/pg_get_coin_denomination.c
@@ -1,65 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_coin_denomination.c
- * @brief Implementation of the get_coin_denomination function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_coin_denomination.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_coin_denomination (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- uint64_t *known_coin_id,
- struct TALER_DenominationHashP *denom_hash)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- denom_hash),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id",
- known_coin_id),
- GNUNET_PQ_result_spec_end
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Getting coin denomination of coin %s\n",
- TALER_B2S (coin_pub));
-
- /* Used in #postgres_get_coin_denomination() to fetch
- the denomination public key hash for
- a coin known to the exchange. */
- PREPARE (pg,
- "get_coin_denomination",
- "SELECT"
- " denominations.denom_pub_hash"
- ",known_coin_id"
- " FROM known_coins"
- " JOIN denominations USING (denominations_serial)"
- " WHERE coin_pub=$1"
- " FOR SHARE;");
-
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_coin_denomination",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_coin_transactions.c b/src/exchangedb/pg_get_coin_transactions.c
@@ -1,1184 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_get_coin_transactions.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_exchangedb_lib.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_coin_transactions.h"
-#include "helper.h"
-#include "taler/exchange-database/start_read_committed.h"
-#include "taler/exchange-database/commit.h"
-#include "taler/exchange-database/rollback.h"
-
-
-/**
- * How often do we re-try when encountering DB serialization issues?
- * (We are read-only, so can only happen due to concurrent insert,
- * which should be very rare.)
- */
-#define RETRIES 3
-
-/**
- * Closure for callbacks called from #TALER_EXCHANGEDB_get_coin_transactions()
- */
-struct CoinHistoryContext
-{
- /**
- * Head of the coin's history list.
- */
- struct TALER_EXCHANGEDB_TransactionList *head;
-
- /**
- * Public key of the coin we are building the history for.
- */
- const struct TALER_CoinSpendPublicKeyP *coin_pub;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Our current offset in the coin history.
- */
- uint64_t chid;
-
- /**
- * Set to 'true' if the transaction failed.
- */
- bool failed;
-
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_coin_deposit (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct TALER_EXCHANGEDB_DepositListEntry *deposit;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- uint64_t serial_id;
-
- deposit = GNUNET_new (struct TALER_EXCHANGEDB_DepositListEntry);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &deposit->amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- &deposit->deposit_fee),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &deposit->h_denom_pub),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &deposit->h_age_commitment),
- &deposit->no_age_commitment),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("wallet_data_hash",
- &deposit->wallet_data_hash),
- &deposit->no_wallet_data_hash),
- GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
- &deposit->timestamp),
- GNUNET_PQ_result_spec_timestamp ("refund_deadline",
- &deposit->refund_deadline),
- GNUNET_PQ_result_spec_timestamp ("wire_deadline",
- &deposit->wire_deadline),
- GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
- &deposit->merchant_pub),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- &deposit->h_contract_terms),
- GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
- &deposit->wire_salt),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &deposit->receiver_wire_account.full_payto
- ),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &deposit->csig),
- GNUNET_PQ_result_spec_uint64 ("coin_deposit_serial_id",
- &serial_id),
- GNUNET_PQ_result_spec_auto_from_type ("done",
- &deposit->done),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (deposit);
- chc->failed = true;
- return;
- }
- }
- tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
- tl->next = chc->head;
- tl->type = TALER_EXCHANGEDB_TT_DEPOSIT;
- tl->details.deposit = deposit;
- tl->serial_id = serial_id;
- tl->coin_history_id = chc->chid;
- chc->head = tl;
- }
-}
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_coin_purse_deposit (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct TALER_EXCHANGEDB_PurseDepositListEntry *deposit;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- uint64_t serial_id;
-
- deposit = GNUNET_new (struct TALER_EXCHANGEDB_PurseDepositListEntry);
- {
- bool not_finished;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &deposit->amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- &deposit->deposit_fee),
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &deposit->purse_pub),
- GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
- &serial_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("partner_base_url",
- &deposit->exchange_base_url),
- NULL),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &deposit->coin_sig),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &deposit->h_age_commitment),
- &deposit->no_age_commitment),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_bool ("refunded",
- &deposit->refunded),
- ¬_finished),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &deposit->h_denom_pub),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (deposit);
- chc->failed = true;
- return;
- }
- if (not_finished)
- deposit->refunded = false;
- /* double-check for all-zeros age commitment */
- if (! deposit->no_age_commitment)
- deposit->no_age_commitment
- = GNUNET_is_zero (&deposit->h_age_commitment);
- }
- tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
- tl->next = chc->head;
- tl->type = TALER_EXCHANGEDB_TT_PURSE_DEPOSIT;
- tl->details.purse_deposit = deposit;
- tl->serial_id = serial_id;
- tl->coin_history_id = chc->chid;
- chc->head = tl;
- }
-}
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_coin_melt (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_MeltListEntry *melt;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- uint64_t serial_id;
-
- melt = GNUNET_new (struct TALER_EXCHANGEDB_MeltListEntry);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("rc",
- &melt->rc),
- /* oldcoin_index not needed */
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &melt->h_denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
- &melt->coin_sig),
- GNUNET_PQ_result_spec_auto_from_type ("refresh_seed",
- &melt->refresh_seed),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
- &melt->blinding_seed),
- &melt->no_blinding_seed),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &melt->amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
- &melt->melt_fee),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &melt->h_age_commitment),
- &melt->no_age_commitment),
- GNUNET_PQ_result_spec_uint64 ("refresh_id",
- &serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (melt);
- chc->failed = true;
- return;
- }
- }
- tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
- tl->next = chc->head;
- tl->type = TALER_EXCHANGEDB_TT_MELT;
- tl->details.melt = melt;
- tl->serial_id = serial_id;
- tl->coin_history_id = chc->chid;
- chc->head = tl;
- }
-}
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_coin_refund (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_RefundListEntry *refund;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- uint64_t serial_id;
-
- refund = GNUNET_new (struct TALER_EXCHANGEDB_RefundListEntry);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
- &refund->merchant_pub),
- GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
- &refund->merchant_sig),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- &refund->h_contract_terms),
- GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
- &refund->rtransaction_id),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &refund->refund_amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
- &refund->refund_fee),
- GNUNET_PQ_result_spec_uint64 ("refund_serial_id",
- &serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (refund);
- chc->failed = true;
- return;
- }
- }
- tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
- tl->next = chc->head;
- tl->type = TALER_EXCHANGEDB_TT_REFUND;
- tl->details.refund = refund;
- tl->serial_id = serial_id;
- tl->coin_history_id = chc->chid;
- chc->head = tl;
- }
-}
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_coin_purse_decision (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_PurseRefundListEntry *prefund;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- uint64_t serial_id;
-
- prefund = GNUNET_new (struct TALER_EXCHANGEDB_PurseRefundListEntry);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &prefund->purse_pub),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &prefund->refund_amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
- &prefund->refund_fee),
- GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id",
- &serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (prefund);
- chc->failed = true;
- return;
- }
- }
- tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
- tl->next = chc->head;
- tl->type = TALER_EXCHANGEDB_TT_PURSE_REFUND;
- tl->details.purse_refund = prefund;
- tl->serial_id = serial_id;
- tl->coin_history_id = chc->chid;
- chc->head = tl;
- }
-}
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_old_coin_recoup (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- uint64_t serial_id;
-
- recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &recoup->coin.coin_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &recoup->coin_sig),
- GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
- &recoup->coin_blind),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &recoup->value),
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- &recoup->timestamp),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &recoup->coin.denom_pub_hash),
- TALER_PQ_result_spec_denom_sig ("denom_sig",
- &recoup->coin.denom_sig),
- GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
- &serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (recoup);
- chc->failed = true;
- return;
- }
- recoup->old_coin_pub = *chc->coin_pub;
- }
- tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
- tl->next = chc->head;
- tl->type = TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER;
- tl->details.old_coin_recoup = recoup;
- tl->serial_id = serial_id;
- tl->coin_history_id = chc->chid;
- chc->head = tl;
- }
-}
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_coin_recoup (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_RecoupListEntry *recoup;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- uint64_t serial_id;
-
- recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupListEntry);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &recoup->reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &recoup->coin_sig),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &recoup->h_denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
- &recoup->coin_blind),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &recoup->value),
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- &recoup->timestamp),
- GNUNET_PQ_result_spec_uint64 ("recoup_uuid",
- &serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (recoup);
- chc->failed = true;
- return;
- }
- }
- tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
- tl->next = chc->head;
- tl->type = TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW;
- tl->details.recoup = recoup;
- tl->serial_id = serial_id;
- tl->coin_history_id = chc->chid;
- chc->head = tl;
- }
-}
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_coin_recoup_refresh (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- uint64_t serial_id;
-
- recoup = GNUNET_new (struct TALER_EXCHANGEDB_RecoupRefreshListEntry);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
- &recoup->old_coin_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &recoup->coin_sig),
- GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
- &recoup->coin_blind),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &recoup->value),
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- &recoup->timestamp),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &recoup->coin.denom_pub_hash),
- TALER_PQ_result_spec_denom_sig ("denom_sig",
- &recoup->coin.denom_sig),
- GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
- &serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (recoup);
- chc->failed = true;
- return;
- }
- recoup->coin.coin_pub = *chc->coin_pub;
- }
- tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
- tl->next = chc->head;
- tl->type = TALER_EXCHANGEDB_TT_RECOUP_REFRESH;
- tl->details.recoup_refresh = recoup;
- tl->serial_id = serial_id;
- tl->coin_history_id = chc->chid;
- chc->head = tl;
- }
-}
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_coin_reserve_open (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_ReserveOpenListEntry *role;
- struct TALER_EXCHANGEDB_TransactionList *tl;
- uint64_t serial_id;
-
- role = GNUNET_new (struct TALER_EXCHANGEDB_ReserveOpenListEntry);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &role->reserve_sig),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &role->coin_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT ("contribution",
- &role->coin_contribution),
- GNUNET_PQ_result_spec_uint64 ("reserve_open_deposit_uuid",
- &serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- GNUNET_free (role);
- chc->failed = true;
- return;
- }
- }
- tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
- tl->next = chc->head;
- tl->type = TALER_EXCHANGEDB_TT_RESERVE_OPEN;
- tl->details.reserve_open = role;
- tl->serial_id = serial_id;
- tl->coin_history_id = chc->chid;
- chc->head = tl;
- }
-}
-
-
-/**
- * Work we need to do.
- */
-struct Work
-{
- /**
- * Name of the table.
- */
- const char *table;
-
- /**
- * SQL prepared statement name.
- */
- const char *statement;
-
- /**
- * Function to call to handle the result(s).
- */
- GNUNET_PQ_PostgresResultHandler cb;
-};
-
-
-/**
- * We found a coin history entry. Lookup details
- * from the respective table and store in @a cls.
- *
- * @param[in,out] cls a `struct CoinHistoryContext`
- * @param result a coin history entry result set
- * @param num_results total number of results in @a results
- */
-static void
-handle_history_entry (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinHistoryContext *chc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = chc->pg;
- static const struct Work work[] = {
- [TALER_EXCHANGEDB_TT_DEPOSIT] =
- { "coin_deposits",
- "get_deposit_with_coin_pub",
- &add_coin_deposit },
- [TALER_EXCHANGEDB_TT_MELT] =
- { "refresh",
- "get_refresh_by_coin",
- &add_coin_melt },
- [TALER_EXCHANGEDB_TT_PURSE_DEPOSIT] =
- { "purse_deposits",
- "get_purse_deposit_by_coin_pub",
- &add_coin_purse_deposit },
- [TALER_EXCHANGEDB_TT_PURSE_REFUND] =
- { "purse_decision",
- "get_purse_decision_by_coin_pub",
- &add_coin_purse_decision },
- [TALER_EXCHANGEDB_TT_REFUND] =
- { "refunds",
- "get_refunds_by_coin",
- &add_coin_refund },
- [TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW] =
- { "recoup",
- "recoup_by_coin",
- &add_coin_recoup },
- [TALER_EXCHANGEDB_TT_RECOUP_REFRESH] =
- { "recoup_refresh::NEW",
- "recoup_by_refreshed_coin",
- &add_coin_recoup_refresh },
- [TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER] =
- { "recoup_refresh::OLD",
- "recoup_by_old_coin",
- &add_old_coin_recoup },
- [TALER_EXCHANGEDB_TT_RESERVE_OPEN] =
- { "reserves_open_deposits",
- "reserve_open_by_coin",
- &add_coin_reserve_open },
- { NULL, NULL, NULL }
- };
- char *table_name;
- uint64_t serial_id;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("table_name",
- &table_name),
- GNUNET_PQ_result_spec_uint64 ("serial_id",
- &serial_id),
- GNUNET_PQ_result_spec_uint64 ("coin_history_serial_id",
- &chc->chid),
- GNUNET_PQ_result_spec_end
- };
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (chc->coin_pub),
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- enum GNUNET_DB_QueryStatus qs;
- bool found = false;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- chc->failed = true;
- return;
- }
-
- for (unsigned int s = 0;
- NULL != work[s].statement;
- s++)
- {
- if (0 != strcmp (table_name,
- work[s].table))
- continue;
- found = true;
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- work[s].statement,
- params,
- work[s].cb,
- chc);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Coin %s had %d transactions at %llu in table %s\n",
- TALER_B2S (chc->coin_pub),
- (int) qs,
- (unsigned long long) serial_id,
- table_name);
- if (0 > qs)
- chc->failed = true;
- break;
- }
- if (! found)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Coin history includes unsupported table `%s`\n",
- table_name);
- chc->failed = true;
- }
- GNUNET_PQ_cleanup_result (rs);
- if (chc->failed)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_coin_transactions (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- bool begin_transaction,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- uint64_t start_off,
- uint64_t etag_in,
- uint64_t *etag_out,
- struct TALER_Amount *balance,
- struct TALER_DenominationHashP *h_denom_pub,
- struct TALER_EXCHANGEDB_TransactionList **tlp)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_QueryParam lparams[] = {
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_uint64 (&start_off),
- GNUNET_PQ_query_param_end
- };
- struct CoinHistoryContext chc = {
- .head = NULL,
- .coin_pub = coin_pub,
- .pg = pg
- };
-
- *tlp = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Getting transactions for coin %s\n",
- TALER_B2S (coin_pub));
- PREPARE (pg,
- "get_coin_history_etag_balance",
- "SELECT"
- " ch.coin_history_serial_id"
- ",kc.remaining"
- ",denom.denom_pub_hash"
- " FROM coin_history ch"
- " JOIN known_coins kc"
- " USING (coin_pub)"
- " JOIN denominations denom"
- " USING (denominations_serial)"
- " WHERE coin_pub=$1"
- " ORDER BY coin_history_serial_id DESC"
- " LIMIT 1;");
- PREPARE (pg,
- "get_coin_history",
- "SELECT"
- " table_name"
- ",serial_id"
- ",coin_history_serial_id"
- " FROM coin_history"
- " WHERE coin_pub=$1"
- " AND coin_history_serial_id > $2"
- " ORDER BY coin_history_serial_id DESC;");
- PREPARE (pg,
- "get_deposit_with_coin_pub",
- "SELECT"
- " cdep.amount_with_fee"
- ",denoms.fee_deposit"
- ",denoms.denom_pub_hash"
- ",kc.age_commitment_hash"
- ",bdep.wallet_timestamp"
- ",bdep.refund_deadline"
- ",bdep.wire_deadline"
- ",bdep.merchant_pub"
- ",bdep.h_contract_terms"
- ",bdep.wallet_data_hash"
- ",bdep.wire_salt"
- ",wt.payto_uri"
- ",cdep.coin_sig"
- ",cdep.coin_deposit_serial_id"
- ",bdep.done"
- " FROM coin_deposits cdep"
- " JOIN batch_deposits bdep"
- " USING (batch_deposit_serial_id)"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " JOIN known_coins kc"
- " ON (kc.coin_pub = cdep.coin_pub)"
- " JOIN denominations denoms"
- " USING (denominations_serial)"
- " WHERE cdep.coin_pub=$1"
- " AND cdep.coin_deposit_serial_id=$2;");
- PREPARE (pg,
- "get_refresh_by_coin",
- "SELECT"
- " rc"
- ",refresh_seed"
- ",blinding_seed"
- ",old_coin_sig"
- ",amount_with_fee"
- ",denoms.denom_pub_hash"
- ",denoms.fee_refresh"
- ",kc.age_commitment_hash"
- ",refresh_id"
- " FROM refresh"
- " JOIN known_coins kc"
- " ON (refresh.old_coin_pub = kc.coin_pub)"
- " JOIN denominations denoms"
- " USING (denominations_serial)"
- " WHERE old_coin_pub=$1"
- " AND refresh_id=$2;");
- PREPARE (pg,
- "get_purse_deposit_by_coin_pub",
- "SELECT"
- " partner_base_url"
- ",pd.amount_with_fee"
- ",denoms.fee_deposit"
- ",denoms.denom_pub_hash"
- ",pd.purse_pub"
- ",kc.age_commitment_hash"
- ",pd.coin_sig"
- ",pd.purse_deposit_serial_id"
- ",pdes.refunded"
- " FROM purse_deposits pd"
- " LEFT JOIN partners"
- " USING (partner_serial_id)"
- " JOIN purse_requests pr"
- " USING (purse_pub)"
- " LEFT JOIN purse_decision pdes"
- " USING (purse_pub)"
- " JOIN known_coins kc"
- " ON (pd.coin_pub = kc.coin_pub)"
- " JOIN denominations denoms"
- " USING (denominations_serial)"
- " WHERE pd.purse_deposit_serial_id=$2"
- " AND pd.coin_pub=$1;");
- PREPARE (pg,
- "get_purse_decision_by_coin_pub",
- "SELECT"
- " pdes.purse_pub"
- ",pd.amount_with_fee"
- ",denom.fee_refund"
- ",pdes.purse_decision_serial_id"
- " FROM purse_decision pdes"
- " JOIN purse_deposits pd"
- " USING (purse_pub)"
- " JOIN known_coins kc"
- " ON (pd.coin_pub = kc.coin_pub)"
- " JOIN denominations denom"
- " USING (denominations_serial)"
- " WHERE pd.coin_pub=$1"
- " AND pdes.purse_decision_serial_id=$2"
- " AND pdes.refunded;");
- PREPARE (pg,
- "get_refunds_by_coin",
- "SELECT"
- " bdep.merchant_pub"
- ",ref.merchant_sig"
- ",bdep.h_contract_terms"
- ",ref.rtransaction_id"
- ",ref.amount_with_fee"
- ",denom.fee_refund"
- ",ref.refund_serial_id"
- " FROM refunds ref"
- " JOIN coin_deposits cdep"
- " ON (ref.coin_pub = cdep.coin_pub AND ref.batch_deposit_serial_id = cdep.batch_deposit_serial_id)"
- " JOIN batch_deposits bdep"
- " ON (ref.batch_deposit_serial_id = bdep.batch_deposit_serial_id)"
- " JOIN known_coins kc"
- " ON (ref.coin_pub = kc.coin_pub)"
- " JOIN denominations denom"
- " USING (denominations_serial)"
- " WHERE ref.coin_pub=$1"
- " AND ref.refund_serial_id=$2;");
- PREPARE (pg,
- "recoup_by_old_coin",
- "SELECT"
- " coins.coin_pub"
- ",rr.coin_sig"
- ",rr.coin_blind"
- ",rr.amount"
- ",rr.recoup_timestamp"
- ",denoms.denom_pub_hash"
- ",coins.denom_sig"
- ",rr.recoup_refresh_uuid"
- " FROM recoup_refresh rr"
- " JOIN known_coins coins"
- " USING (coin_pub)"
- " JOIN denominations denoms"
- " USING (denominations_serial)"
- " WHERE recoup_refresh_uuid=$2"
- " AND refresh_id IN"
- " (SELECT refresh_id"
- " FROM refresh"
- " WHERE refresh.old_coin_pub=$1);");
- PREPARE (pg,
- "recoup_by_coin",
- "SELECT"
- " res.reserve_pub"
- ",denoms.denom_pub_hash"
- ",rcp.coin_sig"
- ",rcp.coin_blind"
- ",rcp.amount"
- ",rcp.recoup_timestamp"
- ",rcp.recoup_uuid"
- " FROM recoup rcp"
- " JOIN withdraw ro"
- " USING (withdraw_id)"
- " JOIN reserves res"
- " USING (reserve_pub)"
- " JOIN known_coins coins"
- " USING (coin_pub)"
- " JOIN denominations denoms"
- " ON (denoms.denominations_serial = coins.denominations_serial)"
- " WHERE rcp.recoup_uuid=$2"
- " AND coins.coin_pub=$1;");
- /* Used to obtain recoup transactions
- for a refreshed coin */
- PREPARE (pg,
- "recoup_by_refreshed_coin",
- "SELECT"
- " old_coins.coin_pub AS old_coin_pub"
- ",rr.coin_sig"
- ",rr.coin_blind"
- ",rr.amount"
- ",rr.recoup_timestamp"
- ",denoms.denom_pub_hash"
- ",coins.denom_sig"
- ",recoup_refresh_uuid"
- " FROM recoup_refresh rr"
- " JOIN refresh rfc"
- " ON (rr.refresh_id = rfc.refresh_id)"
- " JOIN known_coins old_coins"
- " ON (rfc.old_coin_pub = old_coins.coin_pub)"
- " JOIN known_coins coins"
- " ON (rr.coin_pub = coins.coin_pub)"
- " JOIN denominations denoms"
- " ON (denoms.denominations_serial = coins.denominations_serial)"
- " WHERE rr.recoup_refresh_uuid=$2"
- " AND coins.coin_pub=$1;");
- PREPARE (pg,
- "reserve_open_by_coin",
- "SELECT"
- " reserve_open_deposit_uuid"
- ",coin_sig"
- ",reserve_sig"
- ",contribution"
- " FROM reserves_open_deposits"
- " WHERE coin_pub=$1"
- " AND reserve_open_deposit_uuid=$2;");
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- " --- landed here 1\n");
- for (unsigned int i = 0; i<RETRIES; i++)
- {
- enum GNUNET_DB_QueryStatus qs;
- uint64_t end;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("coin_history_serial_id",
- &end),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- h_denom_pub),
- TALER_PQ_RESULT_SPEC_AMOUNT ("remaining",
- balance),
- GNUNET_PQ_result_spec_end
- };
-
- if (begin_transaction)
- {
- if (GNUNET_OK !=
- TALER_TALER_EXCHANGEDB_start_read_committed (pg,
- "get-coin-transactions"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
- /* First only check the last item, to see if
- we even need to iterate */
- qs = GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "get_coin_history_etag_balance",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- if (begin_transaction)
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- if (begin_transaction)
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- if (begin_transaction)
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- *etag_out = end;
- if (end == etag_in)
- return qs;
- }
- /* We indeed need to iterate over the history */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Current ETag for coin %s is %llu\n",
- TALER_B2S (coin_pub),
- (unsigned long long) end);
-
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "get_coin_history",
- lparams,
- &handle_history_entry,
- &chc);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- if (begin_transaction)
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- if (begin_transaction)
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- default:
- break;
- }
- if (chc.failed)
- {
- if (begin_transaction)
- TALER_EXCHANGEDB_rollback (pg);
- TALER_EXCHANGEDB_free_coin_transaction_list (chc.head);
- return GNUNET_DB_STATUS_SOFT_ERROR;
- }
- if (! begin_transaction)
- {
- *tlp = chc.head;
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
- qs = TALER_EXCHANGEDB_commit (pg);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- TALER_EXCHANGEDB_free_coin_transaction_list (chc.head);
- chc.head = NULL;
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TALER_EXCHANGEDB_free_coin_transaction_list (chc.head);
- chc.head = NULL;
- continue;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- *tlp = chc.head;
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- " --- landed here 2\n");
- return GNUNET_DB_STATUS_SOFT_ERROR;
-}
diff --git a/src/exchangedb/pg_get_denomination_by_serial.c b/src/exchangedb/pg_get_denomination_by_serial.c
@@ -1,87 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_denomination_by_serial.c
- * @brief Implementation of the get_denomination_by_serial function for Postgres
- * @author Özgür Kesim
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_denomination_by_serial.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_denomination_by_serial (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t denom_serial,
- struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&denom_serial),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &issue->signature),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &issue->denom_hash),
- GNUNET_PQ_result_spec_timestamp ("valid_from",
- &issue->start),
- GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
- &issue->expire_withdraw),
- GNUNET_PQ_result_spec_timestamp ("expire_deposit",
- &issue->expire_deposit),
- GNUNET_PQ_result_spec_timestamp ("expire_legal",
- &issue->expire_legal),
- TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
- &issue->value),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
- &issue->fees.withdraw),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- &issue->fees.deposit),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
- &issue->fees.refresh),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
- &issue->fees.refund),
- GNUNET_PQ_result_spec_uint32 ("age_mask",
- &issue->age_mask.bits),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "denomination_get_by_serial",
- "SELECT"
- " master_sig"
- ",denom_pub_hash"
- ",valid_from"
- ",expire_withdraw"
- ",expire_deposit"
- ",expire_legal"
- ",coin" /* value of this denom */
- ",fee_withdraw"
- ",fee_deposit"
- ",fee_refresh"
- ",fee_refund"
- ",age_mask"
- " FROM denominations"
- " WHERE denominations_serial=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "denomination_get_by_serial",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_denomination_info.c b/src/exchangedb/pg_get_denomination_info.c
@@ -1,96 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022,2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_denomination_info.c
- * @brief Implementation of the get_denomination_info function for Postgres
- * @author Christian Grothoff
- * @author Özgür Kesim
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_denomination_info.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_denomination_info (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_DenominationHashP *denom_pub_hash,
- uint64_t *denom_serial,
- struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
-{
- enum GNUNET_DB_QueryStatus qs;
- uint64_t serial;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("denominations_serial",
- &serial),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &issue->signature),
- GNUNET_PQ_result_spec_timestamp ("valid_from",
- &issue->start),
- GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
- &issue->expire_withdraw),
- GNUNET_PQ_result_spec_timestamp ("expire_deposit",
- &issue->expire_deposit),
- GNUNET_PQ_result_spec_timestamp ("expire_legal",
- &issue->expire_legal),
- TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
- &issue->value),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
- &issue->fees.withdraw),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- &issue->fees.deposit),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
- &issue->fees.refresh),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
- &issue->fees.refund),
- GNUNET_PQ_result_spec_uint32 ("age_mask",
- &issue->age_mask.bits),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "denomination_get",
- "SELECT"
- " denominations_serial"
- ",master_sig"
- ",valid_from"
- ",expire_withdraw"
- ",expire_deposit"
- ",expire_legal"
- ",coin" /* value of this denom */
- ",fee_withdraw"
- ",fee_deposit"
- ",fee_refresh"
- ",fee_refund"
- ",age_mask"
- " FROM denominations"
- " WHERE denom_pub_hash=$1;");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "denomination_get",
- params,
- rs);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- return qs;
- issue->denom_hash = *denom_pub_hash;
- if (NULL != denom_serial)
- *denom_serial = serial;
- return qs;
-}
diff --git a/src/exchangedb/pg_get_denomination_revocation.c b/src/exchangedb/pg_get_denomination_revocation.c
@@ -1,59 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_denomination_revocation.c
- * @brief Implementation of the get_denomination_revocation function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_denomination_revocation.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_denomination_revocation (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_DenominationHashP *denom_pub_hash,
- struct TALER_MasterSignatureP *master_sig,
- uint64_t *rowid)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- master_sig),
- GNUNET_PQ_result_spec_uint64 ("denom_revocations_serial_id",
- rowid),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "denomination_revocation_get",
- "SELECT"
- " master_sig"
- ",denom_revocations_serial_id"
- " FROM denomination_revocations"
- " WHERE denominations_serial="
- " (SELECT denominations_serial"
- " FROM denominations"
- " WHERE denom_pub_hash=$1);");
-
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "denomination_revocation_get",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_drain_profit.c b/src/exchangedb/pg_get_drain_profit.c
@@ -1,72 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_drain_profit.c
- * @brief Implementation of the get_drain_profit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_drain_profit.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_drain_profit (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- uint64_t *serial,
- char **account_section,
- struct TALER_FullPayto *payto_uri,
- struct GNUNET_TIME_Timestamp *request_timestamp,
- struct TALER_Amount *amount,
- struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("profit_drain_serial_id",
- serial),
- GNUNET_PQ_result_spec_string ("account_section",
- account_section),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri->full_payto),
- GNUNET_PQ_result_spec_timestamp ("trigger_date",
- request_timestamp),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- amount),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_profit_drain",
- "SELECT"
- " profit_drain_serial_id"
- ",account_section"
- ",payto_uri"
- ",trigger_date"
- ",amount"
- ",master_sig"
- " FROM profit_drains"
- " WHERE wtid=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_profit_drain",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_expired_reserves.c b/src/exchangedb/pg_get_expired_reserves.c
@@ -1,169 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_get_expired_reserves.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_expired_reserves.h"
-#include "helper.h"
-
-
-/**
- * Closure for #reserve_expired_cb().
- */
-struct ExpiredReserveContext
-{
- /**
- * Function to call for each expired reserve.
- */
- TALER_EXCHANGEDB_ReserveExpiredCallback rec;
-
- /**
- * Closure to give to @e rec.
- */
- void *rec_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on error.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-reserve_expired_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ExpiredReserveContext *erc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = erc->pg;
- enum GNUNET_GenericReturnValue ret = GNUNET_OK;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_TIME_Timestamp exp_date;
- struct TALER_FullPayto account_details;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_Amount remaining_balance;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("expiration_date",
- &exp_date),
- GNUNET_PQ_result_spec_string ("account_details",
- &account_details.full_payto),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- TALER_PQ_result_spec_amount ("current_balance",
- pg->currency,
- &remaining_balance),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ret = GNUNET_SYSERR;
- break;
- }
- ret = erc->rec (erc->rec_cls,
- &reserve_pub,
- &remaining_balance,
- account_details,
- exp_date,
- 0);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
- erc->status = ret;
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_expired_reserves (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct GNUNET_TIME_Timestamp now,
- TALER_EXCHANGEDB_ReserveExpiredCallback rec,
- void *rec_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&now),
- GNUNET_PQ_query_param_end
- };
- struct ExpiredReserveContext ectx = {
- .rec = rec,
- .rec_cls = rec_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "get_expired_reserves",
- "WITH ed AS MATERIALIZED ( "
- " SELECT expiration_date"
- " ,wire_source_h_payto"
- " ,current_balance"
- " ,r.reserve_pub"
- " FROM reserves r"
- " JOIN reserves_in"
- " USING (reserve_pub)"
- " WHERE expiration_date <= $1 "
- " AND ((current_balance).val != 0 OR (current_balance).frac != 0) "
- " ORDER BY expiration_date ASC "
- " LIMIT 1 "
- ") "
- "SELECT"
- " wt.payto_uri AS account_details"
- " ,ed.expiration_date"
- " ,ed.reserve_pub"
- " ,ed.current_balance"
- " FROM wire_targets wt"
- " JOIN ed"
- " ON (ed.wire_source_h_payto=wt.wire_target_h_payto);");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "get_expired_reserves",
- params,
- &reserve_expired_cb,
- &ectx);
- switch (ectx.status)
- {
- case GNUNET_SYSERR:
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_NO:
- return GNUNET_DB_STATUS_SOFT_ERROR;
- case GNUNET_OK:
- break;
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_get_extension_manifest.c b/src/exchangedb/pg_get_extension_manifest.c
@@ -1,64 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_extension_manifest.c
- * @brief Implementation of the get_extension_manifest function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_extension_manifest.h"
-#include "helper.h"
-
-/**
- * Function called to get the manifest of an extension
- * (age-restriction, policy_extension_...)
- *
- * @param pg the database context
- * @param extension_name the name of the extension
- * @param[out] manifest JSON object of the manifest as string
- * @return transaction status code
- */
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_extension_manifest (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- const char *extension_name,
- char **manifest)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (extension_name),
- GNUNET_PQ_query_param_end
- };
- bool is_null;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("manifest",
- manifest),
- &is_null),
- GNUNET_PQ_result_spec_end
- };
-
- *manifest = NULL;
- PREPARE (pg,
- "get_extension_manifest",
- "SELECT"
- " manifest"
- " FROM extensions"
- " WHERE name=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_extension_manifest",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_global_fee.c b/src/exchangedb/pg_get_global_fee.c
@@ -1,85 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_global_fee.c
- * @brief Implementation of the get_global_fee function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_dbevents.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_global_fee.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct GNUNET_TIME_Timestamp date,
- struct GNUNET_TIME_Timestamp *start_date,
- struct GNUNET_TIME_Timestamp *end_date,
- struct TALER_GlobalFeeSet *fees,
- struct GNUNET_TIME_Relative *purse_timeout,
- struct GNUNET_TIME_Relative *history_expiration
- ,
- uint32_t *purse_account_limit,
- struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&date),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("start_date",
- start_date),
- GNUNET_PQ_result_spec_timestamp ("end_date",
- end_date),
- TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
- &fees->history),
- TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
- &fees->account),
- TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
- &fees->purse),
- GNUNET_PQ_result_spec_relative_time ("purse_timeout",
- purse_timeout),
- GNUNET_PQ_result_spec_relative_time ("history_expiration",
- history_expiration),
- GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
- purse_account_limit),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_global_fee",
- "SELECT "
- " start_date"
- ",end_date"
- ",history_fee"
- ",account_fee"
- ",purse_fee"
- ",purse_timeout"
- ",history_expiration"
- ",purse_account_limit"
- ",master_sig"
- " FROM global_fee"
- " WHERE start_date <= $1"
- " AND end_date > $1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_global_fee",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_global_fees.c b/src/exchangedb/pg_get_global_fees.c
@@ -1,164 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_global_fees.c
- * @brief Implementation of the get_global_fees function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_dbevents.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_global_fees.h"
-#include "helper.h"
-
-
-/**
- * Closure for #global_fees_cb().
- */
-struct GlobalFeeContext
-{
- /**
- * Function to call for each global fee block.
- */
- TALER_EXCHANGEDB_GlobalFeeCallback cb;
-
- /**
- * Closure to give to @e rec.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on error.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-global_fees_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct GlobalFeeContext *gctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = gctx->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_GlobalFeeSet fees;
- struct GNUNET_TIME_Relative purse_timeout;
- struct GNUNET_TIME_Relative history_expiration;
- uint32_t purse_account_limit;
- struct GNUNET_TIME_Timestamp start_date;
- struct GNUNET_TIME_Timestamp end_date;
- struct TALER_MasterSignatureP master_sig;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("start_date",
- &start_date),
- GNUNET_PQ_result_spec_timestamp ("end_date",
- &end_date),
- TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
- &fees.history),
- TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
- &fees.account),
- TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
- &fees.purse),
- GNUNET_PQ_result_spec_relative_time ("purse_timeout",
- &purse_timeout),
- GNUNET_PQ_result_spec_relative_time ("history_expiration",
- &history_expiration),
- GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
- &purse_account_limit),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &master_sig),
- GNUNET_PQ_result_spec_end
- };
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- gctx->status = GNUNET_SYSERR;
- break;
- }
- gctx->cb (gctx->cb_cls,
- &fees,
- purse_timeout,
- history_expiration,
- purse_account_limit,
- start_date,
- end_date,
- &master_sig);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_get_global_fees (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- TALER_EXCHANGEDB_GlobalFeeCallback cb,
- void *cb_cls)
-{
- struct GNUNET_TIME_Timestamp date
- = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_subtract (
- GNUNET_TIME_absolute_get (),
- GNUNET_TIME_UNIT_YEARS));
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&date),
- GNUNET_PQ_query_param_end
- };
- struct GlobalFeeContext gctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
-
- PREPARE (pg,
- "get_global_fees",
- "SELECT "
- " start_date"
- ",end_date"
- ",history_fee"
- ",account_fee"
- ",purse_fee"
- ",purse_timeout"
- ",history_expiration"
- ",purse_account_limit"
- ",master_sig"
- " FROM global_fee"
- " WHERE start_date >= $1");
- return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "get_global_fees",
- params,
- &global_fees_cb,
- &gctx);
-}
diff --git a/src/exchangedb/pg_get_known_coin.c b/src/exchangedb/pg_get_known_coin.c
@@ -1,64 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_known_coin.c
- * @brief Implementation of the get_known_coin function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_known_coin.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_known_coin (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinSpendPublicKeyP *
- coin_pub,
- struct TALER_CoinPublicInfo *coin_info)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &coin_info->denom_pub_hash),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &coin_info->h_age_commitment),
- &coin_info->no_age_commitment),
- TALER_PQ_result_spec_denom_sig ("denom_sig",
- &coin_info->denom_sig),
- GNUNET_PQ_result_spec_end
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Getting known coin data for coin %s\n",
- TALER_B2S (coin_pub));
- coin_info->coin_pub = *coin_pub;
- PREPARE (pg,
- "get_known_coin",
- "SELECT"
- " denominations.denom_pub_hash"
- ",age_commitment_hash"
- ",denom_sig"
- " FROM known_coins"
- " JOIN denominations USING (denominations_serial)"
- " WHERE coin_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_known_coin",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_kyc_rules.c b/src/exchangedb/pg_get_kyc_rules.c
@@ -1,124 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_kyc_rules.c
- * @brief Implementation of the get_kyc_rules function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_kyc_rules.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_kyc_rules (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- bool *no_account_pub,
- union TALER_AccountPublicKeyP *account_pub,
- bool *no_reserve_pub,
- struct TALER_ReservePublicKeyP *reserve_pub,
- json_t **jrules)
-{
- struct GNUNET_TIME_Timestamp now
- = GNUNET_TIME_timestamp_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_timestamp (&now),
- NULL != merchant_pub
- ? GNUNET_PQ_query_param_auto_from_type (merchant_pub)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("target_pub",
- account_pub),
- no_account_pub),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- reserve_pub),
- no_reserve_pub),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("jnew_rules",
- jrules),
- NULL),
- GNUNET_PQ_result_spec_end
- };
-
- *jrules = NULL;
- *no_account_pub = true;
- *no_reserve_pub = true;
- memset (account_pub,
- 0,
- sizeof (*account_pub));
- memset (reserve_pub,
- 0,
- sizeof (*reserve_pub));
- PREPARE (pg,
- "get_kyc_rules",
- "SELECT"
- " out_target_pub AS target_pub"
- " ,out_jnew_rules::TEXT AS jnew_rules"
- " ,out_reserve_pub AS reserve_pub"
- " FROM exchange_do_get_kyc_rules ($1,$2,$3);");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "get_kyc_rules",
- params,
- rs);
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_get_kyc_rules2 (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- json_t **jrules)
-{
- struct GNUNET_TIME_Timestamp now
- = GNUNET_TIME_timestamp_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_timestamp (&now),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("jnew_rules",
- jrules),
- NULL),
- GNUNET_PQ_result_spec_end
- };
-
- *jrules = NULL;
- PREPARE (pg,
- "get_kyc_rules2",
- "SELECT"
- " jnew_rules::TEXT"
- " FROM legitimization_outcomes"
- " WHERE h_payto=$1"
- " AND expiration_time >= $2"
- " AND is_active"
- " ORDER BY expiration_time DESC"
- " LIMIT 1;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "get_kyc_rules2",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_old_coin_by_h_blind.c b/src/exchangedb/pg_get_old_coin_by_h_blind.c
@@ -1,60 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_old_coin_by_h_blind.c
- * @brief Implementation of the get_old_coin_by_h_blind function for Postgres
- * @author Christian Grothoff
- * @author Özgür Kesim
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_old_coin_by_h_blind.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_old_coin_by_h_blind (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_BlindedCoinHashP *h_blind_ev,
- struct TALER_CoinSpendPublicKeyP *old_coin_pub,
- uint64_t *refresh_id)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_blind_ev),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
- old_coin_pub),
- GNUNET_PQ_result_spec_uint64 ("refresh_id",
- refresh_id),
- GNUNET_PQ_result_spec_end
- };
-
- /* Used in #postgres_get_old_coin_by_h_blind() */
- PREPARE (pg,
- "old_coin_by_h_blind",
- "SELECT"
- " okc.coin_pub AS old_coin_pub"
- ",refresh_id"
- " FROM refresh "
- " JOIN known_coins okc ON (refresh.old_coin_pub = okc.coin_pub)"
- " WHERE $1=ANY(h_blind_evs)"
- " LIMIT 1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "old_coin_by_h_blind",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_pending_kyc_requirement_process.c b/src/exchangedb/pg_get_pending_kyc_requirement_process.c
@@ -1,62 +0,0 @@
-/*
- 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_pending_kyc_requirement_process.c
- * @brief Implementation of the get_pending_kyc_requirement_process function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_pending_kyc_requirement_process.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_pending_kyc_requirement_process (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const char *provider_name,
- char **redirect_url)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (provider_name),
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("redirect_url",
- redirect_url),
- NULL),
- GNUNET_PQ_result_spec_end
- };
-
- *redirect_url = NULL;
- PREPARE (pg,
- "get_pending_kyc_requirement_process",
- "SELECT"
- " redirect_url"
- " FROM legitimization_processes"
- " WHERE provider_name=$1"
- " AND h_payto=$2"
- " AND NOT finished"
- " ORDER BY start_time DESC"
- " LIMIT 1");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "get_pending_kyc_requirement_process",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_policy_details.c b/src/exchangedb/pg_get_policy_details.c
@@ -1,60 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_policy_details.c
- * @brief Implementation of the get_policy_details function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_policy_details.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_policy_details (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct GNUNET_HashCode *hc,
- struct TALER_PolicyDetails *details)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (hc),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("deadline",
- &details->deadline),
- TALER_PQ_RESULT_SPEC_AMOUNT ("commitment",
- &details->commitment),
- TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
- &details->accumulated_total),
- TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee",
- &details->policy_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount",
- &details->transferable_amount),
- GNUNET_PQ_result_spec_auto_from_type ("state",
- &details->fulfillment_state),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id",
- &details->policy_fulfillment_id),
- &details->no_policy_fulfillment_id),
- GNUNET_PQ_result_spec_end
- };
-
-
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_policy_details",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_purse_deposit.c b/src/exchangedb/pg_get_purse_deposit.c
@@ -1,80 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_purse_deposit.c
- * @brief Implementation of the get_purse_deposit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_purse_deposit.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_purse_deposit (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- struct TALER_Amount *amount,
- struct TALER_DenominationHashP *h_denom_pub,
- struct TALER_AgeCommitmentHashP *phac,
- struct TALER_CoinSpendSignatureP *coin_sig,
- char **partner_url)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_end
- };
- bool is_null;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- h_denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- phac),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- coin_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- amount),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("partner_base_url",
- partner_url),
- &is_null),
- GNUNET_PQ_result_spec_end
- };
-
- *partner_url = NULL;
- PREPARE (pg,
- "select_purse_deposit_by_coin_pub",
- "SELECT "
- " coin_sig"
- ",amount_with_fee"
- ",denom_pub_hash"
- ",age_commitment_hash"
- ",partner_base_url"
- " FROM purse_deposits"
- " LEFT JOIN partners"
- " USING (partner_serial_id)"
- " JOIN known_coins kc"
- " USING (coin_pub)"
- " JOIN denominations"
- " USING (denominations_serial)"
- " WHERE purse_pub=$1"
- " AND coin_pub=$2;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "select_purse_deposit_by_coin_pub",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_purse_request.c b/src/exchangedb/pg_get_purse_request.c
@@ -1,75 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_template.c
- * @brief Implementation of the template function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_purse_request.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_purse_request (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- struct TALER_PurseMergePublicKeyP *merge_pub,
- struct GNUNET_TIME_Timestamp *purse_expiration,
- struct TALER_PrivateContractHashP *h_contract_terms,
- uint32_t *age_limit,
- struct TALER_Amount *target_amount,
- struct TALER_Amount *balance,
- struct TALER_PurseContractSignatureP *purse_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("merge_pub",
- merge_pub),
- GNUNET_PQ_result_spec_timestamp ("purse_expiration",
- purse_expiration),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- h_contract_terms),
- GNUNET_PQ_result_spec_uint32 ("age_limit",
- age_limit),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- target_amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
- balance),
- GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
- purse_sig),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_purse_request",
- "SELECT "
- " merge_pub"
- ",purse_expiration"
- ",h_contract_terms"
- ",age_limit"
- ",amount_with_fee"
- ",balance"
- ",purse_sig"
- " FROM purse_requests"
- " WHERE purse_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_purse_request",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_ready_deposit.c b/src/exchangedb/pg_get_ready_deposit.c
@@ -1,78 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_ready_deposit.c
- * @brief Implementation of the get_ready_deposit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_ready_deposit.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_ready_deposit (struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t start_shard_row,
- uint64_t end_shard_row,
- struct TALER_MerchantPublicKeyP *
- merchant_pub,
- struct TALER_FullPayto *payto_uri,
- char **extra_wire_subject_metadata)
-{
- struct GNUNET_TIME_Absolute now
- = GNUNET_TIME_absolute_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_uint64 (&start_shard_row),
- GNUNET_PQ_query_param_uint64 (&end_shard_row),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
- merchant_pub),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri->full_payto),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("extra_wire_subject_metadata",
- extra_wire_subject_metadata),
- NULL),
- GNUNET_PQ_result_spec_end
- };
- const char *query = "deposits_get_ready";
-
- *extra_wire_subject_metadata = NULL;
- PREPARE (pg,
- query,
- "SELECT"
- " wts.payto_uri"
- ",bdep.merchant_pub"
- ",bdep.extra_wire_subject_metadata"
- " FROM batch_deposits bdep"
- " JOIN wire_targets wts"
- " USING (wire_target_h_payto)"
- " WHERE NOT (bdep.done OR bdep.policy_blocked)"
- " AND bdep.wire_deadline<=$1"
- " AND bdep.shard >= $2"
- " AND bdep.shard <= $3"
- " ORDER BY "
- " bdep.wire_deadline ASC"
- " ,bdep.shard ASC"
- " LIMIT 1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- query,
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_refresh.c b/src/exchangedb/pg_get_refresh.c
@@ -1,205 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_refresh.c
- * @brief Implementation of the get_refresh function for Postgres
- * @author get_refresh
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_refresh.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_RefreshCommitmentP *rc,
- struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh
- )
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (rc),
- GNUNET_PQ_query_param_end
- };
- bool no_cs_r_values;
- bool no_cs_r_choices;
- bool no_transfer_pubs;
- size_t num_denom_sigs;
- size_t num_transfer_pubs;
- struct TALER_BlindedDenominationSignature *denom_sigs = NULL;
- struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values = NULL;
- struct TALER_TransferPublicKeyP *transfer_pubs = NULL;
- uint64_t *denom_serials = NULL;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &refresh->amount_with_fee),
- GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
- &refresh->coin.coin_pub),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &refresh->coin.h_age_commitment),
- &refresh->coin.no_age_commitment),
- GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
- &refresh->coin_sig),
- GNUNET_PQ_result_spec_auto_from_type ("refresh_seed",
- &refresh->refresh_seed),
- GNUNET_PQ_result_spec_uint32 ("noreveal_index",
- &refresh->noreveal_index),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
- &refresh->blinding_seed),
- &refresh->no_blinding_seed),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_array_cs_r_pub (pg->conn,
- "cs_r_values",
- &refresh->num_cs_r_values,
- &cs_r_values),
- &no_cs_r_values),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 ("cs_r_choices",
- &refresh->cs_r_choices),
- &no_cs_r_choices),
- GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
- &refresh->planchets_h),
- GNUNET_PQ_result_spec_auto_from_type ("selected_h",
- &refresh->selected_h),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_array_fixed_size (pg->conn,
- "transfer_pubs",
- sizeof(*transfer_pubs),
- &num_transfer_pubs,
- (void **) &transfer_pubs),
- &no_transfer_pubs),
- GNUNET_PQ_result_spec_array_uint64 (pg->conn,
- "denom_serials",
- &refresh->num_coins,
- &denom_serials),
- TALER_PQ_result_spec_array_blinded_denom_sig (pg->conn,
- "denom_sigs",
- &num_denom_sigs,
- &denom_sigs),
- GNUNET_PQ_result_spec_bool ("revealed",
- &refresh->revealed),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- memset (&refresh->coin.denom_sig,
- 0,
- sizeof (refresh->coin.denom_sig));
- PREPARE (pg,
- "get_refresh",
- "SELECT"
- " amount_with_fee"
- ",old_coin_pub"
- ",kc.age_commitment_hash AS age_commitment_hash"
- ",old_coin_sig"
- ",refresh_seed"
- ",noreveal_index"
- ",blinding_seed"
- ",cs_r_values"
- ",cs_r_choices"
- ",planchets_h"
- ",transfer_pubs"
- ",selected_h"
- ",denom_serials"
- ",denom_sigs"
- ",revealed"
- " FROM refresh"
- " JOIN known_coins kc"
- " ON (old_coin_pub = kc.coin_pub)"
- " WHERE rc = $1;"
- );
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_refresh",
- params,
- rs);
- GNUNET_PQ_cleanup_query_params_closures (params);
- if (0 > qs)
- {
- GNUNET_break (0);
- GNUNET_PQ_cleanup_result (rs);
- return qs;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- GNUNET_PQ_cleanup_result (rs);
- return qs;
- }
- if (refresh->num_coins != num_denom_sigs)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "got inconsistent number of entries in refresh from DB: "
- "num_coins=%ld, num_denom_sigs=%ld\n",
- refresh->num_coins,
- num_denom_sigs);
- GNUNET_PQ_cleanup_result (rs);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (no_transfer_pubs)
- {
- refresh->is_v27_refresh = true;
- refresh->transfer_pubs = NULL;
- }
- else
- {
- if (num_transfer_pubs != refresh->num_coins)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "got inconsistent number of transfer_pubs in refresh from DB: "
- "num_coins=%ld, num_transfer_pubs=%ld\n",
- refresh->num_coins,
- num_transfer_pubs);
- GNUNET_PQ_cleanup_result (rs);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- refresh->is_v27_refresh = false;
- refresh->transfer_pubs = transfer_pubs;
- }
- if (refresh->no_blinding_seed != no_cs_r_values)
- {
- GNUNET_break (0);
- GNUNET_PQ_cleanup_result (rs);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (no_cs_r_choices != no_cs_r_values)
- {
- GNUNET_break (0);
- GNUNET_PQ_cleanup_result (rs);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (no_cs_r_values)
- {
- refresh->cs_r_values = NULL;
- refresh->num_cs_r_values = 0;
- }
- if (refresh->coin.no_age_commitment)
- memset (&refresh->coin.h_age_commitment,
- 0,
- sizeof(refresh->coin.h_age_commitment));
- refresh->rc = *rc;
- /* move the result arrays */
- refresh->denom_sigs = denom_sigs;
- refresh->denom_serials = denom_serials;
- refresh->cs_r_values = cs_r_values;
- transfer_pubs = NULL;
- denom_sigs = NULL;
- denom_serials = NULL;
- cs_r_values = NULL;
- GNUNET_PQ_cleanup_result (rs);
- return qs;
-}
diff --git a/src/exchangedb/pg_get_reserve_balance.c b/src/exchangedb/pg_get_reserve_balance.c
@@ -1,65 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_reserve_balance.c
- * @brief Implementation of the get_reserve_balance function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_reserve_balance.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_reserve_balance (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- struct TALER_Amount *balance,
- struct TALER_FullPayto *origin_account)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_amount ("current_balance",
- pg->currency,
- balance),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("payto_uri",
- &origin_account->full_payto),
- NULL),
- GNUNET_PQ_result_spec_end
- };
-
- origin_account->full_payto = NULL;
- PREPARE (pg,
- "get_reserve_balance",
- "SELECT"
- " r.current_balance"
- " ,wt.payto_uri"
- " FROM reserves r"
- " LEFT JOIN reserves_in ri"
- " USING (reserve_pub)"
- " LEFT JOIN wire_targets wt"
- " ON (wt.wire_target_h_payto = ri.wire_source_h_payto)"
- " WHERE r.reserve_pub=$1"
- " LIMIT 1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_reserve_balance",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_reserve_by_h_planchets.c b/src/exchangedb/pg_get_reserve_by_h_planchets.c
@@ -1,58 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022,2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_reserve_by_h_planchets.c
- * @brief Implementation of the get_reserve_by_h_planchets function for Postgres
- * @author Christian Grothoff
- * @author Özgür Kesim
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_reserve_by_h_planchets.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_reserve_by_h_planchets (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_HashBlindedPlanchetsP *h_planchets,
- struct TALER_ReservePublicKeyP *reserve_pub,
- uint64_t *withdraw_serial_id)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_planchets),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- reserve_pub),
- GNUNET_PQ_result_spec_uint64 ("withdraw_id",
- withdraw_serial_id),
- GNUNET_PQ_result_spec_end
- };
- /* Used in #postgres_get_reserve_by_h_planchets() */
- PREPARE (pg,
- "reserve_by_h_planchets",
- "SELECT"
- " reserve_pub"
- ",withdraw_id"
- " FROM withdraw"
- " WHERE planchets_h=$1"
- " LIMIT 1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "reserve_by_h_planchets",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_reserve_history.c b/src/exchangedb/pg_get_reserve_history.c
@@ -1,994 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_get_reserve_history.c
- * @brief Obtain (parts of) the history of a reserve.
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_reserve_history.h"
-#include "taler/exchange-database/start_read_committed.h"
-#include "taler/exchange-database/commit.h"
-#include "taler/exchange-database/rollback.h"
-#include "helper.h"
-
-/**
- * How often do we re-try when encountering DB serialization issues?
- * (We are read-only, so can only happen due to concurrent insert,
- * which should be very rare.)
- */
-#define RETRIES 3
-
-
-/**
- * Closure for callbacks invoked via #TALER_EXCHANGEDB_get_reserve_history().
- */
-struct ReserveHistoryContext
-{
-
- /**
- * Which reserve are we building the history for?
- */
- const struct TALER_ReservePublicKeyP *reserve_pub;
-
- /**
- * Where we build the history.
- */
- struct TALER_EXCHANGEDB_ReserveHistory *rh;
-
- /**
- * Tail of @e rh list.
- */
- struct TALER_EXCHANGEDB_ReserveHistory *rh_tail;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Sum of all credit transactions.
- */
- struct TALER_Amount balance_in;
-
- /**
- * Sum of all debit transactions.
- */
- struct TALER_Amount balance_out;
-
- /**
- * Current reserve_history_serial_id being processed,
- * set before each sub-table callback.
- */
- uint64_t current_history_offset;
-
- /**
- * Set to true on serious internal errors during
- * the callbacks.
- */
- bool failed;
-};
-
-
-/**
- * Append and return a fresh element to the reserve
- * history kept in @a rhc.
- *
- * @param rhc where the history is kept
- * @return the fresh element that was added
- */
-static struct TALER_EXCHANGEDB_ReserveHistory *
-append_rh (struct ReserveHistoryContext *rhc)
-{
- struct TALER_EXCHANGEDB_ReserveHistory *tail;
-
- tail = GNUNET_new (struct TALER_EXCHANGEDB_ReserveHistory);
- tail->history_offset = rhc->current_history_offset;
- if (NULL != rhc->rh_tail)
- {
- rhc->rh_tail->next = tail;
- rhc->rh_tail = tail;
- }
- else
- {
- rhc->rh_tail = tail;
- rhc->rh = tail;
- }
- return tail;
-}
-
-
-/**
- * Add bank transfers to result set for #TALER_EXCHANGEDB_get_reserve_history.
- *
- * @param cls a `struct ReserveHistoryContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-add_bank_to_exchange (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReserveHistoryContext *rhc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
-
- while (0 < num_results)
- {
- struct TALER_EXCHANGEDB_BankTransfer *bt;
- struct TALER_EXCHANGEDB_ReserveHistory *tail;
-
- bt = GNUNET_new (struct TALER_EXCHANGEDB_BankTransfer);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("wire_reference",
- &bt->wire_reference),
- TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
- &bt->amount),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- &bt->execution_date),
- GNUNET_PQ_result_spec_string ("sender_account_details",
- &bt->sender_account_details.full_payto),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- --num_results))
- {
- GNUNET_break (0);
- GNUNET_free (bt);
- rhc->failed = true;
- return;
- }
- }
- GNUNET_assert (0 <=
- TALER_amount_add (&rhc->balance_in,
- &rhc->balance_in,
- &bt->amount));
- bt->reserve_pub = *rhc->reserve_pub;
- tail = append_rh (rhc);
- tail->type = TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE;
- tail->details.bank = bt;
- } /* end of 'while (0 < rows)' */
-}
-
-
-/**
- * Add coin withdrawals to result set for #TALER_EXCHANGEDB_get_reserve_history.
- *
- * @param cls a `struct ReserveHistoryContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-add_withdraw (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReserveHistoryContext *rhc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
-
- while (0 < num_results)
- {
- struct TALER_EXCHANGEDB_Withdraw *wd;
- struct TALER_EXCHANGEDB_ReserveHistory *tail;
-
- wd = GNUNET_new (struct TALER_EXCHANGEDB_Withdraw);
- {
- bool no_noreveal_index;
- bool no_max_age;
- bool no_selected_h;
- size_t num_denom_hs;
- size_t num_denom_serials;
- uint64_t *my_denom_serials = NULL;
- struct TALER_DenominationHashP *my_denom_pub_hashes = NULL;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
- &wd->planchets_h),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &wd->reserve_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &wd->amount_with_fee),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint16 ("max_age",
- &wd->max_age),
- &no_max_age),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint16 ("noreveal_index",
- &wd->noreveal_index),
- &no_noreveal_index),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
- &wd->blinding_seed),
- &wd->no_blinding_seed),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("selected_h",
- &wd->selected_h),
- &no_selected_h),
- TALER_PQ_result_spec_array_denom_hash (pg->conn,
- "denom_pub_hashes",
- &num_denom_hs,
- &my_denom_pub_hashes),
- GNUNET_PQ_result_spec_array_uint64 (pg->conn,
- "denom_serials",
- &num_denom_serials,
- &my_denom_serials),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- --num_results))
- {
- GNUNET_break (0);
- GNUNET_free (wd);
- rhc->failed = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
-
- if (num_denom_hs != num_denom_serials)
- {
- GNUNET_break (0);
- GNUNET_free (wd);
- rhc->failed = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
-
- if ((no_noreveal_index != no_max_age) ||
- (no_noreveal_index != no_selected_h))
- {
- GNUNET_break (0);
- GNUNET_free (wd);
- rhc->failed = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- wd->age_proof_required = ! no_max_age;
- wd->num_coins = num_denom_serials;
- wd->reserve_pub = *rhc->reserve_pub;
- wd->denom_serials = my_denom_serials;
- wd->denom_pub_hashes = my_denom_pub_hashes;
- /* prevent cleanup from destroying our actual result */
- my_denom_serials = NULL;
- my_denom_pub_hashes = NULL;
- GNUNET_PQ_cleanup_result (rs);
- }
-
- tail = append_rh (rhc);
- tail->type = TALER_EXCHANGEDB_RO_WITHDRAW_COINS;
- tail->details.withdraw = wd;
- }
-}
-
-
-/**
- * Add recoups to result set for #TALER_EXCHANGEDB_get_reserve_history.
- *
- * @param cls a `struct ReserveHistoryContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-add_recoup (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReserveHistoryContext *rhc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
-
- while (0 < num_results)
- {
- struct TALER_EXCHANGEDB_Recoup *recoup;
- struct TALER_EXCHANGEDB_ReserveHistory *tail;
-
- recoup = GNUNET_new (struct TALER_EXCHANGEDB_Recoup);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &recoup->value),
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &recoup->coin.coin_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
- &recoup->coin_blind),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &recoup->coin_sig),
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- &recoup->timestamp),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &recoup->coin.denom_pub_hash),
- TALER_PQ_result_spec_denom_sig (
- "denom_sig",
- &recoup->coin.denom_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- --num_results))
- {
- GNUNET_break (0);
- GNUNET_free (recoup);
- rhc->failed = true;
- return;
- }
- }
- GNUNET_assert (0 <=
- TALER_amount_add (&rhc->balance_in,
- &rhc->balance_in,
- &recoup->value));
- recoup->reserve_pub = *rhc->reserve_pub;
- tail = append_rh (rhc);
- tail->type = TALER_EXCHANGEDB_RO_RECOUP_COIN;
- tail->details.recoup = recoup;
- } /* end of 'while (0 < rows)' */
-}
-
-
-/**
- * Add exchange-to-bank transfers to result set for
- * #TALER_EXCHANGEDB_get_reserve_history.
- *
- * @param cls a `struct ReserveHistoryContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-add_exchange_to_bank (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReserveHistoryContext *rhc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
-
- while (0 < num_results)
- {
- struct TALER_EXCHANGEDB_ClosingTransfer *closing;
- struct TALER_EXCHANGEDB_ReserveHistory *tail;
-
- closing = GNUNET_new (struct TALER_EXCHANGEDB_ClosingTransfer);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &closing->amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
- &closing->closing_fee),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- &closing->execution_date),
- GNUNET_PQ_result_spec_string ("receiver_account",
- &closing->receiver_account_details.
- full_payto),
- GNUNET_PQ_result_spec_auto_from_type ("wtid",
- &closing->wtid),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- --num_results))
- {
- GNUNET_break (0);
- GNUNET_free (closing);
- rhc->failed = true;
- return;
- }
- }
- GNUNET_assert (0 <=
- TALER_amount_add (&rhc->balance_out,
- &rhc->balance_out,
- &closing->amount));
- closing->reserve_pub = *rhc->reserve_pub;
- tail = append_rh (rhc);
- tail->type = TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK;
- tail->details.closing = closing;
- } /* end of 'while (0 < rows)' */
-}
-
-
-/**
- * Add purse merge transfers to result set for
- * #TALER_EXCHANGEDB_get_reserve_history.
- *
- * @param cls a `struct ReserveHistoryContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-add_p2p_merge (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReserveHistoryContext *rhc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
-
- while (0 < num_results)
- {
- struct TALER_EXCHANGEDB_PurseMerge *merge;
- struct TALER_EXCHANGEDB_ReserveHistory *tail;
-
- merge = GNUNET_new (struct TALER_EXCHANGEDB_PurseMerge);
- {
- uint32_t flags32;
- struct TALER_Amount balance;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
- &merge->purse_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
- &balance),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &merge->amount_with_fee),
- GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
- &merge->merge_timestamp),
- GNUNET_PQ_result_spec_timestamp ("purse_expiration",
- &merge->purse_expiration),
- GNUNET_PQ_result_spec_uint32 ("age_limit",
- &merge->min_age),
- GNUNET_PQ_result_spec_uint32 ("flags",
- &flags32),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- &merge->h_contract_terms),
- GNUNET_PQ_result_spec_auto_from_type ("merge_pub",
- &merge->merge_pub),
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &merge->purse_pub),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &merge->reserve_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- --num_results))
- {
- GNUNET_break (0);
- GNUNET_free (merge);
- rhc->failed = true;
- return;
- }
- merge->flags = (enum TALER_WalletAccountMergeFlags) flags32;
- if ( (! GNUNET_TIME_absolute_is_future (
- merge->merge_timestamp.abs_time)) &&
- (-1 != TALER_amount_cmp (&balance,
- &merge->amount_with_fee)) )
- merge->merged = true;
- }
- if (merge->merged)
- GNUNET_assert (0 <=
- TALER_amount_add (&rhc->balance_in,
- &rhc->balance_in,
- &merge->amount_with_fee));
- GNUNET_assert (0 <=
- TALER_amount_add (&rhc->balance_out,
- &rhc->balance_out,
- &merge->purse_fee));
- merge->reserve_pub = *rhc->reserve_pub;
- tail = append_rh (rhc);
- tail->type = TALER_EXCHANGEDB_RO_PURSE_MERGE;
- tail->details.merge = merge;
- }
-}
-
-
-/**
- * Add paid for history requests to result set for
- * #TALER_EXCHANGEDB_get_reserve_history.
- *
- * @param cls a `struct ReserveHistoryContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-add_open_requests (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReserveHistoryContext *rhc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rhc->pg;
-
- while (0 < num_results)
- {
- struct TALER_EXCHANGEDB_OpenRequest *orq;
- struct TALER_EXCHANGEDB_ReserveHistory *tail;
-
- orq = GNUNET_new (struct TALER_EXCHANGEDB_OpenRequest);
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("open_fee",
- &orq->open_fee),
- GNUNET_PQ_result_spec_timestamp ("request_timestamp",
- &orq->request_timestamp),
- GNUNET_PQ_result_spec_timestamp ("expiration_date",
- &orq->reserve_expiration),
- GNUNET_PQ_result_spec_uint32 ("requested_purse_limit",
- &orq->purse_limit),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &orq->reserve_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- --num_results))
- {
- GNUNET_break (0);
- GNUNET_free (orq);
- rhc->failed = true;
- return;
- }
- }
- GNUNET_assert (0 <=
- TALER_amount_add (&rhc->balance_out,
- &rhc->balance_out,
- &orq->open_fee));
- orq->reserve_pub = *rhc->reserve_pub;
- tail = append_rh (rhc);
- tail->type = TALER_EXCHANGEDB_RO_OPEN_REQUEST;
- tail->details.open_request = orq;
- }
-}
-
-
-/**
- * Add paid for history requests to result set for
- * #TALER_EXCHANGEDB_get_reserve_history.
- *
- * @param cls a `struct ReserveHistoryContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-add_close_requests (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReserveHistoryContext *rhc = cls;
-
- while (0 < num_results)
- {
- struct TALER_EXCHANGEDB_CloseRequest *crq;
- struct TALER_EXCHANGEDB_ReserveHistory *tail;
-
- crq = GNUNET_new (struct TALER_EXCHANGEDB_CloseRequest);
- {
- struct TALER_FullPayto payto_uri;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("close_timestamp",
- &crq->request_timestamp),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri.full_payto),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &crq->reserve_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- --num_results))
- {
- GNUNET_break (0);
- GNUNET_free (crq);
- rhc->failed = true;
- return;
- }
- TALER_full_payto_hash (payto_uri,
- &crq->target_account_h_payto);
- GNUNET_free (payto_uri.full_payto);
- }
- crq->reserve_pub = *rhc->reserve_pub;
- tail = append_rh (rhc);
- tail->type = TALER_EXCHANGEDB_RO_CLOSE_REQUEST;
- tail->details.close_request = crq;
- }
-}
-
-
-/**
- * Add reserve history entries found.
- *
- * @param cls a `struct ReserveHistoryContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-handle_history_entry (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- static const struct
- {
- /**
- * Table with reserve history entry we are responsible for.
- */
- const char *table;
- /**
- * Name of the prepared statement to run.
- */
- const char *statement;
- /**
- * Function to use to process the results.
- */
- GNUNET_PQ_PostgresResultHandler cb;
- } work[] = {
- /** #TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE */
- { "reserves_in",
- "reserves_in_get_transactions",
- add_bank_to_exchange },
- /** #TALER_EXCHANGEDB_RO_WITHDRAW_COINS */
- { "withdraw",
- "get_withdraw_details",
- &add_withdraw },
- /** #TALER_EXCHANGEDB_RO_RECOUP_COIN */
- { "recoup",
- "recoup_by_reserve",
- &add_recoup },
- /** #TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK */
- { "reserves_close",
- "close_by_reserve",
- &add_exchange_to_bank },
- /** #TALER_EXCHANGEDB_RO_PURSE_MERGE */
- { "purse_decision",
- "merge_by_reserve",
- &add_p2p_merge },
- /** #TALER_EXCHANGEDB_RO_OPEN_REQUEST */
- { "reserves_open_requests",
- "open_request_by_reserve",
- &add_open_requests },
- /** #TALER_EXCHANGEDB_RO_CLOSE_REQUEST */
- { "close_requests",
- "close_request_by_reserve",
- &add_close_requests },
- /* List terminator */
- { NULL, NULL, NULL }
- };
- struct ReserveHistoryContext *rhc = cls;
- char *table_name;
- uint64_t serial_id;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("table_name",
- &table_name),
- GNUNET_PQ_result_spec_uint64 ("serial_id",
- &serial_id),
- GNUNET_PQ_result_spec_uint64 ("reserve_history_serial_id",
- &rhc->current_history_offset),
- GNUNET_PQ_result_spec_end
- };
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (rhc->reserve_pub),
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
-
- while (0 < num_results--)
- {
- enum GNUNET_DB_QueryStatus qs;
- bool found = false;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- num_results))
- {
- GNUNET_break (0);
- rhc->failed = true;
- return;
- }
-
- for (unsigned int i = 0;
- NULL != work[i].cb;
- i++)
- {
- if (0 != strcmp (table_name,
- work[i].table))
- continue;
- found = true;
- qs = GNUNET_PQ_eval_prepared_multi_select (rhc->pg->conn,
- work[i].statement,
- params,
- work[i].cb,
- rhc);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Reserve %s had %d transactions at %llu in table %s\n",
- TALER_B2S (rhc->reserve_pub),
- (int) qs,
- (unsigned long long) serial_id,
- table_name);
- if (0 >= qs)
- rhc->failed = true;
- break;
- }
- if (! found)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Reserve history includes unsupported table `%s`\n",
- table_name);
- rhc->failed = true;
- }
- GNUNET_PQ_cleanup_result (rs);
- if (rhc->failed)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_reserve_history (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- uint64_t start_off,
- uint64_t etag_in,
- uint64_t *etag_out,
- struct TALER_Amount *balance,
- struct TALER_EXCHANGEDB_ReserveHistory **rhp)
-{
- struct ReserveHistoryContext rhc = {
- .pg = pg,
- .reserve_pub = reserve_pub
- };
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_QueryParam lparams[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_uint64 (&start_off),
- GNUNET_PQ_query_param_end
- };
-
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (pg->currency,
- &rhc.balance_in));
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (pg->currency,
- &rhc.balance_out));
-
- *rhp = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Getting transactions for reserve %s\n",
- TALER_B2S (reserve_pub));
- PREPARE (pg,
- "get_reserve_history_etag",
- "SELECT"
- " his.reserve_history_serial_id"
- ",r.current_balance"
- " FROM reserve_history his"
- " JOIN reserves r USING (reserve_pub)"
- " WHERE his.reserve_pub=$1"
- " ORDER BY reserve_history_serial_id DESC"
- " LIMIT 1;");
- PREPARE (pg,
- "get_reserve_history",
- "SELECT"
- " table_name"
- ",serial_id"
- ",reserve_history_serial_id"
- " FROM reserve_history"
- " WHERE reserve_pub=$1"
- " AND reserve_history_serial_id > $2"
- " ORDER BY reserve_history_serial_id DESC;");
- PREPARE (pg,
- "reserves_in_get_transactions",
- "SELECT"
- " ri.wire_reference"
- ",ri.credit"
- ",ri.execution_date"
- ",wt.payto_uri AS sender_account_details"
- " FROM reserves_in ri"
- " JOIN wire_targets wt"
- " ON (wire_source_h_payto = wire_target_h_payto)"
- " WHERE ri.reserve_pub=$1"
- " AND ri.reserve_in_serial_id=$2;");
- PREPARE (pg,
- "get_withdraw_details",
- "SELECT"
- " planchets_h"
- ",amount_with_fee"
- ",reserve_sig"
- ",max_age"
- ",noreveal_index"
- ",selected_h"
- ",blinding_seed"
- ",denom_serials"
- ",ARRAY("
- " SELECT denominations.denom_pub_hash FROM ("
- " SELECT UNNEST(denom_serials) AS id,"
- " generate_subscripts(denom_serials, 1) AS nr" /* for order */
- " ) AS denoms"
- " LEFT JOIN denominations ON denominations.denominations_serial=denoms.id"
- ") AS denom_pub_hashes"
- " FROM withdraw "
- " WHERE withdraw_id=$2"
- " AND reserve_pub=$1;");
- PREPARE (pg,
- "recoup_by_reserve",
- "SELECT"
- " rec.coin_pub"
- ",rec.coin_sig"
- ",rec.coin_blind"
- ",rec.amount"
- ",rec.recoup_timestamp"
- ",denom.denom_pub_hash"
- ",kc.denom_sig"
- " FROM recoup rec"
- " JOIN withdraw ro"
- " USING (withdraw_id)"
- " JOIN reserves res"
- " USING (reserve_pub)"
- " JOIN known_coins kc"
- " USING (coin_pub)"
- " JOIN denominations denom"
- " ON (denom.denominations_serial = kc.denominations_serial)"
- " WHERE rec.recoup_uuid=$2"
- " AND res.reserve_pub=$1;");
- PREPARE (pg,
- "close_by_reserve",
- "SELECT"
- " rc.amount"
- ",rc.closing_fee"
- ",rc.execution_date"
- ",wt.payto_uri AS receiver_account"
- ",rc.wtid"
- " FROM reserves_close rc"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " WHERE reserve_pub=$1"
- " AND close_uuid=$2;");
- PREPARE (pg,
- "merge_by_reserve",
- "SELECT"
- " pr.amount_with_fee"
- ",pr.balance"
- ",pr.purse_fee"
- ",pr.h_contract_terms"
- ",pr.merge_pub"
- ",am.reserve_sig"
- ",pm.purse_pub"
- ",pm.merge_timestamp"
- ",pr.purse_expiration"
- ",pr.age_limit"
- ",pr.flags"
- " FROM purse_decision pdes"
- " JOIN purse_requests pr"
- " ON (pr.purse_pub = pdes.purse_pub)"
- " JOIN purse_merges pm"
- " ON (pm.purse_pub = pdes.purse_pub)"
- " JOIN account_merges am"
- " ON (am.purse_pub = pm.purse_pub AND"
- " am.reserve_pub = pm.reserve_pub)"
- " WHERE pdes.purse_decision_serial_id=$2"
- " AND pm.reserve_pub=$1"
- " AND COALESCE(pm.partner_serial_id,0)=0" /* must be local! */
- " AND NOT pdes.refunded;");
- PREPARE (pg,
- "open_request_by_reserve",
- "SELECT"
- " reserve_payment"
- ",request_timestamp"
- ",expiration_date"
- ",requested_purse_limit"
- ",reserve_sig"
- " FROM reserves_open_requests"
- " WHERE reserve_pub=$1"
- " AND open_request_uuid=$2;");
- PREPARE (pg,
- "close_request_by_reserve",
- "SELECT"
- " close_timestamp"
- ",payto_uri"
- ",reserve_sig"
- " FROM close_requests"
- " WHERE reserve_pub=$1"
- " AND close_request_serial_id=$2;");
-
- for (unsigned int i = 0; i<RETRIES; i++)
- {
- enum GNUNET_DB_QueryStatus qs;
- uint64_t end;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("reserve_history_serial_id",
- &end),
- TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
- balance),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- TALER_TALER_EXCHANGEDB_start_read_committed (pg,
- "get-reserve-transactions")
- )
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- /* First only check the last item, to see if
- we even need to iterate */
- qs = GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "get_reserve_history_etag",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- *etag_out = end;
- if (end == etag_in)
- return qs;
- }
- /* We indeed need to iterate over the history */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Current ETag for reserve %s is %llu\n",
- TALER_B2S (reserve_pub),
- (unsigned long long) end);
-
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "get_reserve_history",
- lparams,
- &handle_history_entry,
- &rhc);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- TALER_EXCHANGEDB_rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TALER_EXCHANGEDB_rollback (pg);
- continue;
- default:
- break;
- }
- if (rhc.failed)
- {
- TALER_EXCHANGEDB_rollback (pg);
- TALER_EXCHANGEDB_free_reserve_history (rhc.rh);
- return GNUNET_DB_STATUS_SOFT_ERROR;
- }
- qs = TALER_EXCHANGEDB_commit (pg);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- TALER_EXCHANGEDB_free_reserve_history (rhc.rh);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- TALER_EXCHANGEDB_free_reserve_history (rhc.rh);
- rhc.rh = NULL;
- continue;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- *rhp = rhc.rh;
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
- }
- return GNUNET_DB_STATUS_SOFT_ERROR;
-}
diff --git a/src/exchangedb/pg_get_signature_for_known_coin.c b/src/exchangedb/pg_get_signature_for_known_coin.c
@@ -1,59 +0,0 @@
-/*
- 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_signature_for_known_coin.c
- * @brief Implementation of the get_signature_for_known_coin function for Postgres
- * @author Özgür Kesim
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_signature_for_known_coin.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_signature_for_known_coin (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- struct TALER_DenominationPublicKey *denom_pub,
- struct TALER_DenominationSignature *denom_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- denom_pub),
- TALER_PQ_result_spec_denom_sig ("denom_sig",
- denom_sig),
- GNUNET_PQ_result_spec_end
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Getting denomination and signature for (potentially) known coin %s\n",
- TALER_B2S (coin_pub));
- PREPARE (pg,
- "get_signature_for_known_coin",
- "SELECT"
- " denominations.denom_pub"
- ",denom_sig"
- " FROM known_coins"
- " JOIN denominations USING (denominations_serial)"
- " WHERE coin_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_signature_for_known_coin",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_unfinished_close_requests.c b/src/exchangedb/pg_get_unfinished_close_requests.c
@@ -1,162 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_get_unfinished_close_requests.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_unfinished_close_requests.h"
-#include "helper.h"
-
-
-/**
- * Closure for #reserve_close_cb().
- */
-struct CloseReserveContext
-{
- /**
- * Function to call for each to be closed reserve.
- */
- TALER_EXCHANGEDB_ReserveExpiredCallback rec;
-
- /**
- * Closure to give to @e rec.
- */
- void *rec_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on error.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-reserve_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CloseReserveContext *erc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = erc->pg;
- enum GNUNET_GenericReturnValue ret = GNUNET_OK;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_TIME_Timestamp exp_date;
- struct TALER_FullPayto account_details;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_Amount remaining_balance;
- uint64_t close_request_row;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("expiration_date",
- &exp_date),
- GNUNET_PQ_result_spec_string ("account_details",
- &account_details.full_payto),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- TALER_PQ_RESULT_SPEC_AMOUNT ("close",
- &remaining_balance),
- GNUNET_PQ_result_spec_uint64 ("close_request_serial_id",
- &close_request_row),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ret = GNUNET_SYSERR;
- break;
- }
- ret = erc->rec (erc->rec_cls,
- &reserve_pub,
- &remaining_balance,
- account_details,
- exp_date,
- close_request_row);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
- erc->status = ret;
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_unfinished_close_requests (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- TALER_EXCHANGEDB_ReserveExpiredCallback rec,
- void *rec_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_end
- };
- struct CloseReserveContext ectx = {
- .rec = rec,
- .rec_cls = rec_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "get_unfinished_close_requests",
- "UPDATE close_requests AS rc"
- " SET done=TRUE"
- " WHERE NOT done"
- " RETURNING"
- " reserve_pub"
- " ,close_request_serial_id"
- " ,close_timestamp AS expiration_date"
- " ,close"
- " ,(SELECT payto_uri"
- " FROM reserves_in ri"
- " JOIN wire_targets wt"
- " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)"
- " WHERE ri.reserve_pub=rc.reserve_pub)"
- " AS account_details;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "get_unfinished_close_requests",
- params,
- &reserve_cb,
- &ectx);
- switch (ectx.status)
- {
- case GNUNET_SYSERR:
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_NO:
- return GNUNET_DB_STATUS_SOFT_ERROR;
- case GNUNET_OK:
- break;
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_get_wire_accounts.c b/src/exchangedb/pg_get_wire_accounts.c
@@ -1,179 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_wire_accounts.c
- * @brief Implementation of the get_wire_accounts function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_wire_accounts.h"
-#include "helper.h"
-
-
-/**
- * Closure for #get_wire_accounts_cb().
- */
-struct GetWireAccountsContext
-{
- /**
- * Function to call per result.
- */
- TALER_EXCHANGEDB_WireAccountCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Flag set to #GNUNET_OK as long as everything is fine.
- */
- enum GNUNET_GenericReturnValue status;
-
-};
-
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct MissingWireContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-get_wire_accounts_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct GetWireAccountsContext *ctx = cls;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct TALER_FullPayto payto_uri;
- char *conversion_url = NULL;
- char *open_banking_gateway = NULL;
- char *wire_transfer_gateway = NULL;
- json_t *debit_restrictions = NULL;
- json_t *credit_restrictions = NULL;
- struct TALER_MasterSignatureP master_sig;
- char *bank_label = NULL;
- int64_t priority;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri.full_payto),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("conversion_url",
- &conversion_url),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("open_banking_gateway",
- &open_banking_gateway),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("wire_transfer_gateway",
- &wire_transfer_gateway),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("bank_label",
- &bank_label),
- NULL),
- GNUNET_PQ_result_spec_int64 ("priority",
- &priority),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("debit_restrictions",
- &debit_restrictions),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("credit_restrictions",
- &credit_restrictions),
- NULL),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- if (NULL == debit_restrictions)
- {
- debit_restrictions = json_array ();
- GNUNET_assert (NULL != debit_restrictions);
- }
- if (NULL == credit_restrictions)
- {
- credit_restrictions = json_array ();
- GNUNET_assert (NULL != credit_restrictions);
- }
- ctx->cb (ctx->cb_cls,
- payto_uri,
- conversion_url,
- open_banking_gateway,
- wire_transfer_gateway,
- debit_restrictions,
- credit_restrictions,
- &master_sig,
- bank_label,
- priority);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_wire_accounts (struct TALER_EXCHANGEDB_PostgresContext *pg,
- TALER_EXCHANGEDB_WireAccountCallback cb,
- void *cb_cls)
-{
- struct GetWireAccountsContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .status = GNUNET_OK
- };
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "get_wire_accounts",
- "SELECT"
- " payto_uri"
- ",conversion_url"
- ",open_banking_gateway"
- ",wire_transfer_gateway"
- ",debit_restrictions::TEXT"
- ",credit_restrictions::TEXT"
- ",master_sig"
- ",bank_label"
- ",priority"
- " FROM wire_accounts"
- " WHERE is_active");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "get_wire_accounts",
- params,
- &get_wire_accounts_cb,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_get_wire_fee.c b/src/exchangedb/pg_get_wire_fee.c
@@ -1,74 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_wire_fee.c
- * @brief Implementation of the get_wire_fee function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_wire_fee.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_wire_fee (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *type,
- struct GNUNET_TIME_Timestamp date,
- uint64_t *rowid,
- struct GNUNET_TIME_Timestamp *start_date,
- struct GNUNET_TIME_Timestamp *end_date,
- struct TALER_WireFeeSet *fees,
- struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (type),
- GNUNET_PQ_query_param_timestamp (&date),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("wire_fee_serial",
- rowid),
- GNUNET_PQ_result_spec_timestamp ("start_date",
- start_date),
- GNUNET_PQ_result_spec_timestamp ("end_date",
- end_date),
- TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
- &fees->wire),
- TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
- &fees->closing),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_wire_fee",
- "SELECT"
- " wire_fee_serial"
- ",start_date"
- ",end_date"
- ",wire_fee"
- ",closing_fee"
- ",master_sig"
- " FROM wire_fee"
- " WHERE wire_method=$1"
- " AND start_date <= $2"
- " AND end_date > $2;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_wire_fee",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_get_wire_fees.c b/src/exchangedb/pg_get_wire_fees.c
@@ -1,144 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_wire_fees.c
- * @brief Implementation of the get_wire_fees function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_wire_fees.h"
-#include "helper.h"
-
-/**
- * Closure for #get_wire_fees_cb().
- */
-struct GetWireFeesContext
-{
- /**
- * Function to call per result.
- */
- TALER_EXCHANGEDB_WireFeeCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Flag set to #GNUNET_OK as long as everything is fine.
- */
- enum GNUNET_GenericReturnValue status;
-
-};
-
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct GetWireFeesContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-get_wire_fees_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct GetWireFeesContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct TALER_MasterSignatureP master_sig;
- struct TALER_WireFeeSet fees;
- struct GNUNET_TIME_Timestamp start_date;
- struct GNUNET_TIME_Timestamp end_date;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
- &fees.wire),
- TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
- &fees.closing),
- GNUNET_PQ_result_spec_timestamp ("start_date",
- &start_date),
- GNUNET_PQ_result_spec_timestamp ("end_date",
- &end_date),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &fees,
- start_date,
- end_date,
- &master_sig);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_get_wire_fees (struct TALER_EXCHANGEDB_PostgresContext *
- pg,
- const char *wire_method,
- TALER_EXCHANGEDB_WireFeeCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (wire_method),
- GNUNET_PQ_query_param_end
- };
- struct GetWireFeesContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "get_wire_fees",
- "SELECT"
- " wire_fee"
- ",closing_fee"
- ",start_date"
- ",end_date"
- ",master_sig"
- " FROM wire_fee"
- " WHERE wire_method=$1");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "get_wire_fees",
- params,
- &get_wire_fees_cb,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_get_wire_hash_for_contract.c b/src/exchangedb/pg_get_wire_hash_for_contract.c
@@ -1,77 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2023, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_wire_hash_for_contract.c
- * @brief Implementation of the get_wire_hash_for_contract function for Postgres
- * @author Özgür Kesim
- */
-#include "taler/taler_exchangedb_lib.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_wire_hash_for_contract.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_wire_hash_for_contract (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- struct TALER_MerchantWireHashP *h_wire)
-{
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (merchant_pub),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_end
- };
- struct TALER_FullPayto payto_uri;
- struct TALER_WireSaltP wire_salt;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
- &wire_salt),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri.full_payto),
- GNUNET_PQ_result_spec_end
- };
-
- /* check if the necessary records exist and get them */
- PREPARE (pg,
- "get_wire_hash_for_contract",
- "SELECT"
- " bdep.wire_salt"
- " ,wt.payto_uri"
- " FROM coin_deposits"
- " JOIN batch_deposits bdep"
- " USING (batch_deposit_serial_id)"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " WHERE bdep.merchant_pub=$1"
- " AND bdep.h_contract_terms=$2");
- /* NOTE: above query might be more efficient if we computed the shard
- from the merchant_pub and included that in the query */
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_wire_hash_for_contract",
- params,
- rs);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- {
- TALER_merchant_wire_signature_hash (payto_uri,
- &wire_salt,
- h_wire);
- GNUNET_PQ_cleanup_result (rs);
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_get_withdraw.c b/src/exchangedb/pg_get_withdraw.c
@@ -1,191 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2023, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_get_withdraw.c
- * @brief Implementation of the get_withdraw function for Postgres
- * @author Özgür Kesim
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/get_withdraw.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_get_withdraw (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_HashBlindedPlanchetsP *wch,
- struct TALER_EXCHANGEDB_Withdraw *wd)
-{
- enum GNUNET_DB_QueryStatus ret;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (wch),
- GNUNET_PQ_query_param_end
- };
- struct TALER_BlindedDenominationSignature *my_denom_sigs = NULL;
- uint64_t *my_denom_serials = NULL;
- struct GNUNET_CRYPTO_CSPublicRPairP *my_cs_r_values = NULL;
- size_t num_sigs = 0;
- size_t num_coins = 0;
- size_t num_cs_r_values = 0;
- bool no_noreveal_index;
- bool no_max_age;
- bool no_selected_h;
- bool no_blinding_seed;
- bool no_cs_r_values;
- bool no_cs_r_choices;
-
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
- &wd->planchets_h),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &wd->reserve_sig),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &wd->reserve_pub),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint16 ("max_age",
- &wd->max_age),
- &no_max_age),
- TALER_PQ_result_spec_amount ("amount_with_fee",
- pg->currency,
- &wd->amount_with_fee),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint16 ("noreveal_index",
- &wd->noreveal_index),
- &no_noreveal_index),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("selected_h",
- &wd->selected_h),
- &no_selected_h),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("blinding_seed",
- &wd->blinding_seed),
- &no_blinding_seed),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_array_cs_r_pub (
- pg->conn,
- "cs_r_values",
- &num_cs_r_values,
- &my_cs_r_values),
- &no_cs_r_values),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 ("cs_r_choices",
- &wd->cs_r_choices),
- &no_cs_r_choices),
- TALER_PQ_result_spec_array_blinded_denom_sig (
- pg->conn,
- "denom_sigs",
- &num_sigs,
- &my_denom_sigs),
- GNUNET_PQ_result_spec_array_uint64 (
- pg->conn,
- "denom_serials",
- &num_coins,
- &my_denom_serials),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_withdraw",
- "SELECT"
- " planchets_h"
- ",blinding_seed"
- ",reserve_sig"
- ",reserve_pub"
- ",max_age"
- ",amount_with_fee"
- ",noreveal_index"
- ",selected_h"
- ",blinding_seed"
- ",cs_r_values"
- ",cs_r_choices"
- ",denom_sigs"
- ",denom_serials"
- " FROM withdraw"
- " WHERE planchets_h=$1;");
- ret = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_withdraw",
- params,
- rs);
- if (0 > ret)
- {
- GNUNET_break (0);
- GNUNET_PQ_cleanup_result (rs);
- return ret;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == ret)
- {
- GNUNET_PQ_cleanup_result (rs);
- return ret;
- }
-
- if ((no_max_age != no_noreveal_index) ||
- (no_max_age != no_selected_h))
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "got inconsistent state for max_age, noreveal_index and planchets_h in DB: "
- "no_max_age=%s, no_noreveal_index=%s, no_selected_h=%s\n",
- no_max_age ? "true" : "false",
- no_noreveal_index ? "true" : "false",
- no_selected_h ? "true" : "false");
- GNUNET_PQ_cleanup_result (rs);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (no_blinding_seed != no_cs_r_values)
- {
- GNUNET_break (0);
- GNUNET_PQ_cleanup_result (rs);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (no_cs_r_choices != no_cs_r_values)
- {
- GNUNET_break (0);
- GNUNET_PQ_cleanup_result (rs);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (num_coins != num_sigs)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "got inconsistent number of entries in withdraw from DB: "
- "num_coins=%ld, num_sigs=%ld\n",
- num_coins,
- num_sigs);
- GNUNET_PQ_cleanup_result (rs);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- wd->age_proof_required = ! no_max_age;
- if (no_cs_r_values)
- {
- wd->cs_r_values = NULL;
- wd->num_cs_r_values = 0;
- wd->cs_r_choices = 0;
- }
- wd->denom_sigs = my_denom_sigs;
- wd->num_coins = num_coins;
- wd->denom_serials = my_denom_serials;
- wd->cs_r_values = my_cs_r_values;
- wd->num_cs_r_values = num_cs_r_values;
- /* ensure cleanup_result does not trash data we care about */
- my_denom_sigs = NULL;
- my_denom_serials = NULL;
- my_cs_r_values = NULL;
- num_sigs = 0;
- num_coins = 0;
- num_cs_r_values = 0;
- GNUNET_PQ_cleanup_result (rs);
- return ret;
-}
diff --git a/src/exchangedb/pg_have_deposit2.c b/src/exchangedb/pg_have_deposit2.c
@@ -1,113 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_have_deposit2.c
- * @brief Implementation of the have_deposit2 function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/have_deposit2.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_have_deposit2 (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- const struct TALER_MerchantWireHashP *h_wire,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_MerchantPublicKeyP *merchant,
- struct GNUNET_TIME_Timestamp refund_deadline,
- struct TALER_Amount *deposit_fee,
- struct GNUNET_TIME_Timestamp *exchange_timestamp)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_auto_from_type (merchant),
- GNUNET_PQ_query_param_end
- };
- struct TALER_EXCHANGEDB_Deposit deposit2;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &deposit2.amount_with_fee),
- GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
- &deposit2.timestamp),
- GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
- exchange_timestamp),
- GNUNET_PQ_result_spec_timestamp ("refund_deadline",
- &deposit2.refund_deadline),
- GNUNET_PQ_result_spec_timestamp ("wire_deadline",
- &deposit2.wire_deadline),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- deposit_fee),
- GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
- &deposit2.wire_salt),
- GNUNET_PQ_result_spec_string ("receiver_wire_account",
- &deposit2.receiver_wire_account.full_payto),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
- struct TALER_MerchantWireHashP h_wire2;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Getting deposits for coin %s\n",
- TALER_B2S (coin_pub));
- PREPARE (pg,
- "get_deposit",
- "SELECT"
- " cdep.amount_with_fee"
- ",denominations.fee_deposit"
- ",bdep.wallet_timestamp"
- ",bdep.exchange_timestamp"
- ",bdep.refund_deadline"
- ",bdep.wire_deadline"
- ",bdep.h_contract_terms"
- ",bdep.wire_salt"
- ",wt.payto_uri AS receiver_wire_account"
- " FROM coin_deposits cdep"
- " JOIN batch_deposits bdep USING (batch_deposit_serial_id)"
- " JOIN known_coins kc ON (kc.coin_pub = cdep.coin_pub)"
- " JOIN denominations USING (denominations_serial)"
- " JOIN wire_targets wt USING (wire_target_h_payto)"
- " WHERE cdep.coin_pub=$1"
- " AND bdep.merchant_pub=$3"
- " AND bdep.h_contract_terms=$2;");
- /* Note: query might be made more efficient if we computed the 'shard'
- from merchant_pub and included that as a constraint on bdep! */
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_deposit",
- params,
- rs);
- if (0 >= qs)
- return qs;
- TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account,
- &deposit2.wire_salt,
- &h_wire2);
- GNUNET_free (deposit2.receiver_wire_account.full_payto);
- /* Now we check that the other information in @a deposit
- also matches, and if not report inconsistencies. */
- if ( (GNUNET_TIME_timestamp_cmp (refund_deadline,
- !=,
- deposit2.refund_deadline)) ||
- (0 != GNUNET_memcmp (h_wire,
- &h_wire2) ) )
- {
- /* Inconsistencies detected! Does not match! */
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- }
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-}
diff --git a/src/exchangedb/pg_inject_auditor_triggers.c b/src/exchangedb/pg_inject_auditor_triggers.c
@@ -1,55 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_inject_auditor_triggers.c
- * @brief Implementation of the inject_auditor_triggers function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/gc.h"
-#include "helper.h"
-#include "taler/exchange-database/inject_auditor_triggers.h"
-
-
-/**
- * Function called to inject auditor triggers into the
- * database, triggering the real-time auditor upon
- * relevant INSERTs.
- *
- * @param pg the database context
- * @return #GNUNET_OK on success,
- * #GNUNET_SYSERR on DB errors
- */
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGEDB_inject_auditor_triggers (struct
- TALER_EXCHANGEDB_PostgresContext *pg)
-{
- struct GNUNET_PQ_Context *conn;
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
- "exchangedb-postgres",
- "auditor-triggers-",
- es,
- NULL);
- if (NULL == conn)
- return GNUNET_SYSERR;
- GNUNET_PQ_disconnect (conn);
- return GNUNET_OK;
-}
diff --git a/src/exchangedb/pg_insert_active_legitimization_measure.c b/src/exchangedb/pg_insert_active_legitimization_measure.c
@@ -1,58 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_active_legitimization_measure.c
- * @brief Implementation of the insert_active_legitimization_measure function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_active_legitimization_measure.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_active_legitimization_measure (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AccountAccessTokenP *access_token,
- const json_t *jmeasures,
- uint64_t *legitimization_measure_serial_id)
-{
- struct GNUNET_TIME_Timestamp now
- = GNUNET_TIME_timestamp_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (access_token),
- GNUNET_PQ_query_param_timestamp (&now),
- TALER_PQ_query_param_json (jmeasures),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("out_legitimization_measure_serial_id",
- legitimization_measure_serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "do_insert_active_legitimization_measure",
- "SELECT"
- " out_legitimization_measure_serial_id"
- " FROM exchange_do_insert_active_legitimization_measure"
- "($1, $2, $3::TEXT::JSONB);");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "do_insert_active_legitimization_measure",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_insert_aml_decision.c b/src/exchangedb/pg_insert_aml_decision.c
@@ -1,185 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2023, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_aml_decision.c
- * @brief Implementation of the insert_aml_decision function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_aml_decision.h"
-#include "helper.h"
-#include <gnunet/gnunet_pq_lib.h>
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_aml_decision (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPayto payto_uri,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- struct GNUNET_TIME_Timestamp decision_time,
- struct GNUNET_TIME_Timestamp expiration_time,
- const json_t *properties,
- const json_t *new_rules,
- bool to_investigate,
- const char *new_measure_name,
- const json_t *jmeasures,
- const char *justification,
- const struct TALER_AmlOfficerPublicKeyP *decider_pub,
- const struct TALER_AmlOfficerSignatureP *decider_sig,
- size_t num_events,
- const char *events[static num_events],
- const char *form_name,
- size_t enc_attributes_size,
- const void *enc_attributes,
- struct GNUNET_HashCode *attributes_hash,
- struct GNUNET_TIME_Timestamp attributes_expiration_time,
- bool *invalid_officer,
- bool *unknown_account,
- struct GNUNET_TIME_Timestamp *last_date,
- uint64_t *legitimization_measure_serial_id,
- bool *is_wallet)
-{
- struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = *h_payto
- };
- struct TALER_FullPaytoHashP h_full_payto;
- char *notify_s
- = GNUNET_PQ_get_event_notify_channel (&rep.header);
- bool account_unknown;
- struct GNUNET_PQ_QueryParam params[] = {
- /* $1: in_payto_uri */
- NULL == payto_uri.full_payto
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (payto_uri.full_payto),
- /* $2: in_h_normalized_payto */
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- /* $3: in_h_full_payto */
- NULL == payto_uri.full_payto
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (&h_full_payto),
- /* $4: in_decision_time */
- GNUNET_PQ_query_param_timestamp (&decision_time),
- /* $5: in_expiration_time*/
- GNUNET_PQ_query_param_timestamp (&expiration_time),
- /* $6: in_properties */
- NULL != properties
- ? TALER_PQ_query_param_json (properties)
- : GNUNET_PQ_query_param_null (),
- /* $7: in_kyc_attributes_enc */
- NULL != enc_attributes
- ? GNUNET_PQ_query_param_fixed_size (enc_attributes,
- enc_attributes_size)
- : GNUNET_PQ_query_param_null (),
- /* $8: in_kyc_attributes_hash */
- NULL != attributes_hash
- ? GNUNET_PQ_query_param_auto_from_type (attributes_hash)
- : GNUNET_PQ_query_param_null (),
- /* $9: in_kyc_attributes_expiration */
- GNUNET_PQ_query_param_timestamp (&attributes_expiration_time),
- /* $10: in_new_rules */
- TALER_PQ_query_param_json (new_rules),
- /* $11: in_to_investigate */
- GNUNET_PQ_query_param_bool (to_investigate),
- /* $12: in_new_measure_name */
- NULL != new_measure_name
- ? GNUNET_PQ_query_param_string (new_measure_name)
- : GNUNET_PQ_query_param_null (),
- /* $13: in_jmeasures */
- NULL != jmeasures
- ? TALER_PQ_query_param_json (jmeasures)
- : GNUNET_PQ_query_param_null (),
- /* $14: in_justification */
- NULL != justification
- ? GNUNET_PQ_query_param_string (justification)
- : GNUNET_PQ_query_param_null (),
- /* $15: in_decider_pub */
- NULL != decider_pub
- ? GNUNET_PQ_query_param_auto_from_type (decider_pub)
- : GNUNET_PQ_query_param_null (),
- /* $16: in_decider_sig */
- NULL != decider_sig
- ? GNUNET_PQ_query_param_auto_from_type (decider_sig)
- : GNUNET_PQ_query_param_null (),
- /* $17: in_notify_s*/
- GNUNET_PQ_query_param_string (notify_s),
- /* $18: ina_events */
- GNUNET_PQ_query_param_array_ptrs_string (num_events,
- events,
- pg->conn),
- (NULL == form_name)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (form_name),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("out_invalid_officer",
- invalid_officer),
- GNUNET_PQ_result_spec_bool ("out_account_unknown",
- unknown_account),
- GNUNET_PQ_result_spec_timestamp ("out_last_date",
- last_date),
- GNUNET_PQ_result_spec_uint64 ("out_legitimization_measure_serial_id",
- legitimization_measure_serial_id),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_bool ("out_is_wallet",
- is_wallet),
- &account_unknown),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- *is_wallet = false;
- GNUNET_assert ( ( (NULL == decider_pub) &&
- (NULL == decider_sig) &&
- (NULL == justification) ) ||
- ( (NULL != decider_pub) &&
- (NULL != decider_sig) &&
- (NULL != justification) ) );
-
- if (NULL != payto_uri.full_payto)
- TALER_full_payto_hash (payto_uri,
- &h_full_payto);
- PREPARE (pg,
- "do_insert_aml_decision",
- "SELECT"
- " out_invalid_officer"
- ",out_account_unknown"
- ",out_last_date"
- ",out_legitimization_measure_serial_id"
- ",out_is_wallet"
- " FROM exchange_do_insert_aml_decision"
- "($1,$2,$3,$4,$5,$6::TEXT::JSONB,$7,$8,$9,$10::TEXT::JSONB"
- ",$11,$12,$13::TEXT::JSONB,$14,$15,$16,$17,$18,$19);");
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Inserting LEGI OUTCOME from AML decision with notification on %s\n",
- notify_s);
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "do_insert_aml_decision",
- params,
- rs);
- GNUNET_PQ_cleanup_query_params_closures (params);
- GNUNET_free (notify_s);
- GNUNET_PQ_event_do_poll (pg->conn);
- if (qs <= 0)
- return qs;
- if (account_unknown)
- {
- GNUNET_assert ((*invalid_officer) || (*unknown_account));
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_insert_aml_officer.c b/src/exchangedb/pg_insert_aml_officer.c
@@ -1,62 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_aml_officer.c
- * @brief Implementation of the insert_aml_officer function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_aml_officer.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_aml_officer (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AmlOfficerPublicKeyP *decider_pub,
- const struct TALER_MasterSignatureP *master_sig,
- const char *decider_name,
- bool is_active,
- bool read_only,
- struct GNUNET_TIME_Timestamp last_change,
- struct GNUNET_TIME_Timestamp *previous_change)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (decider_pub),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_string (decider_name),
- GNUNET_PQ_query_param_bool (is_active),
- GNUNET_PQ_query_param_bool (read_only),
- GNUNET_PQ_query_param_timestamp (&last_change),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("out_last_change",
- previous_change),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "do_insert_aml_staff",
- "SELECT"
- " out_last_change"
- " FROM exchange_do_insert_aml_officer"
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "do_insert_aml_staff",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_insert_aml_program_failure.c b/src/exchangedb/pg_insert_aml_program_failure.c
@@ -1,66 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_aml_program_failure.c
- * @brief Implementation of the insert_aml_program_failure function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_aml_program_failure.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_aml_program_failure (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t process_row,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const char *error_message,
- enum TALER_ErrorCode ec)
-{
- uint32_t ec32 = (uint32_t) ec;
- struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = *h_payto
- };
- struct GNUNET_TIME_Timestamp now
- = GNUNET_TIME_timestamp_get ();
- char *kyc_completed_notify_s
- = GNUNET_PQ_get_event_notify_channel (&rep.header);
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&process_row),
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_timestamp (&now),
- GNUNET_PQ_query_param_uint32 (&ec32),
- GNUNET_PQ_query_param_string (error_message),
- GNUNET_PQ_query_param_string (kyc_completed_notify_s),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "insert_aml_program_failure",
- "SELECT out_update"
- " FROM exchange_do_insert_aml_program_failure"
- " ($1, $2, $3, $4, $5, $6);");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_aml_program_failure",
- params);
- GNUNET_free (kyc_completed_notify_s);
- return qs;
-}
diff --git a/src/exchangedb/pg_insert_auditor.c b/src/exchangedb/pg_insert_auditor.c
@@ -1,55 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_auditor.c
- * @brief Implementation of the insert_auditor function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_auditor.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_auditor (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AuditorPublicKeyP *
- auditor_pub,
- const char *auditor_url,
- const char *auditor_name,
- struct GNUNET_TIME_Timestamp start_date)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (auditor_pub),
- GNUNET_PQ_query_param_string (auditor_name),
- GNUNET_PQ_query_param_string (auditor_url),
- GNUNET_PQ_query_param_timestamp (&start_date),
- GNUNET_PQ_query_param_end
- };
-
- /* used in #postgres_insert_auditor() */
- PREPARE (pg,
- "insert_auditor",
- "INSERT INTO auditors "
- "(auditor_pub"
- ",auditor_name"
- ",auditor_url"
- ",is_active"
- ",last_change"
- ") VALUES "
- "($1, $2, $3, true, $4);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_auditor",
- params);
-}
diff --git a/src/exchangedb/pg_insert_auditor_denom_sig.c b/src/exchangedb/pg_insert_auditor_denom_sig.c
@@ -1,58 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_auditor_denom_sig.c
- * @brief Implementation of the insert_auditor_denom_sig function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_auditor_denom_sig.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_insert_auditor_denom_sig (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_DenominationHashP *h_denom_pub,
- const struct TALER_AuditorPublicKeyP *auditor_pub,
- const struct TALER_AuditorSignatureP *auditor_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (auditor_pub),
- GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
- GNUNET_PQ_query_param_auto_from_type (auditor_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_auditor_denom_sig",
- "WITH ax AS"
- " (SELECT auditor_uuid"
- " FROM auditors"
- " WHERE auditor_pub=$1)"
- "INSERT INTO auditor_denom_sigs "
- "(auditor_uuid"
- ",denominations_serial"
- ",auditor_sig"
- ") SELECT ax.auditor_uuid, denominations_serial, $3 "
- " FROM denominations"
- " CROSS JOIN ax"
- " WHERE denom_pub_hash=$2"
- " ON CONFLICT DO NOTHING;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_auditor_denom_sig",
- params);
-}
diff --git a/src/exchangedb/pg_insert_close_request.c b/src/exchangedb/pg_insert_close_request.c
@@ -1,64 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_insert_close_request.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_close_request.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_close_request (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_FullPayto payto_uri,
- const struct TALER_ReserveSignatureP *reserve_sig,
- struct GNUNET_TIME_Timestamp request_timestamp,
- const struct TALER_Amount *balance,
- const struct TALER_Amount *closing_fee)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_timestamp (&request_timestamp),
- GNUNET_PQ_query_param_auto_from_type (reserve_sig),
- TALER_PQ_query_param_amount (pg->conn,
- balance),
- TALER_PQ_query_param_amount (pg->conn,
- closing_fee),
- GNUNET_PQ_query_param_string (payto_uri.full_payto),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_account_close",
- "INSERT INTO close_requests"
- "(reserve_pub"
- ",close_timestamp"
- ",reserve_sig"
- ",close"
- ",close_fee"
- ",payto_uri"
- ")"
- "VALUES "
- "($1, $2, $3, $4, $5, $6)"
- " ON CONFLICT DO NOTHING;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_account_close",
- params);
-}
diff --git a/src/exchangedb/pg_insert_contract.c b/src/exchangedb/pg_insert_contract.c
@@ -1,89 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_contract.c
- * @brief Implementation of the insert_contract function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_contract.h"
-#include "taler/exchange-database/select_contract_by_purse.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_contract (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- const struct TALER_EncryptedContract *econtract,
- bool *in_conflict)
-{
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_auto_from_type (&econtract->contract_pub),
- GNUNET_PQ_query_param_fixed_size (econtract->econtract,
- econtract->econtract_size),
- GNUNET_PQ_query_param_auto_from_type (&econtract->econtract_sig),
- GNUNET_PQ_query_param_end
- };
-
- *in_conflict = false;
- /* Used in #postgres_insert_contract() */
- PREPARE (pg,
- "insert_contract",
- "INSERT INTO contracts"
- " (purse_pub"
- " ,pub_ckey"
- " ,e_contract"
- " ,contract_sig"
- " ,purse_expiration"
- " ) SELECT "
- " $1, $2, $3, $4, purse_expiration"
- " FROM purse_requests"
- " WHERE purse_pub=$1"
- " ON CONFLICT DO NOTHING;");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_contract",
- params);
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
- return qs;
- {
- struct TALER_EncryptedContract econtract2;
-
- qs = TALER_TALER_EXCHANGEDB_select_contract_by_purse (pg,
- purse_pub,
- &econtract2);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if ( (0 == GNUNET_memcmp (&econtract->contract_pub,
- &econtract2.contract_pub)) &&
- (econtract2.econtract_size ==
- econtract->econtract_size) &&
- (0 == memcmp (econtract2.econtract,
- econtract->econtract,
- econtract->econtract_size)) )
- {
- GNUNET_free (econtract2.econtract);
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- }
- GNUNET_free (econtract2.econtract);
- *in_conflict = true;
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
-}
diff --git a/src/exchangedb/pg_insert_denomination_info.c b/src/exchangedb/pg_insert_denomination_info.c
@@ -1,98 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_denomination_info.c
- * @brief Implementation of the insert_denomination_info function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_denomination_info.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_denomination_info (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_DenominationPublicKey *denom_pub,
- const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
-{
- struct TALER_DenominationHashP denom_hash;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&issue->denom_hash),
- TALER_PQ_query_param_denom_pub (denom_pub),
- GNUNET_PQ_query_param_auto_from_type (&issue->signature),
- GNUNET_PQ_query_param_timestamp (&issue->start),
- GNUNET_PQ_query_param_timestamp (&issue->expire_withdraw),
- GNUNET_PQ_query_param_timestamp (&issue->expire_deposit),
- GNUNET_PQ_query_param_timestamp (&issue->expire_legal),
- TALER_PQ_query_param_amount (pg->conn,
- &issue->value),
- TALER_PQ_query_param_amount (pg->conn,
- &issue->fees.withdraw),
- TALER_PQ_query_param_amount (pg->conn,
- &issue->fees.deposit),
- TALER_PQ_query_param_amount (pg->conn,
- &issue->fees.refresh),
- TALER_PQ_query_param_amount (pg->conn,
- &issue->fees.refund),
- GNUNET_PQ_query_param_uint32 (&denom_pub->age_mask.bits),
- GNUNET_PQ_query_param_end
- };
-
- GNUNET_assert (denom_pub->age_mask.bits ==
- issue->age_mask.bits);
- TALER_denom_pub_hash (denom_pub,
- &denom_hash);
- GNUNET_assert (0 ==
- GNUNET_memcmp (&denom_hash,
- &issue->denom_hash));
- GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
- issue->start.abs_time));
- GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
- issue->expire_withdraw.abs_time));
- GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
- issue->expire_deposit.abs_time));
- GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
- issue->expire_legal.abs_time));
- /* check fees match denomination currency */
- GNUNET_assert (GNUNET_YES ==
- TALER_denom_fee_check_currency (
- issue->value.currency,
- &issue->fees));
- PREPARE (pg,
- "denomination_insert",
- "INSERT INTO denominations "
- "(denom_pub_hash"
- ",denom_pub"
- ",master_sig"
- ",valid_from"
- ",expire_withdraw"
- ",expire_deposit"
- ",expire_legal"
- ",coin" /* value of this denom */
- ",fee_withdraw"
- ",fee_deposit"
- ",fee_refresh"
- ",fee_refund"
- ",age_mask"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
- " $11, $12, $13);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "denomination_insert",
- params);
-}
diff --git a/src/exchangedb/pg_insert_denomination_revocation.c b/src/exchangedb/pg_insert_denomination_revocation.c
@@ -1,50 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_denomination_revocation.c
- * @brief Implementation of the insert_denomination_revocation function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_denomination_revocation.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_denomination_revocation (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_DenominationHashP *denom_pub_hash,
- const struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_end
- };
-
- /* Used in #postgres_insert_denomination_revocation() */
- PREPARE (pg,
- "denomination_revocation_insert",
- "INSERT INTO denomination_revocations "
- "(denominations_serial"
- ",master_sig"
- ") SELECT denominations_serial,$2"
- " FROM denominations"
- " WHERE denom_pub_hash=$1;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "denomination_revocation_insert",
- params);
-}
diff --git a/src/exchangedb/pg_insert_drain_profit.c b/src/exchangedb/pg_insert_drain_profit.c
@@ -1,60 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_drain_profit.c
- * @brief Implementation of the insert_drain_profit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_drain_profit.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_drain_profit (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- const char *account_section,
- const struct TALER_FullPayto payto_uri,
- struct GNUNET_TIME_Timestamp request_timestamp,
- const struct TALER_Amount *amount,
- const struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_string (account_section),
- GNUNET_PQ_query_param_string (payto_uri.full_payto),
- GNUNET_PQ_query_param_timestamp (&request_timestamp),
- TALER_PQ_query_param_amount (pg->conn,
- amount),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "drain_profit_insert",
- "INSERT INTO profit_drains "
- "(wtid"
- ",account_section"
- ",payto_uri"
- ",trigger_date"
- ",amount"
- ",master_sig"
- ") VALUES ($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "drain_profit_insert",
- params);
-}
diff --git a/src/exchangedb/pg_insert_global_fee.c b/src/exchangedb/pg_insert_global_fee.c
@@ -1,137 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_global_fee.c
- * @brief Implementation of the insert_global_fee function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_dbevents.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_global_fee.h"
-#include "helper.h"
-#include "taler/exchange-database/get_global_fee.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct GNUNET_TIME_Timestamp start_date,
- struct GNUNET_TIME_Timestamp end_date,
- const struct TALER_GlobalFeeSet *fees,
- struct GNUNET_TIME_Relative purse_timeout,
- struct GNUNET_TIME_Relative
- history_expiration,
- uint32_t purse_account_limit,
- const struct TALER_MasterSignatureP *
- master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&start_date),
- GNUNET_PQ_query_param_timestamp (&end_date),
- TALER_PQ_query_param_amount (pg->conn,
- &fees->history),
- TALER_PQ_query_param_amount (pg->conn,
- &fees->account),
- TALER_PQ_query_param_amount (pg->conn,
- &fees->purse),
- GNUNET_PQ_query_param_relative_time (&purse_timeout),
- GNUNET_PQ_query_param_relative_time (&history_expiration),
- GNUNET_PQ_query_param_uint32 (&purse_account_limit),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_end
- };
- struct TALER_GlobalFeeSet wx;
- struct TALER_MasterSignatureP sig;
- struct GNUNET_TIME_Timestamp sd;
- struct GNUNET_TIME_Timestamp ed;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_TIME_Relative pt;
- struct GNUNET_TIME_Relative he;
- uint32_t pal;
-
- qs = TALER_EXCHANGEDB_get_global_fee (pg,
- start_date,
- &sd,
- &ed,
- &wx,
- &pt,
- &he,
- &pal,
- &sig);
- if (qs < 0)
- return qs;
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- {
- if (0 != GNUNET_memcmp (&sig,
- master_sig))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (0 !=
- TALER_global_fee_set_cmp (fees,
- &wx))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if ( (GNUNET_TIME_timestamp_cmp (sd,
- !=,
- start_date)) ||
- (GNUNET_TIME_timestamp_cmp (ed,
- !=,
- end_date)) )
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if ( (GNUNET_TIME_relative_cmp (purse_timeout,
- !=,
- pt)) ||
- (GNUNET_TIME_relative_cmp (history_expiration,
- !=,
- he)) )
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (purse_account_limit != pal)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- /* equal record already exists */
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- }
-
- /* Used in #postgres_insert_global_fee */
- PREPARE (pg,
- "insert_global_fee",
- "INSERT INTO global_fee "
- "(start_date"
- ",end_date"
- ",history_fee"
- ",account_fee"
- ",purse_fee"
- ",purse_timeout"
- ",history_expiration"
- ",purse_account_limit"
- ",master_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_global_fee",
- params);
-}
diff --git a/src/exchangedb/pg_insert_kyc_failure.c b/src/exchangedb/pg_insert_kyc_failure.c
@@ -1,90 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_kyc_failure.c
- * @brief Implementation of the insert_kyc_failure function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/platform.h" /* UNNECESSARY? */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_dbevents.h" /* UNNECESSARY? */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_kyc_failure.h"
-#include "helper.h"
-#include "taler/exchange-database/event_notify.h" /* UNNECESSARY? */
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_kyc_failure (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t process_row,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const char *provider_name,
- const char *provider_account_id,
- const char *provider_legitimization_id,
- const char *error_message,
- enum TALER_ErrorCode ec)
-{
- uint32_t ec32 = (uint32_t) ec;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&process_row),
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- NULL != provider_name
- ? GNUNET_PQ_query_param_string (provider_name)
- : GNUNET_PQ_query_param_null (),
- NULL != provider_account_id
- ? GNUNET_PQ_query_param_string (provider_account_id)
- : GNUNET_PQ_query_param_null (),
- NULL != provider_legitimization_id
- ? GNUNET_PQ_query_param_string (provider_legitimization_id)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_uint32 (&ec32),
- GNUNET_PQ_query_param_string (error_message),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "insert_kyc_failure",
- "UPDATE legitimization_processes"
- " SET"
- " finished=TRUE"
- " ,provider_user_id=$4"
- " ,provider_legitimization_id=$5"
- " ,error_code=$6"
- " ,error_message=$7"
- " WHERE h_payto=$2"
- " AND legitimization_process_serial_id=$1"
- " AND provider_name=$3;");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_kyc_failure",
- params);
- if (qs > 0)
- {
- /* FIXME-#9419: might want to do this eventually in the same transaction... */
- struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = *h_payto
- };
-
- TALER_EXCHANGEDB_event_notify (pg,
- &rep.header,
- NULL,
- 0);
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_insert_kyc_requirement_process.c b/src/exchangedb/pg_insert_kyc_requirement_process.c
@@ -1,85 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_kyc_requirement_process.c
- * @brief Implementation of the insert_kyc_requirement_process function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_kyc_requirement_process.h"
-#include "helper.h"
-#include <gnunet/gnunet_pq_lib.h>
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_kyc_requirement_process (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- uint32_t measure_index,
- uint64_t legitimization_measure_serial_id,
- const char *provider_name,
- const char *provider_account_id,
- const char *provider_legitimization_id,
- uint64_t *process_row)
-{
- struct GNUNET_TIME_Absolute now
- = GNUNET_TIME_absolute_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_string (provider_name),
- (NULL != provider_account_id)
- ? GNUNET_PQ_query_param_string (provider_account_id)
- : GNUNET_PQ_query_param_null (),
- (NULL != provider_legitimization_id)
- ? GNUNET_PQ_query_param_string (provider_legitimization_id)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id),
- GNUNET_PQ_query_param_uint32 (&measure_index),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("legitimization_process_serial_id",
- process_row),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "insert_kyc_requirement_process",
- "INSERT INTO legitimization_processes"
- " (h_payto"
- " ,start_time"
- " ,provider_name"
- " ,provider_user_id"
- " ,provider_legitimization_id"
- " ,legitimization_measure_serial_id"
- " ,measure_index"
- " ) VALUES "
- " ($1, $2, $3, $4, $5, $6, $7)"
- " ON CONFLICT (legitimization_measure_serial_id,measure_index)"
- " DO UPDATE"
- " SET h_payto=$1"
- " ,start_time=$2"
- " ,provider_name=$3"
- " ,provider_user_id=$4"
- " ,provider_legitimization_id=$5"
- " RETURNING legitimization_process_serial_id");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "insert_kyc_requirement_process",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_insert_partner.c b/src/exchangedb/pg_insert_partner.c
@@ -1,67 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_partner.c
- * @brief Implementation of the insert_partner function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_partner.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_partner (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_MasterPublicKeyP *master_pub
- ,
- struct GNUNET_TIME_Timestamp start_date,
- struct GNUNET_TIME_Timestamp end_date,
- struct GNUNET_TIME_Relative wad_frequency,
- const struct TALER_Amount *wad_fee,
- const char *partner_base_url,
- const struct TALER_MasterSignatureP *master_sig
- )
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (master_pub),
- GNUNET_PQ_query_param_timestamp (&start_date),
- GNUNET_PQ_query_param_timestamp (&end_date),
- GNUNET_PQ_query_param_relative_time (&wad_frequency),
- TALER_PQ_query_param_amount (pg->conn,
- wad_fee),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_string (partner_base_url),
- GNUNET_PQ_query_param_end
- };
-
-
- PREPARE (pg,
- "insert_partner",
- "INSERT INTO partners"
- " (partner_master_pub"
- " ,start_date"
- " ,end_date"
- " ,wad_frequency"
- " ,wad_fee"
- " ,master_sig"
- " ,partner_base_url"
- " ) VALUES "
- " ($1, $2, $3, $4, $5, $6, $7)"
- " ON CONFLICT DO NOTHING;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_partner",
- params);
-}
diff --git a/src/exchangedb/pg_insert_purse_request.c b/src/exchangedb/pg_insert_purse_request.c
@@ -1,122 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_purse_request.c
- * @brief Implementation of the insert_purse_request function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_purse_request.h"
-#include "taler/exchange-database/get_purse_request.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_purse_request (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- const struct TALER_PurseMergePublicKeyP *merge_pub,
- struct GNUNET_TIME_Timestamp purse_expiration,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- uint32_t age_limit,
- enum TALER_WalletAccountMergeFlags flags,
- const struct TALER_Amount *purse_fee,
- const struct TALER_Amount *amount,
- const struct TALER_PurseContractSignatureP *purse_sig,
- bool *in_conflict)
-{
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
- uint32_t flags32 = (uint32_t) flags;
- bool in_reserve_quota = (TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA
- == (flags & TALER_WAMF_MERGE_MODE_MASK));
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_auto_from_type (merge_pub),
- GNUNET_PQ_query_param_timestamp (&now),
- GNUNET_PQ_query_param_timestamp (&purse_expiration),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_uint32 (&age_limit),
- GNUNET_PQ_query_param_uint32 (&flags32),
- GNUNET_PQ_query_param_bool (in_reserve_quota),
- TALER_PQ_query_param_amount (pg->conn,
- amount),
- TALER_PQ_query_param_amount (pg->conn,
- purse_fee),
- GNUNET_PQ_query_param_auto_from_type (purse_sig),
- GNUNET_PQ_query_param_end
- };
-
- *in_conflict = false;
- PREPARE (pg,
- "insert_purse_request",
- "INSERT INTO purse_requests"
- " (purse_pub"
- " ,merge_pub"
- " ,purse_creation"
- " ,purse_expiration"
- " ,h_contract_terms"
- " ,age_limit"
- " ,flags"
- " ,in_reserve_quota"
- " ,amount_with_fee"
- " ,purse_fee"
- " ,purse_sig"
- " ) VALUES "
- " ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)"
- " ON CONFLICT DO NOTHING;");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_purse_request",
- params);
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
- return qs;
- {
- struct TALER_PurseMergePublicKeyP merge_pub2;
- struct GNUNET_TIME_Timestamp purse_expiration2;
- struct TALER_PrivateContractHashP h_contract_terms2;
- uint32_t age_limit2;
- struct TALER_Amount amount2;
- struct TALER_Amount balance;
- struct TALER_PurseContractSignatureP purse_sig2;
-
- qs = TALER_EXCHANGEDB_get_purse_request (pg,
- purse_pub,
- &merge_pub2,
- &purse_expiration2,
- &h_contract_terms2,
- &age_limit2,
- &amount2,
- &balance,
- &purse_sig2);
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if ( (age_limit2 == age_limit) &&
- (0 == TALER_amount_cmp (amount,
- &amount2)) &&
- (0 == GNUNET_memcmp (&h_contract_terms2,
- h_contract_terms)) &&
- (0 == GNUNET_memcmp (&merge_pub2,
- merge_pub)) )
- {
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- }
- *in_conflict = true;
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
-}
diff --git a/src/exchangedb/pg_insert_records_by_table.c b/src/exchangedb/pg_insert_records_by_table.c
@@ -1,2453 +0,0 @@
-/*
- This file is part of GNUnet
- Copyright (C) 2020-2025 Taler Systems SA
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
-
- GNUnet 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
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- SPDX-License-Identifier: AGPL3.0-or-later
- */
-/**
- * @file exchangedb/pg_insert_records_by_table.c
- * @brief replicate_records_by_table implementation
- * @author Christian Grothoff
- * @author Özgür Kesim
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_dbevents.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_records_by_table.h"
-#include "helper.h"
-#include <gnunet/gnunet_pq_lib.h>
-
-
-/**
- * Signature of helper functions of #TALER_EXCHANGEDB_insert_records_by_table().
- *
- * @param pg plugin context
- * @param td record to insert
- * @return transaction status code
- */
-typedef enum GNUNET_DB_QueryStatus
-(*InsertRecordCallback)(struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td);
-
-
-/**
- * Function called with denominations records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_denominations (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct TALER_DenominationHashP denom_hash;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&denom_hash),
- GNUNET_PQ_query_param_uint32 (
- &td->details.denominations.denom_type),
- GNUNET_PQ_query_param_uint32 (
- &td->details.denominations.age_mask),
- TALER_PQ_query_param_denom_pub (
- &td->details.denominations.denom_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.denominations.master_sig),
- GNUNET_PQ_query_param_timestamp (
- &td->details.denominations.valid_from),
- GNUNET_PQ_query_param_timestamp (
- &td->details.denominations.expire_withdraw),
- GNUNET_PQ_query_param_timestamp (
- &td->details.denominations.expire_deposit),
- GNUNET_PQ_query_param_timestamp (
- &td->details.denominations.expire_legal),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.denominations.coin),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.denominations.fees.withdraw),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.denominations.fees.deposit),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.denominations.fees.refresh),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.denominations.fees.refund),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_denominations",
- "INSERT INTO denominations"
- "(denominations_serial"
- ",denom_pub_hash"
- ",denom_type"
- ",age_mask"
- ",denom_pub"
- ",master_sig"
- ",valid_from"
- ",expire_withdraw"
- ",expire_deposit"
- ",expire_legal"
- ",coin"
- ",fee_withdraw"
- ",fee_deposit"
- ",fee_refresh"
- ",fee_refund"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
- " $11, $12, $13, $14, $15);");
-
- TALER_denom_pub_hash (
- &td->details.denominations.denom_pub,
- &denom_hash);
-
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_denominations",
- params);
-}
-
-
-/**
- * Function called with denomination_revocations records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_denomination_revocations (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.denomination_revocations.master_sig),
- GNUNET_PQ_query_param_uint64 (
- &td->details.denomination_revocations.denominations_serial),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_denomination_revocations",
- "INSERT INTO denomination_revocations"
- "(denom_revocations_serial_id"
- ",master_sig"
- ",denominations_serial"
- ") VALUES "
- "($1, $2, $3);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_denomination_revocations",
- params);
-}
-
-
-/**
- * Function called with wire target records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_wire_targets (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct TALER_NormalizedPaytoHashP normalized_payto_hash;
- struct TALER_FullPaytoHashP full_payto_hash;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&full_payto_hash),
- GNUNET_PQ_query_param_auto_from_type (&normalized_payto_hash),
- GNUNET_PQ_query_param_string (
- td->details.wire_targets.full_payto_uri.full_payto),
- GNUNET_PQ_query_param_end
- };
-
- TALER_full_payto_hash (
- td->details.wire_targets.full_payto_uri,
- &full_payto_hash);
- TALER_full_payto_normalize_and_hash (
- td->details.wire_targets.full_payto_uri,
- &normalized_payto_hash);
- PREPARE (pg,
- "insert_into_table_wire_targets",
- "INSERT INTO wire_targets"
- "(wire_target_serial_id"
- ",wire_target_h_payto"
- ",h_normalized_payto"
- ",payto_uri"
- ") VALUES "
- "($1, $2, $3, $4);");
- return GNUNET_PQ_eval_prepared_non_select (
- pg->conn,
- "insert_into_table_wire_targets",
- params);
-}
-
-
-/**
- * Function called with kyc target records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_kyc_targets (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.kyc_targets.h_normalized_payto),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.kyc_targets.access_token),
- td->details.kyc_targets.no_account
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (
- &td->details.kyc_targets.target_pub),
- GNUNET_PQ_query_param_bool (
- td->details.kyc_targets.is_wallet),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_kyc_targets",
- "INSERT INTO kyc_targets"
- "(kyc_target_serial_id"
- ",h_normalized_payto"
- ",access_token"
- ",target_pub"
- ",is_wallet"
- ") VALUES "
- "($1, $2, $3, $4, $5);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_kyc_targets",
- params);
-}
-
-
-/**
- * Function called with records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_legitimization_measures (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.legitimization_measures.target_token),
- GNUNET_PQ_query_param_timestamp (
- &td->details.legitimization_measures.start_time),
- TALER_PQ_query_param_json (
- td->details.legitimization_measures.measures),
- GNUNET_PQ_query_param_uint32 (
- &td->details.legitimization_measures.display_priority),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_legitimization_measures",
- "INSERT INTO legitimization_measures"
- "(legitimization_measure_serial_id"
- ",access_token"
- ",start_time"
- ",jmeasures"
- ",display_priority"
- ") VALUES "
- "($1, $2, $3, $4::TEXT::JSONB, $5);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_legitimization_measures",
- params);
-}
-
-
-/**
- * Function called with records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_legitimization_outcomes (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.legitimization_outcomes.h_payto),
- GNUNET_PQ_query_param_timestamp (
- &td->details.legitimization_outcomes.decision_time),
- GNUNET_PQ_query_param_timestamp (
- &td->details.legitimization_outcomes.expiration_time),
- TALER_PQ_query_param_json (
- td->details.legitimization_outcomes.properties),
- GNUNET_PQ_query_param_bool (
- td->details.legitimization_outcomes.to_investigate),
- TALER_PQ_query_param_json (
- td->details.legitimization_outcomes.new_rules),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_legitimization_outcomes",
- "INSERT INTO legitimization_outcomes"
- "(outcome_serial_id"
- ",h_payto"
- ",decision_time"
- ",expiration_time"
- ",jproperties"
- ",to_investigate"
- ",jnew_rules"
- ") VALUES "
- "($1, $2, $3, $4, $5::TEXT::JSONB, $6, $7::TEXT::JSONB);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_legitimization_outcomes",
- params);
-}
-
-
-/**
- * Function called with records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_legitimization_processes (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.legitimization_processes.h_payto),
- GNUNET_PQ_query_param_timestamp (
- &td->details.legitimization_processes.start_time),
- GNUNET_PQ_query_param_timestamp (
- &td->details.legitimization_processes.expiration_time),
- GNUNET_PQ_query_param_uint64 (
- &td->details.legitimization_processes.legitimization_measure_serial_id),
- GNUNET_PQ_query_param_uint32 (
- &td->details.legitimization_processes.measure_index),
- GNUNET_PQ_query_param_string (
- td->details.legitimization_processes.provider_name),
- GNUNET_PQ_query_param_string (
- td->details.legitimization_processes.provider_user_id),
- GNUNET_PQ_query_param_string (
- td->details.legitimization_processes.provider_legitimization_id),
- GNUNET_PQ_query_param_string (
- td->details.legitimization_processes.redirect_url),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_legitimization_processes",
- "INSERT INTO legitimization_processes"
- "(legitimization_process_serial_id"
- ",h_payto"
- ",start_time"
- ",expiration_time"
- ",legitimization_measure_serial_id"
- ",measure_index"
- ",provider_name"
- ",provider_user_id"
- ",provider_legitimization_id"
- ",redirect_url"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_legitimization_processes",
- params);
-}
-
-
-/**
- * Function called with reserves records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_reserves (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&td->details.reserves.reserve_pub),
- GNUNET_PQ_query_param_timestamp (&td->details.reserves.expiration_date),
- GNUNET_PQ_query_param_timestamp (&td->details.reserves.gc_date),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_reserves",
- "INSERT INTO reserves"
- "(reserve_uuid"
- ",reserve_pub"
- ",expiration_date"
- ",gc_date"
- ") VALUES "
- "($1, $2, $3, $4);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_reserves",
- params);
-}
-
-
-/**
- * Function called with reserves_in records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_reserves_in (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (&td->details.reserves_in.wire_reference),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.reserves_in.credit),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.reserves_in.sender_account_h_payto),
- GNUNET_PQ_query_param_string (
- td->details.reserves_in.exchange_account_section),
- GNUNET_PQ_query_param_timestamp (
- &td->details.reserves_in.execution_date),
- GNUNET_PQ_query_param_auto_from_type (&td->details.reserves_in.reserve_pub),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_reserves_in",
- "INSERT INTO reserves_in"
- "(reserve_in_serial_id"
- ",wire_reference"
- ",credit"
- ",wire_source_h_payto"
- ",exchange_account_section"
- ",execution_date"
- ",reserve_pub"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_reserves_in",
- params);
-}
-
-
-/**
- * Function called with kycauth_in records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_kycauths_in (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (&td->details.kycauth_in.wire_reference),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.reserves_in.credit),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.reserves_in.sender_account_h_payto),
- GNUNET_PQ_query_param_string (
- td->details.reserves_in.exchange_account_section),
- GNUNET_PQ_query_param_timestamp (
- &td->details.reserves_in.execution_date),
- GNUNET_PQ_query_param_auto_from_type (&td->details.kycauth_in.account_pub),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_kycauth_in",
- "INSERT INTO kycauths_in"
- "(kycauth_in_serial_id"
- ",wire_reference"
- ",credit"
- ",wire_source_h_payto"
- ",exchange_account_section"
- ",execution_date"
- ",account_pub"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_kycauth_in",
- params);
-}
-
-
-/**
- * Function called with reserves_open_requests records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_reserves_open_requests (struct TALER_EXCHANGEDB_PostgresContext *
- pg,
- const struct
- TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_timestamp (
- &td->details.reserves_open_requests.expiration_date),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.reserves_open_requests.reserve_sig),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.reserves_open_requests.reserve_payment),
- GNUNET_PQ_query_param_uint32 (
- &td->details.reserves_open_requests.requested_purse_limit),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_reserves_open_requests",
- "INSERT INTO reserves_open_requests"
- "(open_request_uuid"
- ",reserve_pub"
- ",request_timestamp"
- ",expiration_date"
- ",reserve_sig"
- ",reserve_payment"
- ",requested_purse_limit"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_reserves_open_requests",
- params);
-}
-
-
-/**
- * Function called with reserves_open_requests records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_reserves_open_deposits (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.reserves_open_deposits.coin_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.reserves_open_deposits.coin_sig),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.reserves_open_deposits.reserve_sig),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.reserves_open_deposits.contribution),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_reserves_open_deposits",
- "INSERT INTO reserves_open_deposits"
- "(reserve_open_deposit_uuid"
- ",reserve_sig"
- ",reserve_pub"
- ",coin_pub"
- ",coin_sig"
- ",contribution"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_reserves_open_deposits",
- params);
-}
-
-
-/**
- * Function called with reserves_close records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_reserves_close (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_timestamp (
- &td->details.reserves_close.execution_date),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.reserves_close.wtid),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.reserves_close.sender_account_h_payto),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.reserves_close.amount),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.reserves_close.closing_fee),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.reserves_close.reserve_pub),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_reserves_close",
- "INSERT INTO reserves_close"
- "(close_uuid"
- ",execution_date"
- ",wtid"
- ",wire_target_h_payto"
- ",amount"
- ",closing_fee"
- ",reserve_pub"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_reserves_close",
- params);
-}
-
-
-/**
- * Function called with auditors records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_auditors (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&td->details.auditors.auditor_pub),
- GNUNET_PQ_query_param_string (td->details.auditors.auditor_name),
- GNUNET_PQ_query_param_string (td->details.auditors.auditor_url),
- GNUNET_PQ_query_param_bool (td->details.auditors.is_active),
- GNUNET_PQ_query_param_timestamp (&td->details.auditors.last_change),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_auditors",
- "INSERT INTO auditors"
- "(auditor_uuid"
- ",auditor_pub"
- ",auditor_name"
- ",auditor_url"
- ",is_active"
- ",last_change"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_auditors",
- params);
-}
-
-
-/**
- * Function called with auditor_denom_sigs records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_auditor_denom_sigs (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (&td->details.auditor_denom_sigs.auditor_uuid),
- GNUNET_PQ_query_param_uint64 (
- &td->details.auditor_denom_sigs.denominations_serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.auditor_denom_sigs.auditor_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_auditor_denom_sigs",
- "INSERT INTO auditor_denom_sigs"
- "(auditor_denom_serial"
- ",auditor_uuid"
- ",denominations_serial"
- ",auditor_sig"
- ") VALUES "
- "($1, $2, $3, $4);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_auditor_denom_sigs",
- params);
-}
-
-
-/**
- * Function called with exchange_sign_keys records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_exchange_sign_keys (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.exchange_sign_keys.exchange_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.exchange_sign_keys.master_sig),
- GNUNET_PQ_query_param_timestamp (
- &td->details.exchange_sign_keys.meta.start),
- GNUNET_PQ_query_param_timestamp (
- &td->details.exchange_sign_keys.meta.expire_sign),
- GNUNET_PQ_query_param_timestamp (
- &td->details.exchange_sign_keys.meta.expire_legal),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_exchange_sign_keys",
- "INSERT INTO exchange_sign_keys"
- "(esk_serial"
- ",exchange_pub"
- ",master_sig"
- ",valid_from"
- ",expire_sign"
- ",expire_legal"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_exchange_sign_keys",
- params);
-}
-
-
-/**
- * Function called with signkey_revocations records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_signkey_revocations (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (&td->details.signkey_revocations.esk_serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.signkey_revocations.master_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_signkey_revocations",
- "INSERT INTO signkey_revocations"
- "(signkey_revocations_serial_id"
- ",esk_serial"
- ",master_sig"
- ") VALUES "
- "($1, $2, $3);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_signkey_revocations",
- params);
-}
-
-
-/**
- * Function called with known_coins records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_known_coins (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.known_coins.coin_pub),
- TALER_PQ_query_param_denom_sig (
- &td->details.known_coins.denom_sig),
- GNUNET_PQ_query_param_uint64 (
- &td->details.known_coins.denominations_serial),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_known_coins",
- "INSERT INTO known_coins"
- "(known_coin_id"
- ",coin_pub"
- ",denom_sig"
- ",denominations_serial"
- ") VALUES "
- "($1, $2, $3, $4);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_known_coins",
- params);
-}
-
-
-/**
- * Function called with refresh records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&td->details.refresh.rc),
- GNUNET_PQ_query_param_auto_from_type (&td->details.refresh.execution_date),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.refresh.amount_with_fee),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.refresh.old_coin_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.refresh.old_coin_sig),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.refresh.refresh_seed),
- GNUNET_PQ_query_param_uint32 (
- &td->details.refresh.noreveal_index),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.refresh.planchets_h),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.refresh.selected_h),
- td->details.refresh.no_blinding_seed
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (
- &td->details.refresh.blinding_seed),
- td->details.refresh.no_blinding_seed
- ? GNUNET_PQ_query_param_null ()
- : TALER_PQ_query_param_array_cs_r_pub (
- td->details.refresh.num_cs_r_values,
- td->details.refresh.cs_r_values,
- pg->conn),
- td->details.refresh.no_blinding_seed
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (
- &td->details.refresh.cs_r_choices),
- GNUNET_PQ_query_param_array_uint64 (
- td->details.refresh.num_coins,
- td->details.refresh.denom_serials,
- pg->conn),
- TALER_PQ_query_param_array_blinded_denom_sig (
- td->details.refresh.num_coins,
- td->details.refresh.denom_sigs,
- pg->conn),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_refresh",
- "INSERT INTO refresh"
- "(refresh_id"
- ",rc"
- ",execution_date"
- ",amount_with_fee"
- ",old_coin_pub"
- ",old_coin_sig"
- ",refresh_seed"
- ",noreveal_index"
- ",planchets_h"
- ",selected_h"
- ",blinding_seed"
- ",cs_r_values"
- ",cs_r_choices"
- ",denom_serials"
- ",denom_sigs"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6,$7,$8,$9,$10,$11,$12,$13,$14,$15);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_refresh",
- params);
-}
-
-
-/**
- * Function called with batch deposits records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_batch_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (&td->details.batch_deposits.shard),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.batch_deposits.merchant_pub),
- GNUNET_PQ_query_param_timestamp (
- &td->details.batch_deposits.wallet_timestamp),
- GNUNET_PQ_query_param_timestamp (
- &td->details.batch_deposits.exchange_timestamp),
- GNUNET_PQ_query_param_timestamp (
- &td->details.batch_deposits.refund_deadline),
- GNUNET_PQ_query_param_timestamp (&td->details.batch_deposits.wire_deadline),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.batch_deposits.h_contract_terms),
- td->details.batch_deposits.no_wallet_data_hash
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (
- &td->details.batch_deposits.wallet_data_hash),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.batch_deposits.wire_salt),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.batch_deposits.wire_target_h_payto),
- td->details.batch_deposits.no_policy_details
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (
- &td->details.batch_deposits.policy_details_serial_id),
- GNUNET_PQ_query_param_bool (td->details.batch_deposits.policy_blocked),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.batch_deposits.total_amount),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.batch_deposits.total_without_fee),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.batch_deposits.merchant_sig),
- GNUNET_PQ_query_param_bool (td->details.batch_deposits.done),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_batch_deposits",
- "INSERT INTO batch_deposits"
- "(batch_deposit_serial_id"
- ",shard"
- ",merchant_pub"
- ",wallet_timestamp"
- ",exchange_timestamp"
- ",refund_deadline"
- ",wire_deadline"
- ",h_contract_terms"
- ",wallet_data_hash"
- ",wire_salt"
- ",wire_target_h_payto"
- ",policy_details_serial_id"
- ",policy_blocked"
- ",total_amount"
- ",total_without_fee"
- ",merchant_sig"
- ",done"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
- " $11, $12, $13, $14, $15, $16, $17);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_batch_deposits",
- params);
-}
-
-
-/**
- * Function called with deposits records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_coin_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (
- &td->details.coin_deposits.batch_deposit_serial_id),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.coin_deposits.coin_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.coin_deposits.coin_sig),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.coin_deposits.amount_with_fee),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_coin_deposits",
- "INSERT INTO coin_deposits"
- "(coin_deposit_serial_id"
- ",batch_deposit_serial_id"
- ",coin_pub"
- ",coin_sig"
- ",amount_with_fee"
- ") VALUES "
- "($1, $2, $3, $4, $5);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_coin_deposits",
- params);
-}
-
-
-/**
- * Function called with refunds records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_refunds (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&td->details.refunds.coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&td->details.refunds.merchant_sig),
- GNUNET_PQ_query_param_uint64 (&td->details.refunds.rtransaction_id),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.refunds.amount_with_fee),
- GNUNET_PQ_query_param_uint64 (
- &td->details.refunds.batch_deposit_serial_id),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_refunds",
- "INSERT INTO refunds"
- "(refund_serial_id"
- ",coin_pub"
- ",merchant_sig"
- ",rtransaction_id"
- ",amount_with_fee"
- ",batch_deposit_serial_id"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_refunds",
- params);
-}
-
-
-/**
- * Function called with wire_out records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_wire_out (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_timestamp (&td->details.wire_out.execution_date),
- GNUNET_PQ_query_param_auto_from_type (&td->details.wire_out.wtid_raw),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wire_out.wire_target_h_payto),
- GNUNET_PQ_query_param_string (
- td->details.wire_out.exchange_account_section),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wire_out.amount),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_wire_out",
- "INSERT INTO wire_out"
- "(wireout_uuid"
- ",execution_date"
- ",wtid_raw"
- ",wire_target_h_payto"
- ",exchange_account_section"
- ",amount"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_wire_out",
- params);
-}
-
-
-/**
- * Function called with aggregation_tracking records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_aggregation_tracking (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (
- &td->details.aggregation_tracking.batch_deposit_serial_id),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.aggregation_tracking.wtid_raw),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_aggregation_tracking",
- "INSERT INTO aggregation_tracking"
- "(aggregation_serial_id"
- ",batch_deposit_serial_id"
- ",wtid_raw"
- ") VALUES "
- "($1, $2, $3);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_aggregation_tracking",
- params);
-}
-
-
-/**
- * Function called with wire_fee records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_wire_fee (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_string (td->details.wire_fee.wire_method),
- GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.start_date),
- GNUNET_PQ_query_param_timestamp (&td->details.wire_fee.end_date),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wire_fee.fees.wire),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wire_fee.fees.closing),
- GNUNET_PQ_query_param_auto_from_type (&td->details.wire_fee.master_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_wire_fee",
- "INSERT INTO wire_fee"
- "(wire_fee_serial"
- ",wire_method"
- ",start_date"
- ",end_date"
- ",wire_fee"
- ",closing_fee"
- ",master_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_wire_fee",
- params);
-}
-
-
-/**
- * Function called with wire_fee records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_global_fee (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (
- &td->serial),
- GNUNET_PQ_query_param_timestamp (
- &td->details.global_fee.start_date),
- GNUNET_PQ_query_param_timestamp (
- &td->details.global_fee.end_date),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.global_fee.fees.history),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.global_fee.fees.account),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.global_fee.fees.purse),
- GNUNET_PQ_query_param_relative_time (
- &td->details.global_fee.purse_timeout),
- GNUNET_PQ_query_param_relative_time (
- &td->details.global_fee.history_expiration),
- GNUNET_PQ_query_param_uint32 (
- &td->details.global_fee.purse_account_limit),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.global_fee.master_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_global_fee",
- "INSERT INTO global_fee"
- "(global_fee_serial"
- ",start_date"
- ",end_date"
- ",history_fee"
- ",account_fee"
- ",purse_fee"
- ",purse_timeout"
- ",history_expiration"
- ",purse_account_limit"
- ",master_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_global_fee",
- params);
-}
-
-
-/**
- * Function called with recoup records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_recoup (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&td->details.recoup.coin_sig),
- GNUNET_PQ_query_param_auto_from_type (&td->details.recoup.coin_blind),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.recoup.amount),
- GNUNET_PQ_query_param_timestamp (&td->details.recoup.timestamp),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.recoup.coin_pub),
- GNUNET_PQ_query_param_uint64 (&td->details.recoup.withdraw_serial_id),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_recoup",
- "INSERT INTO recoup"
- "(recoup_uuid"
- ",coin_sig"
- ",coin_blind"
- ",amount"
- ",recoup_timestamp"
- ",coin_pub"
- ",withdraw_serial_id"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_recoup",
- params);
-}
-
-
-/**
- * Function called with recoup_refresh records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_recoup_refresh (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&td->details.recoup_refresh.coin_sig),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.recoup_refresh.coin_blind),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.recoup_refresh.amount),
- GNUNET_PQ_query_param_timestamp (&td->details.recoup_refresh.timestamp),
- GNUNET_PQ_query_param_uint64 (&td->details.recoup_refresh.known_coin_id),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.recoup.coin_pub),
- GNUNET_PQ_query_param_uint64 (&td->details.recoup_refresh.rrc_serial),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_recoup_refresh",
- "INSERT INTO recoup_refresh"
- "(recoup_refresh_uuid"
- ",coin_sig"
- ",coin_blind"
- ",amount"
- ",recoup_timestamp"
- ",known_coin_id"
- ",coin_pub"
- ",rrc_serial"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_recoup_refresh",
- params);
-}
-
-
-/**
- * Function called with extensions records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_extensions (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_string (td->details.extensions.name),
- NULL == td->details.extensions.manifest ?
- GNUNET_PQ_query_param_null () :
- GNUNET_PQ_query_param_string (td->details.extensions.manifest),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_extensions",
- "INSERT INTO extensions"
- "(extension_id"
- ",name"
- ",manifest"
- ") VALUES "
- "($1, $2, $3);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_extensions",
- params);
-}
-
-
-/**
- * Function called with policy_details records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_policy_details (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.policy_details.hash_code),
- (td->details.policy_details.no_policy_json)
- ? GNUNET_PQ_query_param_null ()
- : TALER_PQ_query_param_json (td->details.policy_details.policy_json),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.policy_details.commitment),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.policy_details.accumulated_total),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.policy_details.fee),
- TALER_PQ_query_param_amount (pg->conn,
- &td->details.policy_details.transferable),
- GNUNET_PQ_query_param_timestamp (&td->details.policy_details.deadline),
- GNUNET_PQ_query_param_uint16 (
- &td->details.policy_details.fulfillment_state),
- (td->details.policy_details.no_fulfillment_id)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (
- &td->details.policy_details.fulfillment_id),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_policy_details",
- "INSERT INTO policy_details"
- "(policy_details_serial_id"
- ",policy_hash_code"
- ",policy_json"
- ",deadline"
- ",commitment"
- ",accumulated_total"
- ",fee"
- ",transferable"
- ",fulfillment_state"
- ",fulfillment_id"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_policy_details",
- params);
-}
-
-
-/**
- * Function called with policy_fulfillment records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_policy_fulfillments (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_timestamp (
- &td->details.policy_fulfillments.fulfillment_timestamp),
- (NULL == td->details.policy_fulfillments.fulfillment_proof)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (
- td->details.policy_fulfillments.fulfillment_proof),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.policy_fulfillments.h_fulfillment_proof),
- GNUNET_PQ_query_param_fixed_size (
- td->details.policy_fulfillments.policy_hash_codes,
- td->details.policy_fulfillments.policy_hash_codes_count),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_policy_fulfillments",
- "INSERT INTO policy_fulfillments "
- "(fulfillment_id"
- ",fulfillment_timestamp"
- ",fulfillment_proof"
- ",h_fulfillment_proof"
- ",policy_hash_codes"
- ") VALUES "
- "($1, $2, $3::TEXT::JSONB, $4, $5);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_policy_fulfillments",
- params);
-}
-
-
-/**
- * Function called with purse_requests records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_purse_requests (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.purse_requests.purse_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.purse_requests.merge_pub),
- GNUNET_PQ_query_param_timestamp (
- &td->details.purse_requests.purse_creation),
- GNUNET_PQ_query_param_timestamp (
- &td->details.purse_requests.purse_expiration),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.purse_requests.h_contract_terms),
- GNUNET_PQ_query_param_uint32 (&td->details.purse_requests.age_limit),
- GNUNET_PQ_query_param_uint32 (&td->details.purse_requests.flags),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.purse_requests.amount_with_fee),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.purse_requests.purse_fee),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.purse_requests.purse_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_purse_requests",
- "INSERT INTO purse_requests"
- "(purse_requests_serial_id"
- ",purse_pub"
- ",merge_pub"
- ",purse_creation"
- ",purse_expiration"
- ",h_contract_terms"
- ",age_limit"
- ",flags"
- ",amount_with_fee"
- ",purse_fee"
- ",purse_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_purse_requests",
- params);
-}
-
-
-/**
- * Function called with purse_decision records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_purse_decision (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.purse_decision.purse_pub),
- GNUNET_PQ_query_param_timestamp (
- &td->details.purse_decision.action_timestamp),
- GNUNET_PQ_query_param_bool (
- td->details.purse_decision.refunded),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_purse_refunds",
- "INSERT INTO purse_refunds"
- "(purse_refunds_serial_id"
- ",purse_pub"
- ",action_timestamp"
- ",refunded"
- ") VALUES "
- "($1, $2, $3, $4);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_purse_decision",
- params);
-}
-
-
-/**
- * Function called with purse_merges records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_purse_merges (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (&td->details.purse_merges.partner_serial_id),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.purse_merges.reserve_pub),
- GNUNET_PQ_query_param_auto_from_type (&td->details.purse_merges.purse_pub),
- GNUNET_PQ_query_param_auto_from_type (&td->details.purse_merges.merge_sig),
- GNUNET_PQ_query_param_timestamp (&td->details.purse_merges.merge_timestamp),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_purse_merges",
- "INSERT INTO purse_merges"
- "(purse_merge_request_serial_id"
- ",partner_serial_id"
- ",reserve_pub"
- ",purse_pub"
- ",merge_sig"
- ",merge_timestamp"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_purse_merges",
- params);
-}
-
-
-/**
- * Function called with purse_deposits records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_purse_deposits (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (
- &td->details.purse_deposits.partner_serial_id),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.purse_deposits.purse_pub),
- GNUNET_PQ_query_param_auto_from_type (&td->details.purse_deposits.coin_pub),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.purse_deposits.amount_with_fee),
- GNUNET_PQ_query_param_auto_from_type (&td->details.purse_deposits.coin_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_purse_deposits",
- "INSERT INTO purse_deposits"
- "(purse_deposit_serial_id"
- ",partner_serial_id"
- ",purse_pub"
- ",coin_pub"
- ",amount_with_fee"
- ",coin_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_purse_deposits",
- params);
-}
-
-
-/**
-x * Function called with account_mergers records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_account_mergers (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.account_merges.reserve_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.account_merges.reserve_sig),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.account_merges.purse_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.account_merges.wallet_h_payto),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_account_merges",
- "INSERT INTO account_merges"
- "(account_merge_request_serial_id"
- ",reserve_pub"
- ",reserve_sig"
- ",purse_pub"
- ",wallet_h_payto"
- ") VALUES "
- "($1, $2, $3, $4, $5);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_account_merges",
- params);
-}
-
-
-/**
- * Function called with history_requests records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_history_requests (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.history_requests.reserve_pub),
- GNUNET_PQ_query_param_timestamp (
- &td->details.history_requests.request_timestamp),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.history_requests.reserve_sig),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.history_requests.history_fee),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_history_requests",
- "INSERT INTO history_requests"
- "(history_request_serial_id"
- ",reserve_pub"
- ",request_timestamp"
- ",reserve_sig"
- ",history_fee"
- ") VALUES "
- "($1, $2, $3, $4, $5);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_history_requests",
- params);
-}
-
-
-/**
- * Function called with close_requests records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_close_requests (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.close_requests.reserve_pub),
- GNUNET_PQ_query_param_timestamp (
- &td->details.close_requests.close_timestamp),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.close_requests.reserve_sig),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.close_requests.close),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.close_requests.close_fee),
- GNUNET_PQ_query_param_string (
- td->details.close_requests.payto_uri.full_payto),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_close_requests",
- "INSERT INTO close_requests"
- "(close_request_serial_id"
- ",reserve_pub"
- ",close_timestamp"
- ",reserve_sig"
- ",close"
- ",close_fee"
- ",payto_uri"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_close_requests",
- params);
-}
-
-
-/**
- * Function called with wads_out records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_wads_out (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&td->details.wads_out.wad_id),
- GNUNET_PQ_query_param_uint64 (&td->details.wads_out.partner_serial_id),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wads_out.amount),
- GNUNET_PQ_query_param_timestamp (&td->details.wads_out.execution_time),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_wads_out",
- "INSERT INTO wads_out"
- "(wad_out_serial_id"
- ",wad_id"
- ",partner_serial_id"
- ",amount"
- ",execution_time"
- ") VALUES "
- "($1, $2, $3, $4, $5);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_wads_out",
- params);
-}
-
-
-/**
- * Function called with wads_out_entries records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_wads_out_entries (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_uint64 (
- &td->details.wads_out_entries.wad_out_serial_id),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_out_entries.reserve_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_out_entries.purse_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_out_entries.h_contract),
- GNUNET_PQ_query_param_timestamp (
- &td->details.wads_out_entries.purse_expiration),
- GNUNET_PQ_query_param_timestamp (
- &td->details.wads_out_entries.merge_timestamp),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wads_out_entries.amount_with_fee),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wads_out_entries.wad_fee),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wads_out_entries.deposit_fees),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_out_entries.reserve_sig),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_out_entries.purse_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_wad_out_entries",
- "INSERT INTO wad_out_entries"
- "(wad_out_entry_serial_id"
- ",wad_out_serial_id"
- ",reserve_pub"
- ",purse_pub"
- ",h_contract"
- ",purse_expiration"
- ",merge_timestamp"
- ",amount_with_fee"
- ",wad_fee"
- ",deposit_fees"
- ",reserve_sig"
- ",purse_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_wads_out_entries",
- params);
-}
-
-
-/**
- * Function called with wads_in records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_wads_in (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (&td->details.wads_in.wad_id),
- GNUNET_PQ_query_param_string (td->details.wads_in.origin_exchange_url),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wads_in.amount),
- GNUNET_PQ_query_param_timestamp (&td->details.wads_in.arrival_time),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_wads_in",
- "INSERT INTO wads_in"
- "(wad_in_serial_id"
- ",wad_id"
- ",origin_exchange_url"
- ",amount"
- ",arrival_time"
- ") VALUES "
- "($1, $2, $3, $4, $5);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_wads_in",
- params);
-}
-
-
-/**
- * Function called with wads_in_entries records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_wads_in_entries (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_in_entries.reserve_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_in_entries.purse_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_in_entries.h_contract),
- GNUNET_PQ_query_param_timestamp (
- &td->details.wads_in_entries.purse_expiration),
- GNUNET_PQ_query_param_timestamp (
- &td->details.wads_in_entries.merge_timestamp),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wads_in_entries.amount_with_fee),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wads_in_entries.wad_fee),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.wads_in_entries.deposit_fees),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_in_entries.reserve_sig),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.wads_in_entries.purse_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_wad_in_entries",
- "INSERT INTO wad_in_entries"
- "(wad_in_entry_serial_id"
- ",wad_in_serial_id"
- ",reserve_pub"
- ",purse_pub"
- ",h_contract"
- ",purse_expiration"
- ",merge_timestamp"
- ",amount_with_fee"
- ",wad_fee"
- ",deposit_fees"
- ",reserve_sig"
- ",purse_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_wads_in_entries",
- params);
-}
-
-
-/**
- * Function called with profit_drains records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_profit_drains (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.profit_drains.wtid),
- GNUNET_PQ_query_param_string (
- td->details.profit_drains.account_section),
- GNUNET_PQ_query_param_string (
- td->details.profit_drains.payto_uri.full_payto),
- GNUNET_PQ_query_param_timestamp (
- &td->details.profit_drains.trigger_date),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.profit_drains.amount),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.profit_drains.master_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_profit_drains",
- "INSERT INTO profit_drains"
- "(profit_drain_serial_id"
- ",wtid"
- ",account_section"
- ",payto_uri"
- ",trigger_date"
- ",amount"
- ",master_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_profit_drains",
- params);
-}
-
-
-/**
- * Function called with aml_staff records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_aml_staff (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.aml_staff.decider_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.aml_staff.master_sig),
- GNUNET_PQ_query_param_string (
- td->details.aml_staff.decider_name),
- GNUNET_PQ_query_param_bool (
- td->details.aml_staff.is_active),
- GNUNET_PQ_query_param_bool (
- td->details.aml_staff.read_only),
- GNUNET_PQ_query_param_timestamp (
- &td->details.aml_staff.last_change),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_aml_staff",
- "INSERT INTO aml_staff"
- "(aml_staff_uuid"
- ",decider_pub"
- ",master_sig"
- ",decider_name"
- ",is_active"
- ",read_only"
- ",last_change"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_aml_staff",
- params);
-}
-
-
-/**
- * Function called with kyc_attributes records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_kyc_attributes (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.kyc_attributes.h_payto),
- GNUNET_PQ_query_param_uint64 (
- &td->details.kyc_attributes.legitimization_serial),
- GNUNET_PQ_query_param_timestamp (
- &td->details.kyc_attributes.collection_time),
- GNUNET_PQ_query_param_timestamp (
- &td->details.kyc_attributes.expiration_time),
- GNUNET_PQ_query_param_uint64 (
- &td->details.kyc_attributes.trigger_outcome_serial),
- GNUNET_PQ_query_param_fixed_size (
- &td->details.kyc_attributes.encrypted_attributes,
- td->details.kyc_attributes.encrypted_attributes_size),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_kyc_attributes",
- "INSERT INTO kyc_attributes"
- "(kyc_attributes_serial_id"
- ",h_payto"
- ",legitimization_serial"
- ",collection_time"
- ",expiration_time"
- ",trigger_outcome_serial"
- ",encrypted_attributes"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_kyc_attributes",
- params);
-}
-
-
-/**
- * Function called with aml_history records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_aml_history (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.aml_history.h_payto),
- GNUNET_PQ_query_param_uint64 (
- &td->details.aml_history.outcome_serial_id),
- GNUNET_PQ_query_param_string (
- td->details.aml_history.justification),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.aml_history.decider_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.aml_history.decider_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_aml_history",
- "INSERT INTO aml_history"
- "(aml_history_serial_id"
- ",h_payto"
- ",outcome_serial_id"
- ",justification"
- ",decider_pub"
- ",decider_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_aml_history",
- params);
-}
-
-
-/**
- * Function called with kyc_event records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_kyc_events (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_timestamp (
- &td->details.kyc_events.event_timestamp),
- GNUNET_PQ_query_param_string (
- td->details.kyc_events.event_type),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_kyc_events",
- "INSERT INTO kyc_events"
- "(kyc_event_serial_id"
- ",event_timestamp"
- ",event_type"
- ") VALUES "
- "($1, $2, $3);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_kyc_events",
- params);
-}
-
-
-/**
- * Function called with purse_deletion records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_purse_deletion (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.purse_deletion.purse_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.purse_deletion.purse_sig),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_into_table_purse_deletion",
- "INSERT INTO purse_deletion"
- "(purse_deletion_serial_id"
- ",purse_pub"
- ",purse_sig"
- ") VALUES "
- "($1, $2, $3);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_purse_deletion",
- params);
-}
-
-
-/**
- * Function called with withdraw records to insert into table.
- *
- * @param pg plugin context
- * @param td record to insert
- */
-static enum GNUNET_DB_QueryStatus
-irbt_cb_table_withdraw (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_TableData *td)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&td->serial),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.withdraw.planchets_h),
- GNUNET_PQ_query_param_timestamp (
- &td->details.withdraw.execution_date),
- TALER_PQ_query_param_amount (
- pg->conn,
- &td->details.withdraw.amount_with_fee),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.withdraw.reserve_pub),
- GNUNET_PQ_query_param_auto_from_type (
- &td->details.withdraw.reserve_sig),
- td->details.withdraw.age_proof_required
- ? GNUNET_PQ_query_param_uint16 (
- &td->details.withdraw.max_age)
- : GNUNET_PQ_query_param_null (),
- td->details.withdraw.age_proof_required
- ? GNUNET_PQ_query_param_uint16 (
- &td->details.withdraw.noreveal_index)
- : GNUNET_PQ_query_param_null (),
- td->details.withdraw.age_proof_required
- ? GNUNET_PQ_query_param_auto_from_type (
- &td->details.withdraw.selected_h)
- : GNUNET_PQ_query_param_null (),
- td->details.withdraw.no_blinding_seed
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (
- &td->details.withdraw.blinding_seed),
- (0 < td->details.withdraw.num_cs_r_values)
- ? TALER_PQ_query_param_array_cs_r_pub (
- td->details.withdraw.num_cs_r_values,
- td->details.withdraw.cs_r_values,
- pg->conn)
- : GNUNET_PQ_query_param_null (),
- (0 < td->details.withdraw.num_cs_r_values)
- ? GNUNET_PQ_query_param_uint64 (
- &td->details.withdraw.cs_r_choices)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_array_uint64 (
- td->details.withdraw.num_coins,
- td->details.withdraw.denom_serials,
- pg->conn),
- TALER_PQ_query_param_array_blinded_denom_sig (
- td->details.withdraw.num_coins,
- td->details.withdraw.denom_sigs,
- pg->conn),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "insert_into_table_withdraw",
- "INSERT INTO withdraw"
- "(withdraw_id"
- ",planchets_h"
- ",execution_date"
- ",amount_with_fee"
- ",reserve_pub"
- ",reserve_sig"
- ",max_age"
- ",noreveal_index"
- ",selected_h"
- ",blinding_seed"
- ",cs_r_values"
- ",cs_r_choices"
- ",denom_serials"
- ",denom_sigs"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14);");
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_into_table_withdraw",
- params);
- GNUNET_PQ_cleanup_query_params_closures (params);
- return qs;
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_records_by_table (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- const struct
- TALER_EXCHANGEDB_TableData *td)
-{
- InsertRecordCallback rh = NULL;
-
- switch (td->table)
- {
- case TALER_EXCHANGEDB_RT_DENOMINATIONS:
- rh = &irbt_cb_table_denominations;
- break;
- case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS:
- rh = &irbt_cb_table_denomination_revocations;
- break;
- case TALER_EXCHANGEDB_RT_WIRE_TARGETS:
- rh = &irbt_cb_table_wire_targets;
- break;
- case TALER_EXCHANGEDB_RT_KYC_TARGETS:
- rh = &irbt_cb_table_kyc_targets;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES:
- rh = &irbt_cb_table_reserves;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_IN:
- rh = &irbt_cb_table_reserves_in;
- break;
- case TALER_EXCHANGEDB_RT_KYCAUTHS_IN:
- rh = &irbt_cb_table_kycauths_in;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_CLOSE:
- rh = &irbt_cb_table_reserves_close;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS:
- rh = &irbt_cb_table_reserves_open_requests;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
- rh = &irbt_cb_table_reserves_open_deposits;
- break;
- case TALER_EXCHANGEDB_RT_AUDITORS:
- rh = &irbt_cb_table_auditors;
- break;
- case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS:
- rh = &irbt_cb_table_auditor_denom_sigs;
- break;
- case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS:
- rh = &irbt_cb_table_exchange_sign_keys;
- break;
- case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS:
- rh = &irbt_cb_table_signkey_revocations;
- break;
- case TALER_EXCHANGEDB_RT_KNOWN_COINS:
- rh = &irbt_cb_table_known_coins;
- break;
- case TALER_EXCHANGEDB_RT_REFRESH:
- rh = &irbt_cb_table_refresh;
- break;
- case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS:
- rh = &irbt_cb_table_batch_deposits;
- break;
- case TALER_EXCHANGEDB_RT_COIN_DEPOSITS:
- rh = &irbt_cb_table_coin_deposits;
- break;
- case TALER_EXCHANGEDB_RT_REFUNDS:
- rh = &irbt_cb_table_refunds;
- break;
- case TALER_EXCHANGEDB_RT_WIRE_OUT:
- rh = &irbt_cb_table_wire_out;
- break;
- case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING:
- rh = &irbt_cb_table_aggregation_tracking;
- break;
- case TALER_EXCHANGEDB_RT_WIRE_FEE:
- rh = &irbt_cb_table_wire_fee;
- break;
- case TALER_EXCHANGEDB_RT_GLOBAL_FEE:
- rh = &irbt_cb_table_global_fee;
- break;
- case TALER_EXCHANGEDB_RT_RECOUP:
- rh = &irbt_cb_table_recoup;
- break;
- case TALER_EXCHANGEDB_RT_RECOUP_REFRESH:
- rh = &irbt_cb_table_recoup_refresh;
- break;
- case TALER_EXCHANGEDB_RT_EXTENSIONS:
- rh = &irbt_cb_table_extensions;
- break;
- case TALER_EXCHANGEDB_RT_POLICY_DETAILS:
- rh = &irbt_cb_table_policy_details;
- break;
- case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS:
- rh = &irbt_cb_table_policy_fulfillments;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
- rh = &irbt_cb_table_purse_requests;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_DECISION:
- rh = &irbt_cb_table_purse_decision;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_MERGES:
- rh = &irbt_cb_table_purse_merges;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS:
- rh = &irbt_cb_table_purse_deposits;
- break;
- case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES:
- rh = &irbt_cb_table_account_mergers;
- break;
- case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS:
- rh = &irbt_cb_table_history_requests;
- break;
- case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS:
- rh = &irbt_cb_table_close_requests;
- break;
- case TALER_EXCHANGEDB_RT_WADS_OUT:
- rh = &irbt_cb_table_wads_out;
- break;
- case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES:
- rh = &irbt_cb_table_wads_out_entries;
- break;
- case TALER_EXCHANGEDB_RT_WADS_IN:
- rh = &irbt_cb_table_wads_in;
- break;
- case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES:
- rh = &irbt_cb_table_wads_in_entries;
- break;
- case TALER_EXCHANGEDB_RT_PROFIT_DRAINS:
- rh = &irbt_cb_table_profit_drains;
- break;
- case TALER_EXCHANGEDB_RT_AML_STAFF:
- rh = &irbt_cb_table_aml_staff;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_DELETION:
- rh = &irbt_cb_table_purse_deletion;
- break;
- case TALER_EXCHANGEDB_RT_WITHDRAW:
- rh = &irbt_cb_table_withdraw;
- break;
- case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES:
- rh = &irbt_cb_table_legitimization_measures;
- break;
- case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES:
- rh = &irbt_cb_table_legitimization_outcomes;
- break;
- case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES:
- rh = &irbt_cb_table_legitimization_processes;
- break;
- case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES:
- rh = &irbt_cb_table_kyc_attributes;
- break;
- case TALER_EXCHANGEDB_RT_AML_HISTORY:
- rh = &irbt_cb_table_aml_history;
- break;
- case TALER_EXCHANGEDB_RT_KYC_EVENTS:
- rh = &irbt_cb_table_kyc_events;
- break;
- }
- if (NULL == rh)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- return rh (pg,
- td);
-}
-
-
-/* end of pg_insert_records_by_table.c */
diff --git a/src/exchangedb/pg_insert_refund.c b/src/exchangedb/pg_insert_refund.c
@@ -1,62 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_refund.c
- * @brief Implementation of the insert_refund function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_refund.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_refund (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_Refund *refund)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
- GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
- GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
- GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
- GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
- TALER_PQ_query_param_amount (pg->conn,
- &refund->details.refund_amount),
- GNUNET_PQ_query_param_end
- };
-
- GNUNET_assert (GNUNET_YES ==
- TALER_amount_cmp_currency (&refund->details.refund_amount,
- &refund->details.refund_fee));
- PREPARE (pg,
- "insert_refund",
- "INSERT INTO refunds "
- "(coin_pub"
- ",batch_deposit_serial_id"
- ",merchant_sig"
- ",rtransaction_id"
- ",amount_with_fee"
- ") SELECT $1, cdep.batch_deposit_serial_id, $3, $5, $6"
- " FROM coin_deposits cdep"
- " JOIN batch_deposits bdep USING (batch_deposit_serial_id)"
- " WHERE coin_pub=$1"
- " AND h_contract_terms=$4"
- " AND merchant_pub=$2");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_refund",
- params);
-}
diff --git a/src/exchangedb/pg_insert_reserve_closed.c b/src/exchangedb/pg_insert_reserve_closed.c
@@ -1,109 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_reserve_closed.c
- * @brief Implementation of the insert_reserve_closed function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_reserve_closed.h"
-#include "helper.h"
-#include "taler/exchange-database/reserves_get.h"
-#include "taler/exchange-database/reserves_update.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_reserve_closed (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- struct GNUNET_TIME_Timestamp execution_date,
- const struct TALER_FullPayto receiver_account,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- const struct TALER_Amount *amount_with_fee,
- const struct TALER_Amount *closing_fee,
- uint64_t close_request_row)
-{
- struct TALER_EXCHANGEDB_Reserve reserve;
- enum GNUNET_DB_QueryStatus qs;
- struct TALER_FullPaytoHashP h_payto;
-
- TALER_full_payto_hash (receiver_account,
- &h_payto);
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_timestamp (&execution_date),
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_auto_from_type (&h_payto),
- TALER_PQ_query_param_amount (pg->conn,
- amount_with_fee),
- TALER_PQ_query_param_amount (pg->conn,
- closing_fee),
- GNUNET_PQ_query_param_uint64 (&close_request_row),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "reserves_close_insert",
- "INSERT INTO reserves_close "
- "(reserve_pub"
- ",execution_date"
- ",wtid"
- ",wire_target_h_payto"
- ",amount"
- ",closing_fee"
- ",close_request_row"
- ") VALUES ($1, $2, $3, $4, $5, $6, $7);");
-
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "reserves_close_insert",
- params);
- }
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
- return qs;
-
- /* update reserve balance */
- reserve.pub = *reserve_pub;
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- (qs = TALER_EXCHANGEDB_reserves_get (pg,
- &reserve)))
- {
- /* Existence should have been checked before we got here... */
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- qs = GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
- }
- {
- enum TALER_AmountArithmeticResult ret;
-
- ret = TALER_amount_subtract (&reserve.balance,
- &reserve.balance,
- amount_with_fee);
- if (ret < 0)
- {
- /* The reserve history was checked to make sure there is enough of a balance
- left before we tried this; however, concurrent operations may have changed
- the situation by now. We should re-try the transaction. */
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Closing of reserve `%s' refused due to balance mismatch. Retrying.\n",
- TALER_B2S (reserve_pub));
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
- }
- return TALER_EXCHANGEDB_reserves_update (pg,
- &reserve);
-}
diff --git a/src/exchangedb/pg_insert_reserve_open_deposit.c b/src/exchangedb/pg_insert_reserve_open_deposit.c
@@ -1,63 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_insert_reserve_open_deposit.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_reserve_open_deposit.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_reserve_open_deposit (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinPublicInfo *cpi,
- const struct TALER_CoinSpendSignatureP *coin_sig,
- uint64_t known_coin_id,
- const struct TALER_Amount *coin_total,
- const struct TALER_ReserveSignatureP *reserve_sig,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- bool *insufficient_funds)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&cpi->coin_pub),
- GNUNET_PQ_query_param_uint64 (&known_coin_id),
- GNUNET_PQ_query_param_auto_from_type (coin_sig),
- GNUNET_PQ_query_param_auto_from_type (reserve_sig),
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- TALER_PQ_query_param_amount (pg->conn,
- coin_total),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("out_insufficient_funds",
- insufficient_funds),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "insert_reserve_open_deposit",
- "SELECT "
- " out_insufficient_funds"
- " FROM exchange_do_reserve_open_deposit"
- " ($1,$2,$3,$4,$5,$6);");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "insert_reserve_open_deposit",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_insert_sanction_list_hit.c b/src/exchangedb/pg_insert_sanction_list_hit.c
@@ -1,90 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_sanction_list_hit.c
- * @brief Implementation of the insert_sanction_list_hit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_sanction_list_hit.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_sanction_list_hit (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- bool to_investigate,
- const json_t *new_rules,
- const json_t *account_properties,
- unsigned int num_events,
- const char **events)
-{
- struct GNUNET_TIME_Timestamp never
- = GNUNET_TIME_UNIT_FOREVER_TS;
- struct GNUNET_TIME_Timestamp now
- = GNUNET_TIME_timestamp_get ();
- struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = *h_payto
- };
- char *notify_s
- = GNUNET_PQ_get_event_notify_channel (&rep.header);
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_timestamp (&now),
- GNUNET_PQ_query_param_timestamp (&never),
- NULL != account_properties
- ? TALER_PQ_query_param_json (account_properties)
- : GNUNET_PQ_query_param_null (),
- NULL != new_rules
- ? TALER_PQ_query_param_json (new_rules)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_bool (to_investigate),
- GNUNET_PQ_query_param_string (notify_s),
- GNUNET_PQ_query_param_array_ptrs_string (num_events,
- events,
- pg->conn),
- GNUNET_PQ_query_param_end
- };
- uint64_t outcome_serial_id;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("outcome_serial_id",
- &outcome_serial_id),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "do_insert_sanction_list_hit",
- "SELECT"
- " out_outcome_serial_id AS outcome_serial_id"
- " FROM exchange_do_insert_sanction_list_hit"
- "($1,$2,$3,$4::TEXT::JSONB,$5::TEXT::JSONB,$6,$7,$8);");
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Inserting LEGI OUTCOME from sanction list hit\n");
- qs = GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "do_insert_sanction_list_hit",
- params,
- rs);
- (void) outcome_serial_id;
- GNUNET_PQ_cleanup_query_params_closures (params);
- GNUNET_free (notify_s);
- GNUNET_PQ_event_do_poll (pg->conn);
- return qs;
-}
diff --git a/src/exchangedb/pg_insert_signkey_revocation.c b/src/exchangedb/pg_insert_signkey_revocation.c
@@ -1,49 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_signkey_revocation.c
- * @brief Implementation of the insert_signkey_revocation function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_signkey_revocation.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_signkey_revocation (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- const struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (exchange_pub),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_end
- };
-
-
- PREPARE (pg,
- "insert_signkey_revocation",
- "INSERT INTO signkey_revocations "
- "(esk_serial"
- ",master_sig"
- ") SELECT esk_serial, $2 "
- " FROM exchange_sign_keys"
- " WHERE exchange_pub=$1;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_signkey_revocation",
- params);
-}
diff --git a/src/exchangedb/pg_insert_successor_measure.c b/src/exchangedb/pg_insert_successor_measure.c
@@ -1,84 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2023, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_successor_measure.c
- * @brief Implementation of the insert_succesor_measure function for Postgres
- * @author Florian Dold
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_successor_measure.h"
-#include "helper.h"
-#include <gnunet/gnunet_pq_lib.h>
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_successor_measure (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- struct GNUNET_TIME_Timestamp decision_time,
- const char *new_measure_name,
- const json_t *jmeasures,
- bool *unknown_account,
- struct GNUNET_TIME_Timestamp *last_date)
-{
- struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = *h_payto
- };
- /* We're reverting back to default rules => never expires.*/
- struct GNUNET_TIME_Timestamp expiration_time = {
- .abs_time = GNUNET_TIME_UNIT_FOREVER_ABS,
- };
- char *notify_s
- = GNUNET_PQ_get_event_notify_channel (&rep.header);
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_timestamp (&decision_time),
- GNUNET_PQ_query_param_timestamp (&expiration_time),
- NULL != new_measure_name
- ? GNUNET_PQ_query_param_string (new_measure_name)
- : GNUNET_PQ_query_param_null (),
- NULL != jmeasures
- ? TALER_PQ_query_param_json (jmeasures)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("out_account_unknown",
- unknown_account),
- GNUNET_PQ_result_spec_timestamp ("out_last_date",
- last_date),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "do_insert_successor_measure",
- "SELECT"
- " out_account_unknown"
- ",out_last_date"
- ",out_legitimization_measure_serial_id"
- " FROM exchange_do_insert_successor_measure"
- "($1, $2, $3, $4, $5::TEXT::JSONB);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "do_insert_successor_measure",
- params,
- rs);
- GNUNET_free (notify_s);
- GNUNET_PQ_event_do_poll (pg->conn);
- return qs;
-}
diff --git a/src/exchangedb/pg_insert_wire.c b/src/exchangedb/pg_insert_wire.c
@@ -1,81 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2023, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_wire.c
- * @brief Implementation of the insert_wire function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_wire.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_insert_wire (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPayto payto_uri,
- const char *conversion_url,
- const char *open_banking_gateway,
- const char *wire_transfer_gateway,
- const json_t *debit_restrictions,
- const json_t *credit_restrictions,
- struct GNUNET_TIME_Timestamp start_date,
- const struct TALER_MasterSignatureP *master_sig,
- const char *bank_label,
- int64_t priority)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (payto_uri.full_payto),
- NULL == conversion_url
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (conversion_url),
- TALER_PQ_query_param_json (debit_restrictions),
- TALER_PQ_query_param_json (credit_restrictions),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_timestamp (&start_date),
- NULL == bank_label
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (bank_label),
- GNUNET_PQ_query_param_int64 (&priority),
- NULL == open_banking_gateway
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (open_banking_gateway),
- NULL == wire_transfer_gateway
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (wire_transfer_gateway),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_wire",
- "INSERT INTO wire_accounts "
- "(payto_uri"
- ",conversion_url"
- ",debit_restrictions"
- ",credit_restrictions"
- ",master_sig"
- ",is_active"
- ",last_change"
- ",bank_label"
- ",priority"
- ",open_banking_gateway"
- ",wire_transfer_gateway"
- ") VALUES "
- "($1,$2,$3::TEXT::JSONB,$4::TEXT::JSONB,$5,true,$6,$7,$8,$9,$10);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_wire",
- params);
-}
diff --git a/src/exchangedb/pg_insert_wire_fee.c b/src/exchangedb/pg_insert_wire_fee.c
@@ -1,108 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_insert_wire_fee.c
- * @brief Implementation of the insert_wire_fee function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/insert_wire_fee.h"
-#include "helper.h"
-#include "taler/exchange-database/get_wire_fee.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_insert_wire_fee (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- const char *type,
- struct GNUNET_TIME_Timestamp start_date,
- struct GNUNET_TIME_Timestamp end_date,
- const struct TALER_WireFeeSet *fees,
- const struct TALER_MasterSignatureP *
- master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (type),
- GNUNET_PQ_query_param_timestamp (&start_date),
- GNUNET_PQ_query_param_timestamp (&end_date),
- TALER_PQ_query_param_amount (pg->conn,
- &fees->wire),
- TALER_PQ_query_param_amount (pg->conn,
- &fees->closing),
- GNUNET_PQ_query_param_auto_from_type (master_sig),
- GNUNET_PQ_query_param_end
- };
- struct TALER_WireFeeSet wx;
- struct TALER_MasterSignatureP sig;
- struct GNUNET_TIME_Timestamp sd;
- struct GNUNET_TIME_Timestamp ed;
- enum GNUNET_DB_QueryStatus qs;
- uint64_t rowid;
-
- qs = TALER_EXCHANGEDB_get_wire_fee (pg,
- type,
- start_date,
- &rowid,
- &sd,
- &ed,
- &wx,
- &sig);
- if (qs < 0)
- return qs;
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- {
- if (0 != GNUNET_memcmp (&sig,
- master_sig))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (0 !=
- TALER_wire_fee_set_cmp (fees,
- &wx))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if ( (GNUNET_TIME_timestamp_cmp (sd,
- !=,
- start_date)) ||
- (GNUNET_TIME_timestamp_cmp (ed,
- !=,
- end_date)) )
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- /* equal record already exists */
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- }
-
- PREPARE (pg,
- "insert_wire_fee",
- "INSERT INTO wire_fee "
- "(wire_method"
- ",start_date"
- ",end_date"
- ",wire_fee"
- ",closing_fee"
- ",master_sig"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_wire_fee",
- params);
-}
diff --git a/src/exchangedb/pg_iterate_active_auditors.c b/src/exchangedb/pg_iterate_active_auditors.c
@@ -1,120 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_iterate_active_auditors.c
- * @brief Implementation of the iterate_active_auditors function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/iterate_active_auditors.h"
-#include "helper.h"
-
-
-/**
- * Closure for #auditors_cb_helper()
- */
-struct AuditorsIteratorContext
-{
- /**
- * Function to call with the results.
- */
- TALER_EXCHANGEDB_AuditorsCallback cb;
-
- /**
- * Closure to pass to @e cb
- */
- void *cb_cls;
-
-};
-
-
-/**
- * Helper function for #TALER_EXCHANGEDB_iterate_active_auditors().
- * Calls the callback with each auditor.
- *
- * @param cls a `struct SignkeysIteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-auditors_cb_helper (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct AuditorsIteratorContext *dic = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_AuditorPublicKeyP auditor_pub;
- char *auditor_url;
- char *auditor_name;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
- &auditor_pub),
- GNUNET_PQ_result_spec_string ("auditor_url",
- &auditor_url),
- GNUNET_PQ_result_spec_string ("auditor_name",
- &auditor_name),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- return;
- }
- dic->cb (dic->cb_cls,
- &auditor_pub,
- auditor_url,
- auditor_name);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_iterate_active_auditors (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- TALER_EXCHANGEDB_AuditorsCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_end
- };
- struct AuditorsIteratorContext dic = {
- .cb = cb,
- .cb_cls = cb_cls,
- };
-
- PREPARE (pg,
- "select_auditors",
- "SELECT"
- " auditor_pub"
- ",auditor_url"
- ",auditor_name"
- " FROM auditors"
- " WHERE"
- " is_active;");
-
- return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "select_auditors",
- params,
- &auditors_cb_helper,
- &dic);
-}
diff --git a/src/exchangedb/pg_iterate_active_signkeys.c b/src/exchangedb/pg_iterate_active_signkeys.c
@@ -1,142 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_iterate_active_signkeys.c
- * @brief Implementation of the iterate_active_signkeys function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/iterate_active_signkeys.h"
-#include "helper.h"
-
-
-/**
- * Closure for #signkeys_cb_helper()
- */
-struct SignkeysIteratorContext
-{
- /**
- * Function to call with the results.
- */
- TALER_EXCHANGEDB_ActiveSignkeysCallback cb;
-
- /**
- * Closure to pass to @e cb
- */
- void *cb_cls;
-
-};
-
-
-/**
- * Helper function for #TALER_EXCHANGEDB_iterate_active_signkeys().
- * Calls the callback with each signkey.
- *
- * @param cls a `struct SignkeysIteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-signkeys_cb_helper (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct SignkeysIteratorContext *dic = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_SignkeyMetaData meta;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_MasterSignatureP master_sig;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &master_sig),
- GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
- &exchange_pub),
- GNUNET_PQ_result_spec_timestamp ("valid_from",
- &meta.start),
- GNUNET_PQ_result_spec_timestamp ("expire_sign",
- &meta.expire_sign),
- GNUNET_PQ_result_spec_timestamp ("expire_legal",
- &meta.expire_legal),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- return;
- }
- dic->cb (dic->cb_cls,
- &exchange_pub,
- &meta,
- &master_sig);
- }
-}
-
-
-/**
- * Function called to invoke @a cb on every non-revoked exchange signing key
- * that has been signed by the master key. Revoked and (for signing!)
- * expired keys are skipped. Runs in its own read-only transaction.
- *
- * @param pg the database context
- * @param cb function to call on each signing key
- * @param cb_cls closure for @a cb
- * @return transaction status code
- */
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_iterate_active_signkeys (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- TALER_EXCHANGEDB_ActiveSignkeysCallback
- cb,
- void *cb_cls)
-{
- struct GNUNET_TIME_Absolute now = {0};
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_end
- };
- struct SignkeysIteratorContext dic = {
- .cb = cb,
- .cb_cls = cb_cls,
- };
-
- PREPARE (pg,
- "select_signkeys",
- "SELECT"
- " master_sig"
- ",exchange_pub"
- ",valid_from"
- ",expire_sign"
- ",expire_legal"
- " FROM exchange_sign_keys esk"
- " WHERE"
- " expire_sign > $1"
- " AND NOT EXISTS "
- " (SELECT esk_serial "
- " FROM signkey_revocations skr"
- " WHERE esk.esk_serial = skr.esk_serial);");
- now = GNUNET_TIME_absolute_get ();
- return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "select_signkeys",
- params,
- &signkeys_cb_helper,
- &dic);
-}
diff --git a/src/exchangedb/pg_iterate_auditor_denominations.c b/src/exchangedb/pg_iterate_auditor_denominations.c
@@ -1,117 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_iterate_auditor_denominations.c
- * @brief Implementation of the iterate_auditor_denominations function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/iterate_auditor_denominations.h"
-#include "helper.h"
-
-/**
- * Closure for #auditor_denoms_cb_helper()
- */
-struct AuditorDenomsIteratorContext
-{
- /**
- * Function to call with the results.
- */
- TALER_EXCHANGEDB_AuditorDenominationsCallback cb;
-
- /**
- * Closure to pass to @e cb
- */
- void *cb_cls;
-};
-
-
-/**
- * Helper function for #TALER_EXCHANGEDB_iterate_auditor_denominations().
- * Calls the callback with each auditor and denomination pair.
- *
- * @param cls a `struct AuditorDenomsIteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-auditor_denoms_cb_helper (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct AuditorDenomsIteratorContext *dic = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_AuditorPublicKeyP auditor_pub;
- struct TALER_DenominationHashP h_denom_pub;
- struct TALER_AuditorSignatureP auditor_sig;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
- &auditor_pub),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &h_denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("auditor_sig",
- &auditor_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- return;
- }
- dic->cb (dic->cb_cls,
- &auditor_pub,
- &h_denom_pub,
- &auditor_sig);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_iterate_auditor_denominations (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- TALER_EXCHANGEDB_AuditorDenominationsCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_end
- };
- struct AuditorDenomsIteratorContext dic = {
- .cb = cb,
- .cb_cls = cb_cls,
- };
- /* Used in #postgres_iterate_auditor_denominations() */
- PREPARE (pg,
- "select_auditor_denoms",
- "SELECT"
- " auditors.auditor_pub"
- ",denominations.denom_pub_hash"
- ",auditor_denom_sigs.auditor_sig"
- " FROM auditor_denom_sigs"
- " JOIN auditors USING (auditor_uuid)"
- " JOIN denominations USING (denominations_serial)"
- " WHERE auditors.is_active;");
- return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "select_auditor_denoms",
- params,
- &auditor_denoms_cb_helper,
- &dic);
-}
diff --git a/src/exchangedb/pg_iterate_denomination_info.c b/src/exchangedb/pg_iterate_denomination_info.c
@@ -1,185 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_iterate_denomination_info.c
- * @brief Implementation of the iterate_denomination_info function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/iterate_denomination_info.h"
-#include "helper.h"
-
-
-/**
- * Closure for #domination_cb_helper()
- */
-struct DenomIteratorContext
-{
- /**
- * Function to call with the results.
- */
- TALER_EXCHANGEDB_DenominationCallback cb;
-
- /**
- * Closure to pass to @e cb
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-};
-
-
-/**
- * Helper function for #TALER_EXCHANGEDB_iterate_denomination_info().
- * Calls the callback with each denomination key.
- *
- * @param cls a `struct DenomIteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-domination_cb_helper (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct DenomIteratorContext *dic = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dic->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
- struct TALER_DenominationPublicKey denom_pub;
- struct TALER_DenominationHashP denom_hash;
- uint64_t denom_serial;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("denominations_serial",
- &denom_serial),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &issue.signature),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &denom_hash),
- GNUNET_PQ_result_spec_timestamp ("valid_from",
- &issue.start),
- GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
- &issue.expire_withdraw),
- GNUNET_PQ_result_spec_timestamp ("expire_deposit",
- &issue.expire_deposit),
- GNUNET_PQ_result_spec_timestamp ("expire_legal",
- &issue.expire_legal),
- TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
- &issue.value),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
- &issue.fees.withdraw),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- &issue.fees.deposit),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
- &issue.fees.refresh),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
- &issue.fees.refund),
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &denom_pub),
- GNUNET_PQ_result_spec_uint32 ("age_mask",
- &issue.age_mask.bits),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- return;
- }
-
- /* Unfortunately we have to carry the age mask in both, the
- * TALER_DenominationPublicKey and
- * TALER_EXCHANGEDB_DenominationKeyInformation at different times.
- * Here we use _both_ so let's make sure the values are the same. */
- denom_pub.age_mask = issue.age_mask;
- TALER_denom_pub_hash (&denom_pub,
- &issue.denom_hash);
- if (0 !=
- GNUNET_memcmp (&issue.denom_hash,
- &denom_hash))
- {
- GNUNET_break (0);
- }
- else
- {
- dic->cb (dic->cb_cls,
- denom_serial,
- &denom_pub,
- &issue);
- }
- TALER_denom_pub_free (&denom_pub);
- }
-}
-
-
-/**
- * Fetch information about all known denomination keys.
- *
- * @param pg the database context
- * @param cb function to call on each denomination key
- * @param cb_cls closure for @a cb
- * @return transaction status code
- */
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_iterate_denomination_info (struct
- TALER_EXCHANGEDB_PostgresContext *pg
- ,
- TALER_EXCHANGEDB_DenominationCallback
- cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_end
- };
- struct DenomIteratorContext dic = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg
- };
-
- PREPARE (pg,
- "denomination_iterate",
- "SELECT"
- " denominations_serial"
- ",master_sig"
- ",denom_pub_hash"
- ",valid_from"
- ",expire_withdraw"
- ",expire_deposit"
- ",expire_legal"
- ",coin" /* value of this denom */
- ",fee_withdraw"
- ",fee_deposit"
- ",fee_refresh"
- ",fee_refund"
- ",denom_pub"
- ",age_mask"
- " FROM denominations;");
- return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "denomination_iterate",
- params,
- &domination_cb_helper,
- &dic);
-}
diff --git a/src/exchangedb/pg_iterate_denominations.c b/src/exchangedb/pg_iterate_denominations.c
@@ -1,175 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_iterate_denominations.c
- * @brief Implementation of the iterate_denominations function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/iterate_denominations.h"
-#include "helper.h"
-
-
-/**
- * Closure for #dominations_cb_helper()
- */
-struct DenomsIteratorContext
-{
- /**
- * Function to call with the results.
- */
- TALER_EXCHANGEDB_DenominationsCallback cb;
-
- /**
- * Closure to pass to @e cb
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-};
-
-
-/**
- * Helper function for #TALER_EXCHANGEDB_iterate_denominations().
- * Calls the callback with each denomination key.
- *
- * @param cls a `struct DenomsIteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-dominations_cb_helper (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct DenomsIteratorContext *dic = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dic->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_DenominationKeyMetaData meta = {0};
- struct TALER_DenominationPublicKey denom_pub = {0};
- struct TALER_MasterSignatureP master_sig = {0};
- struct TALER_DenominationHashP h_denom_pub = {0};
- bool revoked;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("denominations_serial",
- &meta.serial),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &master_sig),
- GNUNET_PQ_result_spec_bool ("revoked",
- &revoked),
- GNUNET_PQ_result_spec_timestamp ("valid_from",
- &meta.start),
- GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
- &meta.expire_withdraw),
- GNUNET_PQ_result_spec_timestamp ("expire_deposit",
- &meta.expire_deposit),
- GNUNET_PQ_result_spec_timestamp ("expire_legal",
- &meta.expire_legal),
- TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
- &meta.value),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
- &meta.fees.withdraw),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- &meta.fees.deposit),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
- &meta.fees.refresh),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
- &meta.fees.refund),
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &denom_pub),
- GNUNET_PQ_result_spec_uint32 ("age_mask",
- &meta.age_mask.bits),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- return;
- }
-
- /* make sure the mask information is the same */
- denom_pub.age_mask = meta.age_mask;
-
- TALER_denom_pub_hash (&denom_pub,
- &h_denom_pub);
- dic->cb (dic->cb_cls,
- &denom_pub,
- &h_denom_pub,
- &meta,
- &master_sig,
- revoked);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_iterate_denominations (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- TALER_EXCHANGEDB_DenominationsCallback
- cb,
- void *cb_cls)
-{
- struct GNUNET_TIME_Absolute now
- = GNUNET_TIME_absolute_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_end
- };
- struct DenomsIteratorContext dic = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg
- };
-
- PREPARE (pg,
- "select_denominations",
- "SELECT"
- " denominations_serial"
- ",denominations.master_sig"
- ",denom_revocations_serial_id IS NOT NULL AS revoked"
- ",valid_from"
- ",expire_withdraw"
- ",expire_deposit"
- ",expire_legal"
- ",coin" /* value of this denom */
- ",fee_withdraw"
- ",fee_deposit"
- ",fee_refresh"
- ",fee_refund"
- ",denom_type"
- ",age_mask"
- ",denom_pub"
- " FROM denominations"
- " LEFT JOIN "
- " denomination_revocations USING (denominations_serial)"
- " WHERE expire_deposit > $1;");
- return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "select_denominations",
- params,
- &dominations_cb_helper,
- &dic);
-}
diff --git a/src/exchangedb/pg_iterate_kyc_reference.c b/src/exchangedb/pg_iterate_kyc_reference.c
@@ -1,126 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_iterate_kyc_reference.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/iterate_kyc_reference.h"
-#include "helper.h"
-
-
-/**
- * Closure for #iterate_kyc_reference_cb()
- */
-struct IteratorContext
-{
- /**
- * Function to call with the results.
- */
- TALER_EXCHANGEDB_LegitimizationProcessCallback cb;
-
- /**
- * Closure to pass to @e cb
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-};
-
-
-/**
- * Helper function for #TALER_EXCHANGEDB_iterate_kyc_reference().
- * Calls the callback with each denomination key.
- *
- * @param cls a `struct IteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-iterate_kyc_reference_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct IteratorContext *ic = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- char *kyc_provider_name_name;
- char *provider_user_id;
- char *legitimization_id;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("provider_name",
- &kyc_provider_name_name),
- GNUNET_PQ_result_spec_string ("provider_user_id",
- &provider_user_id),
- GNUNET_PQ_result_spec_string ("provider_legitimization_id",
- &legitimization_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- return;
- }
- ic->cb (ic->cb_cls,
- kyc_provider_name_name,
- provider_user_id,
- legitimization_id);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_iterate_kyc_reference (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- TALER_EXCHANGEDB_LegitimizationProcessCallback lpc,
- void *lpc_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_end
- };
- struct IteratorContext ic = {
- .cb = lpc,
- .cb_cls = lpc_cls,
- .pg = pg
- };
-
- PREPARE (pg,
- "iterate_kyc_reference",
- "SELECT "
- " provider_name"
- ",provider_user_id"
- ",provider_legitimization_id"
- " FROM legitimization_processes"
- " WHERE h_payto=$1;");
- return GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "iterate_kyc_reference",
- params,
- &iterate_kyc_reference_cb,
- &ic);
-}
diff --git a/src/exchangedb/pg_iterate_reserve_close_info.c b/src/exchangedb/pg_iterate_reserve_close_info.c
@@ -1,127 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_iterate_reserve_close_info.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/iterate_reserve_close_info.h"
-#include "helper.h"
-
-/**
- * Closure for #iterate_reserve_close_info_cb()
- */
-struct IteratorContext
-{
- /**
- * Function to call with the results.
- */
- TALER_KYCLOGIC_KycAmountCallback cb;
-
- /**
- * Closure to pass to @e cb
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-};
-
-
-/**
- * Helper function for #TALER_EXCHANGEDB_iterate_reserve_close_info().
- * Calls the callback with each denomination key.
- *
- * @param cls a `struct IteratorContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-iterate_reserve_close_info_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct IteratorContext *ic = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ic->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_Amount amount;
- struct GNUNET_TIME_Absolute ts;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_absolute_time ("execution_date",
- &ts),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- return;
- }
- ic->cb (ic->cb_cls,
- &amount,
- ts);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_iterate_reserve_close_info (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- struct GNUNET_TIME_Absolute time_limit,
- TALER_KYCLOGIC_KycAmountCallback kac,
- void *kac_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_absolute_time (&time_limit),
- GNUNET_PQ_query_param_end
- };
- struct IteratorContext ic = {
- .cb = kac,
- .cb_cls = kac_cls,
- .pg = pg
- };
-
- PREPARE (pg,
- "iterate_reserve_close_info",
- "SELECT amount"
- " ,execution_date"
- " FROM reserves_close"
- " WHERE wire_target_h_payto IN ("
- " SELECT wire_target_h_payto"
- " FROM wire_targets"
- " WHERE h_normalized_payto=$1"
- " )"
- " AND execution_date >= $2"
- " ORDER BY execution_date DESC");
- return GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "iterate_reserve_close_info",
- params,
- &iterate_reserve_close_info_cb,
- &ic);
-}
diff --git a/src/exchangedb/pg_kyc_provider_account_lookup.c b/src/exchangedb/pg_kyc_provider_account_lookup.c
@@ -1,66 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_kyc_provider_account_lookup.c
- * @brief Implementation of the kyc_provider_account_lookup function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/kyc_provider_account_lookup.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_kyc_provider_account_lookup (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *provider_name,
- const char *provider_legitimization_id,
- struct TALER_NormalizedPaytoHashP *h_payto,
- bool *is_wallet,
- uint64_t *process_row)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (provider_legitimization_id),
- GNUNET_PQ_query_param_string (provider_name),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("h_payto",
- h_payto),
- GNUNET_PQ_result_spec_bool ("is_wallet",
- is_wallet),
- GNUNET_PQ_result_spec_uint64 ("legitimization_process_serial_id",
- process_row),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_wire_target_by_legitimization_id",
- "SELECT "
- " lp.h_payto"
- ",kt.is_wallet"
- ",lp.legitimization_process_serial_id"
- " FROM legitimization_processes lp"
- " JOIN kyc_targets kt"
- " ON (lp.h_payto = kt.h_normalized_payto)"
- " WHERE provider_legitimization_id=$1"
- " AND provider_name=$2;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "get_wire_target_by_legitimization_id",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_kycauth_in_insert.c b/src/exchangedb/pg_kycauth_in_insert.c
@@ -1,78 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_kycauth_in_insert.c
- * @brief Implementation of the kycauth_in_insert function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/kycauth_in_insert.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_kycauth_in_insert (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const union TALER_AccountPublicKeyP *account_pub,
- const struct TALER_Amount *credit_amount,
- struct GNUNET_TIME_Timestamp execution_date,
- const struct TALER_FullPayto debit_account_uri,
- const char *section_name,
- uint64_t serial_id)
-{
- struct TALER_NormalizedPaytoHashP h_normalized_payto;
- struct TALER_FullPaytoHashP h_full_payto;
-
- TALER_full_payto_hash (debit_account_uri,
- &h_full_payto);
- TALER_full_payto_normalize_and_hash (debit_account_uri,
- &h_normalized_payto);
- {
- struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = h_normalized_payto
- };
- char *notify_s
- = GNUNET_PQ_get_event_notify_channel (&rep.header);
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_uint64 (&serial_id),
- TALER_PQ_query_param_amount (pg->conn,
- credit_amount),
- GNUNET_PQ_query_param_auto_from_type (&h_full_payto),
- GNUNET_PQ_query_param_auto_from_type (&h_normalized_payto),
- GNUNET_PQ_query_param_string (debit_account_uri.full_payto),
- GNUNET_PQ_query_param_string (section_name),
- GNUNET_PQ_query_param_timestamp (&execution_date),
- GNUNET_PQ_query_param_string (notify_s),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "kycauth_in_insert",
- "CALL"
- " exchange_do_kycauth_in_insert"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
- qs = GNUNET_PQ_eval_prepared_non_select (
- pg->conn,
- "kycauth_in_insert",
- params);
- GNUNET_free (notify_s);
- return qs;
- }
-}
diff --git a/src/exchangedb/pg_lookup_active_legitimization.c b/src/exchangedb/pg_lookup_active_legitimization.c
@@ -1,62 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_pending_legitimization.c
- * @brief Implementation of the lookup_pending_legitimization function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_active_legitimization.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_active_legitimization (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t legitimization_process_serial_id,
- uint32_t *measure_index,
- json_t **jmeasures)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&legitimization_process_serial_id),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_json (
- "jmeasures",
- jmeasures),
- GNUNET_PQ_result_spec_uint32 (
- "measure_index",
- measure_index),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "lookup_active_legitimization",
- "SELECT "
- " lm.jmeasures::TEXT"
- ",lp.measure_index"
- " FROM legitimization_processes lp"
- " JOIN legitimization_measures lm"
- " USING (legitimization_measure_serial_id)"
- " WHERE lp.legitimization_process_serial_id=$1"
- " AND NOT lm.is_finished;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "lookup_active_legitimization",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_aml_file_number.c b/src/exchangedb/pg_lookup_aml_file_number.c
@@ -1,59 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_aml_file_number.c
- * @brief Implementation of the lookup_aml_file_number function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_aml_file_number.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_aml_file_number (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- uint64_t *kyc_target_row,
- bool *is_wallet)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "kyc_target_serial_id",
- kyc_target_row),
- GNUNET_PQ_result_spec_bool (
- "is_wallet",
- is_wallet),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "lookup_aml_file_number",
- "SELECT "
- " kyc_target_serial_id"
- ",is_wallet"
- " FROM kyc_targets"
- " WHERE h_normalized_payto=$1");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "lookup_aml_file_number",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_aml_history.c b/src/exchangedb/pg_lookup_aml_history.c
@@ -1,200 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_aml_history.c
- * @brief Implementation of the lookup_aml_history function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_aml_history.h"
-#include "helper.h"
-
-
-/**
- * Closure for callbacks called from #TALER_EXCHANGEDB_lookup_aml_history()
- */
-struct AmlHistoryContext
-{
-
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_AmlHistoryCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to 'true' if the transaction failed.
- */
- bool failed;
-
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct AmlHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_aml_entry (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct AmlHistoryContext *ahc = cls;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- uint64_t outcome_serial_id;
- struct GNUNET_TIME_Timestamp decision_time;
- char *justification;
- struct TALER_AmlOfficerPublicKeyP decider_pub;
- json_t *jproperties;
- json_t *jnew_rules = NULL;
- bool to_investigate;
- bool is_active;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("outcome_serial_id",
- &outcome_serial_id),
- GNUNET_PQ_result_spec_timestamp ("decision_time",
- &decision_time),
- GNUNET_PQ_result_spec_string ("justification",
- &justification),
- GNUNET_PQ_result_spec_auto_from_type ("decider_pub",
- &decider_pub),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("jproperties",
- &jproperties),
- NULL),
- TALER_PQ_result_spec_json ("jnew_rules",
- &jnew_rules),
- GNUNET_PQ_result_spec_bool ("to_investigate",
- &to_investigate),
- GNUNET_PQ_result_spec_bool ("is_active",
- &is_active),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ahc->failed = true;
- return;
- }
- ahc->cb (ahc->cb_cls,
- outcome_serial_id,
- decision_time,
- justification,
- &decider_pub,
- jproperties,
- jnew_rules,
- to_investigate,
- is_active);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_aml_history (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- uint64_t offset,
- int64_t limit,
- TALER_EXCHANGEDB_AmlHistoryCallback cb,
- void *cb_cls)
-{
- struct AmlHistoryContext ahc = {
- .pg = pg,
- .cb = cb,
- .cb_cls = cb_cls
- };
- uint64_t ulimit = (limit < 0) ? (-limit) : limit;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_uint64 (&offset),
- GNUNET_PQ_query_param_uint64 (&ulimit),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "lookup_aml_history_desc",
- "SELECT"
- " lo.decision_time"
- ",lo.outcome_serial_id"
- ",ah.justification"
- ",ah.decider_pub"
- ",lo.jproperties::TEXT"
- ",lo.jnew_rules::TEXT"
- ",lo.to_investigate"
- ",lo.is_active"
- " FROM aml_history ah"
- " JOIN legitimization_outcomes lo"
- " USING (outcome_serial_id)"
- " WHERE ah.h_payto=$1"
- " AND lo.outcome_serial_id < $2"
- " ORDER BY outcome_serial_id DESC"
- " LIMIT $3;");
- PREPARE (pg,
- "lookup_aml_history_asc",
- "SELECT"
- " lo.decision_time"
- ",lo.outcome_serial_id"
- ",ah.justification"
- ",ah.decider_pub"
- ",lo.jproperties::TEXT"
- ",lo.jnew_rules::TEXT"
- ",lo.to_investigate"
- ",lo.is_active"
- " FROM aml_history ah"
- " JOIN legitimization_outcomes lo"
- " USING (outcome_serial_id)"
- " WHERE ah.h_payto=$1"
- " AND lo.outcome_serial_id > $2"
- " ORDER BY outcome_serial_id ASC"
- " LIMIT $3;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- (limit < 0)
- ? "lookup_aml_history_desc"
- : "lookup_aml_history_asc",
- params,
- &handle_aml_entry,
- &ahc);
- if (qs <= 0)
- return qs;
- if (ahc.failed)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_lookup_aml_officer.c b/src/exchangedb/pg_lookup_aml_officer.c
@@ -1,68 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_aml_officer.c
- * @brief Implementation of the lookup_aml_officer function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_aml_officer.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_aml_officer (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AmlOfficerPublicKeyP *decider_pub,
- struct TALER_MasterSignatureP *master_sig,
- char **decider_name,
- bool *is_active,
- bool *read_only,
- struct GNUNET_TIME_Absolute *last_change)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (decider_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- master_sig),
- GNUNET_PQ_result_spec_string ("decider_name",
- decider_name),
- GNUNET_PQ_result_spec_bool ("is_active",
- is_active),
- GNUNET_PQ_result_spec_bool ("read_only",
- read_only),
- GNUNET_PQ_result_spec_absolute_time ("last_change",
- last_change),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "lookup_aml_officer",
- "SELECT "
- " master_sig"
- ",decider_name"
- ",is_active"
- ",read_only"
- ",last_change"
- " FROM aml_staff"
- " WHERE decider_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "lookup_aml_officer",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_auditor_status.c b/src/exchangedb/pg_lookup_auditor_status.c
@@ -1,57 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_auditor_status.c
- * @brief Implementation of the lookup_auditor_status function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_auditor_status.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_auditor_status (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AuditorPublicKeyP *auditor_pub,
- char **auditor_url,
- bool *enabled)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (auditor_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("auditor_url",
- auditor_url),
- GNUNET_PQ_result_spec_bool ("is_active",
- enabled),
- GNUNET_PQ_result_spec_end
- };
-
- /* Used in #postgres_lookup_auditor_status() */
- PREPARE (pg,
- "lookup_auditor_status",
- "SELECT"
- " auditor_url"
- ",is_active"
- " FROM auditors"
- " WHERE auditor_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_auditor_status",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_auditor_timestamp.c b/src/exchangedb/pg_lookup_auditor_timestamp.c
@@ -1,53 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_auditor_timestamp.c
- * @brief Implementation of the lookup_auditor_timestamp function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_auditor_timestamp.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_auditor_timestamp (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AuditorPublicKeyP *auditor_pub,
- struct GNUNET_TIME_Timestamp *last_date)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (auditor_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("last_change",
- last_date),
- GNUNET_PQ_result_spec_end
- };
-
- /* Used in #postgres_lookup_auditor_timestamp() */
- PREPARE (pg,
- "lookup_auditor_timestamp",
- "SELECT"
- " last_change"
- " FROM auditors"
- " WHERE auditor_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_auditor_timestamp",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_completed_legitimization.c b/src/exchangedb/pg_lookup_completed_legitimization.c
@@ -1,95 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_completed_legitimization.c
- * @brief Implementation of the lookup_pending_legitimization function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_completed_legitimization.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_completed_legitimization (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t legitimization_measure_serial_id,
- uint32_t measure_index,
- struct TALER_AccountAccessTokenP *access_token,
- struct TALER_NormalizedPaytoHashP *h_payto,
- bool *is_wallet,
- json_t **jmeasures,
- bool *is_finished,
- size_t *encrypted_attributes_len,
- void **encrypted_attributes
- )
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id),
- GNUNET_PQ_query_param_uint32 (&measure_index),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_json (
- "jmeasures",
- jmeasures),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_normalized_payto",
- h_payto),
- GNUNET_PQ_result_spec_auto_from_type (
- "access_token",
- access_token),
- GNUNET_PQ_result_spec_bool (
- "is_finished",
- is_finished),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_variable_size (
- "encrypted_attributes",
- encrypted_attributes,
- encrypted_attributes_len),
- NULL),
- GNUNET_PQ_result_spec_bool (
- "is_wallet",
- is_wallet),
- GNUNET_PQ_result_spec_end
- };
-
- *encrypted_attributes_len = 0;
- *encrypted_attributes = NULL;
- PREPARE (pg,
- "lookup_completed_legitimization",
- "SELECT "
- " lm.jmeasures::TEXT"
- ",kt.h_normalized_payto"
- ",kt.is_wallet"
- ",lm.access_token"
- ",lm.is_finished"
- ",ka.encrypted_attributes"
- " FROM legitimization_measures lm"
- " JOIN kyc_targets kt"
- " ON (lm.access_token = kt.access_token)"
- " LEFT JOIN legitimization_processes lp"
- " ON (lm.legitimization_measure_serial_id = lp.legitimization_measure_serial_id)"
- " LEFT JOIN kyc_attributes ka"
- " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)"
- " WHERE lm.legitimization_measure_serial_id=$1"
- " AND lp.measure_index=$2;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "lookup_completed_legitimization",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_denomination_key.c b/src/exchangedb/pg_lookup_denomination_key.c
@@ -1,79 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_denomination_key.c
- * @brief Implementation of the lookup_denomination_key function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_denomination_key.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_denomination_key (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_DenominationHashP *h_denom_pub,
- struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("valid_from",
- &meta->start),
- GNUNET_PQ_result_spec_timestamp ("expire_withdraw",
- &meta->expire_withdraw),
- GNUNET_PQ_result_spec_timestamp ("expire_deposit",
- &meta->expire_deposit),
- GNUNET_PQ_result_spec_timestamp ("expire_legal",
- &meta->expire_legal),
- TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
- &meta->value),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
- &meta->fees.withdraw),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- &meta->fees.deposit),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
- &meta->fees.refresh),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
- &meta->fees.refund),
- GNUNET_PQ_result_spec_uint32 ("age_mask",
- &meta->age_mask.bits),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "lookup_denomination_key",
- "SELECT"
- " valid_from"
- ",expire_withdraw"
- ",expire_deposit"
- ",expire_legal"
- ",coin"
- ",fee_withdraw"
- ",fee_deposit"
- ",fee_refresh"
- ",fee_refund"
- ",age_mask"
- " FROM denominations"
- " WHERE denom_pub_hash=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_denomination_key",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_global_fee_by_time.c b/src/exchangedb/pg_lookup_global_fee_by_time.c
@@ -1,180 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_global_fee_by_time.c
- * @brief Implementation of the lookup_global_fee_by_time function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_dbevents.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_global_fee_by_time.h"
-#include "helper.h"
-
-/**
- * Closure for #global_fee_by_time_helper()
- */
-struct GlobalFeeLookupContext
-{
-
- /**
- * Set to the wire fees. Set to invalid if fees conflict over
- * the given time period.
- */
- struct TALER_GlobalFeeSet *fees;
-
- /**
- * Set to timeout of unmerged purses
- */
- struct GNUNET_TIME_Relative *purse_timeout;
-
- /**
- * Set to history expiration for reserves.
- */
- struct GNUNET_TIME_Relative *history_expiration;
-
- /**
- * Set to number of free purses per account.
- */
- uint32_t *purse_account_limit;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-};
-
-
-/**
- * Helper function for #TALER_EXCHANGEDB_lookup_global_fee_by_time().
- * Calls the callback with each denomination key.
- *
- * @param cls a `struct GlobalFeeLookupContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-global_fee_by_time_helper (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct GlobalFeeLookupContext *wlc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = wlc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_GlobalFeeSet fs;
- struct GNUNET_TIME_Relative purse_timeout;
- struct GNUNET_TIME_Relative history_expiration;
- uint32_t purse_account_limit;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
- &fs.history),
- TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
- &fs.account),
- TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
- &fs.purse),
- GNUNET_PQ_result_spec_relative_time ("purse_timeout",
- &purse_timeout),
- GNUNET_PQ_result_spec_relative_time ("history_expiration",
- &history_expiration),
- GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
- &purse_account_limit),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- /* invalidate */
- memset (wlc->fees,
- 0,
- sizeof (struct TALER_GlobalFeeSet));
- return;
- }
- if (0 == i)
- {
- *wlc->fees = fs;
- *wlc->purse_timeout = purse_timeout;
- *wlc->history_expiration = history_expiration;
- *wlc->purse_account_limit = purse_account_limit;
- continue;
- }
- if ( (0 !=
- TALER_global_fee_set_cmp (&fs,
- wlc->fees)) ||
- (purse_account_limit != *wlc->purse_account_limit) ||
- (GNUNET_TIME_relative_cmp (purse_timeout,
- !=,
- *wlc->purse_timeout)) ||
- (GNUNET_TIME_relative_cmp (history_expiration,
- !=,
- *wlc->history_expiration)) )
- {
- /* invalidate */
- memset (wlc->fees,
- 0,
- sizeof (struct TALER_GlobalFeeSet));
- return;
- }
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_global_fee_by_time (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct GNUNET_TIME_Timestamp start_time,
- struct GNUNET_TIME_Timestamp end_time,
- struct TALER_GlobalFeeSet *fees,
- struct GNUNET_TIME_Relative *purse_timeout,
- struct GNUNET_TIME_Relative *history_expiration,
- uint32_t *purse_account_limit)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&start_time),
- GNUNET_PQ_query_param_timestamp (&end_time),
- GNUNET_PQ_query_param_end
- };
- struct GlobalFeeLookupContext wlc = {
- .fees = fees,
- .purse_timeout = purse_timeout,
- .history_expiration = history_expiration,
- .purse_account_limit = purse_account_limit,
- .pg = pg
- };
-
- PREPARE (pg,
- "lookup_global_fee_by_time",
- "SELECT"
- " history_fee"
- ",account_fee"
- ",purse_fee"
- ",purse_timeout"
- ",history_expiration"
- ",purse_account_limit"
- " FROM global_fee"
- " WHERE end_date > $1"
- " AND start_date < $2;");
- return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "lookup_global_fee_by_time",
- params,
- &global_fee_by_time_helper,
- &wlc);
-}
diff --git a/src/exchangedb/pg_lookup_h_payto_by_access_token.c b/src/exchangedb/pg_lookup_h_payto_by_access_token.c
@@ -1,59 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_h_payto_by_access_token.c
- * @brief Implementation of the lookup_h_payto_by_access_token function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_h_payto_by_access_token.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_h_payto_by_access_token (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AccountAccessTokenP *access_token,
- struct TALER_NormalizedPaytoHashP *h_payto,
- bool *is_wallet)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (access_token),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type (
- "h_normalized_payto",
- h_payto),
- GNUNET_PQ_result_spec_bool (
- "is_wallet",
- is_wallet),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "lookup_h_payto_by_access_token",
- "SELECT "
- " h_normalized_payto"
- " ,is_wallet"
- " FROM kyc_targets"
- " WHERE (access_token = $1);");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "lookup_h_payto_by_access_token",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_kyc_history.c b/src/exchangedb/pg_lookup_kyc_history.c
@@ -1,192 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_kyc_history.c
- * @brief Implementation of the lookup_kyc_history function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_kyc_history.h"
-#include "helper.h"
-
-/**
- * Closure for callbacks called from #TALER_EXCHANGEDB_lookup_kyc_history()
- */
-struct KycHistoryContext
-{
-
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_KycHistoryCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to 'true' if the transaction failed.
- */
- bool failed;
-
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct KycHistoryContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_kyc_entry (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct KycHistoryContext *khc = cls;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- char *provider_name = NULL;
- bool finished;
- uint32_t error_code;
- char *error_message = NULL;
- char *provider_user_id = NULL;
- char *provider_legitimization_id = NULL;
- struct GNUNET_TIME_Timestamp collection_time;
- struct GNUNET_TIME_Absolute expiration_time
- = GNUNET_TIME_UNIT_ZERO_ABS;
- void *encrypted_attributes;
- size_t encrypted_attributes_len;
-
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("provider_name",
- &provider_name),
- NULL),
- GNUNET_PQ_result_spec_bool ("finished",
- &finished),
- GNUNET_PQ_result_spec_uint32 ("error_code",
- &error_code),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("error_message",
- &error_message),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("provider_user_id",
- &provider_user_id),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("provider_legitimization_id",
- &provider_legitimization_id),
- NULL),
- GNUNET_PQ_result_spec_timestamp ("collection_time",
- &collection_time),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_absolute_time ("expiration_time",
- &expiration_time),
- NULL),
- GNUNET_PQ_result_spec_variable_size ("encrypted_attributes",
- &encrypted_attributes,
- &encrypted_attributes_len),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- khc->failed = true;
- return;
- }
- khc->cb (khc->cb_cls,
- provider_name,
- finished,
- (enum TALER_ErrorCode) error_code,
- error_message,
- provider_user_id,
- provider_legitimization_id,
- collection_time,
- expiration_time,
- encrypted_attributes_len,
- encrypted_attributes);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_kyc_history (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- TALER_EXCHANGEDB_KycHistoryCallback cb,
- void *cb_cls)
-{
- struct KycHistoryContext khc = {
- .pg = pg,
- .cb = cb,
- .cb_cls = cb_cls
- };
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "lookup_kyc_history",
- "SELECT"
- " lp.provider_name"
- ",lp.finished"
- ",lp.error_code"
- ",lp.error_message"
- ",lp.provider_user_id"
- ",lp.provider_legitimization_id"
- ",ka.collection_time"
- ",ka.expiration_time"
- ",ka.encrypted_attributes"
- " FROM kyc_attributes ka"
- " JOIN legitimization_processes lp"
- " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)"
- " WHERE ka.h_payto=$1"
- " ORDER BY ka.collection_time DESC;");
-
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "lookup_kyc_history",
- params,
- &handle_kyc_entry,
- &khc);
- if (qs <= 0)
- return qs;
- if (khc.failed)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_lookup_kyc_process_by_account.c b/src/exchangedb/pg_lookup_kyc_process_by_account.c
@@ -1,90 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_kyc_process_by_account.c
- * @brief Implementation of the lookup_kyc_process_by_account function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_kyc_process_by_account.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_kyc_process_by_account (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *provider_name,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- uint64_t *process_row,
- struct GNUNET_TIME_Absolute *expiration,
- char **provider_account_id,
- char **provider_legitimization_id,
- bool *is_wallet)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_string (provider_name),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "legitimization_process_serial_id",
- process_row),
- GNUNET_PQ_result_spec_absolute_time (
- "expiration_time",
- expiration),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string (
- "provider_user_id",
- provider_account_id),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string (
- "provider_legitimization_id",
- provider_legitimization_id),
- NULL),
- GNUNET_PQ_result_spec_bool (
- "is_wallet",
- is_wallet),
- GNUNET_PQ_result_spec_end
- };
-
- *provider_account_id = NULL;
- *provider_legitimization_id = NULL;
- PREPARE (pg,
- "lookup_kyc_process_by_account",
- "SELECT "
- " lp.legitimization_process_serial_id"
- ",lp.expiration_time"
- ",lp.provider_user_id"
- ",lp.provider_legitimization_id"
- ",kt.is_wallet"
- " FROM legitimization_processes lp"
- " JOIN kyc_targets kt"
- " ON (lp.h_payto = kt.h_normalized_payto)"
- " WHERE h_payto=$1"
- " AND provider_name=$2"
- " AND NOT finished"
- /* Note: there *should* only be one unfinished
- match, so this is just to be safe(r): */
- " ORDER BY lp.expiration_time DESC"
- " LIMIT 1;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "lookup_kyc_process_by_account",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c
@@ -1,109 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_kyc_requirement_by_row.c
- * @brief Implementation of the lookup_kyc_requirement_by_row function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_kyc_requirement_by_row.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_kyc_requirement_by_row (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const union TALER_AccountPublicKeyP *account_pub,
- enum GNUNET_GenericReturnValue *is_wallet,
- struct TALER_AccountAccessTokenP *access_token,
- uint64_t *rule_gen,
- json_t **jrules,
- bool *aml_review,
- bool *kyc_required)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_auto_from_type (account_pub),
- GNUNET_PQ_query_param_end
- };
- bool bis_wallet;
- bool bis_wallet_unknown;
- bool not_found;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("access_token",
- access_token),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- /* can be NULL due to LEFT JOIN */
- TALER_PQ_result_spec_json ("jrules",
- jrules),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- /* can be NULL due to LEFT JOIN */
- GNUNET_PQ_result_spec_bool ("is_wallet",
- &bis_wallet),
- &bis_wallet_unknown),
- GNUNET_PQ_result_spec_allow_null (
- /* can be NULL due to LEFT JOIN */
- GNUNET_PQ_result_spec_bool ("aml_review",
- aml_review),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 ("rule_gen",
- rule_gen),
- NULL),
- GNUNET_PQ_result_spec_bool ("kyc_required",
- kyc_required),
- GNUNET_PQ_result_spec_bool ("not_found",
- ¬_found),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- *jrules = NULL;
- *aml_review = false;
- *is_wallet = GNUNET_SYSERR;
- *rule_gen = 0;
- memset (access_token,
- 0,
- sizeof (*access_token));
- PREPARE (pg,
- "lookup_kyc_requirement_by_row",
- "SELECT "
- " out_access_token AS access_token"
- ",out_jrules::TEXT AS jrules"
- ",out_is_wallet AS is_wallet"
- ",out_not_found AS not_found"
- ",out_aml_review AS aml_review"
- ",out_kyc_required AS kyc_required"
- ",out_rule_gen AS rule_gen"
- " FROM exchange_do_lookup_kyc_requirement_by_row"
- " ($1, $2);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "lookup_kyc_requirement_by_row",
- params,
- rs);
- if (qs <= 0)
- return qs;
- if (! bis_wallet_unknown)
- *is_wallet = (bis_wallet) ? GNUNET_YES : GNUNET_NO;
- if (not_found)
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- return qs;
-}
diff --git a/src/exchangedb/pg_lookup_kyc_status_by_token.c b/src/exchangedb/pg_lookup_kyc_status_by_token.c
@@ -1,61 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_kyc_status_by_token.c
- * @brief Implementation of the lookup_kyc_status_by_token function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_kyc_status_by_token.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_kyc_status_by_token (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AccountAccessTokenP *access_token,
- uint64_t *row,
- json_t **jmeasures)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (access_token),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "legitimization_measure_serial_id",
- row),
- TALER_PQ_result_spec_json (
- "jmeasures",
- jmeasures),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "lookup_kyc_status_by_token",
- "SELECT"
- " legitimization_measure_serial_id"
- ",jmeasures::TEXT"
- " FROM legitimization_measures"
- " WHERE access_token=$1"
- " AND NOT is_finished"
- " ORDER BY display_priority DESC"
- " LIMIT 1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_kyc_status_by_token",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_pending_legitimization.c b/src/exchangedb/pg_lookup_pending_legitimization.c
@@ -1,76 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_pending_legitimization.c
- * @brief Implementation of the lookup_pending_legitimization function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_pending_legitimization.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_pending_legitimization (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t legitimization_measure_serial_id,
- struct TALER_AccountAccessTokenP *access_token,
- struct TALER_NormalizedPaytoHashP *h_payto,
- json_t **jmeasures,
- bool *is_finished,
- bool *is_wallet)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&legitimization_measure_serial_id),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_json (
- "jmeasures",
- jmeasures),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_normalized_payto",
- h_payto),
- GNUNET_PQ_result_spec_auto_from_type (
- "access_token",
- access_token),
- GNUNET_PQ_result_spec_bool (
- "is_finished",
- is_finished),
- GNUNET_PQ_result_spec_bool (
- "is_wallet",
- is_wallet),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "lookup_pending_legitimization",
- "SELECT "
- " lm.jmeasures::TEXT"
- ",kt.h_normalized_payto"
- ",kt.is_wallet"
- ",lm.access_token"
- ",lm.is_finished"
- " FROM legitimization_measures lm"
- " JOIN kyc_targets kt"
- " USING (access_token)"
- " WHERE lm.legitimization_measure_serial_id=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "lookup_pending_legitimization",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_records_by_table.c b/src/exchangedb/pg_lookup_records_by_table.c
@@ -1,3802 +0,0 @@
-/*
- This file is part of GNUnet
- Copyright (C) 2020-2025 Taler Systems SA
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
-
- GNUnet 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
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- SPDX-License-Identifier: AGPL3.0-or-later
- */
-/**
- * @file exchangedb/pg_lookup_records_by_table.c
- * @brief implementation of lookup_records_by_table
- * @author Christian Grothoff
- * @author Özgür Kesim
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_dbevents.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_records_by_table.h"
-#include "helper.h"
-#include <gnunet/gnunet_pq_lib.h>
-
-
-/**
- * Closure for callbacks used by #postgres_lookup_records_by_table.
- */
-struct LookupRecordsByTableContext
-{
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Function to call with the results.
- */
- TALER_EXCHANGEDB_ReplicationCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Set to true on errors.
- */
- bool error;
-};
-
-
-/**
- * Function called with denominations table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_denominations (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_DENOMINATIONS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_uint32 (
- "denom_type",
- &td.details.denominations.denom_type),
- GNUNET_PQ_result_spec_uint32 (
- "age_mask",
- &td.details.denominations.age_mask),
- TALER_PQ_result_spec_denom_pub (
- "denom_pub",
- &td.details.denominations.denom_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "master_sig",
- &td.details.denominations.master_sig),
- GNUNET_PQ_result_spec_timestamp (
- "valid_from",
- &td.details.denominations.valid_from),
- GNUNET_PQ_result_spec_timestamp (
- "expire_withdraw",
- &td.details.denominations.
- expire_withdraw),
- GNUNET_PQ_result_spec_timestamp (
- "expire_deposit",
- &td.details.denominations.
- expire_deposit),
- GNUNET_PQ_result_spec_timestamp (
- "expire_legal",
- &td.details.denominations.expire_legal),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "coin",
- &td.details.denominations.coin),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "fee_withdraw",
- &td.details.denominations.fees.withdraw),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "fee_deposit",
- &td.details.denominations.fees.deposit),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "fee_refresh",
- &td.details.denominations.fees.refresh),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "fee_refund",
- &td.details.denominations.fees.refund),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with denomination_revocations table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_denomination_revocations (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_uint64 (
- "denominations_serial",
- &td.details.denomination_revocations.denominations_serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "master_sig",
- &td.details.denomination_revocations.master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with wire_targets table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_wire_targets (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_WIRE_TARGETS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_string (
- "payto_uri",
- &td.details.wire_targets.full_payto_uri.full_payto),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with wire_targets table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_kyc_targets (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_KYC_TARGETS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_normalized_payto",
- &td.details.kyc_targets.h_normalized_payto),
- GNUNET_PQ_result_spec_auto_from_type (
- "access_token",
- &td.details.kyc_targets.access_token),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type (
- "target_pub",
- &td.details.kyc_targets.target_pub),
- &td.details.kyc_targets.no_account),
- GNUNET_PQ_result_spec_bool (
- "is_wallet",
- &td.details.kyc_targets.is_wallet),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with reserves table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_reserves (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_RESERVES
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &td.details.reserves.reserve_pub),
- GNUNET_PQ_result_spec_timestamp ("expiration_date",
- &td.details.reserves.expiration_date),
- GNUNET_PQ_result_spec_timestamp ("gc_date",
- &td.details.reserves.gc_date),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with reserves_in table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_reserves_in (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_RESERVES_IN
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.reserves_in.reserve_pub),
- GNUNET_PQ_result_spec_uint64 (
- "wire_reference",
- &td.details.reserves_in.wire_reference),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "credit",
- &td.details.reserves_in.credit),
- GNUNET_PQ_result_spec_auto_from_type (
- "wire_source_h_payto",
- &td.details.reserves_in.sender_account_h_payto),
- GNUNET_PQ_result_spec_string (
- "exchange_account_section",
- &td.details.reserves_in.exchange_account_section),
- GNUNET_PQ_result_spec_timestamp (
- "execution_date",
- &td.details.reserves_in.execution_date),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with kycauth_in table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_kycauth_in (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_KYCAUTHS_IN
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "account_pub",
- &td.details.kycauth_in.account_pub),
- GNUNET_PQ_result_spec_uint64 (
- "wire_reference",
- &td.details.kycauth_in.wire_reference),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "credit",
- &td.details.kycauth_in.credit),
- GNUNET_PQ_result_spec_auto_from_type (
- "wire_source_h_payto",
- &td.details.kycauth_in.sender_account_h_payto),
- GNUNET_PQ_result_spec_string (
- "exchange_account_section",
- &td.details.kycauth_in.exchange_account_section),
- GNUNET_PQ_result_spec_timestamp (
- "execution_date",
- &td.details.kycauth_in.execution_date),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with reserves_close table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_reserves_close (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_RESERVES_CLOSE
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.reserves_close.reserve_pub),
- GNUNET_PQ_result_spec_timestamp (
- "execution_date",
- &td.details.reserves_close.execution_date),
- GNUNET_PQ_result_spec_auto_from_type (
- "wtid",
- &td.details.reserves_close.wtid),
- GNUNET_PQ_result_spec_auto_from_type (
- "wire_target_h_payto",
- &td.details.reserves_close.sender_account_h_payto),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount",
- &td.details.reserves_close.amount),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "closing_fee",
- &td.details.reserves_close.closing_fee),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with reserves_open_requests table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_reserves_open_requests (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.reserves_open_requests.reserve_pub),
- GNUNET_PQ_result_spec_timestamp (
- "request_timestamp",
- &td.details.reserves_open_requests.request_timestamp),
- GNUNET_PQ_result_spec_timestamp (
- "expiration_date",
- &td.details.reserves_open_requests.expiration_date),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_sig",
- &td.details.reserves_open_requests.reserve_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "reserve_payment",
- &td.details.reserves_open_requests.reserve_payment),
- GNUNET_PQ_result_spec_uint32 (
- "requested_purse_limit",
- &td.details.reserves_open_requests.requested_purse_limit),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with reserves_open_deposits table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_reserves_open_deposits (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_sig",
- &td.details.reserves_open_deposits.reserve_sig),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.reserves_open_deposits.reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_pub",
- &td.details.reserves_open_deposits.coin_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_sig",
- &td.details.reserves_open_deposits.coin_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "contribution",
- &td.details.reserves_open_deposits.contribution),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with auditors table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_auditors (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_AUDITORS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
- &td.details.auditors.auditor_pub),
- GNUNET_PQ_result_spec_string ("auditor_url",
- &td.details.auditors.auditor_url),
- GNUNET_PQ_result_spec_string ("auditor_name",
- &td.details.auditors.auditor_name),
- GNUNET_PQ_result_spec_bool ("is_active",
- &td.details.auditors.is_active),
- GNUNET_PQ_result_spec_timestamp ("last_change",
- &td.details.auditors.last_change),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with auditor_denom_sigs table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_auditor_denom_sigs (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_uint64 (
- "auditor_uuid",
- &td.details.auditor_denom_sigs.auditor_uuid),
- GNUNET_PQ_result_spec_uint64 (
- "denominations_serial",
- &td.details.auditor_denom_sigs.denominations_serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "auditor_sig",
- &td.details.auditor_denom_sigs.auditor_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with exchange_sign_keys table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_exchange_sign_keys (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
- &td.details.exchange_sign_keys.
- exchange_pub),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &td.details.exchange_sign_keys.
- master_sig),
- GNUNET_PQ_result_spec_timestamp ("valid_from",
- &td.details.exchange_sign_keys.meta.
- start),
- GNUNET_PQ_result_spec_timestamp ("expire_sign",
- &td.details.exchange_sign_keys.meta.
- expire_sign),
- GNUNET_PQ_result_spec_timestamp ("expire_legal",
- &td.details.exchange_sign_keys.meta.
- expire_legal),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with signkey_revocations table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_signkey_revocations (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_uint64 ("esk_serial",
- &td.details.signkey_revocations.esk_serial),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &td.details.signkey_revocations.
- master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with known_coins table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_known_coins (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_KNOWN_COINS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_pub",
- &td.details.known_coins.coin_pub),
- TALER_PQ_result_spec_denom_sig (
- "denom_sig",
- &td.details.known_coins.denom_sig),
- GNUNET_PQ_result_spec_uint64 (
- "denominations_serial",
- &td.details.known_coins.denominations_serial),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with refresh table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_refresh (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_REFRESH
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- bool no_cs_r_values;
- bool no_cs_r_choices;
- size_t num_denom_sigs;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "rc",
- &td.details.refresh.rc),
- GNUNET_PQ_result_spec_auto_from_type (
- "execution_date",
- &td.details.refresh.execution_date),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount_with_fee",
- &td.details.refresh.amount_with_fee),
- GNUNET_PQ_result_spec_auto_from_type (
- "old_coin_pub",
- &td.details.refresh.old_coin_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "old_coin_sig",
- &td.details.refresh.old_coin_sig),
- GNUNET_PQ_result_spec_auto_from_type (
- "refresh_seed",
- &td.details.refresh.refresh_seed),
- GNUNET_PQ_result_spec_uint32 (
- "noreveal_index",
- &td.details.refresh.noreveal_index),
- GNUNET_PQ_result_spec_auto_from_type (
- "planchets_h",
- &td.details.refresh.planchets_h),
- GNUNET_PQ_result_spec_auto_from_type (
- "selected_h",
- &td.details.refresh.selected_h),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type (
- "blinding_seed",
- &td.details.refresh.blinding_seed),
- &td.details.refresh.no_blinding_seed),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_array_cs_r_pub (
- pg->conn,
- "cs_r_values",
- &td.details.refresh.num_cs_r_values,
- &td.details.refresh.cs_r_values),
- &no_cs_r_values),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 (
- "cs_r_choices",
- &td.details.refresh.cs_r_choices),
- &no_cs_r_choices),
- GNUNET_PQ_result_spec_array_uint64 (
- pg->conn,
- "denom_serials",
- &td.details.refresh.num_coins,
- &td.details.refresh.denom_serials),
- TALER_PQ_result_spec_array_blinded_denom_sig (
- pg->conn,
- "denom_sigs",
- &num_denom_sigs,
- &td.details.refresh.denom_sigs),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with batch deposits table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_batch_deposits (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_BATCH_DEPOSITS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_uint64 (
- "shard",
- &td.details.batch_deposits.shard),
- GNUNET_PQ_result_spec_auto_from_type (
- "merchant_pub",
- &td.details.batch_deposits.merchant_pub),
- GNUNET_PQ_result_spec_timestamp (
- "wallet_timestamp",
- &td.details.batch_deposits.wallet_timestamp),
- GNUNET_PQ_result_spec_timestamp (
- "exchange_timestamp",
- &td.details.batch_deposits.exchange_timestamp),
- GNUNET_PQ_result_spec_timestamp (
- "refund_deadline",
- &td.details.batch_deposits.refund_deadline),
- GNUNET_PQ_result_spec_timestamp (
- "wire_deadline",
- &td.details.batch_deposits.wire_deadline),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_contract_terms",
- &td.details.batch_deposits.h_contract_terms),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type (
- "wallet_data_hash",
- &td.details.batch_deposits.wallet_data_hash),
- &td.details.batch_deposits.no_wallet_data_hash),
- GNUNET_PQ_result_spec_auto_from_type (
- "wire_salt",
- &td.details.batch_deposits.wire_salt),
- GNUNET_PQ_result_spec_auto_from_type (
- "wire_target_h_payto",
- &td.details.batch_deposits.wire_target_h_payto),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 (
- "policy_details_serial_id",
- &td.details.batch_deposits.policy_details_serial_id),
- &td.details.batch_deposits.no_policy_details),
- GNUNET_PQ_result_spec_bool (
- "policy_blocked",
- &td.details.batch_deposits.policy_blocked),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "total_amount",
- &td.details.batch_deposits.total_amount),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "total_without_fee",
- &td.details.batch_deposits.total_without_fee),
- GNUNET_PQ_result_spec_auto_from_type (
- "merchant_sig",
- &td.details.batch_deposits.merchant_sig),
- GNUNET_PQ_result_spec_bool (
- "done",
- &td.details.batch_deposits.done),
- GNUNET_PQ_result_spec_end
- };
-
- td.details.batch_deposits.policy_details_serial_id = 0;
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with coin deposits table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_coin_deposits (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_COIN_DEPOSITS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_uint64 (
- "batch_deposit_serial_id",
- &td.details.coin_deposits.batch_deposit_serial_id),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_pub",
- &td.details.coin_deposits.coin_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_sig",
- &td.details.coin_deposits.coin_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount_with_fee",
- &td.details.coin_deposits.amount_with_fee),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with refunds table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_refunds (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_REFUNDS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_pub",
- &td.details.refunds.coin_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "merchant_sig",
- &td.details.refunds.merchant_sig),
- GNUNET_PQ_result_spec_uint64 (
- "rtransaction_id",
- &td.details.refunds.rtransaction_id),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount_with_fee",
- &td.details.refunds.amount_with_fee),
- GNUNET_PQ_result_spec_uint64 (
- "batch_deposit_serial_id",
- &td.details.refunds.batch_deposit_serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with wire_out table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_wire_out (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_WIRE_OUT
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_timestamp (
- "execution_date",
- &td.details.wire_out.execution_date),
- GNUNET_PQ_result_spec_auto_from_type (
- "wtid_raw",
- &td.details.wire_out.wtid_raw),
- GNUNET_PQ_result_spec_auto_from_type (
- "wire_target_h_payto",
- &td.details.wire_out.wire_target_h_payto),
- GNUNET_PQ_result_spec_string (
- "exchange_account_section",
- &td.details.wire_out.exchange_account_section),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount",
- &td.details.wire_out.amount),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with aggregation_tracking table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_aggregation_tracking (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_uint64 (
- "batch_deposit_serial_id",
- &td.details.aggregation_tracking.batch_deposit_serial_id),
- GNUNET_PQ_result_spec_auto_from_type (
- "wtid_raw",
- &td.details.aggregation_tracking.wtid_raw),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with wire_fee table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_wire_fee (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_WIRE_FEE
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_string ("wire_method",
- &td.details.wire_fee.wire_method),
- GNUNET_PQ_result_spec_timestamp ("start_date",
- &td.details.wire_fee.start_date),
- GNUNET_PQ_result_spec_timestamp ("end_date",
- &td.details.wire_fee.end_date),
- TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
- &td.details.wire_fee.fees.wire),
- TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
- &td.details.wire_fee.fees.closing),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- &td.details.wire_fee.master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with wire_fee table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_global_fee (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_GLOBAL_FEE
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "serial",
- &td.serial),
- GNUNET_PQ_result_spec_timestamp (
- "start_date",
- &td.details.global_fee.start_date),
- GNUNET_PQ_result_spec_timestamp (
- "end_date",
- &td.details.global_fee.end_date),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "history_fee",
- &td.details.global_fee.fees.history),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "account_fee",
- &td.details.global_fee.fees.account),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "purse_fee",
- &td.details.global_fee.fees.purse),
- GNUNET_PQ_result_spec_relative_time (
- "purse_timeout",
- &td.details.global_fee.purse_timeout),
- GNUNET_PQ_result_spec_relative_time (
- "history_expiration",
- &td.details.global_fee.history_expiration),
- GNUNET_PQ_result_spec_uint32 (
- "purse_account_limit",
- &td.details.global_fee.purse_account_limit),
- GNUNET_PQ_result_spec_auto_from_type (
- "master_sig",
- &td.details.global_fee.master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with recoup table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_recoup (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_RECOUP
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &td.details.recoup.coin_sig),
- GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
- &td.details.recoup.coin_blind),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &td.details.recoup.amount),
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- &td.details.recoup.timestamp),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_pub",
- &td.details.recoup.coin_pub),
- GNUNET_PQ_result_spec_uint64 ("withdraw_serial_id",
- &td.details.recoup.withdraw_serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with recoup_refresh table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_recoup_refresh (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_RECOUP_REFRESH
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &td.details.recoup_refresh.coin_sig)
- ,
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_blind",
- &td.details.recoup_refresh.coin_blind),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &td.details.recoup_refresh.amount),
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- &td.details.recoup_refresh.timestamp),
- GNUNET_PQ_result_spec_uint64 ("known_coin_id",
- &td.details.recoup_refresh.known_coin_id),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_pub",
- &td.details.recoup_refresh.coin_pub),
- GNUNET_PQ_result_spec_uint64 ("rrc_serial",
- &td.details.recoup_refresh.rrc_serial),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with extensions table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_extensions (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_EXTENSIONS
- };
- bool no_manifest = false;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("extension_id",
- &td.serial),
- GNUNET_PQ_result_spec_string ("name",
- &td.details.extensions.name),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("manifest",
- &td.details.extensions.manifest),
- &no_manifest),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with policy_details table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_policy_details (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_POLICY_DETAILS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type ("hash_code",
- &td.details.policy_details.
- hash_code),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("policy_json",
- &td.details.policy_details.
- policy_json),
- &td.details.policy_details.no_policy_json),
- GNUNET_PQ_result_spec_timestamp ("deadline",
- &td.details.policy_details.
- deadline),
- TALER_PQ_RESULT_SPEC_AMOUNT ("commitment",
- &td.details.policy_details.
- commitment),
- TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
- &td.details.policy_details.
- accumulated_total),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee",
- &td.details.policy_details.
- fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("transferable",
- &td.details.policy_details.
- transferable),
- GNUNET_PQ_result_spec_uint16 ("fulfillment_state",
- &td.details.policy_details.
- fulfillment_state),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
- &td.details.policy_details.
- fulfillment_id),
- &td.details.policy_details.no_fulfillment_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with policy_fulfillments table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_policy_fulfillments (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- bool no_proof = false;
- bool no_timestamp = false;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
- &td.serial),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_timestamp ("fulfillment_timestamp",
- &td.details.policy_fulfillments.
- fulfillment_timestamp),
- &no_timestamp),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("fulfillment_proof",
- &td.details.policy_fulfillments.
- fulfillment_proof),
- &no_proof),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with purse_requests table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_purse_requests (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_PURSE_REQUESTS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "purse_requests_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_pub",
- &td.details.purse_requests.purse_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "merge_pub",
- &td.details.purse_requests.merge_pub),
- GNUNET_PQ_result_spec_timestamp (
- "purse_creation",
- &td.details.purse_requests.purse_creation),
- GNUNET_PQ_result_spec_timestamp (
- "purse_expiration",
- &td.details.purse_requests.purse_expiration),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_contract_terms",
- &td.details.purse_requests.h_contract_terms),
- GNUNET_PQ_result_spec_uint32 (
- "age_limit",
- &td.details.purse_requests.age_limit),
- GNUNET_PQ_result_spec_uint32 (
- "flags",
- &td.details.purse_requests.flags),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount_with_fee",
- &td.details.purse_requests.amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "purse_fee",
- &td.details.purse_requests.purse_fee),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_sig",
- &td.details.purse_requests.purse_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with purse_decision table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_purse_decision (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_PURSE_DECISION
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "purse_refunds_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_pub",
- &td.details.purse_decision.purse_pub),
- GNUNET_PQ_result_spec_timestamp (
- "action_timestamp",
- &td.details.purse_decision.action_timestamp),
- GNUNET_PQ_result_spec_bool (
- "refunded",
- &td.details.purse_decision.refunded),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with purse_merges table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_purse_merges (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_PURSE_MERGES
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "purse_merge_request_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_uint64 (
- "partner_serial_id",
- &td.details.purse_merges.partner_serial_id),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.purse_merges.reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_pub",
- &td.details.purse_merges.purse_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "merge_sig",
- &td.details.purse_merges.merge_sig),
- GNUNET_PQ_result_spec_timestamp (
- "merge_timestamp",
- &td.details.purse_merges.merge_timestamp),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with purse_deposits table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_purse_deposits (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_PURSE_DEPOSITS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "purse_deposit_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_uint64 (
- "partner_serial_id",
- &td.details.purse_deposits.partner_serial_id),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_pub",
- &td.details.purse_deposits.purse_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_pub",
- &td.details.purse_deposits.coin_pub),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount_with_fee",
- &td.details.purse_deposits.amount_with_fee),
- GNUNET_PQ_result_spec_auto_from_type (
- "coin_sig",
- &td.details.purse_deposits.coin_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with account_merges table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_account_merges (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_ACCOUNT_MERGES
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "account_merge_request_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.account_merges.reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_sig",
- &td.details.account_merges.reserve_sig),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_pub",
- &td.details.account_merges.purse_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "wallet_h_payto",
- &td.details.account_merges.wallet_h_payto),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with history_requests table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_history_requests (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_HISTORY_REQUESTS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "history_request_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.history_requests.reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_sig",
- &td.details.history_requests.reserve_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "history_fee",
- &td.details.history_requests.history_fee),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with close_requests table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_close_requests (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_CLOSE_REQUESTS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "close_request_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.close_requests.reserve_pub),
- GNUNET_PQ_result_spec_timestamp (
- "close_timestamp",
- &td.details.close_requests.close_timestamp),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_sig",
- &td.details.close_requests.reserve_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "close",
- &td.details.close_requests.close),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "close_fee",
- &td.details.close_requests.close_fee),
- GNUNET_PQ_result_spec_string (
- "payto_uri",
- &td.details.close_requests.payto_uri.full_payto),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with wads_out table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_wads_out (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_WADS_OUT
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "wad_out_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "wad_id",
- &td.details.wads_out.wad_id),
- GNUNET_PQ_result_spec_uint64 (
- "partner_serial_id",
- &td.details.wads_out.partner_serial_id),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount",
- &td.details.wads_out.amount),
- GNUNET_PQ_result_spec_timestamp (
- "execution_time",
- &td.details.wads_out.execution_time),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with wads_out_entries table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_wads_out_entries (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "wad_out_entry_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.wads_out_entries.reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_pub",
- &td.details.wads_out_entries.purse_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_contract",
- &td.details.wads_out_entries.h_contract),
- GNUNET_PQ_result_spec_timestamp (
- "purse_expiration",
- &td.details.wads_out_entries.purse_expiration),
- GNUNET_PQ_result_spec_timestamp (
- "merge_timestamp",
- &td.details.wads_out_entries.merge_timestamp),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount_with_fee",
- &td.details.wads_out_entries.amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "wad_fee",
- &td.details.wads_out_entries.wad_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "deposit_fees",
- &td.details.wads_out_entries.deposit_fees),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_sig",
- &td.details.wads_out_entries.reserve_sig),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_sig",
- &td.details.wads_out_entries.purse_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with wads_in table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_wads_in (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_WADS_IN
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "wad_in_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "wad_id",
- &td.details.wads_in.wad_id),
- GNUNET_PQ_result_spec_string (
- "origin_exchange_url",
- &td.details.wads_in.origin_exchange_url),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount",
- &td.details.wads_in.amount),
- GNUNET_PQ_result_spec_timestamp (
- "arrival_time",
- &td.details.wads_in.arrival_time),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with wads_in_entries table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_wads_in_entries (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "wad_in_entry_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.wads_in_entries.reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_pub",
- &td.details.wads_in_entries.purse_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_contract",
- &td.details.wads_in_entries.h_contract),
- GNUNET_PQ_result_spec_timestamp (
- "purse_expiration",
- &td.details.wads_in_entries.purse_expiration),
- GNUNET_PQ_result_spec_timestamp (
- "merge_timestamp",
- &td.details.wads_in_entries.merge_timestamp),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount_with_fee",
- &td.details.wads_in_entries.amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "wad_fee",
- &td.details.wads_in_entries.wad_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "deposit_fees",
- &td.details.wads_in_entries.deposit_fees),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_sig",
- &td.details.wads_in_entries.reserve_sig),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_sig",
- &td.details.wads_in_entries.purse_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with profit_drains table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_profit_drains (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_PROFIT_DRAINS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "profit_drain_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "wtid",
- &td.details.profit_drains.wtid),
- GNUNET_PQ_result_spec_string (
- "account_section",
- &td.details.profit_drains.account_section),
- GNUNET_PQ_result_spec_string (
- "payto_uri",
- &td.details.profit_drains.payto_uri.full_payto),
- GNUNET_PQ_result_spec_timestamp (
- "trigger_date",
- &td.details.profit_drains.trigger_date),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount",
- &td.details.profit_drains.amount),
- GNUNET_PQ_result_spec_auto_from_type (
- "master_sig",
- &td.details.profit_drains.master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with aml_staff table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_aml_staff (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_AML_STAFF
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "aml_staff_uuid",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "decider_pub",
- &td.details.aml_staff.decider_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "master_sig",
- &td.details.aml_staff.master_sig),
- GNUNET_PQ_result_spec_string (
- "decider_name",
- &td.details.aml_staff.decider_name),
- GNUNET_PQ_result_spec_bool (
- "is_active",
- &td.details.aml_staff.is_active),
- GNUNET_PQ_result_spec_bool (
- "read_only",
- &td.details.aml_staff.read_only),
- GNUNET_PQ_result_spec_timestamp (
- "last_change",
- &td.details.aml_staff.last_change),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with purse_deletion table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_purse_deletion (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_PURSE_DELETION
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "purse_deletion_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_sig",
- &td.details.purse_deletion.purse_sig),
- GNUNET_PQ_result_spec_auto_from_type (
- "purse_pub",
- &td.details.purse_deletion.purse_pub),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with withdraw table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_withdraw (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_WITHDRAW
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- bool no_max_age;
- bool no_noreveal_index;
- bool no_selected_h;
- bool no_cs_r_values;
- bool no_cs_r_choices;
- size_t num_sigs;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "withdraw_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "planchets_h",
- &td.details.withdraw.planchets_h),
- GNUNET_PQ_result_spec_timestamp (
- "execution_date",
- &td.details.withdraw.execution_date),
- TALER_PQ_RESULT_SPEC_AMOUNT (
- "amount_with_fee",
- &td.details.withdraw.amount_with_fee),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_pub",
- &td.details.withdraw.reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "reserve_sig",
- &td.details.withdraw.reserve_sig),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint16 (
- "max_age",
- &td.details.withdraw.max_age),
- &no_max_age),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint16 (
- "noreveal_index",
- &td.details.withdraw.noreveal_index),
- &no_noreveal_index),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type (
- "selected_h",
- &td.details.withdraw.selected_h),
- &no_selected_h),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type (
- "blinding_seed",
- &td.details.withdraw.blinding_seed),
- &td.details.withdraw.no_blinding_seed),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_array_cs_r_pub (
- pg->conn,
- "cs_r_values",
- &td.details.withdraw.num_cs_r_values,
- &td.details.withdraw.cs_r_values),
- &no_cs_r_values),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 (
- "cs_r_choices",
- &td.details.withdraw.cs_r_choices),
- &no_cs_r_choices),
- GNUNET_PQ_result_spec_array_uint64 (
- pg->conn,
- "denom_serials",
- &td.details.withdraw.num_coins,
- &td.details.withdraw.denom_serials),
- TALER_PQ_result_spec_array_blinded_denom_sig (
- pg->conn,
- "denom_sigs",
- &num_sigs,
- &td.details.withdraw.denom_sigs),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- if (num_sigs != td.details.withdraw.num_coins)
- {
- GNUNET_break (0);
- ctx->error = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- if (no_max_age != no_noreveal_index)
- {
- GNUNET_break (0);
- ctx->error = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- if (no_max_age != no_selected_h)
- {
- GNUNET_break (0);
- ctx->error = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- if (no_cs_r_values != no_cs_r_choices)
- {
- GNUNET_break (0);
- ctx->error = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- if (no_cs_r_values != td.details.withdraw.no_blinding_seed)
- {
- GNUNET_break (0);
- ctx->error = true;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- td.details.withdraw.age_proof_required = ! no_max_age;
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with legitimization_measures table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_legitimization_measures (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "access_token",
- &td.details.legitimization_measures.target_token),
- GNUNET_PQ_result_spec_timestamp (
- "start_time",
- &td.details.legitimization_measures.start_time),
- TALER_PQ_result_spec_json (
- "jmeasures",
- &td.details.legitimization_measures.measures),
- GNUNET_PQ_result_spec_uint32 (
- "display_priority",
- &td.details.legitimization_measures.display_priority),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with legitimization_outcomes table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_legitimization_outcomes (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_payto",
- &td.details.legitimization_outcomes.h_payto),
- GNUNET_PQ_result_spec_timestamp (
- "decision_time",
- &td.details.legitimization_outcomes.decision_time),
- GNUNET_PQ_result_spec_timestamp (
- "expiration_time",
- &td.details.legitimization_outcomes.expiration_time),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json (
- "jproperties",
- &td.details.legitimization_outcomes.properties),
- NULL),
- GNUNET_PQ_result_spec_bool (
- "to_investigate_id",
- &td.details.legitimization_outcomes.to_investigate),
- TALER_PQ_result_spec_json (
- "jnew_rules",
- &td.details.legitimization_outcomes.new_rules),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with legitimization_processes table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_legitimization_processes (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_payto",
- &td.details.legitimization_processes.h_payto),
- GNUNET_PQ_result_spec_timestamp (
- "start_time",
- &td.details.legitimization_processes.start_time),
- GNUNET_PQ_result_spec_timestamp (
- "expiration_time",
- &td.details.legitimization_processes.expiration_time),
- GNUNET_PQ_result_spec_uint64 (
- "legitimization_measure_serial_id",
- &td.details.legitimization_processes.legitimization_measure_serial_id),
- GNUNET_PQ_result_spec_uint32 (
- "measure_index",
- &td.details.legitimization_processes.measure_index),
- GNUNET_PQ_result_spec_string (
- "provider_name",
- &td.details.legitimization_processes.provider_name),
- GNUNET_PQ_result_spec_string (
- "provider_user_id",
- &td.details.legitimization_processes.provider_user_id),
- GNUNET_PQ_result_spec_string (
- "provider_legitimization_id",
- &td.details.legitimization_processes.provider_legitimization_id),
- GNUNET_PQ_result_spec_string (
- "redirect_url",
- &td.details.legitimization_processes.redirect_url),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with kyc_attributes table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_kyc_attributes (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "kyc_attributes_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_payto",
- &td.details.kyc_attributes.h_payto),
- GNUNET_PQ_result_spec_uint64 (
- "legitimization_serial",
- &td.details.kyc_attributes.legitimization_serial),
- GNUNET_PQ_result_spec_timestamp (
- "collection_time",
- &td.details.kyc_attributes.collection_time),
- GNUNET_PQ_result_spec_timestamp (
- "expiration_time",
- &td.details.kyc_attributes.expiration_time),
- GNUNET_PQ_result_spec_uint64 (
- "trigger_outcome_serial",
- &td.details.kyc_attributes.trigger_outcome_serial),
- GNUNET_PQ_result_spec_variable_size (
- "encrypted_attributes",
- &td.details.kyc_attributes.encrypted_attributes,
- &td.details.kyc_attributes.encrypted_attributes_size),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with aml_history table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_aml_history (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_AML_HISTORY
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "aml_history_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_auto_from_type (
- "h_payto",
- &td.details.aml_history.h_payto),
- GNUNET_PQ_result_spec_uint64 (
- "outcome_serial_id",
- &td.details.aml_history.outcome_serial_id),
- GNUNET_PQ_result_spec_string (
- "justification",
- &td.details.aml_history.justification),
- GNUNET_PQ_result_spec_auto_from_type (
- "decider_pub",
- &td.details.aml_history.decider_pub),
- GNUNET_PQ_result_spec_auto_from_type (
- "decider_sig",
- &td.details.aml_history.decider_sig),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Function called with kyc_events table entries.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-lrbt_cb_table_kyc_events (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LookupRecordsByTableContext *ctx = cls;
- struct TALER_EXCHANGEDB_TableData td = {
- .table = TALER_EXCHANGEDB_RT_KYC_EVENTS
- };
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "kyc_event_serial_id",
- &td.serial),
- GNUNET_PQ_result_spec_timestamp (
- "event_timestamp",
- &td.details.kyc_events.event_timestamp),
- GNUNET_PQ_result_spec_string (
- "event_type",
- &td.details.kyc_events.event_type),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->error = true;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &td);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-/**
- * Assign statement to @a n and PREPARE
- * @a sql under name @a n.
- */
-#define XPREPARE(n,sql) \
- statement = n; \
- PREPARE (pg, n, sql);
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_records_by_table (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- enum TALER_EXCHANGEDB_ReplicatedTable table,
- uint64_t serial,
- TALER_EXCHANGEDB_ReplicationCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial),
- GNUNET_PQ_query_param_end
- };
- struct LookupRecordsByTableContext ctx = {
- .pg = pg,
- .cb = cb,
- .cb_cls = cb_cls
- };
- GNUNET_PQ_PostgresResultHandler rh = NULL;
- const char *statement = NULL;
- enum GNUNET_DB_QueryStatus qs;
-
- switch (table)
- {
- case TALER_EXCHANGEDB_RT_DENOMINATIONS:
- XPREPARE ("select_above_serial_by_table_denominations",
- "SELECT"
- " denominations_serial AS serial"
- ",denom_type"
- ",denom_pub"
- ",master_sig"
- ",valid_from"
- ",expire_withdraw"
- ",expire_deposit"
- ",expire_legal"
- ",coin"
- ",fee_withdraw"
- ",fee_deposit"
- ",fee_refresh"
- ",fee_refund"
- ",age_mask"
- " FROM denominations"
- " WHERE denominations_serial > $1"
- " ORDER BY denominations_serial ASC;");
- rh = &lrbt_cb_table_denominations;
- break;
- case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS:
- XPREPARE ("select_above_serial_by_table_denomination_revocations",
- "SELECT"
- " denom_revocations_serial_id AS serial"
- ",master_sig"
- ",denominations_serial"
- " FROM denomination_revocations"
- " WHERE denom_revocations_serial_id > $1"
- " ORDER BY denom_revocations_serial_id ASC;");
- rh = &lrbt_cb_table_denomination_revocations;
- break;
- case TALER_EXCHANGEDB_RT_WIRE_TARGETS:
- XPREPARE ("select_above_serial_by_table_wire_targets",
- "SELECT"
- " wire_target_serial_id AS serial"
- ",payto_uri"
- " FROM wire_targets"
- " WHERE wire_target_serial_id > $1"
- " ORDER BY wire_target_serial_id ASC;");
- rh = &lrbt_cb_table_wire_targets;
- break;
- case TALER_EXCHANGEDB_RT_KYC_TARGETS:
- XPREPARE ("select_above_serial_by_table_kyc_targets",
- "SELECT"
- " kyc_target_serial_id AS serial"
- ",h_normalized_payto"
- ",access_token"
- ",target_pub"
- ",is_wallet"
- " FROM kyc_targets"
- " WHERE kyc_target_serial_id > $1"
- " ORDER BY kyc_target_serial_id ASC;");
- rh = &lrbt_cb_table_kyc_targets;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES:
- XPREPARE ("select_above_serial_by_table_reserves",
- "SELECT"
- " reserve_uuid AS serial"
- ",reserve_pub"
- ",expiration_date"
- ",gc_date"
- " FROM reserves"
- " WHERE reserve_uuid > $1"
- " ORDER BY reserve_uuid ASC;");
- rh = &lrbt_cb_table_reserves;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_IN:
- XPREPARE ("select_above_serial_by_table_reserves_in",
- "SELECT"
- " reserve_in_serial_id AS serial"
- ",reserve_pub"
- ",wire_reference"
- ",credit"
- ",wire_source_h_payto"
- ",exchange_account_section"
- ",execution_date"
- " FROM reserves_in"
- " WHERE reserve_in_serial_id > $1"
- " ORDER BY reserve_in_serial_id ASC;");
- rh = &lrbt_cb_table_reserves_in;
- break;
- case TALER_EXCHANGEDB_RT_KYCAUTHS_IN:
- XPREPARE ("select_above_serial_by_table_kycauth_in",
- "SELECT"
- " kycauth_in_serial_id AS serial"
- ",account_pub"
- ",wire_reference"
- ",credit"
- ",wire_source_h_payto"
- ",exchange_account_section"
- ",execution_date"
- " FROM kycauths_in"
- " WHERE kycauth_in_serial_id > $1"
- " ORDER BY kycauth_in_serial_id ASC;");
- rh = &lrbt_cb_table_kycauth_in;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_CLOSE:
- XPREPARE ("select_above_serial_by_table_reserves_close",
- "SELECT"
- " close_uuid AS serial"
- ",reserve_pub"
- ",execution_date"
- ",wtid"
- ",wire_target_h_payto"
- ",amount"
- ",closing_fee"
- " FROM reserves_close"
- " WHERE close_uuid > $1"
- " ORDER BY close_uuid ASC;");
- rh = &lrbt_cb_table_reserves_close;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS:
- XPREPARE ("select_above_serial_by_table_reserves_open_requests",
- "SELECT"
- " open_request_uuid AS serial"
- ",reserve_pub"
- ",request_timestamp"
- ",expiration_date"
- ",reserve_sig"
- ",reserve_payment"
- ",requested_purse_limit"
- " FROM reserves_open_requests"
- " WHERE open_request_uuid > $1"
- " ORDER BY open_request_uuid ASC;");
- rh = &lrbt_cb_table_reserves_open_requests;
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
- XPREPARE ("select_above_serial_by_table_reserves_open_deposits",
- "SELECT"
- " reserves_open_deposit_uuid AS serial"
- ",reserve_sig"
- ",reserve_pub"
- ",coin_pub"
- ",coin_sig"
- ",contribution"
- " FROM reserves_open_deposits"
- " WHERE reserves_open_deposit_uuid > $1"
- " ORDER BY reserves_open_deposit_uuid ASC;");
- rh = &lrbt_cb_table_reserves_open_deposits;
- break;
- case TALER_EXCHANGEDB_RT_AUDITORS:
- XPREPARE ("select_above_serial_by_table_auditors",
- "SELECT"
- " auditor_uuid AS serial"
- ",auditor_pub"
- ",auditor_name"
- ",auditor_url"
- ",is_active"
- ",last_change"
- " FROM auditors"
- " WHERE auditor_uuid > $1"
- " ORDER BY auditor_uuid ASC;");
- rh = &lrbt_cb_table_auditors;
- break;
- case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS:
- XPREPARE ("select_above_serial_by_table_auditor_denom_sigs",
- "SELECT"
- " auditor_denom_serial AS serial"
- ",auditor_uuid"
- ",denominations_serial"
- ",auditor_sig"
- " FROM auditor_denom_sigs"
- " WHERE auditor_denom_serial > $1"
- " ORDER BY auditor_denom_serial ASC;");
- rh = &lrbt_cb_table_auditor_denom_sigs;
- break;
- case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS:
- XPREPARE ("select_above_serial_by_table_exchange_sign_keys",
- "SELECT"
- " esk_serial AS serial"
- ",exchange_pub"
- ",master_sig"
- ",valid_from"
- ",expire_sign"
- ",expire_legal"
- " FROM exchange_sign_keys"
- " WHERE esk_serial > $1"
- " ORDER BY esk_serial ASC;");
- rh = &lrbt_cb_table_exchange_sign_keys;
- break;
- case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS:
- XPREPARE ("select_above_serial_by_table_signkey_revocations",
- "SELECT"
- " signkey_revocations_serial_id AS serial"
- ",esk_serial"
- ",master_sig"
- " FROM signkey_revocations"
- " WHERE signkey_revocations_serial_id > $1"
- " ORDER BY signkey_revocations_serial_id ASC;");
- rh = &lrbt_cb_table_signkey_revocations;
- break;
- case TALER_EXCHANGEDB_RT_KNOWN_COINS:
- XPREPARE ("select_above_serial_by_table_known_coins",
- "SELECT"
- " known_coin_id AS serial"
- ",coin_pub"
- ",denom_sig"
- ",denominations_serial"
- " FROM known_coins"
- " WHERE known_coin_id > $1"
- " ORDER BY known_coin_id ASC;");
- rh = &lrbt_cb_table_known_coins;
- break;
- case TALER_EXCHANGEDB_RT_REFRESH:
- XPREPARE ("select_above_serial_by_table_refresh",
- "SELECT"
- " refresh_id AS serial"
- ",rc"
- ",execution_date"
- ",amount_with_fee"
- ",old_coin_pub"
- ",old_coin_sig"
- ",refresh_seed"
- ",noreveal_index"
- ",planchets_h"
- ",selected_h"
- ",blinding_seed"
- ",cs_r_values"
- ",cs_r_choices"
- ",denom_serials"
- ",denom_sigs"
- " FROM refresh"
- " WHERE refresh_id > $1"
- " ORDER BY refresh_id ASC;");
- rh = &lrbt_cb_table_refresh;
- break;
- case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS:
- XPREPARE ("select_above_serial_by_table_batch_deposits",
- "SELECT"
- " batch_deposit_serial_id AS serial"
- ",shard"
- ",merchant_pub"
- ",wallet_timestamp"
- ",exchange_timestamp"
- ",refund_deadline"
- ",wire_deadline"
- ",h_contract_terms"
- ",wallet_data_hash"
- ",wire_salt"
- ",wire_target_h_payto"
- ",policy_details_serial_id"
- ",policy_blocked"
- ",total_amount"
- ",total_without_fee"
- ",merchant_sig"
- ",done"
- " FROM batch_deposits"
- " WHERE batch_deposit_serial_id > $1"
- " ORDER BY batch_deposit_serial_id ASC;");
- rh = &lrbt_cb_table_batch_deposits;
- break;
- case TALER_EXCHANGEDB_RT_COIN_DEPOSITS:
- XPREPARE ("select_above_serial_by_table_coin_deposits",
- "SELECT"
- " coin_deposit_serial_id AS serial"
- ",batch_deposit_serial_id"
- ",coin_pub"
- ",coin_sig"
- ",amount_with_fee"
- " FROM coin_deposits"
- " WHERE coin_deposit_serial_id > $1"
- " ORDER BY coin_deposit_serial_id ASC;");
- rh = &lrbt_cb_table_coin_deposits;
- break;
- case TALER_EXCHANGEDB_RT_REFUNDS:
- XPREPARE ("select_above_serial_by_table_refunds",
- "SELECT"
- " refund_serial_id AS serial"
- ",coin_pub"
- ",merchant_sig"
- ",rtransaction_id"
- ",amount_with_fee"
- ",batch_deposit_serial_id"
- " FROM refunds"
- " WHERE refund_serial_id > $1"
- " ORDER BY refund_serial_id ASC;");
- rh = &lrbt_cb_table_refunds;
- break;
- case TALER_EXCHANGEDB_RT_WIRE_OUT:
- XPREPARE ("select_above_serial_by_table_wire_out",
- "SELECT"
- " wireout_uuid AS serial"
- ",execution_date"
- ",wtid_raw"
- ",wire_target_h_payto"
- ",exchange_account_section"
- ",amount"
- " FROM wire_out"
- " WHERE wireout_uuid > $1"
- " ORDER BY wireout_uuid ASC;");
- rh = &lrbt_cb_table_wire_out;
- break;
- case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING:
- XPREPARE ("select_above_serial_by_table_aggregation_tracking",
- "SELECT"
- " aggregation_serial_id AS serial"
- ",batch_deposit_serial_id"
- ",wtid_raw"
- " FROM aggregation_tracking"
- " WHERE aggregation_serial_id > $1"
- " ORDER BY aggregation_serial_id ASC;");
- rh = &lrbt_cb_table_aggregation_tracking;
- break;
- case TALER_EXCHANGEDB_RT_WIRE_FEE:
- XPREPARE ("select_above_serial_by_table_wire_fee",
- "SELECT"
- " wire_fee_serial AS serial"
- ",wire_method"
- ",start_date"
- ",end_date"
- ",wire_fee"
- ",closing_fee"
- ",master_sig"
- " FROM wire_fee"
- " WHERE wire_fee_serial > $1"
- " ORDER BY wire_fee_serial ASC;");
- rh = &lrbt_cb_table_wire_fee;
- break;
- case TALER_EXCHANGEDB_RT_GLOBAL_FEE:
- XPREPARE ("select_above_serial_by_table_global_fee",
- "SELECT"
- " global_fee_serial AS serial"
- ",start_date"
- ",end_date"
- ",history_fee"
- ",account_fee"
- ",purse_fee"
- ",purse_timeout"
- ",history_expiration"
- ",purse_account_limit"
- ",master_sig"
- " FROM global_fee"
- " WHERE global_fee_serial > $1"
- " ORDER BY global_fee_serial ASC;");
- rh = &lrbt_cb_table_global_fee;
- break;
- case TALER_EXCHANGEDB_RT_RECOUP:
- XPREPARE ("select_above_serial_by_table_recoup",
- "SELECT"
- " recoup_uuid AS serial"
- ",coin_sig"
- ",coin_blind"
- ",amount"
- ",recoup_timestamp"
- ",coin_pub"
- ",reserve_out_serial_id"
- " FROM recoup"
- " WHERE recoup_uuid > $1"
- " ORDER BY recoup_uuid ASC;");
- rh = &lrbt_cb_table_recoup;
- break;
- case TALER_EXCHANGEDB_RT_RECOUP_REFRESH:
- XPREPARE ("select_above_serial_by_table_recoup_refresh",
- "SELECT"
- " recoup_refresh_uuid AS serial"
- ",coin_sig"
- ",coin_blind"
- ",amount"
- ",recoup_timestamp"
- ",coin_pub"
- ",known_coin_id"
- ",rrc_serial"
- " FROM recoup_refresh"
- " WHERE recoup_refresh_uuid > $1"
- " ORDER BY recoup_refresh_uuid ASC;");
- rh = &lrbt_cb_table_recoup_refresh;
- break;
- case TALER_EXCHANGEDB_RT_EXTENSIONS:
- // FIXME: this seems broken! -- where is the SQL!?
- statement = "select_above_serial_by_table_extensions";
- rh = &lrbt_cb_table_extensions;
- break;
- case TALER_EXCHANGEDB_RT_POLICY_DETAILS:
- // FIXME: this seems broken! -- where is the SQL!?
- statement = "select_above_serial_by_table_policy_details";
- rh = &lrbt_cb_table_policy_details;
- break;
- case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS:
- // FIXME: this seems broken! -- where is the SQL!?
- statement = "select_above_serial_by_table_policy_fulfillments";
- rh = &lrbt_cb_table_policy_fulfillments;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
- XPREPARE ("select_above_serial_by_table_purse_requests",
- "SELECT"
- " purse_requests_serial_id"
- ",purse_pub"
- ",merge_pub"
- ",purse_creation"
- ",purse_expiration"
- ",h_contract_terms"
- ",age_limit"
- ",flags"
- ",amount_with_fee"
- ",purse_fee"
- ",purse_sig"
- " FROM purse_requests"
- " WHERE purse_requests_serial_id > $1"
- " ORDER BY purse_requests_serial_id ASC;");
- rh = &lrbt_cb_table_purse_requests;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_DECISION:
- XPREPARE ("select_above_serial_by_table_purse_decision",
- "SELECT"
- " purse_decision_serial_id"
- ",action_timestamp"
- ",refunded"
- ",purse_pub"
- " FROM purse_decision"
- " WHERE purse_decision_serial_id > $1"
- " ORDER BY purse_decision_serial_id ASC;");
- rh = &lrbt_cb_table_purse_decision;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_MERGES:
- XPREPARE ("select_above_serial_by_table_purse_merges",
- "SELECT"
- " purse_merge_request_serial_id"
- ",partner_serial_id"
- ",reserve_pub"
- ",purse_pub"
- ",merge_sig"
- ",merge_timestamp"
- " FROM purse_merges"
- " WHERE purse_merge_request_serial_id > $1"
- " ORDER BY purse_merge_request_serial_id ASC;");
- rh = &lrbt_cb_table_purse_merges;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS:
- XPREPARE ("select_above_serial_by_table_purse_deposits",
- "SELECT"
- " purse_deposit_serial_id"
- ",partner_serial_id"
- ",purse_pub"
- ",coin_pub"
- ",amount_with_fee"
- ",coin_sig"
- " FROM purse_deposits"
- " WHERE purse_deposit_serial_id > $1"
- " ORDER BY purse_deposit_serial_id ASC;");
- rh = &lrbt_cb_table_purse_deposits;
- break;
- case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES:
- XPREPARE ("select_above_serial_by_table_account_merges",
- "SELECT"
- " account_merge_request_serial_id"
- ",reserve_pub"
- ",reserve_sig"
- ",purse_pub"
- ",wallet_h_payto"
- " FROM account_merges"
- " WHERE account_merge_request_serial_id > $1"
- " ORDER BY account_merge_request_serial_id ASC;");
- rh = &lrbt_cb_table_account_merges;
- break;
- case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS:
- XPREPARE ("select_above_serial_by_table_history_requests",
- "SELECT"
- " history_request_serial_id"
- ",reserve_pub"
- ",request_timestamp"
- ",reserve_sig"
- ",history_fee"
- " FROM history_requests"
- " WHERE history_request_serial_id > $1"
- " ORDER BY history_request_serial_id ASC;");
- rh = &lrbt_cb_table_history_requests;
- break;
- case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS:
- XPREPARE ("select_above_serial_by_table_close_requests",
- "SELECT"
- " close_request_serial_id"
- ",reserve_pub"
- ",close_timestamp"
- ",reserve_sig"
- ",close"
- " FROM close_requests"
- " WHERE close_request_serial_id > $1"
- " ORDER BY close_request_serial_id ASC;");
- rh = &lrbt_cb_table_close_requests;
- break;
- case TALER_EXCHANGEDB_RT_WADS_OUT:
- XPREPARE ("select_above_serial_by_table_wads_out",
- "SELECT"
- " wad_out_serial_id"
- ",wad_id"
- ",partner_serial_id"
- ",amount"
- ",execution_time"
- " FROM wads_out"
- " WHERE wad_out_serial_id > $1"
- " ORDER BY wad_out_serial_id ASC;");
- rh = &lrbt_cb_table_wads_out;
- break;
- case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES:
- XPREPARE ("select_above_serial_by_table_wads_out_entries",
- "SELECT"
- " wad_out_entry_serial_id"
- ",reserve_pub"
- ",purse_pub"
- ",h_contract"
- ",purse_expiration"
- ",merge_timestamp"
- ",amount_with_fee"
- ",wad_fee"
- ",deposit_fees"
- ",reserve_sig"
- ",purse_sig"
- " FROM wad_out_entries"
- " WHERE wad_out_entry_serial_id > $1"
- " ORDER BY wad_out_entry_serial_id ASC;");
- rh = &lrbt_cb_table_wads_out_entries;
- break;
- case TALER_EXCHANGEDB_RT_WADS_IN:
- XPREPARE ("select_above_serial_by_table_wads_in",
- "SELECT"
- " wad_in_serial_id"
- ",wad_id"
- ",origin_exchange_url"
- ",amount"
- ",arrival_time"
- " FROM wads_in"
- " WHERE wad_in_serial_id > $1"
- " ORDER BY wad_in_serial_id ASC;");
- rh = &lrbt_cb_table_wads_in;
- break;
- case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES:
- XPREPARE ("select_above_serial_by_table_wads_in_entries",
- "SELECT"
- " wad_in_entry_serial_id"
- ",reserve_pub"
- ",purse_pub"
- ",h_contract"
- ",purse_expiration"
- ",merge_timestamp"
- ",amount_with_fee"
- ",wad_fee"
- ",deposit_fees"
- ",reserve_sig"
- ",purse_sig"
- " FROM wad_in_entries"
- " WHERE wad_in_entry_serial_id > $1"
- " ORDER BY wad_in_entry_serial_id ASC;");
- rh = &lrbt_cb_table_wads_in_entries;
- break;
- case TALER_EXCHANGEDB_RT_PROFIT_DRAINS:
- XPREPARE ("select_above_serial_by_table_profit_drains",
- "SELECT"
- " profit_drain_serial_id"
- ",wtid"
- ",account_section"
- ",payto_uri"
- ",trigger_date"
- ",amount"
- ",master_sig"
- " FROM profit_drains"
- " WHERE profit_drain_serial_id > $1"
- " ORDER BY profit_drain_serial_id ASC;");
- rh = &lrbt_cb_table_profit_drains;
- break;
-
- case TALER_EXCHANGEDB_RT_AML_STAFF:
- XPREPARE ("select_above_serial_by_table_aml_staff",
- "SELECT"
- " aml_staff_uuid"
- ",decider_pub"
- ",master_sig"
- ",decider_name"
- ",is_active"
- ",read_only"
- ",last_change"
- " FROM aml_staff"
- " WHERE aml_staff_uuid > $1"
- " ORDER BY aml_staff_uuid ASC;");
- rh = &lrbt_cb_table_aml_staff;
- break;
- case TALER_EXCHANGEDB_RT_PURSE_DELETION:
- XPREPARE ("select_above_serial_by_table_purse_deletion",
- "SELECT"
- " purse_deletion_serial_id"
- ",purse_pub"
- ",purse_sig"
- " FROM purse_deletion"
- " WHERE purse_deletion_serial_id > $1"
- " ORDER BY purse_deletion_serial_id ASC;");
- rh = &lrbt_cb_table_purse_deletion;
- break;
- case TALER_EXCHANGEDB_RT_WITHDRAW:
- XPREPARE ("select_above_serial_by_table_withdraw",
- "SELECT"
- " withdraw_id"
- ",planchets_h"
- ",execution_date"
- ",amount_with_fee"
- ",reserve_pub"
- ",reserve_sig"
- ",max_age"
- ",noreveal_index"
- ",selected_h"
- ",blinding_seed"
- ",cs_r_values"
- ",cs_r_choices"
- ",denom_serials"
- ",denom_sigs"
- " FROM withdraw"
- " WHERE withdraw_id > $1"
- " ORDER BY withdraw_id ASC;");
- rh = &lrbt_cb_table_withdraw;
- break;
- case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES:
- XPREPARE ("select_above_serial_by_table_legitimization_measures",
- "SELECT"
- " legitimization_measure_serial_id AS serial"
- ",access_token"
- ",start_time"
- ",jmeasures::TEXT"
- ",display_priority"
- " FROM legitimization_measures"
- " WHERE legitimization_measure_serial_id > $1"
- " ORDER BY legitimization_measure_serial_id ASC;");
- rh = &lrbt_cb_table_legitimization_measures;
- break;
- case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES:
- XPREPARE ("select_above_serial_by_table_legitimization_outcomes",
- "SELECT"
- " outcome_serial_id AS serial"
- ",h_payto"
- ",decision_time"
- ",expiration_time"
- ",jproperties::TEXT"
- ",to_investigate"
- ",jnew_rules::TEXT"
- " FROM legitimization_outcomes"
- " WHERE outcome_serial_id > $1"
- " ORDER BY outcome_serial_id ASC;");
- rh = &lrbt_cb_table_legitimization_outcomes;
- break;
- case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES:
- XPREPARE ("select_above_serial_by_table_legitimization_processes",
- "SELECT"
- " legitimization_process_serial_id AS serial"
- ",h_payto"
- ",start_time"
- ",expiration_time"
- ",legitimization_measure_serial_id"
- ",measure_index"
- ",provider_name"
- ",provider_user_id"
- ",provider_legitimization_id"
- ",redirect_url"
- " FROM legitimization_processes"
- " WHERE legitimization_process_serial_id > $1"
- " ORDER BY legitimization_process_serial_id ASC;");
- rh = &lrbt_cb_table_legitimization_processes;
- break;
- case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES:
- XPREPARE ("select_above_serial_by_table_kyc_attributes",
- "SELECT"
- " kyc_attributes_serial_id"
- ",h_payto"
- ",legitimization_serial"
- ",collection_time"
- ",expiration_time"
- ",trigger_outcome_serial"
- ",encrypted_attributes"
- " FROM kyc_attributes"
- " WHERE kyc_attributes_serial_id > $1"
- " ORDER BY kyc_attributes_serial_id ASC;");
- rh = &lrbt_cb_table_kyc_attributes;
- break;
- case TALER_EXCHANGEDB_RT_AML_HISTORY:
- XPREPARE ("select_above_serial_by_table_aml_history",
- "SELECT"
- " aml_history_serial_id"
- ",h_payto"
- ",outcome_serial_id"
- ",justification"
- ",decider_pub"
- ",decider_sig"
- " FROM aml_history"
- " WHERE aml_history_serial_id > $1"
- " ORDER BY aml_history_serial_id ASC;");
- rh = &lrbt_cb_table_aml_history;
- break;
- case TALER_EXCHANGEDB_RT_KYC_EVENTS:
- XPREPARE ("select_above_serial_by_table_kyc_events",
- "SELECT"
- " kyc_event_serial_id AS serial"
- ",event_timestamp"
- ",event_type"
- " FROM kyc_events"
- " WHERE kyc_event_serial_id > $1"
- " ORDER BY kyc_event_serial_id ASC;");
- rh = &lrbt_cb_table_kyc_events;
- break;
- }
- if (NULL == rh)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- statement,
- params,
- rh,
- &ctx);
- if (qs < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to run `%s'\n",
- statement);
- return qs;
- }
- if (ctx.error)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- return qs;
-}
-
-
-#undef XPREPARE
-
-/* end of pg_lookup_records_by_table.c */
diff --git a/src/exchangedb/pg_lookup_rules_by_access_token.c b/src/exchangedb/pg_lookup_rules_by_access_token.c
@@ -1,66 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_rules_by_access_token.c
- * @brief Implementation of the lookup_rules_by_access_token function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_rules_by_access_token.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_rules_by_access_token (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- json_t **jnew_rules,
- uint64_t *rowid)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json (
- "jnew_rules",
- jnew_rules),
- NULL),
- GNUNET_PQ_result_spec_uint64 (
- "row_id",
- rowid),
- GNUNET_PQ_result_spec_end
- };
-
- *jnew_rules = NULL;
- PREPARE (pg,
- "lookup_rules_by_access_token",
- "SELECT"
- " jnew_rules::TEXT"
- ",outcome_serial_id AS row_id"
- " FROM legitimization_outcomes"
- " WHERE h_payto=$1"
- " AND is_active"
- " ORDER BY expiration_time DESC,"
- " outcome_serial_id DESC"
- " LIMIT 1;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "lookup_rules_by_access_token",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_serial_by_table.c b/src/exchangedb/pg_lookup_serial_by_table.c
@@ -1,465 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_lookup_serial_by_table.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_serial_by_table.h"
-#include "helper.h"
-
-
-/**
- * Assign statement to @a n and PREPARE
- * @a sql under name @a n.
- */
-#define XPREPARE(n,sql) \
- statement = n; \
- PREPARE (pg, n, sql);
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_serial_by_table (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- enum TALER_EXCHANGEDB_ReplicatedTable
- table,
- uint64_t *serial)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial",
- serial),
- GNUNET_PQ_result_spec_end
- };
- const char *statement = NULL;
-
- switch (table)
- {
- case TALER_EXCHANGEDB_RT_DENOMINATIONS:
- XPREPARE ("select_serial_by_table_denominations",
- "SELECT"
- " denominations_serial AS serial"
- " FROM denominations"
- " ORDER BY denominations_serial DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS:
- XPREPARE ("select_serial_by_table_denomination_revocations",
- "SELECT"
- " denom_revocations_serial_id AS serial"
- " FROM denomination_revocations"
- " ORDER BY denom_revocations_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_WIRE_TARGETS:
- XPREPARE ("select_serial_by_table_wire_targets",
- "SELECT"
- " wire_target_serial_id AS serial"
- " FROM wire_targets"
- " ORDER BY wire_target_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_KYC_TARGETS:
- XPREPARE ("select_serial_by_table_kyc_targets",
- "SELECT"
- " kyc_target_serial_id AS serial"
- " FROM kyc_targets"
- " ORDER BY kyc_target_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_RESERVES:
- XPREPARE ("select_serial_by_table_reserves",
- "SELECT"
- " reserve_uuid AS serial"
- " FROM reserves"
- " ORDER BY reserve_uuid DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_IN:
- XPREPARE ("select_serial_by_table_reserves_in",
- "SELECT"
- " reserve_in_serial_id AS serial"
- " FROM reserves_in"
- " ORDER BY reserve_in_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_KYCAUTHS_IN:
- XPREPARE ("select_serial_by_table_kycauths_in",
- "SELECT"
- " kycauth_in_serial_id AS serial"
- " FROM kycauths_in"
- " ORDER BY kycauths_in_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_CLOSE:
- XPREPARE ("select_serial_by_table_reserves_close",
- "SELECT"
- " close_uuid AS serial"
- " FROM reserves_close"
- " ORDER BY close_uuid DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS:
- XPREPARE ("select_serial_by_table_reserves_open_requests",
- "SELECT"
- " open_request_uuid AS serial"
- " FROM reserves_open_requests"
- " ORDER BY open_request_uuid DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
- XPREPARE ("select_serial_by_table_reserves_open_deposits",
- "SELECT"
- " reserve_open_deposit_uuid AS serial"
- " FROM reserves_open_deposits"
- " ORDER BY reserve_open_deposit_uuid DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_AUDITORS:
- XPREPARE ("select_serial_by_table_auditors",
- "SELECT"
- " auditor_uuid AS serial"
- " FROM auditors"
- " ORDER BY auditor_uuid DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS:
- XPREPARE ("select_serial_by_table_auditor_denom_sigs",
- "SELECT"
- " auditor_denom_serial AS serial"
- " FROM auditor_denom_sigs"
- " ORDER BY auditor_denom_serial DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS:
- XPREPARE ("select_serial_by_table_exchange_sign_keys",
- "SELECT"
- " esk_serial AS serial"
- " FROM exchange_sign_keys"
- " ORDER BY esk_serial DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS:
- XPREPARE ("select_serial_by_table_signkey_revocations",
- "SELECT"
- " signkey_revocations_serial_id AS serial"
- " FROM signkey_revocations"
- " ORDER BY signkey_revocations_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_KNOWN_COINS:
- XPREPARE ("select_serial_by_table_known_coins",
- "SELECT"
- " known_coin_id AS serial"
- " FROM known_coins"
- " ORDER BY known_coin_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_REFRESH:
- XPREPARE ("select_serial_by_table_refresh",
- "SELECT"
- " refresh_id AS serial"
- " FROM refresh"
- " ORDER BY refresh_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS:
- XPREPARE ("select_serial_by_table_batch_deposits",
- "SELECT"
- " batch_deposit_serial_id AS serial"
- " FROM batch_deposits"
- " ORDER BY batch_deposit_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_COIN_DEPOSITS:
- XPREPARE ("select_serial_by_table_coin_deposits",
- "SELECT"
- " coin_deposit_serial_id AS serial"
- " FROM coin_deposits"
- " ORDER BY coin_deposit_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_REFUNDS:
- XPREPARE ("select_serial_by_table_refunds",
- "SELECT"
- " refund_serial_id AS serial"
- " FROM refunds"
- " ORDER BY refund_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_WIRE_OUT:
- XPREPARE ("select_serial_by_table_wire_out",
- "SELECT"
- " wireout_uuid AS serial"
- " FROM wire_out"
- " ORDER BY wireout_uuid DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING:
- XPREPARE ("select_serial_by_table_aggregation_tracking",
- "SELECT"
- " aggregation_serial_id AS serial"
- " FROM aggregation_tracking"
- " ORDER BY aggregation_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_WIRE_FEE:
- XPREPARE ("select_serial_by_table_wire_fee",
- "SELECT"
- " wire_fee_serial AS serial"
- " FROM wire_fee"
- " ORDER BY wire_fee_serial DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_GLOBAL_FEE:
- XPREPARE ("select_serial_by_table_global_fee",
- "SELECT"
- " global_fee_serial AS serial"
- " FROM global_fee"
- " ORDER BY global_fee_serial DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_RECOUP:
- XPREPARE ("select_serial_by_table_recoup",
- "SELECT"
- " recoup_uuid AS serial"
- " FROM recoup"
- " ORDER BY recoup_uuid DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_RECOUP_REFRESH:
- XPREPARE ("select_serial_by_table_recoup_refresh",
- "SELECT"
- " recoup_refresh_uuid AS serial"
- " FROM recoup_refresh"
- " ORDER BY recoup_refresh_uuid DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_EXTENSIONS:
- XPREPARE ("select_serial_by_table_extensions",
- "SELECT"
- " extension_id AS serial"
- " FROM extensions"
- " ORDER BY extension_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_POLICY_DETAILS:
- XPREPARE ("select_serial_by_table_policy_details",
- "SELECT"
- " policy_details_serial_id AS serial"
- " FROM policy_details"
- " ORDER BY policy_details_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS:
- XPREPARE ("select_serial_by_table_policy_fulfillments",
- "SELECT"
- " fulfillment_id AS serial"
- " FROM policy_fulfillments"
- " ORDER BY fulfillment_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
- XPREPARE ("select_serial_by_table_purse_requests",
- "SELECT"
- " purse_requests_serial_id AS serial"
- " FROM purse_requests"
- " ORDER BY purse_requests_serial_id DESC"
- " LIMIT 1;")
- break;
- case TALER_EXCHANGEDB_RT_PURSE_DECISION:
- XPREPARE ("select_serial_by_table_purse_decision",
- "SELECT"
- " purse_decision_serial_id AS serial"
- " FROM purse_decision"
- " ORDER BY purse_decision_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_PURSE_MERGES:
- XPREPARE ("select_serial_by_table_purse_merges",
- "SELECT"
- " purse_merge_request_serial_id AS serial"
- " FROM purse_merges"
- " ORDER BY purse_merge_request_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS:
- XPREPARE ("select_serial_by_table_purse_deposits",
- "SELECT"
- " purse_deposit_serial_id AS serial"
- " FROM purse_deposits"
- " ORDER BY purse_deposit_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES:
- XPREPARE ("select_serial_by_table_account_merges",
- "SELECT"
- " account_merge_request_serial_id AS serial"
- " FROM account_merges"
- " ORDER BY account_merge_request_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS:
- XPREPARE ("select_serial_by_table_history_requests",
- "SELECT"
- " history_request_serial_id AS serial"
- " FROM history_requests"
- " ORDER BY history_request_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS:
- XPREPARE ("select_serial_by_table_close_requests",
- "SELECT"
- " close_request_serial_id AS serial"
- " FROM close_requests"
- " ORDER BY close_request_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_WADS_OUT:
- XPREPARE ("select_serial_by_table_wads_out",
- "SELECT"
- " wad_out_serial_id AS serial"
- " FROM wads_out"
- " ORDER BY wad_out_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES:
- XPREPARE ("select_serial_by_table_wads_out_entries",
- "SELECT"
- " wad_out_entry_serial_id AS serial"
- " FROM wad_out_entries"
- " ORDER BY wad_out_entry_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_WADS_IN:
- XPREPARE ("select_serial_by_table_wads_in",
- "SELECT"
- " wad_in_serial_id AS serial"
- " FROM wads_in"
- " ORDER BY wad_in_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES:
- XPREPARE ("select_serial_by_table_wads_in_entries",
- "SELECT"
- " wad_in_entry_serial_id AS serial"
- " FROM wad_in_entries"
- " ORDER BY wad_in_entry_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_PROFIT_DRAINS:
- XPREPARE ("select_serial_by_table_profit_drains",
- "SELECT"
- " profit_drain_serial_id AS serial"
- " FROM profit_drains"
- " ORDER BY profit_drain_serial_id DESC"
- " LIMIT 1;");
- statement = "select_serial_by_table_profit_drains";
- break;
- case TALER_EXCHANGEDB_RT_AML_STAFF:
- XPREPARE ("select_serial_by_table_aml_staff",
- "SELECT"
- " aml_staff_uuid AS serial"
- " FROM aml_staff"
- " ORDER BY aml_staff_uuid DESC"
- " LIMIT 1;");
- statement = "select_serial_by_table_aml_staff";
- break;
- case TALER_EXCHANGEDB_RT_PURSE_DELETION:
- XPREPARE ("select_serial_by_table_purse_deletion",
- "SELECT"
- " purse_deletion_serial_id AS serial"
- " FROM purse_deletion"
- " ORDER BY purse_deletion_serial_id DESC"
- " LIMIT 1;");
- statement = "select_serial_by_table_purse_deletion";
- break;
- case TALER_EXCHANGEDB_RT_WITHDRAW:
- XPREPARE ("select_serial_by_table_withdraw",
- "SELECT"
- " withdraw_id AS serial"
- " FROM withdraw"
- " ORDER BY withdraw_id DESC"
- " LIMIT 1;");
- statement = "select_serial_by_table_withdraw";
- break;
- case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES:
- XPREPARE ("select_serial_by_table_legitimization_measures",
- "SELECT"
- " legitimization_measure_serial_id AS serial"
- " FROM legitimization_measures"
- " ORDER BY legitimization_measure_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES:
- XPREPARE ("select_serial_by_table_legitimization_outcomes",
- "SELECT"
- " outcome_serial_id AS serial"
- " FROM legitimization_outcomes"
- " ORDER BY outcome_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES:
- XPREPARE ("select_serial_by_table_legitimization_processes",
- "SELECT"
- " legitimization_process_serial_id AS serial"
- " FROM legitimization_processes"
- " ORDER BY legitimization_process_serial_id DESC"
- " LIMIT 1;");
- break;
- case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES:
- XPREPARE ("select_serial_by_table_kyc_attributes",
- "SELECT"
- " kyc_attributes_serial_id AS serial"
- " FROM kyc_attributes"
- " ORDER BY kyc_attributes_serial_id DESC"
- " LIMIT 1;");
- statement = "select_serial_by_table_kyc_attributes";
- break;
- case TALER_EXCHANGEDB_RT_AML_HISTORY:
- XPREPARE ("select_serial_by_table_aml_history",
- "SELECT"
- " aml_history_serial_id AS serial"
- " FROM aml_history"
- " ORDER BY aml_history_serial_id DESC"
- " LIMIT 1;");
- statement = "select_serial_by_table_aml_history";
- break;
- case TALER_EXCHANGEDB_RT_KYC_EVENTS:
- XPREPARE ("select_serial_by_table_kyc_events",
- "SELECT"
- " kyc_event_serial_id AS serial"
- " FROM kyc_events"
- " ORDER BY kyc_event_serial_id DESC"
- " LIMIT 1;");
- break;
- }
- if (NULL == statement)
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- statement,
- params,
- rs);
-}
-
-
-#undef XPREPARE
diff --git a/src/exchangedb/pg_lookup_signing_key.c b/src/exchangedb/pg_lookup_signing_key.c
@@ -1,60 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_signing_key.c
- * @brief Implementation of the lookup_signing_key function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_signing_key.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_signing_key (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- struct TALER_EXCHANGEDB_SignkeyMetaData *meta)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (exchange_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("valid_from",
- &meta->start),
- GNUNET_PQ_result_spec_timestamp ("expire_sign",
- &meta->expire_sign),
- GNUNET_PQ_result_spec_timestamp ("expire_legal",
- &meta->expire_legal),
- GNUNET_PQ_result_spec_end
- };
-
-
- PREPARE (pg,
- "lookup_signing_key",
- "SELECT"
- " valid_from"
- ",expire_sign"
- ",expire_legal"
- " FROM exchange_sign_keys"
- " WHERE exchange_pub=$1");
-
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_signing_key",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_signkey_revocation.c b/src/exchangedb/pg_lookup_signkey_revocation.c
@@ -1,55 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_signkey_revocation.c
- * @brief Implementation of the lookup_signkey_revocation function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_signkey_revocation.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_signkey_revocation (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (exchange_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- master_sig),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "lookup_signkey_revocation",
- "SELECT "
- " master_sig"
- " FROM signkey_revocations"
- " WHERE esk_serial="
- " (SELECT esk_serial"
- " FROM exchange_sign_keys"
- " WHERE exchange_pub=$1);");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_signkey_revocation",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_transfer_by_deposit.c b/src/exchangedb/pg_lookup_transfer_by_deposit.c
@@ -1,220 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_transfer_by_deposit.c
- * @brief Implementation of the lookup_transfer_by_deposit function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_transfer_by_deposit.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_transfer_by_deposit (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- const struct TALER_MerchantWireHashP *h_wire,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- bool *pending,
- struct TALER_WireTransferIdentifierRawP *wtid,
- struct GNUNET_TIME_Timestamp *exec_time,
- struct TALER_Amount *amount_with_fee,
- struct TALER_Amount *deposit_fee,
- struct TALER_EXCHANGEDB_KycStatus *kyc,
- union TALER_AccountPublicKeyP *account_pub)
-{
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
- GNUNET_PQ_query_param_auto_from_type (merchant_pub),
- GNUNET_PQ_query_param_end
- };
- struct TALER_FullPayto payto_uri;
- struct TALER_WireSaltP wire_salt;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
- wtid),
- GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
- &wire_salt),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri.full_payto),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- exec_time),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- deposit_fee),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("target_pub",
- account_pub),
- NULL),
- GNUNET_PQ_result_spec_end
- };
-
- memset (kyc,
- 0,
- sizeof (*kyc));
- /* check if the aggregation record exists and get it */
- PREPARE (pg,
- "lookup_deposit_wtid",
- "SELECT"
- " atr.wtid_raw"
- ",wire_out.execution_date"
- ",cdep.amount_with_fee"
- ",bdep.wire_salt"
- ",wt.payto_uri"
- ",kt.target_pub"
- ",denom.fee_deposit"
- " FROM coin_deposits cdep"
- " JOIN batch_deposits bdep"
- " USING (batch_deposit_serial_id)"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- /* kyc_targets might not match; then target_pub will be NULL */
- " LEFT JOIN kyc_targets kt"
- " USING (h_normalized_payto)"
- " JOIN aggregation_tracking atr"
- " ON (cdep.batch_deposit_serial_id = atr.batch_deposit_serial_id)"
- " JOIN known_coins kc"
- " ON (kc.coin_pub = cdep.coin_pub)"
- " JOIN denominations denom"
- " USING (denominations_serial)"
- " JOIN wire_out"
- " USING (wtid_raw)"
- " WHERE cdep.coin_pub=$1"
- " AND bdep.merchant_pub=$3"
- " AND bdep.h_contract_terms=$2");
- /* NOTE: above query might be more efficient if we computed the shard
- from the merchant_pub and included that in the query */
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_deposit_wtid",
- params,
- rs);
- if (0 > qs)
- return qs;
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- {
- struct TALER_MerchantWireHashP wh;
-
- TALER_merchant_wire_signature_hash (payto_uri,
- &wire_salt,
- &wh);
- if (0 ==
- GNUNET_memcmp (&wh,
- h_wire))
- {
- *pending = false;
- kyc->ok = true;
- GNUNET_PQ_cleanup_result (rs);
- return qs;
- }
- qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- GNUNET_PQ_cleanup_result (rs);
- }
- *pending = true;
- memset (wtid,
- 0,
- sizeof (*wtid));
- GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "lookup_deposit_wtid returned 0 matching rows\n");
- {
- /* Check if transaction exists in deposits, so that we just
- do not have a WTID yet. In that case, return without wtid
- (by setting 'pending' true). */
- struct GNUNET_PQ_ResultSpec rs2[] = {
- GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
- &wire_salt),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri.full_payto),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- deposit_fee),
- GNUNET_PQ_result_spec_timestamp ("wire_deadline",
- exec_time),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 ("legitimization_requirement_serial_id",
- &kyc->requirement_row),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("target_pub",
- account_pub),
- NULL),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_deposit_without_wtid",
- "SELECT"
- " bdep.wire_salt"
- ",wt.payto_uri"
- ",cdep.amount_with_fee"
- ",denom.fee_deposit"
- ",bdep.wire_deadline"
- ",agt.legitimization_requirement_serial_id"
- ",kt.target_pub"
- " FROM coin_deposits cdep"
- " JOIN batch_deposits bdep"
- " USING (batch_deposit_serial_id)"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- /* kyc_targets might not match; then target_pub will be NULL */
- " LEFT JOIN kyc_targets kt"
- " USING (h_normalized_payto)"
- " JOIN known_coins kc"
- " ON (kc.coin_pub = cdep.coin_pub)"
- " JOIN denominations denom"
- " USING (denominations_serial)"
- " LEFT JOIN aggregation_transient agt "
- " ON ( (bdep.wire_target_h_payto = agt.wire_target_h_payto) AND"
- " (bdep.merchant_pub = agt.merchant_pub) )"
- " WHERE cdep.coin_pub=$1"
- " AND bdep.merchant_pub=$3"
- " AND bdep.h_contract_terms=$2"
- " LIMIT 1;");
- /* NOTE: above query might be more efficient if we computed the shard
- from the merchant_pub and included that in the query */
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_deposit_without_wtid",
- params,
- rs2);
- if (0 > qs)
- return qs;
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- {
- struct TALER_MerchantWireHashP wh;
-
- TALER_merchant_wire_signature_hash (payto_uri,
- &wire_salt,
- &wh);
- if (0 !=
- GNUNET_memcmp (&wh,
- h_wire))
- {
- GNUNET_PQ_cleanup_result (rs2);
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- }
- GNUNET_PQ_cleanup_result (rs2);
- if (0 == kyc->requirement_row)
- kyc->ok = true; /* technically: unknown */
- }
- return qs;
- }
-}
diff --git a/src/exchangedb/pg_lookup_wire_fee_by_time.c b/src/exchangedb/pg_lookup_wire_fee_by_time.c
@@ -1,152 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_wire_fee_by_time.c
- * @brief Implementation of the lookup_wire_fee_by_time function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_wire_fee_by_time.h"
-#include "helper.h"
-
-
-/**
- * Closure for #wire_fee_by_time_helper()
- */
-struct WireFeeLookupContext
-{
-
- /**
- * Set to the wire fees. Set to invalid if fees conflict over
- * the given time period.
- */
- struct TALER_WireFeeSet *fees;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-};
-
-
-/**
- * Helper function for #TALER_EXCHANGEDB_lookup_wire_fee_by_time().
- * Calls the callback with the wire fee structure.
- *
- * @param cls a `struct WireFeeLookupContext`
- * @param result db results
- * @param num_results number of results in @a result
- */
-static void
-wire_fee_by_time_helper (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct WireFeeLookupContext *wlc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = wlc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_WireFeeSet fs;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
- &fs.wire),
- TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
- &fs.closing),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- /* invalidate */
- memset (wlc->fees,
- 0,
- sizeof (struct TALER_WireFeeSet));
- return;
- }
- if (0 == i)
- {
- *wlc->fees = fs;
- continue;
- }
- if (0 !=
- TALER_wire_fee_set_cmp (&fs,
- wlc->fees))
- {
- /* invalidate */
- memset (wlc->fees,
- 0,
- sizeof (struct TALER_WireFeeSet));
- return;
- }
- }
-}
-
-
-/**
- * Lookup information about known wire fees. Finds all applicable
- * fees in the given range. If they are identical, returns the
- * respective @a fees. If any of the fees
- * differ between @a start_time and @a end_time, the transaction
- * succeeds BUT returns an invalid amount for both fees.
- *
- * @param pg the database context
- * @param wire_method the wire method to lookup fees for
- * @param start_time starting time of fee
- * @param end_time end time of fee
- * @param[out] fees wire fees for that time period; if
- * different fees exists within this time
- * period, an 'invalid' amount is returned.
- * @return transaction status code
- */
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_wire_fee_by_time (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *wire_method,
- struct GNUNET_TIME_Timestamp start_time,
- struct GNUNET_TIME_Timestamp end_time,
- struct TALER_WireFeeSet *fees)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (wire_method),
- GNUNET_PQ_query_param_timestamp (&start_time),
- GNUNET_PQ_query_param_timestamp (&end_time),
- GNUNET_PQ_query_param_end
- };
- struct WireFeeLookupContext wlc = {
- .fees = fees,
- .pg = pg
- };
-
- PREPARE (pg,
- "lookup_wire_fee_by_time",
- "SELECT"
- " wire_fee"
- ",closing_fee"
- " FROM wire_fee"
- " WHERE wire_method=$1"
- " AND end_date > $2"
- " AND start_date < $3;");
- return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "lookup_wire_fee_by_time",
- params,
- &wire_fee_by_time_helper,
- &wlc);
-}
diff --git a/src/exchangedb/pg_lookup_wire_timestamp.c b/src/exchangedb/pg_lookup_wire_timestamp.c
@@ -1,52 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_wire_timestamp.c
- * @brief Implementation of the lookup_wire_timestamp function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_wire_timestamp.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_wire_timestamp (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPayto payto_uri,
- struct GNUNET_TIME_Timestamp *last_date)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (payto_uri.full_payto),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("last_change",
- last_date),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "lookup_wire_timestamp",
- "SELECT"
- " last_change"
- " FROM wire_accounts"
- " WHERE payto_uri=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "lookup_wire_timestamp",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_lookup_wire_transfer.c b/src/exchangedb/pg_lookup_wire_transfer.c
@@ -1,184 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_lookup_wire_transfer.c
- * @brief Implementation of the lookup_wire_transfer function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/lookup_wire_transfer.h"
-#include "helper.h"
-
-/**
- * Closure for #handle_wt_result.
- */
-struct WireTransferResultContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_AggregationDataCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on serious errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results. Helper function
- * for #TALER_EXCHANGEDB_lookup_wire_transfer().
- *
- * @param cls closure of type `struct WireTransferResultContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_wt_result (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct WireTransferResultContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct TALER_PrivateContractHashP h_contract_terms;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_FullPaytoHashP h_payto;
- struct TALER_MerchantPublicKeyP merchant_pub;
- struct GNUNET_TIME_Timestamp exec_time;
- struct TALER_Amount amount_with_fee;
- struct TALER_Amount deposit_fee;
- struct TALER_DenominationPublicKey denom_pub;
- struct TALER_FullPayto payto_uri;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- &h_contract_terms),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri.full_payto),
- GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
- &h_payto),
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &coin_pub),
- GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
- &merchant_pub),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- &exec_time),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- &deposit_fee),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ctx->cb (ctx->cb_cls,
- rowid,
- &merchant_pub,
- payto_uri,
- &h_payto,
- exec_time,
- &h_contract_terms,
- &denom_pub,
- &coin_pub,
- &amount_with_fee,
- &deposit_fee);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_lookup_wire_transfer (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- TALER_EXCHANGEDB_AggregationDataCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_end
- };
- struct WireTransferResultContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "lookup_transactions",
- "SELECT"
- " aggregation_serial_id"
- ",bdep.h_contract_terms"
- ",payto_uri"
- ",wt.wire_target_h_payto"
- ",kc.coin_pub"
- ",bdep.merchant_pub"
- ",wire_out.execution_date"
- ",cdep.amount_with_fee"
- ",denom.fee_deposit"
- ",denom.denom_pub"
- " FROM aggregation_tracking"
- " JOIN batch_deposits bdep"
- " USING (batch_deposit_serial_id)"
- " JOIN coin_deposits cdep"
- " USING (batch_deposit_serial_id)"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " JOIN known_coins kc"
- " USING (coin_pub)"
- " JOIN denominations denom"
- " USING (denominations_serial)"
- " JOIN wire_out"
- " USING (wtid_raw)"
- " WHERE wtid_raw=$1;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "lookup_transactions",
- params,
- &handle_wt_result,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_mark_refresh_reveal_success.c b/src/exchangedb/pg_mark_refresh_reveal_success.c
@@ -1,45 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_mark_refresh_reveal_success.c
- * @brief Implementation of the mark_refresh_reveal_success function for Postgres
- * @author Özgür Kesim
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/mark_refresh_reveal_success.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_mark_refresh_reveal_success (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_RefreshCommitmentP *rc)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (rc),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "mark_refresh_reveal_success",
- "UPDATE refresh"
- " SET revealed=true"
- " WHERE rc = $1");
-
- return GNUNET_PQ_eval_prepared_non_select (
- pg->conn,
- "mark_refresh_reveal_success",
- params);
-}
diff --git a/src/exchangedb/pg_persist_kyc_attributes.c b/src/exchangedb/pg_persist_kyc_attributes.c
@@ -1,103 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_persist_kyc_attributes.c
- * @brief Implementation of the persist_kyc_attributes function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/persist_kyc_attributes.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_persist_kyc_attributes (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t process_row,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const char *provider_name,
- const char *provider_account_id,
- const char *provider_legitimization_id,
- uint32_t birthday,
- struct GNUNET_TIME_Absolute expiration_time,
- const char *form_name,
- size_t enc_attributes_size,
- const void *enc_attributes)
-{
- struct GNUNET_TIME_Timestamp collection_time
- = GNUNET_TIME_timestamp_get ();
- struct GNUNET_TIME_Timestamp expiration
- = GNUNET_TIME_absolute_to_timestamp (expiration_time);
- struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = *h_payto
- };
- char *kyc_completed_notify_s
- = GNUNET_PQ_get_event_notify_channel (&rep.header);
- struct GNUNET_PQ_QueryParam params[] = {
- (0 == process_row)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (&process_row),
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_uint32 (&birthday),
- GNUNET_PQ_query_param_string (provider_name),
- (NULL == provider_account_id)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (provider_account_id),
- (NULL == provider_legitimization_id)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (provider_legitimization_id),
- GNUNET_PQ_query_param_timestamp (&collection_time),
- GNUNET_PQ_query_param_absolute_time (&expiration_time),
- GNUNET_PQ_query_param_timestamp (&expiration),
- (NULL == enc_attributes)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_fixed_size (enc_attributes,
- enc_attributes_size),
- GNUNET_PQ_query_param_string (kyc_completed_notify_s),
- (NULL == form_name)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (form_name),
- GNUNET_PQ_query_param_end
- };
- bool ok;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("out_ok",
- &ok),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Inserting KYC attributes, wake up on %s\n",
- kyc_completed_notify_s);
- GNUNET_break (NULL != h_payto);
- PREPARE (pg,
- "persist_kyc_attributes",
- "SELECT "
- " out_ok"
- " FROM exchange_do_persist_kyc_attributes "
- "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "persist_kyc_attributes",
- params,
- rs);
- GNUNET_PQ_cleanup_query_params_closures (params);
- GNUNET_free (kyc_completed_notify_s);
- GNUNET_PQ_event_do_poll (pg->conn);
- return qs;
-}
diff --git a/src/exchangedb/pg_persist_policy_details.c b/src/exchangedb/pg_persist_policy_details.c
@@ -1,74 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_persist_policy_details.c
- * @brief Implementation of the persist_policy_details function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/persist_policy_details.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_persist_policy_details (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PolicyDetails *details,
- uint64_t *policy_details_serial_id,
- struct TALER_Amount *accumulated_total,
- enum TALER_PolicyFulfillmentState *fulfillment_state)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&details->hash_code),
- TALER_PQ_query_param_json (details->policy_json),
- GNUNET_PQ_query_param_timestamp (&details->deadline),
- TALER_PQ_query_param_amount (pg->conn,
- &details->commitment),
- TALER_PQ_query_param_amount (pg->conn,
- &details->accumulated_total),
- TALER_PQ_query_param_amount (pg->conn,
- &details->policy_fee),
- TALER_PQ_query_param_amount (pg->conn,
- &details->transferable_amount),
- GNUNET_PQ_query_param_auto_from_type (&details->fulfillment_state),
- (details->no_policy_fulfillment_id)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_uint64 (&details->policy_fulfillment_id),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id",
- policy_details_serial_id),
- TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
- accumulated_total),
- GNUNET_PQ_result_spec_uint32 ("fulfillment_state",
- fulfillment_state),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "call_insert_or_update_policy_details",
- "SELECT"
- " out_policy_details_serial_id AS policy_details_serial_id"
- ",out_accumulated_total AS accumulated_total"
- ",out_fulfillment_state AS fulfillment_state"
- " FROM exchange_do_insert_or_update_policy_details"
- "($1, $2, $3, $4, $5, $6, $7, $8, $9);");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "call_insert_or_update_policy_details",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_preflight.c b/src/exchangedb/pg_preflight.c
@@ -1,111 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_preflight.c
- * @brief Implementation of the preflight function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/preflight.h"
-#include "helper.h"
-
-
-static enum GNUNET_GenericReturnValue
-internal_setup (struct TALER_EXCHANGEDB_PostgresContext *pg)
-{
- if (NULL == pg->conn)
- {
-#if AUTO_EXPLAIN
- /* Enable verbose logging to see where queries do not
- properly use indices */
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"),
- GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"),
- GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"),
- GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"),
- /* https://wiki.postgresql.org/wiki/Serializable suggests to really
- force the default to 'serializable' if SSI is to be used. */
- GNUNET_PQ_make_try_execute (
- "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
- GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"),
- GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
- GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
- /* Mergejoin causes issues, see Postgres #18380 */
- GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-#else
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_try_execute (
- "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
- GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"),
- GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
- /* Mergejoin causes issues, see Postgres #18380 */
- GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"),
- GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-#endif
- struct GNUNET_PQ_Context *db_conn;
-
- db_conn = GNUNET_PQ_connect_with_cfg2 (pg->cfg,
- "exchangedb-postgres",
- "exchange-", /* load_path_suffix */
- es,
- NULL /* prepared statements */,
- GNUNET_PQ_FLAG_CHECK_CURRENT);
- if (NULL == db_conn)
- return GNUNET_SYSERR;
-
- pg->prep_gen++;
- pg->conn = db_conn;
- }
- if (NULL == pg->transaction_name)
- GNUNET_PQ_reconnect_if_down (pg->conn);
- return GNUNET_OK;
-}
-
-
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGEDB_preflight (struct TALER_EXCHANGEDB_PostgresContext *pg)
-{
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("ROLLBACK"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- if (GNUNET_OK !=
- internal_setup (pg))
- return GNUNET_SYSERR;
- if (NULL == pg->transaction_name)
- return GNUNET_OK; /* all good */
- if (GNUNET_OK ==
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "BUG: Preflight check rolled back transaction `%s'!\n",
- pg->transaction_name);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "BUG: Preflight check failed to rollback transaction `%s'!\n",
- pg->transaction_name);
- }
- pg->transaction_name = NULL;
- return GNUNET_NO;
-}
diff --git a/src/exchangedb/pg_profit_drains_get_pending.c b/src/exchangedb/pg_profit_drains_get_pending.c
@@ -1,75 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_profit_drains_get_pending.c
- * @brief Implementation of the profit_drains_get_pending function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/profit_drains_get_pending.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_profit_drains_get_pending (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t *serial,
- struct TALER_WireTransferIdentifierRawP *wtid,
- char **account_section,
- struct TALER_FullPayto *payto_uri,
- struct GNUNET_TIME_Timestamp *request_timestamp,
- struct TALER_Amount *amount,
- struct TALER_MasterSignatureP *master_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("profit_drain_serial_id",
- serial),
- GNUNET_PQ_result_spec_auto_from_type ("wtid",
- wtid),
- GNUNET_PQ_result_spec_string ("account_section",
- account_section),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri->full_payto),
- GNUNET_PQ_result_spec_timestamp ("trigger_date",
- request_timestamp),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- amount),
- GNUNET_PQ_result_spec_auto_from_type ("master_sig",
- master_sig),
- GNUNET_PQ_result_spec_end
- };
- /* Used in #postgres_profit_drains_get_pending() */
- PREPARE (pg,
- "get_ready_profit_drain",
- "SELECT"
- " profit_drain_serial_id"
- ",wtid"
- ",account_section"
- ",payto_uri"
- ",trigger_date"
- ",amount"
- ",master_sig"
- " FROM profit_drains"
- " WHERE NOT executed"
- " ORDER BY trigger_date ASC;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "get_ready_profit_drain",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_profit_drains_set_finished.c b/src/exchangedb/pg_profit_drains_set_finished.c
@@ -1,45 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_profit_drains_set_finished.c
- * @brief Implementation of the profit_drains_set_finished function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/profit_drains_set_finished.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_profit_drains_set_finished (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "drain_profit_set_finished",
- "UPDATE profit_drains"
- " SET"
- " executed=TRUE"
- " WHERE profit_drain_serial_id=$1;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "drain_profit_set_finished",
- params);
-}
diff --git a/src/exchangedb/pg_release_revolving_shard.c b/src/exchangedb/pg_release_revolving_shard.c
@@ -1,56 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_release_revolving_shard.c
- * @brief Implementation of the release_revolving_shard function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/release_revolving_shard.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_release_revolving_shard (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- const char *job_name,
- uint32_t start_row,
- uint32_t end_row)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (job_name),
- GNUNET_PQ_query_param_uint32 (&start_row),
- GNUNET_PQ_query_param_uint32 (&end_row),
- GNUNET_PQ_query_param_end
- };
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Releasing revolving shard %s %u-%u\n",
- job_name,
- (unsigned int) start_row,
- (unsigned int) end_row);
-
-
- PREPARE (pg,
- "release_revolving_shard",
- "UPDATE revolving_work_shards"
- " SET active=FALSE"
- " WHERE job_name=$1"
- " AND start_row=$2"
- " AND end_row=$3");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "release_revolving_shard",
- params);
-}
diff --git a/src/exchangedb/pg_reserves_get.c b/src/exchangedb/pg_reserves_get.c
@@ -1,57 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_reserves_get.c
- * @brief Implementation of the reserves_get function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/reserves_get.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_reserves_get (struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct TALER_EXCHANGEDB_Reserve *reserve)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&reserve->pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_amount ("current_balance",
- pg->currency,
- &reserve->balance),
- GNUNET_PQ_result_spec_timestamp ("expiration_date",
- &reserve->expiry),
- GNUNET_PQ_result_spec_timestamp ("gc_date",
- &reserve->gc),
- GNUNET_PQ_result_spec_end
- };
- /* Used in #postgres_reserves_get() */
- PREPARE (pg,
- "reserves_get",
- "SELECT"
- " current_balance"
- ",expiration_date"
- ",gc_date"
- " FROM reserves"
- " WHERE reserve_pub=$1"
- " LIMIT 1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "reserves_get",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_reserves_get_origin.c b/src/exchangedb/pg_reserves_get_origin.c
@@ -1,61 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_reserves_get_origin.c
- * @brief Implementation of the reserves_get_origin function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/reserves_get_origin.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_reserves_get_origin (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- struct TALER_FullPaytoHashP *h_payto,
- struct TALER_FullPayto *payto_uri)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type (
- "wire_source_h_payto",
- h_payto),
- GNUNET_PQ_result_spec_string (
- "payto_uri",
- &payto_uri->full_payto),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "get_h_wire_source_of_reserve",
- "SELECT"
- " rt.wire_source_h_payto"
- ",wt.payto_uri"
- " FROM reserves_in rt"
- " JOIN wire_targets wt"
- " ON (rt.wire_source_h_payto = wt.wire_target_h_payto)"
- " WHERE rt.reserve_pub=$1");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "get_h_wire_source_of_reserve",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_reserves_in_insert.c b/src/exchangedb/pg_reserves_in_insert.c
@@ -1,374 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_reserves_in_insert.c
- * @brief Implementation of the reserves_in_insert function for Postgres
- * @author Christian Grothoff
- * @author Joseph Xu
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/reserves_in_insert.h"
-#include "helper.h"
-#include "taler/exchange-database/start.h"
-#include "taler/exchange-database/start_read_committed.h"
-#include "taler/exchange-database/commit.h"
-#include "taler/exchange-database/preflight.h"
-#include "taler/exchange-database/rollback.h"
-
-
-/**
- * Generate event notification for the reserve change.
- *
- * @param reserve_pub reserve to notfiy on
- * @return string to pass to postgres for the notification
- */
-static char *
-compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
-{
- struct TALER_EXCHANGEDB_ReserveEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
- .reserve_pub = *reserve_pub
- };
-
- return GNUNET_PQ_get_event_notify_channel (&rep.header);
-}
-
-
-/**
- * Closure for our helper_cb()
- */
-struct Context
-{
- /**
- * Array of reserve UUIDs to initialize.
- */
- uint64_t *reserve_uuids;
-
- /**
- * Array with entries set to 'true' for duplicate transactions.
- */
- bool *transaction_duplicates;
-
- /**
- * Array with entries set to 'true' for rows with conflicts.
- */
- bool *conflicts;
-
- /**
- * Set to #GNUNET_SYSERR on failures.
- */
- enum GNUNET_GenericReturnValue status;
-
- /**
- * Single value (no array) set to true if we need
- * to follow-up with an update.
- */
- bool needs_update;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct Context *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct Context *ctx = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool (
- "transaction_duplicate",
- &ctx->transaction_duplicates[i]),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint64 ("ruuid",
- &ctx->reserve_uuids[i]),
- &ctx->conflicts[i]),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- if (! ctx->transaction_duplicates[i])
- ctx->needs_update |= ctx->conflicts[i];
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_reserves_in_insert (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
- unsigned int reserves_length,
- enum GNUNET_DB_QueryStatus *results)
-{
- unsigned int dups = 0;
-
- struct TALER_FullPaytoHashP h_full_paytos[
- GNUNET_NZL (reserves_length)];
- struct TALER_NormalizedPaytoHashP h_normalized_paytos[
- GNUNET_NZL (reserves_length)];
- char *notify_s[GNUNET_NZL (reserves_length)];
- struct TALER_ReservePublicKeyP reserve_pubs[GNUNET_NZL (reserves_length)];
- struct TALER_Amount balances[GNUNET_NZL (reserves_length)];
- struct GNUNET_TIME_Timestamp execution_times[GNUNET_NZL (reserves_length)];
- const char *sender_account_details[GNUNET_NZL (reserves_length)];
- const char *exchange_account_names[GNUNET_NZL (reserves_length)];
- uint64_t wire_references[GNUNET_NZL (reserves_length)];
- uint64_t reserve_uuids[GNUNET_NZL (reserves_length)];
- bool transaction_duplicates[GNUNET_NZL (reserves_length)];
- bool conflicts[GNUNET_NZL (reserves_length)];
- struct GNUNET_TIME_Timestamp reserve_expiration
- = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
- struct GNUNET_TIME_Timestamp gc
- = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
- enum GNUNET_DB_QueryStatus qs;
- bool need_update;
-
- for (unsigned int i = 0; i<reserves_length; i++)
- {
- const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
-
- TALER_full_payto_hash (reserve->sender_account_details,
- &h_full_paytos[i]);
- TALER_full_payto_normalize_and_hash (reserve->sender_account_details,
- &h_normalized_paytos[i]);
- notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub);
- reserve_pubs[i] = *reserve->reserve_pub;
- balances[i] = *reserve->balance;
- execution_times[i] = reserve->execution_time;
- sender_account_details[i] = reserve->sender_account_details.full_payto;
- exchange_account_names[i] = reserve->exchange_account_name;
- wire_references[i] = reserve->wire_reference;
- }
-
- /* NOTE: kind-of pointless to explicitly start a transaction here... */
- if (GNUNET_OK !=
- TALER_EXCHANGEDB_preflight (pg))
- {
- GNUNET_break (0);
- qs = GNUNET_DB_STATUS_HARD_ERROR;
- goto finished;
- }
- if (GNUNET_OK !=
- TALER_TALER_EXCHANGEDB_start_read_committed (pg,
- "READ_COMMITED"))
- {
- GNUNET_break (0);
- qs = GNUNET_DB_STATUS_HARD_ERROR;
- goto finished;
- }
- PREPARE (pg,
- "reserves_insert_with_array",
- "SELECT"
- " transaction_duplicate"
- ",ruuid"
- " FROM exchange_do_array_reserves_insert"
- " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);");
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&gc),
- GNUNET_PQ_query_param_timestamp (&reserve_expiration),
- GNUNET_PQ_query_param_array_auto_from_type (reserves_length,
- reserve_pubs,
- pg->conn),
- GNUNET_PQ_query_param_array_uint64 (reserves_length,
- wire_references,
- pg->conn),
- TALER_PQ_query_param_array_amount (
- reserves_length,
- balances,
- pg->conn),
- GNUNET_PQ_query_param_array_ptrs_string (
- reserves_length,
- (const char **) exchange_account_names,
- pg->conn),
- GNUNET_PQ_query_param_array_timestamp (
- reserves_length,
- execution_times,
- pg->conn),
- GNUNET_PQ_query_param_array_auto_from_type (
- reserves_length,
- h_full_paytos,
- pg->conn),
- GNUNET_PQ_query_param_array_auto_from_type (
- reserves_length,
- h_normalized_paytos,
- pg->conn),
- GNUNET_PQ_query_param_array_ptrs_string (
- reserves_length,
- (const char **) sender_account_details,
- pg->conn),
- GNUNET_PQ_query_param_array_ptrs_string (
- reserves_length,
- (const char **) notify_s,
- pg->conn),
- GNUNET_PQ_query_param_end
- };
- struct Context ctx = {
- .reserve_uuids = reserve_uuids,
- .transaction_duplicates = transaction_duplicates,
- .conflicts = conflicts,
- .needs_update = false,
- .status = GNUNET_OK
- };
-
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "reserves_insert_with_array",
- params,
- &helper_cb,
- &ctx);
- GNUNET_PQ_cleanup_query_params_closures (params);
- if ( (qs < 0) ||
- (GNUNET_OK != ctx.status) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to insert into reserves (%d)\n",
- qs);
- goto finished;
- }
- need_update = ctx.needs_update;
- }
-
- {
- enum GNUNET_DB_QueryStatus cs;
-
- cs = TALER_EXCHANGEDB_commit (pg);
- if (cs < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to commit\n");
- qs = cs;
- goto finished;
- }
- }
-
- for (unsigned int i = 0; i<reserves_length; i++)
- {
- if (transaction_duplicates[i])
- dups++;
- results[i] = transaction_duplicates[i]
- ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
- : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
-
- if (! need_update)
- {
- qs = reserves_length;
- goto finished;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Reserve update needed for some reserves in the batch\n");
- PREPARE (pg,
- "reserves_update",
- "SELECT"
- " out_duplicate AS duplicate "
- "FROM exchange_do_batch_reserves_update"
- " ($1,$2,$3,$4,$5,$6,$7);");
-
- if (GNUNET_OK !=
- TALER_EXCHANGEDB_start (pg,
- "reserve-insert-continued"))
- {
- GNUNET_break (0);
- qs = GNUNET_DB_STATUS_HARD_ERROR;
- goto finished;
- }
-
- for (unsigned int i = 0; i<reserves_length; i++)
- {
- if (transaction_duplicates[i])
- continue;
- if (! conflicts[i])
- continue;
- {
- bool duplicate;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (&reserve_pubs[i]),
- GNUNET_PQ_query_param_timestamp (&reserve_expiration),
- GNUNET_PQ_query_param_uint64 (&wire_references[i]),
- TALER_PQ_query_param_amount (pg->conn,
- &balances[i]),
- GNUNET_PQ_query_param_string (exchange_account_names[i]),
- GNUNET_PQ_query_param_auto_from_type (&h_full_paytos[i]),
- GNUNET_PQ_query_param_string (notify_s[i]),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("duplicate",
- &duplicate),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qsi;
-
- qsi = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "reserves_update",
- params,
- rs);
- if (qsi < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to update reserves (%d)\n",
- qsi);
- results[i] = qsi;
- goto finished;
- }
- results[i] = duplicate
- ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
- : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- }
- }
- {
- enum GNUNET_DB_QueryStatus cs;
-
- cs = TALER_EXCHANGEDB_commit (pg);
- if (cs < 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to commit\n");
- qs = cs;
- goto finished;
- }
- }
-finished:
- for (unsigned int i = 0; i<reserves_length; i++)
- GNUNET_free (notify_s[i]);
- if (qs < 0)
- return qs;
- GNUNET_PQ_event_do_poll (pg->conn);
- if (0 != dups)
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "%u/%u duplicates among incoming transactions. Try increasing WIREWATCH_IDLE_SLEEP_INTERVAL in the [exchange] configuration section (if this happens a lot).\n",
- dups,
- reserves_length);
- return qs;
-}
diff --git a/src/exchangedb/pg_reserves_update.c b/src/exchangedb/pg_reserves_update.c
@@ -1,50 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_reserves_update.c
- * @brief Implementation of the reserves_update function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/reserves_update.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_reserves_update (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_EXCHANGEDB_Reserve *reserve
- )
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&reserve->expiry),
- GNUNET_PQ_query_param_timestamp (&reserve->gc),
- TALER_PQ_query_param_amount (pg->conn,
- &reserve->balance),
- GNUNET_PQ_query_param_auto_from_type (&reserve->pub),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "reserve_update",
- "UPDATE reserves"
- " SET"
- " expiration_date=$1"
- ",gc_date=$2"
- ",current_balance=$3"
- " WHERE reserve_pub=$4;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "reserve_update",
- params);
-}
diff --git a/src/exchangedb/pg_rollback.c b/src/exchangedb/pg_rollback.c
@@ -1,45 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_rollback.c
- * @brief Implementation of the rollback function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/exchange-database/rollback.h"
-#include "helper.h"
-
-
-void
-TALER_EXCHANGEDB_rollback (struct TALER_EXCHANGEDB_PostgresContext *pg)
-{
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("ROLLBACK"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- if (NULL == pg->transaction_name)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Skipping rollback, no transaction active\n");
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Rolling back transaction\n");
- GNUNET_break (GNUNET_OK ==
- GNUNET_PQ_exec_statements (pg->conn,
- es));
- pg->transaction_name = NULL;
-}
diff --git a/src/exchangedb/pg_select_account_merges_above_serial_id.c b/src/exchangedb/pg_select_account_merges_above_serial_id.c
@@ -1,188 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_account_merges_above_serial_id.c
- * @brief Implementation of the select_account_merges_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_account_merges_above_serial_id.h"
-#include "helper.h"
-
-
-/**
- * Closure for #account_merge_serial_helper_cb().
- */
-struct AccountMergeSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_AccountMergeCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct AccountMergeSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-account_merge_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct AccountMergeSerialContext *dsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_PurseContractPublicKeyP purse_pub;
- struct TALER_PrivateContractHashP h_contract_terms;
- struct GNUNET_TIME_Timestamp purse_expiration;
- struct TALER_Amount amount;
- uint32_t min_age;
- uint32_t flags32;
- enum TALER_WalletAccountMergeFlags flags;
- struct TALER_Amount purse_fee;
- struct GNUNET_TIME_Timestamp merge_timestamp;
- struct TALER_ReserveSignatureP reserve_sig;
- uint64_t rowid;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
- &purse_fee),
- GNUNET_PQ_result_spec_uint32 ("flags",
- &flags32),
- GNUNET_PQ_result_spec_uint32 ("age_limit",
- &min_age),
- GNUNET_PQ_result_spec_timestamp ("purse_expiration",
- &purse_expiration),
- GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
- &merge_timestamp),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- &h_contract_terms),
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &purse_pub),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &reserve_sig),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- GNUNET_PQ_result_spec_uint64 ("account_merge_request_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- flags = (enum TALER_WalletAccountMergeFlags) flags32;
- ret = dsc->cb (dsc->cb_cls,
- rowid,
- &reserve_pub,
- &purse_pub,
- &h_contract_terms,
- purse_expiration,
- &amount,
- min_age,
- flags,
- &purse_fee,
- merge_timestamp,
- &reserve_sig);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_account_merges_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_AccountMergeCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct AccountMergeSerialContext dsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "audit_get_account_merge_incr",
- "SELECT"
- " am.account_merge_request_serial_id"
- ",am.reserve_pub"
- ",am.purse_pub"
- ",pr.h_contract_terms"
- ",pr.purse_expiration"
- ",pr.amount_with_fee"
- ",pr.age_limit"
- ",pr.flags"
- ",pr.purse_fee"
- ",pm.merge_timestamp"
- ",am.reserve_sig"
- " FROM account_merges am"
- " JOIN purse_requests pr USING (purse_pub)"
- " JOIN purse_merges pm USING (purse_pub)"
- " WHERE ("
- " (account_merge_request_serial_id>=$1)"
- " )"
- " ORDER BY account_merge_request_serial_id ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "audit_get_account_merge_incr",
- params,
- &account_merge_serial_helper_cb,
- &dsc);
- if (GNUNET_OK != dsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.c b/src/exchangedb/pg_select_aggregation_amounts_for_kyc_check.c
@@ -1,154 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_aggregation_amounts_for_kyc_check.c
- * @brief Implementation of the select_aggregation_amounts_for_kyc_check function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_aggregation_amounts_for_kyc_check.h"
-#include "helper.h"
-
-
-/**
- * Closure for #get_kyc_amounts_cb().
- */
-struct KycAmountCheckContext
-{
- /**
- * Function to call per result.
- */
- TALER_KYCLOGIC_KycAmountCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Flag set to #GNUNET_OK as long as everything is fine.
- */
- enum GNUNET_GenericReturnValue status;
-
-};
-
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct KycAmountCheckContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-get_kyc_amounts_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct KycAmountCheckContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct GNUNET_TIME_Absolute date;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_absolute_time ("date",
- &date),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ret = ctx->cb (ctx->cb_cls,
- &amount,
- date);
- GNUNET_PQ_cleanup_result (rs);
- switch (ret)
- {
- case GNUNET_OK:
- continue;
- case GNUNET_NO:
- break;
- case GNUNET_SYSERR:
- ctx->status = GNUNET_SYSERR;
- break;
- }
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_aggregation_amounts_for_kyc_check (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- struct GNUNET_TIME_Absolute time_limit,
- TALER_KYCLOGIC_KycAmountCallback kac,
- void *kac_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_absolute_time (&time_limit),
- GNUNET_PQ_query_param_end
- };
- struct KycAmountCheckContext ctx = {
- .cb = kac,
- .cb_cls = kac_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_kyc_relevant_aggregation_events",
- "SELECT"
- " amount"
- ",execution_date AS date"
- " FROM wire_out"
- " WHERE wire_target_h_payto IN"
- " (SELECT wire_target_h_payto"
- " FROM wire_targets"
- " WHERE h_normalized_payto=$1"
- " )"
- " AND execution_date >= $2"
- " ORDER BY execution_date DESC");
-
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_kyc_relevant_aggregation_events",
- params,
- &get_kyc_amounts_cb,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_aggregation_transient.c b/src/exchangedb/pg_select_aggregation_transient.c
@@ -1,63 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_aggregation_transient.c
- * @brief Implementation of the select_aggregation_transient function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_aggregation_transient.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_aggregation_transient (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPaytoHashP *h_payto,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const char *exchange_account_section,
- struct TALER_WireTransferIdentifierRawP *wtid,
- struct TALER_Amount *total)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_auto_from_type (merchant_pub),
- GNUNET_PQ_query_param_string (exchange_account_section),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- total),
- GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
- wtid),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "select_aggregation_transient",
- "SELECT"
- " amount"
- " ,wtid_raw"
- " FROM aggregation_transient"
- " WHERE wire_target_h_payto=$1"
- " AND merchant_pub=$2"
- " AND exchange_account_section=$3;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "select_aggregation_transient",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_select_aggregations_above_serial.c b/src/exchangedb/pg_select_aggregations_above_serial.c
@@ -1,137 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2023, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_aggregations_above_serial.c
- * @brief Implementation of the select_aggregations_above_serial function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_aggregations_above_serial.h"
-#include "helper.h"
-
-/**
- * Closure for #aggregation_serial_helper_cb().
- */
-struct AggregationSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_AggregationCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct AggregationSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-aggregation_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct AggregationSerialContext *dsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t tracking_rowid;
- uint64_t batch_deposit_serial_id;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount",
- &amount),
- GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id",
- &tracking_rowid),
- GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id",
- &batch_deposit_serial_id),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- dsc->cb (dsc->cb_cls,
- &amount,
- tracking_rowid,
- batch_deposit_serial_id);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_aggregations_above_serial (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t min_tracking_serial_id,
- TALER_EXCHANGEDB_AggregationCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&min_tracking_serial_id),
- GNUNET_PQ_query_param_end
- };
- struct AggregationSerialContext asc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- /* Fetch aggregations with rowid '\geq' the given parameter */
- PREPARE (pg,
- "select_aggregations_above_serial",
- "SELECT"
- " aggregation_serial_id"
- ",batch_deposit_serial_id"
- ",total_amount"
- " FROM exchange_do_select_aggregations_above_serial($1);");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "select_aggregations_above_serial",
- params,
- &aggregation_serial_helper_cb,
- &asc);
- if (GNUNET_OK != asc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_all_kyc_attributes.c b/src/exchangedb/pg_select_all_kyc_attributes.c
@@ -1,168 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_all_kyc_attributes.c
- * @brief Implementation of the select_all_kyc_attributes function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_all_kyc_attributes.h"
-#include "helper.h"
-
-/**
- * Closure for #get_all_attributes_cb().
- */
-struct GetAttributesContext
-{
- /**
- * Function to call per result.
- */
- TALER_EXCHANGEDB_AllAttributesCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Flag set to #GNUNET_OK as long as everything is fine.
- */
- enum GNUNET_GenericReturnValue status;
-
-};
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct GetAttributesContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-get_attributes_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct GetAttributesContext *ctx = cls;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- uint64_t rowid;
- struct GNUNET_TIME_Timestamp collection_time;
- struct GNUNET_TIME_Timestamp expiration_time;
- struct TALER_NormalizedPaytoHashP h_payto;
- json_t *properties = NULL;
- size_t enc_attributes_size;
- void *enc_attributes;
- char *provider;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("provider_name",
- &provider),
- GNUNET_PQ_result_spec_uint64 ("kyc_attributes_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("jproperties",
- &properties),
- NULL),
- GNUNET_PQ_result_spec_timestamp ("collection_time",
- &collection_time),
- GNUNET_PQ_result_spec_timestamp ("expiration_time",
- &expiration_time),
- GNUNET_PQ_result_spec_auto_from_type ("h_payto",
- &h_payto),
- GNUNET_PQ_result_spec_variable_size ("encrypted_attributes",
- &enc_attributes,
- &enc_attributes_size),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ctx->cb (ctx->cb_cls,
- rowid,
- &h_payto,
- provider,
- collection_time,
- expiration_time,
- properties,
- enc_attributes_size,
- enc_attributes);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_all_kyc_attributes (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t min_row_id,
- TALER_EXCHANGEDB_AllAttributesCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&min_row_id),
- GNUNET_PQ_query_param_end
- };
- struct GetAttributesContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_all_kyc_attributes",
- "SELECT "
- " lp.provider_name"
- ",ka.h_payto"
- ",ka.kyc_attributes_serial_id"
- ",lo.jproperties::TEXT"
- ",ka.collection_time"
- ",ka.expiration_time"
- ",ka.encrypted_attributes"
- " FROM kyc_attributes ka"
- " JOIN legitimization_processes lp"
- " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)"
- " LEFT JOIN legitimization_outcomes lo"
- " ON (ka.h_payto = lo.h_payto)"
- /* **IF** we joined with 'lo', the lo must be active */
- " WHERE COALESCE(lo.is_active,TRUE)"
- " AND kyc_attributes_serial_id > $1"
- " ORDER BY kyc_attributes_serial_id ASC"
- );
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_all_kyc_attributes",
- params,
- &get_attributes_cb,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_all_purse_decisions_above_serial_id.c b/src/exchangedb/pg_select_all_purse_decisions_above_serial_id.c
@@ -1,142 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_all_purse_decisions_above_serial_id.c
- * @brief Implementation of the select_all_purse_decisions_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_all_purse_decisions_above_serial_id.h"
-#include "helper.h"
-
-
-/**
- * Closure for #all_purse_decision_serial_helper_cb().
- */
-struct AllPurseDecisionSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_AllPurseDecisionCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseRefundSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-all_purse_decision_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct AllPurseDecisionSerialContext *dsc = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_PurseContractPublicKeyP purse_pub;
- bool refunded;
- uint64_t rowid;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &purse_pub),
- GNUNET_PQ_result_spec_bool ("refunded",
- &refunded),
- GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- ret = dsc->cb (dsc->cb_cls,
- rowid,
- &purse_pub,
- refunded);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_all_purse_decisions_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_AllPurseDecisionCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct AllPurseDecisionSerialContext dsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "audit_select_all_purse_decisions_above_serial_id",
- "SELECT"
- " purse_pub"
- ",refunded"
- ",purse_decision_serial_id"
- " FROM purse_decision"
- " WHERE purse_decision_serial_id>=$1"
- " ORDER BY purse_decision_serial_id ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "audit_select_all_purse_decisions_above_serial_id",
- params,
- &all_purse_decision_serial_helper_cb,
- &dsc);
- if (GNUNET_OK != dsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_all_purse_deletions_above_serial_id.c b/src/exchangedb/pg_select_all_purse_deletions_above_serial_id.c
@@ -1,142 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_all_purse_deletions_above_serial_id.c
- * @brief Implementation of the select_all_purse_deletions_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_all_purse_deletions_above_serial_id.h"
-#include "helper.h"
-
-
-/**
- * Closure for #all_purse_deletion_serial_helper_cb().
- */
-struct AllPurseDeletionSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_AllPurseDeletionsCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseRefundSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-all_purse_deletion_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct AllPurseDeletionSerialContext *dsc = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_PurseContractPublicKeyP purse_pub;
- struct TALER_PurseContractSignatureP purse_sig;
- uint64_t rowid;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &purse_pub),
- GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
- &purse_sig),
- GNUNET_PQ_result_spec_uint64 ("purse_deletion_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- ret = dsc->cb (dsc->cb_cls,
- rowid,
- &purse_pub,
- &purse_sig);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_all_purse_deletions_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_AllPurseDeletionsCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct AllPurseDeletionSerialContext dsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "audit_select_all_purse_deletions_above_serial_id",
- "SELECT"
- " purse_pub"
- ",purse_sig"
- ",purse_deletion_serial_id"
- " FROM purse_deletion"
- " WHERE purse_deletion_serial_id>=$1"
- " ORDER BY purse_deletion_serial_id ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "audit_select_all_purse_deletions_above_serial_id",
- params,
- &all_purse_deletion_serial_helper_cb,
- &dsc);
- if (GNUNET_OK != dsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_aml_attributes.c b/src/exchangedb/pg_select_aml_attributes.c
@@ -1,189 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_aml_attributes.c
- * @brief Implementation of the select_aml_attributes function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_aml_attributes.h"
-#include "helper.h"
-
-
-/**
- * Closure for #handle_aml_result.
- */
-struct AmlAttributeResultContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_AmlAttributeCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on serious errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results. Helper function
- * for #TALER_EXCHANGEDB_select_aml_attributes().
- *
- * @param cls closure of type `struct AmlAttributeResultContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_aml_attributes (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct AmlAttributeResultContext *ctx = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct GNUNET_TIME_Timestamp collection_time;
- char *officer_name = NULL;
- bool by_aml_officer;
- size_t enc_attributes_size;
- void *enc_attributes;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("kyc_attributes_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_timestamp ("collection_time",
- &collection_time),
- GNUNET_PQ_result_spec_bool ("by_aml_officer",
- &by_aml_officer),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("decider_name",
- &officer_name),
- NULL),
- GNUNET_PQ_result_spec_variable_size ("encrypted_attributes",
- &enc_attributes,
- &enc_attributes_size),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
-
- ctx->cb (ctx->cb_cls,
- rowid,
- collection_time,
- by_aml_officer,
- officer_name,
- enc_attributes_size,
- enc_attributes);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_aml_attributes (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- uint64_t offset,
- int64_t limit,
- TALER_EXCHANGEDB_AmlAttributeCallback cb,
- void *cb_cls)
-{
- uint64_t ulimit = (limit > 0) ? limit : -limit;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_uint64 (&offset),
- GNUNET_PQ_query_param_uint64 (&ulimit),
- GNUNET_PQ_query_param_end
- };
- struct AmlAttributeResultContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
- const char *stmt = (limit > 0)
- ? "select_aml_attributes_inc"
- : "select_aml_attributes_dec";
-
- PREPARE (pg,
- "select_aml_attributes_inc",
- "SELECT"
- " ka.kyc_attributes_serial_id"
- ",ka.collection_time"
- ",ka.by_aml_officer"
- ",astaff.decider_name"
- ",ka.encrypted_attributes"
- " FROM kyc_attributes ka"
- " LEFT JOIN legitimization_processes lp"
- " ON (ka.by_aml_officer AND"
- " (ka.legitimization_serial = lp.legitimization_process_serial_id))"
- " LEFT JOIN aml_staff astaff"
- " ON (ka.by_aml_officer AND"
- " (DECODE(lp.provider_user_id, 'base64') = astaff.decider_pub))"
- " WHERE ka.h_payto=$1"
- " AND ka.kyc_attributes_serial_id > $2"
- " ORDER BY ka.kyc_attributes_serial_id ASC"
- " LIMIT $3");
- PREPARE (pg,
- "select_aml_attributes_dec",
- "SELECT"
- " ka.kyc_attributes_serial_id"
- ",ka.collection_time"
- ",ka.by_aml_officer"
- ",astaff.decider_name"
- ",ka.encrypted_attributes"
- " FROM kyc_attributes ka"
- " LEFT JOIN legitimization_processes lp"
- " ON (ka.by_aml_officer AND"
- " (ka.legitimization_serial = lp.legitimization_process_serial_id))"
- " LEFT JOIN aml_staff astaff"
- " ON (ka.by_aml_officer AND"
- " (DECODE(lp.provider_user_id, 'base64') = astaff.decider_pub))"
- " WHERE ka.h_payto=$1"
- " AND ka.kyc_attributes_serial_id < $2"
- " ORDER BY ka.kyc_attributes_serial_id DESC"
- " LIMIT $3");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
- params,
- &handle_aml_attributes,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_aml_decisions.c b/src/exchangedb/pg_select_aml_decisions.c
@@ -1,248 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_aml_decisions.c
- * @brief Implementation of the select_aml_decisions function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_aml_decisions.h"
-#include "helper.h"
-
-
-/**
- * Closure for #handle_aml_result.
- */
-struct AmlProcessResultContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_AmlDecisionCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on serious errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results. Helper function
- * for #TALER_EXCHANGEDB_select_aml_decisions().
- *
- * @param cls closure of type `struct AmlProcessResultContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_aml_result (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct AmlProcessResultContext *ctx = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_NormalizedPaytoHashP h_payto;
- uint64_t rowid;
- char *justification = NULL;
- struct GNUNET_TIME_Timestamp decision_time;
- struct GNUNET_TIME_Absolute expiration_time;
- json_t *jproperties = NULL;
- bool is_wallet;
- bool to_investigate;
- bool is_active;
- json_t *account_rules;
- struct TALER_FullPayto payto;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("outcome_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_auto_from_type ("h_payto",
- &h_payto),
- GNUNET_PQ_result_spec_bool ("is_wallet",
- &is_wallet),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("justification",
- &justification),
- NULL),
- GNUNET_PQ_result_spec_timestamp ("decision_time",
- &decision_time),
- GNUNET_PQ_result_spec_absolute_time ("expiration_time",
- &expiration_time),
- GNUNET_PQ_result_spec_allow_null (
- TALER_PQ_result_spec_json ("jproperties",
- &jproperties),
- NULL),
- TALER_PQ_result_spec_json ("jnew_rules",
- &account_rules),
- GNUNET_PQ_result_spec_bool ("to_investigate",
- &to_investigate),
- GNUNET_PQ_result_spec_bool ("is_active",
- &is_active),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto.full_payto),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- if (GNUNET_TIME_absolute_is_past (expiration_time))
- is_active = false;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Returning AML decisions for `%s' (%s)\n",
- TALER_B2S (&h_payto),
- is_wallet
- ? "wallet"
- : "account");
- ctx->cb (ctx->cb_cls,
- rowid,
- justification,
- &h_payto,
- decision_time,
- expiration_time,
- jproperties,
- to_investigate,
- is_active,
- is_wallet,
- payto,
- account_rules);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_aml_decisions (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- enum TALER_EXCHANGE_YesNoAll investigation_only,
- enum TALER_EXCHANGE_YesNoAll active_only,
- uint64_t offset,
- int64_t limit,
- TALER_EXCHANGEDB_AmlDecisionCallback cb,
- void *cb_cls)
-{
- uint64_t ulimit = (limit > 0) ? limit : -limit;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_bool (NULL == h_payto),
- NULL == h_payto
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
- investigation_only)),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
- investigation_only)),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
- active_only)),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
- active_only)),
- GNUNET_PQ_query_param_uint64 (&offset),
- GNUNET_PQ_query_param_uint64 (&ulimit),
- GNUNET_PQ_query_param_end
- };
- struct AmlProcessResultContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
- const char *stmt = (limit > 0)
- ? "select_aml_decisions_inc"
- : "select_aml_decisions_dec";
-
- PREPARE (pg,
- "select_aml_decisions_inc",
- "SELECT"
- " lo.outcome_serial_id"
- ",lo.h_payto"
- ",ah.justification"
- ",lo.decision_time"
- ",lo.expiration_time"
- ",lo.jproperties::TEXT"
- ",lo.to_investigate"
- ",lo.is_active"
- ",lo.jnew_rules::TEXT"
- ",kt.is_wallet"
- ",wt.payto_uri"
- " FROM legitimization_outcomes lo"
- " JOIN kyc_targets kt"
- " ON (lo.h_payto = kt.h_normalized_payto)"
- " JOIN wire_targets wt"
- " ON (lo.h_payto = wt.h_normalized_payto)"
- " LEFT JOIN aml_history ah"
- " USING (outcome_serial_id)"
- " WHERE (outcome_serial_id > $7)"
- " AND ($1 OR (lo.h_payto = $2))"
- " AND ($3 OR (lo.to_investigate = $4))"
- " AND ($5 OR (lo.is_active = $6))"
- " ORDER BY lo.outcome_serial_id ASC"
- " LIMIT $8");
- PREPARE (pg,
- "select_aml_decisions_dec",
- "SELECT"
- " lo.outcome_serial_id"
- ",lo.h_payto"
- ",ah.justification"
- ",lo.decision_time"
- ",lo.expiration_time"
- ",lo.jproperties::TEXT"
- ",lo.to_investigate"
- ",lo.is_active"
- ",lo.jnew_rules::TEXT"
- ",kt.is_wallet"
- ",wt.payto_uri"
- " FROM legitimization_outcomes lo"
- " JOIN kyc_targets kt"
- " ON (lo.h_payto = kt.h_normalized_payto)"
- " JOIN wire_targets wt"
- " ON (lo.h_payto = wt.h_normalized_payto)"
- " LEFT JOIN aml_history ah"
- " USING (outcome_serial_id)"
- " WHERE lo.outcome_serial_id < $7"
- " AND ($1 OR (lo.h_payto = $2))"
- " AND ($3 OR (lo.to_investigate = $4))"
- " AND ($5 OR (lo.is_active = $6))"
- " ORDER BY lo.outcome_serial_id DESC"
- " LIMIT $8");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
- params,
- &handle_aml_result,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_aml_measures.c b/src/exchangedb/pg_select_aml_measures.c
@@ -1,185 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_aml_measures.c
- * @brief Implementation of the select_aml_measures function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_aml_measures.h"
-#include "helper.h"
-
-
-/**
- * Closure for #handle_aml_result.
- */
-struct LegiMeasureResultContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_LegitimizationMeasureCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on serious errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results. Helper function
- * for #TALER_EXCHANGEDB_select_aml_measures().
- *
- * @param cls closure of type `struct LegiMeasureResultContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_aml_result (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct LegiMeasureResultContext *ctx = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_NormalizedPaytoHashP h_payto;
- uint64_t rowid;
- struct GNUNET_TIME_Absolute start_time;
- json_t *jmeasures;
- bool is_finished;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("legitimization_measure_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_auto_from_type ("h_normalized_payto",
- &h_payto),
- GNUNET_PQ_result_spec_absolute_time ("start_time",
- &start_time),
- TALER_PQ_result_spec_json ("jmeasures",
- &jmeasures),
- GNUNET_PQ_result_spec_bool ("is_finished",
- &is_finished),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ctx->cb (ctx->cb_cls,
- &h_payto,
- start_time,
- jmeasures,
- is_finished,
- rowid);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_aml_measures (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- enum TALER_EXCHANGE_YesNoAll active_only,
- uint64_t offset,
- int64_t limit,
- TALER_EXCHANGEDB_LegitimizationMeasureCallback cb,
- void *cb_cls)
-{
- uint64_t ulimit = (limit > 0) ? limit : -limit;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_bool (NULL == h_payto),
- NULL == h_payto
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
- active_only)),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_NO ==
- active_only)),
- GNUNET_PQ_query_param_uint64 (&offset),
- GNUNET_PQ_query_param_uint64 (&ulimit),
- GNUNET_PQ_query_param_end
- };
- struct LegiMeasureResultContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
- const char *stmt = (limit > 0)
- ? "select_aml_measures_inc"
- : "select_aml_measures_dec";
-
- PREPARE (pg,
- "select_aml_measures_inc",
- "SELECT"
- " lm.legitimization_measure_serial_id"
- ",kt.h_normalized_payto"
- ",lm.jmeasures::TEXT"
- ",lm.start_time"
- ",lm.is_finished"
- " FROM kyc_targets kt"
- " JOIN legitimization_measures lm"
- " USING (access_token)"
- " WHERE (legitimization_measure_serial_id > $5)"
- " AND ($1 OR (kt.h_normalized_payto = $2))"
- " AND ($3 OR (lm.is_finished = $4))"
- " ORDER BY lm.legitimization_measure_serial_id ASC"
- " LIMIT $6");
- PREPARE (pg,
- "select_aml_measures_dec",
- "SELECT"
- " lm.legitimization_measure_serial_id"
- ",kt.h_normalized_payto"
- ",lm.jmeasures::TEXT"
- ",lm.start_time"
- ",lm.is_finished"
- " FROM kyc_targets kt"
- " JOIN legitimization_measures lm"
- " USING (access_token)"
- " WHERE (legitimization_measure_serial_id < $5)"
- " AND ($1 OR (kt.h_normalized_payto = $2))"
- " AND ($3 OR (lm.is_finished = $4))"
- " ORDER BY lm.legitimization_measure_serial_id DESC"
- " LIMIT $6");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
- params,
- &handle_aml_result,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_aml_statistics.c b/src/exchangedb/pg_select_aml_statistics.c
@@ -1,142 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_aml_statistics.c
- * @brief Implementation of the select_aml_statistics function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_aml_statistics.h"
-#include "helper.h"
-
-
-/**
- * Closure for #get_statistics_cb().
- */
-struct GetStatisticsContext
-{
- /**
- * Function to call per result.
- */
- TALER_EXCHANGEDB_AmlStatisticsCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Flag set to #GNUNET_OK as long as everything is fine.
- */
- enum GNUNET_GenericReturnValue status;
-
-};
-
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct GetStatisticsContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-get_statistics_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct GetStatisticsContext *ctx = cls;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- uint64_t val;
- char *name;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("name",
- &name),
- GNUNET_PQ_result_spec_uint64 ("value",
- &val),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ctx->cb (ctx->cb_cls,
- name,
- val);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_aml_statistics (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- size_t num_names,
- const char *names[static num_names],
- struct GNUNET_TIME_Timestamp start_date,
- struct GNUNET_TIME_Timestamp end_date,
- TALER_EXCHANGEDB_AmlStatisticsCallback cb,
- void *cb_cls)
-{
- struct GetStatisticsContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_array_ptrs_string (num_names,
- names,
- pg->conn),
- GNUNET_PQ_query_param_timestamp (&start_date),
- GNUNET_PQ_query_param_timestamp (&end_date),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_aml_statistics",
- "SELECT "
- " event_type AS name"
- ",COUNT(*) AS value"
- " FROM kyc_events"
- " WHERE event_type = ANY ($1)"
- " AND event_timestamp >= $2"
- " AND event_timestamp < $3"
- " GROUP BY event_type;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "select_aml_statistics",
- params,
- &get_statistics_cb,
- &ctx);
- GNUNET_PQ_cleanup_query_params_closures (params);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_auditor_denom_sig.c b/src/exchangedb/pg_select_auditor_denom_sig.c
@@ -1,62 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_auditor_denom_sig.c
- * @brief Implementation of the select_auditor_denom_sig function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_auditor_denom_sig.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_auditor_denom_sig (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_DenominationHashP *h_denom_pub,
- const struct TALER_AuditorPublicKeyP *auditor_pub,
- struct TALER_AuditorSignatureP *auditor_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (auditor_pub),
- GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("auditor_sig",
- auditor_sig),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "select_auditor_denom_sig",
- "SELECT"
- " auditor_sig"
- " FROM auditor_denom_sigs"
- " WHERE auditor_uuid="
- " (SELECT auditor_uuid"
- " FROM auditors"
- " WHERE auditor_pub=$1)"
- " AND denominations_serial="
- " (SELECT denominations_serial"
- " FROM denominations"
- " WHERE denom_pub_hash=$2);");
-
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "select_auditor_denom_sig",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_select_batch_deposits_missing_wire.c b/src/exchangedb/pg_select_batch_deposits_missing_wire.c
@@ -1,140 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_batch_deposits_missing_wire.c
- * @brief Implementation of the select_batch_deposits_missing_wire function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_batch_deposits_missing_wire.h"
-#include "helper.h"
-
-/**
- * Closure for #missing_wire_cb().
- */
-struct MissingWireContext
-{
- /**
- * Function to call per result.
- */
- TALER_EXCHANGEDB_WireMissingCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on error.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct MissingWireContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-missing_wire_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct MissingWireContext *mwc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = mwc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t batch_deposit_serial_id;
- struct GNUNET_TIME_Timestamp deadline;
- struct TALER_FullPaytoHashP wire_target_h_payto;
- struct TALER_Amount total_amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id",
- &batch_deposit_serial_id),
- GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
- &wire_target_h_payto),
- GNUNET_PQ_result_spec_timestamp ("deadline",
- &deadline),
- TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount",
- &total_amount),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- mwc->status = GNUNET_SYSERR;
- return;
- }
- mwc->cb (mwc->cb_cls,
- batch_deposit_serial_id,
- &total_amount,
- &wire_target_h_payto,
- deadline);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_batch_deposits_missing_wire (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t min_batch_deposit_serial_id,
- TALER_EXCHANGEDB_WireMissingCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&min_batch_deposit_serial_id),
- GNUNET_PQ_query_param_end
- };
- struct MissingWireContext mwc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "deposits_get_deposits_missing_wire",
- "SELECT"
- " batch_deposit_serial_id"
- ",wire_target_h_payto"
- ",deadline"
- ",total_amount"
- " FROM exchange_do_select_deposits_missing_wire"
- " ($1);");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "deposits_get_deposits_missing_wire",
- params,
- &missing_wire_cb,
- &mwc);
- if (GNUNET_OK != mwc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_coin_deposits_above_serial_id.c b/src/exchangedb/pg_select_coin_deposits_above_serial_id.c
@@ -1,200 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_coin_deposits_above_serial_id.c
- * @brief Implementation of the select_coin_deposits_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_coin_deposits_above_serial_id.h"
-#include "helper.h"
-
-/**
- * Closure for #deposit_serial_helper_cb().
- */
-struct CoinDepositSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_DepositCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct CoinDepositSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-coin_deposit_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct CoinDepositSerialContext *dsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_Deposit deposit;
- struct GNUNET_TIME_Timestamp exchange_timestamp;
- struct TALER_DenominationPublicKey denom_pub;
- bool done;
- uint64_t rowid;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &deposit.amount_with_fee),
- GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
- &deposit.timestamp),
- GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
- &exchange_timestamp),
- GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
- &deposit.merchant_pub),
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &deposit.coin.coin_pub),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &deposit.coin.h_age_commitment),
- &deposit.coin.no_age_commitment),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("wallet_data_hash",
- &deposit.wallet_data_hash),
- &deposit.no_wallet_data_hash),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &deposit.csig),
- GNUNET_PQ_result_spec_timestamp ("refund_deadline",
- &deposit.refund_deadline),
- GNUNET_PQ_result_spec_timestamp ("wire_deadline",
- &deposit.wire_deadline),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- &deposit.h_contract_terms),
- GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
- &deposit.wire_salt),
- GNUNET_PQ_result_spec_string ("receiver_wire_account",
- &deposit.receiver_wire_account.full_payto),
- GNUNET_PQ_result_spec_bool ("done",
- &done),
- GNUNET_PQ_result_spec_uint64 ("coin_deposit_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- memset (&deposit,
- 0,
- sizeof (deposit));
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- ret = dsc->cb (dsc->cb_cls,
- rowid,
- exchange_timestamp,
- &deposit,
- &denom_pub,
- done);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_coin_deposits_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_DepositCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct CoinDepositSerialContext dsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- /* Fetch deposits with rowid '\geq' the given parameter */
- PREPARE (pg,
- "audit_get_coin_deposits_incr",
- "SELECT"
- " cdep.amount_with_fee"
- ",bdep.wallet_timestamp"
- ",bdep.exchange_timestamp"
- ",bdep.merchant_pub"
- ",bdep.wallet_data_hash"
- ",denom.denom_pub"
- ",kc.coin_pub"
- ",kc.age_commitment_hash"
- ",cdep.coin_sig"
- ",bdep.refund_deadline"
- ",bdep.wire_deadline"
- ",bdep.h_contract_terms"
- ",bdep.wire_salt"
- ",wt.payto_uri AS receiver_wire_account"
- ",bdep.done"
- ",cdep.coin_deposit_serial_id"
- " FROM coin_deposits cdep"
- " JOIN batch_deposits bdep"
- " USING (batch_deposit_serial_id)"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " JOIN known_coins kc"
- " USING (coin_pub)"
- " JOIN denominations denom"
- " USING (denominations_serial)"
- " WHERE (coin_deposit_serial_id>=$1)"
- " ORDER BY coin_deposit_serial_id ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "audit_get_coin_deposits_incr",
- params,
- &coin_deposit_serial_helper_cb,
- &dsc);
- if (GNUNET_OK != dsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_contract.c b/src/exchangedb/pg_select_contract.c
@@ -1,65 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_contract.c
- * @brief Implementation of the select_contract function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_contract.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_contract (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ContractDiffiePublicP *
- pub_ckey,
- struct TALER_PurseContractPublicKeyP *
- purse_pub,
- struct TALER_PurseContractSignatureP *
- econtract_sig,
- size_t *econtract_size,
- void **econtract)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (pub_ckey),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- purse_pub),
- GNUNET_PQ_result_spec_auto_from_type ("contract_sig",
- econtract_sig),
- GNUNET_PQ_result_spec_variable_size ("e_contract",
- econtract,
- econtract_size),
- GNUNET_PQ_result_spec_end
- };
-
- /* Used in #postgres_select_contract */
- PREPARE (pg,
- "select_contract",
- "SELECT "
- " purse_pub"
- ",e_contract"
- ",contract_sig"
- " FROM contracts"
- " WHERE pub_ckey=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "select_contract",
- params,
- rs);
-
-}
diff --git a/src/exchangedb/pg_select_contract_by_purse.c b/src/exchangedb/pg_select_contract_by_purse.c
@@ -1,59 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_contract_by_purse.c
- * @brief Implementation of the select_contract_by_purse function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_contract_by_purse.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_select_contract_by_purse (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- struct TALER_EncryptedContract *econtract)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("pub_ckey",
- &econtract->contract_pub),
- GNUNET_PQ_result_spec_auto_from_type ("contract_sig",
- &econtract->econtract_sig),
- GNUNET_PQ_result_spec_variable_size ("e_contract",
- &econtract->econtract,
- &econtract->econtract_size),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "select_contract_by_purse",
- "SELECT "
- " pub_ckey"
- ",e_contract"
- ",contract_sig"
- " FROM contracts"
- " WHERE purse_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "select_contract_by_purse",
- params,
- rs);
-
-}
diff --git a/src/exchangedb/pg_select_deposit_amounts_for_kyc_check.c b/src/exchangedb/pg_select_deposit_amounts_for_kyc_check.c
@@ -1,153 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_deposit_amounts_for_kyc_check.c
- * @brief Implementation of the select_deposit_amounts_for_kyc_check function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_deposit_amounts_for_kyc_check.h"
-#include "helper.h"
-
-/**
- * Closure for #get_kyc_amounts_cb().
- */
-struct KycAmountCheckContext
-{
- /**
- * Function to call per result.
- */
- TALER_KYCLOGIC_KycAmountCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Flag set to #GNUNET_OK as long as everything is fine.
- */
- enum GNUNET_GenericReturnValue status;
-
-};
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct KycAmountCheckContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-get_kyc_amounts_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct KycAmountCheckContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct GNUNET_TIME_Absolute date;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_absolute_time ("date",
- &date),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ret = ctx->cb (ctx->cb_cls,
- &amount,
- date);
- GNUNET_PQ_cleanup_result (rs);
- switch (ret)
- {
- case GNUNET_OK:
- continue;
- case GNUNET_NO:
- break;
- case GNUNET_SYSERR:
- ctx->status = GNUNET_SYSERR;
- break;
- }
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_deposit_amounts_for_kyc_check (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- struct GNUNET_TIME_Absolute time_limit,
- TALER_KYCLOGIC_KycAmountCallback kac,
- void *kac_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_absolute_time (&time_limit),
- GNUNET_PQ_query_param_end
- };
- struct KycAmountCheckContext ctx = {
- .cb = kac,
- .cb_cls = kac_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_kyc_relevant_deposit_events",
- "SELECT"
- " cd.amount_with_fee AS amount"
- ",bd.exchange_timestamp AS date"
- " FROM batch_deposits bd"
- " JOIN coin_deposits cd"
- " USING (batch_deposit_serial_id)"
- " WHERE wire_target_h_payto IN ("
- " SELECT wire_target_h_payto"
- " FROM wire_targets"
- " WHERE h_normalized_payto=$1"
- " )"
- " AND bd.exchange_timestamp >= $2"
- " ORDER BY bd.exchange_timestamp DESC");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_kyc_relevant_deposit_events",
- params,
- &get_kyc_amounts_cb,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_exchange_credit_transfers.c b/src/exchangedb/pg_select_exchange_credit_transfers.c
@@ -1,180 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_exchange_credit_transfers.c
- * @brief Implementation of the select_exchange_credit_transfers function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_exchange_credit_transfers.h"
-#include "helper.h"
-
-/**
- * Closure for #handle_aml_result.
- */
-struct SelectTransferContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_AmlTransferCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on serious errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results. Helper function
- * for #TALER_EXCHANGEDB_select_exchange_debit_transfers().
- *
- * @param cls closure of type `struct SelectTransferContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_transfer_result (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct SelectTransferContext *stc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- char *payto_uri;
- uint64_t rowid;
- struct GNUNET_TIME_Absolute execution_time;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial_id",
- &rowid),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri),
- GNUNET_PQ_result_spec_absolute_time ("execution_time",
- &execution_time),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- stc->status = GNUNET_SYSERR;
- return;
- }
- stc->cb (stc->cb_cls,
- rowid,
- payto_uri,
- execution_time,
- &amount);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_exchange_credit_transfers (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_Amount *threshold,
- uint64_t offset,
- int64_t limit,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- TALER_EXCHANGEDB_AmlTransferCallback cb,
- void *cb_cls)
-{
- struct SelectTransferContext stc = {
- .pg = pg,
- .cb = cb,
- .cb_cls = cb_cls,
- .status = GNUNET_OK
- };
- uint64_t ulimit = (limit > 0) ? limit : -limit;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&offset),
- GNUNET_PQ_query_param_uint64 (&ulimit),
- TALER_PQ_query_param_amount (pg->conn,
- threshold),
- NULL != h_payto
- ? GNUNET_PQ_query_param_auto_from_type (h_payto)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_exchange_credit_transfers_inc",
- "SELECT"
- " ri.reserve_in_serial_id AS serial_id"
- ",wt.payto_uri"
- ",ri.execution_date AS execution_time"
- ",ri.credit AS amount"
- " FROM reserves_in ri"
- " LEFT JOIN wire_targets wt"
- " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)"
- " WHERE (ri.reserve_in_serial_id > $1)"
- " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
- " AND ( ( (ri.credit).val > ($3::taler_amount).val)"
- " OR ( ( (ri.credit).val >= ($3::taler_amount).val)"
- " AND ( (ri.credit).frac >= ($3::taler_amount).frac) ) )"
- " ORDER BY ri.reserve_in_serial_id ASC"
- " LIMIT $2");
- PREPARE (pg,
- "select_exchange_credit_transfers_dec",
- "SELECT"
- " ri.reserve_in_serial_id AS serial_id"
- ",wt.payto_uri"
- ",ri.execution_date AS execution_time"
- ",ri.credit AS amount"
- " FROM reserves_in ri"
- " LEFT JOIN wire_targets wt"
- " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)"
- " WHERE (ri.reserve_in_serial_id < $1)"
- " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
- " AND ( ( (ri.credit).val > ($3::taler_amount).val)"
- " OR ( ( (ri.credit).val >= ($3::taler_amount).val)"
- " AND ( (ri.credit).frac >= ($3::taler_amount).frac) ) )"
- " ORDER BY ri.reserve_in_serial_id DESC"
- " LIMIT $2");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- (limit > 0)
- ? "select_exchange_credit_transfers_inc"
- : "select_exchange_credit_transfers_dec",
- params,
- &handle_transfer_result,
- &stc);
- if (GNUNET_OK != stc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_exchange_debit_transfers.c b/src/exchangedb/pg_select_exchange_debit_transfers.c
@@ -1,181 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_exchange_debit_transfers.c
- * @brief Implementation of the select_exchange_debit_transfers function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_exchange_debit_transfers.h"
-#include "helper.h"
-
-
-/**
- * Closure for #handle_aml_result.
- */
-struct SelectTransferContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_AmlTransferCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on serious errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results. Helper function
- * for #TALER_EXCHANGEDB_select_exchange_debit_transfers().
- *
- * @param cls closure of type `struct SelectTransferContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_transfer_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct SelectTransferContext *stc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- char *payto_uri;
- uint64_t rowid;
- struct GNUNET_TIME_Absolute execution_time;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial_id",
- &rowid),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri),
- GNUNET_PQ_result_spec_absolute_time ("execution_time",
- &execution_time),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- stc->status = GNUNET_SYSERR;
- return;
- }
- stc->cb (stc->cb_cls,
- rowid,
- payto_uri,
- execution_time,
- &amount);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_exchange_debit_transfers (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_Amount *threshold,
- uint64_t offset,
- int64_t limit,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- TALER_EXCHANGEDB_AmlTransferCallback cb,
- void *cb_cls)
-{
- struct SelectTransferContext stc = {
- .pg = pg,
- .cb = cb,
- .cb_cls = cb_cls,
- .status = GNUNET_OK
- };
- uint64_t ulimit = (limit > 0) ? limit : -limit;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&offset),
- GNUNET_PQ_query_param_uint64 (&ulimit),
- TALER_PQ_query_param_amount (pg->conn,
- threshold),
- NULL != h_payto
- ? GNUNET_PQ_query_param_auto_from_type (h_payto)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_exchange_debit_transfers_inc",
- "SELECT"
- " wo.wireout_uuid AS serial_id"
- ",wt.payto_uri"
- ",wo.execution_date AS execution_time"
- ",wo.amount"
- " FROM wire_out wo"
- " LEFT JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " WHERE (wo.wireout_uuid > $1)"
- " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
- " AND ( ( (wo.amount).val > ($3::taler_amount).val)"
- " OR ( ( (wo.amount).val >= ($3::taler_amount).val)"
- " AND ( (wo.amount).frac >= ($3::taler_amount).frac) ) )"
- " ORDER BY wo.wireout_uuid ASC"
- " LIMIT $2");
- PREPARE (pg,
- "select_exchange_debit_transfers_dec",
- "SELECT"
- " wo.wireout_uuid AS serial_id"
- ",wt.payto_uri"
- ",wo.execution_date AS execution_time"
- ",wo.amount"
- " FROM wire_out wo"
- " LEFT JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " WHERE (wo.wireout_uuid < $1)"
- " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
- " AND ( ( (wo.amount).val > ($3::taler_amount).val)"
- " OR ( ( (wo.amount).val >= ($3::taler_amount).val)"
- " AND ( (wo.amount).frac >= ($3::taler_amount).frac) ) )"
- " ORDER BY wo.wireout_uuid DESC"
- " LIMIT $2");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- (limit > 0)
- ? "select_exchange_debit_transfers_inc"
- : "select_exchange_debit_transfers_dec",
- params,
- &handle_transfer_cb,
- &stc);
- if (GNUNET_OK != stc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_exchange_kycauth_transfers.c b/src/exchangedb/pg_select_exchange_kycauth_transfers.c
@@ -1,180 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_exchange_kycauth_transfers.c
- * @brief Implementation of the select_exchange_kycauth_transfers function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_exchange_kycauth_transfers.h"
-#include "helper.h"
-
-/**
- * Closure for #handle_aml_result.
- */
-struct SelectTransferContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_AmlTransferCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on serious errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results. Helper function
- * for #TALER_EXCHANGEDB_select_exchange_debit_transfers().
- *
- * @param cls closure of type `struct SelectTransferContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_transfer_result (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct SelectTransferContext *stc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- char *payto_uri;
- uint64_t rowid;
- struct GNUNET_TIME_Absolute execution_time;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("serial_id",
- &rowid),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri),
- GNUNET_PQ_result_spec_absolute_time ("execution_time",
- &execution_time),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- stc->status = GNUNET_SYSERR;
- return;
- }
- stc->cb (stc->cb_cls,
- rowid,
- payto_uri,
- execution_time,
- &amount);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_exchange_kycauth_transfers (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_Amount *threshold,
- uint64_t offset,
- int64_t limit,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- TALER_EXCHANGEDB_AmlTransferCallback cb,
- void *cb_cls)
-{
- struct SelectTransferContext stc = {
- .pg = pg,
- .cb = cb,
- .cb_cls = cb_cls,
- .status = GNUNET_OK
- };
- uint64_t ulimit = (limit > 0) ? limit : -limit;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&offset),
- GNUNET_PQ_query_param_uint64 (&ulimit),
- TALER_PQ_query_param_amount (pg->conn,
- threshold),
- NULL != h_payto
- ? GNUNET_PQ_query_param_auto_from_type (h_payto)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_exchange_kycauth_transfers_inc",
- "SELECT"
- " ki.kycauth_in_serial_id AS serial_id"
- ",wt.payto_uri"
- ",ki.execution_date AS execution_time"
- ",ki.credit AS amount"
- " FROM kycauths_in ki"
- " LEFT JOIN wire_targets wt"
- " ON (ki.wire_source_h_payto = wt.wire_target_h_payto)"
- " WHERE (ki.kycauth_in_serial_id > $1)"
- " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
- " AND ( ( (ki.credit).val > ($3::taler_amount).val)"
- " OR ( ( (ki.credit).val >= ($3::taler_amount).val)"
- " AND ( (ki.credit).frac >= ($3::taler_amount).frac) ) )"
- " ORDER BY ki.kycauth_in_serial_id ASC"
- " LIMIT $2");
- PREPARE (pg,
- "select_exchange_kycauth_transfers_dec",
- "SELECT"
- " ki.kycauth_in_serial_id AS serial_id"
- ",wt.payto_uri"
- ",ki.execution_date AS execution_time"
- ",ki.credit AS amount"
- " FROM kycauths_in ki"
- " LEFT JOIN wire_targets wt"
- " ON (ki.wire_source_h_payto = wt.wire_target_h_payto)"
- " WHERE (ki.kycauth_in_serial_id < $1)"
- " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
- " AND ( ( (ki.credit).val > ($3::taler_amount).val)"
- " OR ( ( (ki.credit).val >= ($3::taler_amount).val)"
- " AND ( (ki.credit).frac >= ($3::taler_amount).frac) ) )"
- " ORDER BY ki.kycauth_in_serial_id DESC"
- " LIMIT $2");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- (limit > 0)
- ? "select_exchange_kycauth_transfers_inc"
- : "select_exchange_kycauth_transfers_dec",
- params,
- &handle_transfer_result,
- &stc);
- if (GNUNET_OK != stc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_kyc_accounts.c b/src/exchangedb/pg_select_kyc_accounts.c
@@ -1,235 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_kyc_accounts.c
- * @brief Implementation of the select_kyc_accounts function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_kyc_accounts.h"
-#include "helper.h"
-
-
-/**
- * Closure for #handle_aml_result.
- */
-struct KycAccountResultContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_AmlAccountListCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on serious errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results. Helper function
- * for #TALER_EXCHANGEDB_select_kyc_accounts().
- *
- * @param cls closure of type `struct KycAccountResultContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_kyc_account_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct KycAccountResultContext *ctx = cls;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct TALER_NormalizedPaytoHashP h_payto;
- char *comments = NULL;
- struct GNUNET_TIME_Timestamp open_time
- = GNUNET_TIME_UNIT_FOREVER_TS;
- struct GNUNET_TIME_Timestamp close_time
- = GNUNET_TIME_UNIT_FOREVER_TS;
- bool to_investigate;
- bool high_risk;
- struct TALER_FullPayto payto;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("kyc_target_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_auto_from_type ("h_payto",
- &h_payto),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("comments",
- &comments),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_timestamp ("open_time",
- &open_time),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_timestamp ("close_time",
- &close_time),
- NULL),
- GNUNET_PQ_result_spec_bool ("to_investigate",
- &to_investigate),
- GNUNET_PQ_result_spec_bool ("high_risk",
- &high_risk),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto.full_payto),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ctx->cb (ctx->cb_cls,
- rowid,
- &h_payto,
- open_time,
- close_time,
- comments,
- high_risk,
- to_investigate,
- payto);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_kyc_accounts (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- enum TALER_EXCHANGE_YesNoAll investigation_only,
- enum TALER_EXCHANGE_YesNoAll open_only,
- enum TALER_EXCHANGE_YesNoAll high_risk_only,
- uint64_t offset,
- int64_t limit,
- TALER_EXCHANGEDB_AmlAccountListCallback cb,
- void *cb_cls)
-{
- uint64_t ulimit = (limit > 0) ? limit : -limit;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&offset),
- GNUNET_PQ_query_param_uint64 (&ulimit),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
- investigation_only)),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
- investigation_only)),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
- open_only)),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
- open_only)),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
- high_risk_only)),
- GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
- high_risk_only)),
- GNUNET_PQ_query_param_end
- };
- struct KycAccountResultContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
- const char *stmt = (limit > 0)
- ? "select_kyc_accounts_inc"
- : "select_kyc_accounts_dec";
-
- PREPARE (pg,
- "select_kyc_accounts_inc",
- "SELECT"
- " kt.kyc_target_serial_id"
- ",kt.h_normalized_payto AS h_payto"
- ",kt.open_time"
- ",kt.close_time"
- ",lo.jproperties ->> 'FILE_NOTE' AS comments"
- ",lo.jproperties ->> 'open_date' AS open_time"
- ",COALESCE(lo.to_investigate,FALSE) AS to_investigate"
- ",COALESCE((lo.jproperties ->> 'HIGH_RISK_CUSTOMER')::bool,FALSE) AS high_risk"
- ",wt.payto_uri"
- " FROM kyc_targets kt"
- " JOIN wire_targets wt"
- " ON (wt.h_normalized_payto = kt.h_normalized_payto)"
- " LEFT JOIN legitimization_outcomes lo"
- " ON (lo.h_payto = kt.h_normalized_payto)"
- " WHERE (kyc_target_serial_id > $1)"
- // select most recent outcomes only
- " AND COALESCE (lo.is_active, TRUE)"
- " AND ($3 OR (COALESCE(lo.to_investigate,FALSE) = $4))"
- // Account is open if we had an AML outcome
- " AND ($5 OR ((lo.outcome_serial_id IS NULL) = $6))"
- " AND ($7 OR ((COALESCE((lo.jproperties ->>'high_risk')::bool,FALSE) = $8)))"
- " ORDER BY kt.kyc_target_serial_id ASC"
- " LIMIT $2");
- PREPARE (pg,
- "select_kyc_accounts_dec",
- "SELECT"
- " kt.kyc_target_serial_id"
- ",kt.h_normalized_payto AS h_payto"
- ",kt.open_time"
- ",kt.close_time"
- ",lo.jproperties ->> 'FILE_NOTE' AS comments"
- ",lo.jproperties ->> 'open_date' AS open_time"
- ",COALESCE(lo.to_investigate,FALSE) AS to_investigate"
- ",COALESCE((lo.jproperties ->> 'HIGH_RISK_CUSTOMER')::bool,FALSE) AS high_risk"
- ",wt.payto_uri"
- " FROM kyc_targets kt"
- " LEFT JOIN legitimization_outcomes lo"
- " ON (lo.h_payto = kt.h_normalized_payto)"
- " LEFT JOIN LATERAL ("
- " SELECT payto_uri"
- " FROM wire_targets"
- " WHERE h_normalized_payto = kt.h_normalized_payto"
- " ORDER BY wire_target_serial_id DESC"
- " LIMIT 1"
- " ) wt ON true"
- " WHERE (kyc_target_serial_id < $1)"
- // select most recent outcomes only
- " AND COALESCE (lo.is_active, TRUE)"
- " AND ($3 OR (COALESCE(lo.to_investigate,FALSE) = $4))"
- // Account is open if we had an AML outcome
- " AND ($5 OR ((lo.outcome_serial_id IS NULL) = $6))"
- " AND ($7 OR ((COALESCE((lo.jproperties ->>'high_risk')::bool,FALSE) = $8)))"
- " ORDER BY kt.kyc_target_serial_id DESC"
- " LIMIT $2");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- stmt,
- params,
- &handle_kyc_account_cb,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_kyc_attributes.c b/src/exchangedb/pg_select_kyc_attributes.c
@@ -1,154 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_kyc_attributes.c
- * @brief Implementation of the select_kyc_attributes function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_kyc_attributes.h"
-#include "helper.h"
-
-
-/**
- * Closure for #get_attributes_cb().
- */
-struct GetAttributesContext
-{
- /**
- * Function to call per result.
- */
- TALER_EXCHANGEDB_AttributeCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Key of our query.
- */
- const struct TALER_NormalizedPaytoHashP *h_payto;
-
- /**
- * Flag set to #GNUNET_OK as long as everything is fine.
- */
- enum GNUNET_GenericReturnValue status;
-
-};
-
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct GetAttributesContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-get_attributes_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct GetAttributesContext *ctx = cls;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct GNUNET_TIME_Timestamp collection_time;
- struct GNUNET_TIME_Timestamp expiration_time;
- size_t enc_attributes_size;
- void *enc_attributes;
- char *provider;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_string ("provider_name",
- &provider),
- GNUNET_PQ_result_spec_timestamp ("collection_time",
- &collection_time),
- GNUNET_PQ_result_spec_timestamp ("expiration_time",
- &expiration_time),
- GNUNET_PQ_result_spec_variable_size ("encrypted_attributes",
- &enc_attributes,
- &enc_attributes_size),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ctx->cb (ctx->cb_cls,
- ctx->h_payto,
- provider,
- collection_time,
- expiration_time,
- enc_attributes_size,
- enc_attributes);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_kyc_attributes (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- TALER_EXCHANGEDB_AttributeCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_end
- };
- struct GetAttributesContext ctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .h_payto = h_payto,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_kyc_attributes",
- "SELECT "
- " lp.provider_name"
- ",ka.collection_time"
- ",ka.expiration_time"
- ",ka.encrypted_attributes"
- " FROM kyc_attributes ka"
- " JOIN legitimization_processes lp"
- " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)"
- " WHERE ka.h_payto=$1");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_kyc_attributes",
- params,
- &get_attributes_cb,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_merge_amounts_for_kyc_check.c b/src/exchangedb/pg_select_merge_amounts_for_kyc_check.c
@@ -1,152 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_merge_amounts_for_kyc_check.c
- * @brief Implementation of the select_merge_amounts_for_kyc_check function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_merge_amounts_for_kyc_check.h"
-#include "helper.h"
-
-
-/**
- * Closure for #get_kyc_amounts_cb().
- */
-struct KycAmountCheckContext
-{
- /**
- * Function to call per result.
- */
- TALER_KYCLOGIC_KycAmountCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Flag set to #GNUNET_OK as long as everything is fine.
- */
- enum GNUNET_GenericReturnValue status;
-
-};
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct KycAmountCheckContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-get_kyc_amounts_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct KycAmountCheckContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct GNUNET_TIME_Absolute date;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_absolute_time ("date",
- &date),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ret = ctx->cb (ctx->cb_cls,
- &amount,
- date);
- GNUNET_PQ_cleanup_result (rs);
- switch (ret)
- {
- case GNUNET_OK:
- continue;
- case GNUNET_NO:
- break;
- case GNUNET_SYSERR:
- ctx->status = GNUNET_SYSERR;
- break;
- }
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_merge_amounts_for_kyc_check (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- struct GNUNET_TIME_Absolute time_limit,
- TALER_KYCLOGIC_KycAmountCallback kac,
- void *kac_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_absolute_time (&time_limit),
- GNUNET_PQ_query_param_end
- };
- struct KycAmountCheckContext ctx = {
- .cb = kac,
- .cb_cls = kac_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_kyc_relevant_merge_events",
- "SELECT"
- " amount_with_fee AS amount"
- ",merge_timestamp AS date"
- " FROM account_merges"
- " JOIN purse_merges USING (purse_pub)"
- " JOIN purse_requests USING (purse_pub)"
- " JOIN purse_decision USING (purse_pub)"
- " WHERE wallet_h_payto=$1"
- " AND merge_timestamp >= $2"
- " AND NOT refunded"
- " ORDER BY merge_timestamp DESC");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_kyc_relevant_merge_events",
- params,
- &get_kyc_amounts_cb,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_purse.c b/src/exchangedb/pg_select_purse.c
@@ -1,90 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_purse.c
- * @brief Implementation of the select_purse function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_purse.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_purse (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- struct GNUNET_TIME_Timestamp *purse_creation,
- struct GNUNET_TIME_Timestamp *purse_expiration,
- struct TALER_Amount *amount,
- struct TALER_Amount *deposited,
- struct TALER_PrivateContractHashP *h_contract_terms,
- struct GNUNET_TIME_Timestamp *merge_timestamp,
- bool *purse_deleted,
- bool *purse_refunded)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_timestamp ("purse_expiration",
- purse_expiration),
- GNUNET_PQ_result_spec_timestamp ("purse_creation",
- purse_creation),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
- deposited),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- h_contract_terms),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
- merge_timestamp),
- NULL),
- GNUNET_PQ_result_spec_bool ("purse_deleted",
- purse_deleted),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_bool ("purse_refunded",
- purse_refunded),
- NULL),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "select_purse",
- "SELECT "
- " pr.merge_pub"
- ",pr.purse_creation"
- ",pr.purse_expiration"
- ",pr.h_contract_terms"
- ",pr.amount_with_fee"
- ",pr.balance"
- ",pm.merge_timestamp"
- ",pd.purse_sig IS NOT NULL AS purse_deleted"
- ",pc.refunded AS purse_refunded"
- " FROM purse_requests pr"
- " LEFT JOIN purse_merges pm ON (pm.purse_pub = pr.purse_pub)"
- " LEFT JOIN purse_decision pc ON (pc.purse_pub = pr.purse_pub)"
- " LEFT JOIN purse_deletion pd ON (pd.purse_pub = pr.purse_pub)"
- " WHERE pr.purse_pub=$1;");
- *merge_timestamp = GNUNET_TIME_UNIT_FOREVER_TS;
- *purse_refunded = false;
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "select_purse",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_select_purse_by_merge_pub.c b/src/exchangedb/pg_select_purse_by_merge_pub.c
@@ -1,75 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_purse_by_merge_pub.c
- * @brief Implementation of the select_purse_by_merge_pub function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_purse_by_merge_pub.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_select_purse_by_merge_pub (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseMergePublicKeyP *merge_pub,
- struct TALER_PurseContractPublicKeyP *purse_pub,
- struct GNUNET_TIME_Timestamp *purse_expiration,
- struct TALER_PrivateContractHashP *h_contract_terms,
- uint32_t *age_limit,
- struct TALER_Amount *target_amount,
- struct TALER_Amount *balance,
- struct TALER_PurseContractSignatureP *purse_sig)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (merge_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- purse_pub),
- GNUNET_PQ_result_spec_timestamp ("purse_expiration",
- purse_expiration),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- h_contract_terms),
- GNUNET_PQ_result_spec_uint32 ("age_limit",
- age_limit),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- target_amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
- balance),
- GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
- purse_sig),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "select_purse_by_merge_pub",
- "SELECT "
- " purse_pub"
- ",purse_expiration"
- ",h_contract_terms"
- ",age_limit"
- ",amount_with_fee"
- ",balance"
- ",purse_sig"
- " FROM purse_requests"
- " WHERE merge_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "select_purse_by_merge_pub",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_select_purse_decisions_above_serial_id.c b/src/exchangedb/pg_select_purse_decisions_above_serial_id.c
@@ -1,158 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_purse_decisions_above_serial_id.c
- * @brief Implementation of the select_purse_decisions_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_purse_decisions_above_serial_id.h"
-#include "helper.h"
-
-/**
- * Closure for #purse_decision_serial_helper_cb().
- */
-struct PurseDecisionSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_PurseDecisionCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseRefundSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-purse_decision_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct PurseDecisionSerialContext *dsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_PurseContractPublicKeyP purse_pub;
- struct TALER_ReservePublicKeyP reserve_pub;
- bool no_reserve = true;
- uint64_t rowid;
- struct TALER_Amount val;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &purse_pub),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- &no_reserve),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &val),
- GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- ret = dsc->cb (dsc->cb_cls,
- rowid,
- &purse_pub,
- no_reserve ? NULL : &reserve_pub,
- &val);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_select_purse_decisions_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- bool refunded,
- TALER_EXCHANGEDB_PurseDecisionCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_bool (refunded),
- GNUNET_PQ_query_param_end
- };
- struct PurseDecisionSerialContext dsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "audit_get_purse_decisions_incr",
- "SELECT"
- " pd.purse_pub"
- ",pm.reserve_pub"
- ",pd.purse_decision_serial_id"
- ",pr.amount_with_fee"
- " FROM purse_decision pd"
- " JOIN purse_requests pr ON (pd.purse_pub = pr.purse_pub)"
- " LEFT JOIN purse_merges pm ON (pm.purse_pub = pd.purse_pub)"
- " WHERE ("
- " (purse_decision_serial_id>=$1) AND "
- " (refunded=$2)"
- " )"
- " ORDER BY purse_decision_serial_id ASC;");
-
-
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "audit_get_purse_decisions_incr",
- params,
- &purse_decision_serial_helper_cb,
- &dsc);
- if (GNUNET_OK != dsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_purse_deposits_above_serial_id.c b/src/exchangedb/pg_select_purse_deposits_above_serial_id.c
@@ -1,198 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_purse_deposits_above_serial_id.c
- * @brief Implementation of the select_purse_deposits_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_purse_deposits_above_serial_id.h"
-#include "helper.h"
-
-/**
- * Closure for #purse_deposit_serial_helper_cb().
- */
-struct PurseDepositSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_PurseDepositCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct DepositSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-purse_deposit_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct PurseDepositSerialContext *dsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_PurseDeposit deposit = {
- .exchange_base_url = NULL
- };
- struct TALER_DenominationPublicKey denom_pub;
- uint64_t rowid;
- uint32_t flags32;
- struct TALER_ReservePublicKeyP reserve_pub;
- bool not_merged = false;
- struct TALER_Amount purse_balance;
- struct TALER_Amount purse_total;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &deposit.amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
- &purse_balance),
- TALER_PQ_RESULT_SPEC_AMOUNT ("total",
- &purse_total),
- TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
- &deposit.deposit_fee),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("partner_base_url",
- &deposit.exchange_base_url),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- ¬_merged),
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &deposit.purse_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &deposit.coin_sig),
- GNUNET_PQ_result_spec_uint32 ("flags",
- &flags32),
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &deposit.coin_pub),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &deposit.h_age_commitment),
- &deposit.no_age_commitment),
- GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- memset (&deposit,
- 0,
- sizeof (deposit));
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- ret = dsc->cb (dsc->cb_cls,
- rowid,
- &deposit,
- not_merged ? NULL : &reserve_pub,
- (enum TALER_WalletAccountMergeFlags) flags32,
- &purse_balance,
- &purse_total,
- &denom_pub);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_select_purse_deposits_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_PurseDepositCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct PurseDepositSerialContext dsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "audit_get_purse_deposits_incr",
- "SELECT"
- " pd.amount_with_fee"
- ",pr.amount_with_fee AS total"
- ",pr.balance"
- ",pr.flags"
- ",pd.purse_pub"
- ",pd.coin_sig"
- ",partner_base_url"
- ",denom.denom_pub"
- ",denom.fee_deposit"
- ",pm.reserve_pub"
- ",kc.coin_pub"
- ",kc.age_commitment_hash"
- ",pd.purse_deposit_serial_id"
- " FROM purse_deposits pd"
- " LEFT JOIN partners USING (partner_serial_id)"
- " LEFT JOIN purse_merges pm USING (purse_pub)"
- " JOIN purse_requests pr USING (purse_pub)"
- " JOIN known_coins kc USING (coin_pub)"
- " JOIN denominations denom USING (denominations_serial)"
- " WHERE ("
- " (purse_deposit_serial_id>=$1)"
- " )"
- " ORDER BY purse_deposit_serial_id ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "audit_get_purse_deposits_incr",
- params,
- &purse_deposit_serial_helper_cb,
- &dsc);
- if (GNUNET_OK != dsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_purse_deposits_by_purse.c b/src/exchangedb/pg_select_purse_deposits_by_purse.c
@@ -1,149 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_purse_deposits_by_purse.c
- * @brief Implementation of the select_purse_deposits_by_purse function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_purse_deposits_by_purse.h"
-#include "helper.h"
-
-/**
- * Closure for #purse_refund_coin_helper_cb().
- */
-struct PurseRefundCoinContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_PurseRefundCoinCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseRefundCoinContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-purse_refund_coin_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct PurseRefundCoinContext *dsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_Amount amount_with_fee;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_DenominationPublicKey denom_pub;
- uint64_t rowid;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &denom_pub),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &amount_with_fee),
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &coin_pub),
- GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- ret = dsc->cb (dsc->cb_cls,
- rowid,
- &amount_with_fee,
- &coin_pub,
- &denom_pub);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_select_purse_deposits_by_purse (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_end
- };
- struct PurseRefundCoinContext dsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "audit_get_purse_deposits_by_purse",
- "SELECT"
- " pd.purse_deposit_serial_id"
- ",pd.amount_with_fee"
- ",pd.coin_pub"
- ",denom.denom_pub"
- " FROM purse_deposits pd"
- " JOIN known_coins kc"
- " USING (coin_pub)"
- " JOIN denominations denom"
- " USING (denominations_serial)"
- " WHERE purse_pub=$1;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "audit_get_purse_deposits_by_purse",
- params,
- &purse_refund_coin_helper_cb,
- &dsc);
- if (GNUNET_OK != dsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_purse_merge.c b/src/exchangedb/pg_select_purse_merge.c
@@ -1,76 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_purse_merge.c
- * @brief Implementation of the select_purse_merge function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_purse_merge.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_select_purse_merge (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- struct TALER_PurseMergeSignatureP *merge_sig,
- struct GNUNET_TIME_Timestamp *merge_timestamp,
- char **partner_url,
- struct TALER_ReservePublicKeyP *reserve_pub,
- bool *refunded)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("merge_sig",
- merge_sig),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- reserve_pub),
- GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
- merge_timestamp),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("partner_base_url",
- partner_url),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_bool ("refunded",
- refunded),
- NULL),
- GNUNET_PQ_result_spec_end
- };
-
- *partner_url = NULL;
- *refunded = false;
- PREPARE (pg,
- "select_purse_merge",
- "SELECT "
- " pm.reserve_pub"
- ",pm.merge_sig"
- ",pm.merge_timestamp"
- ",pr.partner_base_url"
- ",pd.refunded"
- " FROM purse_merges pm"
- " LEFT JOIN purse_decision pd USING (purse_pub)"
- " LEFT JOIN partners pr USING (partner_serial_id)"
- " WHERE pm.purse_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "select_purse_merge",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_select_purse_merges_above_serial_id.c b/src/exchangedb/pg_select_purse_merges_above_serial_id.c
@@ -1,186 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_purse_merges_above_serial_id.c
- * @brief Implementation of the select_purse_merges_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_purse_merges_above_serial_id.h"
-#include "helper.h"
-
-
-/**
- * Closure for #purse_deposit_serial_helper_cb().
- */
-struct PurseMergeSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_PurseMergeCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseMergeSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-purse_merges_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct PurseMergeSerialContext *dsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- char *partner_base_url = NULL;
- struct TALER_Amount amount;
- struct TALER_Amount balance;
- uint32_t flags32;
- enum TALER_WalletAccountMergeFlags flags;
- struct TALER_PurseMergePublicKeyP merge_pub;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_PurseMergeSignatureP merge_sig;
- struct TALER_PurseContractPublicKeyP purse_pub;
- struct GNUNET_TIME_Timestamp merge_timestamp;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &amount),
- TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
- &balance),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_string ("partner_base_url",
- &partner_base_url),
- NULL),
- GNUNET_PQ_result_spec_uint32 ("flags",
- &flags32),
- GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
- &merge_timestamp),
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &purse_pub),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type ("merge_sig",
- &merge_sig),
- GNUNET_PQ_result_spec_auto_from_type ("merge_pub",
- &merge_pub),
- GNUNET_PQ_result_spec_uint64 ("purse_merge_request_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- flags = (enum TALER_WalletAccountMergeFlags) flags32;
- ret = dsc->cb (dsc->cb_cls,
- rowid,
- partner_base_url,
- &amount,
- &balance,
- flags,
- &merge_pub,
- &reserve_pub,
- &merge_sig,
- &purse_pub,
- merge_timestamp);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_TALER_EXCHANGEDB_select_purse_merges_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_PurseMergeCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct PurseMergeSerialContext dsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "audit_get_purse_merge_incr",
- "SELECT"
- " pm.purse_merge_request_serial_id"
- ",partner_base_url"
- ",pr.amount_with_fee"
- ",pr.balance"
- ",pr.flags"
- ",pr.merge_pub"
- ",pm.reserve_pub"
- ",pm.merge_sig"
- ",pm.purse_pub"
- ",pm.merge_timestamp"
- " FROM purse_merges pm"
- " JOIN purse_requests pr USING (purse_pub)"
- " LEFT JOIN partners USING (partner_serial_id)"
- " WHERE ("
- " (purse_merge_request_serial_id>=$1)"
- " )"
- " ORDER BY purse_merge_request_serial_id ASC;");
-
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "audit_get_purse_merge_incr",
- params,
- &purse_merges_serial_helper_cb,
- &dsc);
- if (GNUNET_OK != dsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_purse_requests_above_serial_id.c b/src/exchangedb/pg_select_purse_requests_above_serial_id.c
@@ -1,174 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_purse_requests_above_serial_id.c
- * @brief Implementation of the select_purse_requests_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_purse_requests_above_serial_id.h"
-#include "helper.h"
-
-
-/**
- * Closure for #purse_deposit_serial_helper_cb().
- */
-struct PurseRequestsSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_PurseRequestCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseRequestsSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-purse_requests_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct PurseRequestsSerialContext *dsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct TALER_Amount target_amount;
- uint32_t age_limit;
- struct TALER_PurseMergePublicKeyP merge_pub;
- struct TALER_PurseContractPublicKeyP purse_pub;
- struct TALER_PrivateContractHashP h_contract_terms;
- struct TALER_PurseContractSignatureP purse_sig;
- struct GNUNET_TIME_Timestamp purse_creation;
- struct GNUNET_TIME_Timestamp purse_expiration;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &target_amount),
- GNUNET_PQ_result_spec_uint32 ("age_limit",
- &age_limit),
- GNUNET_PQ_result_spec_timestamp ("purse_creation",
- &purse_creation),
- GNUNET_PQ_result_spec_timestamp ("purse_expiration",
- &purse_expiration),
- GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
- &purse_pub),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- &h_contract_terms),
- GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
- &purse_sig),
- GNUNET_PQ_result_spec_auto_from_type ("merge_pub",
- &merge_pub),
- GNUNET_PQ_result_spec_uint64 ("purse_requests_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- dsc->status = GNUNET_SYSERR;
- return;
- }
- ret = dsc->cb (dsc->cb_cls,
- rowid,
- &purse_pub,
- &merge_pub,
- purse_creation,
- purse_expiration,
- &h_contract_terms,
- age_limit,
- &target_amount,
- &purse_sig);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_select_purse_requests_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_PurseRequestCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct PurseRequestsSerialContext dsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "audit_get_purse_requests_incr",
- "SELECT"
- " purse_requests_serial_id"
- ",purse_pub"
- ",amount_with_fee"
- ",age_limit"
- ",h_contract_terms"
- ",purse_creation"
- ",purse_expiration"
- ",merge_pub"
- ",purse_sig"
- " FROM purse_requests"
- " WHERE ("
- " (purse_requests_serial_id>=$1)"
- " )"
- " ORDER BY purse_requests_serial_id ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "audit_get_purse_requests_incr",
- params,
- &purse_requests_serial_helper_cb,
- &dsc);
- if (GNUNET_OK != dsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_recoup_above_serial_id.c b/src/exchangedb/pg_select_recoup_above_serial_id.c
@@ -1,184 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_recoup_above_serial_id.c
- * @brief Implementation of the select_recoup_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_recoup_above_serial_id.h"
-#include "helper.h"
-
-
-/**
- * Closure for #recoup_serial_helper_cb().
- */
-struct RecoupSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_RecoupCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct RecoupSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-recoup_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct RecoupSerialContext *psc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = psc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_CoinPublicInfo coin;
- struct TALER_CoinSpendSignatureP coin_sig;
- union GNUNET_CRYPTO_BlindingSecretP coin_blind;
- struct TALER_Amount amount;
- struct TALER_DenominationPublicKey denom_pub;
- struct GNUNET_TIME_Timestamp timestamp;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("recoup_uuid",
- &rowid),
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- ×tamp),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &coin.coin_pub),
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &coin_sig),
- GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
- &coin_blind),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &coin.denom_pub_hash),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &coin.h_age_commitment),
- &coin.no_age_commitment),
- TALER_PQ_result_spec_denom_sig ("denom_sig",
- &coin.denom_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_end
- };
- int ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- psc->status = GNUNET_SYSERR;
- return;
- }
- ret = psc->cb (psc->cb_cls,
- rowid,
- timestamp,
- &amount,
- &reserve_pub,
- &coin,
- &denom_pub,
- &coin_sig,
- &coin_blind);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_recoup_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_RecoupCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct RecoupSerialContext psc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "recoup_get_incr",
- "SELECT"
- " recoup_uuid"
- ",recoup_timestamp"
- ",withdraw.reserve_pub"
- ",coins.coin_pub"
- ",coin_sig"
- ",coin_blind"
- ",denoms.denom_pub_hash"
- ",coins.denom_sig"
- ",coins.age_commitment_hash"
- ",denoms.denom_pub"
- ",amount"
- " FROM recoup"
- " JOIN known_coins coins"
- " USING (coin_pub)"
- " JOIN withdraw"
- " USING (withdraw_id)"
- " JOIN denominations denoms"
- " ON (coins.denominations_serial = denoms.denominations_serial)"
- " WHERE recoup_uuid>=$1"
- " ORDER BY recoup_uuid ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "recoup_get_incr",
- params,
- &recoup_serial_helper_cb,
- &psc);
- if (GNUNET_OK != psc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c b/src/exchangedb/pg_select_recoup_refresh_above_serial_id.c
@@ -1,204 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_recoup_refresh_above_serial_id.c
- * @brief Implementation of the select_recoup_refresh_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_recoup_refresh_above_serial_id.h"
-#include "helper.h"
-
-
-/**
- * Closure for #recoup_refresh_serial_helper_cb().
- */
-struct RecoupRefreshSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_RecoupRefreshCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct RecoupRefreshSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-recoup_refresh_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct RecoupRefreshSerialContext *psc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = psc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct TALER_CoinSpendPublicKeyP old_coin_pub;
- struct TALER_CoinPublicInfo coin;
- struct TALER_CoinSpendSignatureP coin_sig;
- union GNUNET_CRYPTO_BlindingSecretP coin_blind;
- struct TALER_DenominationPublicKey denom_pub;
- struct TALER_DenominationHashP old_denom_pub_hash;
- struct TALER_Amount amount;
- struct TALER_BlindedCoinHashP h_blind_ev;
- struct GNUNET_TIME_Timestamp timestamp;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
- &rowid),
- GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
- ×tamp),
- GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
- &old_coin_pub),
- GNUNET_PQ_result_spec_auto_from_type ("old_denom_pub_hash",
- &old_denom_pub_hash),
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &coin.coin_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
- &coin_sig),
- GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
- &coin_blind),
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
- &h_blind_ev),
- GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
- &coin.denom_pub_hash),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &coin.h_age_commitment),
- &coin.no_age_commitment),
- TALER_PQ_result_spec_denom_sig ("denom_sig",
- &coin.denom_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- psc->status = GNUNET_SYSERR;
- return;
- }
- ret = psc->cb (psc->cb_cls,
- rowid,
- timestamp,
- &amount,
- &old_coin_pub,
- &old_denom_pub_hash,
- &coin,
- &denom_pub,
- &coin_sig,
- &coin_blind);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_recoup_refresh_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_RecoupRefreshCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct RecoupRefreshSerialContext psc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_recoup_refresh_above_serial_id",
- "SELECT"
- " rr.recoup_refresh_uuid"
- ",rr.recoup_timestamp"
- ",rr.coin_sig"
- ",rr.coin_blind"
- ",rr.amount"
- ",rrc.h_coin_ev AS h_blind_ev" // FIXME:-#9828 r.rc? r.selected_h? Old logic wanted a TALER_BlindedCoinHash, which we now need to derive (from rr.coin_blind)
- ",new_coins.age_commitment_hash"
- ",new_coins.coin_pub AS coin_pub"
- ",new_denoms.denom_pub AS denom_pub"
- ",new_denoms.denom_pub_hash"
- ",new_coins.denom_sig AS denom_sig"
- ",old_coins.coin_pub AS old_coin_pub"
- ",old_denoms.denom_pub_hash AS old_denom_pub_hash"
- " FROM recoup_refresh rr"
- " INNER JOIN refresh_revealed_coins rrc" // FIXME-#9828: no such table anymore!
- // but we have 'refresh_id" which is an FK into 'refresh'!
- " USING (rrc_serial)"
- " INNER JOIN refresh r"
- // but we have 'refresh_id" which is an FK into 'refresh'!
- " USING (refresh_id)"
- " INNER JOIN known_coins old_coins"
- " ON (r.old_coin_pub = old_coins.coin_pub)"
- " INNER JOIN known_coins new_coins"
- " ON (rr.coin_pub == new_coins.coin_pub)"
- " INNER JOIN refresh_commitments rfc"
- " ON (rrc.melt_serial_id = rfc.melt_serial_id)"
- " INNER JOIN denominations new_denoms"
- " ON (new_coins.denominations_serial = new_denoms.denominations_serial)"
- " INNER JOIN denominations old_denoms"
- " ON (old_coins.denominations_serial = old_denoms.denominations_serial)"
- " WHERE recoup_refresh_uuid>=$1"
- " ORDER BY recoup_refresh_uuid ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_recoup_refresh_above_serial_id",
- params,
- &recoup_refresh_serial_helper_cb,
- &psc);
- if (GNUNET_OK != psc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_refreshes_above_serial_id.c b/src/exchangedb/pg_select_refreshes_above_serial_id.c
@@ -1,180 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_refreshes_above_serial_id.c
- * @brief Implementation of the select_refreshes_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_refreshes_above_serial_id.h"
-#include "helper.h"
-
-
-/**
- * Closure for #refreshs_serial_helper_cb().
- */
-struct RefreshsSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_RefreshesCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct RefreshsSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-refreshs_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct RefreshsSerialContext *rsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_DenominationPublicKey old_denom_pub;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_CoinSpendSignatureP coin_sig;
- struct TALER_AgeCommitmentHashP h_age_commitment;
- bool ac_isnull;
- struct TALER_Amount amount_with_fee;
- uint64_t rowid;
- struct TALER_RefreshCommitmentP rc;
- size_t num_nds;
- uint64_t *nds;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_denom_pub ("old_denom_pub",
- &old_denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
- &coin_pub),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
- &h_age_commitment),
- &ac_isnull),
- GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
- &coin_sig),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &amount_with_fee),
- GNUNET_PQ_result_spec_uint64 ("refresh_id",
- &rowid),
- GNUNET_PQ_result_spec_auto_from_type ("rc",
- &rc),
- GNUNET_PQ_result_spec_array_uint64 (pg->conn,
- "new_denominations_serials",
- &num_nds,
- &nds),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- rsc->status = GNUNET_SYSERR;
- return;
- }
-
- ret = rsc->cb (rsc->cb_cls,
- rowid,
- &old_denom_pub,
- &coin_pub,
- &coin_sig,
- ac_isnull ? NULL : &h_age_commitment,
- &amount_with_fee,
- num_nds,
- nds,
- &rc);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_refreshes_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_RefreshesCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct RefreshsSerialContext rsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_refreshes_above_serial_id",
- "SELECT"
- " denom.denom_pub AS old_denom_pub"
- ",r.old_coin_pub"
- ",kc.age_commitment_hash"
- ",r.old_coin_sig"
- ",r.amount_with_fee"
- ",r.refresh_id"
- ",r.rc"
- ",r.denom_serials AS new_denominations_serials"
- " FROM refresh r"
- " JOIN known_coins kc"
- " ON (r.old_coin_pub = kc.coin_pub)"
- " JOIN denominations denom"
- " ON (kc.denominations_serial = denom.denominations_serial)"
- " WHERE refresh_id>=$1"
- " ORDER BY refresh_id ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_refreshes_above_serial_id",
- params,
- &refreshs_serial_helper_cb,
- &rsc);
- if (GNUNET_OK != rsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_refunds_above_serial_id.c b/src/exchangedb/pg_select_refunds_above_serial_id.c
@@ -1,220 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_refunds_above_serial_id.c
- * @brief Implementation of the select_refunds_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_refunds_above_serial_id.h"
-#include "helper.h"
-
-/**
- * Closure for #refunds_serial_helper_cb().
- */
-struct RefundsSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_RefundCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct RefundsSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-refunds_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct RefundsSerialContext *rsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_EXCHANGEDB_Refund refund;
- struct TALER_DenominationPublicKey denom_pub;
- uint64_t rowid;
- bool full_refund;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
- &refund.details.merchant_pub),
- GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
- &refund.details.merchant_sig),
- GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
- &refund.details.h_contract_terms),
- GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
- &refund.details.rtransaction_id),
- TALER_PQ_result_spec_denom_pub ("denom_pub",
- &denom_pub),
- GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
- &refund.coin.coin_pub),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &refund.details.refund_amount),
- GNUNET_PQ_result_spec_uint64 ("refund_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- rsc->status = GNUNET_SYSERR;
- return;
- }
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&rowid),
- GNUNET_PQ_query_param_end
- };
- struct TALER_Amount amount_with_fee;
- uint64_t s_f;
- uint64_t s_v;
- struct GNUNET_PQ_ResultSpec rs2[] = {
- GNUNET_PQ_result_spec_uint64 ("s_v",
- &s_v),
- GNUNET_PQ_result_spec_uint64 ("s_f",
- &s_f),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &amount_with_fee),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "test_refund_full",
- params,
- rs2);
- if (qs <= 0)
- {
- GNUNET_break (0);
- rsc->status = GNUNET_SYSERR;
- return;
- }
- /* normalize */
- s_v += s_f / TALER_AMOUNT_FRAC_BASE;
- s_f %= TALER_AMOUNT_FRAC_BASE;
- full_refund = (s_v >= amount_with_fee.value) &&
- (s_f >= amount_with_fee.fraction);
- }
- ret = rsc->cb (rsc->cb_cls,
- rowid,
- &denom_pub,
- &refund.coin.coin_pub,
- &refund.details.merchant_pub,
- &refund.details.merchant_sig,
- &refund.details.h_contract_terms,
- refund.details.rtransaction_id,
- full_refund,
- &refund.details.refund_amount);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_refunds_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_RefundCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct RefundsSerialContext rsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- /* Fetch refunds with rowid '\geq' the given parameter */
- PREPARE (pg,
- "audit_get_refunds_incr",
- "SELECT"
- " bdep.merchant_pub"
- ",ref.merchant_sig"
- ",bdep.h_contract_terms"
- ",ref.rtransaction_id"
- ",denom.denom_pub"
- ",kc.coin_pub"
- ",ref.amount_with_fee"
- ",ref.refund_serial_id"
- " FROM refunds ref"
- " JOIN batch_deposits bdep"
- " ON (ref.batch_deposit_serial_id=bdep.batch_deposit_serial_id)"
- " JOIN coin_deposits cdep"
- " ON (ref.coin_pub=cdep.coin_pub AND ref.batch_deposit_serial_id=cdep.batch_deposit_serial_id)"
- " JOIN known_coins kc"
- " ON (cdep.coin_pub=kc.coin_pub)"
- " JOIN denominations denom"
- " ON (kc.denominations_serial=denom.denominations_serial)"
- " WHERE ref.refund_serial_id>=$1"
- " ORDER BY ref.refund_serial_id ASC;");
- PREPARE (pg,
- "test_refund_full",
- "SELECT"
- " CAST(SUM(CAST((ref.amount_with_fee).frac AS INT8)) AS INT8) AS s_f"
- ",CAST(SUM((ref.amount_with_fee).val) AS INT8) AS s_v"
- ",cdep.amount_with_fee"
- " FROM refunds ref"
- " JOIN coin_deposits cdep"
- " ON (ref.coin_pub=cdep.coin_pub AND ref.batch_deposit_serial_id=cdep.batch_deposit_serial_id)"
- " WHERE ref.refund_serial_id=$1"
- " GROUP BY (cdep.amount_with_fee);");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "audit_get_refunds_incr",
- params,
- &refunds_serial_helper_cb,
- &rsc);
- if (GNUNET_OK != rsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_refunds_by_coin.c b/src/exchangedb/pg_select_refunds_by_coin.c
@@ -1,139 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_refunds_by_coin.c
- * @brief Implementation of the select_refunds_by_coin function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_refunds_by_coin.h"
-#include "helper.h"
-
-
-/**
- * Closure for #get_refunds_cb().
- */
-struct SelectRefundContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_RefundCoinCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Set to #GNUNET_SYSERR on error.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct SelectRefundContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-get_refunds_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct SelectRefundContext *srctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = srctx->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_Amount amount_with_fee;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &amount_with_fee),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- srctx->status = GNUNET_SYSERR;
- return;
- }
- if (GNUNET_OK !=
- srctx->cb (srctx->cb_cls,
- &amount_with_fee))
- return;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_refunds_by_coin (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct TALER_PrivateContractHashP *h_contract,
- TALER_EXCHANGEDB_RefundCoinCallback cb,
- void *cb_cls)
-{
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (coin_pub),
- GNUNET_PQ_query_param_auto_from_type (merchant_pub),
- GNUNET_PQ_query_param_auto_from_type (h_contract),
- GNUNET_PQ_query_param_end
- };
- struct SelectRefundContext srctx = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- const char *query = "get_refunds_by_coin_and_contract";
-
- PREPARE (pg,
- query,
- "SELECT"
- " ref.amount_with_fee"
- " FROM refunds ref"
- " JOIN coin_deposits cdep"
- " USING (coin_pub,batch_deposit_serial_id)"
- " JOIN batch_deposits bdep"
- " ON (ref.batch_deposit_serial_id = bdep.batch_deposit_serial_id)"
- " WHERE ref.coin_pub=$1"
- " AND bdep.merchant_pub=$2"
- " AND bdep.h_contract_terms=$3;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- query,
- params,
- &get_refunds_cb,
- &srctx);
- if (GNUNET_SYSERR == srctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_reserve_close_info.c b/src/exchangedb/pg_select_reserve_close_info.c
@@ -1,62 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_reserve_close_info.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_reserve_close_info.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_reserve_close_info (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- struct TALER_Amount *balance,
- struct TALER_FullPayto *payto_uri)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_amount ("current_balance",
- pg->currency,
- balance),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri->full_payto),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "select_reserve_close_info",
- "SELECT "
- " r.current_balance"
- ",wt.payto_uri"
- " FROM reserves r"
- " LEFT JOIN reserves_in ri"
- " USING (reserve_pub)"
- " LEFT JOIN wire_targets wt"
- " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)"
- " WHERE r.reserve_pub=$1;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "select_reserve_close_info",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_select_reserve_close_request_info.c b/src/exchangedb/pg_select_reserve_close_request_info.c
@@ -1,73 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2026 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_reserve_close_request_info.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_reserve_close_request_info.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_reserve_close_request_info (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- uint64_t rowid,
- struct TALER_ReserveSignatureP *reserve_sig,
- struct GNUNET_TIME_Timestamp *request_timestamp,
- struct TALER_Amount *close_balance,
- struct TALER_Amount *close_fee,
- struct TALER_FullPayto *payto_uri)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (reserve_pub),
- GNUNET_PQ_query_param_uint64 (&rowid),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- reserve_sig),
- GNUNET_PQ_result_spec_timestamp ("request_timestamp",
- request_timestamp),
- TALER_PQ_result_spec_amount ("close_balance",
- pg->currency,
- close_balance),
- TALER_PQ_result_spec_amount ("close_fee",
- pg->currency,
- close_fee),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri->full_payto),
- GNUNET_PQ_result_spec_end
- };
-
- // FIXME: this SQL query is still complete nonsense!
- PREPARE (pg,
- "select_reserve_close_request_info",
- "SELECT "
- " r.current_balance"
- ",wt.payto_uri"
- " FROM reserves r"
- " LEFT JOIN reserves_in ri"
- " USING (reserve_pub)"
- " WHERE r.reserve_pub=$1"
- " AND r.row_id=$2;");
- return GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "select_reserve_close_request_info",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_select_reserve_closed_above_serial_id.c b/src/exchangedb/pg_select_reserve_closed_above_serial_id.c
@@ -1,172 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_reserve_closed_above_serial_id.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_reserve_closed_above_serial_id.h"
-#include "helper.h"
-
-/**
- * Closure for #reserve_closed_serial_helper_cb().
- */
-struct ReserveClosedSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_ReserveClosedCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin's context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct ReserveClosedSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-reserve_closed_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReserveClosedSerialContext *rcsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rcsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_FullPayto receiver_account;
- struct TALER_WireTransferIdentifierRawP wtid;
- struct TALER_Amount amount_with_fee;
- struct TALER_Amount closing_fee;
- struct GNUNET_TIME_Timestamp execution_date;
- uint64_t close_request_row;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("close_uuid",
- &rowid),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- &execution_date),
- GNUNET_PQ_result_spec_auto_from_type ("wtid",
- &wtid),
- GNUNET_PQ_result_spec_string ("receiver_account",
- &receiver_account.full_payto),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount_with_fee),
- TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
- &closing_fee),
- GNUNET_PQ_result_spec_uint64 ("close_request_row",
- &close_request_row),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- rcsc->status = GNUNET_SYSERR;
- return;
- }
- ret = rcsc->cb (rcsc->cb_cls,
- rowid,
- execution_date,
- &amount_with_fee,
- &closing_fee,
- &reserve_pub,
- receiver_account,
- &wtid,
- close_request_row);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_reserve_closed_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_ReserveClosedCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct ReserveClosedSerialContext rcsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (
- pg,
- "reserves_close_get_incr",
- "SELECT"
- " close_uuid"
- ",reserves.reserve_pub"
- ",execution_date"
- ",wtid"
- ",wt.payto_uri AS receiver_account"
- ",amount"
- ",closing_fee"
- ",close_request_row"
- " FROM reserves_close"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " JOIN reserves"
- " USING (reserve_pub)"
- " WHERE close_uuid>=$1"
- " ORDER BY close_uuid ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "reserves_close_get_incr",
- params,
- &reserve_closed_serial_helper_cb,
- &rcsc);
- if (GNUNET_OK != rcsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_reserve_open_above_serial_id.c b/src/exchangedb/pg_select_reserve_open_above_serial_id.c
@@ -1,163 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file pg_select_reserve_open_above_serial_id.c
- * @brief Low-level (statement-level) Postgres database access for the exchange
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_reserve_open_above_serial_id.h"
-#include "helper.h"
-
-
-/**
- * Closure for #reserve_open_serial_helper_cb().
- */
-struct ReserveOpenSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_ReserveOpenCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin's context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct ReserveOpenSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-reserve_open_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReserveOpenSerialContext *rcsc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rcsc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_ReserveSignatureP reserve_sig;
- uint32_t requested_purse_limit;
- struct GNUNET_TIME_Timestamp request_timestamp;
- struct GNUNET_TIME_Timestamp reserve_expiration;
- struct TALER_Amount reserve_payment;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("open_request_uuid",
- &rowid),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &reserve_sig),
- GNUNET_PQ_result_spec_timestamp ("request_timestamp",
- &request_timestamp),
- GNUNET_PQ_result_spec_timestamp ("expiration_date",
- &reserve_expiration),
- GNUNET_PQ_result_spec_uint32 ("requested_purse_limit",
- &requested_purse_limit),
- TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_payment",
- &reserve_payment),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- rcsc->status = GNUNET_SYSERR;
- return;
- }
- ret = rcsc->cb (rcsc->cb_cls,
- rowid,
- &reserve_payment,
- request_timestamp,
- reserve_expiration,
- requested_purse_limit,
- &reserve_pub,
- &reserve_sig);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_reserve_open_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_ReserveOpenCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct ReserveOpenSerialContext rcsc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (
- pg,
- "reserves_open_get_incr",
- "SELECT"
- " open_request_uuid"
- ",reserve_pub"
- ",request_timestamp"
- ",expiration_date"
- ",reserve_sig"
- ",reserve_payment"
- ",requested_purse_limit"
- " FROM reserves_open_requests"
- " WHERE open_request_uuid>=$1"
- " ORDER BY open_request_uuid ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "reserves_open_get_incr",
- params,
- &reserve_open_serial_helper_cb,
- &rcsc);
- if (GNUNET_OK != rcsc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id.c b/src/exchangedb/pg_select_reserves_in_above_serial_id.c
@@ -1,163 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_reserves_in_above_serial_id.c
- * @brief Implementation of the select_reserves_in_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_reserves_in_above_serial_id.h"
-#include "helper.h"
-
-/**
- * Closure for #reserves_in_serial_helper_cb().
- */
-struct ReservesInSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_ReserveInCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct ReservesInSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-reserves_in_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReservesInSerialContext *risc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = risc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_Amount credit;
- struct TALER_FullPayto sender_account_details;
- struct GNUNET_TIME_Timestamp execution_date;
- uint64_t rowid;
- uint64_t wire_reference;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- GNUNET_PQ_result_spec_uint64 ("wire_reference",
- &wire_reference),
- TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
- &credit),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- &execution_date),
- GNUNET_PQ_result_spec_string ("sender_account_details",
- &sender_account_details.full_payto),
- GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- risc->status = GNUNET_SYSERR;
- return;
- }
- ret = risc->cb (risc->cb_cls,
- rowid,
- &reserve_pub,
- &credit,
- sender_account_details,
- wire_reference,
- execution_date);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_reserves_in_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_ReserveInCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct ReservesInSerialContext risc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_reserves_in_above_serial_id",
- "SELECT"
- " reserves.reserve_pub"
- ",wire_reference"
- ",credit"
- ",execution_date"
- ",wt.payto_uri AS sender_account_details"
- ",reserve_in_serial_id"
- " FROM reserves_in"
- " JOIN reserves"
- " USING (reserve_pub)"
- " JOIN wire_targets wt"
- " ON (wire_source_h_payto = wire_target_h_payto)"
- " WHERE reserve_in_serial_id>=$1"
- " ORDER BY reserve_in_serial_id;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_reserves_in_above_serial_id",
- params,
- &reserves_in_serial_helper_cb,
- &risc);
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- return qs;
- if (GNUNET_OK != risc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c b/src/exchangedb/pg_select_reserves_in_above_serial_id_by_account.c
@@ -1,166 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_reserves_in_above_serial_id_by_account.c
- * @brief Implementation of the select_reserves_in_above_serial_id_by_account function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include \
- "taler/exchange-database/select_reserves_in_above_serial_id_by_account.h"
-#include "helper.h"
-
-
-/**
- * Closure for #reserves_in_serial_helper_cb().
- */
-struct ReservesInSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_ReserveInCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct ReservesInSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-reserves_in_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct ReservesInSerialContext *risc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = risc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_Amount credit;
- struct TALER_FullPayto sender_account_details;
- struct GNUNET_TIME_Timestamp execution_date;
- uint64_t rowid;
- uint64_t wire_reference;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- GNUNET_PQ_result_spec_uint64 ("wire_reference",
- &wire_reference),
- TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
- &credit),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- &execution_date),
- GNUNET_PQ_result_spec_string ("sender_account_details",
- &sender_account_details.full_payto),
- GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id",
- &rowid),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- risc->status = GNUNET_SYSERR;
- return;
- }
- ret = risc->cb (risc->cb_cls,
- rowid,
- &reserve_pub,
- &credit,
- sender_account_details,
- wire_reference,
- execution_date);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_select_reserves_in_above_serial_id_by_account (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *account_name,
- uint64_t serial_id,
- TALER_EXCHANGEDB_ReserveInCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_string (account_name),
- GNUNET_PQ_query_param_end
- };
- struct ReservesInSerialContext risc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_reserves_in_above_serial_id_by_account",
- "SELECT"
- " reserves.reserve_pub"
- ",wire_reference"
- ",credit"
- ",execution_date"
- ",wt.payto_uri AS sender_account_details"
- ",reserve_in_serial_id"
- " FROM reserves_in"
- " JOIN reserves "
- " USING (reserve_pub)"
- " JOIN wire_targets wt"
- " ON (wire_source_h_payto = wire_target_h_payto)"
- " WHERE reserve_in_serial_id>=$1"
- " AND exchange_account_section=$2"
- " ORDER BY reserve_in_serial_id ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_reserves_in_above_serial_id_by_account",
- params,
- &reserves_in_serial_helper_cb,
- &risc);
- if (GNUNET_OK != risc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id.c b/src/exchangedb/pg_select_wire_out_above_serial_id.c
@@ -1,154 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_wire_out_above_serial_id.c
- * @brief Implementation of the select_wire_out_above_serial_id function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_wire_out_above_serial_id.h"
-#include "helper.h"
-
-/**
- * Closure for #wire_out_serial_helper_cb().
- */
-struct WireOutSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_WireTransferOutCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- int status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct WireOutSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-wire_out_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct WireOutSerialContext *wosc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = wosc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct GNUNET_TIME_Timestamp date;
- struct TALER_WireTransferIdentifierRawP wtid;
- struct TALER_FullPayto payto_uri;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
- &rowid),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- &date),
- GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
- &wtid),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri.full_payto),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_end
- };
- int ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- wosc->status = GNUNET_SYSERR;
- return;
- }
- ret = wosc->cb (wosc->cb_cls,
- rowid,
- date,
- &wtid,
- payto_uri,
- &amount);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_wire_out_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_WireTransferOutCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct WireOutSerialContext wosc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_wire_out_above_serial_id",
- "SELECT"
- " wo.wireout_uuid"
- ",wo.execution_date"
- ",wo.wtid_raw"
- ",wt.payto_uri"
- ",wo.amount"
- " FROM wire_out wo"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " WHERE wireout_uuid>=$1"
- " ORDER BY wireout_uuid ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_wire_out_above_serial_id",
- params,
- &wire_out_serial_helper_cb,
- &wosc);
- if (GNUNET_OK != wosc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c b/src/exchangedb/pg_select_wire_out_above_serial_id_by_account.c
@@ -1,157 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_wire_out_above_serial_id_by_account.c
- * @brief Implementation of the select_wire_out_above_serial_id_by_account function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_wire_out_above_serial_id_by_account.h"
-#include "helper.h"
-
-/**
- * Closure for #wire_out_serial_helper_cb().
- */
-struct WireOutSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_WireTransferOutCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- int status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct WireOutSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-wire_out_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct WireOutSerialContext *wosc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = wosc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct GNUNET_TIME_Timestamp date;
- struct TALER_WireTransferIdentifierRawP wtid;
- struct TALER_FullPayto payto_uri;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
- &rowid),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- &date),
- GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
- &wtid),
- GNUNET_PQ_result_spec_string ("payto_uri",
- &payto_uri.full_payto),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_end
- };
- int ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- wosc->status = GNUNET_SYSERR;
- return;
- }
- ret = wosc->cb (wosc->cb_cls,
- rowid,
- date,
- &wtid,
- payto_uri,
- &amount);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_TALER_EXCHANGEDB_select_wire_out_above_serial_id_by_account (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *account_name,
- uint64_t serial_id,
- TALER_EXCHANGEDB_WireTransferOutCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_string (account_name),
- GNUNET_PQ_query_param_end
- };
- struct WireOutSerialContext wosc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_wire_out_above_serial_id_by_account",
- "SELECT"
- " wo.wireout_uuid"
- ",wo.execution_date"
- ",wo.wtid_raw"
- ",wt.payto_uri"
- ",wo.amount"
- " FROM wire_out wo"
- " JOIN wire_targets wt"
- " USING (wire_target_h_payto)"
- " WHERE wo.wireout_uuid>=$1 "
- " AND wo.exchange_account_section=$2"
- " ORDER BY wo.wireout_uuid ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_wire_out_above_serial_id_by_account",
- params,
- &wire_out_serial_helper_cb,
- &wosc);
- if (GNUNET_OK != wosc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c b/src/exchangedb/pg_select_withdraw_amounts_for_kyc_check.c
@@ -1,158 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_withdraw_amounts_for_kyc_check.c
- * @brief Implementation of the select_withdraw_amounts_for_kyc_check function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_withdraw_amounts_for_kyc_check.h"
-#include "taler/exchange-database/select_aggregation_amounts_for_kyc_check.h"
-#include "helper.h"
-
-
-/**
- * Closure for #get_kyc_amounts_cb().
- */
-struct KycAmountCheckContext
-{
- /**
- * Function to call per result.
- */
- TALER_KYCLOGIC_KycAmountCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Flag set to #GNUNET_OK as long as everything is fine.
- */
- enum GNUNET_GenericReturnValue status;
-
-};
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct KycAmountCheckContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-get_kyc_amounts_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct KycAmountCheckContext *ctx = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- struct GNUNET_TIME_Absolute date;
- struct TALER_Amount amount;
- struct GNUNET_PQ_ResultSpec rs[] = {
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
- &amount),
- GNUNET_PQ_result_spec_absolute_time ("date",
- &date),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- ctx->status = GNUNET_SYSERR;
- return;
- }
- ret = ctx->cb (ctx->cb_cls,
- &amount,
- date);
- GNUNET_PQ_cleanup_result (rs);
- switch (ret)
- {
- case GNUNET_OK:
- continue;
- case GNUNET_NO:
- break;
- case GNUNET_SYSERR:
- ctx->status = GNUNET_SYSERR;
- break;
- }
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_withdraw_amounts_for_kyc_check (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- struct GNUNET_TIME_Absolute time_limit,
- TALER_KYCLOGIC_KycAmountCallback kac,
- void *kac_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_absolute_time (&time_limit),
- GNUNET_PQ_query_param_end
- };
- struct KycAmountCheckContext ctx = {
- .cb = kac,
- .cb_cls = kac_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "select_withdraw_amounts_for_kyc_check",
- "SELECT"
- " wd.amount_with_fee AS amount"
- ",wd.execution_date AS date"
- " FROM reserves_in ri"
- " JOIN reserve_history rh"
- " ON (rh.reserve_pub = ri.reserve_pub)"
- " JOIN withdraw wd"
- " ON (wd.withdraw_id = rh.serial_id)"
- " WHERE ri.wire_source_h_payto IN ("
- " SELECT wire_target_h_payto"
- " FROM wire_targets"
- " WHERE h_normalized_payto=$1"
- " )"
- " AND rh.table_name='withdraw'"
- " AND wd.execution_date >= $2"
- " ORDER BY rh.reserve_history_serial_id DESC");
- qs = GNUNET_PQ_eval_prepared_multi_select (
- pg->conn,
- "select_withdraw_amounts_for_kyc_check",
- params,
- &get_kyc_amounts_cb,
- &ctx);
- if (GNUNET_OK != ctx.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_select_withdrawals_above_serial_id.c b/src/exchangedb/pg_select_withdrawals_above_serial_id.c
@@ -1,212 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_select_withdrawals_above_serial_id.c
- * @brief Implementation of the select_withdrawals_above_serial_id function for Postgres
- * @author Christian Grothoff
- * @author Özgür Kesim
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/select_withdrawals_above_serial_id.h"
-#include "helper.h"
-
-/**
- * Closure for #withdraw_serial_helper_cb().
- */
-struct WithdrawSerialContext
-{
-
- /**
- * Callback to call.
- */
- TALER_EXCHANGEDB_WithdrawCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
- /**
- * Plugin context.
- */
- struct TALER_EXCHANGEDB_PostgresContext *pg;
-
- /**
- * Status code, set to #GNUNET_SYSERR on hard errors.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct WithdrawSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-withdraw_serial_helper_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct WithdrawSerialContext *rosc = cls;
- struct TALER_EXCHANGEDB_PostgresContext *pg = rosc->pg;
-
- for (unsigned int i = 0; i<num_results; i++)
- {
- uint64_t rowid;
- struct TALER_HashBlindedPlanchetsP h_planchets;
- struct GNUNET_TIME_Timestamp execution_date;
- struct TALER_Amount amount_with_fee;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_ReserveSignatureP reserve_sig;
- uint16_t max_age;
- bool no_max_age;
- uint16_t noreveal_index;
- bool no_noreveal_index;
- struct TALER_HashBlindedPlanchetsP selected_h;
- bool no_selected_h;
- struct TALER_BlindingMasterSeedP blinding_seed;
- bool no_blinding_seed;
- size_t num_denom_serials;
- uint64_t *denom_serials = NULL;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("withdraw_id",
- &rowid),
- GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
- &h_planchets),
- GNUNET_PQ_result_spec_timestamp ("execution_date",
- &execution_date),
- TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
- &amount_with_fee),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- &reserve_pub),
- GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
- &reserve_sig),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint16 ("max_age",
- &max_age),
- &no_max_age),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_uint16 ("noreveal_index",
- &noreveal_index),
- &no_noreveal_index),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type (
- "selected_h",
- &selected_h),
- &no_selected_h),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type (
- "blinding_seed",
- &blinding_seed),
- &no_blinding_seed),
- GNUNET_PQ_result_spec_array_uint64 (
- pg->conn,
- "denom_serials",
- &num_denom_serials,
- &denom_serials),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- rosc->status = GNUNET_SYSERR;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- if ((! no_max_age) &&
- ((255 <= noreveal_index) || (255 <= max_age)))
- {
- GNUNET_break (0);
- rosc->status = GNUNET_SYSERR;
- GNUNET_PQ_cleanup_result (rs);
- return;
- }
- ret = rosc->cb (rosc->cb_cls,
- rowid,
- num_denom_serials,
- denom_serials,
- no_selected_h ? NULL : &selected_h,
- &h_planchets,
- no_blinding_seed ? NULL : &blinding_seed,
- ! no_max_age,
- (uint8_t) max_age,
- (uint8_t) noreveal_index,
- &reserve_pub,
- &reserve_sig,
- execution_date,
- &amount_with_fee);
- GNUNET_PQ_cleanup_result (rs);
- if (GNUNET_OK != ret)
- break;
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_select_withdrawals_above_serial_id (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t serial_id,
- TALER_EXCHANGEDB_WithdrawCallback cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&serial_id),
- GNUNET_PQ_query_param_end
- };
- struct WithdrawSerialContext rosc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .pg = pg,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- /* Fetch deposits with rowid '\geq' the given parameter */
- PREPARE (pg,
- "audit_get_withdraw_incr",
- "SELECT"
- " withdraw_id"
- ",planchets_h"
- ",execution_date"
- ",amount_with_fee"
- ",reserve_pub"
- ",reserve_sig"
- ",max_age"
- ",noreveal_index"
- ",selected_h"
- ",blinding_seed"
- ",denom_serials"
- " FROM withdraw"
- " WHERE withdraw_id>=$1"
- " ORDER BY withdraw_id ASC;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "audit_get_withdraw_incr",
- params,
- &withdraw_serial_helper_cb,
- &rosc);
- if (GNUNET_OK != rosc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_set_aml_lock.c b/src/exchangedb/pg_set_aml_lock.c
@@ -1,70 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_set_aml_lock.c
- * @brief Implementation of the set_aml_lock function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/set_aml_lock.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_set_aml_lock (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- struct GNUNET_TIME_Relative lock_duration,
- struct GNUNET_TIME_Absolute *existing_lock)
-{
-
- struct GNUNET_TIME_Absolute expires
- = GNUNET_TIME_relative_to_absolute (lock_duration);
- struct GNUNET_TIME_Absolute now
- = GNUNET_TIME_absolute_get ();
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_absolute_time (&now),
- GNUNET_PQ_query_param_absolute_time (&expires),
- GNUNET_PQ_query_param_end
- };
- bool nx; /* true if the *account* is not known */
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_absolute_time ("out_aml_program_lock_timeout",
- existing_lock),
- &nx),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "set_aml_lock",
- "SELECT out_aml_program_lock_timeout"
- " FROM exchange_do_set_aml_lock($1,$2,$3);");
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "set_aml_lock",
- params,
- rs);
- if (qs <= 0)
- return qs;
- if (nx)
- {
- *existing_lock = GNUNET_TIME_UNIT_ZERO_ABS;
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_set_extension_manifest.c b/src/exchangedb/pg_set_extension_manifest.c
@@ -1,53 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_set_extension_manifest.c
- * @brief Implementation of the set_extension_manifest function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/set_extension_manifest.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_set_extension_manifest (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- const char *extension_name,
- const char *manifest)
-{
- struct GNUNET_PQ_QueryParam pcfg =
- (NULL == manifest || 0 == *manifest)
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (manifest);
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (extension_name),
- pcfg,
- GNUNET_PQ_query_param_end
- };
-
-
- PREPARE (pg,
- "set_extension_manifest",
- "INSERT INTO extensions (name, manifest) VALUES ($1, $2) "
- "ON CONFLICT (name) "
- "DO UPDATE SET manifest=$2");
-
-
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "set_extension_manifest",
- params);
-}
diff --git a/src/exchangedb/pg_set_purse_balance.c b/src/exchangedb/pg_set_purse_balance.c
@@ -1,48 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_set_purse_balance.c
- * @brief Implementation of the set_purse_balance function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/set_purse_balance.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_set_purse_balance (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- const struct TALER_Amount *balance)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (purse_pub),
- TALER_PQ_query_param_amount (pg->conn,
- balance),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "set_purse_balance",
- "UPDATE purse_requests"
- " SET balance=$2"
- " WHERE purse_pub=$1;");
-
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "set_purse_balance",
- params);
-}
diff --git a/src/exchangedb/pg_start.c b/src/exchangedb/pg_start.c
@@ -1,51 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_start.c
- * @brief Implementation of the start function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/exchange-database/preflight.h"
-#include "taler/exchange-database/start.h"
-#include "helper.h"
-
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGEDB_start (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const char *name)
-{
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- GNUNET_assert (NULL != name);
- if (GNUNET_SYSERR ==
- TALER_EXCHANGEDB_preflight (pg))
- return GNUNET_SYSERR;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Starting transaction `%s'\n",
- name);
- if (GNUNET_OK !=
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- TALER_LOG_ERROR ("Failed to start transaction\n");
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- pg->transaction_name = name;
- return GNUNET_OK;
-}
diff --git a/src/exchangedb/pg_start_deferred_wire_out.c b/src/exchangedb/pg_start_deferred_wire_out.c
@@ -1,56 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_start_deferred_wire_out.c
- * @brief Implementation of the start_deferred_wire_out function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/exchange-database/start_deferred_wire_out.h"
-#include "helper.h"
-#include "taler/exchange-database/preflight.h"
-#include "taler/exchange-database/rollback.h"
-
-enum GNUNET_GenericReturnValue
-TALER_TALER_EXCHANGEDB_start_deferred_wire_out (struct
- TALER_EXCHANGEDB_PostgresContext
- *pg)
-{
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute (
- "START TRANSACTION ISOLATION LEVEL READ COMMITTED;"),
- GNUNET_PQ_make_execute ("SET CONSTRAINTS ALL DEFERRED;"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- if (GNUNET_SYSERR ==
- TALER_EXCHANGEDB_preflight (pg))
- return GNUNET_SYSERR;
- if (GNUNET_OK !=
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- TALER_LOG_ERROR (
- "Failed to defer wire_out_ref constraint on transaction\n");
- GNUNET_break (0);
- TALER_EXCHANGEDB_rollback (pg);
- return GNUNET_SYSERR;
- }
- pg->transaction_name = "deferred wire out";
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Starting READ COMMITTED DEFERRED transaction `%s'\n",
- pg->transaction_name);
- return GNUNET_OK;
-}
diff --git a/src/exchangedb/pg_start_read_committed.c b/src/exchangedb/pg_start_read_committed.c
@@ -1,53 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_start_read_committed.c
- * @brief Implementation of the start_read_committed function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/exchange-database/start_read_committed.h"
-#include "taler/exchange-database/preflight.h"
-#include "helper.h"
-
-enum GNUNET_GenericReturnValue
-TALER_TALER_EXCHANGEDB_start_read_committed (struct
- TALER_EXCHANGEDB_PostgresContext *
- pg,
- const char *name)
-{
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL READ COMMITTED"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- GNUNET_assert (NULL != name);
- if (GNUNET_SYSERR ==
- TALER_EXCHANGEDB_preflight (pg))
- return GNUNET_SYSERR;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Starting READ COMMITTED transaction `%s`\n",
- name);
- if (GNUNET_OK !=
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- TALER_LOG_ERROR ("Failed to start transaction\n");
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- pg->transaction_name = name;
- return GNUNET_OK;
-}
diff --git a/src/exchangedb/pg_start_read_only.c b/src/exchangedb/pg_start_read_only.c
@@ -1,53 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_start_read_only.c
- * @brief Implementation of the start_read_only function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/exchange-database/start_read_only.h"
-#include "taler/exchange-database/preflight.h"
-#include "helper.h"
-
-enum GNUNET_GenericReturnValue
-TALER_TALER_EXCHANGEDB_start_read_only (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- const char *name)
-{
- struct GNUNET_PQ_ExecuteStatement es[] = {
- GNUNET_PQ_make_execute (
- "START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY"),
- GNUNET_PQ_EXECUTE_STATEMENT_END
- };
-
- GNUNET_assert (NULL != name);
- if (GNUNET_SYSERR ==
- TALER_EXCHANGEDB_preflight (pg))
- return GNUNET_SYSERR;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Starting READ ONLY transaction `%s`\n",
- name);
- if (GNUNET_OK !=
- GNUNET_PQ_exec_statements (pg->conn,
- es))
- {
- TALER_LOG_ERROR ("Failed to start transaction\n");
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- pg->transaction_name = name;
- return GNUNET_OK;
-}
diff --git a/src/exchangedb/pg_store_wire_transfer_out.c b/src/exchangedb/pg_store_wire_transfer_out.c
@@ -1,63 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_store_wire_transfer_out.c
- * @brief Implementation of the store_wire_transfer_out function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/store_wire_transfer_out.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_store_wire_transfer_out (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- struct GNUNET_TIME_Timestamp date,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- const struct TALER_FullPaytoHashP *h_payto,
- const char *exchange_account_section,
- const struct TALER_Amount *amount,
- const char *extra_wire_subject_metadata)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_timestamp (&date),
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_string (exchange_account_section),
- TALER_PQ_query_param_amount (pg->conn,
- amount),
- NULL == extra_wire_subject_metadata
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (extra_wire_subject_metadata),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "insert_wire_out",
- "INSERT INTO wire_out "
- "(execution_date"
- ",wtid_raw"
- ",wire_target_h_payto"
- ",exchange_account_section"
- ",amount"
- ",extra_wire_subject_metadata"
- ") VALUES "
- "($1, $2, $3, $4, $5, $6);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "insert_wire_out",
- params);
-}
diff --git a/src/exchangedb/pg_template.c b/src/exchangedb/pg_template.c
@@ -1,20 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_template.c
- * @brief Implementation of the template function for Postgres
- * @author Christian Grothoff
- */
diff --git a/src/exchangedb/pg_test_aml_officer.c b/src/exchangedb/pg_test_aml_officer.c
@@ -1,52 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_test_aml_officer.c
- * @brief Implementation of the test_aml_officer function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/test_aml_officer.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_test_aml_officer (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AmlOfficerPublicKeyP *decider_pub,
- bool *read_only)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (decider_pub),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_bool ("read_only",
- read_only),
- GNUNET_PQ_result_spec_end
- };
-
- PREPARE (pg,
- "test_aml_staff",
- "SELECT read_only"
- " FROM aml_staff"
- " WHERE decider_pub=$1"
- " AND is_active;");
- return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "test_aml_staff",
- params,
- rs);
-}
diff --git a/src/exchangedb/pg_trigger_kyc_rule_for_account.c b/src/exchangedb/pg_trigger_kyc_rule_for_account.c
@@ -1,98 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_trigger_kyc_rule_for_account.c
- * @brief Implementation of the trigger_kyc_rule_for_account function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/trigger_kyc_rule_for_account.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_trigger_kyc_rule_for_account (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPayto payto_uri,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const union TALER_AccountPublicKeyP *set_account_pub,
- const struct TALER_MerchantPublicKeyP *check_merchant_pub,
- const json_t *jmeasures,
- uint32_t display_priority,
- uint64_t *requirement_row,
- bool *bad_kyc_auth)
-{
- struct GNUNET_TIME_Absolute now
- = GNUNET_TIME_absolute_get ();
- struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = *h_payto
- };
- char *notify_str
- = GNUNET_PQ_get_event_notify_channel (&rep.header);
- struct TALER_FullPaytoHashP h_full_payto;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- NULL == set_account_pub
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (set_account_pub),
- NULL == check_merchant_pub
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (check_merchant_pub),
- NULL == payto_uri.full_payto
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (payto_uri.full_payto),
- NULL == payto_uri.full_payto
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (&h_full_payto),
- GNUNET_PQ_query_param_absolute_time (&now),
- TALER_PQ_query_param_json (jmeasures),
- GNUNET_PQ_query_param_uint32 (&display_priority),
- GNUNET_PQ_query_param_string (notify_str),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 (
- "legitimization_measure_serial_id",
- requirement_row),
- GNUNET_PQ_result_spec_bool (
- "bad_kyc_auth",
- bad_kyc_auth),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "trigger_kyc_rule_for_account",
- "SELECT"
- " out_legitimization_measure_serial_id"
- " AS legitimization_measure_serial_id"
- " ,out_bad_kyc_auth"
- " AS bad_kyc_auth"
- " FROM exchange_do_trigger_kyc_rule_for_account"
- "($1, $2, $3, $4, $5, $6, $7::TEXT::JSONB, $8, $9);");
- if (NULL != payto_uri.full_payto)
- TALER_full_payto_hash (payto_uri,
- &h_full_payto);
- qs = GNUNET_PQ_eval_prepared_singleton_select (
- pg->conn,
- "trigger_kyc_rule_for_account",
- params,
- rs);
- GNUNET_free (notify_str);
- return qs;
-}
diff --git a/src/exchangedb/pg_update_aggregation_transient.c b/src/exchangedb/pg_update_aggregation_transient.c
@@ -1,54 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_update_aggregation_transient.c
- * @brief Implementation of the update_aggregation_transient function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/update_aggregation_transient.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_update_aggregation_transient (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPaytoHashP *h_payto,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- uint64_t kyc_requirement_row,
- const struct TALER_Amount *total)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- TALER_PQ_query_param_amount (pg->conn,
- total),
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_auto_from_type (wtid),
- GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "update_aggregation_transient",
- "UPDATE aggregation_transient"
- " SET amount=$1"
- " ,legitimization_requirement_serial_id=$4"
- " WHERE wire_target_h_payto=$2"
- " AND wtid_raw=$3");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "update_aggregation_transient",
- params);
-}
diff --git a/src/exchangedb/pg_update_auditor.c b/src/exchangedb/pg_update_auditor.c
@@ -1,56 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_update_auditor.c
- * @brief Implementation of the update_auditor function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/update_auditor.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_update_auditor (struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_AuditorPublicKeyP *
- auditor_pub,
- const char *auditor_url,
- const char *auditor_name,
- struct GNUNET_TIME_Timestamp change_date,
- bool enabled)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (auditor_pub),
- GNUNET_PQ_query_param_string (auditor_url),
- GNUNET_PQ_query_param_string (auditor_name),
- GNUNET_PQ_query_param_bool (enabled),
- GNUNET_PQ_query_param_timestamp (&change_date),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "update_auditor",
- "UPDATE auditors"
- " SET"
- " auditor_url=$2"
- " ,auditor_name=$3"
- " ,is_active=$4"
- " ,last_change=$5"
- " WHERE auditor_pub=$1");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "update_auditor",
- params);
-}
diff --git a/src/exchangedb/pg_update_kyc_process_by_row.c b/src/exchangedb/pg_update_kyc_process_by_row.c
@@ -1,131 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_update_kyc_process_by_row.c
- * @brief Implementation of the update_kyc_process_by_row function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_error_codes.h"
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/update_kyc_process_by_row.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_update_kyc_process_by_row (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t process_row,
- const char *provider_name,
- const struct TALER_NormalizedPaytoHashP *h_payto,
- const char *provider_account_id,
- const char *provider_legitimization_id,
- const char *redirect_url,
- struct GNUNET_TIME_Absolute expiration,
- enum TALER_ErrorCode ec,
- const char *error_message_hint,
- bool finished)
-{
- uint32_t ec32 = (uint32_t) ec;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&process_row),
- GNUNET_PQ_query_param_string (provider_name),
- GNUNET_PQ_query_param_auto_from_type (h_payto), /*3*/
- (NULL != provider_account_id)
- ? GNUNET_PQ_query_param_string (provider_account_id)
- : GNUNET_PQ_query_param_null (), /*4*/
- (NULL != provider_legitimization_id)
- ? GNUNET_PQ_query_param_string (provider_legitimization_id)
- : GNUNET_PQ_query_param_null (), /*5*/
- (NULL != redirect_url)
- ? GNUNET_PQ_query_param_string (redirect_url)
- : GNUNET_PQ_query_param_null (), /*6*/
- GNUNET_PQ_query_param_absolute_time (&expiration),
- GNUNET_PQ_query_param_uint32 (&ec32), /* 8 */
- (NULL != error_message_hint)
- ? GNUNET_PQ_query_param_string (error_message_hint)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_bool (finished), /* 10 */
- GNUNET_PQ_query_param_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Updating KYC data for %llu (%s)\n",
- (unsigned long long) process_row,
- provider_name);
- PREPARE (pg,
- "update_legitimization_process",
- "UPDATE legitimization_processes"
- " SET provider_user_id=$4"
- " ,provider_legitimization_id=$5"
- " ,redirect_url=$6"
- " ,expiration_time=GREATEST(expiration_time,$7)"
- " ,error_code=$8"
- " ,error_message=$9"
- " ,finished=$10"
- " WHERE"
- " h_payto=$3"
- " AND legitimization_process_serial_id=$1"
- " AND provider_name=$2;");
- qs = GNUNET_PQ_eval_prepared_non_select (
- pg->conn,
- "update_legitimization_process",
- params);
- if (qs <= 0)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to update legitimization process %llu: %d\n",
- (unsigned long long) process_row,
- qs);
- return qs;
- }
- if (GNUNET_TIME_absolute_is_future (expiration))
- {
- enum GNUNET_DB_QueryStatus qs2;
- struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
- .h_payto = *h_payto
- };
- uint32_t trigger_type = 1;
- struct GNUNET_PQ_QueryParam params2[] = {
- GNUNET_PQ_query_param_auto_from_type (h_payto),
- GNUNET_PQ_query_param_uint32 (&trigger_type),
- GNUNET_PQ_query_param_end
- };
-
- GNUNET_PQ_event_notify (pg->conn,
- &rep.header,
- NULL,
- 0);
- PREPARE (pg,
- "alert_kyc_status_change",
- "INSERT INTO kyc_alerts"
- " (h_payto"
- " ,trigger_type)"
- " VALUES"
- " ($1,$2);");
- qs2 = GNUNET_PQ_eval_prepared_non_select (
- pg->conn,
- "alert_kyc_status_change",
- params2);
- if (qs2 < 0)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to store KYC alert: %d\n",
- qs2);
- }
- return qs;
-}
diff --git a/src/exchangedb/pg_update_wire.c b/src/exchangedb/pg_update_wire.c
@@ -1,88 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022, 2023, 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_update_wire.c
- * @brief Implementation of the update_wire function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/update_wire.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_update_wire (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_FullPayto payto_uri,
- const char *conversion_url,
- const char *open_banking_gateway,
- const char *wire_transfer_gateway,
- const json_t *debit_restrictions,
- const json_t *credit_restrictions,
- struct GNUNET_TIME_Timestamp change_date,
- const struct TALER_MasterSignatureP *master_sig,
- const char *bank_label,
- int64_t priority,
- bool enabled)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (payto_uri.full_payto),
- GNUNET_PQ_query_param_bool (enabled),
- NULL == conversion_url
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (conversion_url),
- enabled
- ? TALER_PQ_query_param_json (debit_restrictions)
- : GNUNET_PQ_query_param_null (),
- enabled
- ? TALER_PQ_query_param_json (credit_restrictions)
- : GNUNET_PQ_query_param_null (),
- GNUNET_PQ_query_param_timestamp (&change_date),
- NULL == master_sig
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_auto_from_type (master_sig),
- NULL == bank_label
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (bank_label),
- GNUNET_PQ_query_param_int64 (&priority),
- NULL == open_banking_gateway
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (open_banking_gateway),
- NULL == wire_transfer_gateway
- ? GNUNET_PQ_query_param_null ()
- : GNUNET_PQ_query_param_string (wire_transfer_gateway),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "update_wire",
- "UPDATE wire_accounts"
- " SET"
- " is_active=$2"
- " ,conversion_url=$3"
- " ,debit_restrictions=$4::TEXT::JSONB"
- " ,credit_restrictions=$5::TEXT::JSONB"
- " ,last_change=$6"
- " ,master_sig=$7"
- " ,bank_label=$8"
- " ,priority=$9"
- " ,open_banking_gateway=$10"
- " ,wire_transfer_gateway=$11"
- " WHERE payto_uri=$1");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "update_wire",
- params);
-}
diff --git a/src/exchangedb/pg_wad_in_insert.c b/src/exchangedb/pg_wad_in_insert.c
@@ -1,58 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_wad_in_insert.c
- * @brief Implementation of the wad_in_insert function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/wad_in_insert.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_wad_in_insert (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- const struct TALER_WadIdentifierP *wad_id,
- const char *origin_exchange_url,
- const struct TALER_Amount *amount,
- struct GNUNET_TIME_Timestamp execution_date,
- const struct TALER_FullPayto debit_account_uri,
- const char *section_name,
- uint64_t serial_id)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (wad_id),
- GNUNET_PQ_query_param_string (origin_exchange_url),
- TALER_PQ_query_param_amount (pg->conn,
- amount),
- GNUNET_PQ_query_param_timestamp (&execution_date),
- GNUNET_PQ_query_param_end
- };
-
- // FIXME-#7271: should we keep the account data + serial_id?
- PREPARE (pg,
- "wad_in_insert",
- "INSERT INTO wads_in "
- "(wad_id"
- ",origin_exchange_url"
- ",amount"
- ",arrival_time"
- ") VALUES "
- "($1, $2, $3, $4);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "wad_in_insert",
- params);
-}
diff --git a/src/exchangedb/pg_wire_prepare_data_get.c b/src/exchangedb/pg_wire_prepare_data_get.c
@@ -1,138 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_wire_prepare_data_get.c
- * @brief Implementation of the wire_prepare_data_get function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/wire_prepare_data_get.h"
-#include "helper.h"
-
-/**
- * Closure for #prewire_cb().
- */
-struct PrewireContext
-{
- /**
- * Function to call on each result.
- */
- TALER_EXCHANGEDB_WirePreparationIterator cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * #GNUNET_OK if everything went fine.
- */
- enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct MissingWireContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-prewire_cb (void *cls,
- PGresult *result,
- unsigned int num_results)
-{
- struct PrewireContext *pc = cls;
-
- for (unsigned int i = 0; i < num_results; i++)
- {
- uint64_t prewire_uuid;
- char *wire_method;
- void *buf = NULL;
- size_t buf_size;
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("prewire_uuid",
- &prewire_uuid),
- GNUNET_PQ_result_spec_string ("wire_method",
- &wire_method),
- GNUNET_PQ_result_spec_variable_size ("buf",
- &buf,
- &buf_size),
- GNUNET_PQ_result_spec_end
- };
-
- if (GNUNET_OK !=
- GNUNET_PQ_extract_result (result,
- rs,
- i))
- {
- GNUNET_break (0);
- pc->status = GNUNET_SYSERR;
- return;
- }
- pc->cb (pc->cb_cls,
- prewire_uuid,
- wire_method,
- buf,
- buf_size);
- GNUNET_PQ_cleanup_result (rs);
- }
-}
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_wire_prepare_data_get (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t start_row,
- uint64_t limit,
- TALER_EXCHANGEDB_WirePreparationIterator
- cb,
- void *cb_cls)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&start_row),
- GNUNET_PQ_query_param_uint64 (&limit),
- GNUNET_PQ_query_param_end
- };
- struct PrewireContext pc = {
- .cb = cb,
- .cb_cls = cb_cls,
- .status = GNUNET_OK
- };
- enum GNUNET_DB_QueryStatus qs;
-
- PREPARE (pg,
- "wire_prepare_data_get",
- "SELECT"
- " prewire_uuid"
- ",wire_method"
- ",buf"
- " FROM prewire"
- " WHERE prewire_uuid >= $1"
- " AND finished=FALSE"
- " AND failed=FALSE"
- " ORDER BY prewire_uuid ASC"
- " LIMIT $2;");
- qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
- "wire_prepare_data_get",
- params,
- &prewire_cb,
- &pc);
- if (GNUNET_OK != pc.status)
- return GNUNET_DB_STATUS_HARD_ERROR;
- return qs;
-}
diff --git a/src/exchangedb/pg_wire_prepare_data_insert.c b/src/exchangedb/pg_wire_prepare_data_insert.c
@@ -1,51 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_wire_prepare_data_insert.c
- * @brief Implementation of the wire_prepare_data_insert function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/wire_prepare_data_insert.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_wire_prepare_data_insert (struct
- TALER_EXCHANGEDB_PostgresContext *pg,
- const char *type,
- const char *buf,
- size_t buf_size)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_string (type),
- GNUNET_PQ_query_param_fixed_size (buf, buf_size),
- GNUNET_PQ_query_param_end
- };
-
-
- /* Used in #postgres_wire_prepare_data_insert() to store
- wire transfer information before actually committing it with the bank */
- PREPARE (pg,
- "wire_prepare_data_insert",
- "INSERT INTO prewire "
- "(wire_method"
- ",buf"
- ") VALUES "
- "($1, $2);");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "wire_prepare_data_insert",
- params);
-}
diff --git a/src/exchangedb/pg_wire_prepare_data_mark_failed.c b/src/exchangedb/pg_wire_prepare_data_mark_failed.c
@@ -1,44 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_wire_prepare_data_mark_failed.c
- * @brief Implementation of the wire_prepare_data_mark_failed function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/wire_prepare_data_mark_failed.h"
-#include "helper.h"
-
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_wire_prepare_data_mark_failed (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t rowid)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&rowid),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "wire_prepare_data_mark_failed",
- "UPDATE prewire"
- " SET failed=TRUE"
- " WHERE prewire_uuid=$1;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "wire_prepare_data_mark_failed",
- params);
-}
diff --git a/src/exchangedb/pg_wire_prepare_data_mark_finished.c b/src/exchangedb/pg_wire_prepare_data_mark_finished.c
@@ -1,43 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_wire_prepare_data_mark_finished.c
- * @brief Implementation of the wire_prepare_data_mark_finished function for Postgres
- * @author Christian Grothoff
- */
-#include "taler/taler_pq_lib.h"
-#include "taler/exchange-database/wire_prepare_data_mark_finished.h"
-#include "helper.h"
-
-enum GNUNET_DB_QueryStatus
-TALER_EXCHANGEDB_wire_prepare_data_mark_finished (
- struct TALER_EXCHANGEDB_PostgresContext *pg,
- uint64_t rowid)
-{
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_uint64 (&rowid),
- GNUNET_PQ_query_param_end
- };
-
- PREPARE (pg,
- "wire_prepare_data_mark_done",
- "UPDATE prewire"
- " SET finished=TRUE"
- " WHERE prewire_uuid=$1;");
- return GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "wire_prepare_data_mark_done",
- params);
-}
diff --git a/src/exchangedb/preflight.c b/src/exchangedb/preflight.c
@@ -0,0 +1,111 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/preflight.c
+ * @brief Implementation of the preflight function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/preflight.h"
+#include "helper.h"
+
+
+static enum GNUNET_GenericReturnValue
+internal_setup (struct TALER_EXCHANGEDB_PostgresContext *pg)
+{
+ if (NULL == pg->conn)
+ {
+#if AUTO_EXPLAIN
+ /* Enable verbose logging to see where queries do not
+ properly use indices */
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_try_execute ("LOAD 'auto_explain';"),
+ GNUNET_PQ_make_try_execute ("SET auto_explain.log_min_duration=50;"),
+ GNUNET_PQ_make_try_execute ("SET auto_explain.log_timing=TRUE;"),
+ GNUNET_PQ_make_try_execute ("SET auto_explain.log_analyze=TRUE;"),
+ /* https://wiki.postgresql.org/wiki/Serializable suggests to really
+ force the default to 'serializable' if SSI is to be used. */
+ GNUNET_PQ_make_try_execute (
+ "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
+ GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"),
+ GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
+ GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
+ /* Mergejoin causes issues, see Postgres #18380 */
+ GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+#else
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_try_execute (
+ "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"),
+ GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"),
+ GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"),
+ /* Mergejoin causes issues, see Postgres #18380 */
+ GNUNET_PQ_make_try_execute ("SET enable_mergejoin=OFF;"),
+ GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+#endif
+ struct GNUNET_PQ_Context *db_conn;
+
+ db_conn = GNUNET_PQ_connect_with_cfg2 (pg->cfg,
+ "exchangedb-postgres",
+ "exchange-", /* load_path_suffix */
+ es,
+ NULL /* prepared statements */,
+ GNUNET_PQ_FLAG_CHECK_CURRENT);
+ if (NULL == db_conn)
+ return GNUNET_SYSERR;
+
+ pg->prep_gen++;
+ pg->conn = db_conn;
+ }
+ if (NULL == pg->transaction_name)
+ GNUNET_PQ_reconnect_if_down (pg->conn);
+ return GNUNET_OK;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGEDB_preflight (struct TALER_EXCHANGEDB_PostgresContext *pg)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("ROLLBACK"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ if (GNUNET_OK !=
+ internal_setup (pg))
+ return GNUNET_SYSERR;
+ if (NULL == pg->transaction_name)
+ return GNUNET_OK; /* all good */
+ if (GNUNET_OK ==
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "BUG: Preflight check rolled back transaction `%s'!\n",
+ pg->transaction_name);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "BUG: Preflight check failed to rollback transaction `%s'!\n",
+ pg->transaction_name);
+ }
+ pg->transaction_name = NULL;
+ return GNUNET_NO;
+}
diff --git a/src/exchangedb/profit_drains_get_pending.c b/src/exchangedb/profit_drains_get_pending.c
@@ -0,0 +1,75 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/profit_drains_get_pending.c
+ * @brief Implementation of the profit_drains_get_pending function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/profit_drains_get_pending.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_profit_drains_get_pending (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t *serial,
+ struct TALER_WireTransferIdentifierRawP *wtid,
+ char **account_section,
+ struct TALER_FullPayto *payto_uri,
+ struct GNUNET_TIME_Timestamp *request_timestamp,
+ struct TALER_Amount *amount,
+ struct TALER_MasterSignatureP *master_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("profit_drain_serial_id",
+ serial),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid",
+ wtid),
+ GNUNET_PQ_result_spec_string ("account_section",
+ account_section),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri->full_payto),
+ GNUNET_PQ_result_spec_timestamp ("trigger_date",
+ request_timestamp),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ amount),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ master_sig),
+ GNUNET_PQ_result_spec_end
+ };
+ /* Used in #postgres_profit_drains_get_pending() */
+ PREPARE (pg,
+ "get_ready_profit_drain",
+ "SELECT"
+ " profit_drain_serial_id"
+ ",wtid"
+ ",account_section"
+ ",payto_uri"
+ ",trigger_date"
+ ",amount"
+ ",master_sig"
+ " FROM profit_drains"
+ " WHERE NOT executed"
+ " ORDER BY trigger_date ASC;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "get_ready_profit_drain",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/profit_drains_set_finished.c b/src/exchangedb/profit_drains_set_finished.c
@@ -0,0 +1,45 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/profit_drains_set_finished.c
+ * @brief Implementation of the profit_drains_set_finished function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/profit_drains_set_finished.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_profit_drains_set_finished (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "drain_profit_set_finished",
+ "UPDATE profit_drains"
+ " SET"
+ " executed=TRUE"
+ " WHERE profit_drain_serial_id=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "drain_profit_set_finished",
+ params);
+}
diff --git a/src/exchangedb/release_revolving_shard.c b/src/exchangedb/release_revolving_shard.c
@@ -0,0 +1,56 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/release_revolving_shard.c
+ * @brief Implementation of the release_revolving_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/release_revolving_shard.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_release_revolving_shard (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *job_name,
+ uint32_t start_row,
+ uint32_t end_row)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (job_name),
+ GNUNET_PQ_query_param_uint32 (&start_row),
+ GNUNET_PQ_query_param_uint32 (&end_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Releasing revolving shard %s %u-%u\n",
+ job_name,
+ (unsigned int) start_row,
+ (unsigned int) end_row);
+
+
+ PREPARE (pg,
+ "release_revolving_shard",
+ "UPDATE revolving_work_shards"
+ " SET active=FALSE"
+ " WHERE job_name=$1"
+ " AND start_row=$2"
+ " AND end_row=$3");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "release_revolving_shard",
+ params);
+}
diff --git a/src/exchangedb/reserves_get.c b/src/exchangedb/reserves_get.c
@@ -0,0 +1,57 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/reserves_get.c
+ * @brief Implementation of the reserves_get function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/reserves_get.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_reserves_get (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct TALER_EXCHANGEDB_Reserve *reserve)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&reserve->pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_amount ("current_balance",
+ pg->currency,
+ &reserve->balance),
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ &reserve->expiry),
+ GNUNET_PQ_result_spec_timestamp ("gc_date",
+ &reserve->gc),
+ GNUNET_PQ_result_spec_end
+ };
+ /* Used in #postgres_reserves_get() */
+ PREPARE (pg,
+ "reserves_get",
+ "SELECT"
+ " current_balance"
+ ",expiration_date"
+ ",gc_date"
+ " FROM reserves"
+ " WHERE reserve_pub=$1"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "reserves_get",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/reserves_get_origin.c b/src/exchangedb/reserves_get_origin.c
@@ -0,0 +1,61 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/reserves_get_origin.c
+ * @brief Implementation of the reserves_get_origin function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/reserves_get_origin.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_reserves_get_origin (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ struct TALER_FullPaytoHashP *h_payto,
+ struct TALER_FullPayto *payto_uri)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type (
+ "wire_source_h_payto",
+ h_payto),
+ GNUNET_PQ_result_spec_string (
+ "payto_uri",
+ &payto_uri->full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "get_h_wire_source_of_reserve",
+ "SELECT"
+ " rt.wire_source_h_payto"
+ ",wt.payto_uri"
+ " FROM reserves_in rt"
+ " JOIN wire_targets wt"
+ " ON (rt.wire_source_h_payto = wt.wire_target_h_payto)"
+ " WHERE rt.reserve_pub=$1");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "get_h_wire_source_of_reserve",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/reserves_in_insert.c b/src/exchangedb/reserves_in_insert.c
@@ -0,0 +1,374 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/reserves_in_insert.c
+ * @brief Implementation of the reserves_in_insert function for Postgres
+ * @author Christian Grothoff
+ * @author Joseph Xu
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/reserves_in_insert.h"
+#include "helper.h"
+#include "taler/exchange-database/start.h"
+#include "taler/exchange-database/start_read_committed.h"
+#include "taler/exchange-database/commit.h"
+#include "taler/exchange-database/preflight.h"
+#include "taler/exchange-database/rollback.h"
+
+
+/**
+ * Generate event notification for the reserve change.
+ *
+ * @param reserve_pub reserve to notfiy on
+ * @return string to pass to postgres for the notification
+ */
+static char *
+compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
+{
+ struct TALER_EXCHANGEDB_ReserveEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING),
+ .reserve_pub = *reserve_pub
+ };
+
+ return GNUNET_PQ_get_event_notify_channel (&rep.header);
+}
+
+
+/**
+ * Closure for our helper_cb()
+ */
+struct Context
+{
+ /**
+ * Array of reserve UUIDs to initialize.
+ */
+ uint64_t *reserve_uuids;
+
+ /**
+ * Array with entries set to 'true' for duplicate transactions.
+ */
+ bool *transaction_duplicates;
+
+ /**
+ * Array with entries set to 'true' for rows with conflicts.
+ */
+ bool *conflicts;
+
+ /**
+ * Set to #GNUNET_SYSERR on failures.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+ /**
+ * Single value (no array) set to true if we need
+ * to follow-up with an update.
+ */
+ bool needs_update;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct Context *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct Context *ctx = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool (
+ "transaction_duplicate",
+ &ctx->transaction_duplicates[i]),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("ruuid",
+ &ctx->reserve_uuids[i]),
+ &ctx->conflicts[i]),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ if (! ctx->transaction_duplicates[i])
+ ctx->needs_update |= ctx->conflicts[i];
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_reserves_in_insert (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
+ unsigned int reserves_length,
+ enum GNUNET_DB_QueryStatus *results)
+{
+ unsigned int dups = 0;
+
+ struct TALER_FullPaytoHashP h_full_paytos[
+ GNUNET_NZL (reserves_length)];
+ struct TALER_NormalizedPaytoHashP h_normalized_paytos[
+ GNUNET_NZL (reserves_length)];
+ char *notify_s[GNUNET_NZL (reserves_length)];
+ struct TALER_ReservePublicKeyP reserve_pubs[GNUNET_NZL (reserves_length)];
+ struct TALER_Amount balances[GNUNET_NZL (reserves_length)];
+ struct GNUNET_TIME_Timestamp execution_times[GNUNET_NZL (reserves_length)];
+ const char *sender_account_details[GNUNET_NZL (reserves_length)];
+ const char *exchange_account_names[GNUNET_NZL (reserves_length)];
+ uint64_t wire_references[GNUNET_NZL (reserves_length)];
+ uint64_t reserve_uuids[GNUNET_NZL (reserves_length)];
+ bool transaction_duplicates[GNUNET_NZL (reserves_length)];
+ bool conflicts[GNUNET_NZL (reserves_length)];
+ struct GNUNET_TIME_Timestamp reserve_expiration
+ = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
+ struct GNUNET_TIME_Timestamp gc
+ = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
+ enum GNUNET_DB_QueryStatus qs;
+ bool need_update;
+
+ for (unsigned int i = 0; i<reserves_length; i++)
+ {
+ const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+
+ TALER_full_payto_hash (reserve->sender_account_details,
+ &h_full_paytos[i]);
+ TALER_full_payto_normalize_and_hash (reserve->sender_account_details,
+ &h_normalized_paytos[i]);
+ notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub);
+ reserve_pubs[i] = *reserve->reserve_pub;
+ balances[i] = *reserve->balance;
+ execution_times[i] = reserve->execution_time;
+ sender_account_details[i] = reserve->sender_account_details.full_payto;
+ exchange_account_names[i] = reserve->exchange_account_name;
+ wire_references[i] = reserve->wire_reference;
+ }
+
+ /* NOTE: kind-of pointless to explicitly start a transaction here... */
+ if (GNUNET_OK !=
+ TALER_EXCHANGEDB_preflight (pg))
+ {
+ GNUNET_break (0);
+ qs = GNUNET_DB_STATUS_HARD_ERROR;
+ goto finished;
+ }
+ if (GNUNET_OK !=
+ TALER_TALER_EXCHANGEDB_start_read_committed (pg,
+ "READ_COMMITED"))
+ {
+ GNUNET_break (0);
+ qs = GNUNET_DB_STATUS_HARD_ERROR;
+ goto finished;
+ }
+ PREPARE (pg,
+ "reserves_insert_with_array",
+ "SELECT"
+ " transaction_duplicate"
+ ",ruuid"
+ " FROM exchange_do_array_reserves_insert"
+ " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);");
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&gc),
+ GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+ GNUNET_PQ_query_param_array_auto_from_type (reserves_length,
+ reserve_pubs,
+ pg->conn),
+ GNUNET_PQ_query_param_array_uint64 (reserves_length,
+ wire_references,
+ pg->conn),
+ TALER_PQ_query_param_array_amount (
+ reserves_length,
+ balances,
+ pg->conn),
+ GNUNET_PQ_query_param_array_ptrs_string (
+ reserves_length,
+ (const char **) exchange_account_names,
+ pg->conn),
+ GNUNET_PQ_query_param_array_timestamp (
+ reserves_length,
+ execution_times,
+ pg->conn),
+ GNUNET_PQ_query_param_array_auto_from_type (
+ reserves_length,
+ h_full_paytos,
+ pg->conn),
+ GNUNET_PQ_query_param_array_auto_from_type (
+ reserves_length,
+ h_normalized_paytos,
+ pg->conn),
+ GNUNET_PQ_query_param_array_ptrs_string (
+ reserves_length,
+ (const char **) sender_account_details,
+ pg->conn),
+ GNUNET_PQ_query_param_array_ptrs_string (
+ reserves_length,
+ (const char **) notify_s,
+ pg->conn),
+ GNUNET_PQ_query_param_end
+ };
+ struct Context ctx = {
+ .reserve_uuids = reserve_uuids,
+ .transaction_duplicates = transaction_duplicates,
+ .conflicts = conflicts,
+ .needs_update = false,
+ .status = GNUNET_OK
+ };
+
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "reserves_insert_with_array",
+ params,
+ &helper_cb,
+ &ctx);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ if ( (qs < 0) ||
+ (GNUNET_OK != ctx.status) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to insert into reserves (%d)\n",
+ qs);
+ goto finished;
+ }
+ need_update = ctx.needs_update;
+ }
+
+ {
+ enum GNUNET_DB_QueryStatus cs;
+
+ cs = TALER_EXCHANGEDB_commit (pg);
+ if (cs < 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to commit\n");
+ qs = cs;
+ goto finished;
+ }
+ }
+
+ for (unsigned int i = 0; i<reserves_length; i++)
+ {
+ if (transaction_duplicates[i])
+ dups++;
+ results[i] = transaction_duplicates[i]
+ ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+ : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+
+ if (! need_update)
+ {
+ qs = reserves_length;
+ goto finished;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Reserve update needed for some reserves in the batch\n");
+ PREPARE (pg,
+ "reserves_update",
+ "SELECT"
+ " out_duplicate AS duplicate "
+ "FROM exchange_do_batch_reserves_update"
+ " ($1,$2,$3,$4,$5,$6,$7);");
+
+ if (GNUNET_OK !=
+ TALER_EXCHANGEDB_start (pg,
+ "reserve-insert-continued"))
+ {
+ GNUNET_break (0);
+ qs = GNUNET_DB_STATUS_HARD_ERROR;
+ goto finished;
+ }
+
+ for (unsigned int i = 0; i<reserves_length; i++)
+ {
+ if (transaction_duplicates[i])
+ continue;
+ if (! conflicts[i])
+ continue;
+ {
+ bool duplicate;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&reserve_pubs[i]),
+ GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+ GNUNET_PQ_query_param_uint64 (&wire_references[i]),
+ TALER_PQ_query_param_amount (pg->conn,
+ &balances[i]),
+ GNUNET_PQ_query_param_string (exchange_account_names[i]),
+ GNUNET_PQ_query_param_auto_from_type (&h_full_paytos[i]),
+ GNUNET_PQ_query_param_string (notify_s[i]),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("duplicate",
+ &duplicate),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qsi;
+
+ qsi = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "reserves_update",
+ params,
+ rs);
+ if (qsi < 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to update reserves (%d)\n",
+ qsi);
+ results[i] = qsi;
+ goto finished;
+ }
+ results[i] = duplicate
+ ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+ : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ }
+ {
+ enum GNUNET_DB_QueryStatus cs;
+
+ cs = TALER_EXCHANGEDB_commit (pg);
+ if (cs < 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to commit\n");
+ qs = cs;
+ goto finished;
+ }
+ }
+finished:
+ for (unsigned int i = 0; i<reserves_length; i++)
+ GNUNET_free (notify_s[i]);
+ if (qs < 0)
+ return qs;
+ GNUNET_PQ_event_do_poll (pg->conn);
+ if (0 != dups)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "%u/%u duplicates among incoming transactions. Try increasing WIREWATCH_IDLE_SLEEP_INTERVAL in the [exchange] configuration section (if this happens a lot).\n",
+ dups,
+ reserves_length);
+ return qs;
+}
diff --git a/src/exchangedb/reserves_update.c b/src/exchangedb/reserves_update.c
@@ -0,0 +1,50 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/reserves_update.c
+ * @brief Implementation of the reserves_update function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/reserves_update.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_reserves_update (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_EXCHANGEDB_Reserve *reserve
+ )
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&reserve->expiry),
+ GNUNET_PQ_query_param_timestamp (&reserve->gc),
+ TALER_PQ_query_param_amount (pg->conn,
+ &reserve->balance),
+ GNUNET_PQ_query_param_auto_from_type (&reserve->pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "reserve_update",
+ "UPDATE reserves"
+ " SET"
+ " expiration_date=$1"
+ ",gc_date=$2"
+ ",current_balance=$3"
+ " WHERE reserve_pub=$4;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "reserve_update",
+ params);
+}
diff --git a/src/exchangedb/rollback.c b/src/exchangedb/rollback.c
@@ -0,0 +1,45 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/rollback.c
+ * @brief Implementation of the rollback function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/exchange-database/rollback.h"
+#include "helper.h"
+
+
+void
+TALER_EXCHANGEDB_rollback (struct TALER_EXCHANGEDB_PostgresContext *pg)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("ROLLBACK"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ if (NULL == pg->transaction_name)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Skipping rollback, no transaction active\n");
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Rolling back transaction\n");
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_PQ_exec_statements (pg->conn,
+ es));
+ pg->transaction_name = NULL;
+}
diff --git a/src/exchangedb/select_account_merges_above_serial_id.c b/src/exchangedb/select_account_merges_above_serial_id.c
@@ -0,0 +1,188 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_account_merges_above_serial_id.c
+ * @brief Implementation of the select_account_merges_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_account_merges_above_serial_id.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #account_merge_serial_helper_cb().
+ */
+struct AccountMergeSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_AccountMergeCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct AccountMergeSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+account_merge_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AccountMergeSerialContext *dsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_PrivateContractHashP h_contract_terms;
+ struct GNUNET_TIME_Timestamp purse_expiration;
+ struct TALER_Amount amount;
+ uint32_t min_age;
+ uint32_t flags32;
+ enum TALER_WalletAccountMergeFlags flags;
+ struct TALER_Amount purse_fee;
+ struct GNUNET_TIME_Timestamp merge_timestamp;
+ struct TALER_ReserveSignatureP reserve_sig;
+ uint64_t rowid;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
+ &purse_fee),
+ GNUNET_PQ_result_spec_uint32 ("flags",
+ &flags32),
+ GNUNET_PQ_result_spec_uint32 ("age_limit",
+ &min_age),
+ GNUNET_PQ_result_spec_timestamp ("purse_expiration",
+ &purse_expiration),
+ GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
+ &merge_timestamp),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &h_contract_terms),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ &reserve_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ GNUNET_PQ_result_spec_uint64 ("account_merge_request_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ flags = (enum TALER_WalletAccountMergeFlags) flags32;
+ ret = dsc->cb (dsc->cb_cls,
+ rowid,
+ &reserve_pub,
+ &purse_pub,
+ &h_contract_terms,
+ purse_expiration,
+ &amount,
+ min_age,
+ flags,
+ &purse_fee,
+ merge_timestamp,
+ &reserve_sig);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_account_merges_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_AccountMergeCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct AccountMergeSerialContext dsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "audit_get_account_merge_incr",
+ "SELECT"
+ " am.account_merge_request_serial_id"
+ ",am.reserve_pub"
+ ",am.purse_pub"
+ ",pr.h_contract_terms"
+ ",pr.purse_expiration"
+ ",pr.amount_with_fee"
+ ",pr.age_limit"
+ ",pr.flags"
+ ",pr.purse_fee"
+ ",pm.merge_timestamp"
+ ",am.reserve_sig"
+ " FROM account_merges am"
+ " JOIN purse_requests pr USING (purse_pub)"
+ " JOIN purse_merges pm USING (purse_pub)"
+ " WHERE ("
+ " (account_merge_request_serial_id>=$1)"
+ " )"
+ " ORDER BY account_merge_request_serial_id ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "audit_get_account_merge_incr",
+ params,
+ &account_merge_serial_helper_cb,
+ &dsc);
+ if (GNUNET_OK != dsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_aggregation_amounts_for_kyc_check.c b/src/exchangedb/select_aggregation_amounts_for_kyc_check.c
@@ -0,0 +1,154 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_aggregation_amounts_for_kyc_check.c
+ * @brief Implementation of the select_aggregation_amounts_for_kyc_check function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_aggregation_amounts_for_kyc_check.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #get_kyc_amounts_cb().
+ */
+struct KycAmountCheckContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_KYCLOGIC_KycAmountCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Flag set to #GNUNET_OK as long as everything is fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct KycAmountCheckContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_kyc_amounts_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycAmountCheckContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct GNUNET_TIME_Absolute date;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_absolute_time ("date",
+ &date),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = ctx->cb (ctx->cb_cls,
+ &amount,
+ date);
+ GNUNET_PQ_cleanup_result (rs);
+ switch (ret)
+ {
+ case GNUNET_OK:
+ continue;
+ case GNUNET_NO:
+ break;
+ case GNUNET_SYSERR:
+ ctx->status = GNUNET_SYSERR;
+ break;
+ }
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_aggregation_amounts_for_kyc_check (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_KYCLOGIC_KycAmountCallback kac,
+ void *kac_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_absolute_time (&time_limit),
+ GNUNET_PQ_query_param_end
+ };
+ struct KycAmountCheckContext ctx = {
+ .cb = kac,
+ .cb_cls = kac_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_kyc_relevant_aggregation_events",
+ "SELECT"
+ " amount"
+ ",execution_date AS date"
+ " FROM wire_out"
+ " WHERE wire_target_h_payto IN"
+ " (SELECT wire_target_h_payto"
+ " FROM wire_targets"
+ " WHERE h_normalized_payto=$1"
+ " )"
+ " AND execution_date >= $2"
+ " ORDER BY execution_date DESC");
+
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_kyc_relevant_aggregation_events",
+ params,
+ &get_kyc_amounts_cb,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_aggregation_transient.c b/src/exchangedb/select_aggregation_transient.c
@@ -0,0 +1,63 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_aggregation_transient.c
+ * @brief Implementation of the select_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_aggregation_transient.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_aggregation_transient (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPaytoHashP *h_payto,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const char *exchange_account_section,
+ struct TALER_WireTransferIdentifierRawP *wtid,
+ struct TALER_Amount *total)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+ GNUNET_PQ_query_param_string (exchange_account_section),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ total),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+ wtid),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "select_aggregation_transient",
+ "SELECT"
+ " amount"
+ " ,wtid_raw"
+ " FROM aggregation_transient"
+ " WHERE wire_target_h_payto=$1"
+ " AND merchant_pub=$2"
+ " AND exchange_account_section=$3;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "select_aggregation_transient",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/select_aggregations_above_serial.c b/src/exchangedb/select_aggregations_above_serial.c
@@ -0,0 +1,137 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2023, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_aggregations_above_serial.c
+ * @brief Implementation of the select_aggregations_above_serial function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_aggregations_above_serial.h"
+#include "helper.h"
+
+/**
+ * Closure for #aggregation_serial_helper_cb().
+ */
+struct AggregationSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_AggregationCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct AggregationSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+aggregation_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AggregationSerialContext *dsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t tracking_rowid;
+ uint64_t batch_deposit_serial_id;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount",
+ &amount),
+ GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id",
+ &tracking_rowid),
+ GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id",
+ &batch_deposit_serial_id),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ dsc->cb (dsc->cb_cls,
+ &amount,
+ tracking_rowid,
+ batch_deposit_serial_id);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_aggregations_above_serial (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t min_tracking_serial_id,
+ TALER_EXCHANGEDB_AggregationCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&min_tracking_serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct AggregationSerialContext asc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Fetch aggregations with rowid '\geq' the given parameter */
+ PREPARE (pg,
+ "select_aggregations_above_serial",
+ "SELECT"
+ " aggregation_serial_id"
+ ",batch_deposit_serial_id"
+ ",total_amount"
+ " FROM exchange_do_select_aggregations_above_serial($1);");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "select_aggregations_above_serial",
+ params,
+ &aggregation_serial_helper_cb,
+ &asc);
+ if (GNUNET_OK != asc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_all_kyc_attributes.c b/src/exchangedb/select_all_kyc_attributes.c
@@ -0,0 +1,168 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_all_kyc_attributes.c
+ * @brief Implementation of the select_all_kyc_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_all_kyc_attributes.h"
+#include "helper.h"
+
+/**
+ * Closure for #get_all_attributes_cb().
+ */
+struct GetAttributesContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_AllAttributesCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Flag set to #GNUNET_OK as long as everything is fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+};
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct GetAttributesContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_attributes_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GetAttributesContext *ctx = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t rowid;
+ struct GNUNET_TIME_Timestamp collection_time;
+ struct GNUNET_TIME_Timestamp expiration_time;
+ struct TALER_NormalizedPaytoHashP h_payto;
+ json_t *properties = NULL;
+ size_t enc_attributes_size;
+ void *enc_attributes;
+ char *provider;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("provider_name",
+ &provider),
+ GNUNET_PQ_result_spec_uint64 ("kyc_attributes_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json ("jproperties",
+ &properties),
+ NULL),
+ GNUNET_PQ_result_spec_timestamp ("collection_time",
+ &collection_time),
+ GNUNET_PQ_result_spec_timestamp ("expiration_time",
+ &expiration_time),
+ GNUNET_PQ_result_spec_auto_from_type ("h_payto",
+ &h_payto),
+ GNUNET_PQ_result_spec_variable_size ("encrypted_attributes",
+ &enc_attributes,
+ &enc_attributes_size),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ rowid,
+ &h_payto,
+ provider,
+ collection_time,
+ expiration_time,
+ properties,
+ enc_attributes_size,
+ enc_attributes);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_all_kyc_attributes (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t min_row_id,
+ TALER_EXCHANGEDB_AllAttributesCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&min_row_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct GetAttributesContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_all_kyc_attributes",
+ "SELECT "
+ " lp.provider_name"
+ ",ka.h_payto"
+ ",ka.kyc_attributes_serial_id"
+ ",lo.jproperties::TEXT"
+ ",ka.collection_time"
+ ",ka.expiration_time"
+ ",ka.encrypted_attributes"
+ " FROM kyc_attributes ka"
+ " JOIN legitimization_processes lp"
+ " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)"
+ " LEFT JOIN legitimization_outcomes lo"
+ " ON (ka.h_payto = lo.h_payto)"
+ /* **IF** we joined with 'lo', the lo must be active */
+ " WHERE COALESCE(lo.is_active,TRUE)"
+ " AND kyc_attributes_serial_id > $1"
+ " ORDER BY kyc_attributes_serial_id ASC"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_all_kyc_attributes",
+ params,
+ &get_attributes_cb,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_all_purse_decisions_above_serial_id.c b/src/exchangedb/select_all_purse_decisions_above_serial_id.c
@@ -0,0 +1,142 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_all_purse_decisions_above_serial_id.c
+ * @brief Implementation of the select_all_purse_decisions_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_all_purse_decisions_above_serial_id.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #all_purse_decision_serial_helper_cb().
+ */
+struct AllPurseDecisionSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_AllPurseDecisionCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseRefundSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+all_purse_decision_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AllPurseDecisionSerialContext *dsc = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ bool refunded;
+ uint64_t rowid;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &purse_pub),
+ GNUNET_PQ_result_spec_bool ("refunded",
+ &refunded),
+ GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = dsc->cb (dsc->cb_cls,
+ rowid,
+ &purse_pub,
+ refunded);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_all_purse_decisions_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_AllPurseDecisionCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct AllPurseDecisionSerialContext dsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "audit_select_all_purse_decisions_above_serial_id",
+ "SELECT"
+ " purse_pub"
+ ",refunded"
+ ",purse_decision_serial_id"
+ " FROM purse_decision"
+ " WHERE purse_decision_serial_id>=$1"
+ " ORDER BY purse_decision_serial_id ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "audit_select_all_purse_decisions_above_serial_id",
+ params,
+ &all_purse_decision_serial_helper_cb,
+ &dsc);
+ if (GNUNET_OK != dsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_all_purse_deletions_above_serial_id.c b/src/exchangedb/select_all_purse_deletions_above_serial_id.c
@@ -0,0 +1,142 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_all_purse_deletions_above_serial_id.c
+ * @brief Implementation of the select_all_purse_deletions_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_all_purse_deletions_above_serial_id.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #all_purse_deletion_serial_helper_cb().
+ */
+struct AllPurseDeletionSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_AllPurseDeletionsCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseRefundSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+all_purse_deletion_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AllPurseDeletionSerialContext *dsc = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_PurseContractSignatureP purse_sig;
+ uint64_t rowid;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
+ &purse_sig),
+ GNUNET_PQ_result_spec_uint64 ("purse_deletion_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = dsc->cb (dsc->cb_cls,
+ rowid,
+ &purse_pub,
+ &purse_sig);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_all_purse_deletions_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_AllPurseDeletionsCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct AllPurseDeletionSerialContext dsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "audit_select_all_purse_deletions_above_serial_id",
+ "SELECT"
+ " purse_pub"
+ ",purse_sig"
+ ",purse_deletion_serial_id"
+ " FROM purse_deletion"
+ " WHERE purse_deletion_serial_id>=$1"
+ " ORDER BY purse_deletion_serial_id ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "audit_select_all_purse_deletions_above_serial_id",
+ params,
+ &all_purse_deletion_serial_helper_cb,
+ &dsc);
+ if (GNUNET_OK != dsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_aml_attributes.c b/src/exchangedb/select_aml_attributes.c
@@ -0,0 +1,189 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_aml_attributes.c
+ * @brief Implementation of the select_aml_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_aml_attributes.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #handle_aml_result.
+ */
+struct AmlAttributeResultContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_AmlAttributeCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on serious errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results. Helper function
+ * for #TALER_EXCHANGEDB_select_aml_attributes().
+ *
+ * @param cls closure of type `struct AmlAttributeResultContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_aml_attributes (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AmlAttributeResultContext *ctx = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct GNUNET_TIME_Timestamp collection_time;
+ char *officer_name = NULL;
+ bool by_aml_officer;
+ size_t enc_attributes_size;
+ void *enc_attributes;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("kyc_attributes_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_timestamp ("collection_time",
+ &collection_time),
+ GNUNET_PQ_result_spec_bool ("by_aml_officer",
+ &by_aml_officer),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("decider_name",
+ &officer_name),
+ NULL),
+ GNUNET_PQ_result_spec_variable_size ("encrypted_attributes",
+ &enc_attributes,
+ &enc_attributes_size),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+
+ ctx->cb (ctx->cb_cls,
+ rowid,
+ collection_time,
+ by_aml_officer,
+ officer_name,
+ enc_attributes_size,
+ enc_attributes);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_aml_attributes (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ uint64_t offset,
+ int64_t limit,
+ TALER_EXCHANGEDB_AmlAttributeCallback cb,
+ void *cb_cls)
+{
+ uint64_t ulimit = (limit > 0) ? limit : -limit;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct AmlAttributeResultContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ const char *stmt = (limit > 0)
+ ? "select_aml_attributes_inc"
+ : "select_aml_attributes_dec";
+
+ PREPARE (pg,
+ "select_aml_attributes_inc",
+ "SELECT"
+ " ka.kyc_attributes_serial_id"
+ ",ka.collection_time"
+ ",ka.by_aml_officer"
+ ",astaff.decider_name"
+ ",ka.encrypted_attributes"
+ " FROM kyc_attributes ka"
+ " LEFT JOIN legitimization_processes lp"
+ " ON (ka.by_aml_officer AND"
+ " (ka.legitimization_serial = lp.legitimization_process_serial_id))"
+ " LEFT JOIN aml_staff astaff"
+ " ON (ka.by_aml_officer AND"
+ " (DECODE(lp.provider_user_id, 'base64') = astaff.decider_pub))"
+ " WHERE ka.h_payto=$1"
+ " AND ka.kyc_attributes_serial_id > $2"
+ " ORDER BY ka.kyc_attributes_serial_id ASC"
+ " LIMIT $3");
+ PREPARE (pg,
+ "select_aml_attributes_dec",
+ "SELECT"
+ " ka.kyc_attributes_serial_id"
+ ",ka.collection_time"
+ ",ka.by_aml_officer"
+ ",astaff.decider_name"
+ ",ka.encrypted_attributes"
+ " FROM kyc_attributes ka"
+ " LEFT JOIN legitimization_processes lp"
+ " ON (ka.by_aml_officer AND"
+ " (ka.legitimization_serial = lp.legitimization_process_serial_id))"
+ " LEFT JOIN aml_staff astaff"
+ " ON (ka.by_aml_officer AND"
+ " (DECODE(lp.provider_user_id, 'base64') = astaff.decider_pub))"
+ " WHERE ka.h_payto=$1"
+ " AND ka.kyc_attributes_serial_id < $2"
+ " ORDER BY ka.kyc_attributes_serial_id DESC"
+ " LIMIT $3");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ stmt,
+ params,
+ &handle_aml_attributes,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_aml_decisions.c b/src/exchangedb/select_aml_decisions.c
@@ -0,0 +1,248 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_aml_decisions.c
+ * @brief Implementation of the select_aml_decisions function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_aml_decisions.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #handle_aml_result.
+ */
+struct AmlProcessResultContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_AmlDecisionCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on serious errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results. Helper function
+ * for #TALER_EXCHANGEDB_select_aml_decisions().
+ *
+ * @param cls closure of type `struct AmlProcessResultContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_aml_result (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AmlProcessResultContext *ctx = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_NormalizedPaytoHashP h_payto;
+ uint64_t rowid;
+ char *justification = NULL;
+ struct GNUNET_TIME_Timestamp decision_time;
+ struct GNUNET_TIME_Absolute expiration_time;
+ json_t *jproperties = NULL;
+ bool is_wallet;
+ bool to_investigate;
+ bool is_active;
+ json_t *account_rules;
+ struct TALER_FullPayto payto;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("outcome_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("h_payto",
+ &h_payto),
+ GNUNET_PQ_result_spec_bool ("is_wallet",
+ &is_wallet),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("justification",
+ &justification),
+ NULL),
+ GNUNET_PQ_result_spec_timestamp ("decision_time",
+ &decision_time),
+ GNUNET_PQ_result_spec_absolute_time ("expiration_time",
+ &expiration_time),
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_json ("jproperties",
+ &jproperties),
+ NULL),
+ TALER_PQ_result_spec_json ("jnew_rules",
+ &account_rules),
+ GNUNET_PQ_result_spec_bool ("to_investigate",
+ &to_investigate),
+ GNUNET_PQ_result_spec_bool ("is_active",
+ &is_active),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto.full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ if (GNUNET_TIME_absolute_is_past (expiration_time))
+ is_active = false;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Returning AML decisions for `%s' (%s)\n",
+ TALER_B2S (&h_payto),
+ is_wallet
+ ? "wallet"
+ : "account");
+ ctx->cb (ctx->cb_cls,
+ rowid,
+ justification,
+ &h_payto,
+ decision_time,
+ expiration_time,
+ jproperties,
+ to_investigate,
+ is_active,
+ is_wallet,
+ payto,
+ account_rules);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_aml_decisions (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ enum TALER_EXCHANGE_YesNoAll investigation_only,
+ enum TALER_EXCHANGE_YesNoAll active_only,
+ uint64_t offset,
+ int64_t limit,
+ TALER_EXCHANGEDB_AmlDecisionCallback cb,
+ void *cb_cls)
+{
+ uint64_t ulimit = (limit > 0) ? limit : -limit;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_bool (NULL == h_payto),
+ NULL == h_payto
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
+ investigation_only)),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
+ investigation_only)),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
+ active_only)),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
+ active_only)),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct AmlProcessResultContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ const char *stmt = (limit > 0)
+ ? "select_aml_decisions_inc"
+ : "select_aml_decisions_dec";
+
+ PREPARE (pg,
+ "select_aml_decisions_inc",
+ "SELECT"
+ " lo.outcome_serial_id"
+ ",lo.h_payto"
+ ",ah.justification"
+ ",lo.decision_time"
+ ",lo.expiration_time"
+ ",lo.jproperties::TEXT"
+ ",lo.to_investigate"
+ ",lo.is_active"
+ ",lo.jnew_rules::TEXT"
+ ",kt.is_wallet"
+ ",wt.payto_uri"
+ " FROM legitimization_outcomes lo"
+ " JOIN kyc_targets kt"
+ " ON (lo.h_payto = kt.h_normalized_payto)"
+ " JOIN wire_targets wt"
+ " ON (lo.h_payto = wt.h_normalized_payto)"
+ " LEFT JOIN aml_history ah"
+ " USING (outcome_serial_id)"
+ " WHERE (outcome_serial_id > $7)"
+ " AND ($1 OR (lo.h_payto = $2))"
+ " AND ($3 OR (lo.to_investigate = $4))"
+ " AND ($5 OR (lo.is_active = $6))"
+ " ORDER BY lo.outcome_serial_id ASC"
+ " LIMIT $8");
+ PREPARE (pg,
+ "select_aml_decisions_dec",
+ "SELECT"
+ " lo.outcome_serial_id"
+ ",lo.h_payto"
+ ",ah.justification"
+ ",lo.decision_time"
+ ",lo.expiration_time"
+ ",lo.jproperties::TEXT"
+ ",lo.to_investigate"
+ ",lo.is_active"
+ ",lo.jnew_rules::TEXT"
+ ",kt.is_wallet"
+ ",wt.payto_uri"
+ " FROM legitimization_outcomes lo"
+ " JOIN kyc_targets kt"
+ " ON (lo.h_payto = kt.h_normalized_payto)"
+ " JOIN wire_targets wt"
+ " ON (lo.h_payto = wt.h_normalized_payto)"
+ " LEFT JOIN aml_history ah"
+ " USING (outcome_serial_id)"
+ " WHERE lo.outcome_serial_id < $7"
+ " AND ($1 OR (lo.h_payto = $2))"
+ " AND ($3 OR (lo.to_investigate = $4))"
+ " AND ($5 OR (lo.is_active = $6))"
+ " ORDER BY lo.outcome_serial_id DESC"
+ " LIMIT $8");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ stmt,
+ params,
+ &handle_aml_result,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_aml_measures.c b/src/exchangedb/select_aml_measures.c
@@ -0,0 +1,185 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_aml_measures.c
+ * @brief Implementation of the select_aml_measures function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_aml_measures.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #handle_aml_result.
+ */
+struct LegiMeasureResultContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_LegitimizationMeasureCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on serious errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results. Helper function
+ * for #TALER_EXCHANGEDB_select_aml_measures().
+ *
+ * @param cls closure of type `struct LegiMeasureResultContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_aml_result (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LegiMeasureResultContext *ctx = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_NormalizedPaytoHashP h_payto;
+ uint64_t rowid;
+ struct GNUNET_TIME_Absolute start_time;
+ json_t *jmeasures;
+ bool is_finished;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("legitimization_measure_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("h_normalized_payto",
+ &h_payto),
+ GNUNET_PQ_result_spec_absolute_time ("start_time",
+ &start_time),
+ TALER_PQ_result_spec_json ("jmeasures",
+ &jmeasures),
+ GNUNET_PQ_result_spec_bool ("is_finished",
+ &is_finished),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ &h_payto,
+ start_time,
+ jmeasures,
+ is_finished,
+ rowid);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_aml_measures (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ enum TALER_EXCHANGE_YesNoAll active_only,
+ uint64_t offset,
+ int64_t limit,
+ TALER_EXCHANGEDB_LegitimizationMeasureCallback cb,
+ void *cb_cls)
+{
+ uint64_t ulimit = (limit > 0) ? limit : -limit;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_bool (NULL == h_payto),
+ NULL == h_payto
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
+ active_only)),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_NO ==
+ active_only)),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct LegiMeasureResultContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ const char *stmt = (limit > 0)
+ ? "select_aml_measures_inc"
+ : "select_aml_measures_dec";
+
+ PREPARE (pg,
+ "select_aml_measures_inc",
+ "SELECT"
+ " lm.legitimization_measure_serial_id"
+ ",kt.h_normalized_payto"
+ ",lm.jmeasures::TEXT"
+ ",lm.start_time"
+ ",lm.is_finished"
+ " FROM kyc_targets kt"
+ " JOIN legitimization_measures lm"
+ " USING (access_token)"
+ " WHERE (legitimization_measure_serial_id > $5)"
+ " AND ($1 OR (kt.h_normalized_payto = $2))"
+ " AND ($3 OR (lm.is_finished = $4))"
+ " ORDER BY lm.legitimization_measure_serial_id ASC"
+ " LIMIT $6");
+ PREPARE (pg,
+ "select_aml_measures_dec",
+ "SELECT"
+ " lm.legitimization_measure_serial_id"
+ ",kt.h_normalized_payto"
+ ",lm.jmeasures::TEXT"
+ ",lm.start_time"
+ ",lm.is_finished"
+ " FROM kyc_targets kt"
+ " JOIN legitimization_measures lm"
+ " USING (access_token)"
+ " WHERE (legitimization_measure_serial_id < $5)"
+ " AND ($1 OR (kt.h_normalized_payto = $2))"
+ " AND ($3 OR (lm.is_finished = $4))"
+ " ORDER BY lm.legitimization_measure_serial_id DESC"
+ " LIMIT $6");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ stmt,
+ params,
+ &handle_aml_result,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_aml_statistics.c b/src/exchangedb/select_aml_statistics.c
@@ -0,0 +1,142 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_aml_statistics.c
+ * @brief Implementation of the select_aml_statistics function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_aml_statistics.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #get_statistics_cb().
+ */
+struct GetStatisticsContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_AmlStatisticsCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Flag set to #GNUNET_OK as long as everything is fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct GetStatisticsContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_statistics_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GetStatisticsContext *ctx = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t val;
+ char *name;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("name",
+ &name),
+ GNUNET_PQ_result_spec_uint64 ("value",
+ &val),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ name,
+ val);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_aml_statistics (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ size_t num_names,
+ const char *names[static num_names],
+ struct GNUNET_TIME_Timestamp start_date,
+ struct GNUNET_TIME_Timestamp end_date,
+ TALER_EXCHANGEDB_AmlStatisticsCallback cb,
+ void *cb_cls)
+{
+ struct GetStatisticsContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_array_ptrs_string (num_names,
+ names,
+ pg->conn),
+ GNUNET_PQ_query_param_timestamp (&start_date),
+ GNUNET_PQ_query_param_timestamp (&end_date),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_aml_statistics",
+ "SELECT "
+ " event_type AS name"
+ ",COUNT(*) AS value"
+ " FROM kyc_events"
+ " WHERE event_type = ANY ($1)"
+ " AND event_timestamp >= $2"
+ " AND event_timestamp < $3"
+ " GROUP BY event_type;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "select_aml_statistics",
+ params,
+ &get_statistics_cb,
+ &ctx);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_auditor_denom_sig.c b/src/exchangedb/select_auditor_denom_sig.c
@@ -0,0 +1,62 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_auditor_denom_sig.c
+ * @brief Implementation of the select_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_auditor_denom_sig.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_auditor_denom_sig (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ struct TALER_AuditorSignatureP *auditor_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+ GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("auditor_sig",
+ auditor_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "select_auditor_denom_sig",
+ "SELECT"
+ " auditor_sig"
+ " FROM auditor_denom_sigs"
+ " WHERE auditor_uuid="
+ " (SELECT auditor_uuid"
+ " FROM auditors"
+ " WHERE auditor_pub=$1)"
+ " AND denominations_serial="
+ " (SELECT denominations_serial"
+ " FROM denominations"
+ " WHERE denom_pub_hash=$2);");
+
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "select_auditor_denom_sig",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/select_batch_deposits_missing_wire.c b/src/exchangedb/select_batch_deposits_missing_wire.c
@@ -0,0 +1,140 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_batch_deposits_missing_wire.c
+ * @brief Implementation of the select_batch_deposits_missing_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_batch_deposits_missing_wire.h"
+#include "helper.h"
+
+/**
+ * Closure for #missing_wire_cb().
+ */
+struct MissingWireContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_WireMissingCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on error.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct MissingWireContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+missing_wire_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct MissingWireContext *mwc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = mwc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t batch_deposit_serial_id;
+ struct GNUNET_TIME_Timestamp deadline;
+ struct TALER_FullPaytoHashP wire_target_h_payto;
+ struct TALER_Amount total_amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id",
+ &batch_deposit_serial_id),
+ GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
+ &wire_target_h_payto),
+ GNUNET_PQ_result_spec_timestamp ("deadline",
+ &deadline),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount",
+ &total_amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ mwc->status = GNUNET_SYSERR;
+ return;
+ }
+ mwc->cb (mwc->cb_cls,
+ batch_deposit_serial_id,
+ &total_amount,
+ &wire_target_h_payto,
+ deadline);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_batch_deposits_missing_wire (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t min_batch_deposit_serial_id,
+ TALER_EXCHANGEDB_WireMissingCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&min_batch_deposit_serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct MissingWireContext mwc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "deposits_get_deposits_missing_wire",
+ "SELECT"
+ " batch_deposit_serial_id"
+ ",wire_target_h_payto"
+ ",deadline"
+ ",total_amount"
+ " FROM exchange_do_select_deposits_missing_wire"
+ " ($1);");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "deposits_get_deposits_missing_wire",
+ params,
+ &missing_wire_cb,
+ &mwc);
+ if (GNUNET_OK != mwc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_coin_deposits_above_serial_id.c b/src/exchangedb/select_coin_deposits_above_serial_id.c
@@ -0,0 +1,200 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_coin_deposits_above_serial_id.c
+ * @brief Implementation of the select_coin_deposits_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_coin_deposits_above_serial_id.h"
+#include "helper.h"
+
+/**
+ * Closure for #deposit_serial_helper_cb().
+ */
+struct CoinDepositSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_DepositCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct CoinDepositSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+coin_deposit_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinDepositSerialContext *dsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_Deposit deposit;
+ struct GNUNET_TIME_Timestamp exchange_timestamp;
+ struct TALER_DenominationPublicKey denom_pub;
+ bool done;
+ uint64_t rowid;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &deposit.amount_with_fee),
+ GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
+ &deposit.timestamp),
+ GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+ &exchange_timestamp),
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+ &deposit.merchant_pub),
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ &denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &deposit.coin.coin_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &deposit.coin.h_age_commitment),
+ &deposit.coin.no_age_commitment),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("wallet_data_hash",
+ &deposit.wallet_data_hash),
+ &deposit.no_wallet_data_hash),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &deposit.csig),
+ GNUNET_PQ_result_spec_timestamp ("refund_deadline",
+ &deposit.refund_deadline),
+ GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+ &deposit.wire_deadline),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &deposit.h_contract_terms),
+ GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+ &deposit.wire_salt),
+ GNUNET_PQ_result_spec_string ("receiver_wire_account",
+ &deposit.receiver_wire_account.full_payto),
+ GNUNET_PQ_result_spec_bool ("done",
+ &done),
+ GNUNET_PQ_result_spec_uint64 ("coin_deposit_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ memset (&deposit,
+ 0,
+ sizeof (deposit));
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = dsc->cb (dsc->cb_cls,
+ rowid,
+ exchange_timestamp,
+ &deposit,
+ &denom_pub,
+ done);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_coin_deposits_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_DepositCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct CoinDepositSerialContext dsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Fetch deposits with rowid '\geq' the given parameter */
+ PREPARE (pg,
+ "audit_get_coin_deposits_incr",
+ "SELECT"
+ " cdep.amount_with_fee"
+ ",bdep.wallet_timestamp"
+ ",bdep.exchange_timestamp"
+ ",bdep.merchant_pub"
+ ",bdep.wallet_data_hash"
+ ",denom.denom_pub"
+ ",kc.coin_pub"
+ ",kc.age_commitment_hash"
+ ",cdep.coin_sig"
+ ",bdep.refund_deadline"
+ ",bdep.wire_deadline"
+ ",bdep.h_contract_terms"
+ ",bdep.wire_salt"
+ ",wt.payto_uri AS receiver_wire_account"
+ ",bdep.done"
+ ",cdep.coin_deposit_serial_id"
+ " FROM coin_deposits cdep"
+ " JOIN batch_deposits bdep"
+ " USING (batch_deposit_serial_id)"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " JOIN known_coins kc"
+ " USING (coin_pub)"
+ " JOIN denominations denom"
+ " USING (denominations_serial)"
+ " WHERE (coin_deposit_serial_id>=$1)"
+ " ORDER BY coin_deposit_serial_id ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "audit_get_coin_deposits_incr",
+ params,
+ &coin_deposit_serial_helper_cb,
+ &dsc);
+ if (GNUNET_OK != dsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_contract.c b/src/exchangedb/select_contract.c
@@ -0,0 +1,65 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_contract.c
+ * @brief Implementation of the select_contract function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_contract.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_contract (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ContractDiffiePublicP *
+ pub_ckey,
+ struct TALER_PurseContractPublicKeyP *
+ purse_pub,
+ struct TALER_PurseContractSignatureP *
+ econtract_sig,
+ size_t *econtract_size,
+ void **econtract)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (pub_ckey),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("contract_sig",
+ econtract_sig),
+ GNUNET_PQ_result_spec_variable_size ("e_contract",
+ econtract,
+ econtract_size),
+ GNUNET_PQ_result_spec_end
+ };
+
+ /* Used in #postgres_select_contract */
+ PREPARE (pg,
+ "select_contract",
+ "SELECT "
+ " purse_pub"
+ ",e_contract"
+ ",contract_sig"
+ " FROM contracts"
+ " WHERE pub_ckey=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "select_contract",
+ params,
+ rs);
+
+}
diff --git a/src/exchangedb/select_contract_by_purse.c b/src/exchangedb/select_contract_by_purse.c
@@ -0,0 +1,59 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_contract_by_purse.c
+ * @brief Implementation of the select_contract_by_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_contract_by_purse.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_select_contract_by_purse (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ struct TALER_EncryptedContract *econtract)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("pub_ckey",
+ &econtract->contract_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("contract_sig",
+ &econtract->econtract_sig),
+ GNUNET_PQ_result_spec_variable_size ("e_contract",
+ &econtract->econtract,
+ &econtract->econtract_size),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "select_contract_by_purse",
+ "SELECT "
+ " pub_ckey"
+ ",e_contract"
+ ",contract_sig"
+ " FROM contracts"
+ " WHERE purse_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "select_contract_by_purse",
+ params,
+ rs);
+
+}
diff --git a/src/exchangedb/select_deposit_amounts_for_kyc_check.c b/src/exchangedb/select_deposit_amounts_for_kyc_check.c
@@ -0,0 +1,153 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_deposit_amounts_for_kyc_check.c
+ * @brief Implementation of the select_deposit_amounts_for_kyc_check function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_deposit_amounts_for_kyc_check.h"
+#include "helper.h"
+
+/**
+ * Closure for #get_kyc_amounts_cb().
+ */
+struct KycAmountCheckContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_KYCLOGIC_KycAmountCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Flag set to #GNUNET_OK as long as everything is fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+};
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct KycAmountCheckContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_kyc_amounts_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycAmountCheckContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct GNUNET_TIME_Absolute date;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_absolute_time ("date",
+ &date),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = ctx->cb (ctx->cb_cls,
+ &amount,
+ date);
+ GNUNET_PQ_cleanup_result (rs);
+ switch (ret)
+ {
+ case GNUNET_OK:
+ continue;
+ case GNUNET_NO:
+ break;
+ case GNUNET_SYSERR:
+ ctx->status = GNUNET_SYSERR;
+ break;
+ }
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_deposit_amounts_for_kyc_check (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_KYCLOGIC_KycAmountCallback kac,
+ void *kac_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_absolute_time (&time_limit),
+ GNUNET_PQ_query_param_end
+ };
+ struct KycAmountCheckContext ctx = {
+ .cb = kac,
+ .cb_cls = kac_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_kyc_relevant_deposit_events",
+ "SELECT"
+ " cd.amount_with_fee AS amount"
+ ",bd.exchange_timestamp AS date"
+ " FROM batch_deposits bd"
+ " JOIN coin_deposits cd"
+ " USING (batch_deposit_serial_id)"
+ " WHERE wire_target_h_payto IN ("
+ " SELECT wire_target_h_payto"
+ " FROM wire_targets"
+ " WHERE h_normalized_payto=$1"
+ " )"
+ " AND bd.exchange_timestamp >= $2"
+ " ORDER BY bd.exchange_timestamp DESC");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_kyc_relevant_deposit_events",
+ params,
+ &get_kyc_amounts_cb,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_exchange_credit_transfers.c b/src/exchangedb/select_exchange_credit_transfers.c
@@ -0,0 +1,180 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_exchange_credit_transfers.c
+ * @brief Implementation of the select_exchange_credit_transfers function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_exchange_credit_transfers.h"
+#include "helper.h"
+
+/**
+ * Closure for #handle_aml_result.
+ */
+struct SelectTransferContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_AmlTransferCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on serious errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results. Helper function
+ * for #TALER_EXCHANGEDB_select_exchange_debit_transfers().
+ *
+ * @param cls closure of type `struct SelectTransferContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_transfer_result (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SelectTransferContext *stc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ char *payto_uri;
+ uint64_t rowid;
+ struct GNUNET_TIME_Absolute execution_time;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri),
+ GNUNET_PQ_result_spec_absolute_time ("execution_time",
+ &execution_time),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ stc->status = GNUNET_SYSERR;
+ return;
+ }
+ stc->cb (stc->cb_cls,
+ rowid,
+ payto_uri,
+ execution_time,
+ &amount);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_exchange_credit_transfers (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_Amount *threshold,
+ uint64_t offset,
+ int64_t limit,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AmlTransferCallback cb,
+ void *cb_cls)
+{
+ struct SelectTransferContext stc = {
+ .pg = pg,
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .status = GNUNET_OK
+ };
+ uint64_t ulimit = (limit > 0) ? limit : -limit;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ TALER_PQ_query_param_amount (pg->conn,
+ threshold),
+ NULL != h_payto
+ ? GNUNET_PQ_query_param_auto_from_type (h_payto)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_exchange_credit_transfers_inc",
+ "SELECT"
+ " ri.reserve_in_serial_id AS serial_id"
+ ",wt.payto_uri"
+ ",ri.execution_date AS execution_time"
+ ",ri.credit AS amount"
+ " FROM reserves_in ri"
+ " LEFT JOIN wire_targets wt"
+ " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)"
+ " WHERE (ri.reserve_in_serial_id > $1)"
+ " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
+ " AND ( ( (ri.credit).val > ($3::taler_amount).val)"
+ " OR ( ( (ri.credit).val >= ($3::taler_amount).val)"
+ " AND ( (ri.credit).frac >= ($3::taler_amount).frac) ) )"
+ " ORDER BY ri.reserve_in_serial_id ASC"
+ " LIMIT $2");
+ PREPARE (pg,
+ "select_exchange_credit_transfers_dec",
+ "SELECT"
+ " ri.reserve_in_serial_id AS serial_id"
+ ",wt.payto_uri"
+ ",ri.execution_date AS execution_time"
+ ",ri.credit AS amount"
+ " FROM reserves_in ri"
+ " LEFT JOIN wire_targets wt"
+ " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)"
+ " WHERE (ri.reserve_in_serial_id < $1)"
+ " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
+ " AND ( ( (ri.credit).val > ($3::taler_amount).val)"
+ " OR ( ( (ri.credit).val >= ($3::taler_amount).val)"
+ " AND ( (ri.credit).frac >= ($3::taler_amount).frac) ) )"
+ " ORDER BY ri.reserve_in_serial_id DESC"
+ " LIMIT $2");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ (limit > 0)
+ ? "select_exchange_credit_transfers_inc"
+ : "select_exchange_credit_transfers_dec",
+ params,
+ &handle_transfer_result,
+ &stc);
+ if (GNUNET_OK != stc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_exchange_debit_transfers.c b/src/exchangedb/select_exchange_debit_transfers.c
@@ -0,0 +1,181 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_exchange_debit_transfers.c
+ * @brief Implementation of the select_exchange_debit_transfers function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_exchange_debit_transfers.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #handle_aml_result.
+ */
+struct SelectTransferContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_AmlTransferCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on serious errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results. Helper function
+ * for #TALER_EXCHANGEDB_select_exchange_debit_transfers().
+ *
+ * @param cls closure of type `struct SelectTransferContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_transfer_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SelectTransferContext *stc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ char *payto_uri;
+ uint64_t rowid;
+ struct GNUNET_TIME_Absolute execution_time;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri),
+ GNUNET_PQ_result_spec_absolute_time ("execution_time",
+ &execution_time),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ stc->status = GNUNET_SYSERR;
+ return;
+ }
+ stc->cb (stc->cb_cls,
+ rowid,
+ payto_uri,
+ execution_time,
+ &amount);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_exchange_debit_transfers (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_Amount *threshold,
+ uint64_t offset,
+ int64_t limit,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AmlTransferCallback cb,
+ void *cb_cls)
+{
+ struct SelectTransferContext stc = {
+ .pg = pg,
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .status = GNUNET_OK
+ };
+ uint64_t ulimit = (limit > 0) ? limit : -limit;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ TALER_PQ_query_param_amount (pg->conn,
+ threshold),
+ NULL != h_payto
+ ? GNUNET_PQ_query_param_auto_from_type (h_payto)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_exchange_debit_transfers_inc",
+ "SELECT"
+ " wo.wireout_uuid AS serial_id"
+ ",wt.payto_uri"
+ ",wo.execution_date AS execution_time"
+ ",wo.amount"
+ " FROM wire_out wo"
+ " LEFT JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " WHERE (wo.wireout_uuid > $1)"
+ " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
+ " AND ( ( (wo.amount).val > ($3::taler_amount).val)"
+ " OR ( ( (wo.amount).val >= ($3::taler_amount).val)"
+ " AND ( (wo.amount).frac >= ($3::taler_amount).frac) ) )"
+ " ORDER BY wo.wireout_uuid ASC"
+ " LIMIT $2");
+ PREPARE (pg,
+ "select_exchange_debit_transfers_dec",
+ "SELECT"
+ " wo.wireout_uuid AS serial_id"
+ ",wt.payto_uri"
+ ",wo.execution_date AS execution_time"
+ ",wo.amount"
+ " FROM wire_out wo"
+ " LEFT JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " WHERE (wo.wireout_uuid < $1)"
+ " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
+ " AND ( ( (wo.amount).val > ($3::taler_amount).val)"
+ " OR ( ( (wo.amount).val >= ($3::taler_amount).val)"
+ " AND ( (wo.amount).frac >= ($3::taler_amount).frac) ) )"
+ " ORDER BY wo.wireout_uuid DESC"
+ " LIMIT $2");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ (limit > 0)
+ ? "select_exchange_debit_transfers_inc"
+ : "select_exchange_debit_transfers_dec",
+ params,
+ &handle_transfer_cb,
+ &stc);
+ if (GNUNET_OK != stc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_exchange_kycauth_transfers.c b/src/exchangedb/select_exchange_kycauth_transfers.c
@@ -0,0 +1,180 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_exchange_kycauth_transfers.c
+ * @brief Implementation of the select_exchange_kycauth_transfers function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_exchange_kycauth_transfers.h"
+#include "helper.h"
+
+/**
+ * Closure for #handle_aml_result.
+ */
+struct SelectTransferContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_AmlTransferCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on serious errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results. Helper function
+ * for #TALER_EXCHANGEDB_select_exchange_debit_transfers().
+ *
+ * @param cls closure of type `struct SelectTransferContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_transfer_result (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SelectTransferContext *stc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = stc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ char *payto_uri;
+ uint64_t rowid;
+ struct GNUNET_TIME_Absolute execution_time;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri),
+ GNUNET_PQ_result_spec_absolute_time ("execution_time",
+ &execution_time),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ stc->status = GNUNET_SYSERR;
+ return;
+ }
+ stc->cb (stc->cb_cls,
+ rowid,
+ payto_uri,
+ execution_time,
+ &amount);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_exchange_kycauth_transfers (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_Amount *threshold,
+ uint64_t offset,
+ int64_t limit,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AmlTransferCallback cb,
+ void *cb_cls)
+{
+ struct SelectTransferContext stc = {
+ .pg = pg,
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .status = GNUNET_OK
+ };
+ uint64_t ulimit = (limit > 0) ? limit : -limit;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ TALER_PQ_query_param_amount (pg->conn,
+ threshold),
+ NULL != h_payto
+ ? GNUNET_PQ_query_param_auto_from_type (h_payto)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_exchange_kycauth_transfers_inc",
+ "SELECT"
+ " ki.kycauth_in_serial_id AS serial_id"
+ ",wt.payto_uri"
+ ",ki.execution_date AS execution_time"
+ ",ki.credit AS amount"
+ " FROM kycauths_in ki"
+ " LEFT JOIN wire_targets wt"
+ " ON (ki.wire_source_h_payto = wt.wire_target_h_payto)"
+ " WHERE (ki.kycauth_in_serial_id > $1)"
+ " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
+ " AND ( ( (ki.credit).val > ($3::taler_amount).val)"
+ " OR ( ( (ki.credit).val >= ($3::taler_amount).val)"
+ " AND ( (ki.credit).frac >= ($3::taler_amount).frac) ) )"
+ " ORDER BY ki.kycauth_in_serial_id ASC"
+ " LIMIT $2");
+ PREPARE (pg,
+ "select_exchange_kycauth_transfers_dec",
+ "SELECT"
+ " ki.kycauth_in_serial_id AS serial_id"
+ ",wt.payto_uri"
+ ",ki.execution_date AS execution_time"
+ ",ki.credit AS amount"
+ " FROM kycauths_in ki"
+ " LEFT JOIN wire_targets wt"
+ " ON (ki.wire_source_h_payto = wt.wire_target_h_payto)"
+ " WHERE (ki.kycauth_in_serial_id < $1)"
+ " AND ( ($4::BYTEA IS NULL) OR (wt.h_normalized_payto=$4) )"
+ " AND ( ( (ki.credit).val > ($3::taler_amount).val)"
+ " OR ( ( (ki.credit).val >= ($3::taler_amount).val)"
+ " AND ( (ki.credit).frac >= ($3::taler_amount).frac) ) )"
+ " ORDER BY ki.kycauth_in_serial_id DESC"
+ " LIMIT $2");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ (limit > 0)
+ ? "select_exchange_kycauth_transfers_inc"
+ : "select_exchange_kycauth_transfers_dec",
+ params,
+ &handle_transfer_result,
+ &stc);
+ if (GNUNET_OK != stc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_kyc_accounts.c b/src/exchangedb/select_kyc_accounts.c
@@ -0,0 +1,235 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_kyc_accounts.c
+ * @brief Implementation of the select_kyc_accounts function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_kyc_accounts.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #handle_aml_result.
+ */
+struct KycAccountResultContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_AmlAccountListCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on serious errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results. Helper function
+ * for #TALER_EXCHANGEDB_select_kyc_accounts().
+ *
+ * @param cls closure of type `struct KycAccountResultContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+handle_kyc_account_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycAccountResultContext *ctx = cls;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct TALER_NormalizedPaytoHashP h_payto;
+ char *comments = NULL;
+ struct GNUNET_TIME_Timestamp open_time
+ = GNUNET_TIME_UNIT_FOREVER_TS;
+ struct GNUNET_TIME_Timestamp close_time
+ = GNUNET_TIME_UNIT_FOREVER_TS;
+ bool to_investigate;
+ bool high_risk;
+ struct TALER_FullPayto payto;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("kyc_target_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("h_payto",
+ &h_payto),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("comments",
+ &comments),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_timestamp ("open_time",
+ &open_time),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_timestamp ("close_time",
+ &close_time),
+ NULL),
+ GNUNET_PQ_result_spec_bool ("to_investigate",
+ &to_investigate),
+ GNUNET_PQ_result_spec_bool ("high_risk",
+ &high_risk),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto.full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ rowid,
+ &h_payto,
+ open_time,
+ close_time,
+ comments,
+ high_risk,
+ to_investigate,
+ payto);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_kyc_accounts (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ enum TALER_EXCHANGE_YesNoAll investigation_only,
+ enum TALER_EXCHANGE_YesNoAll open_only,
+ enum TALER_EXCHANGE_YesNoAll high_risk_only,
+ uint64_t offset,
+ int64_t limit,
+ TALER_EXCHANGEDB_AmlAccountListCallback cb,
+ void *cb_cls)
+{
+ uint64_t ulimit = (limit > 0) ? limit : -limit;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
+ investigation_only)),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
+ investigation_only)),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
+ open_only)),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
+ open_only)),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_ALL ==
+ high_risk_only)),
+ GNUNET_PQ_query_param_bool ((TALER_EXCHANGE_YNA_YES ==
+ high_risk_only)),
+ GNUNET_PQ_query_param_end
+ };
+ struct KycAccountResultContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ const char *stmt = (limit > 0)
+ ? "select_kyc_accounts_inc"
+ : "select_kyc_accounts_dec";
+
+ PREPARE (pg,
+ "select_kyc_accounts_inc",
+ "SELECT"
+ " kt.kyc_target_serial_id"
+ ",kt.h_normalized_payto AS h_payto"
+ ",kt.open_time"
+ ",kt.close_time"
+ ",lo.jproperties ->> 'FILE_NOTE' AS comments"
+ ",lo.jproperties ->> 'open_date' AS open_time"
+ ",COALESCE(lo.to_investigate,FALSE) AS to_investigate"
+ ",COALESCE((lo.jproperties ->> 'HIGH_RISK_CUSTOMER')::bool,FALSE) AS high_risk"
+ ",wt.payto_uri"
+ " FROM kyc_targets kt"
+ " JOIN wire_targets wt"
+ " ON (wt.h_normalized_payto = kt.h_normalized_payto)"
+ " LEFT JOIN legitimization_outcomes lo"
+ " ON (lo.h_payto = kt.h_normalized_payto)"
+ " WHERE (kyc_target_serial_id > $1)"
+ // select most recent outcomes only
+ " AND COALESCE (lo.is_active, TRUE)"
+ " AND ($3 OR (COALESCE(lo.to_investigate,FALSE) = $4))"
+ // Account is open if we had an AML outcome
+ " AND ($5 OR ((lo.outcome_serial_id IS NULL) = $6))"
+ " AND ($7 OR ((COALESCE((lo.jproperties ->>'high_risk')::bool,FALSE) = $8)))"
+ " ORDER BY kt.kyc_target_serial_id ASC"
+ " LIMIT $2");
+ PREPARE (pg,
+ "select_kyc_accounts_dec",
+ "SELECT"
+ " kt.kyc_target_serial_id"
+ ",kt.h_normalized_payto AS h_payto"
+ ",kt.open_time"
+ ",kt.close_time"
+ ",lo.jproperties ->> 'FILE_NOTE' AS comments"
+ ",lo.jproperties ->> 'open_date' AS open_time"
+ ",COALESCE(lo.to_investigate,FALSE) AS to_investigate"
+ ",COALESCE((lo.jproperties ->> 'HIGH_RISK_CUSTOMER')::bool,FALSE) AS high_risk"
+ ",wt.payto_uri"
+ " FROM kyc_targets kt"
+ " LEFT JOIN legitimization_outcomes lo"
+ " ON (lo.h_payto = kt.h_normalized_payto)"
+ " LEFT JOIN LATERAL ("
+ " SELECT payto_uri"
+ " FROM wire_targets"
+ " WHERE h_normalized_payto = kt.h_normalized_payto"
+ " ORDER BY wire_target_serial_id DESC"
+ " LIMIT 1"
+ " ) wt ON true"
+ " WHERE (kyc_target_serial_id < $1)"
+ // select most recent outcomes only
+ " AND COALESCE (lo.is_active, TRUE)"
+ " AND ($3 OR (COALESCE(lo.to_investigate,FALSE) = $4))"
+ // Account is open if we had an AML outcome
+ " AND ($5 OR ((lo.outcome_serial_id IS NULL) = $6))"
+ " AND ($7 OR ((COALESCE((lo.jproperties ->>'high_risk')::bool,FALSE) = $8)))"
+ " ORDER BY kt.kyc_target_serial_id DESC"
+ " LIMIT $2");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ stmt,
+ params,
+ &handle_kyc_account_cb,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_kyc_attributes.c b/src/exchangedb/select_kyc_attributes.c
@@ -0,0 +1,154 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_kyc_attributes.c
+ * @brief Implementation of the select_kyc_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_kyc_attributes.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #get_attributes_cb().
+ */
+struct GetAttributesContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_AttributeCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Key of our query.
+ */
+ const struct TALER_NormalizedPaytoHashP *h_payto;
+
+ /**
+ * Flag set to #GNUNET_OK as long as everything is fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct GetAttributesContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_attributes_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GetAttributesContext *ctx = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct GNUNET_TIME_Timestamp collection_time;
+ struct GNUNET_TIME_Timestamp expiration_time;
+ size_t enc_attributes_size;
+ void *enc_attributes;
+ char *provider;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("provider_name",
+ &provider),
+ GNUNET_PQ_result_spec_timestamp ("collection_time",
+ &collection_time),
+ GNUNET_PQ_result_spec_timestamp ("expiration_time",
+ &expiration_time),
+ GNUNET_PQ_result_spec_variable_size ("encrypted_attributes",
+ &enc_attributes,
+ &enc_attributes_size),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ctx->cb (ctx->cb_cls,
+ ctx->h_payto,
+ provider,
+ collection_time,
+ expiration_time,
+ enc_attributes_size,
+ enc_attributes);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_kyc_attributes (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AttributeCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_end
+ };
+ struct GetAttributesContext ctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .h_payto = h_payto,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_kyc_attributes",
+ "SELECT "
+ " lp.provider_name"
+ ",ka.collection_time"
+ ",ka.expiration_time"
+ ",ka.encrypted_attributes"
+ " FROM kyc_attributes ka"
+ " JOIN legitimization_processes lp"
+ " ON (ka.legitimization_serial = lp.legitimization_process_serial_id)"
+ " WHERE ka.h_payto=$1");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_kyc_attributes",
+ params,
+ &get_attributes_cb,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_merge_amounts_for_kyc_check.c b/src/exchangedb/select_merge_amounts_for_kyc_check.c
@@ -0,0 +1,152 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_merge_amounts_for_kyc_check.c
+ * @brief Implementation of the select_merge_amounts_for_kyc_check function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_merge_amounts_for_kyc_check.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #get_kyc_amounts_cb().
+ */
+struct KycAmountCheckContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_KYCLOGIC_KycAmountCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Flag set to #GNUNET_OK as long as everything is fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+};
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct KycAmountCheckContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_kyc_amounts_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycAmountCheckContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct GNUNET_TIME_Absolute date;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_absolute_time ("date",
+ &date),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = ctx->cb (ctx->cb_cls,
+ &amount,
+ date);
+ GNUNET_PQ_cleanup_result (rs);
+ switch (ret)
+ {
+ case GNUNET_OK:
+ continue;
+ case GNUNET_NO:
+ break;
+ case GNUNET_SYSERR:
+ ctx->status = GNUNET_SYSERR;
+ break;
+ }
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_merge_amounts_for_kyc_check (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_KYCLOGIC_KycAmountCallback kac,
+ void *kac_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_absolute_time (&time_limit),
+ GNUNET_PQ_query_param_end
+ };
+ struct KycAmountCheckContext ctx = {
+ .cb = kac,
+ .cb_cls = kac_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_kyc_relevant_merge_events",
+ "SELECT"
+ " amount_with_fee AS amount"
+ ",merge_timestamp AS date"
+ " FROM account_merges"
+ " JOIN purse_merges USING (purse_pub)"
+ " JOIN purse_requests USING (purse_pub)"
+ " JOIN purse_decision USING (purse_pub)"
+ " WHERE wallet_h_payto=$1"
+ " AND merge_timestamp >= $2"
+ " AND NOT refunded"
+ " ORDER BY merge_timestamp DESC");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_kyc_relevant_merge_events",
+ params,
+ &get_kyc_amounts_cb,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_purse.c b/src/exchangedb/select_purse.c
@@ -0,0 +1,90 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_purse.c
+ * @brief Implementation of the select_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_purse.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_purse (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ struct GNUNET_TIME_Timestamp *purse_creation,
+ struct GNUNET_TIME_Timestamp *purse_expiration,
+ struct TALER_Amount *amount,
+ struct TALER_Amount *deposited,
+ struct TALER_PrivateContractHashP *h_contract_terms,
+ struct GNUNET_TIME_Timestamp *merge_timestamp,
+ bool *purse_deleted,
+ bool *purse_refunded)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_timestamp ("purse_expiration",
+ purse_expiration),
+ GNUNET_PQ_result_spec_timestamp ("purse_creation",
+ purse_creation),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ deposited),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ h_contract_terms),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
+ merge_timestamp),
+ NULL),
+ GNUNET_PQ_result_spec_bool ("purse_deleted",
+ purse_deleted),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_bool ("purse_refunded",
+ purse_refunded),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "select_purse",
+ "SELECT "
+ " pr.merge_pub"
+ ",pr.purse_creation"
+ ",pr.purse_expiration"
+ ",pr.h_contract_terms"
+ ",pr.amount_with_fee"
+ ",pr.balance"
+ ",pm.merge_timestamp"
+ ",pd.purse_sig IS NOT NULL AS purse_deleted"
+ ",pc.refunded AS purse_refunded"
+ " FROM purse_requests pr"
+ " LEFT JOIN purse_merges pm ON (pm.purse_pub = pr.purse_pub)"
+ " LEFT JOIN purse_decision pc ON (pc.purse_pub = pr.purse_pub)"
+ " LEFT JOIN purse_deletion pd ON (pd.purse_pub = pr.purse_pub)"
+ " WHERE pr.purse_pub=$1;");
+ *merge_timestamp = GNUNET_TIME_UNIT_FOREVER_TS;
+ *purse_refunded = false;
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "select_purse",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/select_purse_by_merge_pub.c b/src/exchangedb/select_purse_by_merge_pub.c
@@ -0,0 +1,75 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_purse_by_merge_pub.c
+ * @brief Implementation of the select_purse_by_merge_pub function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_purse_by_merge_pub.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_select_purse_by_merge_pub (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseMergePublicKeyP *merge_pub,
+ struct TALER_PurseContractPublicKeyP *purse_pub,
+ struct GNUNET_TIME_Timestamp *purse_expiration,
+ struct TALER_PrivateContractHashP *h_contract_terms,
+ uint32_t *age_limit,
+ struct TALER_Amount *target_amount,
+ struct TALER_Amount *balance,
+ struct TALER_PurseContractSignatureP *purse_sig)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (merge_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ purse_pub),
+ GNUNET_PQ_result_spec_timestamp ("purse_expiration",
+ purse_expiration),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ h_contract_terms),
+ GNUNET_PQ_result_spec_uint32 ("age_limit",
+ age_limit),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ target_amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ balance),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
+ purse_sig),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "select_purse_by_merge_pub",
+ "SELECT "
+ " purse_pub"
+ ",purse_expiration"
+ ",h_contract_terms"
+ ",age_limit"
+ ",amount_with_fee"
+ ",balance"
+ ",purse_sig"
+ " FROM purse_requests"
+ " WHERE merge_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "select_purse_by_merge_pub",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/select_purse_decisions_above_serial_id.c b/src/exchangedb/select_purse_decisions_above_serial_id.c
@@ -0,0 +1,158 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_purse_decisions_above_serial_id.c
+ * @brief Implementation of the select_purse_decisions_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_purse_decisions_above_serial_id.h"
+#include "helper.h"
+
+/**
+ * Closure for #purse_decision_serial_helper_cb().
+ */
+struct PurseDecisionSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_PurseDecisionCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseRefundSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purse_decision_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseDecisionSerialContext *dsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ bool no_reserve = true;
+ uint64_t rowid;
+ struct TALER_Amount val;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &purse_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ &no_reserve),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &val),
+ GNUNET_PQ_result_spec_uint64 ("purse_decision_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = dsc->cb (dsc->cb_cls,
+ rowid,
+ &purse_pub,
+ no_reserve ? NULL : &reserve_pub,
+ &val);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_select_purse_decisions_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ bool refunded,
+ TALER_EXCHANGEDB_PurseDecisionCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_bool (refunded),
+ GNUNET_PQ_query_param_end
+ };
+ struct PurseDecisionSerialContext dsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "audit_get_purse_decisions_incr",
+ "SELECT"
+ " pd.purse_pub"
+ ",pm.reserve_pub"
+ ",pd.purse_decision_serial_id"
+ ",pr.amount_with_fee"
+ " FROM purse_decision pd"
+ " JOIN purse_requests pr ON (pd.purse_pub = pr.purse_pub)"
+ " LEFT JOIN purse_merges pm ON (pm.purse_pub = pd.purse_pub)"
+ " WHERE ("
+ " (purse_decision_serial_id>=$1) AND "
+ " (refunded=$2)"
+ " )"
+ " ORDER BY purse_decision_serial_id ASC;");
+
+
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "audit_get_purse_decisions_incr",
+ params,
+ &purse_decision_serial_helper_cb,
+ &dsc);
+ if (GNUNET_OK != dsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_purse_deposits_above_serial_id.c b/src/exchangedb/select_purse_deposits_above_serial_id.c
@@ -0,0 +1,198 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_purse_deposits_above_serial_id.c
+ * @brief Implementation of the select_purse_deposits_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_purse_deposits_above_serial_id.h"
+#include "helper.h"
+
+/**
+ * Closure for #purse_deposit_serial_helper_cb().
+ */
+struct PurseDepositSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_PurseDepositCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DepositSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purse_deposit_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseDepositSerialContext *dsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_PurseDeposit deposit = {
+ .exchange_base_url = NULL
+ };
+ struct TALER_DenominationPublicKey denom_pub;
+ uint64_t rowid;
+ uint32_t flags32;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ bool not_merged = false;
+ struct TALER_Amount purse_balance;
+ struct TALER_Amount purse_total;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &deposit.amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ &purse_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("total",
+ &purse_total),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ &deposit.deposit_fee),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("partner_base_url",
+ &deposit.exchange_base_url),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ ¬_merged),
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ &denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &deposit.purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &deposit.coin_sig),
+ GNUNET_PQ_result_spec_uint32 ("flags",
+ &flags32),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &deposit.coin_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &deposit.h_age_commitment),
+ &deposit.no_age_commitment),
+ GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ memset (&deposit,
+ 0,
+ sizeof (deposit));
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = dsc->cb (dsc->cb_cls,
+ rowid,
+ &deposit,
+ not_merged ? NULL : &reserve_pub,
+ (enum TALER_WalletAccountMergeFlags) flags32,
+ &purse_balance,
+ &purse_total,
+ &denom_pub);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_select_purse_deposits_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_PurseDepositCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct PurseDepositSerialContext dsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "audit_get_purse_deposits_incr",
+ "SELECT"
+ " pd.amount_with_fee"
+ ",pr.amount_with_fee AS total"
+ ",pr.balance"
+ ",pr.flags"
+ ",pd.purse_pub"
+ ",pd.coin_sig"
+ ",partner_base_url"
+ ",denom.denom_pub"
+ ",denom.fee_deposit"
+ ",pm.reserve_pub"
+ ",kc.coin_pub"
+ ",kc.age_commitment_hash"
+ ",pd.purse_deposit_serial_id"
+ " FROM purse_deposits pd"
+ " LEFT JOIN partners USING (partner_serial_id)"
+ " LEFT JOIN purse_merges pm USING (purse_pub)"
+ " JOIN purse_requests pr USING (purse_pub)"
+ " JOIN known_coins kc USING (coin_pub)"
+ " JOIN denominations denom USING (denominations_serial)"
+ " WHERE ("
+ " (purse_deposit_serial_id>=$1)"
+ " )"
+ " ORDER BY purse_deposit_serial_id ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "audit_get_purse_deposits_incr",
+ params,
+ &purse_deposit_serial_helper_cb,
+ &dsc);
+ if (GNUNET_OK != dsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_purse_deposits_by_purse.c b/src/exchangedb/select_purse_deposits_by_purse.c
@@ -0,0 +1,149 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_purse_deposits_by_purse.c
+ * @brief Implementation of the select_purse_deposits_by_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_purse_deposits_by_purse.h"
+#include "helper.h"
+
+/**
+ * Closure for #purse_refund_coin_helper_cb().
+ */
+struct PurseRefundCoinContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_PurseRefundCoinCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseRefundCoinContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purse_refund_coin_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseRefundCoinContext *dsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_Amount amount_with_fee;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_DenominationPublicKey denom_pub;
+ uint64_t rowid;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ &denom_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &amount_with_fee),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &coin_pub),
+ GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = dsc->cb (dsc->cb_cls,
+ rowid,
+ &amount_with_fee,
+ &coin_pub,
+ &denom_pub);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_select_purse_deposits_by_purse (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct PurseRefundCoinContext dsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "audit_get_purse_deposits_by_purse",
+ "SELECT"
+ " pd.purse_deposit_serial_id"
+ ",pd.amount_with_fee"
+ ",pd.coin_pub"
+ ",denom.denom_pub"
+ " FROM purse_deposits pd"
+ " JOIN known_coins kc"
+ " USING (coin_pub)"
+ " JOIN denominations denom"
+ " USING (denominations_serial)"
+ " WHERE purse_pub=$1;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "audit_get_purse_deposits_by_purse",
+ params,
+ &purse_refund_coin_helper_cb,
+ &dsc);
+ if (GNUNET_OK != dsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_purse_merge.c b/src/exchangedb/select_purse_merge.c
@@ -0,0 +1,76 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_purse_merge.c
+ * @brief Implementation of the select_purse_merge function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_purse_merge.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_select_purse_merge (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ struct TALER_PurseMergeSignatureP *merge_sig,
+ struct GNUNET_TIME_Timestamp *merge_timestamp,
+ char **partner_url,
+ struct TALER_ReservePublicKeyP *reserve_pub,
+ bool *refunded)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("merge_sig",
+ merge_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ reserve_pub),
+ GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
+ merge_timestamp),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("partner_base_url",
+ partner_url),
+ NULL),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_bool ("refunded",
+ refunded),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+
+ *partner_url = NULL;
+ *refunded = false;
+ PREPARE (pg,
+ "select_purse_merge",
+ "SELECT "
+ " pm.reserve_pub"
+ ",pm.merge_sig"
+ ",pm.merge_timestamp"
+ ",pr.partner_base_url"
+ ",pd.refunded"
+ " FROM purse_merges pm"
+ " LEFT JOIN purse_decision pd USING (purse_pub)"
+ " LEFT JOIN partners pr USING (partner_serial_id)"
+ " WHERE pm.purse_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "select_purse_merge",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/select_purse_merges_above_serial_id.c b/src/exchangedb/select_purse_merges_above_serial_id.c
@@ -0,0 +1,186 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_purse_merges_above_serial_id.c
+ * @brief Implementation of the select_purse_merges_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_purse_merges_above_serial_id.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #purse_deposit_serial_helper_cb().
+ */
+struct PurseMergeSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_PurseMergeCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseMergeSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purse_merges_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseMergeSerialContext *dsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ char *partner_base_url = NULL;
+ struct TALER_Amount amount;
+ struct TALER_Amount balance;
+ uint32_t flags32;
+ enum TALER_WalletAccountMergeFlags flags;
+ struct TALER_PurseMergePublicKeyP merge_pub;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_PurseMergeSignatureP merge_sig;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct GNUNET_TIME_Timestamp merge_timestamp;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ &balance),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("partner_base_url",
+ &partner_base_url),
+ NULL),
+ GNUNET_PQ_result_spec_uint32 ("flags",
+ &flags32),
+ GNUNET_PQ_result_spec_timestamp ("merge_timestamp",
+ &merge_timestamp),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("merge_sig",
+ &merge_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("merge_pub",
+ &merge_pub),
+ GNUNET_PQ_result_spec_uint64 ("purse_merge_request_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ flags = (enum TALER_WalletAccountMergeFlags) flags32;
+ ret = dsc->cb (dsc->cb_cls,
+ rowid,
+ partner_base_url,
+ &amount,
+ &balance,
+ flags,
+ &merge_pub,
+ &reserve_pub,
+ &merge_sig,
+ &purse_pub,
+ merge_timestamp);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_TALER_EXCHANGEDB_select_purse_merges_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_PurseMergeCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct PurseMergeSerialContext dsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "audit_get_purse_merge_incr",
+ "SELECT"
+ " pm.purse_merge_request_serial_id"
+ ",partner_base_url"
+ ",pr.amount_with_fee"
+ ",pr.balance"
+ ",pr.flags"
+ ",pr.merge_pub"
+ ",pm.reserve_pub"
+ ",pm.merge_sig"
+ ",pm.purse_pub"
+ ",pm.merge_timestamp"
+ " FROM purse_merges pm"
+ " JOIN purse_requests pr USING (purse_pub)"
+ " LEFT JOIN partners USING (partner_serial_id)"
+ " WHERE ("
+ " (purse_merge_request_serial_id>=$1)"
+ " )"
+ " ORDER BY purse_merge_request_serial_id ASC;");
+
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "audit_get_purse_merge_incr",
+ params,
+ &purse_merges_serial_helper_cb,
+ &dsc);
+ if (GNUNET_OK != dsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_purse_requests_above_serial_id.c b/src/exchangedb/select_purse_requests_above_serial_id.c
@@ -0,0 +1,174 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_purse_requests_above_serial_id.c
+ * @brief Implementation of the select_purse_requests_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_purse_requests_above_serial_id.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #purse_deposit_serial_helper_cb().
+ */
+struct PurseRequestsSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_PurseRequestCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseRequestsSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purse_requests_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseRequestsSerialContext *dsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct TALER_Amount target_amount;
+ uint32_t age_limit;
+ struct TALER_PurseMergePublicKeyP merge_pub;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_PrivateContractHashP h_contract_terms;
+ struct TALER_PurseContractSignatureP purse_sig;
+ struct GNUNET_TIME_Timestamp purse_creation;
+ struct GNUNET_TIME_Timestamp purse_expiration;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &target_amount),
+ GNUNET_PQ_result_spec_uint32 ("age_limit",
+ &age_limit),
+ GNUNET_PQ_result_spec_timestamp ("purse_creation",
+ &purse_creation),
+ GNUNET_PQ_result_spec_timestamp ("purse_expiration",
+ &purse_expiration),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &purse_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &h_contract_terms),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_sig",
+ &purse_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("merge_pub",
+ &merge_pub),
+ GNUNET_PQ_result_spec_uint64 ("purse_requests_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dsc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = dsc->cb (dsc->cb_cls,
+ rowid,
+ &purse_pub,
+ &merge_pub,
+ purse_creation,
+ purse_expiration,
+ &h_contract_terms,
+ age_limit,
+ &target_amount,
+ &purse_sig);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_select_purse_requests_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_PurseRequestCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct PurseRequestsSerialContext dsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "audit_get_purse_requests_incr",
+ "SELECT"
+ " purse_requests_serial_id"
+ ",purse_pub"
+ ",amount_with_fee"
+ ",age_limit"
+ ",h_contract_terms"
+ ",purse_creation"
+ ",purse_expiration"
+ ",merge_pub"
+ ",purse_sig"
+ " FROM purse_requests"
+ " WHERE ("
+ " (purse_requests_serial_id>=$1)"
+ " )"
+ " ORDER BY purse_requests_serial_id ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "audit_get_purse_requests_incr",
+ params,
+ &purse_requests_serial_helper_cb,
+ &dsc);
+ if (GNUNET_OK != dsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_recoup_above_serial_id.c b/src/exchangedb/select_recoup_above_serial_id.c
@@ -0,0 +1,184 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_recoup_above_serial_id.c
+ * @brief Implementation of the select_recoup_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_recoup_above_serial_id.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #recoup_serial_helper_cb().
+ */
+struct RecoupSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_RecoupCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RecoupSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+recoup_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RecoupSerialContext *psc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = psc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_CoinPublicInfo coin;
+ struct TALER_CoinSpendSignatureP coin_sig;
+ union GNUNET_CRYPTO_BlindingSecretP coin_blind;
+ struct TALER_Amount amount;
+ struct TALER_DenominationPublicKey denom_pub;
+ struct GNUNET_TIME_Timestamp timestamp;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("recoup_uuid",
+ &rowid),
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ ×tamp),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &coin.coin_pub),
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ &denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &coin_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+ &coin_blind),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &coin.denom_pub_hash),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &coin.h_age_commitment),
+ &coin.no_age_commitment),
+ TALER_PQ_result_spec_denom_sig ("denom_sig",
+ &coin.denom_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_end
+ };
+ int ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ psc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = psc->cb (psc->cb_cls,
+ rowid,
+ timestamp,
+ &amount,
+ &reserve_pub,
+ &coin,
+ &denom_pub,
+ &coin_sig,
+ &coin_blind);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_recoup_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_RecoupCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct RecoupSerialContext psc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "recoup_get_incr",
+ "SELECT"
+ " recoup_uuid"
+ ",recoup_timestamp"
+ ",withdraw.reserve_pub"
+ ",coins.coin_pub"
+ ",coin_sig"
+ ",coin_blind"
+ ",denoms.denom_pub_hash"
+ ",coins.denom_sig"
+ ",coins.age_commitment_hash"
+ ",denoms.denom_pub"
+ ",amount"
+ " FROM recoup"
+ " JOIN known_coins coins"
+ " USING (coin_pub)"
+ " JOIN withdraw"
+ " USING (withdraw_id)"
+ " JOIN denominations denoms"
+ " ON (coins.denominations_serial = denoms.denominations_serial)"
+ " WHERE recoup_uuid>=$1"
+ " ORDER BY recoup_uuid ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "recoup_get_incr",
+ params,
+ &recoup_serial_helper_cb,
+ &psc);
+ if (GNUNET_OK != psc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_recoup_refresh_above_serial_id.c b/src/exchangedb/select_recoup_refresh_above_serial_id.c
@@ -0,0 +1,204 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_recoup_refresh_above_serial_id.c
+ * @brief Implementation of the select_recoup_refresh_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_recoup_refresh_above_serial_id.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #recoup_refresh_serial_helper_cb().
+ */
+struct RecoupRefreshSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_RecoupRefreshCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RecoupRefreshSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+recoup_refresh_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RecoupRefreshSerialContext *psc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = psc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct TALER_CoinSpendPublicKeyP old_coin_pub;
+ struct TALER_CoinPublicInfo coin;
+ struct TALER_CoinSpendSignatureP coin_sig;
+ union GNUNET_CRYPTO_BlindingSecretP coin_blind;
+ struct TALER_DenominationPublicKey denom_pub;
+ struct TALER_DenominationHashP old_denom_pub_hash;
+ struct TALER_Amount amount;
+ struct TALER_BlindedCoinHashP h_blind_ev;
+ struct GNUNET_TIME_Timestamp timestamp;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
+ &rowid),
+ GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
+ ×tamp),
+ GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+ &old_coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("old_denom_pub_hash",
+ &old_denom_pub_hash),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &coin.coin_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
+ &coin_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+ &coin_blind),
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ &denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
+ &h_blind_ev),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &coin.denom_pub_hash),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &coin.h_age_commitment),
+ &coin.no_age_commitment),
+ TALER_PQ_result_spec_denom_sig ("denom_sig",
+ &coin.denom_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ psc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = psc->cb (psc->cb_cls,
+ rowid,
+ timestamp,
+ &amount,
+ &old_coin_pub,
+ &old_denom_pub_hash,
+ &coin,
+ &denom_pub,
+ &coin_sig,
+ &coin_blind);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_recoup_refresh_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_RecoupRefreshCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct RecoupRefreshSerialContext psc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_recoup_refresh_above_serial_id",
+ "SELECT"
+ " rr.recoup_refresh_uuid"
+ ",rr.recoup_timestamp"
+ ",rr.coin_sig"
+ ",rr.coin_blind"
+ ",rr.amount"
+ ",rrc.h_coin_ev AS h_blind_ev" // FIXME:-#9828 r.rc? r.selected_h? Old logic wanted a TALER_BlindedCoinHash, which we now need to derive (from rr.coin_blind)
+ ",new_coins.age_commitment_hash"
+ ",new_coins.coin_pub AS coin_pub"
+ ",new_denoms.denom_pub AS denom_pub"
+ ",new_denoms.denom_pub_hash"
+ ",new_coins.denom_sig AS denom_sig"
+ ",old_coins.coin_pub AS old_coin_pub"
+ ",old_denoms.denom_pub_hash AS old_denom_pub_hash"
+ " FROM recoup_refresh rr"
+ " INNER JOIN refresh_revealed_coins rrc" // FIXME-#9828: no such table anymore!
+ // but we have 'refresh_id" which is an FK into 'refresh'!
+ " USING (rrc_serial)"
+ " INNER JOIN refresh r"
+ // but we have 'refresh_id" which is an FK into 'refresh'!
+ " USING (refresh_id)"
+ " INNER JOIN known_coins old_coins"
+ " ON (r.old_coin_pub = old_coins.coin_pub)"
+ " INNER JOIN known_coins new_coins"
+ " ON (rr.coin_pub == new_coins.coin_pub)"
+ " INNER JOIN refresh_commitments rfc"
+ " ON (rrc.melt_serial_id = rfc.melt_serial_id)"
+ " INNER JOIN denominations new_denoms"
+ " ON (new_coins.denominations_serial = new_denoms.denominations_serial)"
+ " INNER JOIN denominations old_denoms"
+ " ON (old_coins.denominations_serial = old_denoms.denominations_serial)"
+ " WHERE recoup_refresh_uuid>=$1"
+ " ORDER BY recoup_refresh_uuid ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_recoup_refresh_above_serial_id",
+ params,
+ &recoup_refresh_serial_helper_cb,
+ &psc);
+ if (GNUNET_OK != psc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_refreshes_above_serial_id.c b/src/exchangedb/select_refreshes_above_serial_id.c
@@ -0,0 +1,180 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_refreshes_above_serial_id.c
+ * @brief Implementation of the select_refreshes_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_refreshes_above_serial_id.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #refreshs_serial_helper_cb().
+ */
+struct RefreshsSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_RefreshesCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RefreshsSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+refreshs_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RefreshsSerialContext *rsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_DenominationPublicKey old_denom_pub;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_CoinSpendSignatureP coin_sig;
+ struct TALER_AgeCommitmentHashP h_age_commitment;
+ bool ac_isnull;
+ struct TALER_Amount amount_with_fee;
+ uint64_t rowid;
+ struct TALER_RefreshCommitmentP rc;
+ size_t num_nds;
+ uint64_t *nds;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_denom_pub ("old_denom_pub",
+ &old_denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
+ &coin_pub),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
+ &h_age_commitment),
+ &ac_isnull),
+ GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
+ &coin_sig),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &amount_with_fee),
+ GNUNET_PQ_result_spec_uint64 ("refresh_id",
+ &rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("rc",
+ &rc),
+ GNUNET_PQ_result_spec_array_uint64 (pg->conn,
+ "new_denominations_serials",
+ &num_nds,
+ &nds),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ rsc->status = GNUNET_SYSERR;
+ return;
+ }
+
+ ret = rsc->cb (rsc->cb_cls,
+ rowid,
+ &old_denom_pub,
+ &coin_pub,
+ &coin_sig,
+ ac_isnull ? NULL : &h_age_commitment,
+ &amount_with_fee,
+ num_nds,
+ nds,
+ &rc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_refreshes_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_RefreshesCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct RefreshsSerialContext rsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_refreshes_above_serial_id",
+ "SELECT"
+ " denom.denom_pub AS old_denom_pub"
+ ",r.old_coin_pub"
+ ",kc.age_commitment_hash"
+ ",r.old_coin_sig"
+ ",r.amount_with_fee"
+ ",r.refresh_id"
+ ",r.rc"
+ ",r.denom_serials AS new_denominations_serials"
+ " FROM refresh r"
+ " JOIN known_coins kc"
+ " ON (r.old_coin_pub = kc.coin_pub)"
+ " JOIN denominations denom"
+ " ON (kc.denominations_serial = denom.denominations_serial)"
+ " WHERE refresh_id>=$1"
+ " ORDER BY refresh_id ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_refreshes_above_serial_id",
+ params,
+ &refreshs_serial_helper_cb,
+ &rsc);
+ if (GNUNET_OK != rsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_refunds_above_serial_id.c b/src/exchangedb/select_refunds_above_serial_id.c
@@ -0,0 +1,220 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_refunds_above_serial_id.c
+ * @brief Implementation of the select_refunds_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_refunds_above_serial_id.h"
+#include "helper.h"
+
+/**
+ * Closure for #refunds_serial_helper_cb().
+ */
+struct RefundsSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_RefundCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RefundsSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+refunds_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RefundsSerialContext *rsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_EXCHANGEDB_Refund refund;
+ struct TALER_DenominationPublicKey denom_pub;
+ uint64_t rowid;
+ bool full_refund;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+ &refund.details.merchant_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
+ &refund.details.merchant_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &refund.details.h_contract_terms),
+ GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
+ &refund.details.rtransaction_id),
+ TALER_PQ_result_spec_denom_pub ("denom_pub",
+ &denom_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+ &refund.coin.coin_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &refund.details.refund_amount),
+ GNUNET_PQ_result_spec_uint64 ("refund_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ rsc->status = GNUNET_SYSERR;
+ return;
+ }
+ {
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&rowid),
+ GNUNET_PQ_query_param_end
+ };
+ struct TALER_Amount amount_with_fee;
+ uint64_t s_f;
+ uint64_t s_v;
+ struct GNUNET_PQ_ResultSpec rs2[] = {
+ GNUNET_PQ_result_spec_uint64 ("s_v",
+ &s_v),
+ GNUNET_PQ_result_spec_uint64 ("s_f",
+ &s_f),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &amount_with_fee),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "test_refund_full",
+ params,
+ rs2);
+ if (qs <= 0)
+ {
+ GNUNET_break (0);
+ rsc->status = GNUNET_SYSERR;
+ return;
+ }
+ /* normalize */
+ s_v += s_f / TALER_AMOUNT_FRAC_BASE;
+ s_f %= TALER_AMOUNT_FRAC_BASE;
+ full_refund = (s_v >= amount_with_fee.value) &&
+ (s_f >= amount_with_fee.fraction);
+ }
+ ret = rsc->cb (rsc->cb_cls,
+ rowid,
+ &denom_pub,
+ &refund.coin.coin_pub,
+ &refund.details.merchant_pub,
+ &refund.details.merchant_sig,
+ &refund.details.h_contract_terms,
+ refund.details.rtransaction_id,
+ full_refund,
+ &refund.details.refund_amount);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_refunds_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_RefundCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct RefundsSerialContext rsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Fetch refunds with rowid '\geq' the given parameter */
+ PREPARE (pg,
+ "audit_get_refunds_incr",
+ "SELECT"
+ " bdep.merchant_pub"
+ ",ref.merchant_sig"
+ ",bdep.h_contract_terms"
+ ",ref.rtransaction_id"
+ ",denom.denom_pub"
+ ",kc.coin_pub"
+ ",ref.amount_with_fee"
+ ",ref.refund_serial_id"
+ " FROM refunds ref"
+ " JOIN batch_deposits bdep"
+ " ON (ref.batch_deposit_serial_id=bdep.batch_deposit_serial_id)"
+ " JOIN coin_deposits cdep"
+ " ON (ref.coin_pub=cdep.coin_pub AND ref.batch_deposit_serial_id=cdep.batch_deposit_serial_id)"
+ " JOIN known_coins kc"
+ " ON (cdep.coin_pub=kc.coin_pub)"
+ " JOIN denominations denom"
+ " ON (kc.denominations_serial=denom.denominations_serial)"
+ " WHERE ref.refund_serial_id>=$1"
+ " ORDER BY ref.refund_serial_id ASC;");
+ PREPARE (pg,
+ "test_refund_full",
+ "SELECT"
+ " CAST(SUM(CAST((ref.amount_with_fee).frac AS INT8)) AS INT8) AS s_f"
+ ",CAST(SUM((ref.amount_with_fee).val) AS INT8) AS s_v"
+ ",cdep.amount_with_fee"
+ " FROM refunds ref"
+ " JOIN coin_deposits cdep"
+ " ON (ref.coin_pub=cdep.coin_pub AND ref.batch_deposit_serial_id=cdep.batch_deposit_serial_id)"
+ " WHERE ref.refund_serial_id=$1"
+ " GROUP BY (cdep.amount_with_fee);");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "audit_get_refunds_incr",
+ params,
+ &refunds_serial_helper_cb,
+ &rsc);
+ if (GNUNET_OK != rsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_refunds_by_coin.c b/src/exchangedb/select_refunds_by_coin.c
@@ -0,0 +1,139 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022-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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_refunds_by_coin.c
+ * @brief Implementation of the select_refunds_by_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_refunds_by_coin.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #get_refunds_cb().
+ */
+struct SelectRefundContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_RefundCoinCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Set to #GNUNET_SYSERR on error.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct SelectRefundContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+get_refunds_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SelectRefundContext *srctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = srctx->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_Amount amount_with_fee;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &amount_with_fee),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ srctx->status = GNUNET_SYSERR;
+ return;
+ }
+ if (GNUNET_OK !=
+ srctx->cb (srctx->cb_cls,
+ &amount_with_fee))
+ return;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_refunds_by_coin (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_PrivateContractHashP *h_contract,
+ TALER_EXCHANGEDB_RefundCoinCallback cb,
+ void *cb_cls)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (coin_pub),
+ GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+ GNUNET_PQ_query_param_auto_from_type (h_contract),
+ GNUNET_PQ_query_param_end
+ };
+ struct SelectRefundContext srctx = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ const char *query = "get_refunds_by_coin_and_contract";
+
+ PREPARE (pg,
+ query,
+ "SELECT"
+ " ref.amount_with_fee"
+ " FROM refunds ref"
+ " JOIN coin_deposits cdep"
+ " USING (coin_pub,batch_deposit_serial_id)"
+ " JOIN batch_deposits bdep"
+ " ON (ref.batch_deposit_serial_id = bdep.batch_deposit_serial_id)"
+ " WHERE ref.coin_pub=$1"
+ " AND bdep.merchant_pub=$2"
+ " AND bdep.h_contract_terms=$3;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ query,
+ params,
+ &get_refunds_cb,
+ &srctx);
+ if (GNUNET_SYSERR == srctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_reserve_close_info.c b/src/exchangedb/select_reserve_close_info.c
@@ -0,0 +1,62 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_reserve_close_info.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_reserve_close_info.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_reserve_close_info (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ struct TALER_Amount *balance,
+ struct TALER_FullPayto *payto_uri)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_amount ("current_balance",
+ pg->currency,
+ balance),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri->full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "select_reserve_close_info",
+ "SELECT "
+ " r.current_balance"
+ ",wt.payto_uri"
+ " FROM reserves r"
+ " LEFT JOIN reserves_in ri"
+ " USING (reserve_pub)"
+ " LEFT JOIN wire_targets wt"
+ " ON (ri.wire_source_h_payto = wt.wire_target_h_payto)"
+ " WHERE r.reserve_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "select_reserve_close_info",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/select_reserve_close_request_info.c b/src/exchangedb/select_reserve_close_request_info.c
@@ -0,0 +1,73 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2026 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_reserve_close_request_info.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_reserve_close_request_info.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_reserve_close_request_info (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ uint64_t rowid,
+ struct TALER_ReserveSignatureP *reserve_sig,
+ struct GNUNET_TIME_Timestamp *request_timestamp,
+ struct TALER_Amount *close_balance,
+ struct TALER_Amount *close_fee,
+ struct TALER_FullPayto *payto_uri)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_uint64 (&rowid),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ reserve_sig),
+ GNUNET_PQ_result_spec_timestamp ("request_timestamp",
+ request_timestamp),
+ TALER_PQ_result_spec_amount ("close_balance",
+ pg->currency,
+ close_balance),
+ TALER_PQ_result_spec_amount ("close_fee",
+ pg->currency,
+ close_fee),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri->full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ // FIXME: this SQL query is still complete nonsense!
+ PREPARE (pg,
+ "select_reserve_close_request_info",
+ "SELECT "
+ " r.current_balance"
+ ",wt.payto_uri"
+ " FROM reserves r"
+ " LEFT JOIN reserves_in ri"
+ " USING (reserve_pub)"
+ " WHERE r.reserve_pub=$1"
+ " AND r.row_id=$2;");
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "select_reserve_close_request_info",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/select_reserve_closed_above_serial_id.c b/src/exchangedb/select_reserve_closed_above_serial_id.c
@@ -0,0 +1,172 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_reserve_closed_above_serial_id.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_reserve_closed_above_serial_id.h"
+#include "helper.h"
+
+/**
+ * Closure for #reserve_closed_serial_helper_cb().
+ */
+struct ReserveClosedSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_ReserveClosedCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin's context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReserveClosedSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_closed_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveClosedSerialContext *rcsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rcsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_FullPayto receiver_account;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_Amount closing_fee;
+ struct GNUNET_TIME_Timestamp execution_date;
+ uint64_t close_request_row;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("close_uuid",
+ &rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ &execution_date),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid",
+ &wtid),
+ GNUNET_PQ_result_spec_string ("receiver_account",
+ &receiver_account.full_payto),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount_with_fee),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
+ &closing_fee),
+ GNUNET_PQ_result_spec_uint64 ("close_request_row",
+ &close_request_row),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ rcsc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = rcsc->cb (rcsc->cb_cls,
+ rowid,
+ execution_date,
+ &amount_with_fee,
+ &closing_fee,
+ &reserve_pub,
+ receiver_account,
+ &wtid,
+ close_request_row);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_reserve_closed_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_ReserveClosedCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct ReserveClosedSerialContext rcsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (
+ pg,
+ "reserves_close_get_incr",
+ "SELECT"
+ " close_uuid"
+ ",reserves.reserve_pub"
+ ",execution_date"
+ ",wtid"
+ ",wt.payto_uri AS receiver_account"
+ ",amount"
+ ",closing_fee"
+ ",close_request_row"
+ " FROM reserves_close"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " JOIN reserves"
+ " USING (reserve_pub)"
+ " WHERE close_uuid>=$1"
+ " ORDER BY close_uuid ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "reserves_close_get_incr",
+ params,
+ &reserve_closed_serial_helper_cb,
+ &rcsc);
+ if (GNUNET_OK != rcsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_reserve_open_above_serial_id.c b/src/exchangedb/select_reserve_open_above_serial_id.c
@@ -0,0 +1,163 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file select_reserve_open_above_serial_id.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_reserve_open_above_serial_id.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #reserve_open_serial_helper_cb().
+ */
+struct ReserveOpenSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_ReserveOpenCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin's context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReserveOpenSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_open_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveOpenSerialContext *rcsc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rcsc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_ReserveSignatureP reserve_sig;
+ uint32_t requested_purse_limit;
+ struct GNUNET_TIME_Timestamp request_timestamp;
+ struct GNUNET_TIME_Timestamp reserve_expiration;
+ struct TALER_Amount reserve_payment;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("open_request_uuid",
+ &rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ &reserve_sig),
+ GNUNET_PQ_result_spec_timestamp ("request_timestamp",
+ &request_timestamp),
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ &reserve_expiration),
+ GNUNET_PQ_result_spec_uint32 ("requested_purse_limit",
+ &requested_purse_limit),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_payment",
+ &reserve_payment),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ rcsc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = rcsc->cb (rcsc->cb_cls,
+ rowid,
+ &reserve_payment,
+ request_timestamp,
+ reserve_expiration,
+ requested_purse_limit,
+ &reserve_pub,
+ &reserve_sig);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_reserve_open_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_ReserveOpenCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct ReserveOpenSerialContext rcsc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (
+ pg,
+ "reserves_open_get_incr",
+ "SELECT"
+ " open_request_uuid"
+ ",reserve_pub"
+ ",request_timestamp"
+ ",expiration_date"
+ ",reserve_sig"
+ ",reserve_payment"
+ ",requested_purse_limit"
+ " FROM reserves_open_requests"
+ " WHERE open_request_uuid>=$1"
+ " ORDER BY open_request_uuid ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "reserves_open_get_incr",
+ params,
+ &reserve_open_serial_helper_cb,
+ &rcsc);
+ if (GNUNET_OK != rcsc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_reserves_in_above_serial_id.c b/src/exchangedb/select_reserves_in_above_serial_id.c
@@ -0,0 +1,163 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_reserves_in_above_serial_id.c
+ * @brief Implementation of the select_reserves_in_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_reserves_in_above_serial_id.h"
+#include "helper.h"
+
+/**
+ * Closure for #reserves_in_serial_helper_cb().
+ */
+struct ReservesInSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_ReserveInCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReservesInSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserves_in_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReservesInSerialContext *risc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = risc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_Amount credit;
+ struct TALER_FullPayto sender_account_details;
+ struct GNUNET_TIME_Timestamp execution_date;
+ uint64_t rowid;
+ uint64_t wire_reference;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ GNUNET_PQ_result_spec_uint64 ("wire_reference",
+ &wire_reference),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
+ &credit),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ &execution_date),
+ GNUNET_PQ_result_spec_string ("sender_account_details",
+ &sender_account_details.full_payto),
+ GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ risc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = risc->cb (risc->cb_cls,
+ rowid,
+ &reserve_pub,
+ &credit,
+ sender_account_details,
+ wire_reference,
+ execution_date);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_reserves_in_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_ReserveInCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct ReservesInSerialContext risc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_reserves_in_above_serial_id",
+ "SELECT"
+ " reserves.reserve_pub"
+ ",wire_reference"
+ ",credit"
+ ",execution_date"
+ ",wt.payto_uri AS sender_account_details"
+ ",reserve_in_serial_id"
+ " FROM reserves_in"
+ " JOIN reserves"
+ " USING (reserve_pub)"
+ " JOIN wire_targets wt"
+ " ON (wire_source_h_payto = wire_target_h_payto)"
+ " WHERE reserve_in_serial_id>=$1"
+ " ORDER BY reserve_in_serial_id;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_reserves_in_above_serial_id",
+ params,
+ &reserves_in_serial_helper_cb,
+ &risc);
+ if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+ return qs;
+ if (GNUNET_OK != risc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_reserves_in_above_serial_id_by_account.c b/src/exchangedb/select_reserves_in_above_serial_id_by_account.c
@@ -0,0 +1,166 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_reserves_in_above_serial_id_by_account.c
+ * @brief Implementation of the select_reserves_in_above_serial_id_by_account function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include \
+ "taler/exchange-database/select_reserves_in_above_serial_id_by_account.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #reserves_in_serial_helper_cb().
+ */
+struct ReservesInSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_ReserveInCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReservesInSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserves_in_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReservesInSerialContext *risc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = risc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_Amount credit;
+ struct TALER_FullPayto sender_account_details;
+ struct GNUNET_TIME_Timestamp execution_date;
+ uint64_t rowid;
+ uint64_t wire_reference;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ GNUNET_PQ_result_spec_uint64 ("wire_reference",
+ &wire_reference),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
+ &credit),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ &execution_date),
+ GNUNET_PQ_result_spec_string ("sender_account_details",
+ &sender_account_details.full_payto),
+ GNUNET_PQ_result_spec_uint64 ("reserve_in_serial_id",
+ &rowid),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ risc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = risc->cb (risc->cb_cls,
+ rowid,
+ &reserve_pub,
+ &credit,
+ sender_account_details,
+ wire_reference,
+ execution_date);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_select_reserves_in_above_serial_id_by_account (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *account_name,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_ReserveInCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_string (account_name),
+ GNUNET_PQ_query_param_end
+ };
+ struct ReservesInSerialContext risc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_reserves_in_above_serial_id_by_account",
+ "SELECT"
+ " reserves.reserve_pub"
+ ",wire_reference"
+ ",credit"
+ ",execution_date"
+ ",wt.payto_uri AS sender_account_details"
+ ",reserve_in_serial_id"
+ " FROM reserves_in"
+ " JOIN reserves "
+ " USING (reserve_pub)"
+ " JOIN wire_targets wt"
+ " ON (wire_source_h_payto = wire_target_h_payto)"
+ " WHERE reserve_in_serial_id>=$1"
+ " AND exchange_account_section=$2"
+ " ORDER BY reserve_in_serial_id ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_reserves_in_above_serial_id_by_account",
+ params,
+ &reserves_in_serial_helper_cb,
+ &risc);
+ if (GNUNET_OK != risc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_wire_out_above_serial_id.c b/src/exchangedb/select_wire_out_above_serial_id.c
@@ -0,0 +1,154 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_wire_out_above_serial_id.c
+ * @brief Implementation of the select_wire_out_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_wire_out_above_serial_id.h"
+#include "helper.h"
+
+/**
+ * Closure for #wire_out_serial_helper_cb().
+ */
+struct WireOutSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_WireTransferOutCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ int status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WireOutSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+wire_out_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireOutSerialContext *wosc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = wosc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct GNUNET_TIME_Timestamp date;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ struct TALER_FullPayto payto_uri;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
+ &rowid),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ &date),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+ &wtid),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri.full_payto),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_end
+ };
+ int ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ wosc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = wosc->cb (wosc->cb_cls,
+ rowid,
+ date,
+ &wtid,
+ payto_uri,
+ &amount);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_wire_out_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_WireTransferOutCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct WireOutSerialContext wosc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_wire_out_above_serial_id",
+ "SELECT"
+ " wo.wireout_uuid"
+ ",wo.execution_date"
+ ",wo.wtid_raw"
+ ",wt.payto_uri"
+ ",wo.amount"
+ " FROM wire_out wo"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " WHERE wireout_uuid>=$1"
+ " ORDER BY wireout_uuid ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_wire_out_above_serial_id",
+ params,
+ &wire_out_serial_helper_cb,
+ &wosc);
+ if (GNUNET_OK != wosc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_wire_out_above_serial_id_by_account.c b/src/exchangedb/select_wire_out_above_serial_id_by_account.c
@@ -0,0 +1,157 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_wire_out_above_serial_id_by_account.c
+ * @brief Implementation of the select_wire_out_above_serial_id_by_account function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_wire_out_above_serial_id_by_account.h"
+#include "helper.h"
+
+/**
+ * Closure for #wire_out_serial_helper_cb().
+ */
+struct WireOutSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_WireTransferOutCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ int status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WireOutSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+wire_out_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireOutSerialContext *wosc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = wosc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct GNUNET_TIME_Timestamp date;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ struct TALER_FullPayto payto_uri;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
+ &rowid),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ &date),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
+ &wtid),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri.full_payto),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_end
+ };
+ int ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ wosc->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = wosc->cb (wosc->cb_cls,
+ rowid,
+ date,
+ &wtid,
+ payto_uri,
+ &amount);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_TALER_EXCHANGEDB_select_wire_out_above_serial_id_by_account (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *account_name,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_WireTransferOutCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_string (account_name),
+ GNUNET_PQ_query_param_end
+ };
+ struct WireOutSerialContext wosc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_wire_out_above_serial_id_by_account",
+ "SELECT"
+ " wo.wireout_uuid"
+ ",wo.execution_date"
+ ",wo.wtid_raw"
+ ",wt.payto_uri"
+ ",wo.amount"
+ " FROM wire_out wo"
+ " JOIN wire_targets wt"
+ " USING (wire_target_h_payto)"
+ " WHERE wo.wireout_uuid>=$1 "
+ " AND wo.exchange_account_section=$2"
+ " ORDER BY wo.wireout_uuid ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_wire_out_above_serial_id_by_account",
+ params,
+ &wire_out_serial_helper_cb,
+ &wosc);
+ if (GNUNET_OK != wosc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_withdraw_amounts_for_kyc_check.c b/src/exchangedb/select_withdraw_amounts_for_kyc_check.c
@@ -0,0 +1,158 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_withdraw_amounts_for_kyc_check.c
+ * @brief Implementation of the select_withdraw_amounts_for_kyc_check function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_withdraw_amounts_for_kyc_check.h"
+#include "taler/exchange-database/select_aggregation_amounts_for_kyc_check.h"
+#include "helper.h"
+
+
+/**
+ * Closure for #get_kyc_amounts_cb().
+ */
+struct KycAmountCheckContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_KYCLOGIC_KycAmountCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Flag set to #GNUNET_OK as long as everything is fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+
+};
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct KycAmountCheckContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+get_kyc_amounts_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycAmountCheckContext *ctx = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct GNUNET_TIME_Absolute date;
+ struct TALER_Amount amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &amount),
+ GNUNET_PQ_result_spec_absolute_time ("date",
+ &date),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->status = GNUNET_SYSERR;
+ return;
+ }
+ ret = ctx->cb (ctx->cb_cls,
+ &amount,
+ date);
+ GNUNET_PQ_cleanup_result (rs);
+ switch (ret)
+ {
+ case GNUNET_OK:
+ continue;
+ case GNUNET_NO:
+ break;
+ case GNUNET_SYSERR:
+ ctx->status = GNUNET_SYSERR;
+ break;
+ }
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_withdraw_amounts_for_kyc_check (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_KYCLOGIC_KycAmountCallback kac,
+ void *kac_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_absolute_time (&time_limit),
+ GNUNET_PQ_query_param_end
+ };
+ struct KycAmountCheckContext ctx = {
+ .cb = kac,
+ .cb_cls = kac_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "select_withdraw_amounts_for_kyc_check",
+ "SELECT"
+ " wd.amount_with_fee AS amount"
+ ",wd.execution_date AS date"
+ " FROM reserves_in ri"
+ " JOIN reserve_history rh"
+ " ON (rh.reserve_pub = ri.reserve_pub)"
+ " JOIN withdraw wd"
+ " ON (wd.withdraw_id = rh.serial_id)"
+ " WHERE ri.wire_source_h_payto IN ("
+ " SELECT wire_target_h_payto"
+ " FROM wire_targets"
+ " WHERE h_normalized_payto=$1"
+ " )"
+ " AND rh.table_name='withdraw'"
+ " AND wd.execution_date >= $2"
+ " ORDER BY rh.reserve_history_serial_id DESC");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ pg->conn,
+ "select_withdraw_amounts_for_kyc_check",
+ params,
+ &get_kyc_amounts_cb,
+ &ctx);
+ if (GNUNET_OK != ctx.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/select_withdrawals_above_serial_id.c b/src/exchangedb/select_withdrawals_above_serial_id.c
@@ -0,0 +1,212 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/select_withdrawals_above_serial_id.c
+ * @brief Implementation of the select_withdrawals_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/select_withdrawals_above_serial_id.h"
+#include "helper.h"
+
+/**
+ * Closure for #withdraw_serial_helper_cb().
+ */
+struct WithdrawSerialContext
+{
+
+ /**
+ * Callback to call.
+ */
+ TALER_EXCHANGEDB_WithdrawCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct TALER_EXCHANGEDB_PostgresContext *pg;
+
+ /**
+ * Status code, set to #GNUNET_SYSERR on hard errors.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Helper function to be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WithdrawSerialContext`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+withdraw_serial_helper_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WithdrawSerialContext *rosc = cls;
+ struct TALER_EXCHANGEDB_PostgresContext *pg = rosc->pg;
+
+ for (unsigned int i = 0; i<num_results; i++)
+ {
+ uint64_t rowid;
+ struct TALER_HashBlindedPlanchetsP h_planchets;
+ struct GNUNET_TIME_Timestamp execution_date;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_ReserveSignatureP reserve_sig;
+ uint16_t max_age;
+ bool no_max_age;
+ uint16_t noreveal_index;
+ bool no_noreveal_index;
+ struct TALER_HashBlindedPlanchetsP selected_h;
+ bool no_selected_h;
+ struct TALER_BlindingMasterSeedP blinding_seed;
+ bool no_blinding_seed;
+ size_t num_denom_serials;
+ uint64_t *denom_serials = NULL;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("withdraw_id",
+ &rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("planchets_h",
+ &h_planchets),
+ GNUNET_PQ_result_spec_timestamp ("execution_date",
+ &execution_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+ &amount_with_fee),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
+ &reserve_sig),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint16 ("max_age",
+ &max_age),
+ &no_max_age),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint16 ("noreveal_index",
+ &noreveal_index),
+ &no_noreveal_index),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type (
+ "selected_h",
+ &selected_h),
+ &no_selected_h),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_auto_from_type (
+ "blinding_seed",
+ &blinding_seed),
+ &no_blinding_seed),
+ GNUNET_PQ_result_spec_array_uint64 (
+ pg->conn,
+ "denom_serials",
+ &num_denom_serials,
+ &denom_serials),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ rosc->status = GNUNET_SYSERR;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ if ((! no_max_age) &&
+ ((255 <= noreveal_index) || (255 <= max_age)))
+ {
+ GNUNET_break (0);
+ rosc->status = GNUNET_SYSERR;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ ret = rosc->cb (rosc->cb_cls,
+ rowid,
+ num_denom_serials,
+ denom_serials,
+ no_selected_h ? NULL : &selected_h,
+ &h_planchets,
+ no_blinding_seed ? NULL : &blinding_seed,
+ ! no_max_age,
+ (uint8_t) max_age,
+ (uint8_t) noreveal_index,
+ &reserve_pub,
+ &reserve_sig,
+ execution_date,
+ &amount_with_fee);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != ret)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_select_withdrawals_above_serial_id (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_WithdrawCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct WithdrawSerialContext rosc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .pg = pg,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Fetch deposits with rowid '\geq' the given parameter */
+ PREPARE (pg,
+ "audit_get_withdraw_incr",
+ "SELECT"
+ " withdraw_id"
+ ",planchets_h"
+ ",execution_date"
+ ",amount_with_fee"
+ ",reserve_pub"
+ ",reserve_sig"
+ ",max_age"
+ ",noreveal_index"
+ ",selected_h"
+ ",blinding_seed"
+ ",denom_serials"
+ " FROM withdraw"
+ " WHERE withdraw_id>=$1"
+ " ORDER BY withdraw_id ASC;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "audit_get_withdraw_incr",
+ params,
+ &withdraw_serial_helper_cb,
+ &rosc);
+ if (GNUNET_OK != rosc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/set_aml_lock.c b/src/exchangedb/set_aml_lock.c
@@ -0,0 +1,70 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/set_aml_lock.c
+ * @brief Implementation of the set_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/set_aml_lock.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_set_aml_lock (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Relative lock_duration,
+ struct GNUNET_TIME_Absolute *existing_lock)
+{
+
+ struct GNUNET_TIME_Absolute expires
+ = GNUNET_TIME_relative_to_absolute (lock_duration);
+ struct GNUNET_TIME_Absolute now
+ = GNUNET_TIME_absolute_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_absolute_time (&expires),
+ GNUNET_PQ_query_param_end
+ };
+ bool nx; /* true if the *account* is not known */
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_absolute_time ("out_aml_program_lock_timeout",
+ existing_lock),
+ &nx),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "set_aml_lock",
+ "SELECT out_aml_program_lock_timeout"
+ " FROM exchange_do_set_aml_lock($1,$2,$3);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "set_aml_lock",
+ params,
+ rs);
+ if (qs <= 0)
+ return qs;
+ if (nx)
+ {
+ *existing_lock = GNUNET_TIME_UNIT_ZERO_ABS;
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ return qs;
+}
diff --git a/src/exchangedb/set_extension_manifest.c b/src/exchangedb/set_extension_manifest.c
@@ -0,0 +1,53 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/set_extension_manifest.c
+ * @brief Implementation of the set_extension_manifest function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/set_extension_manifest.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_set_extension_manifest (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *extension_name,
+ const char *manifest)
+{
+ struct GNUNET_PQ_QueryParam pcfg =
+ (NULL == manifest || 0 == *manifest)
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (manifest);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (extension_name),
+ pcfg,
+ GNUNET_PQ_query_param_end
+ };
+
+
+ PREPARE (pg,
+ "set_extension_manifest",
+ "INSERT INTO extensions (name, manifest) VALUES ($1, $2) "
+ "ON CONFLICT (name) "
+ "DO UPDATE SET manifest=$2");
+
+
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "set_extension_manifest",
+ params);
+}
diff --git a/src/exchangedb/set_purse_balance.c b/src/exchangedb/set_purse_balance.c
@@ -0,0 +1,48 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/set_purse_balance.c
+ * @brief Implementation of the set_purse_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/set_purse_balance.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_set_purse_balance (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_Amount *balance)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ TALER_PQ_query_param_amount (pg->conn,
+ balance),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "set_purse_balance",
+ "UPDATE purse_requests"
+ " SET balance=$2"
+ " WHERE purse_pub=$1;");
+
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "set_purse_balance",
+ params);
+}
diff --git a/src/exchangedb/start.c b/src/exchangedb/start.c
@@ -0,0 +1,51 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/start.c
+ * @brief Implementation of the start function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/exchange-database/preflight.h"
+#include "taler/exchange-database/start.h"
+#include "helper.h"
+
+enum GNUNET_GenericReturnValue
+TALER_EXCHANGEDB_start (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *name)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ GNUNET_assert (NULL != name);
+ if (GNUNET_SYSERR ==
+ TALER_EXCHANGEDB_preflight (pg))
+ return GNUNET_SYSERR;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting transaction `%s'\n",
+ name);
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to start transaction\n");
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ pg->transaction_name = name;
+ return GNUNET_OK;
+}
diff --git a/src/exchangedb/start_deferred_wire_out.c b/src/exchangedb/start_deferred_wire_out.c
@@ -0,0 +1,56 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/start_deferred_wire_out.c
+ * @brief Implementation of the start_deferred_wire_out function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/exchange-database/start_deferred_wire_out.h"
+#include "helper.h"
+#include "taler/exchange-database/preflight.h"
+#include "taler/exchange-database/rollback.h"
+
+enum GNUNET_GenericReturnValue
+TALER_TALER_EXCHANGEDB_start_deferred_wire_out (struct
+ TALER_EXCHANGEDB_PostgresContext
+ *pg)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute (
+ "START TRANSACTION ISOLATION LEVEL READ COMMITTED;"),
+ GNUNET_PQ_make_execute ("SET CONSTRAINTS ALL DEFERRED;"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ if (GNUNET_SYSERR ==
+ TALER_EXCHANGEDB_preflight (pg))
+ return GNUNET_SYSERR;
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ TALER_LOG_ERROR (
+ "Failed to defer wire_out_ref constraint on transaction\n");
+ GNUNET_break (0);
+ TALER_EXCHANGEDB_rollback (pg);
+ return GNUNET_SYSERR;
+ }
+ pg->transaction_name = "deferred wire out";
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting READ COMMITTED DEFERRED transaction `%s'\n",
+ pg->transaction_name);
+ return GNUNET_OK;
+}
diff --git a/src/exchangedb/start_read_committed.c b/src/exchangedb/start_read_committed.c
@@ -0,0 +1,53 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/start_read_committed.c
+ * @brief Implementation of the start_read_committed function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/exchange-database/start_read_committed.h"
+#include "taler/exchange-database/preflight.h"
+#include "helper.h"
+
+enum GNUNET_GenericReturnValue
+TALER_TALER_EXCHANGEDB_start_read_committed (struct
+ TALER_EXCHANGEDB_PostgresContext *
+ pg,
+ const char *name)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL READ COMMITTED"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ GNUNET_assert (NULL != name);
+ if (GNUNET_SYSERR ==
+ TALER_EXCHANGEDB_preflight (pg))
+ return GNUNET_SYSERR;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting READ COMMITTED transaction `%s`\n",
+ name);
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to start transaction\n");
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ pg->transaction_name = name;
+ return GNUNET_OK;
+}
diff --git a/src/exchangedb/start_read_only.c b/src/exchangedb/start_read_only.c
@@ -0,0 +1,53 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/start_read_only.c
+ * @brief Implementation of the start_read_only function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/exchange-database/start_read_only.h"
+#include "taler/exchange-database/preflight.h"
+#include "helper.h"
+
+enum GNUNET_GenericReturnValue
+TALER_TALER_EXCHANGEDB_start_read_only (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *name)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute (
+ "START TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ GNUNET_assert (NULL != name);
+ if (GNUNET_SYSERR ==
+ TALER_EXCHANGEDB_preflight (pg))
+ return GNUNET_SYSERR;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting READ ONLY transaction `%s`\n",
+ name);
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (pg->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to start transaction\n");
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ pg->transaction_name = name;
+ return GNUNET_OK;
+}
diff --git a/src/exchangedb/store_wire_transfer_out.c b/src/exchangedb/store_wire_transfer_out.c
@@ -0,0 +1,63 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/store_wire_transfer_out.c
+ * @brief Implementation of the store_wire_transfer_out function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/store_wire_transfer_out.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_store_wire_transfer_out (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ struct GNUNET_TIME_Timestamp date,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const struct TALER_FullPaytoHashP *h_payto,
+ const char *exchange_account_section,
+ const struct TALER_Amount *amount,
+ const char *extra_wire_subject_metadata)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&date),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_string (exchange_account_section),
+ TALER_PQ_query_param_amount (pg->conn,
+ amount),
+ NULL == extra_wire_subject_metadata
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (extra_wire_subject_metadata),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "insert_wire_out",
+ "INSERT INTO wire_out "
+ "(execution_date"
+ ",wtid_raw"
+ ",wire_target_h_payto"
+ ",exchange_account_section"
+ ",amount"
+ ",extra_wire_subject_metadata"
+ ") VALUES "
+ "($1, $2, $3, $4, $5, $6);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "insert_wire_out",
+ params);
+}
diff --git a/src/exchangedb/template.c b/src/exchangedb/template.c
@@ -0,0 +1,20 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2025 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/template.c
+ * @brief Implementation of the template function for Postgres
+ * @author Christian Grothoff
+ */
diff --git a/src/exchangedb/pg_template.sh b/src/exchangedb/template.sh
diff --git a/src/exchangedb/test_aml_officer.c b/src/exchangedb/test_aml_officer.c
@@ -0,0 +1,52 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/test_aml_officer.c
+ * @brief Implementation of the test_aml_officer function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/test_aml_officer.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_test_aml_officer (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ bool *read_only)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (decider_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_bool ("read_only",
+ read_only),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (pg,
+ "test_aml_staff",
+ "SELECT read_only"
+ " FROM aml_staff"
+ " WHERE decider_pub=$1"
+ " AND is_active;");
+ return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+ "test_aml_staff",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/trigger_kyc_rule_for_account.c b/src/exchangedb/trigger_kyc_rule_for_account.c
@@ -0,0 +1,98 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/trigger_kyc_rule_for_account.c
+ * @brief Implementation of the trigger_kyc_rule_for_account function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/trigger_kyc_rule_for_account.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_trigger_kyc_rule_for_account (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPayto payto_uri,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const union TALER_AccountPublicKeyP *set_account_pub,
+ const struct TALER_MerchantPublicKeyP *check_merchant_pub,
+ const json_t *jmeasures,
+ uint32_t display_priority,
+ uint64_t *requirement_row,
+ bool *bad_kyc_auth)
+{
+ struct GNUNET_TIME_Absolute now
+ = GNUNET_TIME_absolute_get ();
+ struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = *h_payto
+ };
+ char *notify_str
+ = GNUNET_PQ_get_event_notify_channel (&rep.header);
+ struct TALER_FullPaytoHashP h_full_payto;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ NULL == set_account_pub
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (set_account_pub),
+ NULL == check_merchant_pub
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (check_merchant_pub),
+ NULL == payto_uri.full_payto
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (payto_uri.full_payto),
+ NULL == payto_uri.full_payto
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (&h_full_payto),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ TALER_PQ_query_param_json (jmeasures),
+ GNUNET_PQ_query_param_uint32 (&display_priority),
+ GNUNET_PQ_query_param_string (notify_str),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 (
+ "legitimization_measure_serial_id",
+ requirement_row),
+ GNUNET_PQ_result_spec_bool (
+ "bad_kyc_auth",
+ bad_kyc_auth),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "trigger_kyc_rule_for_account",
+ "SELECT"
+ " out_legitimization_measure_serial_id"
+ " AS legitimization_measure_serial_id"
+ " ,out_bad_kyc_auth"
+ " AS bad_kyc_auth"
+ " FROM exchange_do_trigger_kyc_rule_for_account"
+ "($1, $2, $3, $4, $5, $6, $7::TEXT::JSONB, $8, $9);");
+ if (NULL != payto_uri.full_payto)
+ TALER_full_payto_hash (payto_uri,
+ &h_full_payto);
+ qs = GNUNET_PQ_eval_prepared_singleton_select (
+ pg->conn,
+ "trigger_kyc_rule_for_account",
+ params,
+ rs);
+ GNUNET_free (notify_str);
+ return qs;
+}
diff --git a/src/exchangedb/update_aggregation_transient.c b/src/exchangedb/update_aggregation_transient.c
@@ -0,0 +1,54 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/update_aggregation_transient.c
+ * @brief Implementation of the update_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/update_aggregation_transient.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_update_aggregation_transient (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPaytoHashP *h_payto,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ uint64_t kyc_requirement_row,
+ const struct TALER_Amount *total)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (pg->conn,
+ total),
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_uint64 (&kyc_requirement_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "update_aggregation_transient",
+ "UPDATE aggregation_transient"
+ " SET amount=$1"
+ " ,legitimization_requirement_serial_id=$4"
+ " WHERE wire_target_h_payto=$2"
+ " AND wtid_raw=$3");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "update_aggregation_transient",
+ params);
+}
diff --git a/src/exchangedb/update_auditor.c b/src/exchangedb/update_auditor.c
@@ -0,0 +1,56 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/update_auditor.c
+ * @brief Implementation of the update_auditor function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/update_auditor.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_update_auditor (struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_AuditorPublicKeyP *
+ auditor_pub,
+ const char *auditor_url,
+ const char *auditor_name,
+ struct GNUNET_TIME_Timestamp change_date,
+ bool enabled)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (auditor_pub),
+ GNUNET_PQ_query_param_string (auditor_url),
+ GNUNET_PQ_query_param_string (auditor_name),
+ GNUNET_PQ_query_param_bool (enabled),
+ GNUNET_PQ_query_param_timestamp (&change_date),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "update_auditor",
+ "UPDATE auditors"
+ " SET"
+ " auditor_url=$2"
+ " ,auditor_name=$3"
+ " ,is_active=$4"
+ " ,last_change=$5"
+ " WHERE auditor_pub=$1");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "update_auditor",
+ params);
+}
diff --git a/src/exchangedb/update_kyc_process_by_row.c b/src/exchangedb/update_kyc_process_by_row.c
@@ -0,0 +1,131 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/update_kyc_process_by_row.c
+ * @brief Implementation of the update_kyc_process_by_row function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_error_codes.h"
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/update_kyc_process_by_row.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_update_kyc_process_by_row (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t process_row,
+ const char *provider_name,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const char *provider_account_id,
+ const char *provider_legitimization_id,
+ const char *redirect_url,
+ struct GNUNET_TIME_Absolute expiration,
+ enum TALER_ErrorCode ec,
+ const char *error_message_hint,
+ bool finished)
+{
+ uint32_t ec32 = (uint32_t) ec;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&process_row),
+ GNUNET_PQ_query_param_string (provider_name),
+ GNUNET_PQ_query_param_auto_from_type (h_payto), /*3*/
+ (NULL != provider_account_id)
+ ? GNUNET_PQ_query_param_string (provider_account_id)
+ : GNUNET_PQ_query_param_null (), /*4*/
+ (NULL != provider_legitimization_id)
+ ? GNUNET_PQ_query_param_string (provider_legitimization_id)
+ : GNUNET_PQ_query_param_null (), /*5*/
+ (NULL != redirect_url)
+ ? GNUNET_PQ_query_param_string (redirect_url)
+ : GNUNET_PQ_query_param_null (), /*6*/
+ GNUNET_PQ_query_param_absolute_time (&expiration),
+ GNUNET_PQ_query_param_uint32 (&ec32), /* 8 */
+ (NULL != error_message_hint)
+ ? GNUNET_PQ_query_param_string (error_message_hint)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_bool (finished), /* 10 */
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Updating KYC data for %llu (%s)\n",
+ (unsigned long long) process_row,
+ provider_name);
+ PREPARE (pg,
+ "update_legitimization_process",
+ "UPDATE legitimization_processes"
+ " SET provider_user_id=$4"
+ " ,provider_legitimization_id=$5"
+ " ,redirect_url=$6"
+ " ,expiration_time=GREATEST(expiration_time,$7)"
+ " ,error_code=$8"
+ " ,error_message=$9"
+ " ,finished=$10"
+ " WHERE"
+ " h_payto=$3"
+ " AND legitimization_process_serial_id=$1"
+ " AND provider_name=$2;");
+ qs = GNUNET_PQ_eval_prepared_non_select (
+ pg->conn,
+ "update_legitimization_process",
+ params);
+ if (qs <= 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to update legitimization process %llu: %d\n",
+ (unsigned long long) process_row,
+ qs);
+ return qs;
+ }
+ if (GNUNET_TIME_absolute_is_future (expiration))
+ {
+ enum GNUNET_DB_QueryStatus qs2;
+ struct TALER_EXCHANGEDB_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = *h_payto
+ };
+ uint32_t trigger_type = 1;
+ struct GNUNET_PQ_QueryParam params2[] = {
+ GNUNET_PQ_query_param_auto_from_type (h_payto),
+ GNUNET_PQ_query_param_uint32 (&trigger_type),
+ GNUNET_PQ_query_param_end
+ };
+
+ GNUNET_PQ_event_notify (pg->conn,
+ &rep.header,
+ NULL,
+ 0);
+ PREPARE (pg,
+ "alert_kyc_status_change",
+ "INSERT INTO kyc_alerts"
+ " (h_payto"
+ " ,trigger_type)"
+ " VALUES"
+ " ($1,$2);");
+ qs2 = GNUNET_PQ_eval_prepared_non_select (
+ pg->conn,
+ "alert_kyc_status_change",
+ params2);
+ if (qs2 < 0)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to store KYC alert: %d\n",
+ qs2);
+ }
+ return qs;
+}
diff --git a/src/exchangedb/update_wire.c b/src/exchangedb/update_wire.c
@@ -0,0 +1,88 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022, 2023, 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/update_wire.c
+ * @brief Implementation of the update_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/update_wire.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_update_wire (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_FullPayto payto_uri,
+ const char *conversion_url,
+ const char *open_banking_gateway,
+ const char *wire_transfer_gateway,
+ const json_t *debit_restrictions,
+ const json_t *credit_restrictions,
+ struct GNUNET_TIME_Timestamp change_date,
+ const struct TALER_MasterSignatureP *master_sig,
+ const char *bank_label,
+ int64_t priority,
+ bool enabled)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (payto_uri.full_payto),
+ GNUNET_PQ_query_param_bool (enabled),
+ NULL == conversion_url
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (conversion_url),
+ enabled
+ ? TALER_PQ_query_param_json (debit_restrictions)
+ : GNUNET_PQ_query_param_null (),
+ enabled
+ ? TALER_PQ_query_param_json (credit_restrictions)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_timestamp (&change_date),
+ NULL == master_sig
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (master_sig),
+ NULL == bank_label
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (bank_label),
+ GNUNET_PQ_query_param_int64 (&priority),
+ NULL == open_banking_gateway
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (open_banking_gateway),
+ NULL == wire_transfer_gateway
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (wire_transfer_gateway),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "update_wire",
+ "UPDATE wire_accounts"
+ " SET"
+ " is_active=$2"
+ " ,conversion_url=$3"
+ " ,debit_restrictions=$4::TEXT::JSONB"
+ " ,credit_restrictions=$5::TEXT::JSONB"
+ " ,last_change=$6"
+ " ,master_sig=$7"
+ " ,bank_label=$8"
+ " ,priority=$9"
+ " ,open_banking_gateway=$10"
+ " ,wire_transfer_gateway=$11"
+ " WHERE payto_uri=$1");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "update_wire",
+ params);
+}
diff --git a/src/exchangedb/wad_in_insert.c b/src/exchangedb/wad_in_insert.c
@@ -0,0 +1,58 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2024 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/wad_in_insert.c
+ * @brief Implementation of the wad_in_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/wad_in_insert.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_wad_in_insert (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ const struct TALER_WadIdentifierP *wad_id,
+ const char *origin_exchange_url,
+ const struct TALER_Amount *amount,
+ struct GNUNET_TIME_Timestamp execution_date,
+ const struct TALER_FullPayto debit_account_uri,
+ const char *section_name,
+ uint64_t serial_id)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (wad_id),
+ GNUNET_PQ_query_param_string (origin_exchange_url),
+ TALER_PQ_query_param_amount (pg->conn,
+ amount),
+ GNUNET_PQ_query_param_timestamp (&execution_date),
+ GNUNET_PQ_query_param_end
+ };
+
+ // FIXME-#7271: should we keep the account data + serial_id?
+ PREPARE (pg,
+ "wad_in_insert",
+ "INSERT INTO wads_in "
+ "(wad_id"
+ ",origin_exchange_url"
+ ",amount"
+ ",arrival_time"
+ ") VALUES "
+ "($1, $2, $3, $4);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "wad_in_insert",
+ params);
+}
diff --git a/src/exchangedb/wire_prepare_data_get.c b/src/exchangedb/wire_prepare_data_get.c
@@ -0,0 +1,138 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/wire_prepare_data_get.c
+ * @brief Implementation of the wire_prepare_data_get function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/wire_prepare_data_get.h"
+#include "helper.h"
+
+/**
+ * Closure for #prewire_cb().
+ */
+struct PrewireContext
+{
+ /**
+ * Function to call on each result.
+ */
+ TALER_EXCHANGEDB_WirePreparationIterator cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * #GNUNET_OK if everything went fine.
+ */
+ enum GNUNET_GenericReturnValue status;
+};
+
+
+/**
+ * Invoke the callback for each result.
+ *
+ * @param cls a `struct MissingWireContext *`
+ * @param result SQL result
+ * @param num_results number of rows in @a result
+ */
+static void
+prewire_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PrewireContext *pc = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t prewire_uuid;
+ char *wire_method;
+ void *buf = NULL;
+ size_t buf_size;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("prewire_uuid",
+ &prewire_uuid),
+ GNUNET_PQ_result_spec_string ("wire_method",
+ &wire_method),
+ GNUNET_PQ_result_spec_variable_size ("buf",
+ &buf,
+ &buf_size),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ pc->status = GNUNET_SYSERR;
+ return;
+ }
+ pc->cb (pc->cb_cls,
+ prewire_uuid,
+ wire_method,
+ buf,
+ buf_size);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_wire_prepare_data_get (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t start_row,
+ uint64_t limit,
+ TALER_EXCHANGEDB_WirePreparationIterator
+ cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&start_row),
+ GNUNET_PQ_query_param_uint64 (&limit),
+ GNUNET_PQ_query_param_end
+ };
+ struct PrewireContext pc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (pg,
+ "wire_prepare_data_get",
+ "SELECT"
+ " prewire_uuid"
+ ",wire_method"
+ ",buf"
+ " FROM prewire"
+ " WHERE prewire_uuid >= $1"
+ " AND finished=FALSE"
+ " AND failed=FALSE"
+ " ORDER BY prewire_uuid ASC"
+ " LIMIT $2;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ "wire_prepare_data_get",
+ params,
+ &prewire_cb,
+ &pc);
+ if (GNUNET_OK != pc.status)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ return qs;
+}
diff --git a/src/exchangedb/wire_prepare_data_insert.c b/src/exchangedb/wire_prepare_data_insert.c
@@ -0,0 +1,51 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/wire_prepare_data_insert.c
+ * @brief Implementation of the wire_prepare_data_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/wire_prepare_data_insert.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_wire_prepare_data_insert (struct
+ TALER_EXCHANGEDB_PostgresContext *pg,
+ const char *type,
+ const char *buf,
+ size_t buf_size)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (type),
+ GNUNET_PQ_query_param_fixed_size (buf, buf_size),
+ GNUNET_PQ_query_param_end
+ };
+
+
+ /* Used in #postgres_wire_prepare_data_insert() to store
+ wire transfer information before actually committing it with the bank */
+ PREPARE (pg,
+ "wire_prepare_data_insert",
+ "INSERT INTO prewire "
+ "(wire_method"
+ ",buf"
+ ") VALUES "
+ "($1, $2);");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "wire_prepare_data_insert",
+ params);
+}
diff --git a/src/exchangedb/wire_prepare_data_mark_failed.c b/src/exchangedb/wire_prepare_data_mark_failed.c
@@ -0,0 +1,44 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/wire_prepare_data_mark_failed.c
+ * @brief Implementation of the wire_prepare_data_mark_failed function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/wire_prepare_data_mark_failed.h"
+#include "helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_wire_prepare_data_mark_failed (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t rowid)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&rowid),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "wire_prepare_data_mark_failed",
+ "UPDATE prewire"
+ " SET failed=TRUE"
+ " WHERE prewire_uuid=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "wire_prepare_data_mark_failed",
+ params);
+}
diff --git a/src/exchangedb/wire_prepare_data_mark_finished.c b/src/exchangedb/wire_prepare_data_mark_finished.c
@@ -0,0 +1,43 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2022 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 <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/wire_prepare_data_mark_finished.c
+ * @brief Implementation of the wire_prepare_data_mark_finished function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/taler_pq_lib.h"
+#include "taler/exchange-database/wire_prepare_data_mark_finished.h"
+#include "helper.h"
+
+enum GNUNET_DB_QueryStatus
+TALER_EXCHANGEDB_wire_prepare_data_mark_finished (
+ struct TALER_EXCHANGEDB_PostgresContext *pg,
+ uint64_t rowid)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&rowid),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (pg,
+ "wire_prepare_data_mark_done",
+ "UPDATE prewire"
+ " SET finished=TRUE"
+ " WHERE prewire_uuid=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+ "wire_prepare_data_mark_done",
+ params);
+}