commit e8a4dded80704b5d21a73d4ccefc403ca53f9828
parent 3f2e0af9919658227a00b0bb18f4bd2de5acecb6
Author: Christian Grothoff <grothoff@gnu.org>
Date: Wed, 8 Apr 2026 21:27:51 +0200
remove DB plugins (part I)
Diffstat:
587 files changed, 59333 insertions(+), 1010 deletions(-)
diff --git a/src/auditordb/del_denomination_balance.c b/src/auditordb/del_denomination_balance.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 src/auditordb/del_denomination_balance.c
+ * @brief Implementation of the del_denomination_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "del_denomination_balance.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_del_denomination_balance (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_del_denomination_balance",
+ "DELETE"
+ " FROM auditor_denomination_pending"
+ " WHERE denom_pub_hash=$1");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_del_denomination_balance",
+ params);
+}
diff --git a/src/auditordb/del_reserve_info.c b/src/auditordb/del_reserve_info.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 pg_del_reserve_info.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "del_reserve_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_del_reserve_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_del_reserve_info",
+ "DELETE"
+ " FROM auditor_reserves"
+ " WHERE reserve_pub=$1");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_del_reserve_info",
+ params);
+}
diff --git a/src/auditordb/delete_auditor_closure_lag.c b/src/auditordb/delete_auditor_closure_lag.c
@@ -0,0 +1,53 @@
+/*
+ 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 src/auditordb/delete_auditor_closure_lag.c
+ * @brief Implementation of the delete_auditor_closure_lag function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "delete_auditor_closure_lag.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_auditor_closure_lag (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_Amount *amount,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ struct TALER_FullPayto credit_account_uri)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (ctx->conn,
+ amount),
+ GNUNET_PQ_query_param_auto_from_type (wtid),
+ GNUNET_PQ_query_param_string (credit_account_uri.full_payto),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "delete_auditor_closure_lag",
+ "DELETE FROM auditor_closure_lags "
+ " WHERE (amount).frac=($1::taler_amount).frac"
+ " AND (amount).val=($1::taler_amount).val"
+ " AND wtid=$2"
+ " AND account=$3;");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "delete_auditor_closure_lag",
+ params);
+}
diff --git a/src/auditordb/delete_early_aggregation.c b/src/auditordb/delete_early_aggregation.c
@@ -0,0 +1,47 @@
+/*
+ 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 src/auditordb/delete_early_aggregation.c
+ * @brief Implementation of the delete_early_aggregation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "delete_early_aggregation.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_early_aggregation (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t batch_deposit_serial_id)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&batch_deposit_serial_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_delete_early_aggregation",
+ "DELETE"
+ " FROM auditor_early_aggregations"
+ " WHERE batch_deposit_serial_id=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (
+ ctx->conn,
+ "auditor_delete_early_aggregation",
+ params);
+}
diff --git a/src/auditordb/delete_generic.c b/src/auditordb/delete_generic.c
@@ -0,0 +1,83 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "delete_generic.h"
+
+struct Preparations
+{
+ /**
+ * Database reconnect counter.
+ */
+ unsigned long long cnt;
+
+ /**
+ * Which DB did we do prepare for.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+};
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_generic (struct AUDITORDB_PostgresContext *ctx,
+ enum TALER_AUDITORDB_DeletableSuppressableTables table,
+ uint64_t row_id)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&row_id),
+ GNUNET_PQ_query_param_end
+ };
+ static struct Preparations preps[
+ TALER_AUDITORDB_DELETABLESUPPRESSABLE_TABLES_MAX];
+
+ struct Preparations *prep = &preps[table];
+ const char *table_name = AUDITORDB_get_deletable_suppressable_table_name (table);
+ char statement_name[256];
+
+ GNUNET_snprintf (statement_name,
+ sizeof (statement_name),
+ "delete_%s",
+ table_name);
+ if ( (ctx != prep->ctx) ||
+ (prep->cnt < ctx->prep_gen) )
+ {
+ char sql[256];
+ struct GNUNET_PQ_PreparedStatement ps[] = {
+ GNUNET_PQ_make_prepare (statement_name,
+ sql),
+ GNUNET_PQ_PREPARED_STATEMENT_END
+ };
+
+ GNUNET_snprintf (sql,
+ sizeof (sql),
+ "DELETE FROM %s"
+ " WHERE row_id=$1",
+ table_name);
+ if (GNUNET_OK !=
+ GNUNET_PQ_prepare_statements (ctx->conn,
+ ps))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ prep->ctx = ctx;
+ prep->cnt = ctx->prep_gen;
+ }
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ statement_name,
+ params);
+}
diff --git a/src/auditordb/delete_pending_deposit.c b/src/auditordb/delete_pending_deposit.c
@@ -0,0 +1,46 @@
+/*
+ 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 src/auditordb/delete_pending_deposit.c
+ * @brief Implementation of the delete_pending_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "delete_pending_deposit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_pending_deposit (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t batch_deposit_serial_id)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&batch_deposit_serial_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_delete_pending_deposit",
+ "DELETE"
+ " FROM auditor_pending_deposits"
+ " WHERE batch_deposit_serial_id=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_delete_pending_deposit",
+ params);
+}
diff --git a/src/auditordb/delete_purse_info.c b/src/auditordb/delete_purse_info.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 src/auditordb/delete_purse_info.c
+ * @brief Implementation of the delete_purse_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "delete_purse_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_purse_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_purses_delete",
+ "DELETE FROM auditor_purses "
+ " WHERE purse_pub=$1");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_purses_delete",
+ params);
+}
diff --git a/src/auditordb/delete_reserve_in_inconsistency.c b/src/auditordb/delete_reserve_in_inconsistency.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 src/auditordb/delete_reserve_in_inconsistency.c
+ * @brief Implementation of the delete_reserve_in_inconsistency function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "delete_reserve_in_inconsistency.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t row_id)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&row_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "delete_reserve_in_inconsistency",
+ "DELETE FROM auditor_reserve_in_inconsistency "
+ " WHERE row_id=$1");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "delete_reserve_in_inconsistency",
+ params);
+}
diff --git a/src/auditordb/delete_wire_out_inconsistency_if_matching.c b/src/auditordb/delete_wire_out_inconsistency_if_matching.c
@@ -0,0 +1,52 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "delete_wire_out_inconsistency_if_matching.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_wire_out_inconsistency_if_matching (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_WireOutInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (dc->destination_account.full_payto),
+ GNUNET_PQ_query_param_string (dc->diagnostic),
+ GNUNET_PQ_query_param_uint64 (&dc->wire_out_row_id),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->expected),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->claimed),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_wire_out_inconsistency_delete_if_matching",
+ "DELETE FROM auditor_wire_out_inconsistency "
+ " WHERE destination_account=$1"
+ " AND diagnostic=$2"
+ " AND wire_out_serial_id=$3"
+ " AND (expected).val=($4::taler_amount).val"
+ " AND (expected).frac=($4::taler_amount).frac"
+ " AND (claimed).val=($5::taler_amount).val"
+ " AND (claimed).frac=($5::taler_amount).frac;"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (
+ ctx->conn,
+ "auditor_wire_out_inconsistency_delete_if_matching",
+ params);
+}
diff --git a/src/auditordb/get_amount_arithmetic_inconsistency.c b/src/auditordb/get_amount_arithmetic_inconsistency.c
@@ -0,0 +1,175 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_amount_arithmetic_inconsistency.h"
+
+/**
+ * Closure for #deposit_confirmation_cb().
+ */
+struct AmountArithmeticInconsistencyContext
+{
+
+ /**
+ * Function to call for each deposit confirmation.
+ */
+ TALER_AUDITORDB_AmountArithmeticInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_deposit_confirmations().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DepositConfirmationContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+amount_arithmetic_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AmountArithmeticInconsistencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_AmountArithmeticInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_uint64 ("problem_row_id",
+ &dc.problem_row_id),
+ GNUNET_PQ_result_spec_string ("operation",
+ &dc.operation),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("exchange_amount",
+ &dc.exchange_amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("auditor_amount",
+ &dc.auditor_amount),
+ GNUNET_PQ_result_spec_bool ("profitable",
+ &dc.profitable),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_amount_arithmetic_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_AmountArithmeticInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct AmountArithmeticInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_amount_arithmetic_inconsistency_select_desc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",operation"
+ ",exchange_amount"
+ ",auditor_amount"
+ ",profitable"
+ ",suppressed"
+ " FROM auditor_amount_arithmetic_inconsistency"
+ " WHERE (row_id<$1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_amount_arithmetic_inconsistency_select_asc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",operation"
+ ",exchange_amount"
+ ",auditor_amount"
+ ",profitable"
+ ",suppressed"
+ " FROM auditor_amount_arithmetic_inconsistency"
+ " WHERE (row_id>$1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_amount_arithmetic_inconsistency_select_asc"
+ : "auditor_amount_arithmetic_inconsistency_select_desc",
+ params,
+ &amount_arithmetic_inconsistency_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_auditor_closure_lags.c b/src/auditordb/get_auditor_closure_lags.c
@@ -0,0 +1,173 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_auditor_closure_lags.h"
+
+
+struct ClosureLagsContext
+{
+
+ /**
+ * Function to call for each closure lag .
+ */
+ TALER_AUDITORDB_ClosureLagsCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_auditor_closure_lags().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ClosureLagsContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+closure_lags_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ClosureLagsContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_ClosureLags dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_uint64 ("problem_row_id",
+ &dc.problem_row_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &dc.amount),
+ GNUNET_PQ_result_spec_absolute_time ("deadline",
+ &dc.deadline),
+ GNUNET_PQ_result_spec_auto_from_type ("wtid",
+ &dc.wtid),
+ GNUNET_PQ_result_spec_string ("account",
+ &dc.account.full_payto),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_auditor_closure_lags (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ClosureLagsCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct ClosureLagsContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_closure_lags_get_desc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",amount"
+ ",deadline"
+ ",wtid"
+ ",account"
+ ",suppressed"
+ " FROM auditor_closure_lags"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_closure_lags_get_asc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",amount"
+ ",deadline"
+ ",wtid"
+ ",account"
+ ",suppressed"
+ " FROM auditor_closure_lags"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_closure_lags_get_asc"
+ : "auditor_closure_lags_get_desc",
+ params,
+ &closure_lags_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_auditor_progress.c b/src/auditordb/get_auditor_progress.c
@@ -0,0 +1,178 @@
+/*
+ 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 pg_get_auditor_progress.c
+ * @brief Implementation of get_auditor_progress function
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_auditor_progress.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #auditor_progress_cb().
+ */
+struct AuditorProgressContext
+{
+
+ /**
+ * Where to store results.
+ */
+ uint64_t **dst;
+
+ /**
+ * Offset in @e dst.
+ */
+ unsigned int off;
+
+ /**
+ * Length of array at @e dst.
+ */
+ unsigned int len;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Set to true on failure.
+ */
+ bool failure;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_auditor_progress().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct AuditorProgressContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+auditor_progress_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AuditorProgressContext *ctx = cls;
+
+ GNUNET_assert (num_results == ctx->len);
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ bool is_missing = false;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("progress_offset",
+ ctx->dst[i]),
+ &is_missing),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->failure = true;
+ return;
+ }
+ if (is_missing)
+ *ctx->dst[i] = 0;
+ ctx->off++;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_auditor_progress (struct AUDITORDB_PostgresContext *ctx,
+ const char *progress_key,
+ uint64_t *progress_offset,
+ ...)
+{
+ unsigned int cnt = 1;
+ va_list ap;
+
+ va_start (ap,
+ progress_offset);
+ while (NULL != va_arg (ap,
+ const char *))
+ {
+ cnt++;
+ (void) va_arg (ap,
+ uint64_t *);
+ }
+ va_end (ap);
+ {
+ const char *keys[cnt];
+ uint64_t *dsts[cnt];
+ unsigned int off = 1;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_array_ptrs_string (cnt,
+ keys,
+ ctx->conn),
+ GNUNET_PQ_query_param_end
+ };
+ struct AuditorProgressContext ctx = {
+ .dst = dsts,
+ .len = cnt,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ keys[0] = progress_key;
+ dsts[0] = progress_offset;
+ va_start (ap,
+ progress_offset);
+ while (off < cnt)
+ {
+ keys[off] = va_arg (ap,
+ const char *);
+ dsts[off] = va_arg (ap,
+ uint64_t *);
+ off++;
+ }
+ GNUNET_assert (NULL == va_arg (ap,
+ const char *));
+ va_end (ap);
+
+ PREPARE (ctx,
+ "get_auditor_progress",
+ "SELECT"
+ " auditor_do_get_auditor_progress AS progress_offset"
+ " FROM auditor_do_get_auditor_progress "
+ "($1);");
+ ctx.off = 0;
+ qs = GNUNET_PQ_eval_prepared_multi_select (ctx->conn,
+ "get_auditor_progress",
+ params,
+ &auditor_progress_cb,
+ &ctx);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ if (ctx.failure)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ if (qs < 0)
+ return qs;
+ GNUNET_assert (ctx.off == cnt);
+ return qs;
+ }
+}
diff --git a/src/auditordb/get_bad_sig_losses.c b/src/auditordb/get_bad_sig_losses.c
@@ -0,0 +1,181 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_bad_sig_losses.h"
+
+
+struct BadSigLossesContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_BadSigLossesCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_bad_sig_losses().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct BadSigLossesContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+bad_sig_losses_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct BadSigLossesContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_BadSigLosses dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_uint64 ("problem_row_id",
+ &dc.problem_row_id),
+ GNUNET_PQ_result_spec_string ("operation",
+ &dc.operation),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("loss",
+ &dc.loss),
+ GNUNET_PQ_result_spec_auto_from_type ("operation_specific_pub",
+ &dc.operation_specific_pub),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_bad_sig_losses (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ const struct GNUNET_CRYPTO_EddsaPublicKey *op_spec_pub,
+ const char *op,
+ TALER_AUDITORDB_BadSigLossesCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ NULL == op_spec_pub
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_auto_from_type (op_spec_pub),
+ NULL == op
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (op),
+ GNUNET_PQ_query_param_end
+ };
+ struct BadSigLossesContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_bad_sig_losses_get_desc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",operation"
+ ",loss"
+ ",operation_specific_pub"
+ ",suppressed"
+ " FROM auditor_bad_sig_losses"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " AND ($4::BYTEA IS NULL OR operation_specific_pub = $4)"
+ " AND ($5::TEXT IS NULL OR operation = $5)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_bad_sig_losses_get_asc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",operation"
+ ",loss"
+ ",operation_specific_pub"
+ ",suppressed"
+ " FROM auditor_bad_sig_losses"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " AND ($4::BYTEA IS NULL OR operation_specific_pub = $4)"
+ " AND ($5::TEXT IS NULL OR operation = $5)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_bad_sig_losses_get_asc"
+ : "auditor_bad_sig_losses_get_desc",
+ params,
+ &bad_sig_losses_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_balance.c b/src/auditordb/get_balance.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 src/auditordb/get_balance.c
+ * @brief Implementation of the get_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_balance.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #balance_cb().
+ */
+struct BalanceContext
+{
+
+ /**
+ * Where to store results.
+ */
+ struct TALER_Amount **dst;
+
+ /**
+ * Offset in @e dst.
+ */
+ unsigned int off;
+
+ /**
+ * Length of array at @e dst.
+ */
+ unsigned int len;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Set to true on failure.
+ */
+ bool failure;
+
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_balance().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct BalanceContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+balance_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct BalanceContext *ctx = cls;
+ struct AUDITORDB_PostgresContext *ctx = ctx->ctx;
+
+ GNUNET_assert (num_results <= ctx->len);
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ bool is_missing;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_allow_null (
+ TALER_PQ_result_spec_amount ("balance",
+ ctx->currency,
+ ctx->dst[i]),
+ &is_missing),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ ctx->failure = true;
+ return;
+ }
+ if (is_missing)
+ {
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (ctx->currency,
+ ctx->dst[i]));
+ }
+ ctx->off++;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_balance (struct AUDITORDB_PostgresContext *ctx,
+ const char *balance_key,
+ struct TALER_Amount *balance_value,
+ ...)
+{
+ unsigned int cnt = 1;
+ va_list ap;
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (ctx->currency,
+ balance_value));
+ va_start (ap,
+ balance_value);
+ while (NULL != va_arg (ap,
+ const char *))
+ {
+ struct TALER_Amount *dst;
+
+ cnt++;
+ dst = va_arg (ap,
+ struct TALER_Amount *);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (ctx->currency,
+ dst));
+ }
+ va_end (ap);
+ {
+ const char *keys[cnt];
+ struct TALER_Amount *dsts[cnt];
+ unsigned int off = 1;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_array_ptrs_string (cnt,
+ keys,
+ ctx->conn),
+ GNUNET_PQ_query_param_end
+ };
+ struct BalanceContext ctx = {
+ .dst = dsts,
+ .len = cnt,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ keys[0] = balance_key;
+ dsts[0] = balance_value;
+ va_start (ap,
+ balance_value);
+ while (off < cnt)
+ {
+ keys[off] = va_arg (ap,
+ const char *);
+ dsts[off] = va_arg (ap,
+ struct TALER_Amount *);
+ off++;
+ }
+ GNUNET_assert (NULL == va_arg (ap,
+ const char *));
+ va_end (ap);
+
+ PREPARE (ctx,
+ "get_balance",
+ "SELECT "
+ " auditor_do_get_balance AS balance"
+ " FROM auditor_do_get_balance "
+ "($1);");
+ qs = GNUNET_PQ_eval_prepared_multi_select (ctx->conn,
+ "get_balance",
+ params,
+ &balance_cb,
+ &ctx);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ if (ctx.failure)
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ if (qs < 0)
+ return qs;
+ GNUNET_assert (qs == ctx.off);
+ return qs;
+ }
+}
diff --git a/src/auditordb/get_balances.c b/src/auditordb/get_balances.c
@@ -0,0 +1,134 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_balances.h"
+
+
+struct BalancesContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_BalancesCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_balances().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct BalancesContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+balances_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct BalancesContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_Balances dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("balance_key",
+ &dc.balance_key),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance_value",
+ &dc.balance_value),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_balances (struct AUDITORDB_PostgresContext *ctx,
+ const char *balance_key,
+ TALER_AUDITORDB_BalancesCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ NULL == balance_key
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (balance_key),
+ GNUNET_PQ_query_param_end
+ };
+ struct BalancesContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_balances_get",
+ "SELECT"
+ " balance_key"
+ ",balance_value"
+ " FROM auditor_balances"
+ " WHERE ($1::TEXT IS NULL OR balance_key = $1)"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ "auditor_balances_get",
+ params,
+ &balances_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_coin_inconsistency.c b/src/auditordb/get_coin_inconsistency.c
@@ -0,0 +1,184 @@
+/*
+ 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/>
+ */
+
+
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_coin_inconsistency.h"
+
+/**
+ * Closure for #deposit_confirmation_cb().
+ */
+struct CoinInconsistencyContext
+{
+
+ /**
+ * Function to call for each deposit confirmation.
+ */
+ TALER_AUDITORDB_CoinInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_deposit_confirmations().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DepositConfirmationContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+coin_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinInconsistencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t serial_id;
+
+ struct TALER_AUDITORDB_CoinInconsistency dc;
+
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &serial_id),
+ GNUNET_PQ_result_spec_string ("operation",
+ &dc.operation),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("exchange_amount",
+ &dc.exchange_amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("auditor_amount",
+ &dc.auditor_amount),
+ GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &dc.coin_pub),
+ GNUNET_PQ_result_spec_bool ("profitable",
+ &dc.profitable),
+
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+
+ dcc->qs = i + 1;
+
+
+ rval = dcc->cb (dcc->cb_cls,
+ serial_id,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_coin_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed, // maybe not needed
+ TALER_AUDITORDB_CoinInconsistencyCallback cb,
+ void *cb_cls)
+{
+
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct CoinInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+
+ PREPARE (ctx,
+ "auditor_coin_inconsistency_select_desc",
+ "SELECT"
+ " row_id"
+ ",operation"
+ ",exchange_amount"
+ ",auditor_amount"
+ ",coin_pub"
+ ",profitable"
+ " FROM auditor_coin_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_coin_inconsistency_select_asc",
+ "SELECT"
+ " row_id"
+ ",operation"
+ ",exchange_amount"
+ ",auditor_amount"
+ ",coin_pub"
+ ",profitable"
+ " FROM auditor_coin_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (ctx->conn,
+ (limit > 0) ?
+ "auditor_coin_inconsistency_select_asc"
+ :
+ "auditor_coin_inconsistency_select_desc",
+ params,
+ &coin_inconsistency_cb,
+ &dcc);
+
+
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
+\ No newline at end of file
diff --git a/src/auditordb/get_denomination_balance.c b/src/auditordb/get_denomination_balance.c
@@ -0,0 +1,66 @@
+/*
+ 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_get_denomination_balance.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_denomination_balance.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_denomination_balance (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ struct TALER_AUDITORDB_DenominationCirculationData *dcd)
+{
+ 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[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("denom_balance",
+ &dcd->denom_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("denom_loss",
+ &dcd->denom_loss),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("denom_risk",
+ &dcd->denom_risk),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("recoup_loss",
+ &dcd->recoup_loss),
+ GNUNET_PQ_result_spec_uint64 ("num_issued",
+ &dcd->num_issued),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (ctx,
+ "auditor_denomination_pending_select",
+ "SELECT"
+ " denom_balance"
+ ",denom_loss"
+ ",num_issued"
+ ",denom_risk"
+ ",recoup_loss"
+ " FROM auditor_denomination_pending"
+ " WHERE denom_pub_hash=$1");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn,
+ "auditor_denomination_pending_select",
+ params,
+ rs);
+}
diff --git a/src/auditordb/get_denomination_key_validity_withdraw_inconsistency.c b/src/auditordb/get_denomination_key_validity_withdraw_inconsistency.c
@@ -0,0 +1,171 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_denomination_key_validity_withdraw_inconsistency.h"
+
+
+/**
+ * Closure for #denomination_key_validity_withdraw_inconsistency_cb().
+ */
+struct DenominationKeyValidityWithdrawInconsistencyContext
+{
+
+ /**
+ * Function to call for each denomination key validity...
+ */
+ TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_deposit_confirmations().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DepositConfirmationContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+denomination_key_validity_withdraw_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct DenominationKeyValidityWithdrawInconsistencyContext *dcc = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_uint64 ("problem_row_id",
+ &dc.problem_row_id),
+ GNUNET_PQ_result_spec_absolute_time ("execution_date",
+ &dc.execution_date),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &dc.reserve_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("denompub_h",
+ &dc.denompub_h),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_denomination_key_validity_withdraw_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct DenominationKeyValidityWithdrawInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_denomination_key_validity_withdraw_inconsistency_get_desc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",execution_date"
+ ",reserve_pub"
+ ",denompub_h"
+ ",suppressed"
+ " FROM auditor_denomination_key_validity_withdraw_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_denomination_key_validity_withdraw_inconsistency_get_asc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",execution_date"
+ ",reserve_pub"
+ ",denompub_h"
+ ",suppressed"
+ " FROM auditor_denomination_key_validity_withdraw_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_denomination_key_validity_withdraw_inconsistency_get_asc"
+ : "auditor_denomination_key_validity_withdraw_inconsistency_get_desc",
+ params,
+ &denomination_key_validity_withdraw_inconsistency_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_denomination_pending.c b/src/auditordb/get_denomination_pending.c
@@ -0,0 +1,171 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_denomination_pending.h"
+
+
+struct DenominationPendingContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_DenominationPendingCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_denomination_pending().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DenominationPendingContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+denomination_pending_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct DenominationPendingContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t serial_id;
+ struct TALER_AUDITORDB_DenominationPending dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &serial_id),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &dc.denom_pub_hash),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("denom_balance",
+ &dc.denom_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("denom_loss",
+ &dc.denom_loss),
+ GNUNET_PQ_result_spec_uint64 ("num_issued",
+ &dc.num_issued),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("denom_risk",
+ &dc.denom_risk),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("recoup_loss",
+ &dc.recoup_loss),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ serial_id,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_denomination_pending (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_DenominationPendingCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct DenominationPendingContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_denomination_pending_get_desc",
+ "SELECT"
+ " row_id,"
+ " denom_pub_hash,"
+ " denom_balance,"
+ " denom_loss,"
+ " num_issued,"
+ " denom_risk,"
+ " recoup_loss"
+ " FROM auditor_denomination_pending"
+ " WHERE (row_id < $1)"
+ " ORDER BY row_id DESC"
+ " LIMIT $2"
+ );
+ PREPARE (ctx,
+ "auditor_denomination_pending_get_asc",
+ "SELECT"
+ " row_id,"
+ " denom_pub_hash,"
+ " denom_balance,"
+ " denom_loss,"
+ " num_issued,"
+ " denom_risk,"
+ " recoup_loss"
+ " FROM auditor_denomination_pending"
+ " WHERE (row_id > $1)"
+ " ORDER BY row_id ASC"
+ " LIMIT $2"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_denomination_pending_get_asc"
+ : "auditor_denomination_pending_get_desc",
+ params,
+ &denomination_pending_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_denominations_without_sigs.c b/src/auditordb/get_denominations_without_sigs.c
@@ -0,0 +1,171 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_denominations_without_sigs.h"
+
+
+struct DenominationsWithoutSigsContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_DenominationsWithoutSigsCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_denominations_without_sigs().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DenominationsWithoutSigsContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+denominations_without_sigs_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct DenominationsWithoutSigsContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_DenominationsWithoutSigs dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_auto_from_type ("denompub_h",
+ &dc.denompub_h),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("value",
+ &dc.value),
+ GNUNET_PQ_result_spec_absolute_time ("start_time",
+ &dc.start_time),
+ GNUNET_PQ_result_spec_absolute_time ("end_time",
+ &dc.end_time),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+
+ dcc->qs = i + 1;
+
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_denominations_without_sigs (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_DenominationsWithoutSigsCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct DenominationsWithoutSigsContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_denominations_without_sigs_get_desc",
+ "SELECT"
+ " row_id,"
+ " denompub_h,"
+ " value,"
+ " start_time,"
+ " end_time,"
+ " suppressed"
+ " FROM auditor_denominations_without_sigs"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_denominations_without_sigs_get_asc",
+ "SELECT"
+ " row_id,"
+ " denompub_h,"
+ " value,"
+ " start_time,"
+ " end_time,"
+ " suppressed"
+ " FROM auditor_denominations_without_sigs"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_denominations_without_sigs_get_asc"
+ : "auditor_denominations_without_sigs_get_desc",
+ params,
+ &denominations_without_sigs_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_deposit_confirmations.c b/src/auditordb/get_deposit_confirmations.c
@@ -0,0 +1,232 @@
+/*
+ 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_deposit_confirmations.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_deposit_confirmations.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #deposit_confirmation_cb().
+ */
+struct DepositConfirmationContext
+{
+
+ /**
+ * Function to call for each deposit confirmation.
+ */
+ TALER_AUDITORDB_DepositConfirmationCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_deposit_confirmations().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DepositConfirmationContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+deposit_confirmation_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct DepositConfirmationContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_DepositConfirmation dc = { 0 };
+ struct TALER_CoinSpendPublicKeyP *coin_pubs = NULL;
+ struct TALER_CoinSpendSignatureP *coin_sigs = NULL;
+ size_t num_pubs = 0;
+ size_t num_sigs = 0;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+ &dc.h_contract_terms),
+ GNUNET_PQ_result_spec_auto_from_type ("h_policy",
+ &dc.h_policy),
+ GNUNET_PQ_result_spec_auto_from_type ("h_wire",
+ &dc.h_wire),
+ GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
+ &dc.exchange_timestamp),
+ GNUNET_PQ_result_spec_timestamp ("refund_deadline",
+ &dc.refund_deadline),
+ GNUNET_PQ_result_spec_timestamp ("wire_deadline",
+ &dc.wire_deadline),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("total_without_fee",
+ &dc.total_without_fee),
+ GNUNET_PQ_result_spec_auto_array_from_type (ctx->conn,
+ "coin_pubs",
+ &num_pubs,
+ coin_pubs),
+ GNUNET_PQ_result_spec_auto_array_from_type (ctx->conn,
+ "coin_sigs",
+ &num_sigs,
+ coin_sigs),
+ GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+ &dc.merchant),
+ GNUNET_PQ_result_spec_auto_from_type ("exchange_sig",
+ &dc.exchange_sig),
+ GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
+ &dc.exchange_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig",
+ &dc.master_sig),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ if (num_sigs != num_pubs)
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ GNUNET_PQ_cleanup_result (rs);
+ return;
+ }
+ dcc->qs = i + 1;
+ dc.coin_pubs = coin_pubs;
+ dc.coin_sigs = coin_sigs;
+ dc.num_coins = num_sigs;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_deposit_confirmations (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_DepositConfirmationCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct DepositConfirmationContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_deposit_confirmation_select_desc",
+ "SELECT"
+ " row_id"
+ ",h_contract_terms"
+ ",h_policy"
+ ",h_wire"
+ ",exchange_timestamp"
+ ",wire_deadline"
+ ",refund_deadline"
+ ",total_without_fee"
+ ",coin_pubs"
+ ",coin_sigs"
+ ",merchant_pub"
+ ",exchange_sig"
+ ",exchange_pub"
+ ",master_sig"
+ ",suppressed"
+ " FROM auditor_deposit_confirmations"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_deposit_confirmation_select_asc",
+ "SELECT"
+ " row_id"
+ ",h_contract_terms"
+ ",h_policy"
+ ",h_wire"
+ ",exchange_timestamp"
+ ",wire_deadline"
+ ",refund_deadline"
+ ",total_without_fee"
+ ",coin_pubs"
+ ",coin_sigs"
+ ",merchant_pub"
+ ",exchange_sig"
+ ",exchange_pub"
+ ",master_sig"
+ ",suppressed"
+ " FROM auditor_deposit_confirmations"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_deposit_confirmation_select_asc"
+ : "auditor_deposit_confirmation_select_desc",
+ params,
+ &deposit_confirmation_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_emergency.c b/src/auditordb/get_emergency.c
@@ -0,0 +1,180 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_emergency.h"
+
+/**
+ * Closure for #emergency_cb().
+ */
+struct EmergencyContext
+{
+
+ /**
+ * Function to call for each deposit confirmation.
+ */
+ TALER_AUDITORDB_EmergencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_emergency().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct Emergency *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+emergency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct EmergencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_Emergency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_auto_from_type ("denompub_h",
+ &dc.denompub_h),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("denom_risk",
+ &dc.denom_risk),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("denom_loss",
+ &dc.denom_loss),
+ GNUNET_PQ_result_spec_absolute_time ("deposit_start",
+ &dc.deposit_start),
+ GNUNET_PQ_result_spec_absolute_time ("deposit_end",
+ &dc.deposit_end),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("value",
+ &dc.value),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_emergency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_EmergencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct EmergencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_emergency_get_desc",
+ "SELECT"
+ " row_id"
+ ",denompub_h"
+ ",denom_risk"
+ ",denom_loss"
+ ",deposit_start"
+ ",deposit_end"
+ ",value"
+ ",suppressed"
+ " FROM auditor_emergency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_emergency_get_asc",
+ "SELECT"
+ " row_id"
+ ",denompub_h"
+ ",denom_risk"
+ ",denom_loss"
+ ",deposit_start"
+ ",deposit_end"
+ ",value"
+ ",suppressed"
+ " FROM auditor_emergency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_emergency_get_asc"
+ : "auditor_emergency_get_desc",
+ params,
+ &emergency_cb,
+ &dcc);
+
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_emergency_by_count.c b/src/auditordb/get_emergency_by_count.c
@@ -0,0 +1,184 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_emergency_by_count.h"
+
+
+/**
+ * Closure for #emergency_cb().
+ */
+struct EmergencyByCountContext
+{
+
+ /**
+ * Function to call for each deposit confirmation.
+ */
+ TALER_AUDITORDB_EmergenciesByCountCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_emergency_by_count().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct Emergency *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+emergency_by_count_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct EmergencyByCountContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_EmergenciesByCount dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_auto_from_type ("denompub_h",
+ &dc.denompub_h),
+ GNUNET_PQ_result_spec_uint64 ("num_issued",
+ &dc.num_issued),
+ GNUNET_PQ_result_spec_uint64 ("num_known",
+ &dc.num_known),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("risk",
+ &dc.risk),
+ GNUNET_PQ_result_spec_absolute_time ("start",
+ &dc.start),
+ GNUNET_PQ_result_spec_absolute_time ("deposit_end",
+ &dc.deposit_end),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("value",
+ &dc.value),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_emergency_by_count (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_EmergenciesByCountCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct EmergencyByCountContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_emergency_by_count_get_desc",
+ "SELECT"
+ " row_id"
+ ",denompub_h"
+ ",num_issued"
+ ",num_known"
+ ",risk"
+ ",start"
+ ",deposit_end"
+ ",value"
+ ",suppressed"
+ " FROM auditor_emergency_by_count"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_emergency_by_count_get_asc",
+ "SELECT"
+ " row_id"
+ ",denompub_h"
+ ",num_issued"
+ ",num_known"
+ ",risk"
+ ",start"
+ ",deposit_end"
+ ",value"
+ ",suppressed"
+ " FROM auditor_emergency_by_count"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_emergency_by_count_get_asc"
+ : "auditor_emergency_by_count_get_desc",
+ params,
+ &emergency_by_count_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_exchange_signkeys.c b/src/auditordb/get_exchange_signkeys.c
@@ -0,0 +1,184 @@
+/*
+ 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/>
+ */
+
+
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+
+#include "get_exchange_signkeys.h"
+
+
+struct ExchangeSignkeysContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_ExchangeSignkeysCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_exchange_signkeys().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ExchangeSignkeysContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+exchange_signkeys_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ExchangeSignkeysContext *dcc = cls;
+ // struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t serial_id;
+
+ struct TALER_AUDITORDB_ExchangeSignkeys dc;
+
+ struct GNUNET_PQ_ResultSpec rs[] = {
+
+ GNUNET_PQ_result_spec_uint64 ("row_id", &serial_id),
+
+ GNUNET_PQ_result_spec_auto_from_type ("exchange_pub", &dc.exchange_pub),
+ GNUNET_PQ_result_spec_auto_from_type ("master_sig", &dc.master_sig),
+ GNUNET_PQ_result_spec_absolute_time ("ep_valid_from", &dc.ep_valid_from),
+ GNUNET_PQ_result_spec_absolute_time ("ep_expire_sign",
+ &dc.ep_expire_sign),
+ GNUNET_PQ_result_spec_absolute_time ("ep_expire_legal",
+ &dc.ep_expire_legal),
+ GNUNET_PQ_result_spec_bool ("suppressed", &dc.suppressed),
+
+
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+
+ dcc->qs = i + 1;
+
+ rval = dcc->cb (dcc->cb_cls,
+ serial_id,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_exchange_signkeys (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed, // maybe not needed
+ TALER_AUDITORDB_ExchangeSignkeysCallback cb,
+ void *cb_cls)
+{
+
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct ExchangeSignkeysContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_exchange_signkeys_get_desc",
+ "SELECT"
+ " row_id,"
+ " exchange_pub,"
+ " master_sig,"
+ " ep_valid_from,"
+ " ep_expire_sign,"
+ " ep_expire_legal,"
+ " suppressed"
+ " FROM auditor_exchange_signkeys"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_exchange_signkeys_get_asc",
+ "SELECT"
+ " row_id,"
+ " exchange_pub,"
+ " master_sig,"
+ " ep_valid_from,"
+ " ep_expire_sign,"
+ " ep_expire_legal,"
+ " suppressed"
+ " FROM auditor_exchange_signkeys"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (ctx->conn,
+ (limit > 0)
+ ?
+ "auditor_exchange_signkeys_get_asc"
+ :
+ "auditor_exchange_signkeys_get_desc",
+ params,
+ &exchange_signkeys_cb,
+ &dcc);
+
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_fee_time_inconsistency.c b/src/auditordb/get_fee_time_inconsistency.c
@@ -0,0 +1,166 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_fee_time_inconsistency.h"
+
+
+/**
+ * Closure for #feetimeinconsistency_cb().
+ */
+struct FeeTimeInconsistencyContext
+{
+
+ /**
+ * Function to call for each fee time inconsistency
+ */
+ TALER_AUDITORDB_FeeTimeInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_emergency().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct Emergency *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+fee_time_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct FeeTimeInconsistencyContext *dcc = cls;
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_FeeTimeInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_uint64 ("problem_row_id",
+ &dc.problem_row_id),
+ GNUNET_PQ_result_spec_string ("fee_type",
+ &dc.type),
+ GNUNET_PQ_result_spec_absolute_time ("fee_time",
+ &dc.time),
+ GNUNET_PQ_result_spec_string ("diagnostic",
+ &dc.diagnostic),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_fee_time_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_FeeTimeInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct FeeTimeInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_fee_time_inconsistency_get_desc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",fee_type"
+ ",fee_time"
+ ",diagnostic"
+ " FROM auditor_fee_time_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_fee_time_inconsistency_get_asc",
+ "SELECT"
+ " row_id"
+ ",problem_row_id"
+ ",fee_type"
+ ",fee_time"
+ ",diagnostic"
+ " FROM auditor_fee_time_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_fee_time_inconsistency_get_asc"
+ : "auditor_fee_time_inconsistency_get_desc",
+ params,
+ &fee_time_inconsistency_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_misattribution_in_inconsistency.c b/src/auditordb/get_misattribution_in_inconsistency.c
@@ -0,0 +1,168 @@
+/*
+ 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/>
+ */
+
+
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+
+#include "get_misattribution_in_inconsistency.h"
+
+
+struct MisattributionInInconsistencyContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_MisattributionInInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_misattribution_in_inconsistency().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct MisattributionInInconsistencyContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+misattribution_in_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct MisattributionInInconsistencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_MisattributionInInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &dc.amount),
+ GNUNET_PQ_result_spec_uint64 ("bank_row",
+ &dc.bank_row),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &dc.reserve_pub),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_misattribution_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_MisattributionInInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct MisattributionInInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_misattribution_in_inconsistency_get_desc",
+ "SELECT"
+ " row_id"
+ ",amount"
+ ",bank_row"
+ ",reserve_pub"
+ ",suppressed"
+ " FROM auditor_misattribution_in_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_misattribution_in_inconsistency_get_asc",
+ "SELECT"
+ " row_id"
+ ",amount"
+ ",bank_row"
+ ",reserve_pub"
+ ",suppressed"
+ " FROM auditor_misattribution_in_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_misattribution_in_inconsistency_get_asc"
+ : "auditor_misattribution_in_inconsistency_get_desc",
+ params,
+ &misattribution_in_inconsistency_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_progress_points.c b/src/auditordb/get_progress_points.c
@@ -0,0 +1,138 @@
+/*
+ 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 src/auditordb/get_progress_points.c
+ * @brief Implementation of the get_progress_points function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_progress_points.h"
+#include "pg_helper.h"
+
+
+struct ProgressContext
+{
+
+ /**
+ * Function to call for each progress point.
+ */
+ TALER_AUDITORDB_ProgressPointsCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_progress_points().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ProgressContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+progress_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ProgressContext *dcc = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_Progress dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("progress_key",
+ &dc.progress_key),
+ GNUNET_PQ_result_spec_uint64 ("progress_offset",
+ &dc.progress_offset),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_progress_points (struct AUDITORDB_PostgresContext *ctx,
+ const char *progress_key,
+ TALER_AUDITORDB_ProgressPointsCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ NULL == progress_key
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (progress_key),
+ GNUNET_PQ_query_param_end
+ };
+ struct ProgressContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_progress_points_get",
+ "SELECT"
+ " progress_key"
+ ",progress_offset"
+ " FROM auditor_progress"
+ " WHERE ($1::TEXT IS NULL OR progress_key = $1)"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ "auditor_progress_points_get",
+ params,
+ &progress_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_purse_info.c b/src/auditordb/get_purse_info.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 src/auditordb/get_purse_info.c
+ * @brief Implementation of the get_purse_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_purse_info.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_purse_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ uint64_t *rowid,
+ struct TALER_Amount *balance,
+ struct GNUNET_TIME_Timestamp *expiration_date)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ balance),
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ expiration_date),
+ GNUNET_PQ_result_spec_uint64 ("auditor_purses_rowid",
+ rowid),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (ctx,
+ "auditor_get_purse_info",
+ "SELECT"
+ " auditor_purses_rowid"
+ ",expiration_date"
+ ",balance"
+ " FROM auditor_purses"
+ " WHERE purse_pub=$1");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn,
+ "auditor_get_purse_info",
+ params,
+ rs);
+}
diff --git a/src/auditordb/get_purse_not_closed_inconsistencies.c b/src/auditordb/get_purse_not_closed_inconsistencies.c
@@ -0,0 +1,168 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_purse_not_closed_inconsistencies.h"
+
+
+/**
+ * Closure for #purse_not_closed_inconsistencies_cb().
+ */
+struct PurseNotClosedInconsistenciesContext
+{
+
+ /**
+ * Function to call for each purse not closed_inconsistencies.
+ */
+ TALER_AUDITORDB_PurseNotClosedInconsistenciesCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_purse_not_closed_inconsistencies().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseNotClosedInconsistencies *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purse_not_closed_inconsistencies_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseNotClosedInconsistenciesContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_PurseNotClosedInconsistencies dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &dc.purse_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &dc.amount),
+ GNUNET_PQ_result_spec_absolute_time ("expiration_date",
+ &dc.expiration_date),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_purse_not_closed_inconsistencies (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_PurseNotClosedInconsistenciesCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct PurseNotClosedInconsistenciesContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_purse_not_closed_inconsistencies_get_desc",
+ "SELECT"
+ " row_id"
+ ",purse_pub"
+ ",amount"
+ ",expiration_date"
+ ",suppressed"
+ " FROM auditor_purse_not_closed_inconsistencies"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_purse_not_closed_inconsistencies_get_asc",
+ "SELECT"
+ " row_id"
+ ",purse_pub"
+ ",amount"
+ ",expiration_date"
+ ",suppressed"
+ " FROM auditor_purse_not_closed_inconsistencies"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_purse_not_closed_inconsistencies_get_asc"
+ : "auditor_purse_not_closed_inconsistencies_get_desc",
+ params,
+ &purse_not_closed_inconsistencies_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_purses.c b/src/auditordb/get_purses.c
@@ -0,0 +1,163 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_purses.h"
+
+
+struct PursesContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_PursesCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_purses().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PursesContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purses_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PursesContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_Purses dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("auditor_purses_rowid",
+ &dc.auditor_purses_rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &dc.purse_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ &dc.balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("target",
+ &dc.target),
+ GNUNET_PQ_result_spec_absolute_time ("expiration_date",
+ &dc.expiration_date),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ dc.auditor_purses_rowid,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_purses (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_PursesCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct PursesContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_purses_get_desc",
+ "SELECT"
+ " auditor_purses_rowid,"
+ " purse_pub,"
+ " balance,"
+ " target,"
+ " expiration_date"
+ " FROM auditor_purses"
+ " WHERE (auditor_purses_rowid < $1)"
+ " ORDER BY auditor_purses_rowid DESC"
+ " LIMIT $2"
+ );
+ PREPARE (ctx,
+ "auditor_purses_get_asc",
+ "SELECT"
+ " auditor_purses_rowid,"
+ " purse_pub,"
+ " balance,"
+ " target,"
+ " expiration_date"
+ " FROM auditor_purses"
+ " WHERE (auditor_purses_rowid > $1)"
+ " ORDER BY auditor_purses_rowid ASC"
+ " LIMIT $2"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_purses_get_asc"
+ : "auditor_purses_get_desc",
+ params,
+ &purses_cb,
+ &dcc);
+
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_reserve_balance_insufficient_inconsistency.c b/src/auditordb/get_reserve_balance_insufficient_inconsistency.c
@@ -0,0 +1,168 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_reserve_balance_insufficient_inconsistency.h"
+
+
+/**
+ * Closure for #reserve_balance_insufficient_inconsistency_cb().
+ */
+struct ReserveBalanceInsufficientInconsistencyContext
+{
+
+ /**
+ * Function to call for each ReserveBalanceInsufficientInconsistency.
+ */
+ TALER_AUDITORDB_ReserveBalanceInsufficientInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_reserve_balance_insufficient_inconsistency().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReserveBalanceInsufficientInconsistency *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_balance_insufficient_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveBalanceInsufficientInconsistencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_ReserveBalanceInsufficientInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &dc.reserve_pub),
+ GNUNET_PQ_result_spec_bool ("inconsistency_gain",
+ &dc.inconsistency_gain),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("inconsistency_amount",
+ &dc.inconsistency_amount),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_balance_insufficient_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ReserveBalanceInsufficientInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct ReserveBalanceInsufficientInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_reserve_balance_insufficient_inconsistency_get_desc",
+ "SELECT"
+ " row_id"
+ ",reserve_pub"
+ ",inconsistency_gain"
+ ",inconsistency_amount"
+ ",suppressed"
+ " FROM auditor_reserve_balance_insufficient_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_reserve_balance_insufficient_inconsistency_get_asc",
+ "SELECT"
+ " row_id"
+ ",reserve_pub"
+ ",inconsistency_gain"
+ ",inconsistency_amount"
+ ",suppressed"
+ " FROM auditor_reserve_balance_insufficient_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_reserve_balance_insufficient_inconsistency_get_asc"
+ : "auditor_reserve_balance_insufficient_inconsistency_get_desc",
+ params,
+ &reserve_balance_insufficient_inconsistency_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_reserve_balance_summary_wrong_inconsistency.c b/src/auditordb/get_reserve_balance_summary_wrong_inconsistency.c
@@ -0,0 +1,166 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_reserve_balance_summary_wrong_inconsistency.h"
+
+
+struct ReserveBalanceSummaryWrongInconsistencyContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_ReserveBalanceSummaryWrongInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_reserve_balance_summary_wrong_inconsistency().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReserveBalanceSummaryWrongInconsistencyContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_balance_summary_wrong_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveBalanceSummaryWrongInconsistencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_ReserveBalanceSummaryWrongInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &dc.reserve_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("exchange_amount",
+ &dc.exchange_amount),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("auditor_amount",
+ &dc.auditor_amount),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_balance_summary_wrong_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ReserveBalanceSummaryWrongInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct ReserveBalanceSummaryWrongInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_reserve_balance_summary_wrong_inconsistency_get_desc",
+ "SELECT"
+ " row_id"
+ ",reserve_pub"
+ ",exchange_amount"
+ ",auditor_amount"
+ ",suppressed"
+ " FROM auditor_reserve_balance_summary_wrong_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_reserve_balance_summary_wrong_inconsistency_get_asc",
+ "SELECT"
+ " row_id"
+ ",reserve_pub"
+ ",exchange_amount"
+ ",auditor_amount"
+ ",suppressed"
+ " FROM auditor_reserve_balance_summary_wrong_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_reserve_balance_summary_wrong_inconsistency_get_asc"
+ : "auditor_reserve_balance_summary_wrong_inconsistency_get_desc",
+ params,
+ &reserve_balance_summary_wrong_inconsistency_cb,
+ &dcc);
+
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_reserve_in_inconsistency.c b/src/auditordb/get_reserve_in_inconsistency.c
@@ -0,0 +1,182 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_reserve_in_inconsistency.h"
+
+
+struct ReserveInInconsistencyContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_ReserveInInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_reserve_in_inconsistency().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReserveInInconsistencyContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_in_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveInInconsistencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_ReserveInInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.serial_id),
+ GNUNET_PQ_result_spec_uint64 ("bank_row_id",
+ &dc.bank_row_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_exchange_expected",
+ &dc.amount_exchange_expected),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_wired",
+ &dc.amount_wired),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &dc.reserve_pub),
+ GNUNET_PQ_result_spec_absolute_time ("timestamp",
+ &dc.timestamp),
+ GNUNET_PQ_result_spec_string ("account",
+ &dc.account.full_payto),
+ GNUNET_PQ_result_spec_string ("diagnostic",
+ &dc.diagnostic),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ReserveInInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct ReserveInInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_reserve_in_inconsistency_get_desc",
+ "SELECT"
+ " row_id"
+ ",bank_row_id"
+ ",amount_exchange_expected"
+ ",amount_wired"
+ ",reserve_pub"
+ ",timestamp"
+ ",account"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_reserve_in_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_reserve_in_inconsistency_get_asc",
+ "SELECT"
+ " row_id"
+ ",bank_row_id"
+ ",amount_exchange_expected"
+ ",amount_wired"
+ ",reserve_pub"
+ ",timestamp"
+ ",account"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_reserve_in_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_reserve_in_inconsistency_get_asc"
+ : "auditor_reserve_in_inconsistency_get_desc",
+ params,
+ &reserve_in_inconsistency_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_reserve_info.c b/src/auditordb/get_reserve_info.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 pg_get_reserve_info.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_reserve_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ uint64_t *rowid,
+ struct TALER_AUDITORDB_ReserveFeeBalance *rfb,
+ struct GNUNET_TIME_Timestamp *expiration_date,
+ struct TALER_FullPayto *sender_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 ("reserve_balance",
+ &rfb->reserve_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_loss",
+ &rfb->reserve_loss),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("withdraw_fee_balance",
+ &rfb->withdraw_fee_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("close_fee_balance",
+ &rfb->close_fee_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee_balance",
+ &rfb->purse_fee_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("open_fee_balance",
+ &rfb->open_fee_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee_balance",
+ &rfb->history_fee_balance),
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ expiration_date),
+ GNUNET_PQ_result_spec_uint64 ("auditor_reserves_rowid",
+ rowid),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_string ("origin_account",
+ &sender_account->full_payto),
+ NULL),
+ GNUNET_PQ_result_spec_end
+ };
+
+ sender_account->full_payto = NULL;
+ PREPARE (ctx,
+ "auditor_get_reserve_info",
+ "SELECT"
+ " reserve_balance"
+ ",reserve_loss"
+ ",withdraw_fee_balance"
+ ",close_fee_balance"
+ ",purse_fee_balance"
+ ",open_fee_balance"
+ ",history_fee_balance"
+ ",expiration_date"
+ ",auditor_reserves_rowid"
+ ",origin_account"
+ " FROM auditor_reserves"
+ " WHERE reserve_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn,
+ "auditor_get_reserve_info",
+ params,
+ rs);
+}
diff --git a/src/auditordb/get_reserve_not_closed_inconsistency.c b/src/auditordb/get_reserve_not_closed_inconsistency.c
@@ -0,0 +1,169 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_reserve_not_closed_inconsistency.h"
+
+
+struct ReserveNotClosedInconsistencyContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_ReserveNotClosedInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_reserve_not_closed_inconsistency().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReserveNotClosedInconsistencyContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserve_not_closed_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveNotClosedInconsistencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_ReserveNotClosedInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &dc.reserve_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ &dc.balance),
+ GNUNET_PQ_result_spec_absolute_time ("expiration_time",
+ &dc.expiration_time),
+ GNUNET_PQ_result_spec_string ("diagnostic",
+ &dc.diagnostic),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_not_closed_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ReserveNotClosedInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct ReserveNotClosedInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_reserve_not_closed_inconsistency_get_desc",
+ "SELECT"
+ " row_id"
+ ",reserve_pub"
+ ",balance"
+ ",expiration_time"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_reserve_not_closed_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_reserve_not_closed_inconsistency_get_asc",
+ "SELECT"
+ " row_id"
+ ",reserve_pub"
+ ",balance"
+ ",expiration_time"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_reserve_not_closed_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_reserve_not_closed_inconsistency_get_asc"
+ : "auditor_reserve_not_closed_inconsistency_get_desc",
+ params,
+ &reserve_not_closed_inconsistency_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_reserves.c b/src/auditordb/get_reserves.c
@@ -0,0 +1,186 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_reserves.h"
+
+
+struct ReservesContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_ReservesCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_reserves().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct ReservesContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+reserves_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReservesContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_Reserves dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("auditor_reserves_rowid",
+ &dc.auditor_reserves_rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &dc.reserve_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_balance",
+ &dc.reserve_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_loss",
+ &dc.reserve_loss),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("withdraw_fee_balance",
+ &dc.withdraw_fee_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("close_fee_balance",
+ &dc.close_fee_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee_balance",
+ &dc.purse_fee_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("open_fee_balance",
+ &dc.open_fee_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee_balance",
+ &dc.history_fee_balance),
+ GNUNET_PQ_result_spec_absolute_time ("expiration_date",
+ &dc.expiration_date),
+ GNUNET_PQ_result_spec_string ("origin_account",
+ &dc.origin_account.full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ dc.auditor_reserves_rowid,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserves (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_ReservesCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct ReservesContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_reserves_get_desc",
+ "SELECT"
+ " auditor_reserves_rowid,"
+ " reserve_pub,"
+ " reserve_balance,"
+ " reserve_loss,"
+ " withdraw_fee_balance,"
+ " close_fee_balance,"
+ " purse_fee_balance,"
+ " open_fee_balance,"
+ " history_fee_balance,"
+ " expiration_date,"
+ " origin_account"
+ " FROM auditor_reserves"
+ " WHERE (auditor_reserves_rowid < $1)"
+ " ORDER BY auditor_reserves_rowid DESC"
+ " LIMIT $2"
+ );
+ PREPARE (ctx,
+ "auditor_reserves_get_asc",
+ "SELECT"
+ " auditor_reserves_rowid,"
+ " reserve_pub,"
+ " reserve_balance,"
+ " reserve_loss,"
+ " withdraw_fee_balance,"
+ " close_fee_balance,"
+ " purse_fee_balance,"
+ " open_fee_balance,"
+ " history_fee_balance,"
+ " expiration_date,"
+ " origin_account"
+ " FROM auditor_reserves"
+ " WHERE (auditor_reserves_rowid > $1)"
+ " ORDER BY auditor_reserves_rowid ASC"
+ " LIMIT $2"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_reserves_get_asc"
+ : "auditor_reserves_get_desc",
+ params,
+ &reserves_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_row_inconsistency.c b/src/auditordb/get_row_inconsistency.c
@@ -0,0 +1,173 @@
+/*
+ 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/>
+ */
+
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_row_inconsistency.h"
+
+/**
+ * Closure for #deposit_confirmation_cb().
+ */
+struct RowInconsistencyContext
+{
+
+ /**
+ * Function to call for each deposit confirmation.
+ */
+ TALER_AUDITORDB_RowInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_deposit_confirmations().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct DepositConfirmationContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+row_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RowInconsistencyContext *dcc = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t serial_id;
+
+ struct TALER_AUDITORDB_RowInconsistency dc;
+
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id", &serial_id),
+
+ GNUNET_PQ_result_spec_string ("row_table", &dc.row_table),
+ GNUNET_PQ_result_spec_string ("diagnostic", &dc.diagnostic),
+ GNUNET_PQ_result_spec_bool ("suppressed", &dc.suppressed),
+
+
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+
+ dcc->qs = i + 1;
+
+
+ rval = dcc->cb (dcc->cb_cls,
+ serial_id,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_row_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed, // maybe not needed
+ TALER_AUDITORDB_RowInconsistencyCallback cb,
+ void *cb_cls)
+{
+
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct RowInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+
+ PREPARE (ctx,
+ "auditor_row_inconsistency_select_desc",
+ "SELECT"
+ " row_id"
+ ",row_table"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_row_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_row_inconsistency_select_asc",
+ "SELECT"
+ " row_id"
+ ",row_table"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_row_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR suppressed is false)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (ctx->conn,
+ (limit > 0) ?
+ "auditor_row_inconsistency_select_asc"
+ :
+ "auditor_row_inconsistency_select_desc",
+ params,
+ &row_inconsistency_cb,
+ &dcc);
+
+
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
+\ No newline at end of file
diff --git a/src/auditordb/get_row_minor_inconsistencies.c b/src/auditordb/get_row_minor_inconsistencies.c
@@ -0,0 +1,164 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_row_minor_inconsistencies.h"
+
+
+struct RowMinorInconsistenciesContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_RowMinorInconsistenciesCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_row_minor_inconsistencies().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct RowMinorInconsistenciesContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+row_minor_inconsistencies_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RowMinorInconsistenciesContext *dcc = cls;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_RowMinorInconsistencies dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_string ("row_table",
+ &dc.row_table),
+ GNUNET_PQ_result_spec_uint64 ("problem_row",
+ &dc.problem_row),
+ GNUNET_PQ_result_spec_string ("diagnostic",
+ &dc.diagnostic),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_row_minor_inconsistencies (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_RowMinorInconsistenciesCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct RowMinorInconsistenciesContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_row_minor_inconsistencies_get_desc",
+ "SELECT"
+ " row_id"
+ ",problem_row"
+ ",row_table"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_row_minor_inconsistencies"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_row_minor_inconsistencies_get_asc",
+ "SELECT"
+ " row_id"
+ ",problem_row"
+ ",row_table"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_row_minor_inconsistencies"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_row_minor_inconsistencies_get_asc"
+ : "auditor_row_minor_inconsistencies_get_desc",
+ params,
+ &row_minor_inconsistencies_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_wire_fee_summary.c b/src/auditordb/get_wire_fee_summary.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 pg_get_wire_fee_summary.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_wire_fee_summary.h"
+#include "pg_helper.h"
+
+
+/**
+ * Get summary information about an exchanges wire fee balance.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param[out] wire_fee_balance set amount the exchange gained in wire fees
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_wire_fee_summary (struct AUDITORDB_PostgresContext *ctx,
+ struct TALER_Amount *wire_fee_balance)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee_balance",
+ wire_fee_balance),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (ctx,
+ "auditor_wire_fee_balance_select",
+ "SELECT"
+ " wire_fee_balance"
+ " FROM auditor_wire_fee_balance");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn,
+ "auditor_wire_fee_balance_select",
+ params,
+ rs);
+}
diff --git a/src/auditordb/get_wire_format_inconsistency.c b/src/auditordb/get_wire_format_inconsistency.c
@@ -0,0 +1,165 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_wire_format_inconsistency.h"
+
+
+struct WireFormatInconsistencyContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_WireFormatInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_wire_format_inconsistency().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WireFormatInconsistencyContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+wire_format_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireFormatInconsistencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_WireFormatInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &dc.amount),
+ GNUNET_PQ_result_spec_uint64 ("wire_offset",
+ &dc.wire_offset),
+ GNUNET_PQ_result_spec_string ("diagnostic",
+ &dc.diagnostic),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_wire_format_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_WireFormatInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct WireFormatInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_wire_format_inconsistency_get_desc",
+ "SELECT"
+ " row_id,"
+ " amount,"
+ " wire_offset,"
+ " diagnostic,"
+ " suppressed"
+ " FROM auditor_wire_format_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_wire_format_inconsistency_get_asc",
+ "SELECT"
+ " row_id,"
+ " amount,"
+ " wire_offset,"
+ " diagnostic,"
+ " suppressed"
+ " FROM auditor_wire_format_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_wire_format_inconsistency_get_asc"
+ : "auditor_wire_format_inconsistency_get_desc",
+ params,
+ &wire_format_inconsistency_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/get_wire_out_inconsistency.c b/src/auditordb/get_wire_out_inconsistency.c
@@ -0,0 +1,173 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "get_wire_out_inconsistency.h"
+
+
+struct WireOutInconsistencyContext
+{
+
+ /**
+ * Function to call for each bad sig loss.
+ */
+ TALER_AUDITORDB_WireOutInconsistencyCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_get_wire_out_inconsistency().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WireOutInconsistencyContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+wire_out_inconsistency_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireOutInconsistencyContext *dcc = cls;
+ struct AUDITORDB_PostgresContext *ctx = dcc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_WireOutInconsistency dc;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc.row_id),
+ GNUNET_PQ_result_spec_string ("destination_account",
+ &dc.destination_account.full_payto),
+ GNUNET_PQ_result_spec_string ("diagnostic",
+ &dc.diagnostic),
+ GNUNET_PQ_result_spec_uint64 ("wire_out_serial_id",
+ &dc.wire_out_row_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("expected",
+ &dc.expected),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("claimed",
+ &dc.claimed),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+ enum GNUNET_GenericReturnValue rval;
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ dcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ dcc->qs = i + 1;
+ rval = dcc->cb (dcc->cb_cls,
+ &dc);
+ GNUNET_PQ_cleanup_result (rs);
+ if (GNUNET_OK != rval)
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_wire_out_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_WireOutInconsistencyCallback cb,
+ void *cb_cls)
+{
+ uint64_t plimit = (uint64_t) ((limit < 0) ? -limit : limit);
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_uint64 (&plimit),
+ GNUNET_PQ_query_param_end
+ };
+ struct WireOutInconsistencyContext dcc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_wire_out_inconsistency_get_desc",
+ "SELECT"
+ " row_id"
+ ",destination_account"
+ ",diagnostic"
+ ",wire_out_serial_id"
+ ",expected"
+ ",claimed"
+ ",suppressed"
+ " FROM auditor_wire_out_inconsistency"
+ " WHERE (row_id < $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3"
+ );
+ PREPARE (ctx,
+ "auditor_wire_out_inconsistency_get_asc",
+ "SELECT"
+ " row_id"
+ ",destination_account"
+ ",diagnostic"
+ ",wire_out_serial_id"
+ ",expected"
+ ",claimed"
+ ",suppressed"
+ " FROM auditor_wire_out_inconsistency"
+ " WHERE (row_id > $1)"
+ " AND ($2 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3"
+ );
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit > 0)
+ ? "auditor_wire_out_inconsistency_get_asc"
+ : "auditor_wire_out_inconsistency_get_desc",
+ params,
+ &wire_out_inconsistency_cb,
+ &dcc);
+ if (qs > 0)
+ return dcc.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/helper.c b/src/auditordb/helper.c
@@ -0,0 +1,67 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2015, 2016 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file auditordb/auditordb_plugin.c
+ * @brief Logic to load database plugin
+ * @author Christian Grothoff
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ */
+#include "taler/platform.h"
+#include "taler/taler_auditordb_plugin.h"
+#include <ltdl.h>
+#include "helper.h"
+
+
+const char *
+AUDITORDB_get_deletable_suppressable_table_name (enum
+ TALER_AUDITORDB_DeletableSuppressableTables
+ table)
+{
+ const char *tables[] = {
+ "auditor_amount_arithmetic_inconsistency",
+ "auditor_closure_lags",
+ "auditor_progress",
+ "auditor_bad_sig_losses",
+ "auditor_coin_inconsistency",
+ "auditor_denomination_key_validity_withdraw_inconsistency",
+ "auditor_denomination_pending",
+ "auditor_denomination_without_sig",
+ "auditor_deposit_confirmations",
+ "auditor_emergency",
+ "auditor_emergency_by_count",
+ "auditor_fee_time_inconsistency",
+ "auditor_misattribution_in_inconsistency",
+ "auditor_purse_not_closed_inconsistency",
+ "auditor_refreshes_haning",
+ "auditor_reserve_balance_insufficient_inconsistency",
+ "auditor_reserve_balance_summary_wrong_inconsistency",
+ "auditor_reserve_in_inconsistency",
+ "auditor_reserve_not_closed_inconsistency",
+ "auditor_row_inconsistency",
+ "auditor_row_minor_inconsistency",
+ "auditor_wire_format_inconsistency",
+ "auditor_wire_out_inconsistency",
+ NULL,
+ };
+
+ if ( (table < 0) ||
+ (table >= TALER_AUDITORDB_DELETABLESUPPRESSABLE_TABLES_MAX))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ return tables[table];
+}
diff --git a/src/auditordb/insert_amount_arithmetic_inconsistency.c b/src/auditordb/insert_amount_arithmetic_inconsistency.c
@@ -0,0 +1,49 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_amount_arithmetic_inconsistency.h"
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_amount_arithmetic_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_AmountArithmeticInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (dc->operation),
+ GNUNET_PQ_query_param_uint64 (&dc->problem_row_id),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->exchange_amount),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->auditor_amount),
+ GNUNET_PQ_query_param_bool (dc->profitable),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_amount_arithmetic_inconsistency_insert",
+ "INSERT INTO auditor_amount_arithmetic_inconsistency "
+ "(operation"
+ ",problem_row_id"
+ ",exchange_amount"
+ ",auditor_amount"
+ ",profitable"
+ ") VALUES ($1,$2,$3,$4,$5);"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_amount_arithmetic_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_auditor_closure_lags.c b/src/auditordb/insert_auditor_closure_lags.c
@@ -0,0 +1,48 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_auditor_closure_lags.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_auditor_closure_lags (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ClosureLags *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->amount),
+ GNUNET_PQ_query_param_uint64 (&dc->problem_row_id),
+ GNUNET_PQ_query_param_absolute_time (&dc->deadline),
+ GNUNET_PQ_query_param_auto_from_type (&dc->wtid),
+ GNUNET_PQ_query_param_string (dc->account.full_payto),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_closure_lags_insert",
+ "INSERT INTO auditor_closure_lags "
+ "(amount"
+ ",problem_row_id"
+ ",deadline"
+ ",wtid"
+ ",account"
+ ") VALUES ($1,$2,$3,$4,$5);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_closure_lags_insert",
+ params);
+}
diff --git a/src/auditordb/insert_auditor_progress.c b/src/auditordb/insert_auditor_progress.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 pg_insert_auditor_progress.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_auditor_progress.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_auditor_progress (struct AUDITORDB_PostgresContext *ctx,
+ const char *progress_key,
+ uint64_t progress_offset,
+ ...)
+{
+ unsigned int cnt = 1;
+ va_list ap;
+
+ va_start (ap,
+ progress_offset);
+ while (NULL != va_arg (ap,
+ const char *))
+ {
+ cnt++;
+ (void) va_arg (ap,
+ uint64_t);
+ }
+ va_end (ap);
+ {
+ const char *keys[cnt];
+ uint64_t offsets[cnt];
+ unsigned int off = 1;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_array_ptrs_string (cnt,
+ keys,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_uint64 (cnt,
+ offsets,
+ ctx->conn),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ keys[0] = progress_key;
+ offsets[0] = progress_offset;
+
+ va_start (ap,
+ progress_offset);
+ while (off < cnt)
+ {
+ keys[off] = va_arg (ap,
+ const char *);
+ offsets[off] = va_arg (ap,
+ uint64_t);
+ off++;
+ }
+ GNUNET_assert (NULL == va_arg (ap,
+ const char *));
+ va_end (ap);
+
+ PREPARE (ctx,
+ "auditor_progress_insert",
+ "INSERT INTO auditor_progress "
+ "(progress_key"
+ ",progress_offset"
+ ") SELECT *"
+ " FROM UNNEST (CAST($1 AS TEXT[]),"
+ " CAST($2 AS INT8[]))"
+ " ON CONFLICT DO NOTHING;");
+ qs = GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_progress_insert",
+ params);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ return qs;
+ }
+}
diff --git a/src/auditordb/insert_bad_sig_losses.c b/src/auditordb/insert_bad_sig_losses.c
@@ -0,0 +1,47 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_bad_sig_losses.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_bad_sig_losses (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_BadSigLosses *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (dc->operation),
+ GNUNET_PQ_query_param_uint64 (&dc->problem_row_id),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->loss),
+ GNUNET_PQ_query_param_auto_from_type (&dc->operation_specific_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_bad_sig_losses_insert",
+ "INSERT INTO auditor_bad_sig_losses "
+ "(operation"
+ ",problem_row_id"
+ ",loss"
+ ",operation_specific_pub"
+ ") VALUES ($1,$2,$3,$4);"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_bad_sig_losses_insert",
+ params);
+}
diff --git a/src/auditordb/insert_balance.c b/src/auditordb/insert_balance.c
@@ -0,0 +1,96 @@
+/*
+ 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 pg_insert_balance.c
+ * @brief Implementation of the insert_balance function
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_balance.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_balance (struct AUDITORDB_PostgresContext *ctx,
+ const char *balance_key,
+ const struct TALER_Amount *balance_value,
+ ...)
+{
+ unsigned int cnt = 1;
+ va_list ap;
+
+ va_start (ap,
+ balance_value);
+ while (NULL != va_arg (ap,
+ const char *))
+ {
+ cnt++;
+ (void) va_arg (ap,
+ const struct TALER_Amount *);
+ }
+ va_end (ap);
+ {
+ const char *keys[cnt];
+ struct TALER_Amount amounts[cnt];
+ unsigned int off = 1;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_array_ptrs_string (cnt,
+ keys,
+ ctx->conn),
+ TALER_PQ_query_param_array_amount (cnt,
+ amounts,
+ ctx->conn),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ keys[0] = balance_key;
+ amounts[0] = *balance_value;
+
+ va_start (ap,
+ balance_value);
+ while (off < cnt)
+ {
+ keys[off] = va_arg (ap,
+ const char *);
+ amounts[off] = *va_arg (ap,
+ const struct TALER_Amount *);
+ off++;
+ }
+ GNUNET_assert (NULL == va_arg (ap,
+ const char *));
+ va_end (ap);
+
+ PREPARE (ctx,
+ "auditor_balance_insert",
+ "INSERT INTO auditor_balances "
+ "(balance_key"
+ ",balance_value.val"
+ ",balance_value.frac"
+ ") SELECT *"
+ " FROM UNNEST (CAST($1 AS TEXT[]),"
+ " CAST($2 AS taler_amount[]))"
+ " ON CONFLICT DO NOTHING;");
+ qs = GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_balance_insert",
+ params);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ return qs;
+ }
+}
diff --git a/src/auditordb/insert_coin_inconsistency.c b/src/auditordb/insert_coin_inconsistency.c
@@ -0,0 +1,50 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_coin_inconsistency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_coin_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_CoinInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (dc->operation),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->exchange_amount),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->auditor_amount),
+ GNUNET_PQ_query_param_auto_from_type (&dc->coin_pub),
+ GNUNET_PQ_query_param_bool (dc->profitable),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_coin_inconsistency_insert",
+ "INSERT INTO auditor_coin_inconsistency "
+ "(operation"
+ ",exchange_amount"
+ ",auditor_amount"
+ ",coin_pub"
+ ",profitable"
+ ") VALUES ($1,$2,$3,$4,$5)"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_coin_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_denomination_balance.c b/src/auditordb/insert_denomination_balance.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 pg_insert_denomination_balance.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_denomination_balance.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_denomination_balance (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ const struct TALER_AUDITORDB_DenominationCirculationData *dcd)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dcd->denom_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dcd->denom_loss),
+ GNUNET_PQ_query_param_uint64 (&dcd->num_issued),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dcd->denom_risk),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dcd->recoup_loss),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_denomination_pending_insert",
+ "INSERT INTO auditor_denomination_pending "
+ "(denom_pub_hash"
+ ",denom_balance"
+ ",denom_loss"
+ ",num_issued"
+ ",denom_risk"
+ ",recoup_loss"
+ ") VALUES ("
+ "$1,$2,$3,$4,$5,$6"
+ ");");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_denomination_pending_insert",
+ params);
+}
diff --git a/src/auditordb/insert_denomination_key_validity_withdraw_inconsistency.c b/src/auditordb/insert_denomination_key_validity_withdraw_inconsistency.c
@@ -0,0 +1,46 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_denomination_key_validity_withdraw_inconsistency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_denomination_key_validity_withdraw_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_absolute_time (&dc->execution_date),
+ GNUNET_PQ_query_param_uint64 (&dc->problem_row_id),
+ GNUNET_PQ_query_param_auto_from_type (&dc->reserve_pub),
+ GNUNET_PQ_query_param_auto_from_type (&dc->denompub_h),
+
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_denomination_key_validity_withdraw_inconsistency_insert",
+ "INSERT INTO auditor_denomination_key_validity_withdraw_inconsistency "
+ "(execution_date"
+ ",problem_row_id"
+ ",reserve_pub"
+ ",denompub_h"
+ ") VALUES ($1,$2,$3,$4);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_denomination_key_validity_withdraw_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_denomination_pending.c b/src/auditordb/insert_denomination_pending.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/>
+ */
+
+
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+
+#include "insert_denomination_pending.h"
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_denomination_pending (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_DenominationPending *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&dc->denom_pub_hash),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->denom_balance),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->denom_loss),
+ GNUNET_PQ_query_param_uint64 (&dc->num_issued),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->denom_risk),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->recoup_loss),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_denomination_pending_insert",
+ "INSERT INTO auditor_denomination_pending "
+ "( denom_pub_hash,"
+ " denom_balance,"
+ " denom_loss,"
+ " num_issued,"
+ " denom_risk,"
+ " recoup_loss"
+ ") VALUES ($1,$2,$3,$4,$5,$6)"
+ " ON CONFLICT (denom_pub_hash) UPDATE"
+ " SET denom_balance = excluded.denom_balance, "
+ " denom_loss = excluded.denom_loss,"
+ " num_issued = excluded.num_issued,"
+ " denom_risk = excluded.denom_risk,"
+ " recoup_loss = excluded.recoup_loss,"
+ " suppressed = false;"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_denomination_pending_insert",
+ params);
+}
diff --git a/src/auditordb/insert_denominations_without_sigs.c b/src/auditordb/insert_denominations_without_sigs.c
@@ -0,0 +1,51 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_denominations_without_sigs.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_denominations_without_sigs (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_DenominationsWithoutSigs *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&dc->denompub_h),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->value),
+ GNUNET_PQ_query_param_absolute_time (&dc->start_time),
+ GNUNET_PQ_query_param_absolute_time (&dc->end_time),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_denominations_without_sigs_insert",
+ "INSERT INTO auditor_denominations_without_sigs "
+ "(denompub_h,"
+ " value,"
+ " start_time,"
+ " end_time"
+ ") VALUES ($1,$2,$3,$4)"
+ " ON CONFLICT (denompub_h) DO UPDATE"
+ " SET value = excluded.value,"
+ " start_time = excluded.start_time,"
+ " end_time = excluded.end_time,"
+ " suppressed = false"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_denominations_without_sigs_insert",
+ params);
+}
diff --git a/src/auditordb/insert_deposit_confirmation.c b/src/auditordb/insert_deposit_confirmation.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 pg_insert_deposit_confirmation.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_deposit_confirmation.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_deposit_confirmation (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_DepositConfirmation *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&dc->h_contract_terms),
+ GNUNET_PQ_query_param_auto_from_type (&dc->h_policy),
+ GNUNET_PQ_query_param_auto_from_type (&dc->h_wire),
+ GNUNET_PQ_query_param_timestamp (&dc->exchange_timestamp),
+ GNUNET_PQ_query_param_timestamp (&dc->wire_deadline),
+ GNUNET_PQ_query_param_timestamp (&dc->refund_deadline),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->total_without_fee),
+ GNUNET_PQ_query_param_array_auto_from_type (dc->num_coins,
+ dc->coin_pubs,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_auto_from_type (dc->num_coins,
+ dc->coin_sigs,
+ ctx->conn),
+ GNUNET_PQ_query_param_auto_from_type (&dc->merchant),
+ GNUNET_PQ_query_param_auto_from_type (&dc->exchange_sig),
+ GNUNET_PQ_query_param_auto_from_type (&dc->exchange_pub),
+ GNUNET_PQ_query_param_auto_from_type (&dc->master_sig),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_deposit_confirmation_insert",
+ "INSERT INTO auditor_deposit_confirmations "
+ "(h_contract_terms"
+ ",h_policy"
+ ",h_wire"
+ ",exchange_timestamp"
+ ",wire_deadline"
+ ",refund_deadline"
+ ",total_without_fee"
+ ",coin_pubs"
+ ",coin_sigs"
+ ",merchant_pub"
+ ",exchange_sig"
+ ",exchange_pub"
+ ",master_sig" /* master_sig could be normalized... */
+ ") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13);");
+ qs = GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_deposit_confirmation_insert",
+ params);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ return qs;
+}
diff --git a/src/auditordb/insert_early_aggregation.c b/src/auditordb/insert_early_aggregation.c
@@ -0,0 +1,54 @@
+/*
+ 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 src/auditordb/insert_early_aggregation.c
+ * @brief Implementation of the insert_early_aggregation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_early_aggregation.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_early_aggregation (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t batch_deposit_serial_id,
+ uint64_t tracking_serial_id,
+ const struct TALER_Amount *total_amount)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&batch_deposit_serial_id),
+ GNUNET_PQ_query_param_uint64 (&tracking_serial_id),
+ TALER_PQ_query_param_amount (ctx->conn,
+ total_amount),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_insert_early_aggregation",
+ "INSERT INTO auditor_early_aggregations"
+ "(batch_deposit_serial_id"
+ ",tracking_serial_id"
+ ",amount"
+ ") VALUES ($1,$2,$3);");
+ return GNUNET_PQ_eval_prepared_non_select (
+ ctx->conn,
+ "auditor_insert_early_aggregation",
+ params);
+}
diff --git a/src/auditordb/insert_emergency.c b/src/auditordb/insert_emergency.c
@@ -0,0 +1,52 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_emergency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_emergency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_Emergency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&dc->denompub_h),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->denom_risk),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->denom_loss),
+ GNUNET_PQ_query_param_absolute_time (&dc->deposit_start),
+ GNUNET_PQ_query_param_absolute_time (&dc->deposit_end),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->value),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_emergency_insert",
+ "INSERT INTO auditor_emergency "
+ "(denompub_h"
+ ",denom_risk"
+ ",denom_loss"
+ ",deposit_start"
+ ",deposit_end"
+ ",value"
+ ") VALUES ($1,$2,$3,$4,$5,$6);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_emergency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_emergency_by_count.c b/src/auditordb/insert_emergency_by_count.c
@@ -0,0 +1,50 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_emergency_by_count.h"
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_emergency_by_count (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_EmergenciesByCount *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&dc->denompub_h),
+ GNUNET_PQ_query_param_uint64 (&dc->num_issued),
+ GNUNET_PQ_query_param_uint64 (&dc->num_known),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->risk),
+ GNUNET_PQ_query_param_absolute_time (&dc->start),
+ GNUNET_PQ_query_param_absolute_time (&dc->deposit_end),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->value),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_emergency_by_count_insert",
+ "INSERT INTO auditor_emergency_by_count "
+ "(denompub_h"
+ ",num_issued"
+ ",num_known"
+ ",risk"
+ ",start"
+ ",deposit_end"
+ ",value"
+ ") VALUES ($1,$2,$3,$4,$5,$6,$7);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_emergency_by_count_insert",
+ params);
+}
diff --git a/src/auditordb/insert_exchange_signkey.c b/src/auditordb/insert_exchange_signkey.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 pg_insert_exchange_signkey.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_exchange_signkey.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_exchange_signkey (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ExchangeSigningKey *sk)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&sk->ep_start),
+ GNUNET_PQ_query_param_timestamp (&sk->ep_expire),
+ GNUNET_PQ_query_param_timestamp (&sk->ep_end),
+ GNUNET_PQ_query_param_auto_from_type (&sk->exchange_pub),
+ GNUNET_PQ_query_param_auto_from_type (&sk->master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_insert_exchange_signkey",
+ "INSERT INTO auditor_exchange_signkeys "
+ "(ep_valid_from"
+ ",ep_expire_sign"
+ ",ep_expire_legal"
+ ",exchange_pub"
+ ",master_sig"
+ ") VALUES ($1,$2,$3,$4,$5);"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_insert_exchange_signkey",
+ params);
+}
diff --git a/src/auditordb/insert_fee_time_inconsistency.c b/src/auditordb/insert_fee_time_inconsistency.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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_fee_time_inconsistency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_fee_time_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_FeeTimeInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (dc->type),
+ GNUNET_PQ_query_param_uint64 (&dc->problem_row_id),
+ GNUNET_PQ_query_param_absolute_time (&dc->time),
+ GNUNET_PQ_query_param_string (dc->diagnostic),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_fee_time_inconsistency_insert",
+ "INSERT INTO auditor_fee_time_inconsistency "
+ "(fee_type"
+ ",problem_row_id"
+ ",fee_time"
+ ",diagnostic"
+ ") VALUES ($1,$2,$3,$4);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_fee_time_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_historic_denom_revenue.c b/src/auditordb/insert_historic_denom_revenue.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 pg_insert_historic_denom_revenue.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_historic_denom_revenue.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_historic_denom_revenue (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ struct GNUNET_TIME_Timestamp revenue_timestamp,
+ const struct TALER_Amount *revenue_balance,
+ const struct TALER_Amount *loss_balance)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+ GNUNET_PQ_query_param_timestamp (&revenue_timestamp),
+ TALER_PQ_query_param_amount (ctx->conn,
+ revenue_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ loss_balance),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_historic_denomination_revenue_insert",
+ "INSERT INTO auditor_historic_denomination_revenue"
+ "(denom_pub_hash"
+ ",revenue_timestamp"
+ ",revenue_balance"
+ ",loss_balance"
+ ") VALUES ($1,$2,$3,$4);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_historic_denomination_revenue_insert",
+ params);
+}
diff --git a/src/auditordb/insert_historic_reserve_revenue.c b/src/auditordb/insert_historic_reserve_revenue.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 pg_insert_historic_reserve_revenue.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_historic_reserve_revenue.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_historic_reserve_revenue (struct AUDITORDB_PostgresContext *ctx,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Timestamp end_time,
+ const struct TALER_Amount *reserve_profits)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&start_time),
+ GNUNET_PQ_query_param_timestamp (&end_time),
+ TALER_PQ_query_param_amount (ctx->conn,
+ reserve_profits),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_historic_reserve_summary_insert",
+ "INSERT INTO auditor_historic_reserve_summary"
+ "(start_date"
+ ",end_date"
+ ",reserve_profits"
+ ") VALUES ($1,$2,$3);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_historic_reserve_summary_insert",
+ params);
+}
diff --git a/src/auditordb/insert_misattribution_in_inconsistency.c b/src/auditordb/insert_misattribution_in_inconsistency.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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_misattribution_in_inconsistency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_misattribution_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_MisattributionInInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->amount),
+ GNUNET_PQ_query_param_uint64 (&dc->bank_row),
+ GNUNET_PQ_query_param_auto_from_type (&dc->reserve_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_misattribution_in_inconsistency_insert",
+ "INSERT INTO auditor_misattribution_in_inconsistency "
+ "(amount,"
+ " bank_row,"
+ " reserve_pub"
+ ") VALUES ($1,$2,$3);"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_misattribution_in_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_pending_deposit.c b/src/auditordb/insert_pending_deposit.c
@@ -0,0 +1,57 @@
+/*
+ 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 src/auditordb/insert_pending_deposit.c
+ * @brief Implementation of the insert_pending_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_pending_deposit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_pending_deposit (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t batch_deposit_serial_id,
+ const struct TALER_FullPaytoHashP *wire_target_h_payto,
+ const struct TALER_Amount *total_amount,
+ struct GNUNET_TIME_Timestamp deadline)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (ctx->conn,
+ total_amount),
+ GNUNET_PQ_query_param_auto_from_type (wire_target_h_payto),
+ GNUNET_PQ_query_param_uint64 (&batch_deposit_serial_id),
+ GNUNET_PQ_query_param_timestamp (&deadline),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_insert_pending_deposit",
+ "INSERT INTO auditor_pending_deposits "
+ "(total_amount"
+ ",wire_target_h_payto"
+ ",batch_deposit_serial_id"
+ ",deadline"
+ ") VALUES ($1,$2,$3,$4);");
+ return GNUNET_PQ_eval_prepared_non_select (
+ ctx->conn,
+ "auditor_insert_pending_deposit",
+ params);
+}
diff --git a/src/auditordb/insert_purse_info.c b/src/auditordb/insert_purse_info.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 src/auditordb/insert_purse_info.c
+ * @brief Implementation of the insert_purse_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_purse_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_purse_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_Amount *balance,
+ struct GNUNET_TIME_Timestamp expiration_date)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (purse_pub),
+ TALER_PQ_query_param_amount (ctx->conn,
+ balance),
+ GNUNET_PQ_query_param_timestamp (&expiration_date),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_purses_insert",
+ "INSERT INTO auditor_purses "
+ "(purse_pub"
+ ",target"
+ ",expiration_date"
+ ") VALUES ($1,$2,$3);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_purses_insert",
+ params);
+}
diff --git a/src/auditordb/insert_purse_not_closed_inconsistencies.c b/src/auditordb/insert_purse_not_closed_inconsistencies.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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_purse_not_closed_inconsistencies.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_purse_not_closed_inconsistencies (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_PurseNotClosedInconsistencies *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&dc->purse_pub),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->amount),
+ GNUNET_PQ_query_param_absolute_time (&dc->expiration_date),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_purse_not_closed_inconsistencies_insert",
+ "INSERT INTO auditor_purse_not_closed_inconsistencies "
+ "(purse_pub"
+ ",amount"
+ ",expiration_date"
+ ") VALUES ($1,$2,$3)"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_purse_not_closed_inconsistencies_insert",
+ params);
+}
diff --git a/src/auditordb/insert_reserve_balance_insufficient_inconsistency.c b/src/auditordb/insert_reserve_balance_insufficient_inconsistency.c
@@ -0,0 +1,47 @@
+/*
+ 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/>
+ */
+
+
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+
+#include "insert_reserve_balance_insufficient_inconsistency.h"
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_balance_insufficient_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ReserveBalanceInsufficientInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+
+ GNUNET_PQ_query_param_auto_from_type (&dc->reserve_pub),
+ GNUNET_PQ_query_param_bool (dc->inconsistency_gain),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->inconsistency_amount),
+
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_reserve_balance_insufficient_inconsistency_insert",
+ "INSERT INTO auditor_reserve_balance_insufficient_inconsistency "
+ "(reserve_pub"
+ ",inconsistency_gain"
+ ",inconsistency_amount"
+ ") VALUES ($1,$2,$3);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_reserve_balance_insufficient_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_reserve_balance_summary_wrong_inconsistency.c b/src/auditordb/insert_reserve_balance_summary_wrong_inconsistency.c
@@ -0,0 +1,48 @@
+/*
+ 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/>
+ */
+
+
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+
+#include "insert_reserve_balance_summary_wrong_inconsistency.h"
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_balance_summary_wrong_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ReserveBalanceSummaryWrongInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+
+ GNUNET_PQ_query_param_auto_from_type (&dc->reserve_pub),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->exchange_amount),
+ TALER_PQ_query_param_amount (ctx->conn, &dc->auditor_amount),
+
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_reserve_balance_summary_wrong_inconsistency_insert",
+ "INSERT INTO auditor_reserve_balance_summary_wrong_inconsistency "
+ "(reserve_pub,"
+ " exchange_amount,"
+ " auditor_amount"
+ ") VALUES ($1,$2,$3);"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_reserve_balance_summary_wrong_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_reserve_in_inconsistency.c b/src/auditordb/insert_reserve_in_inconsistency.c
@@ -0,0 +1,54 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_reserve_in_inconsistency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ReserveInInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&dc->bank_row_id),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->amount_exchange_expected),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->amount_wired),
+ GNUNET_PQ_query_param_auto_from_type (&dc->reserve_pub),
+ GNUNET_PQ_query_param_absolute_time (&dc->timestamp),
+ GNUNET_PQ_query_param_string (dc->account.full_payto),
+ GNUNET_PQ_query_param_string (dc->diagnostic),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_reserve_in_inconsistency_insert",
+ "INSERT INTO auditor_reserve_in_inconsistency "
+ "(bank_row_id,"
+ " amount_exchange_expected,"
+ " amount_wired,"
+ " reserve_pub,"
+ " timestamp,"
+ " account,"
+ " diagnostic"
+ ") VALUES ($1,$2,$3,$4,$5,$6,$7);"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_reserve_in_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_reserve_info.c b/src/auditordb/insert_reserve_info.c
@@ -0,0 +1,77 @@
+/*
+ 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_info.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_reserve_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_AUDITORDB_ReserveFeeBalance *rfb,
+ struct GNUNET_TIME_Timestamp expiration_date,
+ const struct TALER_FullPayto origin_account)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->reserve_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->reserve_loss),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->withdraw_fee_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->close_fee_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->purse_fee_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->open_fee_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->history_fee_balance),
+ GNUNET_PQ_query_param_timestamp (&expiration_date),
+ NULL == origin_account.full_payto
+ ? GNUNET_PQ_query_param_null ()
+ : GNUNET_PQ_query_param_string (origin_account.full_payto),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_insert_reserve_info",
+ "INSERT INTO auditor_reserves "
+ "(reserve_pub"
+ ",reserve_balance"
+ ",reserve_loss"
+ ",withdraw_fee_balance"
+ ",close_fee_balance"
+ ",purse_fee_balance"
+ ",open_fee_balance"
+ ",history_fee_balance"
+ ",expiration_date"
+ ",origin_account"
+ ") VALUES "
+ "($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_insert_reserve_info",
+ params);
+}
diff --git a/src/auditordb/insert_reserve_not_closed_inconsistency.c b/src/auditordb/insert_reserve_not_closed_inconsistency.c
@@ -0,0 +1,48 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_reserve_not_closed_inconsistency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_not_closed_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ReserveNotClosedInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (&dc->reserve_pub),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->balance),
+ GNUNET_PQ_query_param_absolute_time (&dc->expiration_time),
+ GNUNET_PQ_query_param_string (dc->diagnostic),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_reserve_not_closed_inconsistency_insert",
+ "INSERT INTO auditor_reserve_not_closed_inconsistency "
+ "(reserve_pub,"
+ " balance,"
+ " expiration_time,"
+ " diagnostic"
+ ") VALUES ($1,$2,$3,$4)"
+ " ON CONFLICT DO NOTHING;"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_reserve_not_closed_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_row_inconsistency.c b/src/auditordb/insert_row_inconsistency.c
@@ -0,0 +1,44 @@
+/*
+ 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/>
+ */
+
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_row_inconsistency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_row_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_RowInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (dc->row_table),
+ GNUNET_PQ_query_param_string (dc->diagnostic),
+ GNUNET_PQ_query_param_uint64 (&dc->row_id),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_insert_row_inconsistency",
+ "INSERT INTO auditor_row_inconsistency "
+ "(row_table"
+ ",diagnostic"
+ ",problem_row_id"
+ ") VALUES ($1,$2,$3);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_insert_row_inconsistency",
+ params);
+}
diff --git a/src/auditordb/insert_row_minor_inconsistencies.c b/src/auditordb/insert_row_minor_inconsistencies.c
@@ -0,0 +1,44 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_row_minor_inconsistencies.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_row_minor_inconsistencies (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_RowMinorInconsistencies *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (dc->row_table),
+ GNUNET_PQ_query_param_uint64 (&dc->problem_row),
+ GNUNET_PQ_query_param_string (dc->diagnostic),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_row_minor_inconsistencies_insert",
+ "INSERT INTO auditor_row_minor_inconsistencies "
+ "(row_table"
+ ",problem_row"
+ ",diagnostic"
+ ") VALUES ($1,$2,$3);"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_row_minor_inconsistencies_insert",
+ params);
+}
diff --git a/src/auditordb/insert_wire_format_inconsistency.c b/src/auditordb/insert_wire_format_inconsistency.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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "insert_wire_format_inconsistency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_wire_format_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_WireFormatInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->amount),
+ GNUNET_PQ_query_param_uint64 (&dc->wire_offset),
+ GNUNET_PQ_query_param_string (dc->diagnostic),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_wire_format_inconsistency_insert",
+ "INSERT INTO auditor_wire_format_inconsistency "
+ "(amount"
+ ",wire_offset"
+ ",diagnostic"
+ ") VALUES ($1,$2,$3);"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_wire_format_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/insert_wire_out_inconsistency.c b/src/auditordb/insert_wire_out_inconsistency.c
@@ -0,0 +1,52 @@
+/*
+ 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/>
+ */
+
+
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+
+#include "insert_wire_out_inconsistency.h"
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_wire_out_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_WireOutInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (dc->destination_account.full_payto),
+ GNUNET_PQ_query_param_string (dc->diagnostic),
+ GNUNET_PQ_query_param_uint64 (&dc->wire_out_row_id),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->expected),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dc->claimed),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_wire_out_inconsistency_insert",
+ "INSERT INTO auditor_wire_out_inconsistency "
+ "(destination_account"
+ ",diagnostic"
+ ",wire_out_serial_id"
+ ",expected"
+ ",claimed"
+ ") VALUES ($1,$2,$3,$4,$5);"
+ );
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_wire_out_inconsistency_insert",
+ params);
+}
diff --git a/src/auditordb/lookup_reserve_in_inconsistency.c b/src/auditordb/lookup_reserve_in_inconsistency.c
@@ -0,0 +1,73 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "lookup_reserve_in_inconsistency.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_lookup_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t bank_row_id,
+ struct TALER_AUDITORDB_ReserveInInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&bank_row_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc->serial_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_exchange_expected",
+ &dc->amount_exchange_expected),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_wired",
+ &dc->amount_wired),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &dc->reserve_pub),
+ GNUNET_PQ_result_spec_absolute_time ("timestamp",
+ &dc->timestamp),
+ GNUNET_PQ_result_spec_string ("account",
+ &dc->account.full_payto),
+ GNUNET_PQ_result_spec_string ("diagnostic",
+ &dc->diagnostic),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc->suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (ctx,
+ "auditor_lookup_reserve_in_inconsistency",
+ "SELECT"
+ " row_id"
+ ",amount_exchange_expected"
+ ",amount_wired"
+ ",reserve_pub"
+ ",timestamp"
+ ",account"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_reserve_in_inconsistency"
+ " WHERE (bank_row_id = $1)"
+ );
+ dc->bank_row_id = bank_row_id;
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ ctx->conn,
+ "auditor_lookup_reserve_in_inconsistency",
+ params,
+ rs);
+}
diff --git a/src/auditordb/plugin_auditordb_postgres.c b/src/auditordb/plugin_auditordb_postgres.c
@@ -23,113 +23,113 @@
#include "taler/taler_pq_lib.h"
#include <pthread.h>
#include <libpq-fe.h>
-#include "pg_delete_auditor_closure_lag.h"
-#include "pg_delete_early_aggregation.h"
-#include "pg_delete_generic.h"
-#include "pg_delete_pending_deposit.h"
-#include "pg_delete_purse_info.h"
-#include "pg_delete_reserve_in_inconsistency.h"
-#include "pg_del_denomination_balance.h"
-#include "pg_del_reserve_info.h"
-#include "pg_get_auditor_progress.h"
-#include "pg_get_balance.h"
-#include "pg_get_balances.h"
-#include "pg_get_denomination_balance.h"
-#include "pg_get_deposit_confirmations.h"
-#include "pg_get_purse_info.h"
-#include "pg_get_reserve_info.h"
-#include "pg_get_wire_fee_summary.h"
+#include "delete_auditor_closure_lag.h"
+#include "delete_early_aggregation.h"
+#include "delete_generic.h"
+#include "delete_pending_deposit.h"
+#include "delete_purse_info.h"
+#include "delete_reserve_in_inconsistency.h"
+#include "del_denomination_balance.h"
+#include "del_reserve_info.h"
+#include "get_auditor_progress.h"
+#include "get_balance.h"
+#include "get_balances.h"
+#include "get_denomination_balance.h"
+#include "get_deposit_confirmations.h"
+#include "get_purse_info.h"
+#include "get_reserve_info.h"
+#include "get_wire_fee_summary.h"
#include "pg_helper.h"
-#include "pg_insert_auditor_progress.h"
-#include "pg_insert_balance.h"
-#include "pg_insert_denomination_balance.h"
-#include "pg_insert_deposit_confirmation.h"
-#include "pg_insert_early_aggregation.h"
-#include "pg_insert_exchange_signkey.h"
-#include "pg_insert_historic_denom_revenue.h"
-#include "pg_insert_historic_reserve_revenue.h"
-#include "pg_insert_pending_deposit.h"
-#include "pg_insert_purse_info.h"
-#include "pg_insert_reserve_info.h"
-#include "pg_select_reserve_in_inconsistency.h"
-#include "pg_select_historic_denom_revenue.h"
-#include "pg_select_historic_reserve_revenue.h"
-#include "pg_get_progress_points.h"
-#include "pg_select_pending_deposits.h"
-#include "pg_select_purse_expired.h"
-#include "pg_update_generic_suppressed.h"
-#include "pg_update_auditor_progress.h"
-#include "pg_update_denomination_balance.h"
-#include "pg_update_purse_info.h"
-#include "pg_update_reserve_info.h"
-#include "pg_update_wire_fee_summary.h"
-#include "pg_get_amount_arithmetic_inconsistency.h"
-#include "pg_get_coin_inconsistency.h"
-#include "pg_get_row_inconsistency.h"
-#include "pg_update_balance.h"
-#include "pg_select_early_aggregations.h"
-
-#include "pg_insert_coin_inconsistency.h"
-#include "pg_insert_row_inconsistency.h"
-#include "pg_insert_amount_arithmetic_inconsistency.h"
-
-#include "pg_get_auditor_closure_lags.h"
-#include "pg_insert_auditor_closure_lags.h"
-
-#include "pg_get_emergency_by_count.h"
-#include "pg_insert_emergency_by_count.h"
-
-#include "pg_get_emergency.h"
-#include "pg_insert_emergency.h"
-
-#include "pg_get_bad_sig_losses.h"
-#include "pg_insert_bad_sig_losses.h"
-
-#include "pg_get_denomination_key_validity_withdraw_inconsistency.h"
-#include "pg_insert_denomination_key_validity_withdraw_inconsistency.h"
-
-#include "pg_get_fee_time_inconsistency.h"
-#include "pg_insert_fee_time_inconsistency.h"
-
-#include "pg_get_purse_not_closed_inconsistencies.h"
-#include "pg_insert_purse_not_closed_inconsistencies.h"
-
-#include "pg_get_reserve_balance_insufficient_inconsistency.h"
-#include "pg_insert_reserve_balance_insufficient_inconsistency.h"
-
-#include "pg_get_reserve_in_inconsistency.h"
-#include "pg_lookup_reserve_in_inconsistency.h"
-#include "pg_insert_reserve_in_inconsistency.h"
-
-#include "pg_get_reserve_not_closed_inconsistency.h"
-#include "pg_insert_reserve_not_closed_inconsistency.h"
-
-#include "pg_get_denominations_without_sigs.h"
-#include "pg_insert_denominations_without_sigs.h"
-
-#include "pg_get_misattribution_in_inconsistency.h"
-#include "pg_insert_misattribution_in_inconsistency.h"
-
-#include "pg_get_reserves.h"
-#include "pg_get_purses.h"
-
-#include "pg_get_denomination_pending.h"
-#include "pg_insert_denomination_pending.h"
-
-#include "pg_get_exchange_signkeys.h"
-
-#include "pg_get_wire_format_inconsistency.h"
-#include "pg_insert_wire_format_inconsistency.h"
-
-#include "pg_get_wire_out_inconsistency.h"
-#include "pg_insert_wire_out_inconsistency.h"
-#include "pg_delete_wire_out_inconsistency_if_matching.h"
-
-#include "pg_get_reserve_balance_summary_wrong_inconsistency.h"
-#include "pg_insert_reserve_balance_summary_wrong_inconsistency.h"
-
-#include "pg_get_row_minor_inconsistencies.h"
-#include "pg_insert_row_minor_inconsistencies.h"
+#include "insert_auditor_progress.h"
+#include "insert_balance.h"
+#include "insert_denomination_balance.h"
+#include "insert_deposit_confirmation.h"
+#include "insert_early_aggregation.h"
+#include "insert_exchange_signkey.h"
+#include "insert_historic_denom_revenue.h"
+#include "insert_historic_reserve_revenue.h"
+#include "insert_pending_deposit.h"
+#include "insert_purse_info.h"
+#include "insert_reserve_info.h"
+#include "select_reserve_in_inconsistency.h"
+#include "select_historic_denom_revenue.h"
+#include "select_historic_reserve_revenue.h"
+#include "get_progress_points.h"
+#include "select_pending_deposits.h"
+#include "select_purse_expired.h"
+#include "update_generic_suppressed.h"
+#include "update_auditor_progress.h"
+#include "update_denomination_balance.h"
+#include "update_purse_info.h"
+#include "update_reserve_info.h"
+#include "update_wire_fee_summary.h"
+#include "get_amount_arithmetic_inconsistency.h"
+#include "get_coin_inconsistency.h"
+#include "get_row_inconsistency.h"
+#include "update_balance.h"
+#include "select_early_aggregations.h"
+
+#include "insert_coin_inconsistency.h"
+#include "insert_row_inconsistency.h"
+#include "insert_amount_arithmetic_inconsistency.h"
+
+#include "get_auditor_closure_lags.h"
+#include "insert_auditor_closure_lags.h"
+
+#include "get_emergency_by_count.h"
+#include "insert_emergency_by_count.h"
+
+#include "get_emergency.h"
+#include "insert_emergency.h"
+
+#include "get_bad_sig_losses.h"
+#include "insert_bad_sig_losses.h"
+
+#include "get_denomination_key_validity_withdraw_inconsistency.h"
+#include "insert_denomination_key_validity_withdraw_inconsistency.h"
+
+#include "get_fee_time_inconsistency.h"
+#include "insert_fee_time_inconsistency.h"
+
+#include "get_purse_not_closed_inconsistencies.h"
+#include "insert_purse_not_closed_inconsistencies.h"
+
+#include "get_reserve_balance_insufficient_inconsistency.h"
+#include "insert_reserve_balance_insufficient_inconsistency.h"
+
+#include "get_reserve_in_inconsistency.h"
+#include "lookup_reserve_in_inconsistency.h"
+#include "insert_reserve_in_inconsistency.h"
+
+#include "get_reserve_not_closed_inconsistency.h"
+#include "insert_reserve_not_closed_inconsistency.h"
+
+#include "get_denominations_without_sigs.h"
+#include "insert_denominations_without_sigs.h"
+
+#include "get_misattribution_in_inconsistency.h"
+#include "insert_misattribution_in_inconsistency.h"
+
+#include "get_reserves.h"
+#include "get_purses.h"
+
+#include "get_denomination_pending.h"
+#include "insert_denomination_pending.h"
+
+#include "get_exchange_signkeys.h"
+
+#include "get_wire_format_inconsistency.h"
+#include "insert_wire_format_inconsistency.h"
+
+#include "get_wire_out_inconsistency.h"
+#include "insert_wire_out_inconsistency.h"
+#include "delete_wire_out_inconsistency_if_matching.h"
+
+#include "get_reserve_balance_summary_wrong_inconsistency.h"
+#include "insert_reserve_balance_summary_wrong_inconsistency.h"
+
+#include "get_row_minor_inconsistencies.h"
+#include "insert_row_minor_inconsistencies.h"
#define LOG(kind,...) GNUNET_log_from (kind, "taler-auditordb-postgres", \
__VA_ARGS__)
@@ -140,7 +140,7 @@
* This should only be used by testcases or when restarting the
* auditor from scratch.
*
- * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param cls the `struct AUDITORDB_PostgresContext` with the plugin-specific state
* @param drop_exchangelist drop all tables, including schema versioning
* and the exchange and deposit_confirmations table; NOT to be
* used when restarting the auditor
@@ -150,7 +150,7 @@ static enum GNUNET_GenericReturnValue
postgres_drop_tables (void *cls,
bool drop_exchangelist)
{
- struct PostgresClosure *pc = cls;
+ struct AUDITORDB_PostgresContext *pc = cls;
struct GNUNET_PQ_Context *conn;
enum GNUNET_GenericReturnValue ret;
@@ -171,7 +171,7 @@ postgres_drop_tables (void *cls,
/**
* Create the necessary tables if they are not present
*
- * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param cls the `struct AUDITORDB_PostgresContext` with the plugin-specific state
* @param support_partitions true to support partitioning
* @param num_partitions number of partitions to use
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
@@ -181,7 +181,7 @@ postgres_create_tables (void *cls,
bool support_partitions,
uint32_t num_partitions)
{
- struct PostgresClosure *pc = cls;
+ struct AUDITORDB_PostgresContext *pc = cls;
enum GNUNET_GenericReturnValue ret = GNUNET_OK;
struct GNUNET_PQ_Context *conn;
struct GNUNET_PQ_QueryParam params[] = {
@@ -246,15 +246,13 @@ postgres_create_tables (void *cls,
* @param cb_cls closure for @a cb
* @return handle useful to cancel the listener
*/
-static struct GNUNET_DB_EventHandler *
-postgres_event_listen (void *cls,
+struct GNUNET_DB_EventHandler *
+AUDITORDB_event_listen (struct AUDITORDB_PostgresContext *pg,
const struct GNUNET_DB_EventHeaderP *es,
struct GNUNET_TIME_Relative timeout,
GNUNET_DB_EventCallback cb,
void *cb_cls)
{
- struct PostgresClosure *pg = cls;
-
return GNUNET_PQ_event_listen (pg->conn,
es,
timeout,
@@ -283,14 +281,12 @@ postgres_event_listen_cancel (struct GNUNET_DB_EventHandler *eh)
* @param extra additional event data provided
* @param extra_size number of bytes in @a extra
*/
-static void
-postgres_event_notify (void *cls,
+void
+AUDITORDB_event_notify (struct AUDITORDB_PostgresContext *pg,
const struct GNUNET_DB_EventHeaderP *es,
const void *extra,
size_t extra_size)
{
- struct PostgresClosure *pg = cls;
-
return GNUNET_PQ_event_notify (pg->conn,
es,
extra,
@@ -305,7 +301,7 @@ postgres_event_notify (void *cls,
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
-setup_connection (struct PostgresClosure *pg)
+setup_connection (struct AUDITORDB_PostgresContext *pg)
{
struct GNUNET_PQ_ExecuteStatement es[] = {
GNUNET_PQ_make_try_execute ("SET search_path TO auditor;"),
@@ -336,15 +332,14 @@ setup_connection (struct PostgresClosure *pg)
* Do a pre-flight check that we are not in an uncommitted transaction.
* If we are, rollback the previous transaction and output a warning.
*
- * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param cls the `struct AUDITORDB_PostgresContext` with the plugin-specific state
* @return #GNUNET_OK on success,
* #GNUNET_NO if we rolled back an earlier transaction
* #GNUNET_SYSERR if we have no DB connection
*/
-static enum GNUNET_GenericReturnValue
-postgres_preflight (void *cls)
+enum GNUNET_GenericReturnValue
+AUDITORDB_preflight (struct AUDITORDB_PostgresContext *pg)
{
- struct PostgresClosure *pg = cls;
struct GNUNET_PQ_ExecuteStatement es[] = {
GNUNET_PQ_make_execute ("ROLLBACK"),
GNUNET_PQ_EXECUTE_STATEMENT_END
@@ -378,13 +373,12 @@ postgres_preflight (void *cls)
/**
* Start a transaction.
*
- * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param cls the `struct AUDITORDB_PostgresContext` with the plugin-specific state
* @return #GNUNET_OK on success
*/
-static enum GNUNET_GenericReturnValue
-postgres_start (void *cls)
+enum GNUNET_GenericReturnValue
+AUDITORDB_start (struct AUDITORDB_PostgresContext *pg)
{
- struct PostgresClosure *pg = cls;
struct GNUNET_PQ_ExecuteStatement es[] = {
GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"),
GNUNET_PQ_EXECUTE_STATEMENT_END
@@ -406,12 +400,11 @@ postgres_start (void *cls)
/**
* Roll back the current transaction of a database connection.
*
- * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param cls the `struct AUDITORDB_PostgresContext` with the plugin-specific state
*/
-static void
-postgres_rollback (void *cls)
+void
+AUDITORDB_rollback (struct AUDITORDB_PostgresContext *pg)
{
- struct PostgresClosure *pg = cls;
struct GNUNET_PQ_ExecuteStatement es[] = {
GNUNET_PQ_make_execute ("ROLLBACK"),
GNUNET_PQ_EXECUTE_STATEMENT_END
@@ -426,13 +419,12 @@ postgres_rollback (void *cls)
/**
* Commit the current transaction of a database connection.
*
- * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param cls the `struct AUDITORDB_PostgresContext` with the plugin-specific state
* @return transaction status code
*/
-static enum GNUNET_DB_QueryStatus
-postgres_commit (void *cls)
+enum GNUNET_DB_QueryStatus
+AUDITORDB_commit (struct AUDITORDB_PostgresContext *pg)
{
- struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_end
};
@@ -454,10 +446,9 @@ postgres_commit (void *cls)
* @return #GNUNET_OK on success,
* #GNUNET_SYSERR on DB errors
*/
-static enum GNUNET_GenericReturnValue
-postgres_gc (void *cls)
+enum GNUNET_GenericReturnValue
+AUDITORDB_gc (struct AUDITORDB_PostgresContext *pg)
{
- struct PostgresClosure *pg = cls;
/* For now, we hard-code the cut-off date based on the
common legal requirement to keep data for 10 years.
Might make it configurable in the future. */
@@ -511,18 +502,13 @@ postgres_gc (void *cls)
* @param cls a configuration instance
* @return NULL on error, otherwise a `struct TALER_AUDITORDB_Plugin`
*/
-void *
-libtaler_plugin_auditordb_postgres_init (void *cls);
-
-/* Declaration used to squash compiler warning */
-void *
-libtaler_plugin_auditordb_postgres_init (void *cls)
+struct AUDITORDB_PostgresContext *
+AUDITORDB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ bool skip_preflight)
{
- const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- struct PostgresClosure *pg;
- struct TALER_AUDITORDB_Plugin *plugin;
+ struct AUDITORDB_PostgresContext *pg;
- pg = GNUNET_new (struct PostgresClosure);
+ pg = GNUNET_new (struct AUDITORDB_PostgresContext);
pg->cfg = cfg;
if (GNUNET_OK !=
TALER_config_get_currency (cfg,
@@ -532,213 +518,7 @@ libtaler_plugin_auditordb_postgres_init (void *cls)
GNUNET_free (pg);
return NULL;
}
-
- plugin = GNUNET_new (struct TALER_AUDITORDB_Plugin);
- plugin->cls = pg;
- plugin->preflight = &postgres_preflight;
- plugin->drop_tables = &postgres_drop_tables;
- plugin->create_tables = &postgres_create_tables;
- plugin->event_listen = &postgres_event_listen;
- plugin->event_listen_cancel = &postgres_event_listen_cancel;
- plugin->event_notify = &postgres_event_notify;
- plugin->start = &postgres_start;
- plugin->commit = &postgres_commit;
- plugin->rollback = &postgres_rollback;
- plugin->gc = &postgres_gc;
-
- plugin->get_auditor_progress
- = &TAH_PG_get_auditor_progress;
-
- plugin->get_balance = &TAH_PG_get_balance;
- plugin->get_balances = &TAH_PG_get_balances;
-
- plugin->insert_auditor_progress
- = &TAH_PG_insert_auditor_progress;
- plugin->insert_balance
- = &TAH_PG_insert_balance;
- plugin->update_generic_suppressed
- = &TAH_PG_update_generic_suppressed;
- plugin->delete_generic
- = &TAH_PG_delete_generic;
- plugin->delete_wire_out_inconsistency_if_matching
- = &TAH_PG_delete_wire_out_inconsistency_if_matching;
-
- plugin->delete_auditor_closure_lag
- = &TAH_PG_delete_auditor_closure_lag;
-
- plugin->update_auditor_progress
- = &TAH_PG_update_auditor_progress;
- plugin->insert_deposit_confirmation
- = &TAH_PG_insert_deposit_confirmation;
- plugin->get_deposit_confirmations
- = &TAH_PG_get_deposit_confirmations;
-
- plugin->get_amount_arithmetic_inconsistency
- = &TAH_PG_get_amount_arithmetic_inconsistency;
- plugin->get_coin_inconsistency
- = &TAH_PG_get_coin_inconsistency;
- plugin->get_row_inconsistency
- = &TAH_PG_get_row_inconsistency;
-
-
- plugin->insert_amount_arithmetic_inconsistency
- = &TAH_PG_insert_amount_arithmetic_inconsistency;
- plugin->insert_coin_inconsistency
- = &TAH_PG_insert_coin_inconsistency;
- plugin->insert_row_inconsistency
- = &TAH_PG_insert_row_inconsistency;
-
- plugin->insert_reserve_info
- = &TAH_PG_insert_reserve_info;
- plugin->update_reserve_info
- = &TAH_PG_update_reserve_info;
- plugin->get_reserve_info
- = &TAH_PG_get_reserve_info;
- plugin->del_reserve_info
- = &TAH_PG_del_reserve_info;
-
- plugin->insert_pending_deposit
- = &TAH_PG_insert_pending_deposit;
- plugin->select_pending_deposits
- = &TAH_PG_select_pending_deposits;
- plugin->delete_pending_deposit
- = &TAH_PG_delete_pending_deposit;
-
- plugin->insert_purse_info
- = &TAH_PG_insert_purse_info;
- plugin->update_purse_info
- = &TAH_PG_update_purse_info;
- plugin->get_purse_info
- = &TAH_PG_get_purse_info;
- plugin->delete_purse_info
- = &TAH_PG_delete_purse_info;
- plugin->select_purse_expired
- = &TAH_PG_select_purse_expired;
-
- plugin->insert_denomination_balance
- = &TAH_PG_insert_denomination_balance;
- plugin->update_denomination_balance
- = &TAH_PG_update_denomination_balance;
- plugin->del_denomination_balance
- = &TAH_PG_del_denomination_balance;
- plugin->get_denomination_balance
- = &TAH_PG_get_denomination_balance;
-
- plugin->insert_historic_denom_revenue
- = &TAH_PG_insert_historic_denom_revenue;
-
- plugin->select_historic_denom_revenue
- = &TAH_PG_select_historic_denom_revenue;
-
- plugin->insert_historic_reserve_revenue
- = &TAH_PG_insert_historic_reserve_revenue;
- plugin->select_historic_reserve_revenue
- = &TAH_PG_select_historic_reserve_revenue;
-
-
- plugin->insert_emergency = &TAH_PG_insert_emergency;
- plugin->get_emergency = &TAH_PG_get_emergency;
-
- plugin->insert_emergency_by_count = &TAH_PG_insert_emergency_by_count;
- plugin->get_emergency_by_count = &TAH_PG_get_emergency_by_count;
-
-
- plugin->insert_denomination_key_validity_withdraw_inconsistency =
- &TAH_PG_insert_denomination_key_validity_withdraw_inconsistency;
- plugin->get_denomination_key_validity_withdraw_inconsistency =
- &TAH_PG_get_denomination_key_validity_withdraw_inconsistency;
-
- plugin->insert_purse_not_closed_inconsistencies =
- &TAH_PG_insert_purse_not_closed_inconsistencies;
- plugin->get_purse_not_closed_inconsistencies =
- &TAH_PG_get_purse_not_closed_inconsistencies;
-
-
- plugin->insert_reserve_balance_insufficient_inconsistency =
- &TAH_PG_insert_reserve_balance_insufficient_inconsistency;
- plugin->get_reserve_balance_insufficient_inconsistency =
- &TAH_PG_get_reserve_balance_insufficient_inconsistency;
-
- plugin->insert_bad_sig_losses = &TAH_PG_insert_bad_sig_losses;
- plugin->get_bad_sig_losses = &TAH_PG_get_bad_sig_losses;
-
- plugin->insert_auditor_closure_lags = &TAH_PG_insert_auditor_closure_lags;
- plugin->get_auditor_closure_lags = &TAH_PG_get_auditor_closure_lags;
-
- plugin->insert_reserve_in_inconsistency =
- &TAH_PG_insert_reserve_in_inconsistency;
- plugin->get_reserve_in_inconsistency
- = &TAH_PG_get_reserve_in_inconsistency;
- plugin->lookup_reserve_in_inconsistency
- = &TAH_PG_lookup_reserve_in_inconsistency;
-
- plugin->insert_reserve_not_closed_inconsistency =
- &TAH_PG_insert_reserve_not_closed_inconsistency;
- plugin->get_reserve_not_closed_inconsistency =
- &TAH_PG_get_reserve_not_closed_inconsistency;
-
- plugin->insert_denominations_without_sigs =
- &TAH_PG_insert_denominations_without_sigs;
- plugin->get_denominations_without_sigs =
- &TAH_PG_get_denominations_without_sigs;
-
- plugin->get_progress_points
- = &TAH_PG_get_progress_points;
-
-
- plugin->insert_misattribution_in_inconsistency =
- &TAH_PG_insert_misattribution_in_inconsistency;
- plugin->get_misattribution_in_inconsistency =
- &TAH_PG_get_misattribution_in_inconsistency;
-
- plugin->get_reserves = &TAH_PG_get_reserves;
- plugin->get_purses = &TAH_PG_get_purses;
-
- plugin->insert_denomination_pending = &TAH_PG_insert_denomination_pending;
- plugin->get_denomination_pending = &TAH_PG_get_denomination_pending;
-
- plugin->get_exchange_signkeys = &TAH_PG_get_exchange_signkeys;
-
- plugin->insert_wire_format_inconsistency =
- &TAH_PG_insert_wire_format_inconsistency;
- plugin->get_wire_format_inconsistency = &TAH_PG_get_wire_format_inconsistency;
-
- plugin->insert_early_aggregation
- = &TAH_PG_insert_early_aggregation;
- plugin->delete_early_aggregation
- = &TAH_PG_delete_early_aggregation;
-
- plugin->insert_wire_out_inconsistency
- = &TAH_PG_insert_wire_out_inconsistency;
- plugin->get_wire_out_inconsistency
- = &TAH_PG_get_wire_out_inconsistency;
- plugin->select_reserve_in_inconsistency
- = &TAH_PG_select_reserve_in_inconsistency;
- plugin->delete_reserve_in_inconsistency
- = &TAH_PG_delete_reserve_in_inconsistency;
- plugin->select_early_aggregations
- = &TAH_PG_select_early_aggregations;
-
- plugin->insert_reserve_balance_summary_wrong_inconsistency =
- &TAH_PG_insert_reserve_balance_summary_wrong_inconsistency;
- plugin->get_reserve_balance_summary_wrong_inconsistency =
- &TAH_PG_get_reserve_balance_summary_wrong_inconsistency;
-
-
- plugin->insert_row_minor_inconsistencies =
- &TAH_PG_insert_row_minor_inconsistencies;
- plugin->get_row_minor_inconsistencies = &TAH_PG_get_row_minor_inconsistencies;
-
- plugin->insert_fee_time_inconsistency = &TAH_PG_insert_fee_time_inconsistency;
- plugin->get_fee_time_inconsistency = &TAH_PG_get_fee_time_inconsistency;
-
- plugin->update_balance
- = &TAH_PG_update_balance;
-
- plugin->insert_exchange_signkey
- = &TAH_PG_insert_exchange_signkey;
-
- return plugin;
+ return pg;
}
@@ -748,22 +528,15 @@ libtaler_plugin_auditordb_postgres_init (void *cls)
* @param cls a `struct TALER_AUDITORDB_Plugin`
* @return NULL (always)
*/
-void *
-libtaler_plugin_auditordb_postgres_done (void *cls);
-
-/* Declaration used to squash compiler warning */
-void *
-libtaler_plugin_auditordb_postgres_done (void *cls)
+void
+AUDITORDB_disconnect (struct AUDITORDB_PostgresContext *pg)
{
- struct TALER_AUDITORDB_Plugin *plugin = cls;
- struct PostgresClosure *pg = plugin->cls;
-
+ if (NULL == pg)
+ return;
if (NULL != pg->conn)
GNUNET_PQ_disconnect (pg->conn);
GNUNET_free (pg->currency);
GNUNET_free (pg);
- GNUNET_free (plugin);
- return NULL;
}
diff --git a/src/auditordb/select_early_aggregations.c b/src/auditordb/select_early_aggregations.c
@@ -0,0 +1,171 @@
+/*
+ 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 src/auditordb/select_early_aggregations.c
+ * @brief Implementation of the select_early_aggregations function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_early_aggregations.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #early_aggregation_cb().
+ */
+struct EarlyAggregationContext
+{
+
+ /**
+ * Function to call for each early aggregation.
+ */
+ TALER_AUDITORDB_EarlyAggregationsCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_select_purse_expired().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct EarlyAggregationContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+early_aggregation_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct EarlyAggregationContext *eic = cls;
+ struct AUDITORDB_PostgresContext *ctx = eic->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_AUDITORDB_EarlyAggregation ea;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &ea.row_id),
+ GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id",
+ &ea.batch_deposit_serial_id),
+ GNUNET_PQ_result_spec_uint64 ("tracking_serial_id",
+ &ea.tracking_serial_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &ea.total),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &ea.suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+
+ /* just to be safe in case the structure changes */
+ memset (&ea,
+ 0,
+ sizeof (ea));
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ eic->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ eic->cb (eic->cb_cls,
+ &ea);
+ }
+ eic->qs = num_results;
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_early_aggregations (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_EarlyAggregationsCallback 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 (return_suppressed),
+ GNUNET_PQ_query_param_end
+ };
+ struct EarlyAggregationContext eic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_select_early_aggregations_asc",
+ "SELECT"
+ " row_id"
+ ",batch_deposit_serial_id"
+ ",tracking_serial_id"
+ ",amount"
+ ",suppressed"
+ " FROM auditor_early_aggregations"
+ " WHERE row_id > $1"
+ " AND ($3 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $2;");
+ PREPARE (ctx,
+ "auditor_select_early_aggregations_desc",
+ "SELECT"
+ " row_id"
+ ",batch_deposit_serial_id"
+ ",tracking_serial_id"
+ ",amount"
+ ",suppressed"
+ " FROM auditor_early_aggregations"
+ " WHERE row_id < $1"
+ " AND ($3 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $2;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ (limit < 0)
+ ? "auditor_select_early_aggregations_desc"
+ : "auditor_select_early_aggregations_asc ",
+ params,
+ &early_aggregation_cb,
+ &eic);
+ if (0 > qs)
+ return qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != eic.qs);
+ return eic.qs;
+}
diff --git a/src/auditordb/select_historic_denom_revenue.c b/src/auditordb/select_historic_denom_revenue.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 pg_select_historic_denom_revenue.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_historic_denom_revenue.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #historic_denom_revenue_cb().
+ */
+struct HistoricDenomRevenueContext
+{
+ /**
+ * Function to call for each result.
+ */
+ TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Number of results processed.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_select_historic_denom_revenue().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct HistoricRevenueContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+historic_denom_revenue_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct HistoricDenomRevenueContext *hrc = cls;
+ struct AUDITORDB_PostgresContext *ctx = hrc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t rowid;
+ struct TALER_DenominationHashP denom_pub_hash;
+ struct GNUNET_TIME_Timestamp revenue_timestamp;
+ struct TALER_Amount revenue_balance;
+ struct TALER_Amount loss;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &rowid),
+ GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+ &denom_pub_hash),
+ GNUNET_PQ_result_spec_timestamp ("revenue_timestamp",
+ &revenue_timestamp),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("revenue_balance",
+ &revenue_balance),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("loss_balance",
+ &loss),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ hrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+
+ hrc->qs = i + 1;
+ if (GNUNET_OK !=
+ hrc->cb (hrc->cb_cls,
+ rowid,
+ &denom_pub_hash,
+ revenue_timestamp,
+ &revenue_balance,
+ &loss))
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_historic_denom_revenue (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_HistoricDenominationRevenueDataCallback 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_end
+ };
+ struct HistoricDenomRevenueContext hrc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_historic_denomination_revenue_select_inc",
+ "SELECT"
+ " row_id"
+ ",denom_pub_hash"
+ ",revenue_timestamp"
+ ",revenue_balance"
+ ",loss_balance"
+ " FROM auditor_historic_denomination_revenue"
+ " WHERE row_id > $1"
+ " ORDER BY row_id ASC"
+ " LIMIT $2;");
+ PREPARE (ctx,
+ "auditor_historic_denomination_revenue_select_dec",
+ "SELECT"
+ " row_id"
+ ",denom_pub_hash"
+ ",revenue_timestamp"
+ ",revenue_balance"
+ ",loss_balance"
+ " FROM auditor_historic_denomination_revenue"
+ " WHERE row_id < $1"
+ " ORDER BY row_id DESC"
+ " LIMIT $2;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ limit > 0
+ ? "auditor_historic_denomination_revenue_select_inc"
+ : "auditor_historic_denomination_revenue_select_dec",
+ params,
+ &historic_denom_revenue_cb,
+ &hrc);
+ if (qs <= 0)
+ return qs;
+ return hrc.qs;
+}
diff --git a/src/auditordb/select_historic_reserve_revenue.c b/src/auditordb/select_historic_reserve_revenue.c
@@ -0,0 +1,165 @@
+/*
+ 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_historic_reserve_revenue.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_historic_reserve_revenue.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #historic_reserve_revenue_cb().
+ */
+struct HistoricReserveRevenueContext
+{
+ /**
+ * Function to call for each result.
+ */
+ TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Number of results processed.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_select_historic_reserve_revenue().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct HistoricRevenueContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+historic_reserve_revenue_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct HistoricReserveRevenueContext *hrc = cls;
+ struct AUDITORDB_PostgresContext *ctx = hrc->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t rowid;
+ struct GNUNET_TIME_Timestamp start_date;
+ struct GNUNET_TIME_Timestamp end_date;
+ struct TALER_Amount reserve_profits;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &rowid),
+ GNUNET_PQ_result_spec_timestamp ("start_date",
+ &start_date),
+ GNUNET_PQ_result_spec_timestamp ("end_date",
+ &end_date),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_profits",
+ &reserve_profits),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ hrc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ hrc->qs = i + 1;
+ if (GNUNET_OK !=
+ hrc->cb (hrc->cb_cls,
+ rowid,
+ start_date,
+ end_date,
+ &reserve_profits))
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_historic_reserve_revenue (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_HistoricReserveRevenueDataCallback 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_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ struct HistoricReserveRevenueContext hrc = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+
+ PREPARE (ctx,
+ "auditor_historic_reserve_summary_select_inc",
+ "SELECT"
+ " row_id"
+ ",start_date"
+ ",end_date"
+ ",reserve_profits"
+ " FROM auditor_historic_reserve_summary"
+ " WHERE row_id > $1"
+ " ORDER BY row_id ASC"
+ " LIMIT $2");
+ PREPARE (ctx,
+ "auditor_historic_reserve_summary_select_dec",
+ "SELECT"
+ " row_id"
+ ",start_date"
+ ",end_date"
+ ",reserve_profits"
+ " FROM auditor_historic_reserve_summary"
+ " WHERE row_id < $1"
+ " ORDER BY row_id DESC"
+ " LIMIT $2");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ limit > 0
+ ? "auditor_historic_reserve_summary_select_inc"
+ : "auditor_historic_reserve_summary_select_dec",
+ params,
+ &historic_reserve_revenue_cb,
+ &hrc);
+ if (0 >= qs)
+ return qs;
+ return hrc.qs;
+}
diff --git a/src/auditordb/select_pending_deposits.c b/src/auditordb/select_pending_deposits.c
@@ -0,0 +1,183 @@
+/*
+ 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 src/auditordb/select_pending_deposits.c
+ * @brief Implementation of the select_pending_deposits function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_pending_deposits.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #wire_missing_cb().
+ */
+struct WireMissingContext
+{
+
+ /**
+ * Function to call for each pending deposit.
+ */
+ TALER_AUDITORDB_WireMissingCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_select_purse_expired().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct WireMissingContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+wire_missing_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireMissingContext *eic = cls;
+ struct AUDITORDB_PostgresContext *ctx = eic->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t row_id;
+ uint64_t batch_deposit_serial_id;
+ struct TALER_Amount total_amount;
+ struct TALER_FullPaytoHashP wire_target_h_payto;
+ struct GNUNET_TIME_Timestamp deadline;
+ bool suppressed;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &row_id),
+ GNUNET_PQ_result_spec_uint64 ("batch_deposit_serial_id",
+ &batch_deposit_serial_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("total_amount",
+ &total_amount),
+ GNUNET_PQ_result_spec_auto_from_type ("wire_target_h_payto",
+ &wire_target_h_payto),
+ GNUNET_PQ_result_spec_timestamp ("deadline",
+ &deadline),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ eic->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ eic->cb (eic->cb_cls,
+ row_id,
+ batch_deposit_serial_id,
+ &total_amount,
+ &wire_target_h_payto,
+ deadline,
+ suppressed);
+ }
+ eic->qs = num_results;
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_pending_deposits (struct AUDITORDB_PostgresContext *ctx,
+ struct GNUNET_TIME_Absolute deadline,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_WireMissingCallback cb,
+ void *cb_cls)
+{
+ uint64_t ulimit = (limit < 0) ? -limit : limit;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_absolute_time (&deadline),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ GNUNET_PQ_query_param_bool (return_suppressed),
+ GNUNET_PQ_query_param_end
+ };
+ struct WireMissingContext eic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_select_pending_deposits_asc",
+ "SELECT"
+ " row_id"
+ ",total_amount"
+ ",wire_target_h_payto"
+ ",batch_deposit_serial_id"
+ ",deadline"
+ ",suppressed"
+ " FROM auditor_pending_deposits"
+ " WHERE deadline<$1"
+ " AND (row_id > $2)"
+ " AND ($4 OR NOT suppressed)"
+ " ORDER BY row_id ASC"
+ " LIMIT $3;");
+ PREPARE (ctx,
+ "auditor_select_pending_deposits_desc",
+ "SELECT"
+ " row_id"
+ ",total_amount"
+ ",wire_target_h_payto"
+ ",batch_deposit_serial_id"
+ ",deadline"
+ ",suppressed"
+ " FROM auditor_pending_deposits"
+ " WHERE deadline<$1"
+ " AND (row_id < $2)"
+ " AND ($4 OR NOT suppressed)"
+ " ORDER BY row_id DESC"
+ " LIMIT $3;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (
+ ctx->conn,
+ "auditor_select_pending_deposits",
+ params,
+ &wire_missing_cb,
+ &eic);
+ if (0 > qs)
+ return qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != eic.qs);
+ return eic.qs;
+}
diff --git a/src/auditordb/select_purse_expired.c b/src/auditordb/select_purse_expired.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 src/auditordb/select_purse_expired.c
+ * @brief Implementation of the select_purse_expired function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_purse_expired.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #purse_expired_cb().
+ */
+struct PurseExpiredContext
+{
+
+ /**
+ * Function to call for each expired purse.
+ */
+ TALER_AUDITORDB_ExpiredPurseCallback cb;
+
+ /**
+ * Closure for @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+ /**
+ * Query status to return.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Helper function for #AUDITORDB_select_purse_expired().
+ * To be called with the results of a SELECT statement
+ * that has returned @a num_results results.
+ *
+ * @param cls closure of type `struct PurseExpiredContext *`
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+purse_expired_cb (struct AUDITORDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseExpiredContext *eic = cls;
+ struct AUDITORDB_PostgresContext *ctx = eic->ctx;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct GNUNET_TIME_Timestamp expiration_date;
+ struct TALER_Amount balance;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
+ &purse_pub),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("balance",
+ &balance),
+ GNUNET_PQ_result_spec_timestamp ("expiration_date",
+ &expiration_date),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ eic->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ eic->qs = i + 1;
+ if (GNUNET_OK !=
+ eic->cb (eic->cb_cls,
+ &purse_pub,
+ &balance,
+ expiration_date))
+ break;
+ }
+}
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_purse_expired (struct AUDITORDB_PostgresContext *ctx,
+ TALER_AUDITORDB_ExpiredPurseCallback cb,
+ void *cb_cls)
+{
+ struct GNUNET_TIME_Timestamp now
+ = GNUNET_TIME_timestamp_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_timestamp (&now),
+ GNUNET_PQ_query_param_end
+ };
+ struct PurseExpiredContext eic = {
+ .cb = cb,
+ .cb_cls = cb_cls,
+ .ctx = ctx
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "auditor_select_expired_purses",
+ "SELECT"
+ " purse_pub"
+ ",expiration_date"
+ ",balance"
+ " FROM auditor_purses"
+ " WHERE expiration_date<$1;");
+ qs = GNUNET_PQ_eval_prepared_multi_select (ctx->conn,
+ "auditor_select_expired_purses",
+ params,
+ &purse_expired_cb,
+ &eic);
+ if (qs > 0)
+ return eic.qs;
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+ return qs;
+}
diff --git a/src/auditordb/select_reserve_in_inconsistency.c b/src/auditordb/select_reserve_in_inconsistency.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 src/auditordb/select_reserve_in_inconsistency.c
+ * @brief Implementation of the select_reserve_in_inconsistency function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_reserve_in_inconsistency.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t bank_row_id,
+ struct TALER_AUDITORDB_ReserveInInconsistency *dc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&bank_row_id),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("row_id",
+ &dc->serial_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_exchange_expected",
+ &dc->amount_exchange_expected),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount_wired",
+ &dc->amount_wired),
+ GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
+ &dc->reserve_pub),
+ GNUNET_PQ_result_spec_absolute_time ("timestamp",
+ &dc->timestamp),
+ GNUNET_PQ_result_spec_string ("account",
+ &dc->account.full_payto),
+ GNUNET_PQ_result_spec_string ("diagnostic",
+ &dc->diagnostic),
+ GNUNET_PQ_result_spec_bool ("suppressed",
+ &dc->suppressed),
+ GNUNET_PQ_result_spec_end
+ };
+
+ dc->bank_row_id = bank_row_id;
+ PREPARE (ctx,
+ "select_reserve_in_inconsistency",
+ "SELECT"
+ " row_id"
+ ",amount_exchange_expected"
+ ",amount_wired"
+ ",reserve_pub"
+ ",timestamp"
+ ",account"
+ ",diagnostic"
+ ",suppressed"
+ " FROM auditor_reserve_in_inconsistency"
+ " WHERE (bank_row_id = $1)"
+ );
+ return GNUNET_PQ_eval_prepared_singleton_select (
+ ctx->conn,
+ "select_reserve_in_inconsistency",
+ params,
+ rs);
+}
diff --git a/src/auditordb/template.c b/src/auditordb/template.c
@@ -0,0 +1,26 @@
+/*
+ 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 src/auditordb/template.c
+ * @brief Implementation of the template function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "template.h"
+#include "pg_helper.h"
diff --git a/src/auditordb/update_auditor_progress.c b/src/auditordb/update_auditor_progress.c
@@ -0,0 +1,97 @@
+/*
+ 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 pg_update_auditor_progress.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_auditor_progress.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_auditor_progress (struct AUDITORDB_PostgresContext *ctx,
+ const char *progress_key,
+ uint64_t progress_offset,
+ ...)
+{
+ unsigned int cnt = 1;
+ va_list ap;
+
+ va_start (ap,
+ progress_offset);
+ while (NULL != va_arg (ap,
+ const char *))
+ {
+ cnt++;
+ (void) va_arg (ap,
+ uint64_t);
+ }
+ va_end (ap);
+ {
+ const char *keys[cnt];
+ uint64_t offsets[cnt];
+ unsigned int off = 1;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_array_ptrs_string (cnt,
+ keys,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_uint64 (cnt,
+ offsets,
+ ctx->conn),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ keys[0] = progress_key;
+ offsets[0] = progress_offset;
+
+ va_start (ap,
+ progress_offset);
+ while (off < cnt)
+ {
+ keys[off] = va_arg (ap,
+ const char *);
+ offsets[off] = va_arg (ap,
+ uint64_t);
+ off++;
+ }
+ GNUNET_assert (NULL == va_arg (ap,
+ const char *));
+ va_end (ap);
+
+ PREPARE (ctx,
+ "auditor_progress_update",
+ "UPDATE auditor_progress"
+ " SET progress_offset=data.off"
+ " FROM ("
+ " SELECT *"
+ " FROM UNNEST (CAST($1 AS TEXT[]),"
+ " CAST($2 AS INT8[]))"
+ " AS t(key,off)"
+ " ) AS data"
+ " WHERE auditor_progress.progress_key=data.key;");
+ qs = GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_progress_update",
+ params);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ return qs;
+ }
+}
diff --git a/src/auditordb/update_balance.c b/src/auditordb/update_balance.c
@@ -0,0 +1,98 @@
+/*
+ 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 src/auditordb/update_balance.c
+ * @brief Implementation of the update_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_balance.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_balance (struct AUDITORDB_PostgresContext *ctx,
+ const char *balance_key,
+ const struct TALER_Amount *balance_amount,
+ ...)
+{
+ unsigned int cnt = 1;
+ va_list ap;
+
+ va_start (ap,
+ balance_amount);
+ while (NULL != va_arg (ap,
+ const char *))
+ {
+ cnt++;
+ (void) va_arg (ap,
+ const struct TALER_Amount *);
+ }
+ va_end (ap);
+ {
+ const char *keys[cnt];
+ struct TALER_Amount amounts[cnt];
+ unsigned int off = 1;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_array_ptrs_string (cnt,
+ keys,
+ ctx->conn),
+ TALER_PQ_query_param_array_amount (cnt,
+ amounts,
+ ctx->conn),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ keys[0] = balance_key;
+ amounts[0] = *balance_amount;
+
+ va_start (ap,
+ balance_amount);
+ while (off < cnt)
+ {
+ keys[off] = va_arg (ap,
+ const char *);
+ amounts[off] = *va_arg (ap,
+ const struct TALER_Amount *);
+ off++;
+ }
+ GNUNET_assert (NULL == va_arg (ap,
+ const char *));
+ va_end (ap);
+
+ PREPARE (ctx,
+ "auditor_balance_update",
+ "UPDATE auditor_balances"
+ " SET balance_value.val=data.val"
+ " ,balance_value.frac=data.frac"
+ " FROM ("
+ " SELECT *"
+ " FROM UNNEST (CAST($1 AS TEXT[]),"
+ " CAST($2 AS taler_amount[]))"
+ " AS t(key,val,frac)"
+ " ) AS data"
+ " WHERE auditor_balances.balance_key=data.key;");
+ qs = GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_balance_update",
+ params);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ return qs;
+ }
+}
diff --git a/src/auditordb/update_denomination_balance.c b/src/auditordb/update_denomination_balance.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 pg_update_denomination_balance.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_denomination_balance.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_denomination_balance (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ const struct TALER_AUDITORDB_DenominationCirculationData *dcd)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dcd->denom_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dcd->denom_loss),
+ GNUNET_PQ_query_param_uint64 (&dcd->num_issued),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dcd->denom_risk),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &dcd->recoup_loss),
+ GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_denomination_pending_update",
+ "UPDATE auditor_denomination_pending SET"
+ " denom_balance=$1"
+ ",denom_loss=$2"
+ ",num_issued=$3"
+ ",denom_risk=$4"
+ ",recoup_loss=$5"
+ " WHERE denom_pub_hash=$6");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_denomination_pending_update",
+ params);
+}
diff --git a/src/auditordb/update_generic_suppressed.c b/src/auditordb/update_generic_suppressed.c
@@ -0,0 +1,87 @@
+/*
+ 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/>
+ */
+#include "taler/platform.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_helper.h"
+#include "update_generic_suppressed.h"
+
+struct Preparations
+{
+ /**
+ * Database reconnect counter.
+ */
+ unsigned long long cnt;
+
+ /**
+ * Which DB did we do prepare for.
+ */
+ struct AUDITORDB_PostgresContext *ctx;
+
+};
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_generic_suppressed (struct AUDITORDB_PostgresContext *ctx,
+ enum TALER_AUDITORDB_DeletableSuppressableTables table,
+ uint64_t row_id,
+ bool suppressed)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&row_id),
+ GNUNET_PQ_query_param_bool (suppressed),
+ GNUNET_PQ_query_param_end
+ };
+ static struct Preparations preps[
+ TALER_AUDITORDB_DELETABLESUPPRESSABLE_TABLES_MAX];
+
+ struct Preparations *prep = &preps[table];
+ const char *table_name = AUDITORDB_get_deletable_suppressable_table_name (table);
+ char statement_name[256];
+
+ GNUNET_snprintf (statement_name,
+ sizeof (statement_name),
+ "update_%s",
+ table_name);
+ if ( (ctx != prep->ctx) ||
+ (prep->cnt < ctx->prep_gen) )
+ {
+ char sql[256];
+ struct GNUNET_PQ_PreparedStatement ps[] = {
+ GNUNET_PQ_make_prepare (statement_name,
+ sql),
+ GNUNET_PQ_PREPARED_STATEMENT_END
+ };
+
+ GNUNET_snprintf (sql,
+ sizeof (sql),
+ "UPDATE %s SET"
+ " suppressed=$2"
+ " WHERE row_id=$1",
+ table_name);
+ if (GNUNET_OK !=
+ GNUNET_PQ_prepare_statements (ctx->conn,
+ ps))
+ {
+ GNUNET_break (0);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ prep->ctx = ctx;
+ prep->cnt = ctx->prep_gen;
+ }
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ statement_name,
+ params);
+}
diff --git a/src/auditordb/update_purse_info.c b/src/auditordb/update_purse_info.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 src/auditordb/update_purse_info.c
+ * @brief Implementation of the update_purse_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_purse_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_purse_info (struct AUDITORDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ balance),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_purses_update",
+ "UPDATE auditor_purses"
+ " SET balance=$2"
+ " WHERE purse_pub=$1");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_purses_update",
+ params);
+}
diff --git a/src/auditordb/update_reserve_info.c b/src/auditordb/update_reserve_info.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 pg_update_reserve_info.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_reserve_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_reserve_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_AUDITORDB_ReserveFeeBalance *rfb,
+ struct GNUNET_TIME_Timestamp expiration_date)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->reserve_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->reserve_loss),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->withdraw_fee_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->purse_fee_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->open_fee_balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &rfb->history_fee_balance),
+ GNUNET_PQ_query_param_timestamp (&expiration_date),
+ GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_update_reserve_info",
+ "UPDATE auditor_reserves SET"
+ " reserve_balance=$1"
+ ",reserve_loss=$2"
+ ",withdraw_fee_balance=$3"
+ ",purse_fee_balance=$4"
+ ",open_fee_balance=$5"
+ ",history_fee_balance=$6"
+ ",expiration_date=$7"
+ " WHERE reserve_pub=$8");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_update_reserve_info",
+ params);
+}
diff --git a/src/auditordb/update_wire_fee_summary.c b/src/auditordb/update_wire_fee_summary.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 pg_update_wire_fee_summary.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_wire_fee_summary.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_wire_fee_summary (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_Amount *wire_fee_balance)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (ctx->conn,
+ wire_fee_balance),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "auditor_wire_fee_balance_update",
+ "UPDATE auditor_wire_fee_balance SET"
+ " wire_fee_balance=$1");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "auditor_wire_fee_balance_update",
+ params);
+}
diff --git a/src/exchangedb/abort_shard.c b/src/exchangedb/abort_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 src/exchangedb/abort_shard.c
+ * @brief Implementation of the abort_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "abort_shard.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_abort_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "abort_shard",
+ params);
+}
diff --git a/src/exchangedb/activate_signing_key.c b/src/exchangedb/activate_signing_key.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 src/exchangedb/activate_signing_key.c
+ * @brief Implementation of the activate_signing_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "activate_signing_key.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_activate_signing_key (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_signkey",
+ iparams);
+}
diff --git a/src/exchangedb/add_denomination_key.c b/src/exchangedb/add_denomination_key.c
@@ -0,0 +1,84 @@
+/*
+ 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 src/exchangedb/add_denomination_key.c
+ * @brief Implementation of the add_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "add_denomination_key.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_add_denomination_key (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ &meta->value),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &meta->fees.withdraw),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &meta->fees.deposit),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &meta->fees.refresh),
+ TALER_PQ_query_param_amount (ctx->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 (ctx,
+ "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 (ctx->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,157 @@
+/*
+ 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 src/exchangedb/add_policy_fulfillment_proof.c
+ * @brief Implementation of the add_policy_fulfillment_proof function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "add_policy_fulfillment_proof.h"
+#include "pg_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
+EXCHANGEDB_add_policy_fulfillment_proof (struct EXCHANGEDB_PostgresContext *ctx,
+ 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, ctx->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 (ctx,
+ "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 (ctx->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 (ctx->conn,
+ &pos->commitment),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &pos->accumulated_total),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &pos->policy_fee),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &pos->transferable_amount),
+ GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->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,203 @@
+/*
+ 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 src/exchangedb/aggregate.c
+ * @brief Implementation of the aggregate function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_compute_shard.h"
+#include "pg_event_notify.h"
+#include "aggregate.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_aggregate (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 = 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 (),
+ ctx->aggregator_shift);
+ PREPARE (ctx,
+ "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 (ctx->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 (ctx->currency,
+ total));
+ return qs;
+ }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (ctx->currency,
+ &sum_deposit));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (ctx->currency,
+ &sum_refund));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (ctx->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,459 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_exchangedb_plugin.h"
+#include "taler/taler_pq_lib.h"
+#include "batch_ensure_coin_known.h"
+#include "pg_helper.h"
+
+
+static enum GNUNET_DB_QueryStatus
+insert1 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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 EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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 EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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
+EXCHANGEDB_batch_ensure_coin_known (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ &coin[i],
+ &result[i]);
+ i += 4;
+ continue;
+ }
+ switch (bs)
+ {
+ case 3:
+ case 2:
+ qs = insert2 (ctx,
+ &coin[i],
+ &result[i]);
+ i += 2;
+ break;
+ case 1:
+ qs = insert1 (ctx,
+ &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,259 @@
+/*
+ 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 src/exchangedb/begin_revolving_shard.c
+ * @brief Implementation of the begin_revolving_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "begin_revolving_shard.h"
+#include "pg_commit.h"
+#include "pg_helper.h"
+#include "pg_start.h"
+#include "pg_rollback.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_begin_revolving_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 !=
+ EXCHANGEDB_start (ctx,
+ "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 (ctx,
+ "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 (ctx->conn,
+ "get_last_revolving_shard",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ EXCHANGEDB_rollback (ctx);
+ 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 (ctx,
+ "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 (ctx->conn,
+ "create_revolving_shard",
+ params);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ EXCHANGEDB_rollback (ctx);
+ 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 */
+ EXCHANGEDB_rollback (ctx);
+ 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 (ctx,
+ "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 (ctx->conn,
+ "get_open_revolving_shard",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ EXCHANGEDB_rollback (ctx);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ /* no open shards available */
+ EXCHANGEDB_rollback (ctx);
+ 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 (ctx,
+ "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 (ctx->conn,
+ "reclaim_revolving_shard",
+ iparams);
+ switch (qsz)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ EXCHANGEDB_rollback (ctx);
+ 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 */
+ EXCHANGEDB_rollback (ctx);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
+ }
+ break; /* continue with commit */
+ }
+ } /* end claim oldest existing shard */
+
+ /* commit */
+ {
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = EXCHANGEDB_commit (ctx);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ EXCHANGEDB_rollback (ctx);
+ 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,264 @@
+/*
+ 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 src/exchangedb/begin_shard.c
+ * @brief Implementation of the begin_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "begin_shard.h"
+#include "pg_helper.h"
+#include "pg_start.h"
+#include "pg_rollback.h"
+#include "pg_commit.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_begin_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 !=
+ EXCHANGEDB_start (ctx,
+ "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 (ctx,
+ "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 (ctx->conn,
+ "get_open_shard",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on getting open shard\n");
+ EXCHANGEDB_rollback (ctx);
+ 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 (ctx,
+ "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 (ctx->conn,
+ "reclaim_shard",
+ iparams);
+ switch (qsz)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qsz;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on claiming open shard\n");
+ EXCHANGEDB_rollback (ctx);
+ 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 */
+ EXCHANGEDB_rollback (ctx);
+ 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 (ctx,
+ "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 (ctx->conn,
+ "get_last_shard",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on getting last shard\n");
+ EXCHANGEDB_rollback (ctx);
+ 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 (ctx,
+ "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 (ctx->conn,
+ "claim_next_shard",
+ params);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on claiming next shard\n");
+ EXCHANGEDB_rollback (ctx);
+ 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 */
+ EXCHANGEDB_rollback (ctx);
+ continue;
+ }
+ } /* claim_next_shard */
+
+ /* commit */
+commit:
+ {
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = EXCHANGEDB_commit (ctx);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Serialization error on commit for beginning shard\n");
+ EXCHANGEDB_rollback (ctx);
+ 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,47 @@
+/*
+ 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 src/exchangedb/clear_aml_lock.c
+ * @brief Implementation of the clear_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "clear_aml_lock.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_clear_aml_lock (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "clear_aml_lock",
+ "UPDATE kyc_targets"
+ " SET aml_program_lock_timeout=NULL"
+ " WHERE h_normalized_payto=$1");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "clear_aml_lock",
+ params);
+}
diff --git a/src/exchangedb/commit.c b/src/exchangedb/commit.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 src/exchangedb/commit.c
+ * @brief Implementation of the commit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "commit.h"
+#include "pg_helper.h"
+
+
+/**
+ * Commit the current transaction of a database connection.
+ *
+ * @param cls the `struct EXCHANGEDB_PostgresContext` with the plugin-specific state
+ * @return final transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_commit (struct EXCHANGEDB_PostgresContext *ctx)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_break (NULL != ctx->transaction_name);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Committing transaction `%s'\n",
+ ctx->transaction_name);
+ PREPARE (ctx,
+ "do_commit",
+ "COMMIT");
+ qs = GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "do_commit",
+ params);
+ ctx->transaction_name = NULL;
+ return qs;
+}
diff --git a/src/exchangedb/complete_shard.c b/src/exchangedb/complete_shard.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 src/exchangedb/complete_shard.c
+ * @brief Implementation of the complete_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "complete_shard.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_complete_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "complete_shard",
+ params);
+}
diff --git a/src/exchangedb/compute_shard.c b/src/exchangedb/compute_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 src/exchangedb/compute_shard.c
+ * @brief Implementation of the compute_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "compute_shard.h"
+#include "pg_helper.h"
+
+
+uint64_t
+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,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 src/exchangedb/count_known_coins.c
+ * @brief Implementation of the count_known_coins function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "count_known_coins.h"
+#include "pg_helper.h"
+
+long long
+EXCHANGEDB_count_known_coins (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/create_aggregation_transient.c
+ * @brief Implementation of the create_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "create_aggregation_transient.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_create_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "create_aggregation_transient",
+ params);
+}
diff --git a/src/exchangedb/create_tables.c b/src/exchangedb/create_tables.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 src/exchangedb/create_tables.c
+ * @brief Implementation of the create_tables function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "create_tables.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_create_tables (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 = ctx->conn;
+ ctx->prep_gen++;
+ ctx->conn = conn;
+ PREPARE (ctx,
+ "create_tables",
+ "SELECT"
+ " exchange_do_create_tables"
+ " ($1::INTEGER);");
+ ctx->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,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 src/exchangedb/delete_aggregation_transient.c
+ * @brief Implementation of the delete_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "delete_aggregation_transient.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_delete_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "delete_aggregation_transient",
+ "DELETE FROM aggregation_transient"
+ " WHERE wire_target_h_payto=$1"
+ " AND wtid_raw=$2");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "delete_aggregation_transient",
+ params);
+}
diff --git a/src/exchangedb/delete_shard_locks.c b/src/exchangedb/delete_shard_locks.c
@@ -0,0 +1,40 @@
+/*
+ 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 src/exchangedb/delete_shard_locks.c
+ * @brief Implementation of the delete_shard_locks function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "delete_shard_locks.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_delete_shard_locks (struct EXCHANGEDB_PostgresContext *ctx)
+{
+ 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 (ctx->conn,
+ es);
+}
diff --git a/src/exchangedb/disable_rules.c b/src/exchangedb/disable_rules.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 src/exchangedb/disable_rules.c
+ * @brief Implementation of the disable_rules function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "disable_rules.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_disable_rules (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "call_exchange_drop_customization",
+ "SELECT out_found"
+ " FROM exchange_drop_customization"
+ " ($1);");
+ qs = GNUNET_PQ_eval_prepared_singleton_select (ctx->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,111 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_check_deposit_idempotent.h"
+#include "pg_helper.h"
+#include "pg_compute_shard.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_check_deposit_idempotent (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_EXCHANGEDB_BatchDeposit *bd,
+ struct GNUNET_TIME_Timestamp *exchange_timestamp,
+ bool *is_idempotent)
+{
+ uint64_t deposit_shard = 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,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
+ coin_sigs,
+ ctx->conn),
+ TALER_PQ_query_param_array_amount (bd->num_cdis,
+ amounts_with_fee,
+ ctx->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 (ctx,
+ "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 (ctx->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,173 @@
+/*
+ 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 src/exchangedb/do_deposit.c
+ * @brief Implementation of the do_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_deposit.h"
+#include "pg_helper.h"
+#include "pg_compute_shard.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 = 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,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_ptrs_auto_from_type (bd->num_cdis,
+ coin_sigs,
+ ctx->conn),
+ TALER_PQ_query_param_array_amount (bd->num_cdis,
+ amounts_with_fee,
+ ctx->conn),
+ TALER_PQ_query_param_array_amount (bd->num_cdis,
+ deposit_fees,
+ ctx->conn),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &total_amount),
+ TALER_PQ_query_param_amount (ctx->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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/do_purse_delete.c
+ * @brief Implementation of the do_purse_delete function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_purse_delete.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_purse_delete (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,88 @@
+/*
+ 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 src/exchangedb/do_purse_deposit.c
+ * @brief Implementation of the do_purse_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_purse_deposit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_purse_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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 (
+ ctx->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 (),
+ ctx->legal_reserve_expiration_time));
+
+ PREPARE (ctx,
+ "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 (ctx->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,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 src/exchangedb/do_purse_merge.c
+ * @brief Implementation of the do_purse_merge function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_purse_merge.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_purse_merge (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 (ctx->exchange_url,
+ reserve_pub);
+ TALER_normalized_payto_hash (payto_uri,
+ &h_payto);
+ GNUNET_free (payto_uri.normalized_payto);
+ }
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "call_purse_merge",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_recoup.c b/src/exchangedb/do_recoup.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 src/exchangedb/do_recoup.c
+ * @brief Implementation of the do_recoup function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_recoup.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_recoup (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->legal_reserve_expiration_time);
+ struct GNUNET_TIME_Timestamp reserve_expiration
+ = GNUNET_TIME_relative_to_timestamp (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "call_recoup",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_recoup_refresh.c b/src/exchangedb/do_recoup_refresh.c
@@ -0,0 +1,78 @@
+/*
+ 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 src/exchangedb/do_recoup_refresh.c
+ * @brief Implementation of the do_recoup_refresh function for Postgres
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_recoup_refresh.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_recoup_refresh (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "call_recoup_refresh",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_refresh.c b/src/exchangedb/do_refresh.c
@@ -0,0 +1,140 @@
+/*
+ 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 src/exchangedb/do_refresh.c
+ * @brief Implementation of the do_refresh function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_exchangedb_plugin.h"
+#include "taler/taler_pq_lib.h"
+#include "do_refresh.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_refresh (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ ctx->conn),
+ GNUNET_PQ_query_param_auto_from_type (&refresh->planchets_h),
+ TALER_PQ_query_param_amount (ctx->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,
+ ctx->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,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_uint64 (refresh->num_coins, /* 12 */
+ refresh->denom_serials,
+ ctx->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 (ctx,
+ "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 (ctx->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 src/exchangedb/do_refund.c
+ * @brief Implementation of the do_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_refund.h"
+#include "pg_helper.h"
+#include "pg_compute_shard.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_refund (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 = EXCHANGEDB_compute_shard (&refund->details.merchant_pub);
+ struct TALER_Amount amount_without_fee;
+ struct GNUNET_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_amount (ctx->conn,
+ &refund->details.refund_amount),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &amount_without_fee),
+ TALER_PQ_query_param_amount (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "call_refund",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_reserve_open.c b/src/exchangedb/do_reserve_open.c
@@ -0,0 +1,99 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_reserve_open.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_reserve_open (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ total_paid),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ reserve_payment),
+ GNUNET_PQ_query_param_uint32 (&min_purse_limit),
+ GNUNET_PQ_query_param_uint32 (&ctx->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 (&ctx->legal_reserve_expiration_time),
+ GNUNET_PQ_query_param_timestamp (&now),
+ TALER_PQ_query_param_amount (ctx->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",
+ ctx->currency,
+ open_cost),
+ TALER_PQ_result_spec_amount ("out_reserve_balance",
+ ctx->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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/do_reserve_purse.c
+ * @brief Implementation of the do_reserve_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "do_reserve_purse.h"
+#include "pg_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 cls the @e cls of this struct with the plugin-specific state
+ * @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
+EXCHANGEDB_do_reserve_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (),
+ ctx->idle_reserve_expiration_time));
+ struct GNUNET_TIME_Timestamp reserve_gc
+ = GNUNET_TIME_absolute_to_timestamp (
+ GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+ ctx->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 (ctx->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 (ctx->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 (ctx->currency,
+ &zero_fee));
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "call_reserve_purse",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/do_withdraw.c b/src/exchangedb/do_withdraw.c
@@ -0,0 +1,142 @@
+/*
+ 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 src/exchangedb/do_withdraw.c
+ * @brief Implementation of the do_withdraw function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_exchangedb_plugin.h"
+#include "taler/taler_pq_lib.h"
+#include "do_withdraw.h"
+#include "pg_helper.h"
+#include <gnunet/gnunet_time_lib.h>
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_withdraw (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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,
+ ctx->conn),
+ TALER_PQ_query_param_array_blinded_denom_sig (withdraw->num_coins,
+ withdraw->denom_sigs,
+ ctx->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,
+ ctx->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,
+ ctx->legal_reserve_expiration_time));
+ PREPARE (ctx,
+ "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 (ctx->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,58 @@
+/*
+ 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 src/exchangedb/drain_kyc_alert.c
+ * @brief Implementation of the drain_kyc_alert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "drain_kyc_alert.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_drain_kyc_alert (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "drain_kyc_alert",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/drop_tables.c b/src/exchangedb/drop_tables.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 src/exchangedb/drop_tables.c
+ * @brief Implementation of the drop_tables function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "drop_tables.h"
+#include "pg_helper.h"
+
+
+/**
+ * Drop all Taler tables. This should only be used by testcases.
+ *
+ * @param cls the `struct EXCHANGEDB_PostgresContext` with the plugin-specific state
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_drop_tables (struct EXCHANGEDB_PostgresContext *ctx)
+{
+ struct GNUNET_PQ_Context *conn;
+ enum GNUNET_GenericReturnValue ret;
+
+ if (NULL != ctx->conn)
+ {
+ GNUNET_PQ_disconnect (ctx->conn);
+ ctx->conn = NULL;
+ }
+ conn = GNUNET_PQ_connect_with_cfg (ctx->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,76 @@
+/*
+ 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 src/exchangedb/enable_rules.c
+ * @brief Implementation of the enable_rules function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "enable_rules.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_enable_rules (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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,168 @@
+/*
+ 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 src/exchangedb/ensure_coin_known.c
+ * @brief Implementation of the ensure_coin_known function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_exchangedb_plugin.h"
+#include "taler/taler_pq_lib.h"
+#include "ensure_coin_known.h"
+#include "pg_helper.h"
+
+
+enum TALER_EXCHANGEDB_CoinKnownStatus
+EXCHANGEDB_ensure_coin_known (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/event_listen.c
+ * @brief Implementation of the event_listen function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "event_listen.h"
+#include "pg_helper.h"
+
+/**
+ * Register callback to be invoked on events of type @a es.
+ *
+ * @param cls database context to use
+ * @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 *
+EXCHANGEDB_event_listen (struct EXCHANGEDB_PostgresContext *ctx,
+ struct GNUNET_TIME_Relative timeout,
+ const struct GNUNET_DB_EventHeaderP *es,
+ GNUNET_DB_EventCallback cb,
+ void *cb_cls)
+{
+ return GNUNET_PQ_event_listen (ctx->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,36 @@
+/*
+ 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 src/exchangedb/event_listen_cancel.c
+ * @brief Implementation of the event_listen_cancel function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "event_listen_cancel.h"
+#include "pg_helper.h"
+
+
+void
+EXCHANGEDB_event_listen_cancel (struct EXCHANGEDB_PostgresContext *ctx,
+ struct GNUNET_DB_EventHandler *eh)
+
+{
+ (void) cls;
+ GNUNET_PQ_event_listen_cancel (eh);
+}
diff --git a/src/exchangedb/event_notify.c b/src/exchangedb/event_notify.c
@@ -0,0 +1,39 @@
+/*
+ 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 src/exchangedb/event_notify.c
+ * @brief Implementation of the event_notify function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "event_notify.h"
+#include "pg_helper.h"
+
+
+void
+EXCHANGEDB_event_notify (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct GNUNET_DB_EventHeaderP *es,
+ const void *extra,
+ size_t extra_size)
+{
+ GNUNET_PQ_event_notify (ctx->conn,
+ es,
+ extra,
+ extra_size);
+}
diff --git a/src/exchangedb/expire_purse.c b/src/exchangedb/expire_purse.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 src/exchangedb/expire_purse.c
+ * @brief Implementation of the expire_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "expire_purse.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_expire_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "call_expire_purse",
+ "SELECT "
+ " out_found AS found"
+ " FROM exchange_do_expire_purse"
+ " ($1,$2,$3);");
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (ctx->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,70 @@
+/*
+ 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 src/exchangedb/find_aggregation_transient.c
+ * @brief Implementation of the find_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "find_aggregation_transient.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_find_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->conn,
+ "find_transient_aggregations",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/gc.c b/src/exchangedb/gc.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 src/exchangedb/gc.c
+ * @brief Implementation of the gc function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "gc.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_gc (struct EXCHANGEDB_PostgresContext *ctx)
+{
+ 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 (ctx->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,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 src/exchangedb/get_coin_denomination.c
+ * @brief Implementation of the get_coin_denomination function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_coin_denomination.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_coin_denomination (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,1188 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_exchangedb_plugin.h"
+#include "taler/taler_pq_lib.h"
+#include "get_coin_transactions.h"
+#include "pg_helper.h"
+#include "pg_start_read_committed.h"
+#include "pg_commit.h"
+#include "pg_rollback.h"
+#include "plugin_exchangedb_common.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 #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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinHistoryContext *chc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = chc->ctx;
+ 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 (ctx->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
+EXCHANGEDB_get_coin_transactions (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx
+ };
+
+ *tlp = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Getting transactions for coin %s\n",
+ TALER_B2S (coin_pub));
+ PREPARE (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 !=
+ EXCHANGEDB_start_read_committed (ctx,
+ "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 (
+ ctx->conn,
+ "get_coin_history_etag_balance",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ if (begin_transaction)
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ if (begin_transaction)
+ EXCHANGEDB_rollback (ctx);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ if (begin_transaction)
+ EXCHANGEDB_rollback (ctx);
+ 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 (
+ ctx->conn,
+ "get_coin_history",
+ lparams,
+ &handle_history_entry,
+ &chc);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ if (begin_transaction)
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ if (begin_transaction)
+ EXCHANGEDB_rollback (ctx);
+ continue;
+ default:
+ break;
+ }
+ if (chc.failed)
+ {
+ if (begin_transaction)
+ EXCHANGEDB_rollback (ctx);
+ TEH_COMMON_free_coin_transaction_list (ctx,
+ chc.head);
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+ }
+ if (! begin_transaction)
+ {
+ *tlp = chc.head;
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ }
+ qs = EXCHANGEDB_commit (ctx);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ TEH_COMMON_free_coin_transaction_list (ctx,
+ chc.head);
+ chc.head = NULL;
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TEH_COMMON_free_coin_transaction_list (ctx,
+ 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,88 @@
+/*
+ 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 src/exchangedb/get_denomination_by_serial.c
+ * @brief Implementation of the get_denomination_by_serial function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_denomination_by_serial.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_denomination_by_serial (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,97 @@
+/*
+ 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 src/exchangedb/get_denomination_info.c
+ * @brief Implementation of the get_denomination_info function for Postgres
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_denomination_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_denomination_info (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/get_denomination_revocation.c
+ * @brief Implementation of the get_denomination_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_denomination_revocation.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_denomination_revocation (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/get_drain_profit.c
+ * @brief Implementation of the get_drain_profit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_drain_profit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_drain_profit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,171 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_expired_reserves.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ExpiredReserveContext *erc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = erc->ctx;
+ 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",
+ ctx->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
+EXCHANGEDB_get_expired_reserves (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,66 @@
+/*
+ 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 src/exchangedb/get_extension_manifest.c
+ * @brief Implementation of the get_extension_manifest function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_extension_manifest.h"
+#include "pg_helper.h"
+
+/**
+ * Function called to get the manifest of an extension
+ * (age-restriction, policy_extension_...)
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @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
+EXCHANGEDB_get_extension_manifest (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "get_extension_manifest",
+ "SELECT"
+ " manifest"
+ " FROM extensions"
+ " WHERE name=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->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 src/exchangedb/get_global_fee.c
+ * @brief Implementation of the get_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_global_fee.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_global_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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 src/exchangedb/get_global_fees.c
+ * @brief Implementation of the get_global_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_global_fees.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GlobalFeeContext *gctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = gctx->ctx;
+
+ 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
+EXCHANGEDB_get_global_fees (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->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,66 @@
+/*
+ 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 src/exchangedb/get_known_coin.c
+ * @brief Implementation of the get_known_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_known_coin.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_known_coin (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,125 @@
+/*
+ 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 src/exchangedb/get_kyc_rules.c
+ * @brief Implementation of the get_kyc_rules function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_kyc_rules.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_kyc_rules (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->conn,
+ "get_kyc_rules",
+ params,
+ rs);
+}
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_kyc_rules2 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,62 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_old_coin_by_h_blind.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_old_coin_by_h_blind (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,64 @@
+/*
+ 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 src/exchangedb/get_pending_kyc_requirement_process.c
+ * @brief Implementation of the get_pending_kyc_requirement_process function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_pending_kyc_requirement_process.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_pending_kyc_requirement_process (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,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 src/exchangedb/get_policy_details.c
+ * @brief Implementation of the get_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_policy_details.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_policy_details (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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,82 @@
+/*
+ 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 src/exchangedb/get_purse_deposit.c
+ * @brief Implementation of the get_purse_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_purse_deposit.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_purse_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,77 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_purse_request.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_purse_request (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,80 @@
+/*
+ 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 src/exchangedb/get_ready_deposit.c
+ * @brief Implementation of the get_ready_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_ready_deposit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_ready_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ 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 (ctx->conn,
+ query,
+ params,
+ rs);
+}
diff --git a/src/exchangedb/get_refresh.c b/src/exchangedb/get_refresh.c
@@ -0,0 +1,207 @@
+/*
+ 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 src/exchangedb/get_refresh.c
+ * @brief Implementation of the get_refresh function for Postgres
+ * @author get_refresh
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_refresh.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_refresh (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 (ctx->conn,
+ "transfer_pubs",
+ sizeof(*transfer_pubs),
+ &num_transfer_pubs,
+ (void **) &transfer_pubs),
+ &no_transfer_pubs),
+ GNUNET_PQ_result_spec_array_uint64 (ctx->conn,
+ "denom_serials",
+ &refresh->num_coins,
+ &denom_serials),
+ TALER_PQ_result_spec_array_blinded_denom_sig (ctx->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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/get_reserve_balance.c
+ * @brief Implementation of the get_reserve_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_reserve_balance.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_reserve_balance (struct EXCHANGEDB_PostgresContext *ctx,
+ 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",
+ ctx->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 (ctx,
+ "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 (ctx->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,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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_reserve_by_h_planchets.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_reserve_by_h_planchets (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "reserve_by_h_planchets",
+ "SELECT"
+ " reserve_pub"
+ ",withdraw_id"
+ " FROM withdraw"
+ " WHERE planchets_h=$1"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->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,998 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_reserve_history.h"
+#include "pg_start_read_committed.h"
+#include "pg_commit.h"
+#include "pg_rollback.h"
+#include "plugin_exchangedb_common.h"
+#include "pg_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 #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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rhc->ctx;
+
+ 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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rhc->ctx;
+
+ 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 (ctx->conn,
+ "denom_pub_hashes",
+ &num_denom_hs,
+ &my_denom_pub_hashes),
+ GNUNET_PQ_result_spec_array_uint64 (ctx->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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rhc->ctx;
+
+ 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
+ * #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rhc->ctx;
+
+ 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
+ * #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rhc->ctx;
+
+ 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
+ * #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveHistoryContext *rhc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rhc->ctx;
+
+ 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
+ * #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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->ctx->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
+EXCHANGEDB_get_reserve_history (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 = {
+ .ctx = ctx,
+ .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 (ctx->currency,
+ &rhc.balance_in));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (ctx->currency,
+ &rhc.balance_out));
+
+ *rhp = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Getting transactions for reserve %s\n",
+ TALER_B2S (reserve_pub));
+ PREPARE (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 (ctx,
+ "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 !=
+ EXCHANGEDB_start_read_committed (ctx,
+ "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 (
+ ctx->conn,
+ "get_reserve_history_etag",
+ params,
+ rs);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ EXCHANGEDB_rollback (ctx);
+ continue;
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ EXCHANGEDB_rollback (ctx);
+ 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 (
+ ctx->conn,
+ "get_reserve_history",
+ lparams,
+ &handle_history_entry,
+ &rhc);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ EXCHANGEDB_rollback (ctx);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ EXCHANGEDB_rollback (ctx);
+ continue;
+ default:
+ break;
+ }
+ if (rhc.failed)
+ {
+ EXCHANGEDB_rollback (ctx);
+ TEH_COMMON_free_reserve_history (ctx,
+ rhc.rh);
+ return GNUNET_DB_STATUS_SOFT_ERROR;
+ }
+ qs = EXCHANGEDB_commit (ctx);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ TEH_COMMON_free_reserve_history (ctx,
+ rhc.rh);
+ return qs;
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ TEH_COMMON_free_reserve_history (ctx,
+ 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,61 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_signature_for_known_coin.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_signature_for_known_coin (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,164 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_unfinished_close_requests.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CloseReserveContext *erc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = erc->ctx;
+ 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
+EXCHANGEDB_get_unfinished_close_requests (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,182 @@
+/*
+ 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 src/exchangedb/get_wire_accounts.c
+ * @brief Implementation of the get_wire_accounts function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_wire_accounts.h"
+#include "pg_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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_get_wire_accounts (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/get_wire_fee.c
+ * @brief Implementation of the get_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_wire_fee.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_wire_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,146 @@
+/*
+ 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 src/exchangedb/get_wire_fees.c
+ * @brief Implementation of the get_wire_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_wire_fees.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GetWireFeesContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+
+ 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
+EXCHANGEDB_get_wire_fees (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,79 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_exchangedb_plugin.h"
+#include "taler/taler_pq_lib.h"
+#include "get_wire_hash_for_contract.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_wire_hash_for_contract (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,193 @@
+/*
+ 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 src/exchangedb/get_withdraw.c
+ * @brief Implementation of the get_withdraw function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "get_withdraw.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_withdraw (struct EXCHANGEDB_PostgresContext *ctx,
+ 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",
+ ctx->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 (
+ ctx->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 (
+ ctx->conn,
+ "denom_sigs",
+ &num_sigs,
+ &my_denom_sigs),
+ GNUNET_PQ_result_spec_array_uint64 (
+ ctx->conn,
+ "denom_serials",
+ &num_coins,
+ &my_denom_serials),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->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,115 @@
+/*
+ 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 src/exchangedb/have_deposit2.c
+ * @brief Implementation of the have_deposit2 function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "have_deposit2.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_have_deposit2 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/inject_auditor_triggers.c
+ * @brief Implementation of the inject_auditor_triggers function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_gc.h"
+#include "pg_helper.h"
+#include "inject_auditor_triggers.h"
+
+
+/**
+ * Function called to inject auditor triggers into the
+ * database, triggering the real-time auditor upon
+ * relevant INSERTs.
+ *
+ * @param cls closure
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR on DB errors
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_inject_auditor_triggers (struct EXCHANGEDB_PostgresContext *ctx)
+{
+ 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 (ctx->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,60 @@
+/*
+ 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 src/exchangedb/insert_active_legitimization_measure.c
+ * @brief Implementation of the insert_active_legitimization_measure function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_active_legitimization_measure.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_active_legitimization_measure (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,187 @@
+/*
+ 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 src/exchangedb/insert_aml_decision.c
+ * @brief Implementation of the insert_aml_decision function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_aml_decision.h"
+#include "pg_helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_aml_decision (struct EXCHANGEDB_PostgresContext *ctx,
+ 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_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,
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "do_insert_aml_decision",
+ params,
+ rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ GNUNET_free (notify_s);
+ GNUNET_PQ_event_do_poll (ctx->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,64 @@
+/*
+ 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 src/exchangedb/insert_aml_officer.c
+ * @brief Implementation of the insert_aml_officer function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_aml_officer.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_aml_officer (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,68 @@
+/*
+ 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 src/exchangedb/insert_aml_program_failure.c
+ * @brief Implementation of the insert_aml_program_failure function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_aml_program_failure.h"
+#include "pg_helper.h"
+#include "pg_event_notify.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_aml_program_failure (struct EXCHANGEDB_PostgresContext *ctx,
+ 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_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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/insert_auditor.c
+ * @brief Implementation of the insert_auditor function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_auditor.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_auditor (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/insert_auditor_denom_sig.c
+ * @brief Implementation of the insert_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_auditor_denom_sig.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_auditor_denom_sig (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,66 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_close_request.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_close_request (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ balance),
+ TALER_PQ_query_param_amount (ctx->conn,
+ closing_fee),
+ GNUNET_PQ_query_param_string (payto_uri.full_payto),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_account_close",
+ params);
+}
diff --git a/src/exchangedb/insert_contract.c b/src/exchangedb/insert_contract.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 src/exchangedb/insert_contract.c
+ * @brief Implementation of the insert_contract function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_contract.h"
+#include "pg_select_contract_by_purse.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_contract (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_contract",
+ params);
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs)
+ return qs;
+ {
+ struct TALER_EncryptedContract econtract2;
+
+ qs = EXCHANGEDB_select_contract_by_purse (ctx,
+ 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,99 @@
+/*
+ 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 src/exchangedb/insert_denomination_info.c
+ * @brief Implementation of the insert_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_denomination_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_denomination_info (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ &issue->value),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &issue->fees.withdraw),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &issue->fees.deposit),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &issue->fees.refresh),
+ TALER_PQ_query_param_amount (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "denomination_insert",
+ params);
+}
diff --git a/src/exchangedb/insert_denomination_revocation.c b/src/exchangedb/insert_denomination_revocation.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 src/exchangedb/insert_denomination_revocation.c
+ * @brief Implementation of the insert_denomination_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_denomination_revocation.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_denomination_revocation (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "denomination_revocation_insert",
+ params);
+}
diff --git a/src/exchangedb/insert_drain_profit.c b/src/exchangedb/insert_drain_profit.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 src/exchangedb/insert_drain_profit.c
+ * @brief Implementation of the insert_drain_profit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_drain_profit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_drain_profit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ amount),
+ GNUNET_PQ_query_param_auto_from_type (master_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "drain_profit_insert",
+ params);
+}
diff --git a/src/exchangedb/insert_global_fee.c b/src/exchangedb/insert_global_fee.c
@@ -0,0 +1,136 @@
+/*
+ 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 src/exchangedb/insert_global_fee.c
+ * @brief Implementation of the insert_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_global_fee.h"
+#include "pg_helper.h"
+#include "pg_get_global_fee.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_global_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ &fees->history),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &fees->account),
+ TALER_PQ_query_param_amount (ctx->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 = EXCHANGEDB_get_global_fee (ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_global_fee",
+ params);
+}
diff --git a/src/exchangedb/insert_kyc_failure.c b/src/exchangedb/insert_kyc_failure.c
@@ -0,0 +1,89 @@
+/*
+ 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 src/exchangedb/insert_kyc_failure.c
+ * @brief Implementation of the insert_kyc_failure function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_kyc_failure.h"
+#include "pg_helper.h"
+#include "pg_event_notify.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_kyc_failure (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_kyc_failure",
+ params);
+ if (qs > 0)
+ {
+ /* FIXME-#9419: might want to do this eventually in the same transaction... */
+ struct TALER_KycCompletedEventP rep = {
+ .header.size = htons (sizeof (rep)),
+ .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+ .h_payto = *h_payto
+ };
+
+ EXCHANGEDB_event_notify (ctx,
+ &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,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 src/exchangedb/insert_kyc_requirement_process.c
+ * @brief Implementation of the insert_kyc_requirement_process function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_kyc_requirement_process.h"
+#include "pg_helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_kyc_requirement_process (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->conn,
+ "insert_kyc_requirement_process",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/insert_partner.c b/src/exchangedb/insert_partner.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 src/exchangedb/insert_partner.c
+ * @brief Implementation of the insert_partner function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_partner.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_partner (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_partner",
+ params);
+}
diff --git a/src/exchangedb/insert_purse_request.c b/src/exchangedb/insert_purse_request.c
@@ -0,0 +1,124 @@
+/*
+ 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 src/exchangedb/insert_purse_request.c
+ * @brief Implementation of the insert_purse_request function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_purse_request.h"
+#include "pg_get_purse_request.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_purse_request (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ amount),
+ TALER_PQ_query_param_amount (ctx->conn,
+ purse_fee),
+ GNUNET_PQ_query_param_auto_from_type (purse_sig),
+ GNUNET_PQ_query_param_end
+ };
+
+ *in_conflict = false;
+ PREPARE (ctx,
+ "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 (ctx->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 = EXCHANGEDB_get_purse_request (ctx,
+ 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,2451 @@
+/*
+ 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 src/exchangedb/insert_records_by_table.c
+ * @brief replicate_records_by_table implementation
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_records_by_table.h"
+#include "pg_helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+/**
+ * Signature of helper functions of #EXCHANGEDB_insert_records_by_table().
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ * @return transaction status code
+ */
+typedef enum GNUNET_DB_QueryStatus
+(*InsertRecordCallback)(struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_EXCHANGEDB_TableData *td);
+
+
+/**
+ * Function called with denominations records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_denominations (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.denominations.coin),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ &td->details.denominations.fees.withdraw),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ &td->details.denominations.fees.deposit),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ &td->details.denominations.fees.refresh),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ &td->details.denominations.fees.refund),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_denominations",
+ params);
+}
+
+
+/**
+ * Function called with denomination_revocations records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_denomination_revocations (
+ struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_denomination_revocations",
+ params);
+}
+
+
+/**
+ * Function called with wire target records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wire_targets (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->conn,
+ "insert_into_table_wire_targets",
+ params);
+}
+
+
+/**
+ * Function called with kyc target records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_kyc_targets (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_kyc_targets",
+ params);
+}
+
+
+/**
+ * Function called with records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_legitimization_measures (
+ struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_legitimization_measures",
+ params);
+}
+
+
+/**
+ * Function called with records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_legitimization_outcomes (
+ struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_legitimization_outcomes",
+ params);
+}
+
+
+/**
+ * Function called with records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_legitimization_processes (
+ struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_legitimization_processes",
+ params);
+}
+
+
+/**
+ * Function called with reserves records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_reserves",
+ params);
+}
+
+
+/**
+ * Function called with reserves_in records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves_in (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_reserves_in",
+ params);
+}
+
+
+/**
+ * Function called with kycauth_in records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_kycauths_in (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_kycauth_in",
+ params);
+}
+
+
+/**
+ * Function called with reserves_open_requests records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves_open_requests (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_reserves_open_requests",
+ params);
+}
+
+
+/**
+ * Function called with reserves_open_requests records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves_open_deposits (
+ struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.reserves_open_deposits.contribution),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_reserves_open_deposits",
+ params);
+}
+
+
+/**
+ * Function called with reserves_close records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_reserves_close (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.reserves_close.amount),
+ TALER_PQ_query_param_amount (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_reserves_close",
+ params);
+}
+
+
+/**
+ * Function called with auditors records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_auditors (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_auditors",
+ params);
+}
+
+
+/**
+ * Function called with auditor_denom_sigs records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_auditor_denom_sigs (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_auditor_denom_sigs",
+ params);
+}
+
+
+/**
+ * Function called with exchange_sign_keys records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_exchange_sign_keys (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_exchange_sign_keys",
+ params);
+}
+
+
+/**
+ * Function called with signkey_revocations records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_signkey_revocations (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_signkey_revocations",
+ params);
+}
+
+
+/**
+ * Function called with known_coins records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_known_coins (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_known_coins",
+ params);
+}
+
+
+/**
+ * Function called with refresh records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_refresh (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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,
+ ctx->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,
+ ctx->conn),
+ TALER_PQ_query_param_array_blinded_denom_sig (
+ td->details.refresh.num_coins,
+ td->details.refresh.denom_sigs,
+ ctx->conn),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_refresh",
+ params);
+}
+
+
+/**
+ * Function called with batch deposits records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_batch_deposits (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.batch_deposits.total_amount),
+ TALER_PQ_query_param_amount (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_batch_deposits",
+ params);
+}
+
+
+/**
+ * Function called with deposits records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_coin_deposits (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.coin_deposits.amount_with_fee),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_coin_deposits",
+ params);
+}
+
+
+/**
+ * Function called with refunds records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_refunds (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_refunds",
+ params);
+}
+
+
+/**
+ * Function called with wire_out records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wire_out (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.wire_out.amount),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_wire_out",
+ params);
+}
+
+
+/**
+ * Function called with aggregation_tracking records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_aggregation_tracking (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_aggregation_tracking",
+ params);
+}
+
+
+/**
+ * Function called with wire_fee records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wire_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.wire_fee.fees.wire),
+ TALER_PQ_query_param_amount (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_wire_fee",
+ params);
+}
+
+
+/**
+ * Function called with wire_fee records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_global_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.global_fee.fees.history),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ &td->details.global_fee.fees.account),
+ TALER_PQ_query_param_amount (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_global_fee",
+ params);
+}
+
+
+/**
+ * Function called with recoup records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_recoup (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_recoup",
+ params);
+}
+
+
+/**
+ * Function called with recoup_refresh records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_recoup_refresh (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_recoup_refresh",
+ params);
+}
+
+
+/**
+ * Function called with extensions records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_extensions (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "insert_into_table_extensions",
+ "INSERT INTO extensions"
+ "(extension_id"
+ ",name"
+ ",manifest"
+ ") VALUES "
+ "($1, $2, $3);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "insert_into_table_extensions",
+ params);
+}
+
+
+/**
+ * Function called with policy_details records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_policy_details (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.policy_details.commitment),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ &td->details.policy_details.accumulated_total),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ &td->details.policy_details.fee),
+ TALER_PQ_query_param_amount (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_policy_details",
+ params);
+}
+
+
+/**
+ * Function called with policy_fulfillment records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_policy_fulfillments (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_policy_fulfillments",
+ params);
+}
+
+
+/**
+ * Function called with purse_requests records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_requests (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.purse_requests.amount_with_fee),
+ TALER_PQ_query_param_amount (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_purse_requests",
+ params);
+}
+
+
+/**
+ * Function called with purse_decision records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_decision (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_purse_decision",
+ params);
+}
+
+
+/**
+ * Function called with purse_merges records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_merges (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_purse_merges",
+ params);
+}
+
+
+/**
+ * Function called with purse_deposits records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_deposits (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_purse_deposits",
+ params);
+}
+
+
+/**
+x * Function called with account_mergers records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_account_mergers (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_account_merges",
+ params);
+}
+
+
+/**
+ * Function called with history_requests records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_history_requests (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.history_requests.history_fee),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_history_requests",
+ params);
+}
+
+
+/**
+ * Function called with close_requests records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_close_requests (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.close_requests.close),
+ TALER_PQ_query_param_amount (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_close_requests",
+ params);
+}
+
+
+/**
+ * Function called with wads_out records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wads_out (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.wads_out.amount),
+ GNUNET_PQ_query_param_timestamp (&td->details.wads_out.execution_time),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_wads_out",
+ params);
+}
+
+
+/**
+ * Function called with wads_out_entries records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wads_out_entries (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.wads_out_entries.amount_with_fee),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ &td->details.wads_out_entries.wad_fee),
+ TALER_PQ_query_param_amount (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_wads_out_entries",
+ params);
+}
+
+
+/**
+ * Function called with wads_in records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wads_in (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.wads_in.amount),
+ GNUNET_PQ_query_param_timestamp (&td->details.wads_in.arrival_time),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_wads_in",
+ params);
+}
+
+
+/**
+ * Function called with wads_in_entries records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wads_in_entries (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->conn,
+ &td->details.wads_in_entries.amount_with_fee),
+ TALER_PQ_query_param_amount (
+ ctx->conn,
+ &td->details.wads_in_entries.wad_fee),
+ TALER_PQ_query_param_amount (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_wads_in_entries",
+ params);
+}
+
+
+/**
+ * Function called with profit_drains records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_profit_drains (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_profit_drains",
+ params);
+}
+
+
+/**
+ * Function called with aml_staff records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_aml_staff (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_aml_staff",
+ params);
+}
+
+
+/**
+ * Function called with kyc_attributes records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_kyc_attributes (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_kyc_attributes",
+ params);
+}
+
+
+/**
+ * Function called with aml_history records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_aml_history (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_aml_history",
+ params);
+}
+
+
+/**
+ * Function called with kyc_event records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_kyc_events (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_kyc_events",
+ params);
+}
+
+
+/**
+ * Function called with purse_deletion records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_purse_deletion (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_purse_deletion",
+ params);
+}
+
+
+/**
+ * Function called with withdraw records to insert into table.
+ *
+ * @param ctx plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_withdraw (
+ struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (
+ ctx->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,
+ ctx->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,
+ ctx->conn),
+ TALER_PQ_query_param_array_blinded_denom_sig (
+ td->details.withdraw.num_coins,
+ td->details.withdraw.denom_sigs,
+ ctx->conn),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "insert_into_table_withdraw",
+ params);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ return qs;
+}
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_records_by_table (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ td);
+}
+
+
+/* end of pg_insert_records_by_table.c */
diff --git a/src/exchangedb/insert_refund.c b/src/exchangedb/insert_refund.c
@@ -0,0 +1,64 @@
+/*
+ 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 src/exchangedb/insert_refund.c
+ * @brief Implementation of the insert_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_refund.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_refund (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_refund",
+ params);
+}
diff --git a/src/exchangedb/insert_reserve_closed.c b/src/exchangedb/insert_reserve_closed.c
@@ -0,0 +1,111 @@
+/*
+ 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 src/exchangedb/insert_reserve_closed.c
+ * @brief Implementation of the insert_reserve_closed function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_reserve_closed.h"
+#include "pg_helper.h"
+#include "pg_reserves_get.h"
+#include "pg_reserves_update.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_reserve_closed (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ amount_with_fee),
+ TALER_PQ_query_param_amount (ctx->conn,
+ closing_fee),
+ GNUNET_PQ_query_param_uint64 (&close_request_row),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->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 = EXCHANGEDB_reserves_get (cls,
+ &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 EXCHANGEDB_reserves_update (cls,
+ &reserve);
+}
diff --git a/src/exchangedb/insert_reserve_open_deposit.c b/src/exchangedb/insert_reserve_open_deposit.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 pg_insert_reserve_open_deposit.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_reserve_open_deposit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_reserve_open_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 (ctx,
+ "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 (ctx->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,92 @@
+/*
+ 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 src/exchangedb/insert_sanction_list_hit.c
+ * @brief Implementation of the insert_sanction_list_hit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_sanction_list_hit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_sanction_list_hit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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_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,
+ ctx->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 (ctx,
+ "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 (
+ ctx->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 (ctx->conn);
+ return qs;
+}
diff --git a/src/exchangedb/insert_signkey_revocation.c b/src/exchangedb/insert_signkey_revocation.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 src/exchangedb/insert_signkey_revocation.c
+ * @brief Implementation of the insert_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_signkey_revocation.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_signkey_revocation (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_signkey_revocation",
+ params);
+}
diff --git a/src/exchangedb/insert_successor_measure.c b/src/exchangedb/insert_successor_measure.c
@@ -0,0 +1,86 @@
+/*
+ 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 src/exchangedb/insert_successor_measure.c
+ * @brief Implementation of the insert_succesor_measure function for Postgres
+ * @author Florian Dold
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_successor_measure.h"
+#include "pg_helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_successor_measure (struct EXCHANGEDB_PostgresContext *ctx,
+ 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_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 (ctx,
+ "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 (ctx->conn,
+ "do_insert_successor_measure",
+ params,
+ rs);
+ GNUNET_free (notify_s);
+ GNUNET_PQ_event_do_poll (ctx->conn);
+ return qs;
+}
diff --git a/src/exchangedb/insert_wire.c b/src/exchangedb/insert_wire.c
@@ -0,0 +1,83 @@
+/*
+ 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 src/exchangedb/insert_wire.c
+ * @brief Implementation of the insert_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_wire.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_wire (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_wire",
+ params);
+}
diff --git a/src/exchangedb/insert_wire_fee.c b/src/exchangedb/insert_wire_fee.c
@@ -0,0 +1,109 @@
+/*
+ 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 src/exchangedb/insert_wire_fee.c
+ * @brief Implementation of the insert_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "insert_wire_fee.h"
+#include "pg_helper.h"
+#include "pg_get_wire_fee.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_wire_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ &fees->wire),
+ TALER_PQ_query_param_amount (ctx->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 = EXCHANGEDB_get_wire_fee (ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "insert_wire_fee",
+ params);
+}
diff --git a/src/exchangedb/iterate_active_auditors.c b/src/exchangedb/iterate_active_auditors.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 src/exchangedb/iterate_active_auditors.c
+ * @brief Implementation of the iterate_active_auditors function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "iterate_active_auditors.h"
+#include "pg_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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_iterate_active_auditors (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "select_auditors",
+ "SELECT"
+ " auditor_pub"
+ ",auditor_url"
+ ",auditor_name"
+ " FROM auditors"
+ " WHERE"
+ " is_active;");
+
+ return GNUNET_PQ_eval_prepared_multi_select (ctx->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,143 @@
+/*
+ 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 src/exchangedb/iterate_active_signkeys.c
+ * @brief Implementation of the iterate_active_signkeys function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "iterate_active_signkeys.h"
+#include "pg_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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each signing key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_iterate_active_signkeys (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,119 @@
+/*
+ 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 src/exchangedb/iterate_auditor_denominations.c
+ * @brief Implementation of the iterate_auditor_denominations function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "iterate_auditor_denominations.h"
+#include "pg_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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_iterate_auditor_denominations (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/iterate_denomination_info.c
+ * @brief Implementation of the iterate_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "iterate_denomination_info.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+};
+
+
+/**
+ * Helper function for #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct DenomIteratorContext *dic = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dic->ctx;
+
+ 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 cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each denomination key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_iterate_denomination_info (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->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 src/exchangedb/iterate_denominations.c
+ * @brief Implementation of the iterate_denominations function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "iterate_denominations.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+};
+
+
+/**
+ * Helper function for #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct DenomsIteratorContext *dic = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dic->ctx;
+
+ 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
+EXCHANGEDB_iterate_denominations (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->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,128 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "iterate_kyc_reference.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+};
+
+
+/**
+ * Helper function for #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_iterate_kyc_reference (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx
+ };
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,129 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "iterate_reserve_close_info.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #iterate_reserve_close_info_cb()
+ */
+struct IteratorContext
+{
+ /**
+ * Function to call with the results.
+ */
+ TALER_EXCHANGEDB_KycAmountCallback cb;
+
+ /**
+ * Closure to pass to @e cb
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct EXCHANGEDB_PostgresContext *ctx;
+};
+
+
+/**
+ * Helper function for #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct IteratorContext *ic = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ic->ctx;
+
+ 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
+EXCHANGEDB_iterate_reserve_close_info (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_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,
+ .ctx = ctx
+ };
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,68 @@
+/*
+ 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 src/exchangedb/kyc_provider_account_lookup.c
+ * @brief Implementation of the kyc_provider_account_lookup function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "kyc_provider_account_lookup.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_kyc_provider_account_lookup (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,80 @@
+/*
+ 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 src/exchangedb/kycauth_in_insert.c
+ * @brief Implementation of the kycauth_in_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "kycauth_in_insert.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_kycauth_in_insert (struct EXCHANGEDB_PostgresContext *ctx,
+ 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_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 (ctx->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 (ctx,
+ "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 (
+ ctx->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,64 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_active_legitimization.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_active_legitimization (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,61 @@
+/*
+ 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 src/exchangedb/lookup_aml_file_number.c
+ * @brief Implementation of the lookup_aml_file_number function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_aml_file_number.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_aml_file_number (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,202 @@
+/*
+ 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 src/exchangedb/lookup_aml_history.c
+ * @brief Implementation of the lookup_aml_history function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_aml_history.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for callbacks called from #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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_lookup_aml_history (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ uint64_t offset,
+ int64_t limit,
+ TALER_EXCHANGEDB_AmlHistoryCallback cb,
+ void *cb_cls)
+{
+ struct AmlHistoryContext ahc = {
+ .ctx = ctx,
+ .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 (ctx,
+ "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 (ctx,
+ "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 (
+ ctx->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,70 @@
+/*
+ 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 src/exchangedb/lookup_aml_officer.c
+ * @brief Implementation of the lookup_aml_officer function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_aml_officer.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_aml_officer (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,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 src/exchangedb/lookup_auditor_status.c
+ * @brief Implementation of the lookup_auditor_status function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_auditor_status.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_auditor_status (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "lookup_auditor_status",
+ "SELECT"
+ " auditor_url"
+ ",is_active"
+ " FROM auditors"
+ " WHERE auditor_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->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,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 src/exchangedb/lookup_auditor_timestamp.c
+ * @brief Implementation of the lookup_auditor_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_auditor_timestamp.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_auditor_timestamp (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "lookup_auditor_timestamp",
+ "SELECT"
+ " last_change"
+ " FROM auditors"
+ " WHERE auditor_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->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,97 @@
+/*
+ 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 src/exchangedb/lookup_completed_legitimization.c
+ * @brief Implementation of the lookup_pending_legitimization function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_completed_legitimization.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_completed_legitimization (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,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 src/exchangedb/lookup_denomination_key.c
+ * @brief Implementation of the lookup_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_denomination_key.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_denomination_key (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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 src/exchangedb/lookup_global_fee_by_time.c
+ * @brief Implementation of the lookup_global_fee_by_time function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_global_fee_by_time.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+};
+
+
+/**
+ * Helper function for #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct GlobalFeeLookupContext *wlc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = wlc->ctx;
+
+ 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
+EXCHANGEDB_lookup_global_fee_by_time (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->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,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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_h_payto_by_access_token.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_h_payto_by_access_token (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,193 @@
+/*
+ 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 src/exchangedb/lookup_kyc_history.c
+ * @brief Implementation of the lookup_kyc_history function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_kyc_history.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for callbacks called from #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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_lookup_kyc_history (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_KycHistoryCallback cb,
+ void *cb_cls)
+{
+ struct KycHistoryContext khc = {
+ .ctx = ctx,
+ .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 (ctx,
+ "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 (
+ ctx->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,92 @@
+/*
+ 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 src/exchangedb/lookup_kyc_process_by_account.c
+ * @brief Implementation of the lookup_kyc_process_by_account function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_kyc_process_by_account.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_kyc_process_by_account (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,111 @@
+/*
+ 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 src/exchangedb/lookup_kyc_requirement_by_row.c
+ * @brief Implementation of the lookup_kyc_requirement_by_row function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_kyc_requirement_by_row.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_kyc_requirement_by_row (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,63 @@
+/*
+ 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 src/exchangedb/lookup_kyc_status_by_token.c
+ * @brief Implementation of the lookup_kyc_status_by_token function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_kyc_status_by_token.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_kyc_status_by_token (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,78 @@
+/*
+ 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 src/exchangedb/lookup_pending_legitimization.c
+ * @brief Implementation of the lookup_pending_legitimization function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_pending_legitimization.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_pending_legitimization (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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 src/exchangedb/lookup_records_by_table.c
+ * @brief implementation of lookup_records_by_table
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_records_by_table.h"
+#include "pg_helper.h"
+#include <gnunet/gnunet_pq_lib.h>
+
+
+/**
+ * Closure for callbacks used by #postgres_lookup_records_by_table.
+ */
+struct LookupRecordsByTableContext
+{
+ /**
+ * Plugin context.
+ */
+ struct EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (
+ ctx->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 (
+ ctx->conn,
+ "denom_serials",
+ &td.details.refresh.num_coins,
+ &td.details.refresh.denom_serials),
+ TALER_PQ_result_spec_array_blinded_denom_sig (
+ ctx->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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupRecordsByTableContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+ 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 (
+ ctx->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 (
+ ctx->conn,
+ "denom_serials",
+ &td.details.withdraw.num_coins,
+ &td.details.withdraw.denom_serials),
+ TALER_PQ_result_spec_array_blinded_denom_sig (
+ ctx->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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx, n, sql);
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_records_by_table (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 = {
+ .ctx = ctx,
+ .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 (ctx->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/lookup_rules_by_access_token.c b/src/exchangedb/lookup_rules_by_access_token.c
@@ -0,0 +1,68 @@
+/*
+ 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 src/exchangedb/lookup_rules_by_access_token.c
+ * @brief Implementation of the lookup_rules_by_access_token function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_rules_by_access_token.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_rules_by_access_token (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,466 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_serial_by_table.h"
+#include "pg_helper.h"
+
+
+/**
+ * Assign statement to @a n and PREPARE
+ * @a sql under name @a n.
+ */
+#define XPREPARE(n,sql) \
+ statement = n; \
+ PREPARE (ctx, n, sql);
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_serial_by_table (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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,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 src/exchangedb/lookup_signing_key.c
+ * @brief Implementation of the lookup_signing_key function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_signing_key.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_signing_key (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/lookup_signkey_revocation.c
+ * @brief Implementation of the lookup_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_signkey_revocation.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_signkey_revocation (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,222 @@
+/*
+ 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 src/exchangedb/lookup_transfer_by_deposit.c
+ * @brief Implementation of the lookup_transfer_by_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_transfer_by_deposit.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_transfer_by_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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 (ctx,
+ "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 (ctx->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,154 @@
+/*
+ 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 src/exchangedb/lookup_wire_fee_by_time.c
+ * @brief Implementation of the lookup_wire_fee_by_time function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_wire_fee_by_time.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+};
+
+
+/**
+ * Helper function for #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireFeeLookupContext *wlc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = wlc->ctx;
+
+ 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 cls closure
+ * @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
+EXCHANGEDB_lookup_wire_fee_by_time (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->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,54 @@
+/*
+ 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 src/exchangedb/lookup_wire_timestamp.c
+ * @brief Implementation of the lookup_wire_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_wire_timestamp.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_wire_timestamp (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "lookup_wire_timestamp",
+ "SELECT"
+ " last_change"
+ " FROM wire_accounts"
+ " WHERE payto_uri=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->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,186 @@
+/*
+ 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 src/exchangedb/lookup_wire_transfer.c
+ * @brief Implementation of the lookup_wire_transfer function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "lookup_wire_transfer.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireTransferResultContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+
+ 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
+EXCHANGEDB_lookup_wire_transfer (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,47 @@
+/*
+ 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 src/exchangedb/mark_refresh_reveal_success.c
+ * @brief Implementation of the mark_refresh_reveal_success function for Postgres
+ * @author Özgür Kesim
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "mark_refresh_reveal_success.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_mark_refresh_reveal_success (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_RefreshCommitmentP *rc)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_auto_from_type (rc),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "mark_refresh_reveal_success",
+ "UPDATE refresh"
+ " SET revealed=true"
+ " WHERE rc = $1");
+
+ return GNUNET_PQ_eval_prepared_non_select (
+ ctx->conn,
+ "mark_refresh_reveal_success",
+ params);
+}
+\ No newline at end of file
diff --git a/src/exchangedb/persist_kyc_attributes.c b/src/exchangedb/persist_kyc_attributes.c
@@ -0,0 +1,105 @@
+/*
+ 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 src/exchangedb/persist_kyc_attributes.c
+ * @brief Implementation of the persist_kyc_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "persist_kyc_attributes.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_persist_kyc_attributes (struct EXCHANGEDB_PostgresContext *ctx,
+ 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_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 (ctx,
+ "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 (ctx->conn,
+ "persist_kyc_attributes",
+ params,
+ rs);
+ GNUNET_PQ_cleanup_query_params_closures (params);
+ GNUNET_free (kyc_completed_notify_s);
+ GNUNET_PQ_event_do_poll (ctx->conn);
+ return qs;
+}
diff --git a/src/exchangedb/persist_policy_details.c b/src/exchangedb/persist_policy_details.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 src/exchangedb/persist_policy_details.c
+ * @brief Implementation of the persist_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "persist_policy_details.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_persist_policy_details (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ &details->commitment),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &details->accumulated_total),
+ TALER_PQ_query_param_amount (ctx->conn,
+ &details->policy_fee),
+ TALER_PQ_query_param_amount (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "call_insert_or_update_policy_details",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -27,212 +27,212 @@
#include <poll.h>
#include <pthread.h>
#include <libpq-fe.h>
-#include "pg_abort_shard.h"
-#include "pg_activate_signing_key.h"
-#include "pg_add_denomination_key.h"
-#include "pg_add_policy_fulfillment_proof.h"
-#include "pg_aggregate.h"
-#include "pg_batch_ensure_coin_known.h"
-#include "pg_begin_revolving_shard.h"
-#include "pg_begin_shard.h"
-#include "pg_clear_aml_lock.h"
-#include "pg_commit.h"
-#include "pg_complete_shard.h"
-#include "pg_compute_shard.h"
-#include "pg_count_known_coins.h"
-#include "pg_create_aggregation_transient.h"
-#include "pg_create_tables.h"
-#include "pg_delete_aggregation_transient.h"
-#include "pg_delete_shard_locks.h"
-#include "pg_disable_rules.h"
-#include "pg_do_withdraw.h"
-#include "pg_do_check_deposit_idempotent.h"
-#include "pg_do_deposit.h"
-#include "pg_do_purse_delete.h"
-#include "pg_do_purse_deposit.h"
-#include "pg_do_purse_merge.h"
-#include "pg_do_recoup.h"
-#include "pg_do_recoup_refresh.h"
-#include "pg_do_refresh.h"
-#include "pg_do_refund.h"
-#include "pg_do_reserve_open.h"
-#include "pg_do_reserve_purse.h"
-#include "pg_drain_kyc_alert.h"
-#include "pg_drop_tables.h"
-#include "pg_enable_rules.h"
-#include "pg_ensure_coin_known.h"
-#include "pg_event_listen.h"
-#include "pg_event_listen_cancel.h"
-#include "pg_event_notify.h"
-#include "pg_expire_purse.h"
-#include "pg_find_aggregation_transient.h"
-#include "pg_gc.h"
-#include "pg_get_withdraw.h"
-#include "pg_get_coin_denomination.h"
-#include "pg_get_coin_transactions.h"
-#include "pg_get_denomination_info.h"
-#include "pg_get_denomination_by_serial.h"
-#include "pg_get_denomination_revocation.h"
-#include "pg_get_drain_profit.h"
-#include "pg_get_expired_reserves.h"
-#include "pg_get_extension_manifest.h"
-#include "pg_get_global_fee.h"
-#include "pg_get_global_fees.h"
-#include "pg_get_known_coin.h"
-#include "pg_get_kyc_rules.h"
-#include "pg_get_old_coin_by_h_blind.h"
-#include "pg_get_pending_kyc_requirement_process.h"
-#include "pg_get_policy_details.h"
-#include "pg_get_purse_deposit.h"
-#include "pg_get_purse_request.h"
-#include "pg_get_ready_deposit.h"
-#include "pg_get_refresh.h"
-#include "pg_get_reserve_balance.h"
-#include "pg_get_reserve_by_h_planchets.h"
-#include "pg_get_reserve_history.h"
-#include "pg_get_signature_for_known_coin.h"
-#include "pg_get_unfinished_close_requests.h"
-#include "pg_get_wire_accounts.h"
-#include "pg_get_wire_fee.h"
-#include "pg_get_wire_fees.h"
-#include "pg_get_wire_hash_for_contract.h"
-#include "pg_have_deposit2.h"
+#include "abort_shard.h"
+#include "activate_signing_key.h"
+#include "add_denomination_key.h"
+#include "add_policy_fulfillment_proof.h"
+#include "aggregate.h"
+#include "batch_ensure_coin_known.h"
+#include "begin_revolving_shard.h"
+#include "begin_shard.h"
+#include "clear_aml_lock.h"
+#include "commit.h"
+#include "complete_shard.h"
+#include "compute_shard.h"
+#include "count_known_coins.h"
+#include "create_aggregation_transient.h"
+#include "create_tables.h"
+#include "delete_aggregation_transient.h"
+#include "delete_shard_locks.h"
+#include "disable_rules.h"
+#include "do_withdraw.h"
+#include "do_check_deposit_idempotent.h"
+#include "do_deposit.h"
+#include "do_purse_delete.h"
+#include "do_purse_deposit.h"
+#include "do_purse_merge.h"
+#include "do_recoup.h"
+#include "do_recoup_refresh.h"
+#include "do_refresh.h"
+#include "do_refund.h"
+#include "do_reserve_open.h"
+#include "do_reserve_purse.h"
+#include "drain_kyc_alert.h"
+#include "drop_tables.h"
+#include "enable_rules.h"
+#include "ensure_coin_known.h"
+#include "event_listen.h"
+#include "event_listen_cancel.h"
+#include "event_notify.h"
+#include "expire_purse.h"
+#include "find_aggregation_transient.h"
+#include "gc.h"
+#include "get_withdraw.h"
+#include "get_coin_denomination.h"
+#include "get_coin_transactions.h"
+#include "get_denomination_info.h"
+#include "get_denomination_by_serial.h"
+#include "get_denomination_revocation.h"
+#include "get_drain_profit.h"
+#include "get_expired_reserves.h"
+#include "get_extension_manifest.h"
+#include "get_global_fee.h"
+#include "get_global_fees.h"
+#include "get_known_coin.h"
+#include "get_kyc_rules.h"
+#include "get_old_coin_by_h_blind.h"
+#include "get_pending_kyc_requirement_process.h"
+#include "get_policy_details.h"
+#include "get_purse_deposit.h"
+#include "get_purse_request.h"
+#include "get_ready_deposit.h"
+#include "get_refresh.h"
+#include "get_reserve_balance.h"
+#include "get_reserve_by_h_planchets.h"
+#include "get_reserve_history.h"
+#include "get_signature_for_known_coin.h"
+#include "get_unfinished_close_requests.h"
+#include "get_wire_accounts.h"
+#include "get_wire_fee.h"
+#include "get_wire_fees.h"
+#include "get_wire_hash_for_contract.h"
+#include "have_deposit2.h"
#include "pg_helper.h"
-#include "pg_inject_auditor_triggers.h"
-#include "pg_insert_active_legitimization_measure.h"
-#include "pg_insert_aml_decision.h"
-#include "pg_insert_aml_officer.h"
-#include "pg_insert_aml_program_failure.h"
-#include "pg_insert_auditor.h"
-#include "pg_insert_auditor_denom_sig.h"
-#include "pg_insert_close_request.h"
-#include "pg_insert_contract.h"
-#include "pg_insert_denomination_info.h"
-#include "pg_insert_denomination_revocation.h"
-#include "pg_insert_drain_profit.h"
-#include "pg_insert_global_fee.h"
-#include "pg_insert_kyc_failure.h"
-#include "pg_insert_kyc_requirement_process.h"
-#include "pg_insert_partner.h"
-#include "pg_insert_purse_request.h"
-#include "pg_insert_records_by_table.h"
-#include "pg_insert_refund.h"
-#include "pg_insert_reserve_closed.h"
-#include "pg_insert_reserve_open_deposit.h"
-#include "pg_insert_sanction_list_hit.h"
-#include "pg_insert_signkey_revocation.h"
-#include "pg_insert_successor_measure.h"
-#include "pg_insert_wire.h"
-#include "pg_insert_wire_fee.h"
-#include "pg_iterate_active_auditors.h"
-#include "pg_iterate_active_signkeys.h"
-#include "pg_iterate_auditor_denominations.h"
-#include "pg_iterate_denomination_info.h"
-#include "pg_iterate_denominations.h"
-#include "pg_iterate_kyc_reference.h"
-#include "pg_iterate_reserve_close_info.h"
-#include "pg_kyc_provider_account_lookup.h"
-#include "pg_kycauth_in_insert.h"
-#include "pg_lookup_active_legitimization.h"
-#include "pg_lookup_aml_file_number.h"
-#include "pg_lookup_aml_history.h"
-#include "pg_lookup_aml_officer.h"
-#include "pg_lookup_auditor_status.h"
-#include "pg_lookup_auditor_timestamp.h"
-#include "pg_lookup_completed_legitimization.h"
-#include "pg_lookup_denomination_key.h"
-#include "pg_lookup_global_fee_by_time.h"
-#include "pg_lookup_h_payto_by_access_token.h"
-#include "pg_lookup_kyc_history.h"
-#include "pg_lookup_kyc_process_by_account.h"
-#include "pg_lookup_kyc_requirement_by_row.h"
-#include "pg_lookup_kyc_status_by_token.h"
-#include "pg_lookup_pending_legitimization.h"
-#include "pg_lookup_records_by_table.h"
-#include "pg_lookup_rules_by_access_token.h"
-#include "pg_lookup_serial_by_table.h"
-#include "pg_lookup_signing_key.h"
-#include "pg_lookup_signkey_revocation.h"
-#include "pg_lookup_transfer_by_deposit.h"
-#include "pg_lookup_wire_fee_by_time.h"
-#include "pg_lookup_wire_timestamp.h"
-#include "pg_lookup_wire_transfer.h"
-#include "pg_mark_refresh_reveal_success.h"
-#include "pg_persist_kyc_attributes.h"
-#include "pg_persist_policy_details.h"
-#include "pg_preflight.h"
-#include "pg_profit_drains_get_pending.h"
-#include "pg_profit_drains_set_finished.h"
-#include "pg_release_revolving_shard.h"
-#include "pg_reserves_get.h"
-#include "pg_reserves_get_origin.h"
-#include "pg_reserves_in_insert.h"
-#include "pg_reserves_update.h"
-#include "pg_rollback.h"
-#include "pg_select_account_merges_above_serial_id.h"
-#include "pg_select_aggregation_amounts_for_kyc_check.h"
-#include "pg_select_aggregation_transient.h"
-#include "pg_select_aggregations_above_serial.h"
-#include "pg_select_all_kyc_attributes.h"
-#include "pg_select_all_purse_decisions_above_serial_id.h"
-#include "pg_select_all_purse_deletions_above_serial_id.h"
-#include "pg_select_aml_attributes.h"
-#include "pg_select_aml_decisions.h"
-#include "pg_select_aml_measures.h"
-#include "pg_select_aml_statistics.h"
-#include "pg_select_auditor_denom_sig.h"
-#include "pg_select_batch_deposits_missing_wire.h"
-#include "pg_select_coin_deposits_above_serial_id.h"
-#include "pg_select_contract.h"
-#include "pg_select_contract_by_purse.h"
-#include "pg_select_deposit_amounts_for_kyc_check.h"
-#include "pg_select_exchange_credit_transfers.h"
-#include "pg_select_exchange_debit_transfers.h"
-#include "pg_select_exchange_kycauth_transfers.h"
-#include "pg_select_kyc_accounts.h"
-#include "pg_select_kyc_attributes.h"
-#include "pg_select_merge_amounts_for_kyc_check.h"
-#include "pg_select_purse.h"
-#include "pg_select_purse_by_merge_pub.h"
-#include "pg_select_purse_decisions_above_serial_id.h"
-#include "pg_select_purse_deposits_above_serial_id.h"
-#include "pg_select_purse_deposits_by_purse.h"
-#include "pg_select_purse_merge.h"
-#include "pg_select_purse_merges_above_serial_id.h"
-#include "pg_select_purse_requests_above_serial_id.h"
-#include "pg_select_recoup_above_serial_id.h"
-#include "pg_select_recoup_refresh_above_serial_id.h"
-#include "pg_select_refreshes_above_serial_id.h"
-#include "pg_select_refunds_above_serial_id.h"
-#include "pg_select_refunds_by_coin.h"
-#include "pg_select_reserve_close_info.h"
-#include "pg_select_reserve_closed_above_serial_id.h"
-#include "pg_select_reserve_open_above_serial_id.h"
-#include "pg_select_reserves_in_above_serial_id.h"
-#include "pg_select_reserves_in_above_serial_id_by_account.h"
-#include "pg_select_wire_out_above_serial_id.h"
-#include "pg_select_wire_out_above_serial_id_by_account.h"
-#include "pg_select_withdraw_amounts_for_kyc_check.h"
-#include "pg_select_withdrawals_above_serial_id.h"
-#include "pg_set_aml_lock.h"
-#include "pg_set_extension_manifest.h"
-#include "pg_set_purse_balance.h"
-#include "pg_start.h"
-#include "pg_start_deferred_wire_out.h"
-#include "pg_start_read_committed.h"
-#include "pg_start_read_only.h"
-#include "pg_store_wire_transfer_out.h"
-#include "pg_test_aml_officer.h"
-#include "pg_trigger_kyc_rule_for_account.h"
-#include "pg_update_aggregation_transient.h"
-#include "pg_update_auditor.h"
-#include "pg_update_kyc_process_by_row.h"
-#include "pg_update_wire.h"
-#include "pg_wad_in_insert.h"
-#include "pg_wire_prepare_data_get.h"
-#include "pg_wire_prepare_data_insert.h"
-#include "pg_wire_prepare_data_mark_failed.h"
-#include "pg_wire_prepare_data_mark_finished.h"
+#include "inject_auditor_triggers.h"
+#include "insert_active_legitimization_measure.h"
+#include "insert_aml_decision.h"
+#include "insert_aml_officer.h"
+#include "insert_aml_program_failure.h"
+#include "insert_auditor.h"
+#include "insert_auditor_denom_sig.h"
+#include "insert_close_request.h"
+#include "insert_contract.h"
+#include "insert_denomination_info.h"
+#include "insert_denomination_revocation.h"
+#include "insert_drain_profit.h"
+#include "insert_global_fee.h"
+#include "insert_kyc_failure.h"
+#include "insert_kyc_requirement_process.h"
+#include "insert_partner.h"
+#include "insert_purse_request.h"
+#include "insert_records_by_table.h"
+#include "insert_refund.h"
+#include "insert_reserve_closed.h"
+#include "insert_reserve_open_deposit.h"
+#include "insert_sanction_list_hit.h"
+#include "insert_signkey_revocation.h"
+#include "insert_successor_measure.h"
+#include "insert_wire.h"
+#include "insert_wire_fee.h"
+#include "iterate_active_auditors.h"
+#include "iterate_active_signkeys.h"
+#include "iterate_auditor_denominations.h"
+#include "iterate_denomination_info.h"
+#include "iterate_denominations.h"
+#include "iterate_kyc_reference.h"
+#include "iterate_reserve_close_info.h"
+#include "kyc_provider_account_lookup.h"
+#include "kycauth_in_insert.h"
+#include "lookup_active_legitimization.h"
+#include "lookup_aml_file_number.h"
+#include "lookup_aml_history.h"
+#include "lookup_aml_officer.h"
+#include "lookup_auditor_status.h"
+#include "lookup_auditor_timestamp.h"
+#include "lookup_completed_legitimization.h"
+#include "lookup_denomination_key.h"
+#include "lookup_global_fee_by_time.h"
+#include "lookup_h_payto_by_access_token.h"
+#include "lookup_kyc_history.h"
+#include "lookup_kyc_process_by_account.h"
+#include "lookup_kyc_requirement_by_row.h"
+#include "lookup_kyc_status_by_token.h"
+#include "lookup_pending_legitimization.h"
+#include "lookup_records_by_table.h"
+#include "lookup_rules_by_access_token.h"
+#include "lookup_serial_by_table.h"
+#include "lookup_signing_key.h"
+#include "lookup_signkey_revocation.h"
+#include "lookup_transfer_by_deposit.h"
+#include "lookup_wire_fee_by_time.h"
+#include "lookup_wire_timestamp.h"
+#include "lookup_wire_transfer.h"
+#include "mark_refresh_reveal_success.h"
+#include "persist_kyc_attributes.h"
+#include "persist_policy_details.h"
+#include "preflight.h"
+#include "profit_drains_get_pending.h"
+#include "profit_drains_set_finished.h"
+#include "release_revolving_shard.h"
+#include "reserves_get.h"
+#include "reserves_get_origin.h"
+#include "reserves_in_insert.h"
+#include "reserves_update.h"
+#include "rollback.h"
+#include "select_account_merges_above_serial_id.h"
+#include "select_aggregation_amounts_for_kyc_check.h"
+#include "select_aggregation_transient.h"
+#include "select_aggregations_above_serial.h"
+#include "select_all_kyc_attributes.h"
+#include "select_all_purse_decisions_above_serial_id.h"
+#include "select_all_purse_deletions_above_serial_id.h"
+#include "select_aml_attributes.h"
+#include "select_aml_decisions.h"
+#include "select_aml_measures.h"
+#include "select_aml_statistics.h"
+#include "select_auditor_denom_sig.h"
+#include "select_batch_deposits_missing_wire.h"
+#include "select_coin_deposits_above_serial_id.h"
+#include "select_contract.h"
+#include "select_contract_by_purse.h"
+#include "select_deposit_amounts_for_kyc_check.h"
+#include "select_exchange_credit_transfers.h"
+#include "select_exchange_debit_transfers.h"
+#include "select_exchange_kycauth_transfers.h"
+#include "select_kyc_accounts.h"
+#include "select_kyc_attributes.h"
+#include "select_merge_amounts_for_kyc_check.h"
+#include "select_purse.h"
+#include "select_purse_by_merge_pub.h"
+#include "select_purse_decisions_above_serial_id.h"
+#include "select_purse_deposits_above_serial_id.h"
+#include "select_purse_deposits_by_purse.h"
+#include "select_purse_merge.h"
+#include "select_purse_merges_above_serial_id.h"
+#include "select_purse_requests_above_serial_id.h"
+#include "select_recoup_above_serial_id.h"
+#include "select_recoup_refresh_above_serial_id.h"
+#include "select_refreshes_above_serial_id.h"
+#include "select_refunds_above_serial_id.h"
+#include "select_refunds_by_coin.h"
+#include "select_reserve_close_info.h"
+#include "select_reserve_closed_above_serial_id.h"
+#include "select_reserve_open_above_serial_id.h"
+#include "select_reserves_in_above_serial_id.h"
+#include "select_reserves_in_above_serial_id_by_account.h"
+#include "select_wire_out_above_serial_id.h"
+#include "select_wire_out_above_serial_id_by_account.h"
+#include "select_withdraw_amounts_for_kyc_check.h"
+#include "select_withdrawals_above_serial_id.h"
+#include "set_aml_lock.h"
+#include "set_extension_manifest.h"
+#include "set_purse_balance.h"
+#include "start.h"
+#include "start_deferred_wire_out.h"
+#include "start_read_committed.h"
+#include "start_read_only.h"
+#include "store_wire_transfer_out.h"
+#include "test_aml_officer.h"
+#include "trigger_kyc_rule_for_account.h"
+#include "update_aggregation_transient.h"
+#include "update_auditor.h"
+#include "update_kyc_process_by_row.h"
+#include "update_wire.h"
+#include "wad_in_insert.h"
+#include "wire_prepare_data_get.h"
+#include "wire_prepare_data_insert.h"
+#include "wire_prepare_data_mark_failed.h"
+#include "wire_prepare_data_mark_finished.h"
#include "plugin_exchangedb_common.h"
#include "plugin_exchangedb_postgres.h"
#include "taler/taler_dbevents.h"
@@ -275,20 +275,14 @@
* @return NULL on error, otherwise a `struct
* TALER_EXCHANGEDB_Plugin`
*/
-void *
-libtaler_plugin_exchangedb_postgres_init (void *cls);
-
-/* Declaration used to squash compiler warning */
-void *
-libtaler_plugin_exchangedb_postgres_init (void *cls)
+struct EXCHANGEDB_PostgresContext *
+EXCHANGEDB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ bool skip_preflight)
{
- const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
- struct PostgresClosure *pg;
- struct TALER_EXCHANGEDB_Plugin *plugin;
+ struct EXCHANGEDB_PostgresContext *pg;
unsigned long long dpl;
- pg = GNUNET_new (struct PostgresClosure);
- plugin = GNUNET_new (struct TALER_EXCHANGEDB_Plugin);
+ pg = GNUNET_new (struct EXCHANGEDB_PostgresContext);
pg->cfg = cfg;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
@@ -327,7 +321,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
GNUNET_CONFIGURATION_get_value_time (cfg,
"exchangedb",
"MAX_AML_PROGRAM_RUNTIME",
- &plugin->max_aml_program_runtime))
+ &pg->max_aml_program_runtime))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"exchangedb",
@@ -378,427 +372,22 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
{
goto fail;
}
- plugin->cls = pg;
- plugin->do_reserve_open
- = &TEH_PG_do_reserve_open;
- plugin->drop_tables
- = &TEH_PG_drop_tables;
- plugin->free_coin_transaction_list
- = &TEH_COMMON_free_coin_transaction_list;
- plugin->free_reserve_history
- = &TEH_COMMON_free_reserve_history;
- plugin->get_coin_transactions
- = &TEH_PG_get_coin_transactions;
- plugin->get_expired_reserves
- = &TEH_PG_get_expired_reserves;
- plugin->get_purse_request
- = &TEH_PG_get_purse_request;
- plugin->get_reserve_history
- = &TEH_PG_get_reserve_history;
- plugin->get_unfinished_close_requests
- = &TEH_PG_get_unfinished_close_requests;
- plugin->insert_records_by_table
- = &TEH_PG_insert_records_by_table;
- plugin->insert_reserve_open_deposit
- = &TEH_PG_insert_reserve_open_deposit;
- plugin->insert_close_request
- = &TEH_PG_insert_close_request;
- plugin->delete_aggregation_transient
- = &TEH_PG_delete_aggregation_transient;
- plugin->iterate_reserve_close_info
- = &TEH_PG_iterate_reserve_close_info;
- plugin->iterate_kyc_reference
- = &TEH_PG_iterate_kyc_reference;
- plugin->lookup_records_by_table
- = &TEH_PG_lookup_records_by_table;
- plugin->lookup_serial_by_table
- = &TEH_PG_lookup_serial_by_table;
- plugin->select_account_merges_above_serial_id
- = &TEH_PG_select_account_merges_above_serial_id;
- plugin->select_all_purse_decisions_above_serial_id
- = &TEH_PG_select_all_purse_decisions_above_serial_id;
- plugin->select_all_purse_deletions_above_serial_id
- = &TEH_PG_select_all_purse_deletions_above_serial_id;
- plugin->select_purse
- = &TEH_PG_select_purse;
- plugin->select_purse_deposits_above_serial_id
- = &TEH_PG_select_purse_deposits_above_serial_id;
- plugin->select_purse_merges_above_serial_id
- = &TEH_PG_select_purse_merges_above_serial_id;
- plugin->select_purse_requests_above_serial_id
- = &TEH_PG_select_purse_requests_above_serial_id;
- plugin->select_reserve_close_info
- = &TEH_PG_select_reserve_close_info;
- plugin->select_reserve_closed_above_serial_id
- = &TEH_PG_select_reserve_closed_above_serial_id;
- plugin->select_reserve_open_above_serial_id
- = &TEH_PG_select_reserve_open_above_serial_id;
- plugin->insert_purse_request
- = &TEH_PG_insert_purse_request;
- plugin->iterate_active_signkeys
- = &TEH_PG_iterate_active_signkeys;
- plugin->commit
- = &TEH_PG_commit;
- plugin->preflight
- = &TEH_PG_preflight;
- plugin->select_aggregation_amounts_for_kyc_check
- = &TEH_PG_select_aggregation_amounts_for_kyc_check;
- plugin->get_kyc_rules
- = &TEH_PG_get_kyc_rules;
- plugin->get_kyc_rules2
- = &TEH_PG_get_kyc_rules2;
- plugin->kyc_provider_account_lookup
- = &TEH_PG_kyc_provider_account_lookup;
- plugin->lookup_kyc_process_by_account
- = &TEH_PG_lookup_kyc_process_by_account;
- plugin->update_kyc_process_by_row
- = &TEH_PG_update_kyc_process_by_row;
- plugin->insert_kyc_requirement_process
- = &TEH_PG_insert_kyc_requirement_process;
- plugin->select_withdraw_amounts_for_kyc_check
- = &TEH_PG_select_withdraw_amounts_for_kyc_check;
- plugin->select_merge_amounts_for_kyc_check
- = &TEH_PG_select_merge_amounts_for_kyc_check;
- plugin->profit_drains_set_finished
- = &TEH_PG_profit_drains_set_finished;
- plugin->profit_drains_get_pending
- = &TEH_PG_profit_drains_get_pending;
- plugin->get_drain_profit
- = &TEH_PG_get_drain_profit;
- plugin->get_purse_deposit
- = &TEH_PG_get_purse_deposit;
- plugin->insert_contract
- = &TEH_PG_insert_contract;
- plugin->select_contract
- = &TEH_PG_select_contract;
- plugin->select_purse_merge
- = &TEH_PG_select_purse_merge;
- plugin->select_contract_by_purse
- = &TEH_PG_select_contract_by_purse;
- plugin->insert_drain_profit
- = &TEH_PG_insert_drain_profit;
- plugin->do_reserve_purse
- = &TEH_PG_do_reserve_purse;
- plugin->lookup_global_fee_by_time
- = &TEH_PG_lookup_global_fee_by_time;
- plugin->do_purse_deposit
- = &TEH_PG_do_purse_deposit;
- plugin->activate_signing_key
- = &TEH_PG_activate_signing_key;
- plugin->update_auditor
- = &TEH_PG_update_auditor;
- plugin->begin_revolving_shard
- = &TEH_PG_begin_revolving_shard;
- plugin->get_extension_manifest
- = &TEH_PG_get_extension_manifest;
- plugin->do_purse_merge
- = &TEH_PG_do_purse_merge;
- plugin->do_purse_delete
- = &TEH_PG_do_purse_delete;
- plugin->start_read_committed
- = &TEH_PG_start_read_committed;
- plugin->start_read_only
- = &TEH_PG_start_read_only;
- plugin->insert_denomination_info
- = &TEH_PG_insert_denomination_info;
- plugin->lookup_wire_fee_by_time
- = &TEH_PG_lookup_wire_fee_by_time;
- plugin->start
- = &TEH_PG_start;
- plugin->rollback
- = &TEH_PG_rollback;
- plugin->create_tables
- = &TEH_PG_create_tables;
- plugin->event_listen
- = &TEH_PG_event_listen;
- plugin->event_listen_cancel
- = &TEH_PG_event_listen_cancel;
- plugin->event_notify
- = &TEH_PG_event_notify;
- plugin->get_denomination_info
- = &TEH_PG_get_denomination_info;
- plugin->get_denomination_by_serial
- = &TEH_PG_get_denomination_by_serial;
- plugin->iterate_denomination_info
- = &TEH_PG_iterate_denomination_info;
- plugin->iterate_denominations
- = &TEH_PG_iterate_denominations;
- plugin->iterate_active_auditors
- = &TEH_PG_iterate_active_auditors;
- plugin->iterate_auditor_denominations
- = &TEH_PG_iterate_auditor_denominations;
- plugin->lookup_rules_by_access_token
- = &TEH_PG_lookup_rules_by_access_token;
- plugin->reserves_get
- = &TEH_PG_reserves_get;
- plugin->reserves_get_origin
- = &TEH_PG_reserves_get_origin;
- plugin->drain_kyc_alert
- = &TEH_PG_drain_kyc_alert;
- plugin->reserves_in_insert
- = &TEH_PG_reserves_in_insert;
- plugin->do_withdraw
- = &TEH_PG_do_withdraw;
- plugin->get_withdraw
- = &TEH_PG_get_withdraw;
- plugin->wad_in_insert
- = &TEH_PG_wad_in_insert;
- plugin->kycauth_in_insert
- = &TEH_PG_kycauth_in_insert;
- plugin->get_policy_details
- = &TEH_PG_get_policy_details;
- plugin->persist_policy_details
- = &TEH_PG_persist_policy_details;
- plugin->do_deposit
- = &TEH_PG_do_deposit;
- plugin->get_wire_hash_for_contract
- = &TEH_PG_get_wire_hash_for_contract;
- plugin->add_policy_fulfillment_proof
- = &TEH_PG_add_policy_fulfillment_proof;
- plugin->do_refresh
- = &TEH_PG_do_refresh;
- plugin->mark_refresh_reveal_success
- = &TEH_PG_mark_refresh_reveal_success;
- plugin->do_refund
- = &TEH_PG_do_refund;
- plugin->do_recoup
- = &TEH_PG_do_recoup;
- plugin->do_recoup_refresh
- = &TEH_PG_do_recoup_refresh;
- plugin->get_reserve_balance
- = &TEH_PG_get_reserve_balance;
- plugin->count_known_coins
- = &TEH_PG_count_known_coins;
- plugin->ensure_coin_known
- = &TEH_PG_ensure_coin_known;
- plugin->get_known_coin
- = &TEH_PG_get_known_coin;
- plugin->get_signature_for_known_coin
- = &TEH_PG_get_signature_for_known_coin;
- plugin->get_coin_denomination
- = &TEH_PG_get_coin_denomination;
- plugin->have_deposit2
- = &TEH_PG_have_deposit2;
- plugin->aggregate
- = &TEH_PG_aggregate;
- plugin->create_aggregation_transient
- = &TEH_PG_create_aggregation_transient;
- plugin->select_aggregation_transient
- = &TEH_PG_select_aggregation_transient;
- plugin->find_aggregation_transient
- = &TEH_PG_find_aggregation_transient;
- plugin->update_aggregation_transient
- = &TEH_PG_update_aggregation_transient;
- plugin->get_ready_deposit
- = &TEH_PG_get_ready_deposit;
- plugin->insert_refund
- = &TEH_PG_insert_refund;
- plugin->select_refunds_by_coin
- = &TEH_PG_select_refunds_by_coin;
- plugin->select_aml_measures
- = &TEH_PG_select_aml_measures;
- plugin->get_refresh
- = &TEH_PG_get_refresh;
- plugin->lookup_wire_transfer
- = &TEH_PG_lookup_wire_transfer;
- plugin->lookup_transfer_by_deposit
- = &TEH_PG_lookup_transfer_by_deposit;
- plugin->insert_wire_fee
- = &TEH_PG_insert_wire_fee;
- plugin->insert_global_fee
- = &TEH_PG_insert_global_fee;
- plugin->get_wire_fee
- = &TEH_PG_get_wire_fee;
- plugin->get_global_fee
- = &TEH_PG_get_global_fee;
- plugin->get_global_fees
- = &TEH_PG_get_global_fees;
- plugin->insert_reserve_closed
- = &TEH_PG_insert_reserve_closed;
- plugin->wire_prepare_data_insert
- = &TEH_PG_wire_prepare_data_insert;
- plugin->wire_prepare_data_mark_finished
- = &TEH_PG_wire_prepare_data_mark_finished;
- plugin->wire_prepare_data_mark_failed
- = &TEH_PG_wire_prepare_data_mark_failed;
- plugin->wire_prepare_data_get
- = &TEH_PG_wire_prepare_data_get;
- plugin->start_deferred_wire_out
- = &TEH_PG_start_deferred_wire_out;
- plugin->store_wire_transfer_out
- = &TEH_PG_store_wire_transfer_out;
- plugin->gc
- = &TEH_PG_gc;
- plugin->select_coin_deposits_above_serial_id
- = &TEH_PG_select_coin_deposits_above_serial_id;
- plugin->lookup_aml_file_number
- = &TEH_PG_lookup_aml_file_number;
- plugin->lookup_aml_history
- = &TEH_PG_lookup_aml_history;
- plugin->lookup_kyc_history
- = &TEH_PG_lookup_kyc_history;
- plugin->select_purse_decisions_above_serial_id
- = &TEH_PG_select_purse_decisions_above_serial_id;
- plugin->select_purse_deposits_by_purse
- = &TEH_PG_select_purse_deposits_by_purse;
- plugin->select_refreshes_above_serial_id
- = &TEH_PG_select_refreshes_above_serial_id;
- plugin->select_refunds_above_serial_id
- = &TEH_PG_select_refunds_above_serial_id;
- plugin->select_reserves_in_above_serial_id
- = &TEH_PG_select_reserves_in_above_serial_id;
- plugin->select_reserves_in_above_serial_id_by_account
- = &TEH_PG_select_reserves_in_above_serial_id_by_account;
- plugin->select_withdrawals_above_serial_id
- = &TEH_PG_select_withdrawals_above_serial_id;
- plugin->select_wire_out_above_serial_id
- = &TEH_PG_select_wire_out_above_serial_id;
- plugin->select_wire_out_above_serial_id_by_account
- = &TEH_PG_select_wire_out_above_serial_id_by_account;
- plugin->select_recoup_above_serial_id
- = &TEH_PG_select_recoup_above_serial_id;
- plugin->select_recoup_refresh_above_serial_id
- = &TEH_PG_select_recoup_refresh_above_serial_id;
- plugin->get_reserve_by_h_planchets
- = &TEH_PG_get_reserve_by_h_planchets;
- plugin->get_old_coin_by_h_blind
- = &TEH_PG_get_old_coin_by_h_blind;
- plugin->insert_denomination_revocation
- = &TEH_PG_insert_denomination_revocation;
- plugin->get_denomination_revocation
- = &TEH_PG_get_denomination_revocation;
- plugin->select_batch_deposits_missing_wire
- = &TEH_PG_select_batch_deposits_missing_wire;
- plugin->select_aggregations_above_serial
- = &TEH_PG_select_aggregations_above_serial;
- plugin->lookup_auditor_timestamp
- = &TEH_PG_lookup_auditor_timestamp;
- plugin->lookup_auditor_status
- = &TEH_PG_lookup_auditor_status;
- plugin->insert_auditor
- = &TEH_PG_insert_auditor;
- plugin->lookup_wire_timestamp
- = &TEH_PG_lookup_wire_timestamp;
- plugin->insert_wire
- = &TEH_PG_insert_wire;
- plugin->update_wire
- = &TEH_PG_update_wire;
- plugin->get_wire_accounts
- = &TEH_PG_get_wire_accounts;
- plugin->get_wire_fees
- = &TEH_PG_get_wire_fees;
- plugin->select_aml_decisions
- = &TEH_PG_select_aml_decisions;
- plugin->select_deposit_amounts_for_kyc_check
- = &TEH_PG_select_deposit_amounts_for_kyc_check;
- plugin->do_check_deposit_idempotent
- = &TEH_PG_do_check_deposit_idempotent;
- plugin->insert_signkey_revocation
- = &TEH_PG_insert_signkey_revocation;
- plugin->select_aml_attributes
- = &TEH_PG_select_aml_attributes;
- plugin->select_aml_statistics
- = &TEH_PG_select_aml_statistics;
- plugin->lookup_signkey_revocation
- = &TEH_PG_lookup_signkey_revocation;
- plugin->lookup_denomination_key
- = &TEH_PG_lookup_denomination_key;
- plugin->lookup_completed_legitimization
- = &TEH_PG_lookup_completed_legitimization;
- plugin->lookup_pending_legitimization
- = &TEH_PG_lookup_pending_legitimization;
- plugin->lookup_active_legitimization
- = &TEH_PG_lookup_active_legitimization;
- plugin->insert_auditor_denom_sig
- = &TEH_PG_insert_auditor_denom_sig;
- plugin->select_auditor_denom_sig
- = &TEH_PG_select_auditor_denom_sig;
- plugin->select_kyc_accounts
- = &TEH_PG_select_kyc_accounts;
- plugin->add_denomination_key
- = &TEH_PG_add_denomination_key;
- plugin->lookup_signing_key
- = &TEH_PG_lookup_signing_key;
- plugin->lookup_h_payto_by_access_token
- = &TEH_PG_lookup_h_payto_by_access_token;
- plugin->insert_sanction_list_hit
- = &TEH_PG_insert_sanction_list_hit;
- plugin->select_exchange_debit_transfers
- = &TEH_PG_select_exchange_debit_transfers;
- plugin->select_exchange_credit_transfers
- = &TEH_PG_select_exchange_credit_transfers;
- plugin->select_exchange_kycauth_transfers
- = &TEH_PG_select_exchange_kycauth_transfers;
- plugin->select_all_kyc_attributes
- = &TEH_PG_select_all_kyc_attributes;
- plugin->begin_shard
- = &TEH_PG_begin_shard;
- plugin->abort_shard
- = &TEH_PG_abort_shard;
- plugin->insert_kyc_failure
- = &TEH_PG_insert_kyc_failure;
- plugin->complete_shard
- = &TEH_PG_complete_shard;
- plugin->release_revolving_shard
- = &TEH_PG_release_revolving_shard;
- plugin->delete_shard_locks
- = &TEH_PG_delete_shard_locks;
- plugin->set_extension_manifest
- = &TEH_PG_set_extension_manifest;
- plugin->insert_partner
- = &TEH_PG_insert_partner;
- plugin->expire_purse
- = &TEH_PG_expire_purse;
- plugin->select_purse_by_merge_pub
- = &TEH_PG_select_purse_by_merge_pub;
- plugin->set_purse_balance
- = &TEH_PG_set_purse_balance;
- plugin->get_pending_kyc_requirement_process
- = &TEH_PG_get_pending_kyc_requirement_process;
- plugin->select_kyc_attributes
- = &TEH_PG_select_kyc_attributes;
- plugin->insert_aml_officer
- = &TEH_PG_insert_aml_officer;
- plugin->enable_rules
- = &TEH_PG_enable_rules;
- plugin->disable_rules
- = &TEH_PG_disable_rules;
- plugin->test_aml_officer
- = &TEH_PG_test_aml_officer;
- plugin->lookup_aml_officer
- = &TEH_PG_lookup_aml_officer;
- plugin->insert_active_legitimization_measure
- = &TEH_PG_insert_active_legitimization_measure;
- plugin->insert_aml_decision
- = &TEH_PG_insert_aml_decision;
- plugin->lookup_kyc_requirement_by_row
- = &TEH_PG_lookup_kyc_requirement_by_row;
- plugin->trigger_kyc_rule_for_account
- = &TEH_PG_trigger_kyc_rule_for_account;
- plugin->lookup_kyc_status_by_token
- = &TEH_PG_lookup_kyc_status_by_token;
- plugin->batch_ensure_coin_known
- = &TEH_PG_batch_ensure_coin_known;
- plugin->inject_auditor_triggers
- = &TEH_PG_inject_auditor_triggers;
- plugin->insert_successor_measure
- = &TEH_PG_insert_successor_measure;
- plugin->insert_aml_program_failure
- = &TEH_PG_insert_aml_program_failure;
- plugin->persist_kyc_attributes
- = &TEH_PG_persist_kyc_attributes;
- plugin->clear_aml_lock
- = &TEH_PG_clear_aml_lock;
- plugin->set_aml_lock
- = &TEH_PG_set_aml_lock;
-
- return plugin;
+ if (! skip_preflight)
+ {
+ if (GNUNET_OK !=
+ EXCHANGEDB_internal_setup (pg,
+ false))
+ {
+ goto fail;
+ }
+ }
+ return pg;
fail:
GNUNET_free (pg->exchange_url);
GNUNET_free (pg->sql_dir);
+ GNUNET_free (pg->currency);
GNUNET_free (pg);
- GNUNET_free (plugin);
return NULL;
}
@@ -809,16 +398,11 @@ fail:
* @param cls a `struct TALER_EXCHANGEDB_Plugin`
* @return NULL (always)
*/
-void *
-libtaler_plugin_exchangedb_postgres_done (void *cls);
-
-/* Declaration used to squash compiler warning */
-void *
-libtaler_plugin_exchangedb_postgres_done (void *cls)
+void
+EXCHANGEDB_disconnect (struct EXCHANGEDB_PostgresContext *pg)
{
- struct TALER_EXCHANGEDB_Plugin *plugin = cls;
- struct PostgresClosure *pg = plugin->cls;
-
+ if (NULL == pg)
+ return;
if (NULL != pg->conn)
{
GNUNET_PQ_disconnect (pg->conn);
@@ -828,8 +412,6 @@ libtaler_plugin_exchangedb_postgres_done (void *cls)
GNUNET_free (pg->sql_dir);
GNUNET_free (pg->currency);
GNUNET_free (pg);
- GNUNET_free (plugin);
- return NULL;
}
diff --git a/src/exchangedb/preflight.c b/src/exchangedb/preflight.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 src/exchangedb/preflight.c
+ * @brief Implementation of the preflight function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "preflight.h"
+#include "pg_helper.h"
+#include "plugin_exchangedb_postgres.h"
+
+
+/**
+ * Connect to the database if the connection does not exist yet
+ * and check that we are ready to operate.
+ *
+ * @param ctx the plugin-specific state
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+internal_setup (struct EXCHANGEDB_PostgresContext *ctx)
+{
+ if (NULL == ctx->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 (ctx->cfg,
+ "exchangedb-postgres",
+ "exchange-", /* load_path_suffix */
+ es,
+ NULL /* prepared statements */,
+ GNUNET_PQ_FLAG_CHECK_CURRENT);
+ if (NULL == db_conn)
+ return GNUNET_SYSERR;
+
+ ctx->prep_gen++;
+ ctx->conn = db_conn;
+ }
+ if (NULL == ctx->transaction_name)
+ GNUNET_PQ_reconnect_if_down (ctx->conn);
+ return GNUNET_OK;
+}
+
+
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_preflight (struct EXCHANGEDB_PostgresContext *ctx)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("ROLLBACK"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ if (GNUNET_OK !=
+ internal_setup (ctx))
+ return GNUNET_SYSERR;
+ if (NULL == ctx->transaction_name)
+ return GNUNET_OK; /* all good */
+ if (GNUNET_OK ==
+ GNUNET_PQ_exec_statements (ctx->conn,
+ es))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "BUG: Preflight check rolled back transaction `%s'!\n",
+ ctx->transaction_name);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "BUG: Preflight check failed to rollback transaction `%s'!\n",
+ ctx->transaction_name);
+ }
+ ctx->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,77 @@
+/*
+ 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 src/exchangedb/profit_drains_get_pending.c
+ * @brief Implementation of the profit_drains_get_pending function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "profit_drains_get_pending.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_profit_drains_get_pending (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,47 @@
+/*
+ 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 src/exchangedb/profit_drains_set_finished.c
+ * @brief Implementation of the profit_drains_set_finished function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "profit_drains_set_finished.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_profit_drains_set_finished (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&serial),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "drain_profit_set_finished",
+ "UPDATE profit_drains"
+ " SET"
+ " executed=TRUE"
+ " WHERE profit_drain_serial_id=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->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,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 src/exchangedb/release_revolving_shard.c
+ * @brief Implementation of the release_revolving_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "release_revolving_shard.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_release_revolving_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "release_revolving_shard",
+ params);
+}
diff --git a/src/exchangedb/reserves_get.c b/src/exchangedb/reserves_get.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 src/exchangedb/reserves_get.c
+ * @brief Implementation of the reserves_get function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "reserves_get.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_reserves_get (struct EXCHANGEDB_PostgresContext *ctx,
+ 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",
+ ctx->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 (ctx,
+ "reserves_get",
+ "SELECT"
+ " current_balance"
+ ",expiration_date"
+ ",gc_date"
+ " FROM reserves"
+ " WHERE reserve_pub=$1"
+ " LIMIT 1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn,
+ "reserves_get",
+ params,
+ rs);
+}
diff --git a/src/exchangedb/reserves_get_origin.c b/src/exchangedb/reserves_get_origin.c
@@ -0,0 +1,63 @@
+/*
+ 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 src/exchangedb/reserves_get_origin.c
+ * @brief Implementation of the reserves_get_origin function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "reserves_get_origin.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_reserves_get_origin (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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,377 @@
+/*
+ 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 src/exchangedb/reserves_in_insert.c
+ * @brief Implementation of the reserves_in_insert function for Postgres
+ * @author Christian Grothoff
+ * @author Joseph Xu
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "reserves_in_insert.h"
+#include "pg_helper.h"
+#include "pg_start.h"
+#include "pg_start_read_committed.h"
+#include "pg_commit.h"
+#include "pg_preflight.h"
+#include "pg_rollback.h"
+#include "pg_event_notify.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_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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_reserves_in_insert (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->idle_reserve_expiration_time);
+ struct GNUNET_TIME_Timestamp gc
+ = GNUNET_TIME_relative_to_timestamp (ctx->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 !=
+ EXCHANGEDB_preflight (ctx))
+ {
+ GNUNET_break (0);
+ qs = GNUNET_DB_STATUS_HARD_ERROR;
+ goto finished;
+ }
+ if (GNUNET_OK !=
+ EXCHANGEDB_start_read_committed (ctx,
+ "READ_COMMITED"))
+ {
+ GNUNET_break (0);
+ qs = GNUNET_DB_STATUS_HARD_ERROR;
+ goto finished;
+ }
+ PREPARE (ctx,
+ "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,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_uint64 (reserves_length,
+ wire_references,
+ ctx->conn),
+ TALER_PQ_query_param_array_amount (
+ reserves_length,
+ balances,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_ptrs_string (
+ reserves_length,
+ (const char **) exchange_account_names,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_timestamp (
+ reserves_length,
+ execution_times,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_auto_from_type (
+ reserves_length,
+ h_full_paytos,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_auto_from_type (
+ reserves_length,
+ h_normalized_paytos,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_ptrs_string (
+ reserves_length,
+ (const char **) sender_account_details,
+ ctx->conn),
+ GNUNET_PQ_query_param_array_ptrs_string (
+ reserves_length,
+ (const char **) notify_s,
+ ctx->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 (ctx->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 = EXCHANGEDB_commit (ctx);
+ 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 (ctx,
+ "reserves_update",
+ "SELECT"
+ " out_duplicate AS duplicate "
+ "FROM exchange_do_batch_reserves_update"
+ " ($1,$2,$3,$4,$5,$6,$7);");
+
+ if (GNUNET_OK !=
+ EXCHANGEDB_start (ctx,
+ "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 (ctx->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 (ctx->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 = EXCHANGEDB_commit (ctx);
+ 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 (ctx->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,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 src/exchangedb/reserves_update.c
+ * @brief Implementation of the reserves_update function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "reserves_update.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_reserves_update (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ &reserve->balance),
+ GNUNET_PQ_query_param_auto_from_type (&reserve->pub),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "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 (ctx->conn,
+ "reserve_update",
+ params);
+}
diff --git a/src/exchangedb/rollback.c b/src/exchangedb/rollback.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 src/exchangedb/rollback.c
+ * @brief Implementation of the rollback function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "rollback.h"
+#include "pg_helper.h"
+
+
+void
+EXCHANGEDB_rollback (struct EXCHANGEDB_PostgresContext *ctx)
+{
+ struct GNUNET_PQ_ExecuteStatement es[] = {
+ GNUNET_PQ_make_execute ("ROLLBACK"),
+ GNUNET_PQ_EXECUTE_STATEMENT_END
+ };
+
+ if (NULL == ctx->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 (ctx->conn,
+ es));
+ ctx->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,190 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_account_merges_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AccountMergeSerialContext *dsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dsc->ctx;
+
+ 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
+EXCHANGEDB_select_account_merges_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,156 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_aggregation_amounts_for_kyc_check.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #get_kyc_amounts_cb().
+ */
+struct KycAmountCheckContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_KycAmountCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycAmountCheckContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+
+ 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
+EXCHANGEDB_select_aggregation_amounts_for_kyc_check (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,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 src/exchangedb/select_aggregation_transient.c
+ * @brief Implementation of the select_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_aggregation_transient.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,139 @@
+/*
+ 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 src/exchangedb/select_aggregations_above_serial.c
+ * @brief Implementation of the select_aggregations_above_serial function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_aggregations_above_serial.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct AggregationSerialContext *dsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dsc->ctx;
+
+ 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
+EXCHANGEDB_select_aggregations_above_serial (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Fetch aggregations with rowid '\geq' the given parameter */
+ PREPARE (ctx,
+ "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 (ctx->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,170 @@
+/*
+ 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 src/exchangedb/select_all_kyc_attributes.c
+ * @brief Implementation of the select_all_kyc_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_all_kyc_attributes.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_select_all_kyc_attributes (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,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 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_all_purse_decisions_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_select_all_purse_decisions_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,144 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_all_purse_deletions_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_select_all_purse_deletions_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,191 @@
+/*
+ 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 src/exchangedb/select_aml_attributes.c
+ * @brief Implementation of the select_aml_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_aml_attributes.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_select_aml_attributes (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ const char *stmt = (limit > 0)
+ ? "select_aml_attributes_inc"
+ : "select_aml_attributes_dec";
+
+ PREPARE (ctx,
+ "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 (ctx,
+ "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 (ctx->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,250 @@
+/*
+ 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 src/exchangedb/select_aml_decisions.c
+ * @brief Implementation of the select_aml_decisions function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_aml_decisions.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_select_aml_decisions (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ const char *stmt = (limit > 0)
+ ? "select_aml_decisions_inc"
+ : "select_aml_decisions_dec";
+
+ PREPARE (ctx,
+ "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 (ctx,
+ "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 (ctx->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,187 @@
+/*
+ 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 src/exchangedb/select_aml_measures.c
+ * @brief Implementation of the select_aml_measures function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_aml_measures.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_select_aml_measures (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ const char *stmt = (limit > 0)
+ ? "select_aml_measures_inc"
+ : "select_aml_measures_dec";
+
+ PREPARE (ctx,
+ "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 (ctx,
+ "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 (ctx->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,144 @@
+/*
+ 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 src/exchangedb/select_aml_statistics.c
+ * @brief Implementation of the select_aml_statistics function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_aml_statistics.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_select_aml_statistics (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_array_ptrs_string (num_names,
+ names,
+ ctx->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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/select_auditor_denom_sig.c
+ * @brief Implementation of the select_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_auditor_denom_sig.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_auditor_denom_sig (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,142 @@
+/*
+ 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 src/exchangedb/select_batch_deposits_missing_wire.c
+ * @brief Implementation of the select_batch_deposits_missing_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_batch_deposits_missing_wire.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct MissingWireContext *mwc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = mwc->ctx;
+
+ 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
+EXCHANGEDB_select_batch_deposits_missing_wire (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,202 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_coin_deposits_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct CoinDepositSerialContext *dsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dsc->ctx;
+
+ 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
+EXCHANGEDB_select_coin_deposits_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Fetch deposits with rowid '\geq' the given parameter */
+ PREPARE (ctx,
+ "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 (ctx->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 src/exchangedb/select_contract.c
+ * @brief Implementation of the select_contract function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_contract.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_contract (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "select_contract",
+ "SELECT "
+ " purse_pub"
+ ",e_contract"
+ ",contract_sig"
+ " FROM contracts"
+ " WHERE pub_ckey=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->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,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 src/exchangedb/select_contract_by_purse.c
+ * @brief Implementation of the select_contract_by_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_contract_by_purse.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_contract_by_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "select_contract_by_purse",
+ "SELECT "
+ " pub_ckey"
+ ",e_contract"
+ ",contract_sig"
+ " FROM contracts"
+ " WHERE purse_pub=$1;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->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,155 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_deposit_amounts_for_kyc_check.h"
+#include "pg_helper.h"
+
+/**
+ * Closure for #get_kyc_amounts_cb().
+ */
+struct KycAmountCheckContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_KycAmountCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycAmountCheckContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+
+ 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
+EXCHANGEDB_select_deposit_amounts_for_kyc_check (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,182 @@
+/*
+ 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 src/exchangedb/select_exchange_credit_transfers.c
+ * @brief Implementation of the select_exchange_credit_transfers function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_exchange_credit_transfers.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SelectTransferContext *stc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = stc->ctx;
+
+ 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
+EXCHANGEDB_select_exchange_credit_transfers (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 = {
+ .ctx = ctx,
+ .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 (ctx->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 (ctx,
+ "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 (ctx,
+ "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 (
+ ctx->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,183 @@
+/*
+ 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 src/exchangedb/select_exchange_debit_transfers.c
+ * @brief Implementation of the select_exchange_debit_transfers function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_exchange_debit_transfers.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SelectTransferContext *stc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = stc->ctx;
+
+ 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
+EXCHANGEDB_select_exchange_debit_transfers (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 = {
+ .ctx = ctx,
+ .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 (ctx->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 (ctx,
+ "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 (ctx,
+ "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 (
+ ctx->conn,
+ (limit > 0)
+ ? "select_exchange_debit_transfers_inc"
+ : "select_exchange_debit_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_kycauth_transfers.c b/src/exchangedb/select_exchange_kycauth_transfers.c
@@ -0,0 +1,182 @@
+/*
+ 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 src/exchangedb/select_exchange_kycauth_transfers.c
+ * @brief Implementation of the select_exchange_kycauth_transfers function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_exchange_kycauth_transfers.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 #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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SelectTransferContext *stc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = stc->ctx;
+
+ 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
+EXCHANGEDB_select_exchange_kycauth_transfers (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 = {
+ .ctx = ctx,
+ .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 (ctx->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 (ctx,
+ "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 (ctx,
+ "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 (
+ ctx->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,237 @@
+/*
+ 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 src/exchangedb/select_kyc_accounts.c
+ * @brief Implementation of the select_kyc_accounts function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_kyc_accounts.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 #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_result (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_select_kyc_accounts (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ const char *stmt = (limit > 0)
+ ? "select_kyc_accounts_inc"
+ : "select_kyc_accounts_dec";
+
+ PREPARE (ctx,
+ "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 (ctx,
+ "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 (ctx->conn,
+ stmt,
+ params,
+ &handle_kyc_account_result,
+ &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,156 @@
+/*
+ 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 src/exchangedb/select_kyc_attributes.c
+ * @brief Implementation of the select_kyc_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_kyc_attributes.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_select_kyc_attributes (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .h_payto = h_payto,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_merge_amounts_for_kyc_check.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #get_kyc_amounts_cb().
+ */
+struct KycAmountCheckContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_KycAmountCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycAmountCheckContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+
+ 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
+EXCHANGEDB_select_merge_amounts_for_kyc_check (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,92 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_purse.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,77 @@
+/*
+ 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 src/exchangedb/select_purse_by_merge_pub.c
+ * @brief Implementation of the select_purse_by_merge_pub function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_purse_by_merge_pub.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse_by_merge_pub (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,160 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_purse_decisions_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseDecisionSerialContext *dsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dsc->ctx;
+
+ 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
+EXCHANGEDB_select_purse_decisions_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,200 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_purse_deposits_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseDepositSerialContext *dsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dsc->ctx;
+
+ 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
+EXCHANGEDB_select_purse_deposits_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,151 @@
+/*
+ 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 src/exchangedb/select_purse_deposits_by_purse.c
+ * @brief Implementation of the select_purse_deposits_by_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_purse_deposits_by_purse.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseRefundCoinContext *dsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dsc->ctx;
+
+ 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
+EXCHANGEDB_select_purse_deposits_by_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,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 src/exchangedb/select_purse_merge.c
+ * @brief Implementation of the select_purse_merge function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_purse_merge.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse_merge (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_purse_merges_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseMergeSerialContext *dsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dsc->ctx;
+
+ 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
+EXCHANGEDB_select_purse_merges_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,176 @@
+/*
+ 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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_purse_requests_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct PurseRequestsSerialContext *dsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = dsc->ctx;
+
+ 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
+EXCHANGEDB_select_purse_requests_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,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 src/exchangedb/select_recoup_above_serial_id.c
+ * @brief Implementation of the select_recoup_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_recoup_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RecoupSerialContext *psc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = psc->ctx;
+
+ 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
+EXCHANGEDB_select_recoup_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (ctx->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,206 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_recoup_refresh_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RecoupRefreshSerialContext *psc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = psc->ctx;
+
+ 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
+EXCHANGEDB_select_recoup_refresh_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,182 @@
+/*
+ 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 src/exchangedb/select_refreshes_above_serial_id.c
+ * @brief Implementation of the select_refreshes_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_refreshes_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RefreshsSerialContext *rsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rsc->ctx;
+
+ 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 (ctx->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
+EXCHANGEDB_select_refreshes_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,221 @@
+/*
+ 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 src/exchangedb/select_refunds_above_serial_id.c
+ * @brief Implementation of the select_refunds_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_refunds_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct RefundsSerialContext *rsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rsc->ctx;
+
+ 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 (
+ ctx->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
+EXCHANGEDB_select_refunds_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Fetch refunds with rowid '\geq' the given parameter */
+ PREPARE (ctx,
+ "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 (ctx,
+ "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 (ctx->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,141 @@
+/*
+ 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 src/exchangedb/select_refunds_by_coin.c
+ * @brief Implementation of the select_refunds_by_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_refunds_by_coin.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct SelectRefundContext *srctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = srctx->ctx;
+
+ 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
+EXCHANGEDB_select_refunds_by_coin (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ const char *query = "get_refunds_by_coin_and_contract";
+
+ PREPARE (ctx,
+ 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 (ctx->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,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 pg_select_reserve_close_info.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_reserve_close_info.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_reserve_close_info (struct EXCHANGEDB_PostgresContext *ctx,
+ 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",
+ ctx->currency,
+ balance),
+ GNUNET_PQ_result_spec_string ("payto_uri",
+ &payto_uri->full_payto),
+ GNUNET_PQ_result_spec_end
+ };
+
+ PREPARE (ctx,
+ "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 (
+ ctx->conn,
+ "select_reserve_close_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,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 pg_select_reserve_closed_above_serial_id.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_reserve_closed_above_serial_id.h"
+#include "plugin_exchangedb_common.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveClosedSerialContext *rcsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rcsc->ctx;
+
+ 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
+EXCHANGEDB_select_reserve_closed_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (
+ ctx,
+ "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 (
+ ctx->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,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 pg_select_reserve_open_above_serial_id.c
+ * @brief Low-level (statement-level) Postgres database access for the exchange
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_reserve_open_above_serial_id.h"
+#include "plugin_exchangedb_common.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReserveOpenSerialContext *rcsc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rcsc->ctx;
+
+ 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
+EXCHANGEDB_select_reserve_open_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (
+ ctx,
+ "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 (ctx->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,165 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_reserves_in_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReservesInSerialContext *risc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = risc->ctx;
+
+ 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
+EXCHANGEDB_select_reserves_in_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,167 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_reserves_in_above_serial_id_by_account.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct ReservesInSerialContext *risc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = risc->ctx;
+
+ 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
+EXCHANGEDB_select_reserves_in_above_serial_id_by_account (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,156 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_wire_out_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireOutSerialContext *wosc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = wosc->ctx;
+
+ 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
+EXCHANGEDB_select_wire_out_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,159 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_wire_out_above_serial_id_by_account.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WireOutSerialContext *wosc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = wosc->ctx;
+
+ 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
+EXCHANGEDB_select_wire_out_above_serial_id_by_account (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,160 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_withdraw_amounts_for_kyc_check.h"
+#include "pg_select_aggregation_amounts_for_kyc_check.h"
+#include "pg_helper.h"
+
+
+/**
+ * Closure for #get_kyc_amounts_cb().
+ */
+struct KycAmountCheckContext
+{
+ /**
+ * Function to call per result.
+ */
+ TALER_EXCHANGEDB_KycAmountCallback cb;
+
+ /**
+ * Closure for @e cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Plugin context.
+ */
+ struct EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct KycAmountCheckContext *ctx = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = ctx->ctx;
+
+ 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
+EXCHANGEDB_select_withdraw_amounts_for_kyc_check (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ PREPARE (ctx,
+ "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 (
+ ctx->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,214 @@
+/*
+ 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 src/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/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "select_withdrawals_above_serial_id.h"
+#include "pg_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 EXCHANGEDB_PostgresContext *ctx;
+
+ /**
+ * 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 (struct EXCHANGEDB_PostgresContext *ctx,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct WithdrawSerialContext *rosc = cls;
+ struct EXCHANGEDB_PostgresContext *ctx = rosc->ctx;
+
+ 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 (
+ ctx->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
+EXCHANGEDB_select_withdrawals_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ 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,
+ .ctx = ctx,
+ .status = GNUNET_OK
+ };
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Fetch deposits with rowid '\geq' the given parameter */
+ PREPARE (ctx,
+ "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 (ctx->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,71 @@
+/*
+ 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 src/exchangedb/set_aml_lock.c
+ * @brief Implementation of the set_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "set_aml_lock.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_set_aml_lock (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/set_extension_manifest.c
+ * @brief Implementation of the set_extension_manifest function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "set_extension_manifest.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_set_extension_manifest (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "set_extension_manifest",
+ params);
+}
diff --git a/src/exchangedb/set_purse_balance.c b/src/exchangedb/set_purse_balance.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 src/exchangedb/set_purse_balance.c
+ * @brief Implementation of the set_purse_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "set_purse_balance.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_set_purse_balance (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->conn,
+ balance),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "set_purse_balance",
+ "UPDATE purse_requests"
+ " SET balance=$2"
+ " WHERE purse_pub=$1;");
+
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "set_purse_balance",
+ params);
+}
diff --git a/src/exchangedb/start.c b/src/exchangedb/start.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 src/exchangedb/start.c
+ * @brief Implementation of the start function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "pg_preflight.h"
+#include "start.h"
+#include "pg_helper.h"
+
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_start (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 ==
+ EXCHANGEDB_preflight (ctx))
+ return GNUNET_SYSERR;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting transaction `%s'\n",
+ name);
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (ctx->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to start transaction\n");
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ ctx->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,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 src/exchangedb/start_deferred_wire_out.c
+ * @brief Implementation of the start_deferred_wire_out function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "start_deferred_wire_out.h"
+#include "pg_helper.h"
+#include "pg_preflight.h"
+#include "pg_rollback.h"
+
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_start_deferred_wire_out (struct EXCHANGEDB_PostgresContext *ctx)
+{
+ 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 ==
+ EXCHANGEDB_preflight (ctx))
+ return GNUNET_SYSERR;
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (ctx->conn,
+ es))
+ {
+ TALER_LOG_ERROR (
+ "Failed to defer wire_out_ref constraint on transaction\n");
+ GNUNET_break (0);
+ EXCHANGEDB_rollback (ctx);
+ return GNUNET_SYSERR;
+ }
+ ctx->transaction_name = "deferred wire out";
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting READ COMMITTED DEFERRED transaction `%s'\n",
+ ctx->transaction_name);
+ return GNUNET_OK;
+}
diff --git a/src/exchangedb/start_read_committed.c b/src/exchangedb/start_read_committed.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 src/exchangedb/start_read_committed.c
+ * @brief Implementation of the start_read_committed function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "start_read_committed.h"
+#include "pg_preflight.h"
+#include "pg_helper.h"
+
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_start_read_committed (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 ==
+ EXCHANGEDB_preflight (ctx))
+ return GNUNET_SYSERR;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting READ COMMITTED transaction `%s`\n",
+ name);
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (ctx->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to start transaction\n");
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ ctx->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,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 src/exchangedb/start_read_only.c
+ * @brief Implementation of the start_read_only function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "start_read_only.h"
+#include "pg_preflight.h"
+#include "pg_helper.h"
+
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_start_read_only (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 ==
+ EXCHANGEDB_preflight (ctx))
+ return GNUNET_SYSERR;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting READ ONLY transaction `%s`\n",
+ name);
+ if (GNUNET_OK !=
+ GNUNET_PQ_exec_statements (ctx->conn,
+ es))
+ {
+ TALER_LOG_ERROR ("Failed to start transaction\n");
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ ctx->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,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 src/exchangedb/store_wire_transfer_out.c
+ * @brief Implementation of the store_wire_transfer_out function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "store_wire_transfer_out.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_store_wire_transfer_out (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "insert_wire_out",
+ params);
+}
diff --git a/src/exchangedb/test_aml_officer.c b/src/exchangedb/test_aml_officer.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 src/exchangedb/test_aml_officer.c
+ * @brief Implementation of the test_aml_officer function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "test_aml_officer.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_test_aml_officer (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "test_aml_staff",
+ "SELECT read_only"
+ " FROM aml_staff"
+ " WHERE decider_pub=$1"
+ " AND is_active;");
+ return GNUNET_PQ_eval_prepared_singleton_select (ctx->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,100 @@
+/*
+ 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 src/exchangedb/trigger_kyc_rule_for_account.c
+ * @brief Implementation of the trigger_kyc_rule_for_account function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "trigger_kyc_rule_for_account.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_trigger_kyc_rule_for_account (struct EXCHANGEDB_PostgresContext *ctx,
+ 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_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 (ctx,
+ "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 (
+ ctx->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,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 src/exchangedb/update_aggregation_transient.c
+ * @brief Implementation of the update_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_aggregation_transient.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_update_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 (ctx,
+ "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 (ctx->conn,
+ "update_aggregation_transient",
+ params);
+}
diff --git a/src/exchangedb/update_auditor.c b/src/exchangedb/update_auditor.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 src/exchangedb/update_auditor.c
+ * @brief Implementation of the update_auditor function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_auditor.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_update_auditor (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,132 @@
+/*
+ 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 src/exchangedb/update_kyc_process_by_row.c
+ * @brief Implementation of the update_kyc_process_by_row function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_kyc_process_by_row.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_update_kyc_process_by_row (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (
+ ctx->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_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 (ctx->conn,
+ &rep.header,
+ NULL,
+ 0);
+ PREPARE (ctx,
+ "alert_kyc_status_change",
+ "INSERT INTO kyc_alerts"
+ " (h_payto"
+ " ,trigger_type)"
+ " VALUES"
+ " ($1,$2);");
+ qs2 = GNUNET_PQ_eval_prepared_non_select (
+ ctx->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,90 @@
+/*
+ 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 src/exchangedb/update_wire.c
+ * @brief Implementation of the update_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "update_wire.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_update_wire (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->conn,
+ "update_wire",
+ params);
+}
diff --git a/src/exchangedb/wad_in_insert.c b/src/exchangedb/wad_in_insert.c
@@ -0,0 +1,60 @@
+/*
+ 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 src/exchangedb/wad_in_insert.c
+ * @brief Implementation of the wad_in_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "wad_in_insert.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_wad_in_insert (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx->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 (ctx,
+ "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 (ctx->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,139 @@
+/*
+ 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 src/exchangedb/wire_prepare_data_get.c
+ * @brief Implementation of the wire_prepare_data_get function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "wire_prepare_data_get.h"
+#include "pg_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 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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
+EXCHANGEDB_wire_prepare_data_get (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "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 (ctx->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,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 src/exchangedb/wire_prepare_data_insert.c
+ * @brief Implementation of the wire_prepare_data_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "wire_prepare_data_insert.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_wire_prepare_data_insert (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 (ctx,
+ "wire_prepare_data_insert",
+ "INSERT INTO prewire "
+ "(wire_method"
+ ",buf"
+ ") VALUES "
+ "($1, $2);");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->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,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 src/exchangedb/wire_prepare_data_mark_failed.c
+ * @brief Implementation of the wire_prepare_data_mark_failed function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "wire_prepare_data_mark_failed.h"
+#include "pg_helper.h"
+
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_wire_prepare_data_mark_failed (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t rowid)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&rowid),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "wire_prepare_data_mark_failed",
+ "UPDATE prewire"
+ " SET failed=TRUE"
+ " WHERE prewire_uuid=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->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,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 src/exchangedb/wire_prepare_data_mark_finished.c
+ * @brief Implementation of the wire_prepare_data_mark_finished function for Postgres
+ * @author Christian Grothoff
+ */
+#include "taler/platform.h"
+#include "taler/taler_error_codes.h"
+#include "taler/taler_dbevents.h"
+#include "taler/taler_pq_lib.h"
+#include "wire_prepare_data_mark_finished.h"
+#include "pg_helper.h"
+
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_wire_prepare_data_mark_finished (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t rowid)
+{
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_uint64 (&rowid),
+ GNUNET_PQ_query_param_end
+ };
+
+ PREPARE (ctx,
+ "wire_prepare_data_mark_done",
+ "UPDATE prewire"
+ " SET finished=TRUE"
+ " WHERE prewire_uuid=$1;");
+ return GNUNET_PQ_eval_prepared_non_select (ctx->conn,
+ "wire_prepare_data_mark_done",
+ params);
+}
diff --git a/src/include/taler/auditor-database/del_denomination_balance.h b/src/include/taler/auditor-database/del_denomination_balance.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/auditor-database/del_denomination_balance.h
+ * @brief implementation of the del_denomination_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_DEL_DENOMINATION_BALANCE_H
+#define AUDITOR_DATABASE_DEL_DENOMINATION_BALANCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Delete information about a denomination key's balances.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param denom_pub_hash hash of the denomination public key
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_del_denomination_balance (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash);
+
+#endif
diff --git a/src/include/taler/auditor-database/del_reserve_info.h b/src/include/taler/auditor-database/del_reserve_info.h
@@ -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 pg_del_reserve_info.h
+ * @brief implementation of the del_reserve_info function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_DEL_RESERVE_INFO_H
+#define AUDITOR_DATABASE_DEL_RESERVE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Delete information about a reserve.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_del_reserve_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/delete_auditor_closure_lag.h b/src/include/taler/auditor-database/delete_auditor_closure_lag.h
@@ -0,0 +1,47 @@
+/*
+ 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 src/include/taler/auditor-database/delete_auditor_closure_lag.h
+ * @brief implementation of the delete_auditor_closure_lag function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_DELETE_AUDITOR_CLOSURE_LAG_H
+#define AUDITOR_DATABASE_DELETE_AUDITOR_CLOSURE_LAG_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * A previously missing wire transfer may have been found. Remove an alert
+ * (if we raised one).
+ *
+ * @param cls plugin closure
+ * @param amount wire transfer amount
+ * @param wtid wire transfer subject
+ * @param credit_account_uri destination account
+ * @return #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no matching alert was
+ * found
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_auditor_closure_lag (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_Amount *amount,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ struct TALER_FullPayto credit_account_uri);
+
+#endif
diff --git a/src/include/taler/auditor-database/delete_early_aggregation.h b/src/include/taler/auditor-database/delete_early_aggregation.h
@@ -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 src/include/taler/auditor-database/delete_early_aggregation.h
+ * @brief implementation of the delete_early_aggregation function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_DELETE_EARLY_AGGREGATION_H
+#define AUDITOR_DATABASE_DELETE_EARLY_AGGREGATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Delete a row from the early aggregation table.
+ * Usually done when the expected aggregation
+ * was finally detected.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param batch_deposit_serial_id which entry to delete
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_early_aggregation (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t batch_deposit_serial_id);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/delete_generic.h b/src/include/taler/auditor-database/delete_generic.h
@@ -0,0 +1,39 @@
+/*
+ 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_delete_generic.h
+ * @brief implementation of the delete_generic function
+ * @author Nic Eigel
+ */
+#ifndef AUDITOR_DATABASE_DELETE_GENERIC_H
+#define AUDITOR_DATABASE_DELETE_GENERIC_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ // FIXME: add comments
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_generic (struct AUDITORDB_PostgresContext *ctx,
+ enum TALER_AUDITORDB_DeletableSuppressableTables table,
+ uint64_t row_id);
+
+#endif
diff --git a/src/include/taler/auditor-database/delete_pending_deposit.h b/src/include/taler/auditor-database/delete_pending_deposit.h
@@ -0,0 +1,45 @@
+/*
+ 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 src/include/taler/auditor-database/delete_pending_deposit.h
+ * @brief implementation of the delete_pending_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_DELETE_PENDING_DEPOSIT_H
+#define AUDITOR_DATABASE_DELETE_PENDING_DEPOSIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Delete a row from the pending deposit table.
+ * Usually done when the respective wire transfer
+ * was finally detected.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param batch_deposit_serial_id which entry to delete
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_pending_deposit (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t batch_deposit_serial_id);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/delete_purse_info.h b/src/include/taler/auditor-database/delete_purse_info.h
@@ -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 src/include/taler/auditor-database/delete_purse_info.h
+ * @brief implementation of the delete_purse_info function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_DELETE_PURSE_INFO_H
+#define AUDITOR_DATABASE_DELETE_PURSE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Delete information about a purse.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub public key of the reserve
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_purse_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/delete_reserve_in_inconsistency.h b/src/include/taler/auditor-database/delete_reserve_in_inconsistency.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/auditor-database/delete_reserve_in_inconsistency.h
+ * @brief implementation of the delete_reserve_in_inconsistency function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_DELETE_RESERVE_IN_INCONSISTENCY_H
+#define AUDITOR_DATABASE_DELETE_RESERVE_IN_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Delete information about an reserve-in-inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param row_id row of the inconsistency in our table
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t row_id);
+
+#endif
diff --git a/src/include/taler/auditor-database/delete_wire_out_inconsistency_if_matching.h b/src/include/taler/auditor-database/delete_wire_out_inconsistency_if_matching.h
@@ -0,0 +1,36 @@
+/*
+ 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/>
+ */
+#ifndef AUDITOR_DATABASE_DELETE_WIRE_OUT_INCONSISTENCY_IF_MATCHING_H
+#define AUDITOR_DATABASE_DELETE_WIRE_OUT_INCONSISTENCY_IF_MATCHING_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Delete information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_delete_wire_out_inconsistency_if_matching (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_WireOutInconsistency *dc);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_amount_arithmetic_inconsistency.h b/src/include/taler/auditor-database/get_amount_arithmetic_inconsistency.h
@@ -0,0 +1,383 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_AMOUNT_ARITHMETIC_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_AMOUNT_ARITHMETIC_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Information about a signing key of an exchange.
+ */
+struct TALER_AUDITORDB_ExchangeSigningKey
+{
+
+ /**
+ * When does @e exchange_pub start to be used?
+ */
+ struct GNUNET_TIME_Timestamp ep_start;
+
+ /**
+ * When will the exchange stop signing with @e exchange_pub?
+ */
+ struct GNUNET_TIME_Timestamp ep_expire;
+
+ /**
+ * When does the signing key expire (for legal disputes)?
+ */
+ struct GNUNET_TIME_Timestamp ep_end;
+
+ /**
+ * What is the public offline signing key this is all about?
+ */
+ struct TALER_ExchangePublicKeyP exchange_pub;
+
+ /**
+ * Signature by the offline master key affirming the above.
+ */
+ struct TALER_MasterSignatureP master_sig;
+};
+
+
+/**
+ * Information about a deposit confirmation we received from
+ * a merchant.
+ */
+struct TALER_AUDITORDB_DepositConfirmation
+{
+
+ /**
+ * Hash over the contract for which this deposit is made.
+ */
+ struct TALER_PrivateContractHashP h_contract_terms;
+
+ /**
+ * Hash over the policy extension for the deposit.
+ */
+ struct TALER_ExtensionPolicyHashP h_policy;
+
+ /**
+ * Hash over the wiring information of the merchant.
+ */
+ struct TALER_MerchantWireHashP h_wire;
+
+ /**
+ * Time when this deposit confirmation was generated by the exchange.
+ */
+ struct GNUNET_TIME_Timestamp exchange_timestamp;
+
+ /**
+ * How much time does the @e merchant have to issue a refund
+ * request? Zero if refunds are not allowed. After this time, the
+ * coin cannot be refunded. Note that the wire transfer will not be
+ * performed by the exchange until the refund deadline. This value
+ * is taken from the original deposit request.
+ */
+ struct GNUNET_TIME_Timestamp refund_deadline;
+
+ /**
+ * How much time does the @e exchange have to wire the funds?
+ */
+ struct GNUNET_TIME_Timestamp wire_deadline;
+
+ /**
+ * Amount to be deposited, excluding fee. Calculated from the
+ * amount with fee and the fee from the deposit request.
+ */
+ struct TALER_Amount total_without_fee;
+
+ /**
+ * Array of the coin public keys involved in the
+ * batch deposit operation.
+ */
+ const struct TALER_CoinSpendPublicKeyP *coin_pubs;
+
+ /**
+ * Array of coin deposit signatures from the deposit operation.
+ */
+ const struct TALER_CoinSpendSignatureP *coin_sigs;
+
+ /**
+ * The Merchant's public key. Allows the merchant to later refund
+ * the transaction or to inquire about the wire transfer identifier.
+ */
+ struct TALER_MerchantPublicKeyP merchant;
+
+ /**
+ * Signature from the exchange of type
+ * #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT.
+ */
+ struct TALER_ExchangeSignatureP exchange_sig;
+
+ /**
+ * Public signing key from the exchange matching @e exchange_sig.
+ */
+ struct TALER_ExchangePublicKeyP exchange_pub;
+
+ /**
+ * Exchange master signature over @e exchange_sig.
+ */
+ struct TALER_MasterSignatureP master_sig;
+
+ /**
+ * Row of this entry in the auditor database.
+ */
+ uint64_t row_id;
+
+ /**
+ * Length of the @e coin_pubs and @e coin_sigs arrays.
+ */
+ unsigned int num_coins;
+
+ bool suppressed;
+
+};
+
+// MARK: CRUD
+
+/**
+ * Information about a row inconsistency
+ */
+struct TALER_AUDITORDB_Generic_Update
+{
+ uint64_t row_id;
+ bool suppressed;
+ bool ancient;
+};
+
+/**
+ * Information about an arithmetic inconsistency
+ */
+struct TALER_AUDITORDB_AmountArithmeticInconsistency
+{
+ uint64_t row_id;
+ uint64_t problem_row_id;
+ char *operation;
+ struct TALER_Amount exchange_amount;
+ struct TALER_Amount auditor_amount;
+ bool profitable;
+ bool suppressed;
+};
+
+/**
+ * Information about a coin inconsistency
+ */
+struct TALER_AUDITORDB_CoinInconsistency
+{
+ uint64_t row_id;
+ char *operation;
+ struct TALER_Amount exchange_amount;
+ struct TALER_Amount auditor_amount;
+ struct GNUNET_CRYPTO_EddsaPublicKey coin_pub;
+ bool profitable;
+};
+
+/**
+ * Information about a row inconsistency
+ */
+struct TALER_AUDITORDB_RowInconsistency
+{
+ uint64_t row_id;
+ char *row_table;
+ char *diagnostic;
+ bool suppressed;
+};
+
+/**
+ * Information about a bad sig loss
+ */
+struct TALER_AUDITORDB_BadSigLosses
+{
+ uint64_t row_id;
+ uint64_t problem_row_id;
+ char *operation;
+ struct TALER_Amount loss;
+ struct GNUNET_CRYPTO_EddsaPublicKey operation_specific_pub;
+ bool suppressed;
+};
+
+/**
+ * Information about a closure lags
+ */
+struct TALER_AUDITORDB_ClosureLags
+{
+ uint64_t row_id;
+ uint64_t problem_row_id;
+ struct TALER_Amount amount;
+ struct GNUNET_TIME_Absolute deadline;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ struct TALER_FullPayto account;
+ bool suppressed;
+};
+
+/**
+ * Information about a emergency
+ */
+struct TALER_AUDITORDB_Emergency
+{
+ uint64_t row_id;
+ struct TALER_DenominationHashP denompub_h;
+ struct TALER_Amount denom_risk;
+ struct TALER_Amount denom_loss;
+ struct GNUNET_TIME_Absolute deposit_start;
+ struct GNUNET_TIME_Absolute deposit_end;
+ struct TALER_Amount value;
+ bool suppressed;
+};
+
+/**
+ * Information about an emergency by count
+ */
+struct TALER_AUDITORDB_EmergenciesByCount
+{
+ uint64_t row_id;
+ struct TALER_DenominationHashP denompub_h;
+ uint64_t num_issued;
+ uint64_t num_known;
+ struct TALER_Amount risk;
+ struct GNUNET_TIME_Absolute start;
+ struct GNUNET_TIME_Absolute deposit_end;
+ struct TALER_Amount value;
+ bool suppressed;
+};
+
+/**
+ * Information about progress of the audit.
+ */
+struct TALER_AUDITORDB_Progress
+{
+ char *progress_key;
+ uint64_t progress_offset;
+};
+
+
+/**
+ * Information about a fee time inconsistency
+ */
+struct TALER_AUDITORDB_FeeTimeInconsistency
+{
+ uint64_t row_id;
+ uint64_t problem_row_id;
+ char *type;
+ struct GNUNET_TIME_Absolute time;
+ char *diagnostic;
+};
+
+/**
+ * Information about a denom key validity withdraw inconsistency
+ */
+struct TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistency
+{
+ uint64_t row_id;
+ uint64_t problem_row_id;
+ struct GNUNET_TIME_Absolute execution_date;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_DenominationHashP denompub_h;
+ bool suppressed;
+};
+
+/**
+ * Information about a purse not closed inconsistencies
+ */
+struct TALER_AUDITORDB_PurseNotClosedInconsistencies
+{
+ uint64_t row_id;
+ struct GNUNET_CRYPTO_EddsaPublicKey purse_pub;
+ struct TALER_Amount amount;
+ struct GNUNET_TIME_Absolute expiration_date;
+ bool suppressed;
+};
+
+/**
+ * Information about a reserve balance insufficient inconsistency
+ */
+struct TALER_AUDITORDB_ReserveBalanceInsufficientInconsistency
+{
+ uint64_t row_id;
+ struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub;
+ bool inconsistency_gain;
+ struct TALER_Amount inconsistency_amount;
+ bool suppressed;
+};
+
+/**
+ * Information about a reserve in inconsistency
+ */
+struct TALER_AUDITORDB_ReserveInInconsistency
+{
+ uint64_t serial_id;
+ uint64_t bank_row_id;
+ struct TALER_Amount amount_exchange_expected;
+ struct TALER_Amount amount_wired;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct GNUNET_TIME_Absolute timestamp;
+ struct TALER_FullPayto account;
+ char *diagnostic;
+ bool suppressed;
+
+};
+
+/**
+ * Information about a balance
+ */
+struct TALER_AUDITORDB_Balances
+{
+ uint64_t row_id;
+ char *balance_key;
+ struct TALER_Amount balance_value;
+ bool suppressed;
+
+};
+
+/**
+ * Function called with arithmetic inconsistencies stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_AmountArithmeticInconsistencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_AmountArithmeticInconsistency *dc);
+
+/**
+ * Get information about deposit confirmations from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_amount_arithmetic_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_AmountArithmeticInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_auditor_closure_lags.h b/src/include/taler/auditor-database/get_auditor_closure_lags.h
@@ -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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_AUDITOR_CLOSURE_LAGS_H
+#define AUDITOR_DATABASE_GET_AUDITOR_CLOSURE_LAGS_H
+
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with closure lags stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_ClosureLagsCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_ClosureLags *dc);
+
+/**
+ * Get information about auditor closure lags from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_auditor_closure_lags (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ClosureLagsCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_auditor_progress.h b/src/include/taler/auditor-database/get_auditor_progress.h
@@ -0,0 +1,46 @@
+/*
+ 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 pg_get_auditor_progress.h
+ * @brief implementation of the get_auditor_progress function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_GET_AUDITOR_PROGRESS_H
+#define AUDITOR_DATABASE_GET_AUDITOR_PROGRESS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Get information about the progress of the auditor.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param progress_key name of the progress indicator
+ * @param[out] progress_offset set to offset until which we have made progress
+ * @param ... NULL terminated list of additional key-value pairs to fetch
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_auditor_progress (struct AUDITORDB_PostgresContext *ctx,
+ const char *progress_key,
+ uint64_t *progress_offset,
+ ...);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_bad_sig_losses.h b/src/include/taler/auditor-database/get_bad_sig_losses.h
@@ -0,0 +1,64 @@
+/*
+ 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/>
+ */
+#ifndef AUDITOR_DATABASE_GET_BAD_SIG_LOSSES_H
+#define AUDITOR_DATABASE_GET_BAD_SIG_LOSSES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with bad signature losses stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_BadSigLossesCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_BadSigLosses *dc);
+
+/**
+ * Get information about bad signature losses from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param op_spec_pub public key to filter by; FIXME: replace by pointer
+ * @param op operation to filter by
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_bad_sig_losses (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ const struct GNUNET_CRYPTO_EddsaPublicKey *op_spec_pub,
+ const char *op,
+ TALER_AUDITORDB_BadSigLossesCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_balance.h b/src/include/taler/auditor-database/get_balance.h
@@ -0,0 +1,46 @@
+/*
+ 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 src/include/taler/auditor-database/get_balance.h
+ * @brief implementation of the get_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_GET_BALANCE_H
+#define AUDITOR_DATABASE_GET_BALANCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Get summary information about balance tracked by the auditor.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param balance_key key of the balance to store
+ * @param[out] balance_value set to amount stored under @a balance_key
+ * @param ... NULL terminated list of additional key-value pairs to fetch
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_balance (struct AUDITORDB_PostgresContext *ctx,
+ const char *balance_key,
+ struct TALER_Amount *balance_value,
+ ...);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_balances.h b/src/include/taler/auditor-database/get_balances.h
@@ -0,0 +1,48 @@
+/*
+ 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/>
+ */
+#ifndef AUDITOR_DATABASE_GET_BALANCES_H
+#define AUDITOR_DATABASE_GET_BALANCES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_BalancesCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_Balances *dc);
+
+/**
+ * Get information about balances from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param balance_key key to filter by, NULL to match all balance keys
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_balances (struct AUDITORDB_PostgresContext *ctx,
+ const char *balance_key,
+ TALER_AUDITORDB_BalancesCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_coin_inconsistency.h b/src/include/taler/auditor-database/get_coin_inconsistency.h
@@ -0,0 +1,63 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_COIN_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_COIN_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with coin inconsistencies stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param serial_id location of the @a dc in the database
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_CoinInconsistencyCallback)(
+ void *cls,
+ uint64_t serial_id,
+ const struct TALER_AUDITORDB_CoinInconsistency *dc);
+
+/**
+ * Get information about deposit confirmations from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_coin_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_CoinInconsistencyCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/get_denomination_balance.h b/src/include/taler/auditor-database/get_denomination_balance.h
@@ -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 pg_get_denomination_balance.h
+ * @brief implementation of the get_denomination_balance function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_GET_DENOMINATION_BALANCE_H
+#define AUDITOR_DATABASE_GET_DENOMINATION_BALANCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Get information about a denomination key's balances.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param denom_pub_hash hash of the denomination public key
+ * @param[out] dcd circulation data to initialize
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_denomination_balance (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ struct TALER_AUDITORDB_DenominationCirculationData *dcd);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_denomination_key_validity_withdraw_inconsistency.h b/src/include/taler/auditor-database/get_denomination_key_validity_withdraw_inconsistency.h
@@ -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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_DENOMINATION_KEY_VALIDITY_WITHDRAW_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_DENOMINATION_KEY_VALIDITY_WITHDRAW_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with fee denomination key validity withdraw inconsistency stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistencyCallback)(
+ void *cls,
+ const struct
+ TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistency *dc);
+
+/**
+ * Get information about denominations key validity withdraw inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_denomination_key_validity_withdraw_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_denomination_pending.h b/src/include/taler/auditor-database/get_denomination_pending.h
@@ -0,0 +1,51 @@
+/*
+ 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/>
+ */
+#ifndef AUDITOR_DATABASE_GET_DENOMINATION_PENDING_H
+#define AUDITOR_DATABASE_GET_DENOMINATION_PENDING_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_DenominationPendingCallback)(
+ void *cls,
+ uint64_t serial_id,
+ const struct TALER_AUDITORDB_DenominationPending *dc);
+
+/**
+ * Get information about denomination-pending from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_denomination_pending (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_DenominationPendingCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_denominations_without_sigs.h b/src/include/taler/auditor-database/get_denominations_without_sigs.h
@@ -0,0 +1,54 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_GET_DENOMINATIONS_WITHOUT_SIGS_H
+#define AUDITOR_DATABASE_GET_DENOMINATIONS_WITHOUT_SIGS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_DenominationsWithoutSigsCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_DenominationsWithoutSigs *dc);
+
+/**
+ * Get information about denominations-without-sigs from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_denominations_without_sigs (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_DenominationsWithoutSigsCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_deposit_confirmations.h b/src/include/taler/auditor-database/get_deposit_confirmations.h
@@ -0,0 +1,292 @@
+/*
+ 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_get_deposit_confirmations.h
+ * @brief implementation of the get_deposit_confirmations function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_GET_DEPOSIT_CONFIRMATIONS_H
+#define AUDITOR_DATABASE_GET_DEPOSIT_CONFIRMATIONS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Balance values for a reserve (or all reserves).
+ */
+struct TALER_AUDITORDB_ReserveFeeBalance
+{
+ /**
+ * Remaining funds.
+ */
+ struct TALER_Amount reserve_balance;
+
+ /**
+ * Losses from operations that should not have
+ * happened (e.g. negative balance).
+ */
+ struct TALER_Amount reserve_loss;
+
+ /**
+ * Fees charged for withdraw.
+ */
+ struct TALER_Amount withdraw_fee_balance;
+
+ /**
+ * Fees charged for closing.
+ */
+ struct TALER_Amount close_fee_balance;
+
+ /**
+ * Fees charged for purse creation.
+ */
+ struct TALER_Amount purse_fee_balance;
+
+ /**
+ * Opening fees charged.
+ */
+ struct TALER_Amount open_fee_balance;
+
+ /**
+ * History fees charged.
+ */
+ struct TALER_Amount history_fee_balance;
+};
+
+
+/**
+ * Balance data for denominations in circulation.
+ */
+struct TALER_AUDITORDB_DenominationCirculationData
+{
+ /**
+ * Amount of outstanding coins in circulation.
+ */
+ struct TALER_Amount denom_balance;
+
+ /**
+ * Amount lost due coins illicitly accepted (effectively, a
+ * negative @a denom_balance).
+ */
+ struct TALER_Amount denom_loss;
+
+ /**
+ * Total amount that could still be theoretically lost in the future due to
+ * recoup operations. (Total put into circulation minus @e recoup_loss).
+ */
+ struct TALER_Amount denom_risk;
+
+ /**
+ * Amount lost due to recoups.
+ */
+ struct TALER_Amount recoup_loss;
+
+ /**
+ * Number of coins of this denomination that the exchange signed into
+ * existence.
+ */
+ uint64_t num_issued;
+};
+
+struct TALER_AUDITORDB_DenominationsWithoutSigs
+{
+ uint64_t row_id;
+ struct TALER_DenominationHashP denompub_h;
+ struct TALER_Amount value;
+ struct GNUNET_TIME_Absolute start_time;
+ struct GNUNET_TIME_Absolute end_time;
+ bool suppressed;
+};
+
+struct TALER_AUDITORDB_MisattributionInInconsistency
+{
+ uint64_t row_id;
+ struct TALER_Amount amount;
+ uint64_t bank_row;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_Reserves
+{
+ uint64_t row_id;
+ uint64_t auditor_reserves_rowid;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_Amount reserve_balance;
+ struct TALER_Amount reserve_loss;
+ struct TALER_Amount withdraw_fee_balance;
+ struct TALER_Amount close_fee_balance;
+ struct TALER_Amount purse_fee_balance;
+ struct TALER_Amount open_fee_balance;
+ struct TALER_Amount history_fee_balance;
+ struct GNUNET_TIME_Absolute expiration_date;
+ struct TALER_FullPayto origin_account;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_Purses
+{
+ uint64_t row_id;
+ uint64_t auditor_purses_rowid;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_Amount balance;
+ struct TALER_Amount target;
+ struct GNUNET_TIME_Absolute expiration_date;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_HistoricDenominationRevenue
+{
+ uint64_t row_id;
+ struct TALER_DenominationHashP denom_pub_hash;
+ struct GNUNET_TIME_Absolute revenue_timestamp;
+ struct TALER_Amount revenue_balance;
+ struct TALER_Amount loss_balance;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_DenominationPending
+{
+ uint64_t row_id;
+ struct TALER_DenominationHashP denom_pub_hash;
+ struct TALER_Amount denom_balance;
+ struct TALER_Amount denom_loss;
+ uint64_t num_issued;
+ struct TALER_Amount denom_risk;
+ struct TALER_Amount recoup_loss;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_HistoricReserveSummary
+{
+ uint64_t row_id;
+ struct GNUNET_TIME_Absolute start_date;
+ struct GNUNET_TIME_Absolute end_date;
+ struct TALER_Amount reserve_profits;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_ExchangeSignkeys
+{
+ uint64_t row_id;
+ struct TALER_ExchangePublicKeyP exchange_pub;
+ struct TALER_MasterSignatureP master_sig;
+ struct GNUNET_TIME_Absolute ep_valid_from;
+ struct GNUNET_TIME_Absolute ep_expire_sign;
+ struct GNUNET_TIME_Absolute ep_expire_legal;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_WireFormatInconsistency
+{
+ uint64_t row_id;
+ struct TALER_Amount amount;
+ uint64_t wire_offset;
+ char *diagnostic;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_WireOutInconsistency
+{
+ uint64_t row_id;
+ struct TALER_FullPayto destination_account;
+ char *diagnostic;
+ uint64_t wire_out_row_id;
+ struct TALER_Amount expected;
+ struct TALER_Amount claimed;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_RowMinorInconsistencies
+{
+ uint64_t row_id;
+ char *row_table;
+ uint64_t problem_row;
+ char *diagnostic;
+ bool suppressed;
+};
+
+
+struct TALER_AUDITORDB_ReserveBalanceSummaryWrongInconsistency
+{
+ uint64_t row_id;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_Amount exchange_amount;
+ struct TALER_Amount auditor_amount;
+ bool suppressed;
+
+};
+
+struct TALER_AUDITORDB_ReserveNotClosedInconsistency
+{
+ uint64_t row_id;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_Amount balance;
+ struct GNUNET_TIME_Absolute expiration_time;
+ char *diagnostic;
+ bool suppressed;
+
+};
+
+/**
+ * Function called with deposit confirmations stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the deposit confirmation itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_DepositConfirmationCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_DepositConfirmation *dc);
+
+/**
+ * Get information about deposit confirmations from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_deposit_confirmations (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_DepositConfirmationCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_emergency.h b/src/include/taler/auditor-database/get_emergency.h
@@ -0,0 +1,60 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_EMERGENCY_H
+#define AUDITOR_DATABASE_GET_EMERGENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with emergencies stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_EmergencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_Emergency *dc);
+
+/**
+ * Get information about emergency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_emergency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_EmergencyCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_emergency_by_count.h b/src/include/taler/auditor-database/get_emergency_by_count.h
@@ -0,0 +1,60 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_EMERGENCY_BY_COUNT_H
+#define AUDITOR_DATABASE_GET_EMERGENCY_BY_COUNT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with emergencies stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_EmergenciesByCountCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_EmergenciesByCount *dc);
+
+/**
+ * Get information about emergency by count from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_emergency_by_count (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_EmergenciesByCountCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_exchange_signkeys.h b/src/include/taler/auditor-database/get_exchange_signkeys.h
@@ -0,0 +1,55 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_GET_EXCHANGE_SIGNKEYS_H
+#define AUDITOR_DATABASE_GET_EXCHANGE_SIGNKEYS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_ExchangeSignkeysCallback)(
+ void *cls,
+ uint64_t serial_id,
+ const struct TALER_AUDITORDB_ExchangeSignkeys *dc);
+
+/**
+ * Get information about exchange-signkeys from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_exchange_signkeys (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ExchangeSignkeysCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_fee_time_inconsistency.h b/src/include/taler/auditor-database/get_fee_time_inconsistency.h
@@ -0,0 +1,60 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_FEE_TIME_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_FEE_TIME_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with fee time inconsistency stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_FeeTimeInconsistencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_FeeTimeInconsistency *dc);
+
+/**
+ * Get information about fee time inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_fee_time_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_FeeTimeInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_misattribution_in_inconsistency.h b/src/include/taler/auditor-database/get_misattribution_in_inconsistency.h
@@ -0,0 +1,54 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_GET_MISATTRIBUTION_IN_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_MISATTRIBUTION_IN_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_MisattributionInInconsistencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_MisattributionInInconsistency *dc);
+
+/**
+ * Get information about misattribution-in-inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_misattribution_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_MisattributionInInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_progress_points.h b/src/include/taler/auditor-database/get_progress_points.h
@@ -0,0 +1,55 @@
+/*
+ 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 src/include/taler/auditor-database/get_progress_points.h
+ * @brief implementation of the get_progress_points function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_GET_PROGRESS_POINTS_H
+#define AUDITOR_DATABASE_GET_PROGRESS_POINTS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_ProgressPointsCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_Progress *pp);
+
+/**
+ * Get information about progress from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param progress_key only return this particular progress point
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_progress_points (struct AUDITORDB_PostgresContext *ctx,
+ const char *progress_key,
+ TALER_AUDITORDB_ProgressPointsCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/get_purse_info.h b/src/include/taler/auditor-database/get_purse_info.h
@@ -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 src/include/taler/auditor-database/get_purse_info.h
+ * @brief implementation of the get_purse_info function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_GET_PURSE_INFO_H
+#define AUDITOR_DATABASE_GET_PURSE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Get information about a purse.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub public key of the purse
+ * @param[out] rowid which row did we get the information from
+ * @param[out] balance set to balance of the purse
+ * @param[out] expiration_date expiration date of the purse
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_purse_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ uint64_t *rowid,
+ struct TALER_Amount *balance,
+ struct GNUNET_TIME_Timestamp *expiration_date);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_purse_not_closed_inconsistencies.h b/src/include/taler/auditor-database/get_purse_not_closed_inconsistencies.h
@@ -0,0 +1,60 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_PURSE_NOT_CLOSED_INCONSISTENCIES_H
+#define AUDITOR_DATABASE_GET_PURSE_NOT_CLOSED_INCONSISTENCIES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with purse not closed inconsistencies stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_PurseNotClosedInconsistenciesCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_PurseNotClosedInconsistencies *dc);
+
+/**
+ * Get information about purse not closed inconsistencies from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_purse_not_closed_inconsistencies (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_PurseNotClosedInconsistenciesCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_purses.h b/src/include/taler/auditor-database/get_purses.h
@@ -0,0 +1,51 @@
+/*
+ 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/>
+ */
+#ifndef AUDITOR_DATABASE_GET_PURSES_H
+#define AUDITOR_DATABASE_GET_PURSES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_PursesCallback)(
+ void *cls,
+ uint64_t serial_id,
+ const struct TALER_AUDITORDB_Purses *dc);
+
+/**
+ * Get information about purses from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_purses (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_PursesCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_reserve_balance_insufficient_inconsistency.h b/src/include/taler/auditor-database/get_reserve_balance_insufficient_inconsistency.h
@@ -0,0 +1,60 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_RESERVE_BALANCE_INSUFFICIENT_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_RESERVE_BALANCE_INSUFFICIENT_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with reserve balance insufficient inconsistency stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_ReserveBalanceInsufficientInconsistencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_ReserveBalanceInsufficientInconsistency *dc);
+
+/**
+ * Get information about reserve balance insufficient inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_balance_insufficient_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ReserveBalanceInsufficientInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_reserve_balance_summary_wrong_inconsistency.h b/src/include/taler/auditor-database/get_reserve_balance_summary_wrong_inconsistency.h
@@ -0,0 +1,54 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_GET_RESERVE_BALANCE_SUMMARY_WRONG_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_RESERVE_BALANCE_SUMMARY_WRONG_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_ReserveBalanceSummaryWrongInconsistencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_ReserveBalanceSummaryWrongInconsistency *dc);
+
+/**
+ * Get information about reserve-balance-summary-wrong-inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_balance_summary_wrong_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ReserveBalanceSummaryWrongInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_reserve_in_inconsistency.h b/src/include/taler/auditor-database/get_reserve_in_inconsistency.h
@@ -0,0 +1,54 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_GET_RESERVE_IN_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_RESERVE_IN_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_ReserveInInconsistencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_ReserveInInconsistency *dc);
+
+/**
+ * Get information about reserve-in-inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ReserveInInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_reserve_info.h b/src/include/taler/auditor-database/get_reserve_info.h
@@ -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 pg_get_reserve_info.h
+ * @brief implementation of the get_reserve_info function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_GET_RESERVE_INFO_H
+#define AUDITOR_DATABASE_GET_RESERVE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Get information about a reserve.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param[out] rowid which row did we get the information from
+ * @param[out] rfb where to store the reserve balance summary
+ * @param[out] expiration_date expiration date of the reserve
+ * @param[out] sender_account from where did the money in the reserve originally come from
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ uint64_t *rowid,
+ struct TALER_AUDITORDB_ReserveFeeBalance *rfb,
+ struct GNUNET_TIME_Timestamp *expiration_date,
+ struct TALER_FullPayto *sender_account);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/get_reserve_not_closed_inconsistency.h b/src/include/taler/auditor-database/get_reserve_not_closed_inconsistency.h
@@ -0,0 +1,54 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_GET_RESERVE_NOT_CLOSED_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_RESERVE_NOT_CLOSED_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_ReserveNotClosedInconsistencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_ReserveNotClosedInconsistency *dc);
+
+/**
+ * Get information about reserve-not-closed-inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserve_not_closed_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_ReserveNotClosedInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_reserves.h b/src/include/taler/auditor-database/get_reserves.h
@@ -0,0 +1,51 @@
+/*
+ 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/>
+ */
+#ifndef AUDITOR_DATABASE_GET_RESERVES_H
+#define AUDITOR_DATABASE_GET_RESERVES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_ReservesCallback)(
+ void *cls,
+ uint64_t serial_id,
+ const struct TALER_AUDITORDB_Reserves *dc);
+
+/**
+ * Get information about reserves from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_reserves (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_ReservesCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_row_inconsistency.h b/src/include/taler/auditor-database/get_row_inconsistency.h
@@ -0,0 +1,63 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_GET_ROW_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_ROW_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with row inconsistencies stored in
+ * the auditor's database.
+ *
+ * @param cls closure
+ * @param serial_id location of the @a dc in the database
+ * @param dc the structure itself
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_RowInconsistencyCallback)(
+ void *cls,
+ uint64_t serial_id,
+ const struct TALER_AUDITORDB_RowInconsistency *dc);
+
+/**
+ * Get information about deposit confirmations from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_row_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_RowInconsistencyCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/get_row_minor_inconsistencies.h b/src/include/taler/auditor-database/get_row_minor_inconsistencies.h
@@ -0,0 +1,54 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_GET_ROW_MINOR_INCONSISTENCIES_H
+#define AUDITOR_DATABASE_GET_ROW_MINOR_INCONSISTENCIES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_RowMinorInconsistenciesCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_RowMinorInconsistencies *dc);
+
+/**
+ * Get information about row-minor-inconsistencies from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_row_minor_inconsistencies (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_RowMinorInconsistenciesCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/get_wire_fee_summary.h b/src/include/taler/auditor-database/get_wire_fee_summary.h
@@ -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 pg_get_wire_fee_summary.h
+ * @brief implementation of the get_wire_fee_summary function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_GET_WIRE_FEE_SUMMARY_H
+#define AUDITOR_DATABASE_GET_WIRE_FEE_SUMMARY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Get summary information about an exchanges wire fee balance.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param[out] wire_fee_balance set amount the exchange gained in wire fees
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_wire_fee_summary (struct AUDITORDB_PostgresContext *ctx,
+ struct TALER_Amount *wire_fee_balance);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/get_wire_format_inconsistency.h b/src/include/taler/auditor-database/get_wire_format_inconsistency.h
@@ -0,0 +1,54 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_GET_WIRE_FORMAT_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_WIRE_FORMAT_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_WireFormatInconsistencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_WireFormatInconsistency *dc);
+
+/**
+ * Get information about wire-format-inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_wire_format_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_WireFormatInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif // AUDITOR_DATABASE_GET_WIRE_FORMAT_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/get_wire_out_inconsistency.h b/src/include/taler/auditor-database/get_wire_out_inconsistency.h
@@ -0,0 +1,54 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_GET_WIRE_OUT_INCONSISTENCY_H
+#define AUDITOR_DATABASE_GET_WIRE_OUT_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_WireOutInconsistencyCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_WireOutInconsistency *dc);
+
+/**
+ * Get information about wire-out-inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit number of records to return, negative for descending
+ * @param offset table row to start from, exclusive, direction determined by @a limit
+ * @param return_suppressed should suppressed rows be returned anyway?
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_get_wire_out_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_WireOutInconsistencyCallback cb,
+ void *cb_cls);
+
+#endif // AUDITOR_DATABASE_GET_WIRE_OUT_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_amount_arithmetic_inconsistency.h b/src/include/taler/auditor-database/insert_amount_arithmetic_inconsistency.h
@@ -0,0 +1,37 @@
+/*
+ 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/>
+ */
+#ifndef AUDITOR_DATABASE_INSERT_AMOUNT_ARITHMETIC_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_AMOUNT_ARITHMETIC_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+// #include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a deposit confirmation into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_amount_arithmetic_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_AmountArithmeticInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_AMOUNT_ARITHMETIC_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_auditor_closure_lags.h b/src/include/taler/auditor-database/insert_auditor_closure_lags.h
@@ -0,0 +1,37 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_INSERT_AUDITOR_CLOSURE_LAGS_H
+#define AUDITOR_DATABASE_INSERT_AUDITOR_CLOSURE_LAGS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a closure into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_auditor_closure_lags (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ClosureLags *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_AUDITOR_CLOSURE_LAGS_H
diff --git a/src/include/taler/auditor-database/insert_auditor_progress.h b/src/include/taler/auditor-database/insert_auditor_progress.h
@@ -0,0 +1,47 @@
+/*
+ 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_auditor_progress.h
+ * @brief implementation of the insert_auditor_progress function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_AUDITOR_PROGRESS_H
+#define AUDITOR_DATABASE_INSERT_AUDITOR_PROGRESS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about the auditor's progress with an exchange's
+ * data.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param progress_key name of the progress indicator
+ * @param progress_offset offset until which we have made progress
+ * @param ... NULL terminated list of additional key-value pairs to insert
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_auditor_progress (struct AUDITORDB_PostgresContext *ctx,
+ const char *progress_key,
+ uint64_t progress_offset,
+ ...);
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_bad_sig_losses.h b/src/include/taler/auditor-database/insert_bad_sig_losses.h
@@ -0,0 +1,36 @@
+/*
+ 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/>
+ */
+#ifndef AUDITOR_DATABASE_INSERT_BAD_SIG_LOSSES_H
+#define AUDITOR_DATABASE_INSERT_BAD_SIG_LOSSES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_bad_sig_losses (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_BadSigLosses *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_BAD_SIG_LOSSES_H
diff --git a/src/include/taler/auditor-database/insert_balance.h b/src/include/taler/auditor-database/insert_balance.h
@@ -0,0 +1,47 @@
+/*
+ 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 pg_insert_balance.h
+ * @brief implementation of the insert_balance function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_BALANCE_H
+#define AUDITOR_DATABASE_INSERT_BALANCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a balance tracked by the auditor. There must not be an
+ * existing record.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param balance_key key of the balance to store
+ * @param balance_value value to store
+ * @param ... NULL terminated list of additional key-value pairs to insert
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_balance (struct AUDITORDB_PostgresContext *ctx,
+ const char *balance_key,
+ const struct TALER_Amount *balance_value,
+ ...);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_coin_inconsistency.h b/src/include/taler/auditor-database/insert_coin_inconsistency.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_INSERT_COIN_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_COIN_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+// #include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a deposit confirmation into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_coin_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_CoinInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_COIN_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_denomination_balance.h b/src/include/taler/auditor-database/insert_denomination_balance.h
@@ -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 pg_insert_denomination_balance.h
+ * @brief implementation of the insert_denomination_balance function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_DENOMINATION_BALANCE_H
+#define AUDITOR_DATABASE_INSERT_DENOMINATION_BALANCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a denomination key's balances. There
+ * must not be an existing record for the denomination key.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param denom_pub_hash hash of the denomination public key
+ * @param dcd circulation data to store
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_denomination_balance (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ const struct TALER_AUDITORDB_DenominationCirculationData *dcd);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_denomination_key_validity_withdraw_inconsistency.h b/src/include/taler/auditor-database/insert_denomination_key_validity_withdraw_inconsistency.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_INSERT_DENOMINATION_KEY_VALIDITY_WITHDRAW_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_DENOMINATION_KEY_VALIDITY_WITHDRAW_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a denomination key validity withdraw inconsistency into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_denomination_key_validity_withdraw_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct
+ TALER_AUDITORDB_DenominationKeyValidityWithdrawInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_DENOMINATION_KEY_VALIDITY_WITHDRAW_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_denomination_pending.h b/src/include/taler/auditor-database/insert_denomination_pending.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_INSERT_DENOMINATION_PENDING_H
+#define AUDITOR_DATABASE_INSERT_DENOMINATION_PENDING_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_denomination_pending (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_DenominationPending *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_DENOMINATION_PENDING_H
diff --git a/src/include/taler/auditor-database/insert_denominations_without_sigs.h b/src/include/taler/auditor-database/insert_denominations_without_sigs.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_INSERT_DENOMINATIONS_WITHOUT_SIGS_H
+#define AUDITOR_DATABASE_INSERT_DENOMINATIONS_WITHOUT_SIGS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_denominations_without_sigs (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_DenominationsWithoutSigs *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_DENOMINATIONS_WITHOUT_SIGS_H
diff --git a/src/include/taler/auditor-database/insert_deposit_confirmation.h b/src/include/taler/auditor-database/insert_deposit_confirmation.h
@@ -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 pg_insert_deposit_confirmation.h
+ * @brief implementation of the insert_deposit_confirmation function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_DEPOSIT_CONFIRMATION_H
+#define AUDITOR_DATABASE_INSERT_DEPOSIT_CONFIRMATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a deposit confirmation into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_deposit_confirmation (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_DepositConfirmation *dc);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_early_aggregation.h b/src/include/taler/auditor-database/insert_early_aggregation.h
@@ -0,0 +1,49 @@
+/*
+ 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 src/include/taler/auditor-database/insert_early_aggregation.h
+ * @brief implementation of the insert_early_aggregation function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_EARLY_AGGREGATION_H
+#define AUDITOR_DATABASE_INSERT_EARLY_AGGREGATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert new row into the early aggregation table. This can happen simply
+ * because of when the taler-helper-auditor-transfer looks at which of the
+ * two tables. If it is cleared in the next iteration, this is perfectly
+ * expected.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param batch_deposit_serial_id where in the batch deposit table are we
+ * @param tracking_serial_id where in the tracking table are we
+ * @param total_amount value of all missing deposits, including fees
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_early_aggregation (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t batch_deposit_serial_id,
+ uint64_t tracking_serial_id,
+ const struct TALER_Amount *total_amount);
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_emergency.h b/src/include/taler/auditor-database/insert_emergency.h
@@ -0,0 +1,37 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_INSERT_EMERGENCY_H
+#define AUDITOR_DATABASE_INSERT_EMERGENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a emergency into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_emergency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_Emergency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_EMERGENCY_H
diff --git a/src/include/taler/auditor-database/insert_emergency_by_count.h b/src/include/taler/auditor-database/insert_emergency_by_count.h
@@ -0,0 +1,37 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_INSERT_EMERGENCY_BY_COUNT_H
+#define AUDITOR_DATABASE_INSERT_EMERGENCY_BY_COUNT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a emergency into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_emergency_by_count (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_EmergenciesByCount *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_EMERGENCY_BY_COUNT_H
diff --git a/src/include/taler/auditor-database/insert_exchange_signkey.h b/src/include/taler/auditor-database/insert_exchange_signkey.h
@@ -0,0 +1,41 @@
+/*
+ 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_exchange_signkey.h
+ * @brief implementation of the insert_exchange_signkey function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_EXCHANGE_SIGNKEY_H
+#define AUDITOR_DATABASE_INSERT_EXCHANGE_SIGNKEY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a signing key of the exchange.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param sk signing key information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_exchange_signkey (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ExchangeSigningKey *sk);
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_fee_time_inconsistency.h b/src/include/taler/auditor-database/insert_fee_time_inconsistency.h
@@ -0,0 +1,37 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_INSERT_FEE_TIME_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_FEE_TIME_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a fee time inconsistency into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_fee_time_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_FeeTimeInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_FEE_TIME_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_historic_denom_revenue.h b/src/include/taler/auditor-database/insert_historic_denom_revenue.h
@@ -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 pg_insert_historic_denom_revenue.h
+ * @brief implementation of the insert_historic_denom_revenue function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_HISTORIC_DENOM_REVENUE_H
+#define AUDITOR_DATABASE_INSERT_HISTORIC_DENOM_REVENUE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about an exchange's historic
+ * revenue about a denomination key.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param denom_pub_hash hash of the denomination key
+ * @param revenue_timestamp when did this profit get realized
+ * @param revenue_balance what was the total profit made from
+ * deposit fees, melting fees, refresh fees
+ * and coins that were never returned?
+ * @param loss_balance total losses suffered by the exchange at the time
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_historic_denom_revenue (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ struct GNUNET_TIME_Timestamp revenue_timestamp,
+ const struct TALER_Amount *revenue_balance,
+ const struct TALER_Amount *loss_balance);
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_historic_reserve_revenue.h b/src/include/taler/auditor-database/insert_historic_reserve_revenue.h
@@ -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 pg_insert_historic_reserve_revenue.h
+ * @brief implementation of the insert_historic_reserve_revenue function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_HISTORIC_RESERVE_REVENUE_H
+#define AUDITOR_DATABASE_INSERT_HISTORIC_RESERVE_REVENUE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about an exchange's historic revenue from reserves.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param start_time beginning of aggregated time interval
+ * @param end_time end of aggregated time interval
+ * @param reserve_profits total profits made
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_historic_reserve_revenue (struct AUDITORDB_PostgresContext *ctx,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Timestamp end_time,
+ const struct TALER_Amount *reserve_profits);
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_misattribution_in_inconsistency.h b/src/include/taler/auditor-database/insert_misattribution_in_inconsistency.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_INSERT_MISATTRIBUTION_IN_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_MISATTRIBUTION_IN_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_misattribution_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_MisattributionInInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_MISATTRIBUTION_IN_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_pending_deposit.h b/src/include/taler/auditor-database/insert_pending_deposit.h
@@ -0,0 +1,49 @@
+/*
+ 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 src/include/taler/auditor-database/insert_pending_deposit.h
+ * @brief implementation of the insert_pending_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_PENDING_DEPOSIT_H
+#define AUDITOR_DATABASE_INSERT_PENDING_DEPOSIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert new row into the pending deposits table.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param batch_deposit_serial_id where in the table are we
+ * @param total_amount value of all missing deposits, including fees
+ * @param wire_target_h_payto hash of the recipient account's payto URI
+ * @param deadline what was the requested wire transfer deadline
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_pending_deposit (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t batch_deposit_serial_id,
+ const struct TALER_FullPaytoHashP *wire_target_h_payto,
+ const struct TALER_Amount *total_amount,
+ struct GNUNET_TIME_Timestamp deadline);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_purse_info.h b/src/include/taler/auditor-database/insert_purse_info.h
@@ -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 src/include/taler/auditor-database/insert_purse_info.h
+ * @brief implementation of the insert_purse_info function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_PURSE_INFO_H
+#define AUDITOR_DATABASE_INSERT_PURSE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a purse. There must not be an
+ * existing record for the purse.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub public key of the purse
+ * @param balance balance of the purse
+ * @param expiration_date expiration date of the purse
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_purse_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_Amount *balance,
+ struct GNUNET_TIME_Timestamp expiration_date);
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_purse_not_closed_inconsistencies.h b/src/include/taler/auditor-database/insert_purse_not_closed_inconsistencies.h
@@ -0,0 +1,37 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_INSERT_PURSE_NOT_CLOSED_INCONSISTENCIES_H
+#define AUDITOR_DATABASE_INSERT_PURSE_NOT_CLOSED_INCONSISTENCIES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a purse not closed inconsistencies into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_purse_not_closed_inconsistencies (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_PurseNotClosedInconsistencies *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_PURSE_NOT_CLOSED_INCONSISTENCIES_H
diff --git a/src/include/taler/auditor-database/insert_reserve_balance_insufficient_inconsistency.h b/src/include/taler/auditor-database/insert_reserve_balance_insufficient_inconsistency.h
@@ -0,0 +1,37 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_INSERT_RESERVE_BALANCE_INSUFFICIENT_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_RESERVE_BALANCE_INSUFFICIENT_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a reserve balance inconsistency into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_balance_insufficient_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ReserveBalanceInsufficientInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_RESERVE_BALANCE_INSUFFICIENT_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_reserve_balance_summary_wrong_inconsistency.h b/src/include/taler/auditor-database/insert_reserve_balance_summary_wrong_inconsistency.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_INSERT_RESERVE_BALANCE_SUMMARY_WRONG_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_RESERVE_BALANCE_SUMMARY_WRONG_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_balance_summary_wrong_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ReserveBalanceSummaryWrongInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_RESERVE_BALANCE_SUMMARY_WRONG_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_reserve_in_inconsistency.h b/src/include/taler/auditor-database/insert_reserve_in_inconsistency.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_INSERT_RESERVE_IN_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_RESERVE_IN_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ReserveInInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_RESERVE_IN_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_reserve_info.h b/src/include/taler/auditor-database/insert_reserve_info.h
@@ -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 pg_insert_reserve_info.h
+ * @brief implementation of the insert_reserve_info function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_INSERT_RESERVE_INFO_H
+#define AUDITOR_DATABASE_INSERT_RESERVE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a reserve. There must not be an
+ * existing record for the reserve.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param rfb balance amounts for the reserve
+ * @param expiration_date when will the reserve expire
+ * @param origin_account where did the money in the reserve originally come from
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_AUDITORDB_ReserveFeeBalance *rfb,
+ struct GNUNET_TIME_Timestamp expiration_date,
+ const struct TALER_FullPayto origin_account);
+
+#endif
diff --git a/src/include/taler/auditor-database/insert_reserve_not_closed_inconsistency.h b/src/include/taler/auditor-database/insert_reserve_not_closed_inconsistency.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_INSERT_RESERVE_NOT_CLOSED_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_RESERVE_NOT_CLOSED_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_reserve_not_closed_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_ReserveNotClosedInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_RESERVE_NOT_CLOSED_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_row_inconsistency.h b/src/include/taler/auditor-database/insert_row_inconsistency.h
@@ -0,0 +1,37 @@
+/*
+ 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/>
+ */
+
+#ifndef AUDITOR_DATABASE_INSERT_ROW_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_ROW_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a deposit confirmation into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_row_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_RowInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_ROW_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_row_minor_inconsistencies.h b/src/include/taler/auditor-database/insert_row_minor_inconsistencies.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_INSERT_ROW_MINOR_INCONSISTENCIES_H
+#define AUDITOR_DATABASE_INSERT_ROW_MINOR_INCONSISTENCIES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_row_minor_inconsistencies (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_RowMinorInconsistencies *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_ROW_MINOR_INCONSISTENCIES_H
diff --git a/src/include/taler/auditor-database/insert_wire_format_inconsistency.h b/src/include/taler/auditor-database/insert_wire_format_inconsistency.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_INSERT_WIRE_FORMAT_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_WIRE_FORMAT_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_wire_format_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_WireFormatInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_WIRE_FORMAT_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/insert_wire_out_inconsistency.h b/src/include/taler/auditor-database/insert_wire_out_inconsistency.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+
+
+#ifndef AUDITOR_DATABASE_INSERT_WIRE_OUT_INCONSISTENCY_H
+#define AUDITOR_DATABASE_INSERT_WIRE_OUT_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a bad sig loss into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param dc deposit confirmation information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_insert_wire_out_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_AUDITORDB_WireOutInconsistency *dc);
+
+#endif // AUDITOR_DATABASE_INSERT_WIRE_OUT_INCONSISTENCY_H
diff --git a/src/include/taler/auditor-database/lookup_reserve_in_inconsistency.h b/src/include/taler/auditor-database/lookup_reserve_in_inconsistency.h
@@ -0,0 +1,38 @@
+/*
+ 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/>
+ */
+#ifndef AUDITOR_DATABASE_LOOKUP_RESERVE_IN_INCONSISTENCY_H
+#define AUDITOR_DATABASE_LOOKUP_RESERVE_IN_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Lookup information about reserve-in-inconsistency from the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param bank_row_id row of the transaction at the bank
+ * @param[out] dc set to the transaction details
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_lookup_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t bank_row_id,
+ struct TALER_AUDITORDB_ReserveInInconsistency *dc);
+
+#endif
diff --git a/src/include/taler/auditor-database/select_early_aggregations.h b/src/include/taler/auditor-database/select_early_aggregations.h
@@ -0,0 +1,99 @@
+/*
+ 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 src/include/taler/auditor-database/select_early_aggregations.h
+ * @brief implementation of the select_early_aggregations function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_SELECT_EARLY_AGGREGATIONS_H
+#define AUDITOR_DATABASE_SELECT_EARLY_AGGREGATIONS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Information about an early aggregation event.
+ */
+struct TALER_AUDITORDB_EarlyAggregation
+{
+ /**
+ * Row of the event in the auditor database.
+ */
+ uint64_t row_id;
+
+ /**
+ * Row of the batch deposit in the exchange database.
+ */
+ uint64_t batch_deposit_serial_id;
+
+ /**
+ * FIXME
+ */
+ uint64_t tracking_serial_id;
+
+ /**
+ * Total amount involved.
+ */
+ struct TALER_Amount total;
+
+ /**
+ * True if this report was previously suppressed.
+ */
+ bool suppressed;
+};
+
+
+/**
+ * Function to call with information about early aggregations.
+ *
+ * @param cls closure
+ * @param ea event data
+ * @return #GNUNET_OK to continue to iterate
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_EarlyAggregationsCallback)(
+ void *cls,
+ const struct TALER_AUDITORDB_EarlyAggregation *ea);
+
+/**
+ * Returns all aggregations that were found that were done
+ * too early.
+ *
+ * @param cls closure
+ * @param limit number of rows to return, negative to iterate backwards
+ * @param offset starting offset, exclusive
+ * @param return_suppressed true to also return suppressed events
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_early_aggregations (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_EarlyAggregationsCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/select_historic_denom_revenue.h b/src/include/taler/auditor-database/select_historic_denom_revenue.h
@@ -0,0 +1,93 @@
+/*
+ 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_historic_denom_revenue.h
+ * @brief implementation of the select_historic_denom_revenue function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_SELECT_HISTORIC_DENOM_REVENUE_H
+#define AUDITOR_DATABASE_SELECT_HISTORIC_DENOM_REVENUE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+/* Callback typedefs */
+/**
+ * @file include/taler/taler_auditordb_plugin.h
+ * @brief Low-level (statement-level) database access for the auditor
+ * @author Florian Dold
+ * @author Christian Grothoff
+ */
+#ifndef TALER_AUDITORDB_PLUGIN_H
+#define TALER_AUDITORDB_PLUGIN_H
+
+#include <jansson.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_db_lib.h>
+#include <taler/taler_util.h>
+#include <taler/taler_auditordb_lib.h>
+#include <taler/taler_signatures.h>
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Function called with the results of select_historic_denom_revenue()
+ *
+ * @param cls closure
+ * @param serial_id row for the denomination revenue in the auditor database
+ * @param denom_pub_hash hash of the denomination key
+ * @param revenue_timestamp when did this profit get realized
+ * @param revenue_balance what was the total profit made from
+ * deposit fees, melting fees, refresh fees
+ * and coins that were never returned?
+ * @param loss_balance what was the total loss
+ * @return sets the return value of select_denomination_info(),
+ * #GNUNET_OK to continue,
+ * #GNUNET_NO to stop processing further rows
+ * #GNUNET_SYSERR or other values on error.
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_HistoricDenominationRevenueDataCallback)(
+ void *cls,
+ uint64_t serial_id,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ struct GNUNET_TIME_Timestamp revenue_timestamp,
+ const struct TALER_Amount *revenue_balance,
+ const struct TALER_Amount *loss_balance);
+
+/**
+ * Obtain all of the historic denomination key revenue
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit return at most this number of results, negative to descend from @a offset
+ * @param offset row from which to return @a limit results
+ * @param cb function to call with the results
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_historic_denom_revenue (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/select_historic_reserve_revenue.h b/src/include/taler/auditor-database/select_historic_reserve_revenue.h
@@ -0,0 +1,73 @@
+/*
+ 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_historic_reserve_revenue.h
+ * @brief implementation of the select_historic_reserve_revenue function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_SELECT_HISTORIC_RESERVE_REVENUE_H
+#define AUDITOR_DATABASE_SELECT_HISTORIC_RESERVE_REVENUE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with the results of select_historic_reserve_revenue()
+ *
+ * @param cls closure
+ * @param serial_id row ID in the history table
+ * @param start_time beginning of aggregated time interval
+ * @param end_time end of aggregated time interval
+ * @param reserve_profits total profits made
+ *
+ * @return sets the return value of select_denomination_info(),
+ * #GNUNET_OK to continue,
+ * #GNUNET_NO to stop processing further rows
+ * #GNUNET_SYSERR or other values on error.
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_HistoricReserveRevenueDataCallback)(
+ void *cls,
+ uint64_t serial_id,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Timestamp end_time,
+ const struct TALER_Amount *reserve_profits);
+
+/**
+ * Return information about an exchange's historic revenue from reserves.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param limit return at most this number of results, negative to descend from @a offset
+ * @param offset row from which to return @a limit results
+ * @param cb function to call with results
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_historic_reserve_revenue (struct AUDITORDB_PostgresContext *ctx,
+ int64_t limit,
+ uint64_t offset,
+ TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/select_pending_deposits.h b/src/include/taler/auditor-database/select_pending_deposits.h
@@ -0,0 +1,78 @@
+/*
+ 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 src/include/taler/auditor-database/select_pending_deposits.h
+ * @brief implementation of the select_pending_deposits function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_SELECT_PENDING_DEPOSITS_H
+#define AUDITOR_DATABASE_SELECT_PENDING_DEPOSITS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called on deposits that are past their due date
+ * and have not yet seen a wire transfer.
+ *
+ * @param cls closure
+ * @param row_id row ID of the alert in the auditor database
+ * @param batch_deposit_serial_id where in the exchange table are we
+ * @param total_amount value of all missing deposits, including fees
+ * @param wire_target_h_payto hash of the recipient account's payto URI
+ * @param deadline what was the earliest requested wire transfer deadline
+ * @param suppressed true if this report was suppressed
+ */
+typedef void
+(*TALER_AUDITORDB_WireMissingCallback) (
+ void *cls,
+ uint64_t row_id,
+ uint64_t batch_deposit_serial_id,
+ const struct TALER_Amount *total_amount,
+ const struct TALER_FullPaytoHashP *wire_target_h_payto,
+ struct GNUNET_TIME_Timestamp deadline,
+ bool suppressed);
+
+/**
+ * Return (batch) deposits for which we have not yet
+ * seen the required wire transfer.
+ *
+ * @param cls closure
+ * @param deadline only return up to this deadline
+ * @param limit number of rows to return, negative to iterate backwards
+ * @param offset starting offset, exclusive
+ * @param return_suppressed true to also return suppressed events
+ * @param cb function to call on each entry
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_pending_deposits (struct AUDITORDB_PostgresContext *ctx,
+ struct GNUNET_TIME_Absolute deadline,
+ int64_t limit,
+ uint64_t offset,
+ bool return_suppressed,
+ TALER_AUDITORDB_WireMissingCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/select_purse_expired.h b/src/include/taler/auditor-database/select_purse_expired.h
@@ -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 src/include/taler/auditor-database/select_purse_expired.h
+ * @brief implementation of the select_purse_expired function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_SELECT_PURSE_EXPIRED_H
+#define AUDITOR_DATABASE_SELECT_PURSE_EXPIRED_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+
+
+struct AUDITORDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called on expired purses.
+ *
+ * @param cls closure
+ * @param purse_pub public key of the purse
+ * @param balance amount of money in the purse
+ * @param expiration_date when did the purse expire?
+ * @return #GNUNET_OK to continue to iterate
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_AUDITORDB_ExpiredPurseCallback)(
+ void *cls,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_Amount *balance,
+ struct GNUNET_TIME_Timestamp expiration_date);
+
+/**
+ * Get information about expired purses.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on expired purses
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_purse_expired (struct AUDITORDB_PostgresContext *ctx,
+ TALER_AUDITORDB_ExpiredPurseCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/auditor-database/select_reserve_in_inconsistency.h b/src/include/taler/auditor-database/select_reserve_in_inconsistency.h
@@ -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 src/include/taler/auditor-database/select_reserve_in_inconsistency.h
+ * @brief implementation of the select_reserve_in_inconsistency function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_SELECT_RESERVE_IN_INCONSISTENCY_H
+#define AUDITOR_DATABASE_SELECT_RESERVE_IN_INCONSISTENCY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Return any reserve incoming inconsistency associated with the
+ * given @a bank_row_id.
+ *
+ * @param cls closure
+ * @param bank_row_id row to select by
+ * @param[out] dc details to return
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_select_reserve_in_inconsistency (struct AUDITORDB_PostgresContext *ctx,
+ uint64_t bank_row_id,
+ struct TALER_AUDITORDB_ReserveInInconsistency *dc);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/template.h b/src/include/taler/auditor-database/template.h
@@ -0,0 +1,31 @@
+/*
+ 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 src/include/taler/auditor-database/template.h
+ * @brief implementation of the template function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_TEMPLATE_H
+#define AUDITOR_DATABASE_TEMPLATE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+#endif
diff --git a/src/include/taler/auditor-database/update_auditor_progress.h b/src/include/taler/auditor-database/update_auditor_progress.h
@@ -0,0 +1,47 @@
+/*
+ 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_update_auditor_progress.h
+ * @brief implementation of the update_auditor_progress function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_UPDATE_AUDITOR_PROGRESS_H
+#define AUDITOR_DATABASE_UPDATE_AUDITOR_PROGRESS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Update information about the progress of the auditor. There
+ * must be an existing record for the exchange.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param progress_key name of the progress indicator
+ * @param progress_offset offset until which we have made progress
+ * @param ... NULL terminated list of additional key-value pairs to update
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_auditor_progress (struct AUDITORDB_PostgresContext *ctx,
+ const char *progress_key,
+ uint64_t progress_offset,
+ ...);
+
+#endif
diff --git a/src/include/taler/auditor-database/update_balance.h b/src/include/taler/auditor-database/update_balance.h
@@ -0,0 +1,48 @@
+/*
+ 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 src/include/taler/auditor-database/update_balance.h
+ * @brief implementation of the update_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_UPDATE_BALANCE_H
+#define AUDITOR_DATABASE_UPDATE_BALANCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about a balance tracked by the auditor. Destructively updates an
+ * existing record, which must already exist.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param balance_key key of the balance to store
+ * @param balance_amount value to store
+ * @param ... NULL terminated list of additional key-value pairs to update
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_balance (struct AUDITORDB_PostgresContext *ctx,
+ const char *balance_key,
+ const struct TALER_Amount *balance_amount,
+ ...);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/update_denomination_balance.h b/src/include/taler/auditor-database/update_denomination_balance.h
@@ -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 pg_update_denomination_balance.h
+ * @brief implementation of the update_denomination_balance function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_UPDATE_DENOMINATION_BALANCE_H
+#define AUDITOR_DATABASE_UPDATE_DENOMINATION_BALANCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Update information about a denomination key's balances. There
+ * must be an existing record for the denomination key.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param denom_pub_hash hash of the denomination public key
+ * @param dcd circulation data to store
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_denomination_balance (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ const struct TALER_AUDITORDB_DenominationCirculationData *dcd);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/update_generic_suppressed.h b/src/include/taler/auditor-database/update_generic_suppressed.h
@@ -0,0 +1,41 @@
+/*
+ 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_update_auditor_progress.h
+ * @brief implementation of the update_auditor_progress function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_UPDATE_GENERIC_SUPPRESSED_H
+#define AUDITOR_DATABASE_UPDATE_GENERIC_SUPPRESSED_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ // FIXME: add comments
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_generic_suppressed (struct AUDITORDB_PostgresContext *ctx,
+ enum TALER_AUDITORDB_DeletableSuppressableTables table,
+ uint64_t row_id,
+ bool suppressed);
+
+#endif
diff --git a/src/include/taler/auditor-database/update_purse_info.h b/src/include/taler/auditor-database/update_purse_info.h
@@ -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 src/include/taler/auditor-database/update_purse_info.h
+ * @brief implementation of the update_purse_info function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_UPDATE_PURSE_INFO_H
+#define AUDITOR_DATABASE_UPDATE_PURSE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Update information about a purse. Destructively updates an
+ * existing record, which must already exist.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub public key of the purse
+ * @param balance new balance for the purse
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_purse_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_Amount *balance);
+
+
+#endif
diff --git a/src/include/taler/auditor-database/update_reserve_info.h b/src/include/taler/auditor-database/update_reserve_info.h
@@ -0,0 +1,47 @@
+/*
+ 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_update_reserve_info.h
+ * @brief implementation of the update_reserve_info function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_UPDATE_RESERVE_INFO_H
+#define AUDITOR_DATABASE_UPDATE_RESERVE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Update information about a reserve. Destructively updates an
+ * existing record, which must already exist.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param rfb amounts for the reserve
+ * @param expiration_date expiration date of the reserve
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_reserve_info (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_AUDITORDB_ReserveFeeBalance *rfb,
+ struct GNUNET_TIME_Timestamp expiration_date);
+
+#endif
diff --git a/src/include/taler/auditor-database/update_wire_fee_summary.h b/src/include/taler/auditor-database/update_wire_fee_summary.h
@@ -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 pg_update_wire_fee_summary.h
+ * @brief implementation of the update_wire_fee_summary function
+ * @author Christian Grothoff
+ */
+#ifndef AUDITOR_DATABASE_UPDATE_WIRE_FEE_SUMMARY_H
+#define AUDITOR_DATABASE_UPDATE_WIRE_FEE_SUMMARY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_auditordb_plugin.h"
+
+
+
+struct AUDITORDB_PostgresContext;
+/**
+ * Insert information about exchange's wire fee balance. Destructively updates an
+ * existing record, which must already exist.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param wire_fee_balance amount the exchange gained in wire fees
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+AUDITORDB_update_wire_fee_summary (struct AUDITORDB_PostgresContext *ctx,
+ const struct TALER_Amount *wire_fee_balance);
+
+#endif
diff --git a/src/include/taler/exchange-database/abort_shard.h b/src/include/taler/exchange-database/abort_shard.h
@@ -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 src/include/taler/exchange-database/abort_shard.h
+ * @brief implementation of the abort_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ABORT_SHARD_H
+#define EXCHANGE_DATABASE_ABORT_SHARD_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to abort work on a shard.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param job_name name of the operation to abort a word shard for
+ * @param start_row inclusive start row of the shard
+ * @param end_row exclusive end row of the shard
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_abort_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *job_name,
+ uint64_t start_row,
+ uint64_t end_row);
+
+#endif
diff --git a/src/include/taler/exchange-database/activate_signing_key.h b/src/include/taler/exchange-database/activate_signing_key.h
@@ -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 src/include/taler/exchange-database/activate_signing_key.h
+ * @brief implementation of the activate_signing_key function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ACTIVATE_SIGNING_KEY_H
+#define EXCHANGE_DATABASE_ACTIVATE_SIGNING_KEY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Add signing key.
+ *
+ * @param cls closure
+ * @param exchange_pub the exchange online signing public key
+ * @param meta meta data about @a exchange_pub
+ * @param master_sig master signature to add
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_activate_signing_key (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ const struct TALER_EXCHANGEDB_SignkeyMetaData *meta,
+ const struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/include/taler/exchange-database/add_denomination_key.h b/src/include/taler/exchange-database/add_denomination_key.h
@@ -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 src/include/taler/exchange-database/add_denomination_key.h
+ * @brief implementation of the add_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ADD_DENOMINATION_KEY_H
+#define EXCHANGE_DATABASE_ADD_DENOMINATION_KEY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Activate denomination key, turning it into a "current" or "valid"
+ * denomination key by adding the master signature.
+ *
+ * @param cls closure
+ * @param h_denom_pub hash of the denomination public key
+ * @param denom_pub the actual denomination key
+ * @param meta meta data about the denomination
+ * @param master_sig master signature to add
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_add_denomination_key (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/add_policy_fulfillment_proof.h b/src/include/taler/exchange-database/add_policy_fulfillment_proof.h
@@ -0,0 +1,40 @@
+/*
+ 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 src/include/taler/exchange-database/add_policy_fulfillment_proof.h
+ * @brief implementation of the add_policy_fulfillment_proof function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ADD_POLICY_FULFILLMENT_PROOF_H
+#define EXCHANGE_DATABASE_ADD_POLICY_FULFILLMENT_PROOF_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Add a proof of fulfillment into the policy_fulfillments table
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param fulfillment fullfilment transaction data to be added
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_add_policy_fulfillment_proof (struct EXCHANGEDB_PostgresContext *ctx,
+ struct TALER_PolicyFulfillmentTransactionData *fulfillment);
+
+#endif
diff --git a/src/include/taler/exchange-database/aggregate.h b/src/include/taler/exchange-database/aggregate.h
@@ -0,0 +1,47 @@
+/*
+ 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 src/include/taler/exchange-database/aggregate.h
+ * @brief implementation of the aggregate function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_AGGREGATE_H
+#define EXCHANGE_DATABASE_AGGREGATE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Aggregate all matching deposits for @a h_payto and
+ * @a merchant_pub, returning the total amounts.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param merchant_pub public key of the merchant
+ * @param wtid wire transfer ID to set for the aggregate
+ * @param[out] total set to the sum of the total deposits minus applicable deposit fees and refunds
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_aggregate (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_FullPaytoHashP *h_payto,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ struct TALER_Amount *total);
+
+#endif
diff --git a/src/include/taler/exchange-database/batch_ensure_coin_known.h b/src/include/taler/exchange-database/batch_ensure_coin_known.h
@@ -0,0 +1,48 @@
+/*
+ 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 src/include/taler/exchange-database/batch_ensure_coin_known.h
+ * @brief implementation of the batch_ensure_coin_known function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_BATCH_ENSURE_COIN_KNOWN_H
+#define EXCHANGE_DATABASE_BATCH_ENSURE_COIN_KNOWN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Make sure the array of given @a coin is known to the database.
+ *
+ * @param cls database connection plugin state
+ * @param coin array of coins that must be made known
+ * @param[out] result array where to store information about each coin
+ * @param coin_length length of the @a coin and @a result arraysf
+ * @param batch_size desired (maximum) batch size
+ * @return database transaction status, non-negative on success
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_batch_ensure_coin_known (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_CoinPublicInfo *coin,
+ struct TALER_EXCHANGEDB_CoinInfo *result,
+ unsigned int coin_length,
+ unsigned int batch_size);
+
+#endif
diff --git a/src/include/taler/exchange-database/begin_revolving_shard.h b/src/include/taler/exchange-database/begin_revolving_shard.h
@@ -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 src/include/taler/exchange-database/begin_revolving_shard.h
+ * @brief implementation of the begin_revolving_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_BEGIN_REVOLVING_SHARD_H
+#define EXCHANGE_DATABASE_BEGIN_REVOLVING_SHARD_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to grab a revolving work shard on an operation @a op. Runs
+ * in its own transaction. Returns the oldest inactive shard.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param job_name name of the operation to grab a revolving shard for
+ * @param shard_size desired shard size
+ * @param shard_limit exclusive end of the shard range
+ * @param[out] start_row inclusive start row of the shard (returned)
+ * @param[out] end_row inclusive end row of the shard (returned)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_begin_revolving_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *job_name,
+ uint32_t shard_size,
+ uint32_t shard_limit,
+ uint32_t *start_row,
+ uint32_t *end_row);
+
+#endif
diff --git a/src/include/taler/exchange-database/begin_shard.h b/src/include/taler/exchange-database/begin_shard.h
@@ -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 src/include/taler/exchange-database/begin_shard.h
+ * @brief implementation of the begin_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_BEGIN_SHARD_H
+#define EXCHANGE_DATABASE_BEGIN_SHARD_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to grab a work shard on an operation @a op. Runs in its
+ * own transaction.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param job_name name of the operation to grab a word shard for
+ * @param delay minimum age of a shard to grab
+ * @param shard_size desired shard size
+ * @param[out] start_row inclusive start row of the shard (returned)
+ * @param[out] end_row exclusive end row of the shard (returned)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_begin_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *job_name,
+ struct GNUNET_TIME_Relative delay,
+ uint64_t shard_size,
+ uint64_t *start_row,
+ uint64_t *end_row);
+
+#endif
diff --git a/src/include/taler/exchange-database/clear_aml_lock.h b/src/include/taler/exchange-database/clear_aml_lock.h
@@ -0,0 +1,47 @@
+/*
+ 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 src/include/taler/exchange-database/clear_aml_lock.h
+ * @brief implementation of the clear_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_CLEAR_AML_LOCK_H
+#define EXCHANGE_DATABASE_CLEAR_AML_LOCK_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Clear a lock on running AML programs for the @a h_payto
+ * account. Returns 0 if @a h_payto is not known; does not
+ * actually care if there was a lock. Also does not by
+ * itself notify clients waiting for the lock, that
+ * notification the caller must do separately after finishing
+ * the database update.
+ *
+ * @param cls closure
+ * @param h_payto account to clear the lock for
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_clear_aml_lock (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto);
+
+#endif
diff --git a/src/include/taler/exchange-database/commit.h b/src/include/taler/exchange-database/commit.h
@@ -0,0 +1,39 @@
+/*
+ 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 src/include/taler/exchange-database/commit.h
+ * @brief implementation of the commit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_COMMIT_H
+#define EXCHANGE_DATABASE_COMMIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Commit the current transaction of a database connection.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @return final transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_commit (struct EXCHANGEDB_PostgresContext *ctx);
+
+#endif
diff --git a/src/include/taler/exchange-database/complete_shard.h b/src/include/taler/exchange-database/complete_shard.h
@@ -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 src/include/taler/exchange-database/complete_shard.h
+ * @brief implementation of the complete_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_COMPLETE_SHARD_H
+#define EXCHANGE_DATABASE_COMPLETE_SHARD_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to persist that work on a shard was completed.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param job_name name of the operation to grab a word shard for
+ * @param start_row inclusive start row of the shard
+ * @param end_row exclusive end row of the shard
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_complete_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *job_name,
+ uint64_t start_row,
+ uint64_t end_row);
+
+#endif
diff --git a/src/include/taler/exchange-database/compute_shard.h b/src/include/taler/exchange-database/compute_shard.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/compute_shard.h
+ * @brief implementation of the compute_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_COMPUTE_SHARD_H
+#define EXCHANGE_DATABASE_COMPUTE_SHARD_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Compute the shard number of a given @a merchant_pub.
+ *
+ * @param merchant_pub merchant public key to compute shard for
+ * @return shard number
+ */
+uint64_t
+EXCHANGEDB_compute_shard (const struct TALER_MerchantPublicKeyP *merchant_pub);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/count_known_coins.h b/src/include/taler/exchange-database/count_known_coins.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/count_known_coins.h
+ * @brief implementation of the count_known_coins function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_COUNT_KNOWN_COINS_H
+#define EXCHANGE_DATABASE_COUNT_KNOWN_COINS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Count the number of known coins by denomination.
+ *
+ * @param cls database connection plugin state
+ * @param denom_pub_hash denomination to count by
+ * @return number of coins if non-negative, otherwise an `enum GNUNET_DB_QueryStatus`
+ */
+long long
+EXCHANGEDB_count_known_coins (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct
+ TALER_DenominationHashP *denom_pub_hash);
+
+#endif
diff --git a/src/include/taler/exchange-database/create_aggregation_transient.h b/src/include/taler/exchange-database/create_aggregation_transient.h
@@ -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 src/include/taler/exchange-database/create_aggregation_transient.h
+ * @brief implementation of the create_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_CREATE_AGGREGATION_TRANSIENT_H
+#define EXCHANGE_DATABASE_CREATE_AGGREGATION_TRANSIENT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Create a new entry in the transient aggregation table.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param exchange_account_section exchange account to use
+ * @param merchant_pub public key of the merchant receiving the transfer
+ * @param wtid the raw wire transfer identifier to be used
+ * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none
+ * @param total amount to be wired in the future
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_create_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/create_tables.h b/src/include/taler/exchange-database/create_tables.h
@@ -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 src/include/taler/exchange-database/create_tables.h
+ * @brief implementation of the create_tables function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_CREATE_TABLES_H
+#define EXCHANGE_DATABASE_CREATE_TABLES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Create the necessary tables if they are not present
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param support_partitions true to enable partitioning support (disables foreign key constraints)
+ * @param num_partitions number of partitions to create,
+ * (0 to not actually use partitions, 1 to only
+ * setup a default partition, >1 for real partitions)
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_create_tables (struct EXCHANGEDB_PostgresContext *ctx,
+ bool support_partitions,
+ uint32_t num_partitions);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/delete_aggregation_transient.h b/src/include/taler/exchange-database/delete_aggregation_transient.h
@@ -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 src/include/taler/exchange-database/delete_aggregation_transient.h
+ * @brief implementation of the delete_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DELETE_AGGREGATION_TRANSIENT_H
+#define EXCHANGE_DATABASE_DELETE_AGGREGATION_TRANSIENT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Delete existing entry in the transient aggregation table.
+ * @a h_payto is only needed for query performance.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param wtid the raw wire transfer identifier to update
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_delete_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_FullPaytoHashP *h_payto,
+ const struct TALER_WireTransferIdentifierRawP *wtid);
+
+#endif
diff --git a/src/include/taler/exchange-database/delete_shard_locks.h b/src/include/taler/exchange-database/delete_shard_locks.h
@@ -0,0 +1,40 @@
+/*
+ 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 src/include/taler/exchange-database/delete_shard_locks.h
+ * @brief implementation of the delete_shard_locks function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DELETE_SHARD_LOCKS_H
+#define EXCHANGE_DATABASE_DELETE_SHARD_LOCKS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to delete all revolving shards.
+ * To be used after a crash or when the shard size is
+ * changed.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @return transaction status code
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_delete_shard_locks (struct EXCHANGEDB_PostgresContext *ctx);
+
+#endif
diff --git a/src/include/taler/exchange-database/disable_rules.h b/src/include/taler/exchange-database/disable_rules.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/disable_rules.h
+ * @brief implementation of the disable_rules function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DISABLE_RULES_H
+#define EXCHANGE_DATABASE_DISABLE_RULES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Disable (delete/drop) customization rule schema from a deployment.
+ *
+ * @param cls closure
+ * @param schema name of the schema with customization rules to remove
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_disable_rules (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *schema);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_check_deposit_idempotent.h b/src/include/taler/exchange-database/do_check_deposit_idempotent.h
@@ -0,0 +1,46 @@
+/*
+ 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 src/include/taler/exchange-database/do_check_deposit_idempotent.h
+ * @brief implementation of the do_check_deposit_idempotent function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_CHECK_DEPOSIT_IDEMPOTENT_H
+#define EXCHANGE_DATABASE_DO_CHECK_DEPOSIT_IDEMPOTENT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Check ifdeposit operation is idempotent to existing one.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param bd batch deposit operation details
+ * @param[in,out] exchange_timestamp time to use for the deposit (possibly updated)
+ * @param[out] is_idempotent set to true if the request is idempotent
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_check_deposit_idempotent (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_EXCHANGEDB_BatchDeposit *bd,
+ struct GNUNET_TIME_Timestamp *exchange_timestamp,
+ bool *is_idempotent);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_deposit.h b/src/include/taler/exchange-database/do_deposit.h
@@ -0,0 +1,58 @@
+/*
+ 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 src/include/taler/exchange-database/do_deposit.h
+ * @brief implementation of the do_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_DEPOSIT_H
+#define EXCHANGE_DATABASE_DO_DEPOSIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Perform deposit operation, checking for sufficient balance
+ * of the coins and possibly persisting the deposit details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param bd batch deposit operation details
+ * @param deposit_fees array of "bd->num_cids" deposit fees
+ * of the respective coins
+ * @param[in,out] exchange_timestamp time to use for the deposit (possibly updated)
+ * @param[out] accumulated_total_without_fee set to the sum of all deposits
+ * made for this merchant and contract (minus deposit fees)
+ * @param[out] balance_ok set to true if the balance was sufficient
+ * @param[out] bad_balance_index set to the first index of a coin for which the balance was insufficient,
+ * only used if @a balance_ok is set to false.
+ * @param[out] in_conflict set to true if the deposit conflicted
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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 *in_conflict);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_purse_delete.h b/src/include/taler/exchange-database/do_purse_delete.h
@@ -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 src/include/taler/exchange-database/do_purse_delete.h
+ * @brief implementation of the do_purse_delete function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_PURSE_DELETE_H
+#define EXCHANGE_DATABASE_DO_PURSE_DELETE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to explicitly delete a purse.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub purse to delete
+ * @param purse_sig signature affirming the deletion
+ * @param[out] decided set to true if the purse was
+ * already decided and thus could not be deleted
+ * @param[out] found set to true if the purse was found
+ * (if false, purse could not be deleted)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_purse_delete (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PurseContractSignatureP *purse_sig,
+ bool *decided,
+ bool *found);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_purse_deposit.h b/src/include/taler/exchange-database/do_purse_deposit.h
@@ -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 src/include/taler/exchange-database/do_purse_deposit.h
+ * @brief implementation of the do_purse_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_PURSE_DEPOSIT_H
+#define EXCHANGE_DATABASE_DO_PURSE_DEPOSIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to execute a transaction crediting
+ * a purse with @a amount from @a coin_pub. Reduces the
+ * value of @a coin_pub and increase the balance of
+ * the @a purse_pub purse. If the balance reaches the
+ * target amount and the purse has been merged, triggers
+ * the updates of the reserve/account balance.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub purse to credit
+ * @param coin_pub coin to deposit (debit)
+ * @param amount fraction of the coin's value to deposit
+ * @param coin_sig signature affirming the operation
+ * @param amount_minus_fee amount to add to the purse
+ * @param[out] balance_ok set to false if the coin's
+ * remaining balance is below @a amount;
+ * in this case, the return value will be
+ * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure
+ * @param[out] too_late set to true if it is too late to deposit into the purse
+ * @param[out] conflict set to true if the deposit failed due to a conflict (coin already spent,
+ * or deposited into this purse with a different amount)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_purse_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_purse_merge.h b/src/include/taler/exchange-database/do_purse_merge.h
@@ -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 src/include/taler/exchange-database/do_purse_merge.h
+ * @brief implementation of the do_purse_merge function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_PURSE_MERGE_H
+#define EXCHANGE_DATABASE_DO_PURSE_MERGE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to approve merging a purse into a
+ * reserve by the respective purse merge key.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @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 partner_url URL of the partner exchange, can be NULL if the reserves lives with us
+ * @param reserve_pub public key of the reserve to credit
+ * @param[out] no_partner set to true if @a partner_url is unknown
+ * @param[out] no_balance set to true if the @a purse_pub is not paid up yet
+ * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_purse_merge (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_recoup.h b/src/include/taler/exchange-database/do_recoup.h
@@ -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 src/include/taler/exchange-database/do_recoup.h
+ * @brief implementation of the do_recoup function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_RECOUP_H
+#define EXCHANGE_DATABASE_DO_RECOUP_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Perform recoup operation, checking for sufficient deposits
+ * of the coin and possibly persisting the recoup details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve to credit
+ * @param withdraw_serial_id row in the withdraw table justifying the recoup
+ * @param coin_bks coin blinding key secret to persist
+ * @param coin_pub public key of the coin being recouped
+ * @param known_coin_id row of the @a coin_pub in the known_coins table
+ * @param coin_sig signature of the coin requesting the recoup
+ * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed
+ * @param[out] recoup_ok set if the recoup succeeded (balance ok)
+ * @param[out] internal_failure set on internal failures
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_recoup (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ uint64_t withdraw_serial_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);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_recoup_refresh.h b/src/include/taler/exchange-database/do_recoup_refresh.h
@@ -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 src/include/taler/exchange-database/do_recoup_refresh.h
+ * @brief implementation of the do_recoup_refresh function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_RECOUP_REFRESH_H
+#define EXCHANGE_DATABASE_DO_RECOUP_REFRESH_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Perform recoup-refresh operation, checking for sufficient deposits of the
+ * coin and possibly persisting the recoup-refresh details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param old_coin_pub public key of the old coin to credit
+ * @param rrc_serial row in the refresh_revealed_coins table justifying the recoup-refresh
+ * @param coin_bks coin blinding key secret to persist
+ * @param coin_pub public key of the coin being recouped
+ * @param known_coin_id row of the @a coin_pub in the known_coins table
+ * @param coin_sig signature of the coin requesting the recoup
+ * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed
+ * @param[out] recoup_ok set if the recoup-refresh succeeded (balance ok)
+ * @param[out] internal_failure set on internal failures
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_recoup_refresh (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+ uint64_t rrc_serial,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_refresh.h b/src/include/taler/exchange-database/do_refresh.h
@@ -0,0 +1,58 @@
+/*
+ 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 src/include/taler/exchange-database/do_refresh.h
+ * @brief implementation of the do_refresh function for Postgres
+ * @author Özgür Kesim
+ */
+#ifndef EXCHANGE_DATABASE_DO_REFRESH_H
+#define EXCHANGE_DATABASE_DO_REFRESH_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Perform refresh operation--introduced with v26 of the API--,
+ * checking for sufficient balance of the coin and possibly persisting the melt/refresh details.
+ *
+ * @param cls the plugin-specific state
+ * @param[in,out] refresh refresh operation details; the noreveal_index
+ * is set in case the coin was already melted before
+ * @param timestamp the timestamp of this melt operation, helpful for the coin history.
+ * @param[in,out] zombie_required true if the melt must only succeed
+ * if the coin is a zombie, set to false if the requirement was satisfied
+ * @param[out] found set to true if there exists already an entry in the database for
+ * the calculated commitment hash.
+ * @param[out] noreveal_index if @e idempotent ist true, the existing value of the noreveal_index.
+ * @param[out] nonce_reuse set to true if the blinding seed for CS was re-used.
+ * @param[out] balance_ok set to true if the balance was sufficient
+ * @param[out] coin_balance if balance_ok is false, set to the remaining value of the coin
+ * @return query execution status, NO_RESULTS in case of an unknown coin.
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_refresh (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_refund.h b/src/include/taler/exchange-database/do_refund.h
@@ -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 src/include/taler/exchange-database/do_refund.h
+ * @brief implementation of the do_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_REFUND_H
+#define EXCHANGE_DATABASE_DO_REFUND_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Perform refund operation, checking for sufficient deposits
+ * of the coin and possibly persisting the refund details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param refund refund operation details
+ * @param deposit_fee deposit fee applicable for the coin, possibly refunded
+ * @param known_coin_id row of the coin in the known_coins table
+ * @param[out] not_found set if the deposit was not found
+ * @param[out] refund_ok set if the refund succeeded (below deposit amount)
+ * @param[out] gone if the merchant was already paid
+ * @param[out] conflict set if the refund ID was reused
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_refund (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_reserve_open.h b/src/include/taler/exchange-database/do_reserve_open.h
@@ -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 pg_do_reserve_open.h
+ * @brief implementation of the do_reserve_open function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_RESERVE_OPEN_H
+#define EXCHANGE_DATABASE_DO_RESERVE_OPEN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Perform reserve open operation on database.
+ *
+ * @param cls closure
+ * @param reserve_pub which reserve is this about?
+ * @param total_paid total amount paid (coins and reserve)
+ * @param reserve_payment amount to be paid from the reserve
+ * @param min_purse_limit minimum number of purses we should be able to open
+ * @param reserve_sig signature by the reserve for the operation
+ * @param desired_expiration when should the reserve expire (earliest time)
+ * @param now when did we the client initiate the action
+ * @param open_fee annual fee to be charged for the open operation by the exchange
+ * @param[out] no_funds set to true if reserve balance is insufficient
+ * @param[out] reserve_balance set to the original reserve balance (at the start of this transaction)
+ * @param[out] open_cost set to the actual cost
+ * @param[out] final_expiration when will the reserve expire now
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_reserve_open (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/do_reserve_purse.h b/src/include/taler/exchange-database/do_reserve_purse.h
@@ -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 src/include/taler/exchange-database/do_reserve_purse.h
+ * @brief implementation of the do_reserve_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DO_RESERVE_PURSE_H
+#define EXCHANGE_DATABASE_DO_RESERVE_PURSE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * 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 cls the @e cls of this struct with the plugin-specific state
+ * @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
+EXCHANGEDB_do_reserve_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/do_withdraw.h b/src/include/taler/exchange-database/do_withdraw.h
@@ -0,0 +1,60 @@
+/*
+ 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 src/include/taler/exchange-database/do_withdraw.h
+ * @brief implementation of the do_withdraw function for Postgres
+ * @author Özgür Kesim
+ */
+#ifndef EXCHANGE_DATABASE_DO_WITHDRAW_H
+#define EXCHANGE_DATABASE_DO_WITHDRAW_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Perform reserve update as part of an age-withdraw operation, checking for
+ * sufficient balance and fulfillment of age requirements. Finally persisting
+ * the withdrawal details.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param withdraw the withdraw data
+ * @param now the timestamp of the withdraw
+ * @param[out] balance_ok set to true if the balance was sufficient
+ * @param[out] reserve_balance set to original balance of the reserve
+ * @param[out] age_ok set to true if age requirements were met
+ * @param[out] allowed_maximum_age if @e age_ok is FALSE, this is set to the allowed maximum age
+ * @param[out] reserve_birthday if @e age_ok is FALSE, this is set to the reserve's birthday
+ * @param[out] idempotent set to true if an entry already exists for the given h_planchets and reserve_pub
+ * @param[out] noreveal_index if @e idempotent is true, set to the noreveal_index in the existing record
+ * @param[out] nonce_reuse set to true if the blinding_seed has been found in the table for a different withdraw
+ * @return 0 if no reserve was found, 1 if a reserve was found, else the query execution status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_do_withdraw (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_EXCHANGEDB_Withdraw *withdraw,
+ const struct GNUNET_TIME_Timestamp *now,
+ bool *balance_ok,
+ struct TALER_Amount *reserve_balance,
+ bool *age_ok,
+ uint16_t *allowed_maximum_age,
+ uint32_t *reserve_birthday,
+ bool *idempotent,
+ uint16_t *noreveal_index,
+ bool *nonce_reuse);
+
+#endif
diff --git a/src/include/taler/exchange-database/drain_kyc_alert.h b/src/include/taler/exchange-database/drain_kyc_alert.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/drain_kyc_alert.h
+ * @brief implementation of the drain_kyc_alert function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DRAIN_KYC_ALERT_H
+#define EXCHANGE_DATABASE_DRAIN_KYC_ALERT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Extract next KYC alert. Deletes the alert.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param trigger_type which type of alert to drain
+ * @param[out] h_payto set to hash of payto-URI where KYC status changed
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_drain_kyc_alert (struct EXCHANGEDB_PostgresContext *ctx,
+ uint32_t trigger_type,
+ struct TALER_NormalizedPaytoHashP *h_payto);
+
+#endif
diff --git a/src/include/taler/exchange-database/drop_tables.h b/src/include/taler/exchange-database/drop_tables.h
@@ -0,0 +1,40 @@
+/*
+ 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 src/include/taler/exchange-database/drop_tables.h
+ * @brief implementation of the drop_tables function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_DROP_TABLES_H
+#define EXCHANGE_DATABASE_DROP_TABLES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Drop all Taler tables. This should only be used by testcases.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_drop_tables (struct EXCHANGEDB_PostgresContext *ctx);
+
+#endif
diff --git a/src/include/taler/exchange-database/enable_rules.h b/src/include/taler/exchange-database/enable_rules.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/enable_rules.h
+ * @brief implementation of the enable_rules function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ENABLE_RULES_H
+#define EXCHANGE_DATABASE_ENABLE_RULES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Enable (create/insert) customization rule schema from a deployment.
+ *
+ * @param cls closure
+ * @param schema name of the schema with customization rules to remove
+ * @return transaction status
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_enable_rules (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *schema);
+
+#endif
diff --git a/src/include/taler/exchange-database/ensure_coin_known.h b/src/include/taler/exchange-database/ensure_coin_known.h
@@ -0,0 +1,47 @@
+/*
+ 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 src/include/taler/exchange-database/ensure_coin_known.h
+ * @brief implementation of the ensure_coin_known function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ENSURE_COIN_KNOWN_H
+#define EXCHANGE_DATABASE_ENSURE_COIN_KNOWN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Make sure the given @a coin is known to the database.
+ *
+ * @param cls database connection plugin state
+ * @param coin the coin that must be made known
+ * @param[out] known_coin_id set to the unique row of the coin
+ * @param[out] denom_hash set to the denomination hash of the existing
+ * coin (for conflict error reporting)
+ * @param[out] h_age_commitment set to the conflicting age commitment hash on conflict
+ * @return database transaction status, non-negative on success
+ */
+enum TALER_EXCHANGEDB_CoinKnownStatus
+EXCHANGEDB_ensure_coin_known (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_CoinPublicInfo *coin,
+ uint64_t *known_coin_id,
+ struct TALER_DenominationHashP *denom_hash,
+ struct TALER_AgeCommitmentHashP *h_age_commitment);
+
+#endif
diff --git a/src/include/taler/exchange-database/event_listen.h b/src/include/taler/exchange-database/event_listen.h
@@ -0,0 +1,47 @@
+/*
+ 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 src/include/taler/exchange-database/event_listen.h
+ * @brief implementation of the event_listen function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_EVENT_LISTEN_H
+#define EXCHANGE_DATABASE_EVENT_LISTEN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Register callback to be invoked on events of type @a es.
+ *
+ * @param cls database context to use
+ * @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 *
+EXCHANGEDB_event_listen (struct EXCHANGEDB_PostgresContext *ctx,
+ struct GNUNET_TIME_Relative timeout,
+ const struct GNUNET_DB_EventHeaderP *es,
+ GNUNET_DB_EventCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/event_listen_cancel.h b/src/include/taler/exchange-database/event_listen_cancel.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/event_listen_cancel.h
+ * @brief implementation of the event_listen_cancel function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_EVENT_LISTEN_CANCEL_H
+#define EXCHANGE_DATABASE_EVENT_LISTEN_CANCEL_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Stop notifications.
+ *
+ * @param cls the plugin's `struct PostgresClosure`
+ * @param eh handle to unregister.
+ */
+void
+EXCHANGEDB_event_listen_cancel (struct EXCHANGEDB_PostgresContext *ctx,
+ struct GNUNET_DB_EventHandler *eh);
+
+#endif
diff --git a/src/include/taler/exchange-database/event_notify.h b/src/include/taler/exchange-database/event_notify.h
@@ -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 src/include/taler/exchange-database/event_notify.h
+ * @brief implementation of the event_notify function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_EVENT_NOTIFY_H
+#define EXCHANGE_DATABASE_EVENT_NOTIFY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Notify all that listen on @a es of an event.
+ *
+ * @param cls database context to use
+ * @param es specification of the event to generate
+ * @param extra additional event data provided
+ * @param extra_size number of bytes in @a extra
+ */
+void
+EXCHANGEDB_event_notify (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct GNUNET_DB_EventHeaderP *es,
+ const void *extra,
+ size_t extra_size);
+
+#endif
diff --git a/src/include/taler/exchange-database/expire_purse.h b/src/include/taler/exchange-database/expire_purse.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/expire_purse.h
+ * @brief implementation of the expire_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_EXPIRE_PURSE_H
+#define EXCHANGE_DATABASE_EXPIRE_PURSE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to clean up one expired purse.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param start_time select purse expired after this time
+ * @param end_time select purse expired before this time
+ * @return transaction status code (#GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no purse expired in the given time interval).
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_expire_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ struct GNUNET_TIME_Absolute start_time,
+ struct GNUNET_TIME_Absolute end_time);
+
+#endif
diff --git a/src/include/taler/exchange-database/find_aggregation_transient.h b/src/include/taler/exchange-database/find_aggregation_transient.h
@@ -0,0 +1,48 @@
+/*
+ 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 src/include/taler/exchange-database/find_aggregation_transient.h
+ * @brief implementation of the find_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_FIND_AGGREGATION_TRANSIENT_H
+#define EXCHANGE_DATABASE_FIND_AGGREGATION_TRANSIENT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Find existing entry in the transient aggregation table.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param[out] payto_uri corresponding payto URI, to be freed by caller
+ * @param[out] wtid wire transfer identifier of transient aggregation
+ * @param[out] merchant_pub public key of the merchant
+ * @param[out] total amount aggregated so far
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_find_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct TALER_FullPayto *payto_uri,
+ struct TALER_WireTransferIdentifierRawP *wtid,
+ struct TALER_MerchantPublicKeyP *merchant_pub,
+ struct TALER_Amount *total);
+
+#endif
diff --git a/src/include/taler/exchange-database/gc.h b/src/include/taler/exchange-database/gc.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/gc.h
+ * @brief implementation of the gc function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GC_H
+#define EXCHANGE_DATABASE_GC_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to perform "garbage collection" on the
+ * database, expiring records we no longer require.
+ *
+ * @param cls closure
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR on DB errors
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_gc (struct EXCHANGEDB_PostgresContext *ctx);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_coin_denomination.h b/src/include/taler/exchange-database/get_coin_denomination.h
@@ -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 src/include/taler/exchange-database/get_coin_denomination.h
+ * @brief implementation of the get_coin_denomination function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_COIN_DENOMINATION_H
+#define EXCHANGE_DATABASE_GET_COIN_DENOMINATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Retrieve the denomination of a known coin.
+ *
+ * @param cls the plugin closure
+ * @param coin_pub the public key of the coin to search for
+ * @param[out] known_coin_id set to the ID of the coin in the known_coins table
+ * @param[out] denom_hash where to store the hash of the coins denomination
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_coin_denomination (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ uint64_t *known_coin_id,
+ struct TALER_DenominationHashP *denom_hash);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_coin_transactions.h b/src/include/taler/exchange-database/get_coin_transactions.h
@@ -0,0 +1,64 @@
+/*
+ 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.h
+ * @brief implementation of the get_coin_transactions function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_COIN_TRANSACTIONS_H
+#define EXCHANGE_DATABASE_GET_COIN_TRANSACTIONS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Compile a list of (historic) transactions performed with the given coin
+ * (melt, refund, recoup and deposit operations). Should return 0 if the @a
+ * coin_pub is unknown, otherwise determine @a etag_out and if it is past @a
+ * etag_in return the history after @a start_off. @a etag_out should be set
+ * to the last row ID of the given @a coin_pub in the coin history table.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param begin_transaction true to run this in its own transaction(s)
+ * @param coin_pub coin to investigate
+ * @param start_off starting offset from which on to return entries
+ * @param etag_in up to this offset the client already has a response, do not
+ * return anything unless @a etag_out will be larger
+ * @param[out] etag_out set to the latest history offset known for this @a coin_pub
+ * @param[out] balance set to current balance of the coin
+ * @param[out] h_denom_pub set to denomination public key of the coin
+ * @param[out] tlp set to list of transactions, set to NULL if coin has no
+ * transaction history past @a start_off or if @a etag_in is equal
+ * to the value written to @a etag_out.
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_coin_transactions (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/get_denomination_by_serial.h b/src/include/taler/exchange-database/get_denomination_by_serial.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/get_denomination_by_serial.h
+ * @brief implementation of the get_denomination_by_serial function for Postgres
+ * @author Özgür Kesim
+ */
+#ifndef EXCHANGE_DATABASE_GET_DENOMINATION_BY_SERIAL_H
+#define EXCHANGE_DATABASE_GET_DENOMINATION_BY_SERIAL_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Fetch information about a denomination for a given serial.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param denom_serial row in the denomination table
+ * @param[out] issue set to issue information with value, fees and other info about the coin
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_denomination_by_serial (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t denom_serial,
+ struct TALER_EXCHANGEDB_DenominationKeyInformation *issue);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_denomination_info.h b/src/include/taler/exchange-database/get_denomination_info.h
@@ -0,0 +1,45 @@
+/*
+ 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 src/include/taler/exchange-database/get_denomination_info.h
+ * @brief implementation of the get_denomination_info function for Postgres
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#ifndef EXCHANGE_DATABASE_GET_DENOMINATION_INFO_H
+#define EXCHANGE_DATABASE_GET_DENOMINATION_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Fetch information about a denomination key.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param denom_pub_hash hash of the public key used for signing coins of this denomination
+ * @param[out] denom_serial row in the denomination table, might be NULL
+ * @param[out] issue set to issue information with value, fees and other info about the coin
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_denomination_info (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ uint64_t *denom_serial,
+ struct TALER_EXCHANGEDB_DenominationKeyInformation *issue);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_denomination_revocation.h b/src/include/taler/exchange-database/get_denomination_revocation.h
@@ -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 src/include/taler/exchange-database/get_denomination_revocation.h
+ * @brief implementation of the get_denomination_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_DENOMINATION_REVOCATION_H
+#define EXCHANGE_DATABASE_GET_DENOMINATION_REVOCATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Obtain information about a denomination key's revocation from
+ * the database.
+ *
+ * @param cls closure
+ * @param denom_pub_hash hash of the revoked denomination key
+ * @param[out] master_sig signature affirming the revocation
+ * @param[out] rowid row where the information is stored
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_denomination_revocation (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ struct TALER_MasterSignatureP *master_sig,
+ uint64_t *rowid);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_drain_profit.h b/src/include/taler/exchange-database/get_drain_profit.h
@@ -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 src/include/taler/exchange-database/get_drain_profit.h
+ * @brief implementation of the get_drain_profit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_DRAIN_PROFIT_H
+#define EXCHANGE_DATABASE_GET_DRAIN_PROFIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to get information about a profit drain event.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param wtid wire transfer ID to look up drain event for
+ * @param[out] serial set to serial ID of the entry
+ * @param[out] account_section set to account to drain
+ * @param[out] payto_uri set to account to wire funds to
+ * @param[out] request_timestamp set to time of the signature
+ * @param[out] amount set to amount to wire
+ * @param[out] master_sig set to signature affirming the operation
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_drain_profit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_expired_reserves.h b/src/include/taler/exchange-database/get_expired_reserves.h
@@ -0,0 +1,73 @@
+/*
+ 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_get_expired_reserves.h
+ * @brief implementation of the get_expired_reserves function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_EXPIRED_RESERVES_H
+#define EXCHANGE_DATABASE_GET_EXPIRED_RESERVES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about expired reserves.
+ *
+ * @param cls closure
+ * @param reserve_pub public key of the reserve
+ * @param left amount left in the reserve
+ * @param account_details information about the reserve's bank account, in payto://-format
+ * @param expiration_date when did the reserve expire
+ * @param close_request_row row that caused the reserve
+ * to be closed, 0 if it expired without request
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO to retry
+ * #GNUNET_SYSERR on hard failures (exit)
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_ReserveExpiredCallback)(
+ void *cls,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *left,
+ const struct TALER_FullPayto account_details,
+ struct GNUNET_TIME_Timestamp expiration_date,
+ uint64_t close_request_row);
+
+/**
+ * Obtain information about expired reserves and their
+ * remaining balances.
+ *
+ * @param cls closure of the plugin
+ * @param now timestamp based on which we decide expiration
+ * @param rec function to call on expired reserves
+ * @param rec_cls closure for @a rec
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_expired_reserves (struct EXCHANGEDB_PostgresContext *ctx,
+ struct GNUNET_TIME_Timestamp now,
+ TALER_EXCHANGEDB_ReserveExpiredCallback rec,
+ void *rec_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_extension_manifest.h b/src/include/taler/exchange-database/get_extension_manifest.h
@@ -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 src/include/taler/exchange-database/get_extension_manifest.h
+ * @brief implementation of the get_extension_manifest function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_EXTENSION_MANIFEST_H
+#define EXCHANGE_DATABASE_GET_EXTENSION_MANIFEST_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to get the manifest of an extension
+ * (age-restriction, policy_extension_...)
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @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
+EXCHANGEDB_get_extension_manifest (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *extension_name,
+ char **manifest);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_global_fee.h b/src/include/taler/exchange-database/get_global_fee.h
@@ -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 src/include/taler/exchange-database/get_global_fee.h
+ * @brief implementation of the get_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_GLOBAL_FEE_H
+#define EXCHANGE_DATABASE_GET_GLOBAL_FEE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Obtain global fees from database.
+ *
+ * @param cls closure
+ * @param date for which date do we want the fee?
+ * @param[out] start_date when does the fee go into effect
+ * @param[out] end_date when does the fee end being valid
+ * @param[out] fees how high are the wire fees
+ * @param[out] purse_timeout set to how long we keep unmerged purses
+ * @param[out] history_expiration set to how long we keep account histories
+ * @param[out] purse_account_limit set to the number of free purses per account
+ * @param[out] master_sig signature over the above by the exchange master key
+ * @return status of the transaction
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_global_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_global_fees.h b/src/include/taler/exchange-database/get_global_fees.h
@@ -0,0 +1,70 @@
+/*
+ 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 src/include/taler/exchange-database/get_global_fees.h
+ * @brief implementation of the get_global_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_GLOBAL_FEES_H
+#define EXCHANGE_DATABASE_GET_GLOBAL_FEES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Provide information about global fees.
+ *
+ * @param cls closure
+ * @param fees the global fees we charge
+ * @param purse_timeout when do purses time out
+ * @param history_expiration how long are account histories preserved
+ * @param purse_account_limit how many purses are free per account
+ * @param start_date from when are these fees valid (start date)
+ * @param end_date until when are these fees valid (end date, exclusive)
+ * @param master_sig master key signature affirming that this is the correct
+ * fee (of purpose #TALER_SIGNATURE_MASTER_GLOBAL_FEES)
+ */
+typedef void
+(*TALER_EXCHANGEDB_GlobalFeeCallback)(
+ void *cls,
+ const 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,
+ const struct TALER_MasterSignatureP *master_sig);
+
+/**
+ * Obtain global fees from database.
+ *
+ * @param cls closure
+ * @param cb function to call on each fee entry
+ * @param cb_cls closure for @a cb
+ * @return status of the transaction
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_global_fees (struct EXCHANGEDB_PostgresContext *ctx,
+ TALER_EXCHANGEDB_GlobalFeeCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_known_coin.h b/src/include/taler/exchange-database/get_known_coin.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/get_known_coin.h
+ * @brief implementation of the get_known_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_KNOWN_COIN_H
+#define EXCHANGE_DATABASE_GET_KNOWN_COIN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Retrieve the record for a known coin.
+ *
+ * @param cls the plugin closure
+ * @param coin_pub the public key of the coin to search for
+ * @param coin_info place holder for the returned coin information object
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_known_coin (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ struct TALER_CoinPublicInfo *coin_info);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_kyc_rules.h b/src/include/taler/exchange-database/get_kyc_rules.h
@@ -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 src/include/taler/exchange-database/get_kyc_rules.h
+ * @brief implementation of the get_kyc_rules function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_KYC_RULES_H
+#define EXCHANGE_DATABASE_GET_KYC_RULES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Return KYC rules that apply to the given account.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto account identifier
+ * @param merchant_pub merchant public key used by the client, or NULL
+ * if not available; if multiple @a reserve_pub values could be returned,
+ * we should use this one
+ * @param[out] no_account_pub set to true if no @a account_pub is available
+ * @param[out] account_pub set to account public key the rules
+ * apply to (because this key was used in KYC auth)
+ * @param[out] no_reserve_pub set to true if no @a reserve_pub is available
+ * @param[out] reserve_pub set to last incoming reserve public key
+ * of a wire transfer to the exchange from the given @a h_payto
+ * apply to (because this key was used in KYC auth)
+ * @param[out] jrules set to the active KYC rules for the
+ * given account, set to NULL if no custom rules are active
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_kyc_rules (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+/**
+ * Return only the KYC rules that apply to the given account.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto account identifier
+ * @param[out] jrules set to the active KYC rules for the
+ * given account, set to NULL if no custom rules are active
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_kyc_rules2 (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ json_t **jrules);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_old_coin_by_h_blind.h b/src/include/taler/exchange-database/get_old_coin_by_h_blind.h
@@ -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 src/include/taler/exchange-database/get_old_coin_by_h_blind.h
+ * @brief implementation of the get_old_coin_by_h_blind function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_OLD_COIN_BY_H_BLIND_H
+#define EXCHANGE_DATABASE_GET_OLD_COIN_BY_H_BLIND_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Obtain information about which old coin a coin was refreshed
+ * given the hash of the blinded (fresh) coin.
+ *
+ * @param cls closure
+ * @param h_blind_ev hash of the blinded coin
+ * @param[out] old_coin_pub set to information about the old coin (on success only)
+ * @param[out] rrc_serial set to serial number of the entry in the database
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_old_coin_by_h_blind (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_BlindedCoinHashP *h_blind_ev,
+ struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+ uint64_t *rrc_serial);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_pending_kyc_requirement_process.h b/src/include/taler/exchange-database/get_pending_kyc_requirement_process.h
@@ -0,0 +1,46 @@
+/*
+ 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 src/include/taler/exchange-database/get_pending_kyc_requirement_process.h
+ * @brief implementation of the get_pending_kyc_requirement_process function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_PENDING_KYC_REQUIREMENT_PROCESS_H
+#define EXCHANGE_DATABASE_GET_PENDING_KYC_REQUIREMENT_PROCESS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Fetch information about pending KYC requirement process.
+ *
+ * @param cls closure
+ * @param h_payto account that must be KYC'ed
+ * @param provider_name provider that must be checked
+ * @param[out] redirect_url set to redirect URL for the process
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_pending_kyc_requirement_process (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const char *provider_name,
+ char **redirect_url);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_policy_details.h b/src/include/taler/exchange-database/get_policy_details.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/get_policy_details.h
+ * @brief implementation of the get_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_POLICY_DETAILS_H
+#define EXCHANGE_DATABASE_GET_POLICY_DETAILS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/* Get the details of a policy, referenced by its hash code
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param hc The hash code under which the details to a particular policy should be found
+ * @param[out] details The found details
+ * @return query execution status
+ * */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_policy_details (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct GNUNET_HashCode *hc,
+ struct TALER_PolicyDetails *details);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_purse_deposit.h b/src/include/taler/exchange-database/get_purse_deposit.h
@@ -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 src/include/taler/exchange-database/get_purse_deposit.h
+ * @brief implementation of the get_purse_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_PURSE_DEPOSIT_H
+#define EXCHANGE_DATABASE_GET_PURSE_DEPOSIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to obtain a coin deposit data from
+ * depositing the coin into a purse.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub purse to credit
+ * @param coin_pub coin to deposit (debit)
+ * @param[out] amount set fraction of the coin's value that was deposited (with fee)
+ * @param[out] h_denom_pub set to hash of denomination of the coin
+ * @param[out] phac set to hash of age restriction on the coin
+ * @param[out] coin_sig set to signature affirming the operation
+ * @param[out] partner_url set to the URL of the partner exchange, or NULL for ourselves, must be freed by caller
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_purse_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_purse_request.h b/src/include/taler/exchange-database/get_purse_request.h
@@ -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 src/include/taler/exchange-database/get_purse_request.h
+ * @brief implementation of the get_purse_request function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_PURSE_REQUEST_H
+#define EXCHANGE_DATABASE_GET_PURSE_REQUEST_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to return meta data about a purse by the
+ * purse public key.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub public key of the purse
+ * @param[out] merge_pub public key representing the merge capability
+ * @param[out] purse_expiration when would an unmerged purse expire
+ * @param[out] h_contract_terms contract associated with the purse
+ * @param[out] age_limit the age limit for deposits into the purse
+ * @param[out] target_amount amount to be put into the purse
+ * @param[out] balance amount put so far into the purse
+ * @param[out] purse_sig signature of the purse over the initialization data
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_purse_request (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_ready_deposit.h b/src/include/taler/exchange-database/get_ready_deposit.h
@@ -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 src/include/taler/exchange-database/get_ready_deposit.h
+ * @brief implementation of the get_ready_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_READY_DEPOSIT_H
+#define EXCHANGE_DATABASE_GET_READY_DEPOSIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Obtain information about deposits that are ready to be executed. Such
+ * deposits must not be marked as "done", the execution time must be
+ * in the past, and the KYC status must be 'ok'.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param start_shard_row minimum shard row to select
+ * @param end_shard_row maximum shard row to select (inclusive)
+ * @param[out] merchant_pub set to the public key of a merchant with a ready deposit
+ * @param[out] payto_uri set to the account of the merchant, to be freed by caller
+ * @param[out] extra_wire_subject_metadata set to additional metadata to include in the wire subject, or NULL for none
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_ready_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_refresh.h b/src/include/taler/exchange-database/get_refresh.h
@@ -0,0 +1,44 @@
+/*
+ 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 src/include/taler/exchange-database/get_refresh.h
+ * @brief implementation of the get_refresh function for Postgres
+ * @author Özgür Kesim
+ */
+#ifndef EXCHANGE_DATABASE_GET_REFRESH_H
+#define EXCHANGE_DATABASE_GET_REFRESH_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup refresh refresh commitment data under the given @a rc.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param rc commitment hash to use to locate the operation
+ * @param[out] refresh where to store the result; note that
+ * refresh->session.coin.denom_sig will be set to NULL
+ * and is not fetched by this routine (as it is not needed by the client)
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_refresh (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_RefreshCommitmentP *rc,
+ struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS *refresh);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_reserve_balance.h b/src/include/taler/exchange-database/get_reserve_balance.h
@@ -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 src/include/taler/exchange-database/get_reserve_balance.h
+ * @brief implementation of the get_reserve_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_RESERVE_BALANCE_H
+#define EXCHANGE_DATABASE_GET_RESERVE_BALANCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Get the balance of the specified reserve.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param[out] balance set to the reserve balance
+ * @param[out] origin_account set to URI of the origin account, NULL
+ * if we have no origin account (reserve created by P2P merge)
+* @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_reserve_balance (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ struct TALER_Amount *balance,
+ struct TALER_FullPayto *origin_account);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_reserve_by_h_planchets.h b/src/include/taler/exchange-database/get_reserve_by_h_planchets.h
@@ -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 src/include/taler/exchange-database/get_reserve_by_h_planchets.h
+ * @brief implementation of the get_reserve_by_h_planchets function for Postgres
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#ifndef EXCHANGE_DATABASE_GET_RESERVE_BY_H_PLANCHETS_H
+#define EXCHANGE_DATABASE_GET_RESERVE_BY_H_PLANCHETS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Obtain information about which reserve a coin was generated
+ * from given the hash of the blinded coin.
+ *
+ * @param cls closure
+ * @param h_planchets hash that uniquely identifies the withdraw request
+ * @param[out] reserve_pub set to information about the reserve (on success only)
+ * @param[out] withdraw_serial_id set to row of the @a h_commitment in withdraw
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_reserve_by_h_planchets (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_HashBlindedPlanchetsP *h_planchets,
+ struct TALER_ReservePublicKeyP *reserve_pub,
+ uint64_t *withdraw_serial_id);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_reserve_history.h b/src/include/taler/exchange-database/get_reserve_history.h
@@ -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 pg_get_reserve_history.h
+ * @brief implementation of the get_reserve_history function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_RESERVE_HISTORY_H
+#define EXCHANGE_DATABASE_GET_RESERVE_HISTORY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Compile a list of (historic) transactions performed with the given reserve
+ * (withdraw, incoming wire, open, close operations). Should return 0 if the @a
+ * reserve_pub is unknown, otherwise determine @a etag_out and if it is past @a
+ * etag_in return the history after @a start_off. @a etag_out should be set
+ * to the last row ID of the given @a reserve_pub in the reserve history table.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param start_off maximum starting offset in history to exclude from returning
+ * @param etag_in up to this offset the client already has a response, do not
+ * return anything unless @a etag_out will be larger
+ * @param[out] etag_out set to the latest history offset known for this @a coin_pub
+ * @param[out] balance set to the reserve balance
+ * @param[out] rhp set to known transaction history (NULL if reserve is unknown)
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_reserve_history (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/get_signature_for_known_coin.h b/src/include/taler/exchange-database/get_signature_for_known_coin.h
@@ -0,0 +1,44 @@
+/*
+ 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 src/include/taler/exchange-database/get_signature_for_known_coin.h
+ * @brief implementation of the get_signature_for_known_coin function for Postgres
+ * @author Özgür Kesim
+ */
+#ifndef EXCHANGE_DATABASE_GET_SIGNATURE_FOR_KNOWN_COIN_H
+#define EXCHANGE_DATABASE_GET_SIGNATURE_FOR_KNOWN_COIN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Retrieve the denomination and the corresponding signature for a known coin.
+ *
+ * @param cls the plugin closure
+ * @param coin_pub the public key of the coin to search for
+ * @param[out] denom_pub the denomination of the public key, if coin was present
+ * @param[out] denom_sig the signature with the denomination key of the coin, if coin was present
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_signature_for_known_coin (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ struct TALER_DenominationPublicKey *denom_pub,
+ struct TALER_DenominationSignature *denom_sig);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_unfinished_close_requests.h b/src/include/taler/exchange-database/get_unfinished_close_requests.h
@@ -0,0 +1,73 @@
+/*
+ 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_get_unfinished_close_requests.h
+ * @brief implementation of the get_unfinished_close_requests function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_UNFINISHED_CLOSE_REQUESTS_H
+#define EXCHANGE_DATABASE_GET_UNFINISHED_CLOSE_REQUESTS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about expired reserves.
+ *
+ * @param cls closure
+ * @param reserve_pub public key of the reserve
+ * @param left amount left in the reserve
+ * @param account_details information about the reserve's bank account, in payto://-format
+ * @param expiration_date when did the reserve expire
+ * @param close_request_row row that caused the reserve
+ * to be closed, 0 if it expired without request
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO to retry
+ * #GNUNET_SYSERR on hard failures (exit)
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_ReserveExpiredCallback)(
+ void *cls,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *left,
+ const struct TALER_FullPayto account_details,
+ struct GNUNET_TIME_Timestamp expiration_date,
+ uint64_t close_request_row);
+
+/**
+ * Obtain information about force-closed reserves
+ * where the close was not yet done (and their remaining
+ * balances). Updates the returned reserve's close
+ * status to "done".
+ *
+ * @param cls closure of the plugin
+ * @param rec function to call on expired reserves
+ * @param rec_cls closure for @a rec
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_unfinished_close_requests (struct EXCHANGEDB_PostgresContext *ctx,
+ TALER_EXCHANGEDB_ReserveExpiredCallback rec,
+ void *rec_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_wire_accounts.h b/src/include/taler/exchange-database/get_wire_accounts.h
@@ -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 src/include/taler/exchange-database/get_wire_accounts.h
+ * @brief implementation of the get_wire_accounts function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_WIRE_ACCOUNTS_H
+#define EXCHANGE_DATABASE_GET_WIRE_ACCOUNTS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Provide information about a wire account.
+ *
+ * @param cls closure
+ * @param payto_uri the exchange bank account URI
+ * @param conversion_url URL of a conversion service, NULL if there is no conversion
+ * @param open_banking_gateway open banking gateway service, NULL if unavailable
+ * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable
+ * @param debit_restrictions JSON array with debit restrictions on the account
+ * @param credit_restrictions JSON array with credit restrictions on the account
+ * @param master_sig master key signature affirming that this is a bank
+ * account of the exchange (of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS)
+ * @param bank_label label the wallet should use to display the account, can be NULL
+ * @param priority priority for ordering bank account labels
+ */
+typedef void
+(*TALER_EXCHANGEDB_WireAccountCallback)(
+ void *cls,
+ 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,
+ const struct TALER_MasterSignatureP *master_sig,
+ const char *bank_label,
+ int64_t priority);
+
+/**
+ * Obtain information about the enabled wire accounts of the exchange.
+ *
+ * @param cls closure
+ * @param cb function to call on each account
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_wire_accounts (struct EXCHANGEDB_PostgresContext *ctx,
+ TALER_EXCHANGEDB_WireAccountCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_wire_fee.h b/src/include/taler/exchange-database/get_wire_fee.h
@@ -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 src/include/taler/exchange-database/get_wire_fee.h
+ * @brief implementation of the get_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_WIRE_FEE_H
+#define EXCHANGE_DATABASE_GET_WIRE_FEE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Obtain wire fee from database.
+ *
+ * @param cls closure
+ * @param type type of wire transfer the fee applies for
+ * @param date for which date do we want the fee?
+ * @param[out] rowid set to row in the database with the wire fee
+ * @param[out] start_date when does the fee go into effect
+ * @param[out] end_date when does the fee end being valid
+ * @param[out] fees how high are the wire fees
+ * @param[out] master_sig signature over the above by the exchange master key
+ * @return status of the transaction
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_wire_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_wire_fees.h b/src/include/taler/exchange-database/get_wire_fees.h
@@ -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 src/include/taler/exchange-database/get_wire_fees.h
+ * @brief implementation of the get_wire_fees function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_GET_WIRE_FEES_H
+#define EXCHANGE_DATABASE_GET_WIRE_FEES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Provide information about wire fees.
+ *
+ * @param cls closure
+ * @param fees the wire fees we charge
+ * @param start_date from when are these fees valid (start date)
+ * @param end_date until when are these fees valid (end date, exclusive)
+ * @param master_sig master key signature affirming that this is the correct
+ * fee (of purpose #TALER_SIGNATURE_MASTER_WIRE_FEES)
+ */
+typedef void
+(*TALER_EXCHANGEDB_WireFeeCallback)(
+ void *cls,
+ const struct TALER_WireFeeSet *fees,
+ struct GNUNET_TIME_Timestamp start_date,
+ struct GNUNET_TIME_Timestamp end_date,
+ const struct TALER_MasterSignatureP *master_sig);
+
+/**
+ * Obtain information about the fee structure of the exchange for
+ * a given @a wire_method
+ *
+ * @param cls closure
+ * @param wire_method which wire method to obtain fees for
+ * @param cb function to call on each account
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_wire_fees (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *wire_method,
+ TALER_EXCHANGEDB_WireFeeCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_wire_hash_for_contract.h b/src/include/taler/exchange-database/get_wire_hash_for_contract.h
@@ -0,0 +1,47 @@
+/*
+ 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 src/include/taler/exchange-database/get_wire_hash_for_contract.h
+ * @brief implementation of the get_wire_hash_for_contract function for Postgres
+ * @author Özgür Kesim
+ */
+#ifndef EXCHANGE_DATABASE_GET_WIRE_HASH_FOR_CONTRACT_H
+#define EXCHANGE_DATABASE_GET_WIRE_HASH_FOR_CONTRACT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Try to get the salted hash of a merchant's bank account to a deposit
+ * contract. This is necessary in the event of a conflict with a given
+ * (merchant_pub, h_contract_terms) during deposit.
+ *
+ * @param cls closure
+ * @param merchant_pub merchant public key
+ * @param h_contract_terms hash of the proposal data
+ * @param[out] h_wire salted hash of a merchant's bank account
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_wire_hash_for_contract (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ struct TALER_MerchantWireHashP *h_wire);
+
+#endif
diff --git a/src/include/taler/exchange-database/get_withdraw.h b/src/include/taler/exchange-database/get_withdraw.h
@@ -0,0 +1,45 @@
+/*
+ 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 src/include/taler/exchange-database/get_withdraw.h
+ * @brief implementation of the get_withdraw function for Postgres
+ * @author Özgür KESIM
+ */
+#ifndef EXCHANGE_DATABASE_GET_WITHDRAW_H
+#define EXCHANGE_DATABASE_GET_WITHDRAW_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Locate the response for a withdraw request under a hash that uniquely
+ * identifies the withdraw operation. Used to ensure idempotency of the
+ * request.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param wch hash over all hashes of blinded planchets that uniquely identifies the withdraw operation
+ * @param[out] wd corresponding details of the previous withdraw request if an entry was found
+ * @return statement execution status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_get_withdraw (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_HashBlindedPlanchetsP *wch,
+ struct TALER_EXCHANGEDB_Withdraw *wd);
+
+#endif
diff --git a/src/include/taler/exchange-database/have_deposit2.h b/src/include/taler/exchange-database/have_deposit2.h
@@ -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 src/include/taler/exchange-database/have_deposit2.h
+ * @brief implementation of the have_deposit2 function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_HAVE_DEPOSIT2_H
+#define EXCHANGE_DATABASE_HAVE_DEPOSIT2_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Check if we have the specified deposit already in the database.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param h_contract_terms contract to check for
+ * @param h_wire wire hash to check for
+ * @param coin_pub public key of the coin to check for
+ * @param merchant merchant public key to check for
+ * @param refund_deadline expected refund deadline
+ * @param[out] deposit_fee set to the deposit fee the exchange charged
+ * @param[out] exchange_timestamp set to the time when the exchange received the deposit
+ * @return 1 if we know this operation,
+ * 0 if this exact deposit is unknown to us,
+ * otherwise transaction error status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_have_deposit2 (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/inject_auditor_triggers.h b/src/include/taler/exchange-database/inject_auditor_triggers.h
@@ -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 src/include/taler/exchange-database/inject_auditor_triggers.h
+ * @brief implementation of the inject_auditor_triggers function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INJECT_AUDITOR_TRIGGERS_H
+#define EXCHANGE_DATABASE_INJECT_AUDITOR_TRIGGERS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to inject auditor triggers into the
+ * database, triggering the real-time auditor upon
+ * relevant INSERTs.
+ *
+ * @param cls closure
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR on DB errors
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_inject_auditor_triggers (struct EXCHANGEDB_PostgresContext *ctx);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_active_legitimization_measure.h b/src/include/taler/exchange-database/insert_active_legitimization_measure.h
@@ -0,0 +1,49 @@
+/*
+ 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 src/include/taler/exchange-database/insert_active_legitimization_measure.h
+ * @brief implementation of the insert_active_legitimization_measure function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_ACTIVE_LEGITIMIZATION_MEASURE_H
+#define EXCHANGE_DATABASE_INSERT_ACTIVE_LEGITIMIZATION_MEASURE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Create new active legitimization measure.
+ *
+ *
+ * @param cls closure
+ * @param access_token access token that identifies the
+ * account the legitimization measures apply to
+ * @param jmeasures new legitimization measures
+ * @param[out] legitimization_measure_serial_id
+ * set to new row in legitimization_measures table
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_active_legitimization_measure (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_AccountAccessTokenP *access_token,
+ const json_t *jmeasures,
+ uint64_t *legitimization_measure_serial_id);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_aml_decision.h b/src/include/taler/exchange-database/insert_aml_decision.h
@@ -0,0 +1,94 @@
+/*
+ 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 src/include/taler/exchange-database/insert_aml_decision.h
+ * @brief implementation of the insert_aml_decision function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_AML_DECISION_H
+#define EXCHANGE_DATABASE_INSERT_AML_DECISION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert an AML decision. Inserts into AML history and insert or updates AML
+ * status.
+ *
+ * @param cls closure
+ * @param payto_uri full URI of the account, optional,
+ * can be NULL if the backend already knows the account
+ * @param h_payto account for which the attribute data is stored
+ * @param decision_time when was the decision made
+ * @param expiration_time when does the decision expire
+ * @param properties JSON object with properties to set for the account
+ * @param new_rules JSON array with new AML/KYC rules
+ * @param to_investigate true if AML staff should look more into this account
+ * @param new_measure_name name of the @a jmeasures measure that was triggered, or NULL for none
+ * @param jmeasures a JSON with LegitimizationMeasures to apply to the
+ * account, or NULL to not apply any measure right now
+ * @param justification human-readable text justifying the decision
+ * @param decider_pub public key of the staff member
+ * @param decider_sig signature of the staff member
+ * @param num_events length of the @a events array
+ * @param events array of events to trigger
+ * @param enc_attributes_size number of bytes in @a enc_attributes
+ * @param enc_attributes encrypted attribute data
+ * @param form_name name of the form from which @a enc_attributes originate, can be NULL
+ * @param attributes_hash hash of the unencrypted attribute data
+ * @param attributes_expiration_time when does the attribute data expire
+ * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now
+ * @param[out] unknown_account set to TRUE if @a h_payto does not refer to a known account and @a jmeasures was given
+ * @param[out] last_date set to the previous decision time;
+ * the INSERT is not performed if @a last_date is not before @a decision_time
+ * @param[out] legitimization_measure_serial_id serial ID of the legitimization measures
+ * of the decision
+ * @param[out] is_wallet set to true if @a h_payto is for a wallet
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_aml_decision (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_aml_officer.h b/src/include/taler/exchange-database/insert_aml_officer.h
@@ -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 src/include/taler/exchange-database/insert_aml_officer.h
+ * @brief implementation of the insert_aml_officer function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_AML_OFFICER_H
+#define EXCHANGE_DATABASE_INSERT_AML_OFFICER_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert AML staff record. If the time given in
+ * @a last_change is before the previous change in the
+ * database, only @e previous_change is returned and
+ * no actual change is committed to the database.
+ *
+ * @param cls closure
+ * @param decider_pub public key of the staff member
+ * @param master_sig offline signature affirming the AML officer
+ * @param decider_name full name of the staff member
+ * @param is_active true to enable, false to set as inactive
+ * @param read_only true to set read-only access
+ * @param last_change when was the change made effective
+ * @param[out] previous_change set to the time of the previous change
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_aml_officer (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_aml_program_failure.h b/src/include/taler/exchange-database/insert_aml_program_failure.h
@@ -0,0 +1,49 @@
+/*
+ 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 src/include/taler/exchange-database/insert_aml_program_failure.h
+ * @brief implementation of the insert_aml_program_failure function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_AML_PROGRAM_FAILURE_H
+#define EXCHANGE_DATABASE_INSERT_AML_PROGRAM_FAILURE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Update AML program status to finished (and failed).
+ *
+ * @param cls closure
+ * @param process_row KYC process row to update
+ * @param h_payto account for which the attribute data is stored
+ * @param error_message details about what went wrong
+ * @param ec error code about the failure
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_aml_program_failure (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t process_row,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const char *error_message,
+ enum TALER_ErrorCode ec);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_auditor.h b/src/include/taler/exchange-database/insert_auditor.h
@@ -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 src/include/taler/exchange-database/insert_auditor.h
+ * @brief implementation of the insert_auditor function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_AUDITOR_H
+#define EXCHANGE_DATABASE_INSERT_AUDITOR_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert information about an auditor that will audit this exchange.
+ *
+ * @param cls closure
+ * @param auditor_pub key of the auditor
+ * @param auditor_url base URL of the auditor's REST service
+ * @param auditor_name name of the auditor (for humans)
+ * @param start_date date when the auditor was added by the offline system
+ * (only to be used for replay detection)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_auditor (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ const char *auditor_url,
+ const char *auditor_name,
+ struct GNUNET_TIME_Timestamp start_date);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_auditor_denom_sig.h b/src/include/taler/exchange-database/insert_auditor_denom_sig.h
@@ -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 src/include/taler/exchange-database/insert_auditor_denom_sig.h
+ * @brief implementation of the insert_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_AUDITOR_DENOM_SIG_H
+#define EXCHANGE_DATABASE_INSERT_AUDITOR_DENOM_SIG_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert information about an auditor auditing a denomination key.
+ *
+ * @param cls closure
+ * @param h_denom_pub the audited denomination
+ * @param auditor_pub the auditor's key
+ * @param auditor_sig signature affirming the auditor's audit activity
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_auditor_denom_sig (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ const struct TALER_AuditorSignatureP *auditor_sig);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_close_request.h b/src/include/taler/exchange-database/insert_close_request.h
@@ -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 pg_insert_close_request.h
+ * @brief implementation of the insert_close_request function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_CLOSE_REQUEST_H
+#define EXCHANGE_DATABASE_INSERT_CLOSE_REQUEST_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to initiate closure of an account.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param reserve_pub public key of the account to close
+ * @param payto_uri where to wire the funds
+ * @param reserve_sig signature affiming that the account is to be closed
+ * @param request_timestamp time of the close request (client-side?)
+ * @param balance final balance in the reserve
+ * @param closing_fee closing fee to charge
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_close_request (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_contract.h b/src/include/taler/exchange-database/insert_contract.h
@@ -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 src/include/taler/exchange-database/insert_contract.h
+ * @brief implementation of the insert_contract function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_CONTRACT_H
+#define EXCHANGE_DATABASE_INSERT_CONTRACT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to persist an encrypted contract associated with a reserve.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub the purse the contract is associated with (must exist)
+ * @param econtract the encrypted contract
+ * @param[out] in_conflict set to true if @a econtract
+ * conflicts with an existing contract;
+ * in this case, the return value will be
+ * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_contract (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_EncryptedContract *econtract,
+ bool *in_conflict);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_denomination_info.h b/src/include/taler/exchange-database/insert_denomination_info.h
@@ -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 src/include/taler/exchange-database/insert_denomination_info.h
+ * @brief implementation of the insert_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_DENOMINATION_INFO_H
+#define EXCHANGE_DATABASE_INSERT_DENOMINATION_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert a denomination key's public information into the database for
+ * reference by auditors and other consistency checks.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param denom_pub the public key used for signing coins of this denomination
+ * @param issue issuing information with value, fees and other info about the coin
+ * @return status of the query
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_denomination_info (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_denomination_revocation.h b/src/include/taler/exchange-database/insert_denomination_revocation.h
@@ -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 src/include/taler/exchange-database/insert_denomination_revocation.h
+ * @brief implementation of the insert_denomination_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_DENOMINATION_REVOCATION_H
+#define EXCHANGE_DATABASE_INSERT_DENOMINATION_REVOCATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Store information that a denomination key was revoked
+ * in the database.
+ *
+ * @param cls closure
+ * @param denom_pub_hash hash of the revoked denomination key
+ * @param master_sig signature affirming the revocation
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_denomination_revocation (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *denom_pub_hash,
+ const struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_drain_profit.h b/src/include/taler/exchange-database/insert_drain_profit.h
@@ -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 src/include/taler/exchange-database/insert_drain_profit.h
+ * @brief implementation of the insert_drain_profit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_DRAIN_PROFIT_H
+#define EXCHANGE_DATABASE_INSERT_DRAIN_PROFIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to persist a request to drain profits.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param wtid wire transfer ID to use
+ * @param account_section account to drain
+ * @param payto_uri account to wire funds to
+ * @param request_timestamp when was the request made
+ * @param amount amount to wire
+ * @param master_sig signature affirming the operation
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_drain_profit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_global_fee.h b/src/include/taler/exchange-database/insert_global_fee.h
@@ -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 src/include/taler/exchange-database/insert_global_fee.h
+ * @brief implementation of the insert_global_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_GLOBAL_FEE_H
+#define EXCHANGE_DATABASE_INSERT_GLOBAL_FEE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert global fee data into database.
+ *
+ * @param cls closure
+ * @param start_date when does the fees go into effect
+ * @param end_date when does the fees end being valid
+ * @param fees how high is are the global fees
+ * @param purse_timeout when do purses time out
+ * @param history_expiration how long are account histories preserved
+ * @param purse_account_limit how many purses are free per account
+ * @param master_sig signature over the above by the exchange master key
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_global_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_kyc_failure.h b/src/include/taler/exchange-database/insert_kyc_failure.h
@@ -0,0 +1,55 @@
+/*
+ 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 src/include/taler/exchange-database/insert_kyc_failure.h
+ * @brief implementation of the insert_kyc_failure function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_KYC_FAILURE_H
+#define EXCHANGE_DATABASE_INSERT_KYC_FAILURE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Update KYC process status to finished (and failed).
+ *
+ * @param cls closure
+ * @param process_row KYC process row to update
+ * @param h_payto account for which the attribute data is stored
+ * @param provider_name provider that must be checked
+ * @param provider_account_id provider account ID
+ * @param provider_legitimization_id provider legitimization ID
+ * @param error_message details about what went wrong
+ * @param ec error code about the failure
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_kyc_failure (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_kyc_requirement_process.h b/src/include/taler/exchange-database/insert_kyc_requirement_process.h
@@ -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 src/include/taler/exchange-database/insert_kyc_requirement_process.h
+ * @brief implementation of the insert_kyc_requirement_process function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_KYC_REQUIREMENT_PROCESS_H
+#define EXCHANGE_DATABASE_INSERT_KYC_REQUIREMENT_PROCESS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Begin KYC requirement process.
+ *
+ * @param cls closure
+ * @param h_payto account that must be KYC'ed
+ * @param measure_index which of the measures in
+ * jmeasures does this KYC process relate to
+ * @param legitimization_measure_serial_id which
+ * legitimization measure set does this KYC process
+ * relate to (uniquely identifies jmeasures)
+ * @param provider_name provider that must be checked
+ * @param provider_account_id provider account ID
+ * @param provider_legitimization_id provider legitimization ID
+ * @param[out] process_row row the process is stored under
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_kyc_requirement_process (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_partner.h b/src/include/taler/exchange-database/insert_partner.h
@@ -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 src/include/taler/exchange-database/insert_partner.h
+ * @brief implementation of the insert_partner function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_PARTNER_H
+#define EXCHANGE_DATABASE_INSERT_PARTNER_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to store configuration data about a partner
+ * exchange that we are federated with.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param master_pub public offline signing key of the partner exchange
+ * @param start_date when does the following data start to be valid
+ * @param end_date when does the validity end (exclusive)
+ * @param wad_frequency how often do we do exchange-to-exchange settlements?
+ * @param wad_fee how much do we charge for transfers to the partner
+ * @param partner_base_url base URL of the partner exchange
+ * @param master_sig signature with our offline signing key affirming the above
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_partner (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_purse_request.h b/src/include/taler/exchange-database/insert_purse_request.h
@@ -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 src/include/taler/exchange-database/insert_purse_request.h
+ * @brief implementation of the insert_purse_request function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_PURSE_REQUEST_H
+#define EXCHANGE_DATABASE_INSERT_PURSE_REQUEST_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to create a new purse with certain meta data.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub public key of the new purse
+ * @param merge_pub public key providing the merge capability
+ * @param purse_expiration time when the purse will expire
+ * @param h_contract_terms hash of the contract for the purse
+ * @param age_limit age limit to enforce for payments into the purse
+ * @param flags flags for the operation
+ * @param purse_fee fee we are allowed to charge to the reserve (depending on @a flags)
+ * @param amount target amount (with fees) to be put into the purse
+ * @param purse_sig signature with @a purse_pub's private key affirming the above
+ * @param[out] in_conflict set to true if the meta data
+ * conflicts with an existing purse;
+ * in this case, the return value will be
+ * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_purse_request (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_records_by_table.h b/src/include/taler/exchange-database/insert_records_by_table.h
@@ -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 pg_insert_records_by_table.h
+ * @brief implementation of the insert_records_by_table function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_RECORDS_BY_TABLE_H
+#define EXCHANGE_DATABASE_INSERT_RECORDS_BY_TABLE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert record set into @a table. Used in exchange-auditor database
+ * replication.
+ *
+ * @param cls closure
+ * @param td table data to insert
+ * @return transaction status code, #GNUNET_DB_STATUS_HARD_ERROR if
+ * @e table in @a tr is not supported
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_records_by_table (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_EXCHANGEDB_TableData *td);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_refund.h b/src/include/taler/exchange-database/insert_refund.h
@@ -0,0 +1,40 @@
+/*
+ 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 src/include/taler/exchange-database/insert_refund.h
+ * @brief implementation of the insert_refund function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_REFUND_H
+#define EXCHANGE_DATABASE_INSERT_REFUND_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert information about refunded coin into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param refund refund information to store
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_refund (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_EXCHANGEDB_Refund *refund);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_reserve_closed.h b/src/include/taler/exchange-database/insert_reserve_closed.h
@@ -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 src/include/taler/exchange-database/insert_reserve_closed.h
+ * @brief implementation of the insert_reserve_closed function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_RESERVE_CLOSED_H
+#define EXCHANGE_DATABASE_INSERT_RESERVE_CLOSED_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert reserve close operation into database.
+ *
+ * @param cls closure
+ * @param reserve_pub which reserve is this about?
+ * @param execution_date when did we perform the transfer?
+ * @param receiver_account to which account do we transfer?
+ * @param wtid wire transfer details
+ * @param amount_with_fee amount we charged to the reserve
+ * @param closing_fee how high is the closing fee
+ * @param close_request_row identifies explicit close request, 0 for none
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_reserve_closed (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_reserve_open_deposit.h b/src/include/taler/exchange-database/insert_reserve_open_deposit.h
@@ -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 pg_insert_reserve_open_deposit.h
+ * @brief implementation of the insert_reserve_open_deposit function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_RESERVE_OPEN_DEPOSIT_H
+#define EXCHANGE_DATABASE_INSERT_RESERVE_OPEN_DEPOSIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert reserve open coin deposit data into database.
+ * Subtracts the @a coin_total from the coin's balance.
+ *
+ * @param cls closure
+ * @param cpi public information about the coin
+ * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT
+ * @param known_coin_id ID of the coin in the known_coins table
+ * @param coin_total amount to be spent of the coin (including deposit fee)
+ * @param reserve_sig signature by the reserve affirming the open operation
+ * @param reserve_pub public key of the reserve being opened
+ * @param[out] insufficient_funds set to true if the coin's balance is insufficient, otherwise to false
+ * @return transaction status code, 0 if operation is already in the DB
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_reserve_open_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_sanction_list_hit.h b/src/include/taler/exchange-database/insert_sanction_list_hit.h
@@ -0,0 +1,54 @@
+/*
+ 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 src/include/taler/exchange-database/insert_sanction_list_hit.h
+ * @brief implementation of the insert_sanction_list_hit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_SANCTION_LIST_HIT_H
+#define EXCHANGE_DATABASE_INSERT_SANCTION_LIST_HIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Update sanction list hit status of the given account.
+ *
+ * @param cls closure
+ * @param h_payto account for which the hit is to be stored
+ * @param to_investigate true to flag account for investigation,
+ * false to **preserve** existing status
+ * @param new_rules new KYC rules to apply to the account, NULL to preserve
+ * existing rules
+ * @param account_properties new account properties
+ * @param num_events length of the @a events array
+ * @param events array of KYC events to trigger
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_sanction_list_hit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_signkey_revocation.h b/src/include/taler/exchange-database/insert_signkey_revocation.h
@@ -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 src/include/taler/exchange-database/insert_signkey_revocation.h
+ * @brief implementation of the insert_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_SIGNKEY_REVOCATION_H
+#define EXCHANGE_DATABASE_INSERT_SIGNKEY_REVOCATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Store information about a revoked online signing key.
+ *
+ * @param cls closure
+ * @param exchange_pub exchange online signing key that was revoked
+ * @param master_sig signature affirming the revocation
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_signkey_revocation (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ const struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_successor_measure.h b/src/include/taler/exchange-database/insert_successor_measure.h
@@ -0,0 +1,40 @@
+/*
+ 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 src/include/taler/exchange-database/insert_successor_measure.h
+ * @brief implementation of the insert_successor_measure function for Postgres
+ * @author Florian Dold
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_SUCCESSOR_MEASURE_H
+#define EXCHANGE_DATABASE_INSERT_SUCCESSOR_MEASURE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_successor_measure (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_wire.h b/src/include/taler/exchange-database/insert_wire.h
@@ -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 src/include/taler/exchange-database/insert_wire.h
+ * @brief implementation of the insert_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_WIRE_H
+#define EXCHANGE_DATABASE_INSERT_WIRE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert information about an wire account used by this exchange.
+ *
+ * @param cls closure
+ * @param payto_uri wire account of the exchange
+ * @param conversion_url URL of a conversion service, NULL if there is no conversion
+ * @param open_banking_gateway open banking gateway service, NULL if unavailable
+ * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable
+ * @param debit_restrictions JSON array with debit restrictions on the account
+ * @param credit_restrictions JSON array with credit restrictions on the account
+ * @param start_date date when the account was added by the offline system
+ * (only to be used for replay detection)
+ * @param master_sig public signature affirming the existence of the account,
+ * must be of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS
+ * @param bank_label label to show this entry under in the UI, can be NULL
+ * @param priority determines order in which entries are shown in the UI
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_wire (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/insert_wire_fee.h b/src/include/taler/exchange-database/insert_wire_fee.h
@@ -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 src/include/taler/exchange-database/insert_wire_fee.h
+ * @brief implementation of the insert_wire_fee function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_INSERT_WIRE_FEE_H
+#define EXCHANGE_DATABASE_INSERT_WIRE_FEE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert wire transfer fee into database.
+ *
+ * @param cls closure
+ * @param type type of wire transfer this fee applies for
+ * @param start_date when does the fee go into effect
+ * @param end_date when does the fee end being valid
+ * @param fees how high are the wire fees
+ * @param master_sig signature over the above by the exchange master key
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_insert_wire_fee (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/iterate_active_auditors.h b/src/include/taler/exchange-database/iterate_active_auditors.h
@@ -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 src/include/taler/exchange-database/iterate_active_auditors.h
+ * @brief implementation of the iterate_active_auditors function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ITERATE_ACTIVE_AUDITORS_H
+#define EXCHANGE_DATABASE_ITERATE_ACTIVE_AUDITORS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with information about the exchange's auditors.
+ *
+ * @param cls closure with a `struct TEH_KeyStateHandle *`
+ * @param auditor_pub the public key of the auditor
+ * @param auditor_url URL of the REST API of the auditor
+ * @param auditor_name human readable official name of the auditor
+ */
+typedef void
+(*TALER_EXCHANGEDB_AuditorsCallback)(
+ void *cls,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ const char *auditor_url,
+ const char *auditor_name);
+
+/**
+ * Function called to invoke @a cb on every active auditor. Disabled
+ * auditors are skipped. Runs in its own read-only transaction.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each active auditor
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_iterate_active_auditors (struct EXCHANGEDB_PostgresContext *ctx,
+ TALER_EXCHANGEDB_AuditorsCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/iterate_active_signkeys.h b/src/include/taler/exchange-database/iterate_active_signkeys.h
@@ -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 src/include/taler/exchange-database/iterate_active_signkeys.h
+ * @brief implementation of the iterate_active_signkeys function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ITERATE_ACTIVE_SIGNKEYS_H
+#define EXCHANGE_DATABASE_ITERATE_ACTIVE_SIGNKEYS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Signature of a function called with information about the exchange's
+ * online signing keys.
+ *
+ * @param cls closure with a `struct TEH_KeyStateHandle *`
+ * @param exchange_pub public key of the exchange
+ * @param meta meta data information about the signing type (expirations)
+ * @param master_sig master signature affirming the validity of this denomination
+ */
+typedef void
+(*TALER_EXCHANGEDB_ActiveSignkeysCallback)(
+ void *cls,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ const struct TALER_EXCHANGEDB_SignkeyMetaData *meta,
+ const struct TALER_MasterSignatureP *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 cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each signing key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_iterate_active_signkeys (struct EXCHANGEDB_PostgresContext *ctx,
+ TALER_EXCHANGEDB_ActiveSignkeysCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/iterate_auditor_denominations.h b/src/include/taler/exchange-database/iterate_auditor_denominations.h
@@ -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 src/include/taler/exchange-database/iterate_auditor_denominations.h
+ * @brief implementation of the iterate_auditor_denominations function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ITERATE_AUDITOR_DENOMINATIONS_H
+#define EXCHANGE_DATABASE_ITERATE_AUDITOR_DENOMINATIONS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with information about the denominations
+ * audited by the exchange's auditors.
+ *
+ * @param cls closure with a `struct TEH_KeyStateHandle *`
+ * @param auditor_pub the public key of an auditor
+ * @param h_denom_pub hash of a denomination key audited by this auditor
+ * @param auditor_sig signature from the auditor affirming this
+ */
+typedef void
+(*TALER_EXCHANGEDB_AuditorDenominationsCallback)(
+ void *cls,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ const struct TALER_AuditorSignatureP *auditor_sig);
+
+/**
+ * Function called to invoke @a cb on every denomination with an active
+ * auditor. Disabled auditors and denominations without auditor are
+ * skipped. Runs in its own read-only transaction.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each active auditor
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_iterate_auditor_denominations (struct EXCHANGEDB_PostgresContext *ctx,
+ TALER_EXCHANGEDB_AuditorDenominationsCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/iterate_denomination_info.h b/src/include/taler/exchange-database/iterate_denomination_info.h
@@ -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 src/include/taler/exchange-database/iterate_denomination_info.h
+ * @brief implementation of the iterate_denomination_info function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ITERATE_DENOMINATION_INFO_H
+#define EXCHANGE_DATABASE_ITERATE_DENOMINATION_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with information about the exchange's denomination keys.
+ * Note that the 'master' field in @a issue will not yet be initialized when
+ * this function is called!
+ *
+ * @param cls closure
+ * @param denom_serial table row of the denomination
+ * @param denom_pub public key of the denomination
+ * @param issue detailed information about the denomination (value, expiration times, fees);
+ */
+typedef void
+(*TALER_EXCHANGEDB_DenominationCallback)(
+ void *cls,
+ uint64_t denom_serial,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue);
+
+/**
+ * Fetch information about all known denomination keys.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each denomination key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_iterate_denomination_info (struct EXCHANGEDB_PostgresContext *ctx,
+ TALER_EXCHANGEDB_DenominationCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/iterate_denominations.h b/src/include/taler/exchange-database/iterate_denominations.h
@@ -0,0 +1,287 @@
+/*
+ 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 src/include/taler/exchange-database/iterate_denominations.h
+ * @brief implementation of the iterate_denominations function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ITERATE_DENOMINATIONS_H
+#define EXCHANGE_DATABASE_ITERATE_DENOMINATIONS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * @brief All information about a denomination key (which is used to
+ * sign coins into existence).
+ */
+struct TALER_EXCHANGEDB_DenominationKey
+{
+ /**
+ * The private key of the denomination. Will be NULL if the private
+ * key is not available (this is the case after the key has expired
+ * for signing coins, but is still valid for depositing coins).
+ */
+ struct TALER_DenominationPrivateKey denom_priv;
+
+ /**
+ * Decoded denomination public key (the hash of it is in
+ * @e issue, but we sometimes need the full public key as well).
+ */
+ struct TALER_DenominationPublicKey denom_pub;
+
+ /**
+ * Signed public information about a denomination key.
+ */
+ struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
+};
+
+
+/**
+ * @brief Information we keep on bank transfer(s) that established a reserve.
+ */
+struct TALER_EXCHANGEDB_BankTransfer
+{
+
+ /**
+ * Public key of the reserve that was filled.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Amount that was transferred to the exchange.
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * When did the exchange receive the incoming transaction?
+ * (This is the execution date of the exchange's database,
+ * the execution date of the bank should be in @e wire).
+ */
+ struct GNUNET_TIME_Timestamp execution_date;
+
+ /**
+ * Detailed wire information about the sending account
+ * in "payto://" format.
+ */
+ struct TALER_FullPayto sender_account_details;
+
+ /**
+ * Data uniquely identifying the wire transfer (wire transfer-type specific)
+ */
+ uint64_t wire_reference;
+
+};
+
+
+/**
+ * @brief Information we keep on bank transfer(s) that
+ * closed a reserve.
+ */
+struct TALER_EXCHANGEDB_ClosingTransfer
+{
+
+ /**
+ * Public key of the reserve that was depleted.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Amount that was transferred from the exchange.
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Amount that was charged by the exchange.
+ */
+ struct TALER_Amount closing_fee;
+
+ /**
+ * When did the exchange execute the transaction?
+ */
+ struct GNUNET_TIME_Timestamp execution_date;
+
+ /**
+ * Detailed wire information about the receiving account
+ * in payto://-format.
+ */
+ struct TALER_FullPayto receiver_account_details;
+
+ /**
+ * Detailed wire transfer information that uniquely identifies the
+ * wire transfer.
+ */
+ struct TALER_WireTransferIdentifierRawP wtid;
+
+};
+
+
+/**
+ * @brief A summary of a Reserve
+ */
+struct TALER_EXCHANGEDB_Reserve
+{
+ /**
+ * The reserve's public key. This uniquely identifies the reserve
+ */
+ struct TALER_ReservePublicKeyP pub;
+
+ /**
+ * The balance amount existing in the reserve
+ */
+ struct TALER_Amount balance;
+
+ /**
+ * The expiration date of this reserve; funds will be wired back
+ * at this time.
+ */
+ struct GNUNET_TIME_Timestamp expiry;
+
+ /**
+ * The legal expiration date of this reserve; we will forget about
+ * it at this time.
+ */
+ struct GNUNET_TIME_Timestamp gc;
+};
+
+
+/**
+ * Meta data about a denomination public key.
+ * If this is changed, you must also adjust
+ * taler-exchange-httpd-post-management-keys.c::denomination_meta_cmp().
+ */
+struct TALER_EXCHANGEDB_DenominationKeyMetaData
+{
+ /**
+ * Serial of the denomination key as in the DB.
+ * Can be used calls to stored procedures in order to spare
+ * additional lookups.
+ */
+ uint64_t serial;
+
+ /**
+ * Start time of the validity period for this key.
+ */
+ struct GNUNET_TIME_Timestamp start;
+
+ /**
+ * The exchange will sign fresh coins between @e start and this time.
+ * @e expire_withdraw will be somewhat larger than @e start to
+ * ensure a sufficiently large anonymity set, while also allowing
+ * the Exchange to limit the financial damage in case of a key being
+ * compromised. Thus, exchanges with low volume are expected to have a
+ * longer withdraw period (@e expire_withdraw - @e start) than exchanges
+ * with high transaction volume. The period may also differ between
+ * types of coins. A exchange may also have a few denomination keys
+ * with the same value with overlapping validity periods, to address
+ * issues such as clock skew.
+ */
+ struct GNUNET_TIME_Timestamp expire_withdraw;
+
+ /**
+ * Coins signed with the denomination key must be spent or refreshed
+ * between @e start and this expiration time. After this time, the
+ * exchange will refuse transactions involving this key as it will
+ * "drop" the table with double-spending information (shortly after)
+ * this time. Note that wallets should refresh coins significantly
+ * before this time to be on the safe side. @e expire_deposit must be
+ * significantly larger than @e expire_withdraw (by months or even
+ * years).
+ */
+ struct GNUNET_TIME_Timestamp expire_deposit;
+
+ /**
+ * When do signatures with this denomination key become invalid?
+ * After this point, these signatures cannot be used in (legal)
+ * disputes anymore, as the Exchange is then allowed to destroy its side
+ * of the evidence. @e expire_legal is expected to be significantly
+ * larger than @e expire_deposit (by a year or more).
+ */
+ struct GNUNET_TIME_Timestamp expire_legal;
+
+ /**
+ * The value of the coins signed with this denomination key.
+ */
+ struct TALER_Amount value;
+
+ /**
+ * The fees the exchange charges for operations with
+ * coins of this denomination.
+ */
+ struct TALER_DenomFeeSet fees;
+
+ /**
+ * Age restriction for the denomination. (can be zero). If not zero, the bits
+ * set in the mask mark the edges at the beginning of a next age group. F.e.
+ * for the age groups
+ * 0-7, 8-9, 10-11, 12-14, 14-15, 16-17, 18-21, 21-*
+ * the following bits are set:
+ *
+ * 31 24 16 8 0
+ * | | | | |
+ * oooooooo oo1oo1o1 o1o1o1o1 ooooooo1
+ *
+ * A value of 0 means that the denomination does not support the extension for
+ * age-restriction.
+ */
+ struct TALER_AgeMask age_mask;
+};
+
+
+/**
+ * Signature of a function called with information about the exchange's
+ * denomination keys.
+ *
+ * @param cls closure with a `struct TEH_KeyStateHandle *`
+ * @param denom_pub public key of the denomination
+ * @param h_denom_pub hash of @a denom_pub
+ * @param meta meta data information about the denomination type (value, expirations, fees)
+ * @param master_sig master signature affirming the validity of this denomination
+ * @param recoup_possible true if the key was revoked and clients can currently recoup
+ * coins of this denomination
+ */
+typedef void
+(*TALER_EXCHANGEDB_DenominationsCallback)(
+ void *cls,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
+ const struct TALER_MasterSignatureP *master_sig,
+ bool recoup_possible);
+
+/**
+ * Function called to invoke @a cb on every known denomination key (revoked
+ * and non-revoked) that has been signed by the master key. Runs in its own
+ * read-only transaction.
+ *
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param cb function to call on each denomination key
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_iterate_denominations (struct EXCHANGEDB_PostgresContext *ctx,
+ TALER_EXCHANGEDB_DenominationsCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/iterate_kyc_reference.h b/src/include/taler/exchange-database/iterate_kyc_reference.h
@@ -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 pg_iterate_kyc_reference.h
+ * @brief implementation of the iterate_kyc_reference function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ITERATE_KYC_REFERENCE_H
+#define EXCHANGE_DATABASE_ITERATE_KYC_REFERENCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called on all legitimization operations
+ * we have performed for the given account so far
+ * (and that have not yet expired).
+ *
+ * @param cls closure
+ * @param kyc_provider_name name of the provider
+ * of the respective KYC process
+ * @param provider_user_id UID at a provider (can be NULL)
+ * @param legi_id legitimization process ID (can be NULL)
+ */
+typedef void
+(*TALER_EXCHANGEDB_LegitimizationProcessCallback)(
+ void *cls,
+ const char *kyc_provider_name,
+ const char *provider_user_id,
+ const char *legi_id);
+
+/**
+ * Call us on KYC legitimization processes satisfied and not expired for the
+ * given account.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto account identifier
+ * @param lpc function to call for each satisfied KYC legitimization process
+ * @param lpc_cls closure for @a lpc
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_iterate_kyc_reference (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_LegitimizationProcessCallback lpc,
+ void *lpc_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/iterate_reserve_close_info.h b/src/include/taler/exchange-database/iterate_reserve_close_info.h
@@ -0,0 +1,141 @@
+/*
+ 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.h
+ * @brief implementation of the iterate_reserve_close_info function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ITERATE_RESERVE_CLOSE_INFO_H
+#define EXCHANGE_DATABASE_ITERATE_RESERVE_CLOSE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Information per Clause-Schnorr (CS) fresh coin to
+ * be persisted for idempotency during refreshes-reveal.
+ */
+struct TALER_EXCHANGEDB_CsRevealFreshCoinData
+{
+ /**
+ * Denomination of the fresh coin.
+ */
+ struct TALER_DenominationHashP new_denom_pub_hash;
+
+ /**
+ * Blind signature of the fresh coin (possibly updated
+ * in case if a replay!).
+ */
+ struct TALER_BlindedDenominationSignature bsig;
+
+ /**
+ * Offset of the fresh coin in the reveal operation.
+ * (May not match the array offset as we may have
+ * a mixture of RSA and CS coins being created, and
+ * this request is only made for the CS subset).
+ */
+ uint32_t coin_off;
+};
+
+
+/**
+ * Generic KYC status for some operation.
+ */
+struct TALER_EXCHANGEDB_KycStatus
+{
+
+ /**
+ * Account public key that is currently associated
+ * with the account. Only set if @e have_account_pub
+ * is true.
+ */
+ union TALER_AccountPublicKeyP account_pub;
+
+ /**
+ * Number that identifies the KYC requirement the operation
+ * was about.
+ */
+ uint64_t requirement_row;
+
+ /**
+ * True if @e account_pub is set.
+ */
+ bool have_account_pub;
+
+ /**
+ * True if the KYC status is "satisfied".
+ */
+ bool ok;
+
+};
+
+
+struct TALER_EXCHANGEDB_ReserveInInfo
+{
+ const struct TALER_ReservePublicKeyP *reserve_pub;
+ const struct TALER_Amount *balance;
+ struct GNUNET_TIME_Timestamp execution_time;
+ struct TALER_FullPayto sender_account_details;
+ const char *exchange_account_name;
+ uint64_t wire_reference;
+};
+
+
+/**
+ * Function called on each @a amount that was found to
+ * be relevant for a KYC check.
+ *
+ * @param cls closure to allow the KYC module to
+ * total up amounts and evaluate rules
+ * @param amount encountered transaction amount
+ * @param date when was the amount encountered
+ * @return #GNUNET_OK to continue to iterate,
+ * #GNUNET_NO to abort iteration
+ * #GNUNET_SYSERR on internal error (also abort itaration)
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_KycAmountCallback)(
+ void *cls,
+ const struct TALER_Amount *amount,
+ struct GNUNET_TIME_Absolute date);
+
+/**
+ * Select information needed for KYC checks on reserve close: historic
+ * reserve closures going to the same account.
+ *
+ * @param cls closure
+ * @param h_payto which target account is this about?
+ * @param time_limit oldest transaction that could be relevant
+ * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK).
+ * @param kac_cls closure for @a kac
+ * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_iterate_reserve_close_info (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_KycAmountCallback kac,
+ void *kac_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/kyc_provider_account_lookup.h b/src/include/taler/exchange-database/kyc_provider_account_lookup.h
@@ -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 src/include/taler/exchange-database/kyc_provider_account_lookup.h
+ * @brief implementation of the kyc_provider_account_lookup function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_KYC_PROVIDER_ACCOUNT_LOOKUP_H
+#define EXCHANGE_DATABASE_KYC_PROVIDER_ACCOUNT_LOOKUP_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup an
+ * @a h_payto by @a provider_legitimization_id.
+ *
+ * @param cls closure
+ * @param provider_name
+ * @param provider_legitimization_id legi to look up
+ * @param[out] h_payto where to write the result
+ * @param[out] is_wallet set to true if @a h_payto is for a wallet
+ * @param[out] process_row where to write the row of the entry
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_kyc_provider_account_lookup (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *provider_name,
+ const char *provider_legitimization_id,
+ struct TALER_NormalizedPaytoHashP *h_payto,
+ bool *is_wallet,
+ uint64_t *process_row);
+
+#endif
diff --git a/src/include/taler/exchange-database/kycauth_in_insert.h b/src/include/taler/exchange-database/kycauth_in_insert.h
@@ -0,0 +1,53 @@
+/*
+ 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 src/include/taler/exchange-database/kycauth_in_insert.h
+ * @brief implementation of the kycauth_in_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_KYCAUTH_IN_INSERT_H
+#define EXCHANGE_DATABASE_KYCAUTH_IN_INSERT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert an incoming KCYAUTH wire transfer into
+ * the database and update the authentication key
+ * for the origin account.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param account_pub public key of the account
+ * @param credit_amount amount we were credited
+ * @param execution_date when was the transfer made
+ * @param debit_account_uri URI of the debit account
+ * @param section_name section of the exchange bank account that received the transfer
+ * @param serial_id bank-specific row identifying the transfer
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_kycauth_in_insert (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_active_legitimization.h b/src/include/taler/exchange-database/lookup_active_legitimization.h
@@ -0,0 +1,50 @@
+/*
+ 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 src/include/taler/exchange-database/lookup_active_legitimization.h
+ * @brief implementation of the lookup_active_legitimization function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_ACTIVE_LEGITIMIZATION_H
+#define EXCHANGE_DATABASE_LOOKUP_ACTIVE_LEGITIMIZATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup measure data for an active legitimization process.
+ *
+ * @param cls closure
+ * @param legitimization_process_serial_id
+ * row in legitimization_processes table to access
+ * @param[out] measure_index set to the measure the
+ * process is trying to satisfy
+ * @param[out] jmeasures set to the legitimization
+ * measures that were put on the account
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_active_legitimization (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t legitimization_process_serial_id,
+ uint32_t *measure_index,
+ json_t **jmeasures);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_aml_file_number.h b/src/include/taler/exchange-database/lookup_aml_file_number.h
@@ -0,0 +1,47 @@
+/*
+ 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 src/include/taler/exchange-database/lookup_aml_file_number.h
+ * @brief implementation of the lookup_aml_file_number function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_AML_FILE_NUMBER_H
+#define EXCHANGE_DATABASE_LOOKUP_AML_FILE_NUMBER_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup AML file number by the payto address.
+ *
+ * @param cls closure
+ * @param h_payto account for which to find the row ID
+ * @param[out] kyc_target_row set to row in the kyc_targets table for @a h_payto
+ * @param[out] is_wallet set to true if this account is for a wallet
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_aml_file_number (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ uint64_t *kyc_target_row,
+ bool *is_wallet);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_aml_history.h b/src/include/taler/exchange-database/lookup_aml_history.h
@@ -0,0 +1,82 @@
+/*
+ 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 src/include/taler/exchange-database/lookup_aml_history.h
+ * @brief implementation of the lookup_aml_history function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_AML_HISTORY_H
+#define EXCHANGE_DATABASE_LOOKUP_AML_HISTORY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with historic AML events of an
+ * account.
+ *
+ * @param cls closure
+ * @param outcome_serial_id row ID of the decision
+ * @param decision_time when was the decision taken
+ * @param justification what was the given justification
+ * @param decider_pub which key signed the decision
+ * @param jproperties what are the new account properties
+ * @param jnew_rules what are the new account rules
+ * @param to_investigate should AML staff investigate
+ * after the decision
+ * @param is_active is this the active decision
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlHistoryCallback) (
+ void *cls,
+ uint64_t outcome_serial_id,
+ struct GNUNET_TIME_Timestamp decision_time,
+ const char *justification,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ const json_t *jproperties,
+ const json_t *jnew_rules,
+ bool to_investigate,
+ bool is_active);
+
+/**
+ * Lookup AML history for an account identified via
+ * @a h_payto.
+ *
+ * @param cls closure
+ * @param h_payto hash of account to lookup history for
+ * @param offset row ID to start returning results from
+ * @param limit how many results to return, negative for descending order
+ * @param cb function to call on results
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_aml_history (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ uint64_t offset,
+ int64_t limit,
+ TALER_EXCHANGEDB_AmlHistoryCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_aml_officer.h b/src/include/taler/exchange-database/lookup_aml_officer.h
@@ -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 src/include/taler/exchange-database/lookup_aml_officer.h
+ * @brief implementation of the lookup_aml_officer function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_AML_OFFICER_H
+#define EXCHANGE_DATABASE_LOOKUP_AML_OFFICER_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Fetch AML staff record.
+ *
+ * @param cls closure
+ * @param decider_pub public key of the staff member
+ * @param[out] master_sig offline signature affirming the AML officer
+ * @param[out] decider_name full name of the staff member
+ * @param[out] is_active true to enable, false to set as inactive
+ * @param[out] read_only true to set read-only access
+ * @param[out] last_change when was the change made effective
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_aml_officer (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_auditor_status.h b/src/include/taler/exchange-database/lookup_auditor_status.h
@@ -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 src/include/taler/exchange-database/lookup_auditor_status.h
+ * @brief implementation of the lookup_auditor_status function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_AUDITOR_STATUS_H
+#define EXCHANGE_DATABASE_LOOKUP_AUDITOR_STATUS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup current state of an auditor.
+ *
+ * @param cls closure
+ * @param auditor_pub key to look up information for
+ * @param[out] auditor_url set to the base URL of the auditor's REST API; memory to be
+ * released by the caller!
+ * @param[out] enabled set if the auditor is currently in use
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_auditor_status (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ char **auditor_url,
+ bool *enabled);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_auditor_timestamp.h b/src/include/taler/exchange-database/lookup_auditor_timestamp.h
@@ -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 src/include/taler/exchange-database/lookup_auditor_timestamp.h
+ * @brief implementation of the lookup_auditor_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_AUDITOR_TIMESTAMP_H
+#define EXCHANGE_DATABASE_LOOKUP_AUDITOR_TIMESTAMP_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Check the last date an auditor was modified.
+ *
+ * @param cls closure
+ * @param auditor_pub key to look up information for
+ * @param[out] last_date last modification date to auditor status
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_auditor_timestamp (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ struct GNUNET_TIME_Timestamp *last_date);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_completed_legitimization.h b/src/include/taler/exchange-database/lookup_completed_legitimization.h
@@ -0,0 +1,67 @@
+/*
+ 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.h
+ * @brief implementation of the lookup_pending_legitimization function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_COMPLETED_LEGITIMIZATION_H
+#define EXCHANGE_DATABASE_LOOKUP_COMPLETED_LEGITIMIZATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup measure data for a legitimization process.
+ *
+ * @param cls closure
+ * @param legitimization_measure_serial_id
+ * row in legitimization_measures table to access
+ * @param measure_index index of the measure to return
+ * attribute data for
+ * @param[out] access_token
+ * set to token for access control that must match
+ * @param[out] h_payto set to the the hash of the
+ * payto URI of the account undergoing legitimization
+ * @param[out] is_wallet set to true if @a h_payto is for a wallet
+ * @param[out] jmeasures set to the legitimization
+ * measures that were put on the account
+ * @param[out] is_finished set to true if the legitimization was
+ * already finished
+ * @param[out] encrypted_attributes_len set to length of
+ * @a encrypted_attributes
+ * @param[out] encrypted_attributes set to the attributes
+ * obtained for the legitimization process, if it
+ * succeeded, otherwise set to NULL
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_completed_legitimization (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_denomination_key.h b/src/include/taler/exchange-database/lookup_denomination_key.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/lookup_denomination_key.h
+ * @brief implementation of the lookup_denomination_key function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_DENOMINATION_KEY_H
+#define EXCHANGE_DATABASE_LOOKUP_DENOMINATION_KEY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup information about current denomination key.
+ *
+ * @param cls closure
+ * @param h_denom_pub hash of the denomination public key
+ * @param[out] meta set to various meta data about the key
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_denomination_key (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_global_fee_by_time.h b/src/include/taler/exchange-database/lookup_global_fee_by_time.h
@@ -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 src/include/taler/exchange-database/lookup_global_fee_by_time.h
+ * @brief implementation of the lookup_global_fee_by_time function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_GLOBAL_FEE_BY_TIME_H
+#define EXCHANGE_DATABASE_LOOKUP_GLOBAL_FEE_BY_TIME_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup information about known global fees.
+ *
+ * @param cls closure
+ * @param start_time starting time of fee
+ * @param end_time end time of fee
+ * @param[out] fees set to wire fees for that time period; if
+ * different global fee exists within this time
+ * period, an 'invalid' amount is returned.
+ * @param[out] purse_timeout set to when unmerged purses expire
+ * @param[out] history_expiration set to when we expire reserve histories
+ * @param[out] purse_account_limit set to number of free purses
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_global_fee_by_time (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_h_payto_by_access_token.h b/src/include/taler/exchange-database/lookup_h_payto_by_access_token.h
@@ -0,0 +1,49 @@
+/*
+ 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 src/include/taler/exchange-database/lookup_h_payto_by_access_token.h
+ * @brief implementation of the lookup_h_payto_by_access_token function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_H_PAYTO_BY_ACCESS_TOKEN_H
+#define EXCHANGE_DATABASE_LOOKUP_H_PAYTO_BY_ACCESS_TOKEN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup @a h_payto based on an @a access_token.
+ *
+ * @param cls closure
+ * @param access_token
+ * set to token for access control
+ * @param[out] h_payto set to the the hash of the
+ * payto URI of the account (if found)
+ * @param[out] is_wallet set to true if @a h_payto
+ * is for a wallet
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_h_payto_by_access_token (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_AccountAccessTokenP *access_token,
+ struct TALER_NormalizedPaytoHashP *h_payto,
+ bool *is_wallet);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_kyc_history.h b/src/include/taler/exchange-database/lookup_kyc_history.h
@@ -0,0 +1,83 @@
+/*
+ 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 src/include/taler/exchange-database/lookup_kyc_history.h
+ * @brief implementation of the lookup_kyc_history function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_KYC_HISTORY_H
+#define EXCHANGE_DATABASE_LOOKUP_KYC_HISTORY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with historic KYC events of an
+ * account.
+ *
+ * @param cls closure
+ * @param provider_name name of the KYC provider
+ * @param finished did the KYC process finish
+ * @param error_code error code from the KYC process
+ * @param error_message error message from the KYC process,
+ * or NULL for none
+ * @param provider_user_id user ID at the provider
+ * or NULL for none
+ * @param provider_legitimization_id legitimization process ID at the provider
+ * or NULL for none
+ * @param collection_time when was the data collected
+ * @param expiration_time when does the collected data expire
+ * @param encrypted_attributes_len number of bytes in @a encrypted_attributes
+ * @param encrypted_attributes encrypted KYC attributes
+ */
+typedef void
+(*TALER_EXCHANGEDB_KycHistoryCallback) (
+ void *cls,
+ const char *provider_name,
+ bool finished,
+ enum TALER_ErrorCode error_code,
+ const char *error_message,
+ const char *provider_user_id,
+ const char *provider_legitimization_id,
+ struct GNUNET_TIME_Timestamp collection_time,
+ struct GNUNET_TIME_Absolute expiration_time,
+ size_t encrypted_attributes_len,
+ const void *encrypted_attributes);
+
+/**
+ * Lookup KYC history for an account identified via
+ * @a h_payto.
+ *
+ * @param cls closure
+ * @param h_payto hash of account to lookup history for
+ * @param cb function to call on results
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_kyc_history (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_KycHistoryCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_kyc_process_by_account.h b/src/include/taler/exchange-database/lookup_kyc_process_by_account.h
@@ -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 src/include/taler/exchange-database/lookup_kyc_process_by_account.h
+ * @brief implementation of the lookup_kyc_process_by_account function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_KYC_PROCESS_BY_ACCOUNT_H
+#define EXCHANGE_DATABASE_LOOKUP_KYC_PROCESS_BY_ACCOUNT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup KYC provider meta data.
+ *
+ * @param cls closure
+ * @param provider_name provider that must be checked
+ * @param h_payto account that must be KYC'ed
+ * @param[out] process_row row with the legitimization data
+ * @param[out] expiration how long is this KYC check set to be valid (in the past if invalid)
+ * @param[out] provider_account_id provider account ID
+ * @param[out] provider_legitimization_id provider legitimization ID
+ * @param[out] is_wallet set to true if @a h_payto is for a wallet
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_kyc_process_by_account (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_kyc_requirement_by_row.h b/src/include/taler/exchange-database/lookup_kyc_requirement_by_row.h
@@ -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 src/include/taler/exchange-database/lookup_kyc_requirement_by_row.h
+ * @brief implementation of the lookup_kyc_requirement_by_row function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_KYC_REQUIREMENT_BY_ROW_H
+#define EXCHANGE_DATABASE_LOOKUP_KYC_REQUIREMENT_BY_ROW_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup KYC requirement.
+ *
+ * @param cls closure
+ * @param h_payto identifies account to look up requirement for
+ * @param account_pub set to public key of the account
+ * needed to authorize access
+ * @param[out] is_wallet set to #GNUNET_YES if the account is
+ * that of a wallet (#GNUNET_SYSERR is used if unknown)
+ * @param[out] access_token set to the access token to begin
+ * work on KYC processes for this account
+ * @param[out] rule_gen row ID of the last decision this
+ * response is based on (for long-polling by clients)
+ * @param[out] jrules set to active ``LegitimizationRuleSet``
+ * of the account impacted by the requirement
+ * @param[out] aml_review set to true if the account is under
+ * active review by AML staff
+ * @param[out] kyc_required set to true if the user must pass
+ * some KYC check before some previous operation may continue
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_kyc_requirement_by_row (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_kyc_status_by_token.h b/src/include/taler/exchange-database/lookup_kyc_status_by_token.h
@@ -0,0 +1,47 @@
+/*
+ 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 src/include/taler/exchange-database/lookup_kyc_status_by_token.h
+ * @brief implementation of the lookup_kyc_status_by_token function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_KYC_STATUS_BY_TOKEN_H
+#define EXCHANGE_DATABASE_LOOKUP_KYC_STATUS_BY_TOKEN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup KYC status by account access token.
+ *
+ * @param cls closure
+ * @param access_token key to look under
+ * @param[out] row set to requirement row that matches
+ * @param[out] jmeasures set to the LegitimizationMeasures for the @a access_token; must be freed by caller!
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_kyc_status_by_token (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_AccountAccessTokenP *access_token,
+ uint64_t *row,
+ json_t **jmeasures);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_pending_legitimization.h b/src/include/taler/exchange-database/lookup_pending_legitimization.h
@@ -0,0 +1,57 @@
+/*
+ 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 src/include/taler/exchange-database/lookup_pending_legitimization.h
+ * @brief implementation of the lookup_pending_legitimization function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_PENDING_LEGITIMIZATION_H
+#define EXCHANGE_DATABASE_LOOKUP_PENDING_LEGITIMIZATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup measure data for a legitimization process.
+ *
+ * @param cls closure
+ * @param legitimization_measure_serial_id
+ * row in legitimization_measures table to access
+ * @param[out] access_token
+ * set to token for access control that must match
+ * @param[out] h_payto set to the the hash of the
+ * payto URI of the account undergoing legitimization
+ * @param[out] jmeasures set to the legitimization
+ * measures that were put on the account
+ * @param[out] is_finished set to true if the legitimization was
+ * already finished
+ * @param[out] is_wallet set to true if @a h_payto is for a wallet
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_pending_legitimization (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_records_by_table.h b/src/include/taler/exchange-database/lookup_records_by_table.h
@@ -0,0 +1,904 @@
+/*
+ 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_lookup_records_by_table.h
+ * @brief implementation of the lookup_records_by_table function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_RECORDS_BY_TABLE_H
+#define EXCHANGE_DATABASE_LOOKUP_RECORDS_BY_TABLE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+/* Callback typedefs */
+/**
+ * @file include/taler/taler_exchangedb_plugin.h
+ * @brief Low-level (statement-level) database access for the exchange
+ * @author Florian Dold
+ * @author Christian Grothoff
+ * @author Özgür Kesim
+ */
+#ifndef TALER_EXCHANGEDB_PLUGIN_H
+#define TALER_EXCHANGEDB_PLUGIN_H
+#include <jansson.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_db_lib.h>
+#include <taler/taler_util.h>
+#include <taler/taler_signatures.h>
+#include <taler/taler_extensions_policy.h>
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * The conflict that can occur for the age restriction
+ */
+enum TALER_EXCHANGEDB_AgeCommitmentHash_Conflict
+{
+ /**
+ * Value OK, no conflict
+ */
+ TALER_AgeCommitmentHashP_NoConflict = 0,
+
+ /**
+ * Given hash had a value, but NULL (or zero) was expected
+ */
+ TALER_AgeCommitmentHashP_NullExpected = 1,
+
+ /**
+ * Given hash was NULL, but value was expected
+ */
+ TALER_AgeCommitmentHashP_ValueExpected = 2,
+
+ /**
+ * Given hash differs from value in the known coin
+ */
+ TALER_AgeCommitmentHashP_ValueDiffers = 3,
+};
+
+/**
+ * Per-coin information returned when doing a batch insert.
+ */
+struct TALER_EXCHANGEDB_CoinInfo
+{
+ /**
+ * Row of the coin in the known_coins table.
+ */
+ uint64_t known_coin_id;
+
+ /**
+ * Hash of the denomination, relevant on @e denom_conflict.
+ */
+ struct TALER_DenominationHashP denom_hash;
+
+ /**
+ * Hash of the age commitment, relevant on @e age_conflict.
+ */
+ struct TALER_AgeCommitmentHashP h_age_commitment;
+
+ /**
+ * True if the coin was known previously.
+ */
+ bool existed;
+
+ /**
+ * True if the known coin has a different denomination;
+ * application will find denomination of the already
+ * known coin in @e denom_hash.
+ */
+ bool denom_conflict;
+
+ /**
+ * Indicates if and what kind of conflict with the age
+ * restriction of the known coin was present;
+ * application will find age commitment of the already
+ * known coin in @e h_age_commitment.
+ */
+ enum TALER_EXCHANGEDB_AgeCommitmentHash_Conflict age_conflict;
+};
+
+
+/**
+ * Information about a denomination key.
+ */
+struct TALER_EXCHANGEDB_DenominationKeyInformation
+{
+
+ /**
+ * Signature over this struct to affirm the validity of the key.
+ */
+ struct TALER_MasterSignatureP signature;
+
+ /**
+ * Start time of the validity period for this key.
+ */
+ struct GNUNET_TIME_Timestamp start;
+
+ /**
+ * The exchange will sign fresh coins between @e start and this time.
+ * @e expire_withdraw will be somewhat larger than @e start to
+ * ensure a sufficiently large anonymity set, while also allowing
+ * the Exchange to limit the financial damage in case of a key being
+ * compromised. Thus, exchanges with low volume are expected to have a
+ * longer withdraw period (@e expire_withdraw - @e start) than exchanges
+ * with high transaction volume. The period may also differ between
+ * types of coins. A exchange may also have a few denomination keys
+ * with the same value with overlapping validity periods, to address
+ * issues such as clock skew.
+ */
+ struct GNUNET_TIME_Timestamp expire_withdraw;
+
+ /**
+ * Coins signed with the denomination key must be spent or refreshed
+ * between @e start and this expiration time. After this time, the
+ * exchange will refuse transactions involving this key as it will
+ * "drop" the table with double-spending information (shortly after)
+ * this time. Note that wallets should refresh coins significantly
+ * before this time to be on the safe side. @e expire_deposit must be
+ * significantly larger than @e expire_withdraw (by months or even
+ * years).
+ */
+ struct GNUNET_TIME_Timestamp expire_deposit;
+
+ /**
+ * When do signatures with this denomination key become invalid?
+ * After this point, these signatures cannot be used in (legal)
+ * disputes anymore, as the Exchange is then allowed to destroy its side
+ * of the evidence. @e expire_legal is expected to be significantly
+ * larger than @e expire_deposit (by a year or more).
+ */
+ struct GNUNET_TIME_Timestamp expire_legal;
+
+ /**
+ * The value of the coins signed with this denomination key.
+ */
+ struct TALER_Amount value;
+
+ /**
+ * Fees for the coin.
+ */
+ struct TALER_DenomFeeSet fees;
+
+ /**
+ * Hash code of the denomination public key. (Used to avoid having
+ * the variable-size RSA key in this struct.)
+ */
+ struct TALER_DenominationHashP denom_hash;
+
+ /**
+ * If denomination was setup for age restriction, non-zero age mask.
+ * Note that the mask is not part of the signature.
+ */
+ struct TALER_AgeMask age_mask;
+};
+
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Events signalling that a coin deposit status
+ * changed.
+ */
+struct TALER_CoinDepositEventP
+{
+ /**
+ * Of type #TALER_DBEVENT_EXCHANGE_DEPOSIT_STATUS_CHANGED.
+ */
+ struct GNUNET_DB_EventHeaderP header;
+
+ /**
+ * Public key of the merchant.
+ */
+ struct TALER_MerchantPublicKeyP merchant_pub;
+
+};
+
+/**
+ * Events signalling a reserve got funding.
+ */
+struct TALER_ReserveEventP
+{
+ /**
+ * Of type #TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING.
+ */
+ struct GNUNET_DB_EventHeaderP header;
+
+ /**
+ * Public key of the reserve the event is about.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+};
+
+
+/**
+ * Signature of events signalling a purse changed its status.
+ */
+struct TALER_PurseEventP
+{
+ /**
+ * Of type #TALER_DBEVENT_EXCHANGE_PURSE_MERGED or
+ * #TALER_DBEVENT_EXCHANGE_PURSE_DEPOSITED.
+ */
+ struct GNUNET_DB_EventHeaderP header;
+
+ /**
+ * Public key of the purse the event is about.
+ */
+ struct TALER_PurseContractPublicKeyP purse_pub;
+};
+
+
+/**
+ * Signature of events signalling a KYC process was completed.
+ */
+struct TALER_KycCompletedEventP
+{
+ /**
+ * Of type #TALER_DBEVENT_EXCHANGE_KYC_COMPLETED.
+ */
+ struct GNUNET_DB_EventHeaderP header;
+
+ /**
+ * Hash of payto://-URI for which the KYC state changed.
+ */
+ struct TALER_NormalizedPaytoHashP h_payto;
+};
+
+
+GNUNET_NETWORK_STRUCT_END
+
+/**
+ * Meta data about an exchange online signing key.
+ */
+struct TALER_EXCHANGEDB_SignkeyMetaData
+{
+ /**
+ * Start time of the validity period for this key.
+ */
+ struct GNUNET_TIME_Timestamp start;
+
+ /**
+ * The exchange will sign messages with this key between @e start and this time.
+ */
+ struct GNUNET_TIME_Timestamp expire_sign;
+
+ /**
+ * When do signatures with this sign key become invalid?
+ * After this point, these signatures cannot be used in (legal)
+ * disputes anymore, as the Exchange is then allowed to destroy its side
+ * of the evidence. @e expire_legal is expected to be significantly
+ * larger than @e expire_sign (by a year or more).
+ */
+ struct GNUNET_TIME_Timestamp expire_legal;
+
+};
+
+
+/**
+ * Enumeration of all of the tables replicated by exchange-auditor
+ * database replication.
+ *
+ * Note: wire_accounts is not replicated. So far not needed by the auditor.
+ */
+enum TALER_EXCHANGEDB_ReplicatedTable
+{
+ TALER_EXCHANGEDB_RT_DENOMINATIONS,
+ TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS,
+ TALER_EXCHANGEDB_RT_KYC_TARGETS,
+ TALER_EXCHANGEDB_RT_WIRE_TARGETS,
+ TALER_EXCHANGEDB_RT_RESERVES,
+ TALER_EXCHANGEDB_RT_RESERVES_IN,
+ TALER_EXCHANGEDB_RT_RESERVES_CLOSE,
+ TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS,
+ TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS,
+ TALER_EXCHANGEDB_RT_AUDITORS,
+ TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS,
+ TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS,
+ TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS,
+ TALER_EXCHANGEDB_RT_KNOWN_COINS,
+ TALER_EXCHANGEDB_RT_REFRESH,
+ TALER_EXCHANGEDB_RT_BATCH_DEPOSITS,
+ TALER_EXCHANGEDB_RT_COIN_DEPOSITS,
+ TALER_EXCHANGEDB_RT_REFUNDS,
+ TALER_EXCHANGEDB_RT_WIRE_OUT,
+ TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING,
+ TALER_EXCHANGEDB_RT_WIRE_FEE,
+ TALER_EXCHANGEDB_RT_GLOBAL_FEE,
+ TALER_EXCHANGEDB_RT_RECOUP,
+ TALER_EXCHANGEDB_RT_RECOUP_REFRESH,
+ TALER_EXCHANGEDB_RT_EXTENSIONS,
+ TALER_EXCHANGEDB_RT_POLICY_DETAILS,
+ TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS,
+ TALER_EXCHANGEDB_RT_PURSE_REQUESTS,
+ TALER_EXCHANGEDB_RT_PURSE_DECISION,
+ TALER_EXCHANGEDB_RT_PURSE_MERGES,
+ TALER_EXCHANGEDB_RT_PURSE_DEPOSITS,
+ TALER_EXCHANGEDB_RT_ACCOUNT_MERGES,
+ TALER_EXCHANGEDB_RT_HISTORY_REQUESTS,
+ TALER_EXCHANGEDB_RT_CLOSE_REQUESTS,
+ TALER_EXCHANGEDB_RT_WADS_OUT,
+ TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES,
+ TALER_EXCHANGEDB_RT_WADS_IN,
+ TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES,
+ TALER_EXCHANGEDB_RT_PROFIT_DRAINS,
+ TALER_EXCHANGEDB_RT_AML_STAFF,
+ TALER_EXCHANGEDB_RT_PURSE_DELETION,
+ TALER_EXCHANGEDB_RT_WITHDRAW,
+ TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES,
+ TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES,
+ TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES,
+ TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES,
+ TALER_EXCHANGEDB_RT_AML_HISTORY,
+ TALER_EXCHANGEDB_RT_KYC_EVENTS,
+ TALER_EXCHANGEDB_RT_KYCAUTHS_IN
+};
+
+
+/**
+ * Record of a single entry in a replicated table.
+ */
+struct TALER_EXCHANGEDB_TableData
+{
+ /**
+ * Data of which table is returned here?
+ */
+ enum TALER_EXCHANGEDB_ReplicatedTable table;
+
+ /**
+ * Serial number of the record.
+ */
+ uint64_t serial;
+
+ /**
+ * Table-specific details.
+ */
+ union
+ {
+
+ /**
+ * Details from the 'denominations' table.
+ */
+ struct
+ {
+ uint32_t denom_type;
+ uint32_t age_mask;
+ struct TALER_DenominationPublicKey denom_pub;
+ struct TALER_MasterSignatureP master_sig;
+ struct GNUNET_TIME_Timestamp valid_from;
+ struct GNUNET_TIME_Timestamp expire_withdraw;
+ struct GNUNET_TIME_Timestamp expire_deposit;
+ struct GNUNET_TIME_Timestamp expire_legal;
+ struct TALER_Amount coin;
+ struct TALER_DenomFeeSet fees;
+ } denominations;
+
+ struct
+ {
+ struct TALER_MasterSignatureP master_sig;
+ uint64_t denominations_serial;
+ } denomination_revocations;
+
+ struct
+ {
+ struct TALER_FullPayto full_payto_uri;
+ } wire_targets;
+
+ struct
+ {
+ struct TALER_NormalizedPaytoHashP h_normalized_payto;
+ struct TALER_AccountAccessTokenP access_token;
+ union TALER_AccountPublicKeyP target_pub;
+ bool no_account;
+ bool is_wallet;
+ } kyc_targets;
+
+ struct
+ {
+ struct TALER_AccountAccessTokenP target_token;
+ struct GNUNET_TIME_Timestamp start_time;
+ json_t *measures;
+ uint32_t display_priority;
+ } legitimization_measures;
+
+ struct
+ {
+ struct TALER_NormalizedPaytoHashP h_payto;
+ struct GNUNET_TIME_Timestamp decision_time;
+ struct GNUNET_TIME_Timestamp expiration_time;
+ json_t *properties;
+ bool to_investigate;
+ json_t *new_rules;
+ } legitimization_outcomes;
+
+ struct
+ {
+ struct TALER_NormalizedPaytoHashP h_payto;
+ struct GNUNET_TIME_Timestamp start_time;
+ struct GNUNET_TIME_Timestamp expiration_time;
+ uint64_t legitimization_measure_serial_id;
+ uint32_t measure_index;
+ char *provider_name;
+ char *provider_user_id;
+ char *provider_legitimization_id;
+ char *redirect_url;
+ } legitimization_processes;
+
+ struct
+ {
+ struct TALER_NormalizedPaytoHashP h_payto;
+ uint64_t legitimization_serial;
+ struct GNUNET_TIME_Timestamp collection_time;
+ struct GNUNET_TIME_Timestamp expiration_time;
+ uint64_t trigger_outcome_serial;
+ void *encrypted_attributes;
+ size_t encrypted_attributes_size;
+ } kyc_attributes;
+
+ struct
+ {
+ struct TALER_NormalizedPaytoHashP h_payto;
+ uint64_t outcome_serial_id;
+ char *justification;
+ struct TALER_AmlOfficerPublicKeyP decider_pub;
+ struct TALER_AmlOfficerSignatureP decider_sig;
+ } aml_history;
+
+ struct
+ {
+ struct GNUNET_TIME_Timestamp event_timestamp;
+ char *event_type;
+ } kyc_events;
+
+ struct
+ {
+ struct TALER_AmlOfficerPublicKeyP decider_pub;
+ struct TALER_MasterSignatureP master_sig;
+ char *decider_name;
+ bool is_active;
+ bool read_only;
+ struct GNUNET_TIME_Timestamp last_change;
+ } aml_staff;
+
+ struct
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct GNUNET_TIME_Timestamp expiration_date;
+ struct GNUNET_TIME_Timestamp gc_date;
+ } reserves;
+
+ struct
+ {
+ uint64_t wire_reference;
+ struct TALER_Amount credit;
+ struct TALER_FullPaytoHashP sender_account_h_payto;
+ char *exchange_account_section;
+ struct GNUNET_TIME_Timestamp execution_date;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ } reserves_in;
+
+ struct
+ {
+ uint64_t wire_reference;
+ struct TALER_Amount credit;
+ struct TALER_FullPaytoHashP sender_account_h_payto;
+ char *exchange_account_section;
+ struct GNUNET_TIME_Timestamp execution_date;
+ union TALER_AccountPublicKeyP account_pub;
+ } kycauth_in;
+
+ struct
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct GNUNET_TIME_Timestamp request_timestamp;
+ struct GNUNET_TIME_Timestamp expiration_date;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct TALER_Amount reserve_payment;
+ uint32_t requested_purse_limit;
+ } reserves_open_requests;
+
+ struct
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_CoinSpendSignatureP coin_sig;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct TALER_Amount contribution;
+ } reserves_open_deposits;
+
+ struct
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct GNUNET_TIME_Timestamp execution_date;
+ struct TALER_WireTransferIdentifierRawP wtid;
+ struct TALER_FullPaytoHashP sender_account_h_payto;
+ struct TALER_Amount amount;
+ struct TALER_Amount closing_fee;
+ } reserves_close;
+
+ struct
+ {
+ struct TALER_AuditorPublicKeyP auditor_pub;
+ char *auditor_url;
+ char *auditor_name;
+ bool is_active;
+ struct GNUNET_TIME_Timestamp last_change;
+ } auditors;
+
+ struct
+ {
+ uint64_t auditor_uuid;
+ uint64_t denominations_serial;
+ struct TALER_AuditorSignatureP auditor_sig;
+ } auditor_denom_sigs;
+
+ struct
+ {
+ struct TALER_ExchangePublicKeyP exchange_pub;
+ struct TALER_MasterSignatureP master_sig;
+ struct TALER_EXCHANGEDB_SignkeyMetaData meta;
+ } exchange_sign_keys;
+
+ struct
+ {
+ uint64_t esk_serial;
+ struct TALER_MasterSignatureP master_sig;
+ } signkey_revocations;
+
+ struct
+ {
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_AgeCommitmentHashP age_hash;
+ uint64_t denominations_serial;
+ struct TALER_DenominationSignature denom_sig;
+ } known_coins;
+
+ struct
+ {
+ struct TALER_RefreshCommitmentP rc;
+ struct GNUNET_TIME_Timestamp execution_date;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_CoinSpendPublicKeyP old_coin_pub;
+ struct TALER_CoinSpendSignatureP old_coin_sig;
+ struct TALER_PublicRefreshMasterSeedP refresh_seed;
+ uint32_t noreveal_index;
+ struct TALER_HashBlindedPlanchetsP planchets_h;
+ struct TALER_HashBlindedPlanchetsP selected_h;
+ bool no_blinding_seed;
+ struct TALER_BlindingMasterSeedP blinding_seed;
+ size_t num_cs_r_values;
+ struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values;
+ uint64_t cs_r_choices;
+ size_t num_coins;
+ uint64_t *denom_serials;
+ struct TALER_BlindedDenominationSignature *denom_sigs;
+ } refresh;
+
+ struct
+ {
+ uint64_t shard;
+ struct TALER_MerchantPublicKeyP merchant_pub;
+ struct GNUNET_TIME_Timestamp wallet_timestamp;
+ struct GNUNET_TIME_Timestamp exchange_timestamp;
+ struct GNUNET_TIME_Timestamp refund_deadline;
+ struct GNUNET_TIME_Timestamp wire_deadline;
+ struct TALER_PrivateContractHashP h_contract_terms;
+ bool no_wallet_data_hash;
+ struct GNUNET_HashCode wallet_data_hash;
+ struct TALER_WireSaltP wire_salt;
+ struct TALER_FullPaytoHashP wire_target_h_payto;
+ bool no_policy_details;
+ uint64_t policy_details_serial_id;
+ bool policy_blocked;
+ struct TALER_Amount total_amount;
+ struct TALER_Amount total_without_fee;
+ struct TALER_MerchantSignatureP merchant_sig;
+ bool done;
+ } batch_deposits;
+
+ struct
+ {
+ uint64_t batch_deposit_serial_id;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_CoinSpendSignatureP coin_sig;
+ struct TALER_Amount amount_with_fee;
+ } coin_deposits;
+
+ struct
+ {
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ uint64_t batch_deposit_serial_id;
+ struct TALER_MerchantSignatureP merchant_sig;
+ uint64_t rtransaction_id;
+ struct TALER_Amount amount_with_fee;
+ } refunds;
+
+ struct
+ {
+ struct GNUNET_TIME_Timestamp execution_date;
+ struct TALER_WireTransferIdentifierRawP wtid_raw;
+ struct TALER_FullPaytoHashP wire_target_h_payto;
+ char *exchange_account_section;
+ struct TALER_Amount amount;
+ } wire_out;
+
+ struct
+ {
+ uint64_t batch_deposit_serial_id;
+ struct TALER_WireTransferIdentifierRawP wtid_raw;
+ } aggregation_tracking;
+
+ struct
+ {
+ char *wire_method;
+ struct GNUNET_TIME_Timestamp start_date;
+ struct GNUNET_TIME_Timestamp end_date;
+ struct TALER_WireFeeSet fees;
+ struct TALER_MasterSignatureP master_sig;
+ } wire_fee;
+
+ struct
+ {
+ 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;
+ } global_fee;
+
+ struct
+ {
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_CoinSpendSignatureP coin_sig;
+ union GNUNET_CRYPTO_BlindingSecretP coin_blind;
+ struct TALER_Amount amount;
+ struct GNUNET_TIME_Timestamp timestamp;
+ uint64_t withdraw_serial_id;
+ } recoup;
+
+ struct
+ {
+ uint64_t known_coin_id;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_CoinSpendSignatureP coin_sig;
+ union GNUNET_CRYPTO_BlindingSecretP coin_blind;
+ struct TALER_Amount amount;
+ struct GNUNET_TIME_Timestamp timestamp;
+ uint64_t rrc_serial;
+ } recoup_refresh;
+
+ struct
+ {
+ char *name;
+ char *manifest;
+ } extensions;
+
+ struct
+ {
+ struct GNUNET_HashCode hash_code;
+ json_t *policy_json;
+ bool no_policy_json;
+ struct GNUNET_TIME_Timestamp deadline;
+ struct TALER_Amount commitment;
+ struct TALER_Amount accumulated_total;
+ struct TALER_Amount fee;
+ struct TALER_Amount transferable;
+ uint16_t fulfillment_state; /* will also be recomputed */
+ uint64_t fulfillment_id;
+ bool no_fulfillment_id;
+ } policy_details;
+
+ struct
+ {
+ struct GNUNET_TIME_Timestamp fulfillment_timestamp;
+ char *fulfillment_proof;
+ struct GNUNET_HashCode h_fulfillment_proof;
+ struct GNUNET_HashCode *policy_hash_codes;
+ size_t policy_hash_codes_count;
+ } policy_fulfillments;
+
+ struct
+ {
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_PurseMergePublicKeyP merge_pub;
+ struct GNUNET_TIME_Timestamp purse_creation;
+ struct GNUNET_TIME_Timestamp purse_expiration;
+ struct TALER_PrivateContractHashP h_contract_terms;
+ uint32_t age_limit;
+ uint32_t flags;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_Amount purse_fee;
+ struct TALER_PurseContractSignatureP purse_sig;
+ } purse_requests;
+
+ struct
+ {
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct GNUNET_TIME_Timestamp action_timestamp;
+ bool refunded;
+ } purse_decision;
+
+ struct
+ {
+ uint64_t partner_serial_id;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_PurseMergeSignatureP merge_sig;
+ struct GNUNET_TIME_Timestamp merge_timestamp;
+ } purse_merges;
+
+ struct
+ {
+ uint64_t partner_serial_id;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_CoinSpendSignatureP coin_sig;
+ } purse_deposits;
+
+ struct
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_NormalizedPaytoHashP wallet_h_payto;
+ } account_merges;
+
+ struct
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct GNUNET_TIME_Timestamp request_timestamp;
+ struct TALER_Amount history_fee;
+ } history_requests;
+
+ struct
+ {
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct GNUNET_TIME_Timestamp close_timestamp;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct TALER_Amount close;
+ struct TALER_Amount close_fee;
+ struct TALER_FullPayto payto_uri;
+ } close_requests;
+
+ struct
+ {
+ struct TALER_WadIdentifierP wad_id;
+ uint64_t partner_serial_id;
+ struct TALER_Amount amount;
+ struct GNUNET_TIME_Timestamp execution_time;
+ } wads_out;
+
+ struct
+ {
+ uint64_t wad_out_serial_id;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_PrivateContractHashP h_contract;
+ struct GNUNET_TIME_Timestamp purse_expiration;
+ struct GNUNET_TIME_Timestamp merge_timestamp;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_Amount wad_fee;
+ struct TALER_Amount deposit_fees;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct TALER_PurseContractSignatureP purse_sig;
+ } wads_out_entries;
+
+ struct
+ {
+ struct TALER_WadIdentifierP wad_id;
+ char *origin_exchange_url;
+ struct TALER_Amount amount;
+ struct GNUNET_TIME_Timestamp arrival_time;
+ } wads_in;
+
+ struct
+ {
+ uint64_t wad_in_serial_id;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_PrivateContractHashP h_contract;
+ struct GNUNET_TIME_Timestamp purse_expiration;
+ struct GNUNET_TIME_Timestamp merge_timestamp;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_Amount wad_fee;
+ struct TALER_Amount deposit_fees;
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct TALER_PurseContractSignatureP purse_sig;
+ } wads_in_entries;
+
+ struct
+ {
+ struct TALER_WireTransferIdentifierRawP wtid;
+ char *account_section;
+ struct TALER_FullPayto payto_uri;
+ struct GNUNET_TIME_Timestamp trigger_date;
+ struct TALER_Amount amount;
+ struct TALER_MasterSignatureP master_sig;
+ } profit_drains;
+
+ struct
+ {
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_PurseContractSignatureP purse_sig;
+ } purse_deletion;
+
+ struct
+ {
+ struct TALER_HashBlindedPlanchetsP planchets_h;
+ struct GNUNET_TIME_Timestamp execution_date;
+ struct TALER_Amount amount_with_fee;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_ReserveSignatureP reserve_sig;
+ bool age_proof_required;
+ uint16_t max_age;
+ uint16_t noreveal_index;
+ struct TALER_HashBlindedPlanchetsP selected_h;
+ bool no_blinding_seed;
+ struct TALER_BlindingMasterSeedP blinding_seed;
+ size_t num_cs_r_values;
+ struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values;
+ uint64_t cs_r_choices;
+ size_t num_coins;
+ uint64_t *denom_serials;
+ struct TALER_BlindedDenominationSignature *denom_sigs;
+ } withdraw;
+
+ } details;
+
+};
+
+
+/**
+ * Function called on data to replicate in the auditor's database.
+ *
+ * @param cls closure
+ * @param td record from an exchange table
+ * @return #GNUNET_OK to continue to iterate,
+ * #GNUNET_SYSERR to fail with an error
+ */
+typedef int
+(*TALER_EXCHANGEDB_ReplicationCallback)(
+ void *cls,
+ const struct TALER_EXCHANGEDB_TableData *td);
+
+/**
+ * Lookup records above @a serial number in @a table. Used in
+ * exchange-auditor database replication.
+ *
+ * @param cls closure
+ * @param table table for which we should return the serial
+ * @param serial largest serial number to exclude
+ * @param cb function to call on the records
+ * @param cb_cls closure for @a cb
+ * @return transaction status code, GNUNET_DB_STATUS_HARD_ERROR if
+ * @a table does not have a serial number
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_records_by_table (struct EXCHANGEDB_PostgresContext *ctx,
+ enum TALER_EXCHANGEDB_ReplicatedTable table,
+ uint64_t serial,
+ TALER_EXCHANGEDB_ReplicationCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_rules_by_access_token.h b/src/include/taler/exchange-database/lookup_rules_by_access_token.h
@@ -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 src/include/taler/exchange-database/lookup_rules_by_access_token.h
+ * @brief implementation of the lookup_rules_by_access_token function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_RULES_BY_ACCESS_TOKEN_H
+#define EXCHANGE_DATABASE_LOOKUP_RULES_BY_ACCESS_TOKEN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup KYC rules by account access token.
+ *
+ * @param cls closure
+ * @param h_payto account hash to look under
+ * @param[out] jnew_rules set to active LegitimizationRuleSet
+ * @param[out] rowid set to outcome_serial_id of the row
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_rules_by_access_token (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ json_t **jnew_rules,
+ uint64_t *rowid);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_serial_by_table.h b/src/include/taler/exchange-database/lookup_serial_by_table.h
@@ -0,0 +1,47 @@
+/*
+ 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_lookup_serial_by_table.h
+ * @brief implementation of the lookup_serial_by_table function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_SERIAL_BY_TABLE_H
+#define EXCHANGE_DATABASE_LOOKUP_SERIAL_BY_TABLE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup the latest serial number of @a table. Used in
+ * exchange-auditor database replication.
+ *
+ * @param cls closure
+ * @param table table for which we should return the serial
+ * @param[out] serial latest serial number in use
+ * @return transaction status code, GNUNET_DB_STATUS_HARD_ERROR if
+ * @a table does not have a serial number
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_serial_by_table (struct EXCHANGEDB_PostgresContext *ctx,
+ enum TALER_EXCHANGEDB_ReplicatedTable table,
+ uint64_t *serial);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_signing_key.h b/src/include/taler/exchange-database/lookup_signing_key.h
@@ -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 src/include/taler/exchange-database/lookup_signing_key.h
+ * @brief implementation of the lookup_signing_key function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_SIGNING_KEY_H
+#define EXCHANGE_DATABASE_LOOKUP_SIGNING_KEY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Lookup signing key meta data.
+ *
+ * @param cls closure
+ * @param exchange_pub the exchange online signing public key
+ * @param[out] meta meta data about @a exchange_pub
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_signing_key (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ struct TALER_EXCHANGEDB_SignkeyMetaData *meta);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_signkey_revocation.h b/src/include/taler/exchange-database/lookup_signkey_revocation.h
@@ -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 src/include/taler/exchange-database/lookup_signkey_revocation.h
+ * @brief implementation of the lookup_signkey_revocation function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_SIGNKEY_REVOCATION_H
+#define EXCHANGE_DATABASE_LOOKUP_SIGNKEY_REVOCATION_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Obtain information about a revoked online signing key.
+ *
+ * @param cls closure
+ * @param exchange_pub exchange online signing key
+ * @param[out] master_sig set to signature affirming the revocation (if revoked)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_signkey_revocation (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_ExchangePublicKeyP *exchange_pub,
+ struct TALER_MasterSignatureP *master_sig);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_transfer_by_deposit.h b/src/include/taler/exchange-database/lookup_transfer_by_deposit.h
@@ -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 src/include/taler/exchange-database/lookup_transfer_by_deposit.h
+ * @brief implementation of the lookup_transfer_by_deposit function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_TRANSFER_BY_DEPOSIT_H
+#define EXCHANGE_DATABASE_LOOKUP_TRANSFER_BY_DEPOSIT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Try to find the wire transfer details for a deposit operation.
+ * If we did not execute the deposit yet, return when it is supposed
+ * to be executed.
+ *
+ * @param cls closure
+ * @param h_contract_terms hash of the proposal data
+ * @param h_wire hash of merchant wire details
+ * @param coin_pub public key of deposited coin
+ * @param merchant_pub merchant public key
+ * @param[out] pending set to true if the transaction is still pending
+ * @param[out] wtid wire transfer identifier, only set if @a pending is false
+ * @param[out] exec_time when was the transaction done, or
+ * when we expect it to be done (if @a pending is false)
+ * @param[out] amount_with_fee set to the total deposited amount
+ * @param[out] deposit_fee set to how much the exchange did charge for the deposit
+ * @param[out] kyc set to the kyc status of the receiver (if @a pending)
+ * @param[out] account_pub set to public key that is authorized to start the KYC process; unchanged if no such key is known
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_transfer_by_deposit (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_wire_fee_by_time.h b/src/include/taler/exchange-database/lookup_wire_fee_by_time.h
@@ -0,0 +1,77 @@
+/*
+ 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 src/include/taler/exchange-database/lookup_wire_fee_by_time.h
+ * @brief implementation of the lookup_wire_fee_by_time function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_WIRE_FEE_BY_TIME_H
+#define EXCHANGE_DATABASE_LOOKUP_WIRE_FEE_BY_TIME_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * 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 cls closure
+ * @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
+EXCHANGEDB_lookup_wire_fee_by_time (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *wire_method,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Timestamp end_time,
+ struct TALER_WireFeeSet *fees);
+
+/**
+ * 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 cls closure
+ * @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
+EXCHANGEDB_lookup_wire_fee_by_time (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *wire_method,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Timestamp end_time,
+ struct TALER_WireFeeSet *fees);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_wire_timestamp.h b/src/include/taler/exchange-database/lookup_wire_timestamp.h
@@ -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 src/include/taler/exchange-database/lookup_wire_timestamp.h
+ * @brief implementation of the lookup_wire_timestamp function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_WIRE_TIMESTAMP_H
+#define EXCHANGE_DATABASE_LOOKUP_WIRE_TIMESTAMP_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Check the last date an exchange wire account was modified.
+ *
+ * @param cls closure
+ * @param payto_uri key to look up information for
+ * @param[out] last_date last modification date to auditor status
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_wire_timestamp (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_FullPayto payto_uri,
+ struct GNUNET_TIME_Timestamp *last_date);
+
+#endif
diff --git a/src/include/taler/exchange-database/lookup_wire_transfer.h b/src/include/taler/exchange-database/lookup_wire_transfer.h
@@ -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 src/include/taler/exchange-database/lookup_wire_transfer.h
+ * @brief implementation of the lookup_wire_transfer function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_LOOKUP_WIRE_TRANSFER_H
+#define EXCHANGE_DATABASE_LOOKUP_WIRE_TRANSFER_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with the results of the lookup of the
+ * transaction data associated with a wire transfer identifier.
+ *
+ * @param cls closure
+ * @param rowid which row in the table is the information from (for diagnostics)
+ * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
+ * @param account_payto_uri which account did the transfer go to?
+ * @param h_payto hash over @a account_payto_uri as it is in the DB
+ * @param exec_time execution time of the wire transfer (should be same for all callbacks with the same @e cls)
+ * @param h_contract_terms which proposal was this payment about
+ * @param denom_pub denomination of @a coin_pub
+ * @param coin_pub which public key was this payment about
+ * @param coin_value amount contributed by this coin in total (with fee)
+ * @param coin_fee applicable fee for this coin
+ */
+typedef void
+(*TALER_EXCHANGEDB_AggregationDataCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_FullPayto account_payto_uri,
+ const struct TALER_FullPaytoHashP *h_payto,
+ struct GNUNET_TIME_Timestamp exec_time,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_Amount *coin_value,
+ const struct TALER_Amount *coin_fee);
+
+/**
+ * Lookup the list of Taler transactions that were aggregated
+ * into a wire transfer by the respective @a wtid.
+ *
+ * @param cls closure
+ * @param wtid the raw wire transfer identifier we used
+ * @param cb function to call on each transaction found
+ * @param cb_cls closure for @a cb
+ * @return query status of the transaction
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_lookup_wire_transfer (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ TALER_EXCHANGEDB_AggregationDataCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/mark_refresh_reveal_success.h b/src/include/taler/exchange-database/mark_refresh_reveal_success.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/mark_refresh_reveal_success.h
+ * @brief Mark the successful reveal of a refresh in the database
+ * @author Özgür Kesim
+ */
+#ifndef EXCHANGE_DATABASE_MARK_REFRESH_REVEAL_SUCCESS_H
+#define EXCHANGE_DATABASE_MARK_REFRESH_REVEAL_SUCCESS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Mark a refresh, given by the commitment, as successfully revealed.
+ *
+ * @param cls closure
+ * @param rc commitment for the refresh
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_mark_refresh_reveal_success (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_RefreshCommitmentP *rc);
+
+#endif
diff --git a/src/include/taler/exchange-database/persist_kyc_attributes.h b/src/include/taler/exchange-database/persist_kyc_attributes.h
@@ -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 src/include/taler/exchange-database/persist_kyc_attributes.h
+ * @brief implementation of the persist_kyc_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_PERSIST_KYC_ATTRIBUTES_H
+#define EXCHANGE_DATABASE_PERSIST_KYC_ATTRIBUTES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Store KYC attribute data.
+ *
+ * @param cls closure
+ * @param process_row KYC process row to update
+ * @param h_payto account for which the attribute data is stored
+ * @param provider_name name of the provider that provided the attributes
+ * @param provider_account_id provider account ID
+ * @param provider_legitimization_id provider legitimization ID
+ * @param birthday birthdate of user, in days after 1990, or 0 if unknown or definitively adult
+ * @param expiration_time when does the data expire
+ * @param form_name name of the form from which the @a enc_attributes originate, can be NULL
+ * @param enc_attributes_size number of bytes in @a enc_attributes
+ * @param enc_attributes encrypted attribute data
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_persist_kyc_attributes (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/persist_policy_details.h b/src/include/taler/exchange-database/persist_policy_details.h
@@ -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 src/include/taler/exchange-database/persist_policy_details.h
+ * @brief implementation of the persist_policy_details function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_PERSIST_POLICY_DETAILS_H
+#define EXCHANGE_DATABASE_PERSIST_POLICY_DETAILS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Persist the details to a policy in the policy_details table. If there
+ * already exists a policy, update the fields accordingly.
+ *
+ * @param details The policy details that should be persisted. If an entry for
+ * the given details->hash_code exists, the values will be updated.
+ * @param[out] policy_details_serial_id The row ID of the policy details
+ * @param[out] accumulated_total The total amount accumulated in that policy
+ * @param[out] fulfillment_state The state of policy. If the state was Insufficient prior to the call and the provided deposit raises the accumulated_total above the commitment, it will be set to Ready.
+ * @return query execution status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_persist_policy_details (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_PolicyDetails *details,
+ uint64_t *policy_details_serial_id,
+ struct TALER_Amount *accumulated_total,
+ enum TALER_PolicyFulfillmentState *fulfillment_state);
+
+#endif
diff --git a/src/include/taler/exchange-database/preflight.h b/src/include/taler/exchange-database/preflight.h
@@ -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 src/include/taler/exchange-database/preflight.h
+ * @brief implementation of the preflight function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_PREFLIGHT_H
+#define EXCHANGE_DATABASE_PREFLIGHT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Do a pre-flight check that we are not in an uncommitted transaction.
+ * If we are, try to commit the previous transaction and output a warning.
+ * Does not return anything, as we will continue regardless of the outcome.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @return #GNUNET_OK if everything is fine
+ * #GNUNET_NO if a transaction was rolled back
+ * #GNUNET_SYSERR on hard errors
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_preflight (struct EXCHANGEDB_PostgresContext *ctx);
+
+#endif
diff --git a/src/include/taler/exchange-database/profit_drains_get_pending.h b/src/include/taler/exchange-database/profit_drains_get_pending.h
@@ -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 src/include/taler/exchange-database/profit_drains_get_pending.h
+ * @brief implementation of the profit_drains_get_pending function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_PROFIT_DRAINS_GET_PENDING_H
+#define EXCHANGE_DATABASE_PROFIT_DRAINS_GET_PENDING_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Get profit drain operation ready to execute.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param[out] serial set to serial ID of the entry
+ * @param[out] wtid set set to wire transfer ID to use
+ * @param[out] account_section set to account to drain
+ * @param[out] payto_uri set to account to wire funds to
+ * @param[out] request_timestamp set to time of the signature
+ * @param[out] amount set to amount to wire
+ * @param[out] master_sig set to signature affirming the operation
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_profit_drains_get_pending (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/profit_drains_set_finished.h b/src/include/taler/exchange-database/profit_drains_set_finished.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/profit_drains_set_finished.h
+ * @brief implementation of the profit_drains_set_finished function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_PROFIT_DRAINS_SET_FINISHED_H
+#define EXCHANGE_DATABASE_PROFIT_DRAINS_SET_FINISHED_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Set profit drain operation to finished.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param serial serial ID of the entry to mark finished
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_profit_drains_set_finished (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial);
+
+#endif
diff --git a/src/include/taler/exchange-database/release_revolving_shard.h b/src/include/taler/exchange-database/release_revolving_shard.h
@@ -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 src/include/taler/exchange-database/release_revolving_shard.h
+ * @brief implementation of the release_revolving_shard function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_RELEASE_REVOLVING_SHARD_H
+#define EXCHANGE_DATABASE_RELEASE_REVOLVING_SHARD_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to release a revolving shard
+ * back into the work pool. Clears the
+ * "completed" flag.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param job_name name of the operation to grab a word shard for
+ * @param start_row inclusive start row of the shard
+ * @param end_row exclusive end row of the shard
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_release_revolving_shard (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *job_name,
+ uint32_t start_row,
+ uint32_t end_row);
+
+#endif
diff --git a/src/include/taler/exchange-database/reserves_get.h b/src/include/taler/exchange-database/reserves_get.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/reserves_get.h
+ * @brief implementation of the reserves_get function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_RESERVES_GET_H
+#define EXCHANGE_DATABASE_RESERVES_GET_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Get the summary of a reserve.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param[in,out] reserve the reserve data. The public key of the reserve should be
+ * set in this structure; it is used to query the database. The balance
+ * and expiration are then filled accordingly.
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_reserves_get (struct EXCHANGEDB_PostgresContext *ctx,
+ struct TALER_EXCHANGEDB_Reserve *reserve);
+
+#endif
diff --git a/src/include/taler/exchange-database/reserves_get_origin.h b/src/include/taler/exchange-database/reserves_get_origin.h
@@ -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 src/include/taler/exchange-database/reserves_get_origin.h
+ * @brief implementation of the reserves_get_origin function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_RESERVES_GET_ORIGIN_H
+#define EXCHANGE_DATABASE_RESERVES_GET_ORIGIN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Get the origin of funds of a reserve.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve_pub public key of the reserve
+ * @param[out] h_payto set to hash of the wire source payto://-URI
+ * @param[out] payto_uri set to the wire source payto://-URI
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_reserves_get_origin (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ struct TALER_FullPaytoHashP *h_payto,
+ struct TALER_FullPayto *payto_uri);
+
+#endif
diff --git a/src/include/taler/exchange-database/reserves_in_insert.h b/src/include/taler/exchange-database/reserves_in_insert.h
@@ -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 src/include/taler/exchange-database/reserves_in_insert.h
+ * @brief implementation of the reserves_in_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_RESERVES_IN_INSERT_H
+#define EXCHANGE_DATABASE_RESERVES_IN_INSERT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert an incoming transaction into reserves. New reserves are also
+ * created through this function. Runs its own transaction(s).
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserves array of reserves to insert
+ * @param reserves_length length of the @a reserves array
+ * @param[out] results set to query status per reserve, must be of length @a reserves_length
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_reserves_in_insert (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
+ unsigned int reserves_length,
+ enum GNUNET_DB_QueryStatus *results);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/reserves_update.h b/src/include/taler/exchange-database/reserves_update.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/reserves_update.h
+ * @brief implementation of the reserves_update function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_RESERVES_UPDATE_H
+#define EXCHANGE_DATABASE_RESERVES_UPDATE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Updates a reserve with the data from the given reserve structure.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param reserve the reserve structure whose data will be used to update the
+ * corresponding record in the database.
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_reserves_update (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_EXCHANGEDB_Reserve *reserve);
+
+#endif
diff --git a/src/include/taler/exchange-database/rollback.h b/src/include/taler/exchange-database/rollback.h
@@ -0,0 +1,38 @@
+/*
+ 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 src/include/taler/exchange-database/rollback.h
+ * @brief implementation of the rollback function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_ROLLBACK_H
+#define EXCHANGE_DATABASE_ROLLBACK_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Roll back the current transaction of a database connection.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ */
+void
+EXCHANGEDB_rollback (struct EXCHANGEDB_PostgresContext *ctx);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_account_merges_above_serial_id.h b/src/include/taler/exchange-database/select_account_merges_above_serial_id.h
@@ -0,0 +1,84 @@
+/*
+ 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.h
+ * @brief implementation of the select_account_merges_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_ACCOUNT_MERGES_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_ACCOUNT_MERGES_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about
+ * account merge requests that have been made, with
+ * the goal of auditing the account merge execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param reserve_pub reserve affected by the merge
+ * @param purse_pub purse being merged
+ * @param h_contract_terms hash over contract of the purse
+ * @param purse_expiration when would the purse expire
+ * @param amount total amount in the purse
+ * @param min_age minimum age of all coins deposited into the purse
+ * @param flags how was the purse created
+ * @param purse_fee if a purse fee was paid, how high is it
+ * @param merge_timestamp when was the merge approved
+ * @param reserve_sig signature by reserve approving the merge
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_AccountMergeCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ struct GNUNET_TIME_Timestamp purse_expiration,
+ const struct TALER_Amount *amount,
+ uint32_t min_age,
+ enum TALER_WalletAccountMergeFlags flags,
+ const struct TALER_Amount *purse_fee,
+ struct GNUNET_TIME_Timestamp merge_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig);
+
+/**
+ * Select account merges above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_account_merges_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_AccountMergeCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_aggregation_amounts_for_kyc_check.h b/src/include/taler/exchange-database/select_aggregation_amounts_for_kyc_check.h
@@ -0,0 +1,140 @@
+/*
+ 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 src/include/taler/exchange-database/select_aggregation_amounts_for_kyc_check.h
+ * @brief implementation of the select_aggregation_amounts_for_kyc_check function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_AGGREGATION_AMOUNTS_FOR_KYC_CHECK_H
+#define EXCHANGE_DATABASE_SELECT_AGGREGATION_AMOUNTS_FOR_KYC_CHECK_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Information per Clause-Schnorr (CS) fresh coin to
+ * be persisted for idempotency during refreshes-reveal.
+ */
+struct TALER_EXCHANGEDB_CsRevealFreshCoinData
+{
+ /**
+ * Denomination of the fresh coin.
+ */
+ struct TALER_DenominationHashP new_denom_pub_hash;
+
+ /**
+ * Blind signature of the fresh coin (possibly updated
+ * in case if a replay!).
+ */
+ struct TALER_BlindedDenominationSignature bsig;
+
+ /**
+ * Offset of the fresh coin in the reveal operation.
+ * (May not match the array offset as we may have
+ * a mixture of RSA and CS coins being created, and
+ * this request is only made for the CS subset).
+ */
+ uint32_t coin_off;
+};
+
+
+/**
+ * Generic KYC status for some operation.
+ */
+struct TALER_EXCHANGEDB_KycStatus
+{
+
+ /**
+ * Account public key that is currently associated
+ * with the account. Only set if @e have_account_pub
+ * is true.
+ */
+ union TALER_AccountPublicKeyP account_pub;
+
+ /**
+ * Number that identifies the KYC requirement the operation
+ * was about.
+ */
+ uint64_t requirement_row;
+
+ /**
+ * True if @e account_pub is set.
+ */
+ bool have_account_pub;
+
+ /**
+ * True if the KYC status is "satisfied".
+ */
+ bool ok;
+
+};
+
+
+struct TALER_EXCHANGEDB_ReserveInInfo
+{
+ const struct TALER_ReservePublicKeyP *reserve_pub;
+ const struct TALER_Amount *balance;
+ struct GNUNET_TIME_Timestamp execution_time;
+ struct TALER_FullPayto sender_account_details;
+ const char *exchange_account_name;
+ uint64_t wire_reference;
+};
+
+
+/**
+ * Function called on each @a amount that was found to
+ * be relevant for a KYC check.
+ *
+ * @param cls closure to allow the KYC module to
+ * total up amounts and evaluate rules
+ * @param amount encountered transaction amount
+ * @param date when was the amount encountered
+ * @return #GNUNET_OK to continue to iterate,
+ * #GNUNET_NO to abort iteration
+ * #GNUNET_SYSERR on internal error (also abort itaration)
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_KycAmountCallback)(
+ void *cls,
+ const struct TALER_Amount *amount,
+ struct GNUNET_TIME_Absolute date);
+
+/**
+ * Call @a kac on deposited amounts after @a time_limit which are relevant for a
+ * KYC trigger for a the (credited) account identified by @a h_payto.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto account identifier
+ * @param time_limit oldest transaction that could be relevant
+ * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK).
+ * @param kac_cls closure for @a kac
+ * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_aggregation_amounts_for_kyc_check (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_KycAmountCallback kac,
+ void *kac_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_aggregation_transient.h b/src/include/taler/exchange-database/select_aggregation_transient.h
@@ -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 src/include/taler/exchange-database/select_aggregation_transient.h
+ * @brief implementation of the select_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_AGGREGATION_TRANSIENT_H
+#define EXCHANGE_DATABASE_SELECT_AGGREGATION_TRANSIENT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Find existing entry in the transient aggregation table.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param merchant_pub public key of the merchant receiving the transfer
+ * @param exchange_account_section exchange account to use
+ * @param[out] wtid set to the raw wire transfer identifier to be used
+ * @param[out] total existing amount to be wired in the future
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_aggregations_above_serial.h b/src/include/taler/exchange-database/select_aggregations_above_serial.h
@@ -0,0 +1,67 @@
+/*
+ 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 src/include/taler/exchange-database/select_aggregations_above_serial.h
+ * @brief implementation of the select_aggregations_above_serial function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_AGGREGATIONS_ABOVE_SERIAL_H
+#define EXCHANGE_DATABASE_SELECT_AGGREGATIONS_ABOVE_SERIAL_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called on aggregations that were done for
+ * a (batch) deposit.
+ *
+ * @param cls closure
+ * @param amount affected amount
+ * @param tracking_serial_id where in the table are we
+ * @param batch_deposit_serial_id which batch deposit was aggregated
+ */
+typedef void
+(*TALER_EXCHANGEDB_AggregationCallback)(
+ void *cls,
+ const struct TALER_Amount *amount,
+ uint64_t tracking_serial_id,
+ uint64_t batch_deposit_serial_id);
+
+/**
+ * Select all aggregation tracking IDs in the database
+ * above a given @a min_tracking_serial_id.
+ *
+ * @param cls closure
+ * @param min_tracking_serial_id only return entries strictly above this row (and in order)
+ * @param cb function to call on all such aggregations
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_aggregations_above_serial (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t min_tracking_serial_id,
+ TALER_EXCHANGEDB_AggregationCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_all_kyc_attributes.h b/src/include/taler/exchange-database/select_all_kyc_attributes.h
@@ -0,0 +1,75 @@
+/*
+ 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 src/include/taler/exchange-database/select_all_kyc_attributes.h
+ * @brief implementation of the select_all_kyc_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_ALL_KYC_ATTRIBUTES_H
+#define EXCHANGE_DATABASE_SELECT_ALL_KYC_ATTRIBUTES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Return KYC attribute information.
+ *
+ * @param cls closure
+ * @param row_id current row in kyc_attributes table
+ * @param h_payto account the attributes are about
+ * @param provider_name name of the provider that collected the attributes
+ * @param collection_time when were the attributes collected
+ * @param expiration_time when does the data expire
+ * @param properties properties that were set for @a h_payto
+ * @param enc_attributes_size size of @a enc_attributes
+ * @param enc_attributes the encrypted collected attributes
+ * @return true to continue to iterate
+ */
+typedef bool
+(*TALER_EXCHANGEDB_AllAttributesCallback)(
+ void *cls,
+ uint64_t row_id,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const char *provider_name,
+ struct GNUNET_TIME_Timestamp collection_time,
+ struct GNUNET_TIME_Timestamp expiration_time,
+ const json_t *properties,
+ size_t enc_attributes_size,
+ const void *enc_attributes);
+
+/**
+ * Lookup all KYC attributes above @a min_row_id.
+ *
+ * @param cls closure
+ * @param min_row_id minimum row ID to return (exclusive)
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_all_kyc_attributes (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t min_row_id,
+ TALER_EXCHANGEDB_AllAttributesCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_all_purse_decisions_above_serial_id.h b/src/include/taler/exchange-database/select_all_purse_decisions_above_serial_id.h
@@ -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 pg_select_all_purse_decisions_above_serial_id.h
+ * @brief implementation of the select_all_purse_decisions_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_ALL_PURSE_DECISIONS_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_ALL_PURSE_DECISIONS_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about purse decisions that have been made, with
+ * the goal of auditing the purse's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param purse_pub public key of the purse
+ * @param refunded true if decision was to refund
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_AllPurseDecisionCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ bool refunded);
+
+/**
+ * Select purse decisions above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_all_purse_decisions_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_AllPurseDecisionCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_all_purse_deletions_above_serial_id.h b/src/include/taler/exchange-database/select_all_purse_deletions_above_serial_id.h
@@ -0,0 +1,67 @@
+/*
+ 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 src/include/taler/exchange-database/select_all_purse_deletions_above_serial_id.h
+ * @brief implementation of the select_all_purse_deletions_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_ALL_PURSE_DELETIONS_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_ALL_PURSE_DELETIONS_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about purse deletions that have been made, with
+ * the goal of auditing the purse's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param purse_pub public key of the purse
+ * @param purse_sig signature affirming deletion of the purse
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_AllPurseDeletionsCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PurseContractSignatureP *purse_sig);
+
+/**
+ * Select all purse deletions above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_all_purse_deletions_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_AllPurseDeletionsCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_aml_attributes.h b/src/include/taler/exchange-database/select_aml_attributes.h
@@ -0,0 +1,76 @@
+/*
+ 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 src/include/taler/exchange-database/select_aml_attributes.h
+ * @brief implementation of the select_aml_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_AML_ATTRIBUTES_H
+#define EXCHANGE_DATABASE_SELECT_AML_ATTRIBUTES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Return AML attribute information.
+ *
+ * @param cls closure
+ * @param row_id current row in kyc_attributes table
+ * @param collection_time when were the attributes collected
+ * @param by_aml_officer true if the data was filed by an AML officer
+ * @param officer_name name of the officer, NULL if not @a by_aml_officer
+ * @param enc_attributes_size size of @a enc_attributes
+ * @param enc_attributes the encrypted collected attributes
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlAttributeCallback)(
+ void *cls,
+ uint64_t row_id,
+ struct GNUNET_TIME_Timestamp collection_time,
+ bool by_aml_officer,
+ const char *officer_name,
+ size_t enc_attributes_size,
+ const void *enc_attributes);
+
+/**
+ * Lookup AML attributes of a particular account.
+ *
+ * @param cls closure
+ * @param h_payto which account should we return attributes for
+ * @param offset row to start from
+ * @param limit how many records to return (negative
+ * to go back in time, positive to go forward)
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_aml_attributes (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ uint64_t offset,
+ int64_t limit,
+ TALER_EXCHANGEDB_AmlAttributeCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_aml_decisions.h b/src/include/taler/exchange-database/select_aml_decisions.h
@@ -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 src/include/taler/exchange-database/select_aml_decisions.h
+ * @brief implementation of the select_aml_decisions function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_AML_DECISIONS_H
+#define EXCHANGE_DATABASE_SELECT_AML_DECISIONS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Return AML decision information.
+ *
+ * @param cls closure
+ * @param row_id current row in legitimization outcomes table
+ * @param justification human-readable reason for the decision, NULL if none is available
+ * @param h_payto account for which the attribute data is stored
+ * @param decision_time when was the decision taken
+ * @param expiration_time when will the rules expire
+ * @param jproperties properties set for the account,
+ * NULL if no properties were set
+ * @param to_investigate true if AML staff should look at the account
+ * @param is_active true if this is the currently active decision about the account
+ * @param is_wallet true if the @a h_payto is for a Taler wallet
+ * @param payto payto URI of the account the decision is about
+ * @param account_rules current active rules for the account
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlDecisionCallback)(
+ void *cls,
+ uint64_t row_id,
+ const char *justification,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Timestamp decision_time,
+ struct GNUNET_TIME_Absolute expiration_time,
+ const json_t *jproperties,
+ bool to_investigate,
+ bool is_active,
+ bool is_wallet,
+ struct TALER_FullPayto payto,
+ const json_t *account_rules);
+
+/**
+ * Lookup AML decisions that have a particular state.
+ *
+ * @param cls closure
+ * @param h_payto which account should we return the AML decision history for, NULL to return all accounts
+ * @param investigation_only filter by investigation state
+ * @param active_only filter for only active states
+ * @param offset row to start from
+ * @param limit how many records to return (negative
+ * to go back in time, positive to go forward)
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_aml_decisions (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_aml_measures.h b/src/include/taler/exchange-database/select_aml_measures.h
@@ -0,0 +1,76 @@
+/*
+ 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 src/include/taler/exchange-database/select_aml_measures.h
+ * @brief implementation of the select_aml_measures function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_AML_MEASURES_H
+#define EXCHANGE_DATABASE_SELECT_AML_MEASURES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with legitimization measures.
+ *
+ * @param cls closure
+ * @param h_payto hash of account the measure applies to
+ * @param start_time when was the process started
+ * @param jmeasures object of type ``LegitimizationMeasures``
+ * @param is_finished true if the measure was finished
+ * @param measure_serial_id row ID of the measure in the exchange table
+ */
+typedef void
+(*TALER_EXCHANGEDB_LegitimizationMeasureCallback) (
+ void *cls,
+ struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute start_time,
+ const json_t *jmeasures,
+ bool is_finished,
+ uint64_t measure_serial_id);
+
+/**
+ * Lookup legitimization measures.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored,
+ * NULL to select for all accounts
+ * @param active_only select only measures that are active
+ * @param offset row offset to select from
+ * @param limit number of results to return, negative to
+ * return in descending order from @a offset
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_aml_measures (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_aml_statistics.h b/src/include/taler/exchange-database/select_aml_statistics.h
@@ -0,0 +1,68 @@
+/*
+ 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 src/include/taler/exchange-database/select_aml_statistics.h
+ * @brief implementation of the select_aml_statistics function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_AML_STATISTICS_H
+#define EXCHANGE_DATABASE_SELECT_AML_STATISTICS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with AML statistics (counters).
+ *
+ * @param cls closure
+ * @param name name of the counter
+ * @param cnt number of events for @a name in the query range
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlStatisticsCallback)(
+ void *cls,
+ const char *name,
+ uint64_t cnt);
+
+/**
+ * Obtain the AML statistics for a given set of @a names and
+ * timeframe.
+ *
+ * @param cls closure
+ * @param num_names length of the @e names array
+ * @param names array of names of the statistics to fetch
+ * @param start_date start of time range
+ * @param end_date end of time range
+ * @param cb function to call on each statistic
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_aml_statistics (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_auditor_denom_sig.h b/src/include/taler/exchange-database/select_auditor_denom_sig.h
@@ -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 src/include/taler/exchange-database/select_auditor_denom_sig.h
+ * @brief implementation of the select_auditor_denom_sig function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_AUDITOR_DENOM_SIG_H
+#define EXCHANGE_DATABASE_SELECT_AUDITOR_DENOM_SIG_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Select information about an auditor auditing a denomination key.
+ *
+ * @param cls closure
+ * @param h_denom_pub the audited denomination
+ * @param auditor_pub the auditor's key
+ * @param[out] auditor_sig set to signature affirming the auditor's audit activity
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_auditor_denom_sig (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_DenominationHashP *h_denom_pub,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ struct TALER_AuditorSignatureP *auditor_sig);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_batch_deposits_missing_wire.h b/src/include/taler/exchange-database/select_batch_deposits_missing_wire.h
@@ -0,0 +1,66 @@
+/*
+ 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 src/include/taler/exchange-database/select_batch_deposits_missing_wire.h
+ * @brief implementation of the select_batch_deposits_missing_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_BATCH_DEPOSITS_MISSING_WIRE_H
+#define EXCHANGE_DATABASE_SELECT_BATCH_DEPOSITS_MISSING_WIRE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called on (batch) deposits will need a wire
+ * transfer.
+ *
+ * @param cls closure
+ * @param batch_deposit_serial_id where in the table are we
+ * @param total_amount value of all missing deposits, including fees
+ * @param wire_target_h_payto hash of the recipient account's payto URI
+ * @param deadline what was the earliest requested wire transfer deadline
+ */
+typedef void
+(*TALER_EXCHANGEDB_WireMissingCallback)(
+ void *cls,
+ uint64_t batch_deposit_serial_id,
+ const struct TALER_Amount *total_amount,
+ const struct TALER_FullPaytoHashP *wire_target_h_payto,
+ struct GNUNET_TIME_Timestamp deadline);
+
+/**
+ * Select all of those batch deposits in the database
+ * above the given serial ID.
+ *
+ * @param cls closure
+ * @param min_batch_deposit_serial_id select all batch deposits above this ID
+ * @param cb function to call on all such deposits
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_batch_deposits_missing_wire (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t min_batch_deposit_serial_id,
+ TALER_EXCHANGEDB_WireMissingCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_coin_deposits_above_serial_id.h b/src/include/taler/exchange-database/select_coin_deposits_above_serial_id.h
@@ -0,0 +1,69 @@
+/*
+ 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 src/include/taler/exchange-database/select_coin_deposits_above_serial_id.h
+ * @brief implementation of the select_coin_deposits_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_COIN_DEPOSITS_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_COIN_DEPOSITS_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about deposits that have been made,
+ * with the goal of auditing the deposit's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param exchange_timestamp when did the deposit happen
+ * @param deposit deposit details
+ * @param denom_pub denomination public key of @a coin_pub
+ * @param done flag set if the deposit was already executed (or not)
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_DepositCallback)(
+ void *cls,
+ uint64_t rowid,
+ struct GNUNET_TIME_Timestamp exchange_timestamp,
+ const struct TALER_EXCHANGEDB_Deposit *deposit,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ bool done);
+
+/**
+ * Select deposits above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_coin_deposits_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_DepositCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_contract.h b/src/include/taler/exchange-database/select_contract.h
@@ -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 src/include/taler/exchange-database/select_contract.h
+ * @brief implementation of the select_contract function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_CONTRACT_H
+#define EXCHANGE_DATABASE_SELECT_CONTRACT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to retrieve an encrypted contract.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub key to lookup the contract by
+ * @param[out] pub_ckey set to the ephemeral DH used to encrypt the contract
+ * @param[out] econtract_sig set to the signature over the encrypted contract
+ * @param[out] econtract_size set to the number of bytes in @a econtract
+ * @param[out] econtract set to the encrypted contract on success, to be freed by the caller
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_contract (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_ContractDiffiePublicP *pub_ckey,
+ struct TALER_PurseContractPublicKeyP *purse_pub,
+ struct TALER_PurseContractSignatureP *econtract_sig,
+ size_t *econtract_size,
+ void **econtract);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_contract_by_purse.h b/src/include/taler/exchange-database/select_contract_by_purse.h
@@ -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 src/include/taler/exchange-database/select_contract_by_purse.h
+ * @brief implementation of the select_contract_by_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_CONTRACT_BY_PURSE_H
+#define EXCHANGE_DATABASE_SELECT_CONTRACT_BY_PURSE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to retrieve an encrypted contract.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub key to lookup the contract by
+ * @param[out] econtract set to the encrypted contract on success, to be freed by the caller
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_contract_by_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ struct TALER_EncryptedContract *econtract);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_deposit_amounts_for_kyc_check.h b/src/include/taler/exchange-database/select_deposit_amounts_for_kyc_check.h
@@ -0,0 +1,143 @@
+/*
+ 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 src/include/taler/exchange-database/select_deposit_amounts_for_kyc_check.h
+ * @brief implementation of the select_deposit_amounts_for_kyc_check function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_DEPOSIT_AMOUNTS_FOR_KYC_CHECK_H
+#define EXCHANGE_DATABASE_SELECT_DEPOSIT_AMOUNTS_FOR_KYC_CHECK_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Information per Clause-Schnorr (CS) fresh coin to
+ * be persisted for idempotency during refreshes-reveal.
+ */
+struct TALER_EXCHANGEDB_CsRevealFreshCoinData
+{
+ /**
+ * Denomination of the fresh coin.
+ */
+ struct TALER_DenominationHashP new_denom_pub_hash;
+
+ /**
+ * Blind signature of the fresh coin (possibly updated
+ * in case if a replay!).
+ */
+ struct TALER_BlindedDenominationSignature bsig;
+
+ /**
+ * Offset of the fresh coin in the reveal operation.
+ * (May not match the array offset as we may have
+ * a mixture of RSA and CS coins being created, and
+ * this request is only made for the CS subset).
+ */
+ uint32_t coin_off;
+};
+
+
+/**
+ * Generic KYC status for some operation.
+ */
+struct TALER_EXCHANGEDB_KycStatus
+{
+
+ /**
+ * Account public key that is currently associated
+ * with the account. Only set if @e have_account_pub
+ * is true.
+ */
+ union TALER_AccountPublicKeyP account_pub;
+
+ /**
+ * Number that identifies the KYC requirement the operation
+ * was about.
+ */
+ uint64_t requirement_row;
+
+ /**
+ * True if @e account_pub is set.
+ */
+ bool have_account_pub;
+
+ /**
+ * True if the KYC status is "satisfied".
+ */
+ bool ok;
+
+};
+
+
+struct TALER_EXCHANGEDB_ReserveInInfo
+{
+ const struct TALER_ReservePublicKeyP *reserve_pub;
+ const struct TALER_Amount *balance;
+ struct GNUNET_TIME_Timestamp execution_time;
+ struct TALER_FullPayto sender_account_details;
+ const char *exchange_account_name;
+ uint64_t wire_reference;
+};
+
+
+/**
+ * Function called on each @a amount that was found to
+ * be relevant for a KYC check.
+ *
+ * @param cls closure to allow the KYC module to
+ * total up amounts and evaluate rules
+ * @param amount encountered transaction amount
+ * @param date when was the amount encountered
+ * @return #GNUNET_OK to continue to iterate,
+ * #GNUNET_NO to abort iteration
+ * #GNUNET_SYSERR on internal error (also abort itaration)
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_KycAmountCallback)(
+ void *cls,
+ const struct TALER_Amount *amount,
+ struct GNUNET_TIME_Absolute date);
+
+/**
+ * Call @a kac on deposited amounts after @a time_limit which are relevant for a
+ * KYC trigger for a merchant identified by @a h_payto.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto account identifier
+ * @param time_limit oldest transaction that could be relevant
+ * @param kac function to call for each applicable amount,
+ * in reverse chronological order (or until @a kac aborts
+ * by returning anything except #GNUNET_OK).
+ * @param kac_cls closure for @a kac
+ * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_deposit_amounts_for_kyc_check (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_KycAmountCallback kac,
+ void *kac_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_exchange_credit_transfers.h b/src/include/taler/exchange-database/select_exchange_credit_transfers.h
@@ -0,0 +1,72 @@
+/*
+ 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 src/include/taler/exchange-database/select_exchange_credit_transfers.h
+ * @brief implementation of the select_exchange_credit_transfers function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_EXCHANGE_CREDIT_TRANSFERS_H
+#define EXCHANGE_DATABASE_SELECT_EXCHANGE_CREDIT_TRANSFERS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Callback that is given AML-relevant transfer data.
+ *
+ * @param cls closure
+ * @param row_id current row in AML status table
+ * @param payto_uri account involved with the wire transfer
+ * @param execution_time when was the transfer made
+ * @param amount wire amount of the transfer
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlTransferCallback)(
+ void *cls,
+ uint64_t row_id,
+ const char *payto_uri,
+ struct GNUNET_TIME_Absolute execution_time,
+ const struct TALER_Amount *amount);
+
+/**
+ * Return AML-relevant wire transfer credit data.
+ *
+ * @param cls closure
+ * @param threshold minimum wire amount to return data for
+ * @param offset offset in table to filter by
+ * @param limit maximum number of entries to return, negative for descending
+ * @param h_payto account to filter transfer data by
+ * @param cb function to call on each result
+ * @param cb_cls closure to pass to @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_exchange_credit_transfers (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_Amount *threshold,
+ uint64_t offset,
+ int64_t limit,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AmlTransferCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_exchange_debit_transfers.h b/src/include/taler/exchange-database/select_exchange_debit_transfers.h
@@ -0,0 +1,72 @@
+/*
+ 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 src/include/taler/exchange-database/select_exchange_debit_transfers.h
+ * @brief implementation of the select_exchange_debit_transfers function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_EXCHANGE_DEBIT_TRANSFERS_H
+#define EXCHANGE_DATABASE_SELECT_EXCHANGE_DEBIT_TRANSFERS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Callback that is given AML-relevant transfer data.
+ *
+ * @param cls closure
+ * @param row_id current row in AML status table
+ * @param payto_uri account involved with the wire transfer
+ * @param execution_time when was the transfer made
+ * @param amount wire amount of the transfer
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlTransferCallback)(
+ void *cls,
+ uint64_t row_id,
+ const char *payto_uri,
+ struct GNUNET_TIME_Absolute execution_time,
+ const struct TALER_Amount *amount);
+
+/**
+ * Return AML-relevant wire transfer debit data.
+ *
+ * @param cls closure
+ * @param threshold minimum wire amount to return data for
+ * @param offset offset in table to filter by
+ * @param limit maximum number of entries to return, negative for descending
+ * @param h_payto account to filter transfer data by
+ * @param cb function to call on each result
+ * @param cb_cls closure to pass to @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_exchange_debit_transfers (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_Amount *threshold,
+ uint64_t offset,
+ int64_t limit,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AmlTransferCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_exchange_kycauth_transfers.h b/src/include/taler/exchange-database/select_exchange_kycauth_transfers.h
@@ -0,0 +1,72 @@
+/*
+ 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 src/include/taler/exchange-database/select_exchange_kycauth_transfers.h
+ * @brief implementation of the select_exchange_kycauth_transfers function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_EXCHANGE_KYCAUTH_TRANSFERS_H
+#define EXCHANGE_DATABASE_SELECT_EXCHANGE_KYCAUTH_TRANSFERS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Callback that is given AML-relevant transfer data.
+ *
+ * @param cls closure
+ * @param row_id current row in AML status table
+ * @param payto_uri account involved with the wire transfer
+ * @param execution_time when was the transfer made
+ * @param amount wire amount of the transfer
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlTransferCallback)(
+ void *cls,
+ uint64_t row_id,
+ const char *payto_uri,
+ struct GNUNET_TIME_Absolute execution_time,
+ const struct TALER_Amount *amount);
+
+/**
+ * Return wire transfer kycauth data.
+ *
+ * @param cls closure
+ * @param threshold minimum wire amount to return data for
+ * @param offset offset in table to filter by
+ * @param limit maximum number of entries to return, negative for descending
+ * @param h_payto account to filter transfer data by
+ * @param cb function to call on each result
+ * @param cb_cls closure to pass to @a cb
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_exchange_kycauth_transfers (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_Amount *threshold,
+ uint64_t offset,
+ int64_t limit,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AmlTransferCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_kyc_accounts.h b/src/include/taler/exchange-database/select_kyc_accounts.h
@@ -0,0 +1,86 @@
+/*
+ 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 src/include/taler/exchange-database/select_kyc_accounts.h
+ * @brief implementation of the select_kyc_accounts function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_KYC_ACCOUNTS_H
+#define EXCHANGE_DATABASE_SELECT_KYC_ACCOUNTS_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Return account summary information.
+ *
+ * @param cls closure
+ * @param row_id current row in AML status table
+ * @param h_payto account for which the attribute data is stored
+ * @param open_time when was the account opened formally,
+ * GNUNET_TIME_UNIT_FOREVER_TS if it was never opened
+ * @param close_time when was the account formally closed,
+ * GNUNET_TIME_UNIT_ZERO_TS if it was never closed
+ * @param comments comments on the account
+ * @param high_risk is this a high-risk business relationship
+ * @param to_investigate TRUE if this account should be investigated
+ * @param payto the payto URI of the account
+ */
+typedef void
+(*TALER_EXCHANGEDB_AmlAccountListCallback)(
+ void *cls,
+ uint64_t row_id,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Timestamp open_time,
+ struct GNUNET_TIME_Timestamp close_time,
+ const char *comments,
+ bool high_risk,
+ bool to_investigate,
+ struct TALER_FullPayto payto);
+
+/**
+ * List accounts managed by the exchange (for AML/KYC).
+ *
+ * @param cls closure
+ * @param investigation_only filter by investigation state
+ * @param open_only filter for only open accounts
+ * @param high_risk_only filter for only high-risk accounts
+ * @param offset row to start from
+ * @param limit how many records to return (negative
+ * to go back in time, positive to go forward)
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_kyc_accounts (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_kyc_attributes.h b/src/include/taler/exchange-database/select_kyc_attributes.h
@@ -0,0 +1,70 @@
+/*
+ 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 src/include/taler/exchange-database/select_kyc_attributes.h
+ * @brief implementation of the select_kyc_attributes function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_KYC_ATTRIBUTES_H
+#define EXCHANGE_DATABASE_SELECT_KYC_ATTRIBUTES_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Callback with KYC attributes about a particular user.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored
+ * @param provider_name provider that must be checked
+ * @param collection_time when was the data collected
+ * @param expiration_time when does the data expire
+ * @param enc_attributes_size number of bytes in @a enc_attributes
+ * @param enc_attributes encrypted attribute data
+ */
+typedef void
+(*TALER_EXCHANGEDB_AttributeCallback)(
+ void *cls,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ const char *provider_name,
+ struct GNUNET_TIME_Timestamp collection_time,
+ struct GNUNET_TIME_Timestamp expiration_time,
+ size_t enc_attributes_size,
+ const void *enc_attributes);
+
+/**
+ * Lookup KYC attribute data for a specific account.
+ *
+ * @param cls closure
+ * @param h_payto account for which the attribute data is stored
+ * @param cb callback to invoke on each match
+ * @param cb_cls closure for @a cb
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_kyc_attributes (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ TALER_EXCHANGEDB_AttributeCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_merge_amounts_for_kyc_check.h b/src/include/taler/exchange-database/select_merge_amounts_for_kyc_check.h
@@ -0,0 +1,139 @@
+/*
+ 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 src/include/taler/exchange-database/select_merge_amounts_for_kyc_check.h
+ * @brief implementation of the select_merge_amounts_for_kyc_check function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_MERGE_AMOUNTS_FOR_KYC_CHECK_H
+#define EXCHANGE_DATABASE_SELECT_MERGE_AMOUNTS_FOR_KYC_CHECK_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Information per Clause-Schnorr (CS) fresh coin to
+ * be persisted for idempotency during refreshes-reveal.
+ */
+struct TALER_EXCHANGEDB_CsRevealFreshCoinData
+{
+ /**
+ * Denomination of the fresh coin.
+ */
+ struct TALER_DenominationHashP new_denom_pub_hash;
+
+ /**
+ * Blind signature of the fresh coin (possibly updated
+ * in case if a replay!).
+ */
+ struct TALER_BlindedDenominationSignature bsig;
+
+ /**
+ * Offset of the fresh coin in the reveal operation.
+ * (May not match the array offset as we may have
+ * a mixture of RSA and CS coins being created, and
+ * this request is only made for the CS subset).
+ */
+ uint32_t coin_off;
+};
+
+
+/**
+ * Generic KYC status for some operation.
+ */
+struct TALER_EXCHANGEDB_KycStatus
+{
+
+ /**
+ * Account public key that is currently associated
+ * with the account. Only set if @e have_account_pub
+ * is true.
+ */
+ union TALER_AccountPublicKeyP account_pub;
+
+ /**
+ * Number that identifies the KYC requirement the operation
+ * was about.
+ */
+ uint64_t requirement_row;
+
+ /**
+ * True if @e account_pub is set.
+ */
+ bool have_account_pub;
+
+ /**
+ * True if the KYC status is "satisfied".
+ */
+ bool ok;
+
+};
+
+
+struct TALER_EXCHANGEDB_ReserveInInfo
+{
+ const struct TALER_ReservePublicKeyP *reserve_pub;
+ const struct TALER_Amount *balance;
+ struct GNUNET_TIME_Timestamp execution_time;
+ struct TALER_FullPayto sender_account_details;
+ const char *exchange_account_name;
+ uint64_t wire_reference;
+};
+
+
+/**
+ * Function called on each @a amount that was found to
+ * be relevant for a KYC check.
+ *
+ * @param cls closure to allow the KYC module to
+ * total up amounts and evaluate rules
+ * @param amount encountered transaction amount
+ * @param date when was the amount encountered
+ * @return #GNUNET_OK to continue to iterate,
+ * #GNUNET_NO to abort iteration
+ * #GNUNET_SYSERR on internal error (also abort itaration)
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_KycAmountCallback)(
+ void *cls,
+ const struct TALER_Amount *amount,
+ struct GNUNET_TIME_Absolute date);
+
+/**
+ * Call @a kac on merged reserve amounts after @a time_limit which are relevant for a
+ * KYC trigger for a the wallet identified by @a h_payto.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto account identifier
+ * @param time_limit oldest transaction that could be relevant
+ * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK).
+ * @param kac_cls closure for @a kac
+ * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_merge_amounts_for_kyc_check (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_KycAmountCallback kac,
+ void *kac_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_purse.h b/src/include/taler/exchange-database/select_purse.h
@@ -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 pg_select_purse.h
+ * @brief implementation of the select_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_PURSE_H
+#define EXCHANGE_DATABASE_SELECT_PURSE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to obtain information about a purse.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub public key of the new purse
+ * @param[out] purse_creation set to time when the purse was created
+ * @param[out] purse_expiration set to time when the purse will expire
+ * @param[out] amount set to target amount (with fees) to be put into the purse
+ * @param[out] deposited set to actual amount put into the purse so far
+ * @param[out] h_contract_terms set to hash of the contract for the purse
+ * @param[out] merge_timestamp set to time when the purse was merged, or NEVER if not
+ * @param[out] purse_deleted set to true if purse was deleted
+ * @param[out] purse_refunded set to true if purse was refunded
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_purse_by_merge_pub.h b/src/include/taler/exchange-database/select_purse_by_merge_pub.h
@@ -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 src/include/taler/exchange-database/select_purse_by_merge_pub.h
+ * @brief implementation of the select_purse_by_merge_pub function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_PURSE_BY_MERGE_PUB_H
+#define EXCHANGE_DATABASE_SELECT_PURSE_BY_MERGE_PUB_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to return meta data about a purse by the
+ * merge capability key.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param merge_pub public key representing the merge capability
+ * @param[out] purse_pub public key of the purse
+ * @param[out] purse_expiration when would an unmerged purse expire
+ * @param[out] h_contract_terms contract associated with the purse
+ * @param[out] age_limit the age limit for deposits into the purse
+ * @param[out] target_amount amount to be put into the purse
+ * @param[out] balance amount put so far into the purse
+ * @param[out] purse_sig signature of the purse over the initialization data
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse_by_merge_pub (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_purse_decisions_above_serial_id.h b/src/include/taler/exchange-database/select_purse_decisions_above_serial_id.h
@@ -0,0 +1,70 @@
+/*
+ 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 src/include/taler/exchange-database/select_purse_decisions_above_serial_id.h
+ * @brief implementation of the select_purse_decisions_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_PURSE_DECISIONS_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_PURSE_DECISIONS_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about purse decisions that have been made, with
+ * the goal of auditing the purse's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param purse_pub public key of the purse
+ * @param reserve_pub public key of the target reserve, NULL if not known / refunded
+ * @param purse_value what is the (target) value of the purse
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_PurseDecisionCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *purse_value);
+
+/**
+ * Select purse decisions above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param refunded which refund status to select for
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse_decisions_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ bool refunded,
+ TALER_EXCHANGEDB_PurseDecisionCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_purse_deposits_above_serial_id.h b/src/include/taler/exchange-database/select_purse_deposits_above_serial_id.h
@@ -0,0 +1,77 @@
+/*
+ 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.h
+ * @brief implementation of the select_purse_deposits_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_PURSE_DEPOSITS_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_PURSE_DEPOSITS_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about purse deposits that have been made, with
+ * the goal of auditing the deposit's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param deposit deposit details
+ * @param reserve_pub which reserve is the purse merged into, NULL if unknown
+ * @param flags purse flags
+ * @param auditor_balance purse balance (according to the
+ * auditor during auditing)
+ * @param purse_total target amount the purse should reach
+ * @param denom_pub denomination public key of @a coin_pub
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_PurseDepositCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_EXCHANGEDB_PurseDeposit *deposit,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ enum TALER_WalletAccountMergeFlags flags,
+ const struct TALER_Amount *auditor_balance,
+ const struct TALER_Amount *purse_total,
+ const struct TALER_DenominationPublicKey *denom_pub);
+
+/**
+ * Select deposits above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse_deposits_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_PurseDepositCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_purse_deposits_by_purse.h b/src/include/taler/exchange-database/select_purse_deposits_by_purse.h
@@ -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 src/include/taler/exchange-database/select_purse_deposits_by_purse.h
+ * @brief implementation of the select_purse_deposits_by_purse function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_PURSE_DEPOSITS_BY_PURSE_H
+#define EXCHANGE_DATABASE_SELECT_PURSE_DEPOSITS_BY_PURSE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about purse refunds that have been made, with
+ * the goal of auditing the purse refund's execution.
+ *
+ * @param cls closure
+ * @param rowid row of the refund event
+ * @param amount_with_fee amount of the deposit into the purse
+ * @param coin_pub coin that is to be refunded the @a given amount_with_fee
+ * @param denom_pub denomination of @a coin_pub
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_PurseRefundCoinCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_Amount *amount_with_fee,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_DenominationPublicKey *denom_pub);
+
+/**
+ * Select coin affected by purse refund.
+ *
+ * @param cls closure
+ * @param purse_pub purse that was refunded
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse_deposits_by_purse (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_purse_merge.h b/src/include/taler/exchange-database/select_purse_merge.h
@@ -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 src/include/taler/exchange-database/select_purse_merge.h
+ * @brief implementation of the select_purse_merge function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_PURSE_MERGE_H
+#define EXCHANGE_DATABASE_SELECT_PURSE_MERGE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to approve merging of a purse with
+ * an account, made by the receiving account.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param purse_pub public key of the purse
+ * @param[out] merge_sig set to the signature confirming the merge
+ * @param[out] merge_timestamp set to the time of the merge
+ * @param[out] partner_url set to the URL of the target exchange, or NULL if the target exchange is us. To be freed by the caller.
+ * @param[out] reserve_pub set to the public key of the reserve/account being credited
+ * @param[out] refunded set to true if purse was refunded
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse_merge (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_purse_merges_above_serial_id.h b/src/include/taler/exchange-database/select_purse_merges_above_serial_id.h
@@ -0,0 +1,82 @@
+/*
+ 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.h
+ * @brief implementation of the select_purse_merges_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_PURSE_MERGES_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_PURSE_MERGES_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about purse
+ * merges that have been made, with
+ * the goal of auditing the purse merge execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param partner_base_url where is the reserve, NULL for this exchange
+ * @param amount total amount expected in the purse
+ * @param balance current balance in the purse (according to the auditor)
+ * @param flags purse flags
+ * @param merge_pub merge capability key
+ * @param reserve_pub reserve the merge affects
+ * @param merge_sig signature affirming the merge
+ * @param purse_pub purse key
+ * @param merge_timestamp when did the merge happen
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_PurseMergeCallback)(
+ void *cls,
+ uint64_t rowid,
+ const char *partner_base_url,
+ const struct TALER_Amount *amount,
+ const struct TALER_Amount *balance,
+ enum TALER_WalletAccountMergeFlags flags,
+ const struct TALER_PurseMergePublicKeyP *merge_pub,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_PurseMergeSignatureP *merge_sig,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ struct GNUNET_TIME_Timestamp merge_timestamp);
+
+/**
+ * Select purse merges deposits above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse_merges_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_PurseMergeCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_purse_requests_above_serial_id.h b/src/include/taler/exchange-database/select_purse_requests_above_serial_id.h
@@ -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 pg_select_purse_requests_above_serial_id.h
+ * @brief implementation of the select_purse_requests_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_PURSE_REQUESTS_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_PURSE_REQUESTS_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called on purse requests.
+ *
+ * @param cls closure
+ * @param rowid purse request table row of the purse
+ * @param purse_pub public key of the purse
+ * @param merge_pub public key representing the merge capability
+ * @param purse_creation when was the purse created?
+ * @param purse_expiration when would an unmerged purse expire
+ * @param h_contract_terms contract associated with the purse
+ * @param age_limit the age limit for deposits into the purse
+ * @param target_amount amount to be put into the purse
+ * @param purse_sig signature of the purse over the initialization data
+ * @return #GNUNET_OK to continue to iterate
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_PurseRequestCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PurseMergePublicKeyP *merge_pub,
+ struct GNUNET_TIME_Timestamp purse_creation,
+ struct GNUNET_TIME_Timestamp purse_expiration,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ uint32_t age_limit,
+ const struct TALER_Amount *target_amount,
+ const struct TALER_PurseContractSignatureP *purse_sig);
+
+/**
+ * Select purse requestss deposits above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_purse_requests_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_PurseRequestCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_recoup_above_serial_id.h b/src/include/taler/exchange-database/select_recoup_above_serial_id.h
@@ -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 src/include/taler/exchange-database/select_recoup_above_serial_id.h
+ * @brief implementation of the select_recoup_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_RECOUP_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_RECOUP_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called about recoups the exchange has to perform.
+ *
+ * @param cls closure
+ * @param rowid row identifier used to uniquely identify the recoup operation
+ * @param timestamp when did we receive the recoup request
+ * @param amount how much should be added back to the reserve
+ * @param reserve_pub public key of the reserve
+ * @param coin public information about the coin
+ * @param denom_pub denomination key of @a coin
+ * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP
+ * @param coin_blind blinding factor used to blind the coin
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_RecoupCallback)(
+ void *cls,
+ uint64_t rowid,
+ struct GNUNET_TIME_Timestamp timestamp,
+ const struct TALER_Amount *amount,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_CoinPublicInfo *coin,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ const union GNUNET_CRYPTO_BlindingSecretP *coin_blind);
+
+/**
+ * Function called to select recoup requests the exchange
+ * received, ordered by serial ID (monotonically increasing).
+ *
+ * @param cls closure
+ * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_recoup_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_RecoupCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_recoup_refresh_above_serial_id.h b/src/include/taler/exchange-database/select_recoup_refresh_above_serial_id.h
@@ -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 src/include/taler/exchange-database/select_recoup_refresh_above_serial_id.h
+ * @brief implementation of the select_recoup_refresh_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_RECOUP_REFRESH_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_RECOUP_REFRESH_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called about recoups on refreshed coins the exchange has to
+ * perform.
+ *
+ * @param cls closure
+ * @param rowid row identifier used to uniquely identify the recoup operation
+ * @param timestamp when did we receive the recoup request
+ * @param amount how much should be added back to the old coin
+ * @param old_coin_pub original coin that was refreshed to create @a coin
+ * @param old_denom_pub_hash hash of public key of @a old_coin_pub
+ * @param coin public information about the fresh coin
+ * @param denom_pub denomination key of @a coin
+ * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_COIN_RECOUP
+ * @param coin_blind blinding factor used to blind the coin
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_RecoupRefreshCallback)(
+ void *cls,
+ uint64_t rowid,
+ struct GNUNET_TIME_Timestamp timestamp,
+ const struct TALER_Amount *amount,
+ const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
+ const struct TALER_DenominationHashP *old_denom_pub_hash,
+ const struct TALER_CoinPublicInfo *coin,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ const union GNUNET_CRYPTO_BlindingSecretP *coin_blind);
+
+/**
+ * Function called to select recoup requests the exchange received for
+ * refreshed coins, ordered by serial ID (monotonically increasing).
+ *
+ * @param cls closure
+ * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_recoup_refresh_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_RecoupRefreshCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_refreshes_above_serial_id.h b/src/include/taler/exchange-database/select_refreshes_above_serial_id.h
@@ -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 src/include/taler/exchange-database/select_refreshes_above_serial_id.h
+ * @brief implementation of the select_refreshes_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_REFRESHES_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_REFRESHES_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about coins that were melted,
+ * with the goal of auditing the refresh's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the refresh session in our DB
+ * @param old_denom_pub denomination public key of @a coin_pub
+ * @param coin_pub public key of the coin
+ * @param coin_sig signature from the coin
+ * @param h_age_commitment hash of the age commitment for the coin
+ * @param amount_with_fee amount that was deposited including fee
+ * @param num_nds length of the @a new_denom_serials array
+ * @param new_denom_serials array of denomination serials of fresh coins
+ * @param rc what the refresh commitment
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_RefreshesCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_DenominationPublicKey *old_denom_pub,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_CoinSpendSignatureP *coin_sig,
+ const struct TALER_AgeCommitmentHashP *h_age_commitment,
+ const struct TALER_Amount *amount_with_fee,
+ size_t num_nds,
+ uint64_t new_denom_serials[static num_nds],
+ const struct TALER_RefreshCommitmentP *rc);
+
+/**
+ * Select refresh sessions above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_refreshes_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_RefreshesCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_refunds_above_serial_id.h b/src/include/taler/exchange-database/select_refunds_above_serial_id.h
@@ -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 src/include/taler/exchange-database/select_refunds_above_serial_id.h
+ * @brief implementation of the select_refunds_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_REFUNDS_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_REFUNDS_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about coins that were refunding,
+ * with the goal of auditing the refund's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the refund in our DB
+ * @param denom_pub denomination public key of @a coin_pub
+ * @param coin_pub public key of the coin
+ * @param merchant_pub public key of the merchant
+ * @param merchant_sig signature of the merchant
+ * @param h_contract_terms hash of the proposal data known to merchant and customer
+ * @param rtransaction_id refund transaction ID chosen by the merchant
+ * @param full_refund true if the refunds total up to the entire value of the deposit
+ * @param amount_with_fee amount that was deposited including fee
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_RefundCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_DenominationPublicKey *denom_pub,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct TALER_MerchantSignatureP *merchant_sig,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ uint64_t rtransaction_id,
+ bool full_refund,
+ const struct TALER_Amount *amount_with_fee);
+
+/**
+ * Select refunds above @a serial_id in monotonically increasing
+ * order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_refunds_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_RefundCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_refunds_by_coin.h b/src/include/taler/exchange-database/select_refunds_by_coin.h
@@ -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 src/include/taler/exchange-database/select_refunds_by_coin.h
+ * @brief implementation of the select_refunds_by_coin function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_REFUNDS_BY_COIN_H
+#define EXCHANGE_DATABASE_SELECT_REFUNDS_BY_COIN_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Callback invoked with information about refunds applicable
+ * to a particular coin and contract.
+ *
+ * @param cls closure
+ * @param amount_with_fee amount being refunded
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_RefundCoinCallback)(
+ void *cls,
+ const struct TALER_Amount *amount_with_fee);
+
+/**
+ * Select refunds by @a coin_pub, @a merchant_pub and @a h_contract.
+ *
+ * @param cls closure of plugin
+ * @param coin_pub coin to get refunds for
+ * @param merchant_pub merchant to get refunds for
+ * @param h_contract contract (hash) to get refunds for
+ * @param cb function to call for each refund found
+ * @param cb_cls closure for @a cb
+ * @return query result status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_refunds_by_coin (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_reserve_close_info.h b/src/include/taler/exchange-database/select_reserve_close_info.h
@@ -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 pg_select_reserve_close_info.h
+ * @brief implementation of the select_reserve_close_info function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_RESERVE_CLOSE_INFO_H
+#define EXCHANGE_DATABASE_SELECT_RESERVE_CLOSE_INFO_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Select information needed to see if we can close
+ * a reserve.
+ *
+ * @param cls closure
+ * @param reserve_pub which reserve is this about?
+ * @param[out] balance current reserve balance
+ * @param[out] payto_uri set to URL of account that
+ * originally funded the reserve;
+ * could be set to NULL if not known
+ * @return transaction status code, 0 if reserve unknown
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_reserve_close_info (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ struct TALER_Amount *balance,
+ struct TALER_FullPayto *payto_uri);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_reserve_closed_above_serial_id.h b/src/include/taler/exchange-database/select_reserve_closed_above_serial_id.h
@@ -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 pg_select_reserve_closed_above_serial_id.h
+ * @brief implementation of the select_reserve_closed_above_serial_id function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_RESERVE_CLOSED_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_RESERVE_CLOSED_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called about reserve closing operations
+ * the aggregator triggered.
+ *
+ * @param cls closure
+ * @param rowid row identifier used to uniquely identify the reserve closing operation
+ * @param execution_date when did we execute the close operation
+ * @param amount_with_fee how much did we debit the reserve
+ * @param closing_fee how much did we charge for closing the reserve
+ * @param reserve_pub public key of the reserve
+ * @param receiver_account where did we send the funds, in payto://-format
+ * @param wtid identifier used for the wire transfer
+ * @param close_request_row row with the responsible close
+ * request, 0 if regular expiration triggered close
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_ReserveClosedCallback)(
+ void *cls,
+ uint64_t rowid,
+ struct GNUNET_TIME_Timestamp execution_date,
+ const struct TALER_Amount *amount_with_fee,
+ const struct TALER_Amount *closing_fee,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_FullPayto receiver_account,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ uint64_t close_request_row);
+
+/**
+ * Function called to select reserve close operations the aggregator
+ * triggered, ordered by serial ID (monotonically increasing).
+ *
+ * @param cls closure
+ * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_reserve_closed_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_ReserveClosedCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_reserve_open_above_serial_id.h b/src/include/taler/exchange-database/select_reserve_open_above_serial_id.h
@@ -0,0 +1,77 @@
+/*
+ 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.h
+ * @brief implementation of the select_reserve_open_above_serial_id function
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_RESERVE_OPEN_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_RESERVE_OPEN_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called about reserve opening operations.
+ *
+ * @param cls closure
+ * @param rowid row identifier used to uniquely identify the reserve closing operation
+ * @param reserve_payment how much to pay from the
+ * reserve's own balance for opening the reserve
+ * @param request_timestamp when was the request created
+ * @param reserve_expiration desired expiration time for the reserve
+ * @param purse_limit minimum number of purses the client
+ * wants to have concurrently open for this reserve
+ * @param reserve_pub public key of the reserve
+ * @param reserve_sig signature affirming the operation
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_ReserveOpenCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_Amount *reserve_payment,
+ struct GNUNET_TIME_Timestamp request_timestamp,
+ struct GNUNET_TIME_Timestamp reserve_expiration,
+ uint32_t purse_limit,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_ReserveSignatureP *reserve_sig);
+
+/**
+ * Function called to select reserve open operations, ordered by serial ID
+ * (monotonically increasing).
+ *
+ * @param cls closure
+ * @param serial_id lowest serial ID to include (select larger or equal)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_reserve_open_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_ReserveOpenCallback cb,
+ void *cb_cls);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/select_reserves_in_above_serial_id.h b/src/include/taler/exchange-database/select_reserves_in_above_serial_id.h
@@ -0,0 +1,70 @@
+/*
+ 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 src/include/taler/exchange-database/select_reserves_in_above_serial_id.h
+ * @brief implementation of the select_reserves_in_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about incoming wire transfers.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the refresh session in our DB
+ * @param reserve_pub public key of the reserve (also the wire subject)
+ * @param credit amount that was received
+ * @param sender_account_details information about the sender's bank account, in payto://-format
+ * @param wire_reference unique identifier for the wire transfer
+ * @param execution_date when did we receive the funds
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_ReserveInCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *credit,
+ const struct TALER_FullPayto sender_account_details,
+ uint64_t wire_reference,
+ struct GNUNET_TIME_Timestamp execution_date);
+
+/**
+ * Select inbound wire transfers into reserves_in above @a serial_id
+ * in monotonically increasing order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_reserves_in_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_ReserveInCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_reserves_in_above_serial_id_by_account.h b/src/include/taler/exchange-database/select_reserves_in_above_serial_id_by_account.h
@@ -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 src/include/taler/exchange-database/select_reserves_in_above_serial_id_by_account.h
+ * @brief implementation of the select_reserves_in_above_serial_id_by_account function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_BY_ACCOUNT_H
+#define EXCHANGE_DATABASE_SELECT_RESERVES_IN_ABOVE_SERIAL_ID_BY_ACCOUNT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about incoming wire transfers.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the refresh session in our DB
+ * @param reserve_pub public key of the reserve (also the wire subject)
+ * @param credit amount that was received
+ * @param sender_account_details information about the sender's bank account, in payto://-format
+ * @param wire_reference unique identifier for the wire transfer
+ * @param execution_date when did we receive the funds
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_ReserveInCallback)(
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *credit,
+ const struct TALER_FullPayto sender_account_details,
+ uint64_t wire_reference,
+ struct GNUNET_TIME_Timestamp execution_date);
+
+/**
+ * Select inbound wire transfers into reserves_in above @a serial_id
+ * in monotonically increasing order by account.
+ *
+ * @param cls closure
+ * @param account_name name of the account to select by
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_reserves_in_above_serial_id_by_account (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *account_name,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_ReserveInCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_wire_out_above_serial_id.h b/src/include/taler/exchange-database/select_wire_out_above_serial_id.h
@@ -0,0 +1,70 @@
+/*
+ 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 src/include/taler/exchange-database/select_wire_out_above_serial_id.h
+ * @brief implementation of the select_wire_out_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with the results of the lookup of the
+ * wire transfer data of the exchange.
+ *
+ * @param cls closure
+ * @param rowid identifier of the respective row in the database
+ * @param date timestamp of the wire transfer (roughly)
+ * @param wtid wire transfer subject
+ * @param payto_uri details of the receiver, URI in payto://-format
+ * @param amount amount that was wired
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_WireTransferOutCallback)(
+ void *cls,
+ uint64_t rowid,
+ struct GNUNET_TIME_Timestamp date,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const struct TALER_FullPayto payto_uri,
+ const struct TALER_Amount *amount);
+
+/**
+ * Function called to select all wire transfers the exchange
+ * executed.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_wire_out_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_WireTransferOutCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_wire_out_above_serial_id_by_account.h b/src/include/taler/exchange-database/select_wire_out_above_serial_id_by_account.h
@@ -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 src/include/taler/exchange-database/select_wire_out_above_serial_id_by_account.h
+ * @brief implementation of the select_wire_out_above_serial_id_by_account function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_BY_ACCOUNT_H
+#define EXCHANGE_DATABASE_SELECT_WIRE_OUT_ABOVE_SERIAL_ID_BY_ACCOUNT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with the results of the lookup of the
+ * wire transfer data of the exchange.
+ *
+ * @param cls closure
+ * @param rowid identifier of the respective row in the database
+ * @param date timestamp of the wire transfer (roughly)
+ * @param wtid wire transfer subject
+ * @param payto_uri details of the receiver, URI in payto://-format
+ * @param amount amount that was wired
+ * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_WireTransferOutCallback)(
+ void *cls,
+ uint64_t rowid,
+ struct GNUNET_TIME_Timestamp date,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const struct TALER_FullPayto payto_uri,
+ const struct TALER_Amount *amount);
+
+/**
+ * Function called to select all wire transfers the exchange
+ * executed by account.
+ *
+ * @param cls closure
+ * @param account_name account to select
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_wire_out_above_serial_id_by_account (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *account_name,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_WireTransferOutCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_withdraw_amounts_for_kyc_check.h b/src/include/taler/exchange-database/select_withdraw_amounts_for_kyc_check.h
@@ -0,0 +1,140 @@
+/*
+ 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 src/include/taler/exchange-database/select_withdraw_amounts_for_kyc_check.h
+ * @brief implementation of the select_withdraw_amounts_for_kyc_check function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_WITHDRAW_AMOUNTS_FOR_KYC_CHECK_H
+#define EXCHANGE_DATABASE_SELECT_WITHDRAW_AMOUNTS_FOR_KYC_CHECK_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Information per Clause-Schnorr (CS) fresh coin to
+ * be persisted for idempotency during refreshes-reveal.
+ */
+struct TALER_EXCHANGEDB_CsRevealFreshCoinData
+{
+ /**
+ * Denomination of the fresh coin.
+ */
+ struct TALER_DenominationHashP new_denom_pub_hash;
+
+ /**
+ * Blind signature of the fresh coin (possibly updated
+ * in case if a replay!).
+ */
+ struct TALER_BlindedDenominationSignature bsig;
+
+ /**
+ * Offset of the fresh coin in the reveal operation.
+ * (May not match the array offset as we may have
+ * a mixture of RSA and CS coins being created, and
+ * this request is only made for the CS subset).
+ */
+ uint32_t coin_off;
+};
+
+
+/**
+ * Generic KYC status for some operation.
+ */
+struct TALER_EXCHANGEDB_KycStatus
+{
+
+ /**
+ * Account public key that is currently associated
+ * with the account. Only set if @e have_account_pub
+ * is true.
+ */
+ union TALER_AccountPublicKeyP account_pub;
+
+ /**
+ * Number that identifies the KYC requirement the operation
+ * was about.
+ */
+ uint64_t requirement_row;
+
+ /**
+ * True if @e account_pub is set.
+ */
+ bool have_account_pub;
+
+ /**
+ * True if the KYC status is "satisfied".
+ */
+ bool ok;
+
+};
+
+
+struct TALER_EXCHANGEDB_ReserveInInfo
+{
+ const struct TALER_ReservePublicKeyP *reserve_pub;
+ const struct TALER_Amount *balance;
+ struct GNUNET_TIME_Timestamp execution_time;
+ struct TALER_FullPayto sender_account_details;
+ const char *exchange_account_name;
+ uint64_t wire_reference;
+};
+
+
+/**
+ * Function called on each @a amount that was found to
+ * be relevant for a KYC check.
+ *
+ * @param cls closure to allow the KYC module to
+ * total up amounts and evaluate rules
+ * @param amount encountered transaction amount
+ * @param date when was the amount encountered
+ * @return #GNUNET_OK to continue to iterate,
+ * #GNUNET_NO to abort iteration
+ * #GNUNET_SYSERR on internal error (also abort itaration)
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_KycAmountCallback)(
+ void *cls,
+ const struct TALER_Amount *amount,
+ struct GNUNET_TIME_Absolute date);
+
+/**
+ * Call @a kac on withdrawn amounts after @a time_limit which are relevant
+ * for a KYC trigger for a the (debited) account identified by @a h_payto.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto account identifier
+ * @param time_limit oldest transaction that could be relevant
+ * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK).
+ * @param kac_cls closure for @a kac
+ * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_withdraw_amounts_for_kyc_check (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Absolute time_limit,
+ TALER_EXCHANGEDB_KycAmountCallback kac,
+ void *kac_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/select_withdrawals_above_serial_id.h b/src/include/taler/exchange-database/select_withdrawals_above_serial_id.h
@@ -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 src/include/taler/exchange-database/select_withdrawals_above_serial_id.h
+ * @brief implementation of the select_withdrawals_above_serial_id function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SELECT_WITHDRAWALS_ABOVE_SERIAL_ID_H
+#define EXCHANGE_DATABASE_SELECT_WITHDRAWALS_ABOVE_SERIAL_ID_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * Function called with details about withdraw operations.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the refresh session in our DB
+ * @param num_denom_serials number of elements in @e denom_serials array
+ * @param denom_serials array with length @e num_denom_serials of serial ID's of denominations in our DB
+ * @param selected_h hash over the gamma-selected planchets
+ * @param h_planchets running hash over all hashes of blinded planchets in the original withdraw request
+ * @param blinding_seed the blinding seed for CS denominations that was provided during withdraw; might be NULL
+ * @param age_proof_required true if the withdraw request required an age proof.
+ * @param max_age if @e age_proof_required is true, the maximum age that was set on the coins.
+ * @param noreveal_index if @e age_proof_required is true, the index that was returned by the exchange for the reveal phase.
+ * @param reserve_pub public key of the reserve
+ * @param reserve_sig signature over the withdraw operation
+ * @param execution_date when did the wallet withdraw the coin
+ * @param amount_with_fee amount that was withdrawn
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+typedef enum GNUNET_GenericReturnValue
+(*TALER_EXCHANGEDB_WithdrawCallback)(
+ void *cls,
+ uint64_t rowid,
+ size_t num_denom_serials,
+ const uint64_t *denom_serials,
+ const struct TALER_HashBlindedPlanchetsP *selected_h,
+ const struct TALER_HashBlindedPlanchetsP *h_planchets,
+ const struct TALER_BlindingMasterSeedP *blinding_seed,
+ bool age_proof_required,
+ uint8_t max_age,
+ uint8_t noreveal_index,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_ReserveSignatureP *reserve_sig,
+ struct GNUNET_TIME_Timestamp execution_date,
+ const struct TALER_Amount *amount_with_fee);
+
+/**
+ * Select withdraw operations from reserves_out above @a serial_id
+ * in monotonically increasing order.
+ *
+ * @param cls closure
+ * @param serial_id highest serial ID to exclude (select strictly larger)
+ * @param cb function to call on each result
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_select_withdrawals_above_serial_id (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t serial_id,
+ TALER_EXCHANGEDB_WithdrawCallback cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/set_aml_lock.h b/src/include/taler/exchange-database/set_aml_lock.h
@@ -0,0 +1,49 @@
+/*
+ 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 src/include/taler/exchange-database/set_aml_lock.h
+ * @brief implementation of the set_aml_lock function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SET_AML_LOCK_H
+#define EXCHANGE_DATABASE_SET_AML_LOCK_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Set a lock for @a lock_duration on running AML programs for the @a h_payto
+ * account. If a lock already exists, returns the timeout of the
+ * @a existing_lock. Returns 0 if @a h_payto is not known.
+ *
+ * @param cls closure
+ * @param h_payto account to lock
+ * @param lock_duration how long to lock the account
+ * @param[out] existing_lock set to timeout of existing lock, or
+ * to zero if there is no existing lock
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_set_aml_lock (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_NormalizedPaytoHashP *h_payto,
+ struct GNUNET_TIME_Relative lock_duration,
+ struct GNUNET_TIME_Absolute *existing_lock);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/set_extension_manifest.h b/src/include/taler/exchange-database/set_extension_manifest.h
@@ -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 src/include/taler/exchange-database/set_extension_manifest.h
+ * @brief implementation of the set_extension_manifest function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SET_EXTENSION_MANIFEST_H
+#define EXCHANGE_DATABASE_SET_EXTENSION_MANIFEST_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to save the manifest of an extension
+ * (age-restriction, policy_extension_...) After successful storage of the
+ * configuration it triggers the corresponding event.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param extension_name the name of the extension
+ * @param manifest JSON object of the configuration as string
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_set_extension_manifest (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *extension_name,
+ const char *manifest);
+
+#endif
diff --git a/src/include/taler/exchange-database/set_purse_balance.h b/src/include/taler/exchange-database/set_purse_balance.h
@@ -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 src/include/taler/exchange-database/set_purse_balance.h
+ * @brief implementation of the set_purse_balance function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_SET_PURSE_BALANCE_H
+#define EXCHANGE_DATABASE_SET_PURSE_BALANCE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Set the current @a balance in the purse
+ * identified by @a purse_pub. Used by the auditor
+ * to update the balance as calculated by the auditor.
+ *
+ * @param cls closure
+ * @param purse_pub public key of a purse
+ * @param balance new balance to store under the purse
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_set_purse_balance (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_Amount *balance);
+
+#endif
diff --git a/src/include/taler/exchange-database/start.h b/src/include/taler/exchange-database/start.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/start.h
+ * @brief implementation of the start function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_START_H
+#define EXCHANGE_DATABASE_START_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Start a transaction.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param name unique name identifying the transaction (for debugging)
+ * must point to a constant
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_start (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *name);
+
+#endif
diff --git a/src/include/taler/exchange-database/start_deferred_wire_out.h b/src/include/taler/exchange-database/start_deferred_wire_out.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/start_deferred_wire_out.h
+ * @brief implementation of the start_deferred_wire_out function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_START_DEFERRED_WIRE_OUT_H
+#define EXCHANGE_DATABASE_START_DEFERRED_WIRE_OUT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Starts a READ COMMITTED transaction where we transiently violate the foreign
+ * constraints on the "wire_out" table as we insert aggregations
+ * and only add the wire transfer out at the end.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_start_deferred_wire_out (struct EXCHANGEDB_PostgresContext *ctx);
+
+#endif
diff --git a/src/include/taler/exchange-database/start_read_committed.h b/src/include/taler/exchange-database/start_read_committed.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/start_read_committed.h
+ * @brief implementation of the start_read_committed function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_START_READ_COMMITTED_H
+#define EXCHANGE_DATABASE_START_READ_COMMITTED_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Start a READ COMMITTED transaction.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param name unique name identifying the transaction (for debugging)
+ * must point to a constant
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_start_read_committed (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *name);
+
+#endif
diff --git a/src/include/taler/exchange-database/start_read_only.h b/src/include/taler/exchange-database/start_read_only.h
@@ -0,0 +1,42 @@
+/*
+ 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 src/include/taler/exchange-database/start_read_only.h
+ * @brief implementation of the start_read_only function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_START_READ_ONLY_H
+#define EXCHANGE_DATABASE_START_READ_ONLY_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Start a READ ONLY serializable transaction.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param name unique name identifying the transaction (for debugging)
+ * must point to a constant
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+EXCHANGEDB_start_read_only (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *name);
+
+#endif
diff --git a/src/include/taler/exchange-database/store_wire_transfer_out.h b/src/include/taler/exchange-database/store_wire_transfer_out.h
@@ -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 src/include/taler/exchange-database/store_wire_transfer_out.h
+ * @brief implementation of the store_wire_transfer_out function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_STORE_WIRE_TRANSFER_OUT_H
+#define EXCHANGE_DATABASE_STORE_WIRE_TRANSFER_OUT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Store information about an outgoing wire transfer that was executed.
+ *
+ * @param cls closure
+ * @param date time of the wire transfer
+ * @param wtid subject of the wire transfer
+ * @param h_payto identifies the receiver account of the wire transfer
+ * @param exchange_account_section configuration section of the exchange specifying the
+ * exchange's bank account being used
+ * @param amount amount that was transmitted
+ * @param extra_wire_subject_metadata additional meta data for the wire transfer subject, can be NULL
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_store_wire_transfer_out (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/test_aml_officer.h b/src/include/taler/exchange-database/test_aml_officer.h
@@ -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 src/include/taler/exchange-database/test_aml_officer.h
+ * @brief implementation of the test_aml_officer function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_TEST_AML_OFFICER_H
+#define EXCHANGE_DATABASE_TEST_AML_OFFICER_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Test if the given AML staff member is active
+ * (at least read-only).
+ *
+ * @param cls closure
+ * @param decider_pub public key of the staff member
+ * @param[out] read_only set to true if the member is read-only
+ * @return database transaction status, if member is unknown or not active, 1 if member is active
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_test_aml_officer (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_AmlOfficerPublicKeyP *decider_pub,
+ bool *read_only);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/trigger_kyc_rule_for_account.h b/src/include/taler/exchange-database/trigger_kyc_rule_for_account.h
@@ -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 src/include/taler/exchange-database/trigger_kyc_rule_for_account.h
+ * @brief implementation of the trigger_kyc_rule_for_account function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_TRIGGER_KYC_RULE_FOR_ACCOUNT_H
+#define EXCHANGE_DATABASE_TRIGGER_KYC_RULE_FOR_ACCOUNT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert KYC requirement for @a h_payto account into table.
+ *
+ * @param cls closure
+ * @param payto_uri account that must be KYC'ed,
+ * can be NULL if @a h_payto is already
+ * guaranteed to be in wire_targets
+ * @param h_payto hash of @a payto_uri
+ * @param set_account_pub public key to enable for the
+ * KYC authorization, NULL if not known
+ * @param check_merchant_pub public key that must already
+ * be enabled for a KYC authorzation for it to be
+ * valid, NULL if not known
+ * @param jmeasures serialized MeasureSet to put in place
+ * @param display_priority priority of the rule
+ * @param[out] requirement_row set to legitimization requirement row for this check
+ * @param[out] bad_kyc_auth set if @a check_account_pub
+ * did not match the existing KYC auth
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_trigger_kyc_rule_for_account (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/update_aggregation_transient.h b/src/include/taler/exchange-database/update_aggregation_transient.h
@@ -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 src/include/taler/exchange-database/update_aggregation_transient.h
+ * @brief implementation of the update_aggregation_transient function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_UPDATE_AGGREGATION_TRANSIENT_H
+#define EXCHANGE_DATABASE_UPDATE_AGGREGATION_TRANSIENT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Update existing entry in the transient aggregation table.
+ * @a h_payto is only needed for query performance.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param h_payto destination of the wire transfer
+ * @param wtid the raw wire transfer identifier to update
+ * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none
+ * @param total new total amount to be wired in the future
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_update_aggregation_transient (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_FullPaytoHashP *h_payto,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ uint64_t kyc_requirement_row,
+ const struct TALER_Amount *total);
+
+#endif
diff --git a/src/include/taler/exchange-database/update_auditor.h b/src/include/taler/exchange-database/update_auditor.h
@@ -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 src/include/taler/exchange-database/update_auditor.h
+ * @brief implementation of the update_auditor function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_UPDATE_AUDITOR_H
+#define EXCHANGE_DATABASE_UPDATE_AUDITOR_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Update information about an auditor that will audit this exchange.
+ *
+ * @param cls closure
+ * @param auditor_pub key of the auditor (primary key for the existing record)
+ * @param auditor_url base URL of the auditor's REST service, to be updated
+ * @param auditor_name name of the auditor (for humans)
+ * @param change_date date when the auditor status was last changed
+ * (only to be used for replay detection)
+ * @param enabled true to enable, false to disable
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_update_auditor (struct EXCHANGEDB_PostgresContext *ctx,
+ const struct TALER_AuditorPublicKeyP *auditor_pub,
+ const char *auditor_url,
+ const char *auditor_name,
+ struct GNUNET_TIME_Timestamp change_date,
+ bool enabled);
+
+#endif
diff --git a/src/include/taler/exchange-database/update_kyc_process_by_row.h b/src/include/taler/exchange-database/update_kyc_process_by_row.h
@@ -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 src/include/taler/exchange-database/update_kyc_process_by_row.h
+ * @brief implementation of the update_kyc_process_by_row function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_UPDATE_KYC_PROCESS_BY_ROW_H
+#define EXCHANGE_DATABASE_UPDATE_KYC_PROCESS_BY_ROW_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Update KYC requirement check with provider-linkage and/or
+ * expiration data.
+ *
+ * @param cls closure
+ * @param process_row row to select by
+ * @param provider_name provider that must be checked (technically redundant)
+ * @param h_payto account that must be KYC'ed (helps access by shard, otherwise also redundant)
+ * @param provider_account_id provider account ID
+ * @param provider_legitimization_id provider legitimization ID
+ * @param redirect_url where the user should be redirected to start the KYC process
+ * @param expiration how long is this KYC check set to be valid (in the past if invalid)
+ * @param ec error code, #TALER_EC_NONE on success
+ * @param error_message_hint human-readable error message details (in addition to @a ec, NULL on success)
+ * @param finished true to mark the process as done
+ * @return database transaction status
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_update_kyc_process_by_row (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/update_wire.h b/src/include/taler/exchange-database/update_wire.h
@@ -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 src/include/taler/exchange-database/update_wire.h
+ * @brief implementation of the update_wire function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_UPDATE_WIRE_H
+#define EXCHANGE_DATABASE_UPDATE_WIRE_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Update information about a wire account of the exchange.
+ *
+ * @param cls closure
+ * @param payto_uri account the update is about
+ * @param conversion_url URL of a conversion service, NULL if there is no conversion
+ * @param open_banking_gateway open banking gateway service, NULL if unavailable
+ * @param wire_transfer_gateway wire transfer gateway service, NULL if unavailable
+ * @param debit_restrictions JSON array with debit restrictions on the account; NULL allowed if not @a enabled
+ * @param credit_restrictions JSON array with credit restrictions on the account; NULL allowed if not @a enabled
+ * @param change_date date when the account status was last changed
+ * (only to be used for replay detection)
+ * @param master_sig master signature to store, can be NULL (if @a enabled is false)
+ * @param bank_label label to show this entry under in the UI, can be NULL
+ * @param priority determines order in which entries are shown in the UI
+ * @param enabled true to enable, false to disable (the actual change)
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_update_wire (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+#endif
diff --git a/src/include/taler/exchange-database/wad_in_insert.h b/src/include/taler/exchange-database/wad_in_insert.h
@@ -0,0 +1,54 @@
+/*
+ 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 src/include/taler/exchange-database/wad_in_insert.h
+ * @brief implementation of the wad_in_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_WAD_IN_INSERT_H
+#define EXCHANGE_DATABASE_WAD_IN_INSERT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Insert an incoming WAD wire transfer into the database.
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param wad_id WAD identifier
+ * @param origin_exchange_url exchange base URL originating the transfer
+ * @param amount the amount that was transferred
+ * @param execution_date when was the transfer made
+ * @param debit_account_uri URI of the debit account
+ * @param section_name section of the exchange bank account that received the transfer
+ * @param serial_id bank-specific row identifying the transfer
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_wad_in_insert (struct EXCHANGEDB_PostgresContext *ctx,
+ 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);
+
+
+#endif
diff --git a/src/include/taler/exchange-database/wire_prepare_data_get.h b/src/include/taler/exchange-database/wire_prepare_data_get.h
@@ -0,0 +1,1753 @@
+/*
+ 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 src/include/taler/exchange-database/wire_prepare_data_get.h
+ * @brief implementation of the wire_prepare_data_get function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_WIRE_PREPARE_DATA_GET_H
+#define EXCHANGE_DATABASE_WIRE_PREPARE_DATA_GET_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+
+
+struct EXCHANGEDB_PostgresContext;
+/* Callback typedefs */
+/**
+ * @brief Information we keep for a withdrawn coin to reproduce
+ * the /batch-withdraw operation if needed, and to have proof
+ * that a reserve was drained by this amount.
+ *
+ * @note This structure will be removed at some point after v24 of the protocol
+ * FIXME: to be deleted.
+ */
+struct TALER_EXCHANGEDB_CollectableBlindcoin
+{
+
+ /**
+ * Our (blinded) signature over the (blinded) coin.
+ */
+ struct TALER_BlindedDenominationSignature sig;
+
+ /**
+ * Hash of the denomination key (which coin was generated).
+ */
+ struct TALER_DenominationHashP denom_pub_hash;
+
+ /**
+ * Value of the coin being exchangeed (matching the denomination key)
+ * plus the transaction fee. We include this in what is being
+ * signed so that we can verify a reserve's remaining total balance
+ * without needing to access the respective denomination key
+ * information each time.
+ */
+ struct TALER_Amount amount_with_fee;
+
+ /**
+ * Withdrawal fee charged by the exchange. This must match the Exchange's
+ * denomination key's withdrawal fee. If the client puts in an
+ * invalid withdrawal fee (too high or too low) that does not match
+ * the Exchange's denomination key, the withdraw operation is invalid
+ * and will be rejected by the exchange. The @e amount_with_fee minus
+ * the @e withdraw_fee is must match the value of the generated
+ * coin. We include this in what is being signed so that we can
+ * verify a exchange's accounting without needing to access the
+ * respective denomination key information each time.
+ */
+ struct TALER_Amount withdraw_fee;
+
+ /**
+ * Public key of the reserve that was drained.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Hash over the blinded message, needed to verify
+ * the @e reserve_sig.
+ */
+ struct TALER_BlindedCoinHashP h_coin_envelope;
+
+ /**
+ * Signature confirming the withdrawal, matching @e reserve_pub,
+ * @e denom_pub and @e h_coin_envelope.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+};
+
+/**
+ * @brief Information we keep for a withdraw request
+ * to reproduce the /withdraw operation if needed, and to have proof
+ * that a reserve was drained by this amount.
+ */
+struct TALER_EXCHANGEDB_Withdraw
+{
+ /**
+ * Total amount (with fee) committed to withdraw
+ */
+ struct TALER_Amount amount_with_fee;
+
+ /**
+ * true, if a proof of age was required following this withdraw,
+ * in a subsequent call to /reveal-withdraw.
+ * In this case, @e max_age, @e h_commitment and
+ * @e noreveal_index are to be taken into account
+ */
+ bool age_proof_required;
+
+ /**
+ * Maximum age (in years) that the coins are restricted to,
+ * if ``age_proof_required`` is true.
+ */
+ uint16_t max_age;
+
+ /**
+ * If ``age_proof_required`` is true, index (smaller #TALER_CNC_KAPPA)
+ * which the exchange has chosen to keep unrevealed
+ * during the next cut and choose (aka /reveal-age) step.
+ * This value applies to all n coins in the commitment.
+ */
+ uint16_t noreveal_index;
+
+ /**
+ * If @e age_proof_required is true, the running hash over all blinded coin
+ * envelope's TALER_BlindedCoinHashP values.
+ * It runs over ``kappa*num_coins``, starting with the hashes for the coins
+ * for kappa index=0, then index=1 etc.,
+ * i.e. h[0][0]...h[0][n-1]h[1][0]...h[1][n-1]...h[κ-1][0]...h[κ-1][n-1]
+ */
+ struct TALER_HashBlindedPlanchetsP planchets_h;
+
+ /**
+ * Public key of the reserve that was drained.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Signature confirming the withdrawal commitment
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+
+ /**
+ * Number of coins to be withdrawn.
+ */
+ size_t num_coins;
+
+ /**
+ * The hash of the blinded coin envelopes which are signed by the exchange.
+ * In case of @e age_proof_required = true, this is the hash over the chosen coins'
+ * envelopes (according to @e noreveal_index) from the request, which contained
+ * kappa*num_coins blinded coins envelopes.
+ */
+ struct TALER_HashBlindedPlanchetsP selected_h;
+
+ /**
+ * Array of @a num_coins denomination signatures of the blinded coins @a
+ * h_coin_evs.
+ */
+ struct TALER_BlindedDenominationSignature *denom_sigs;
+
+ /**
+ * Array of @a num_coins serial id's of the denominations, corresponding to
+ * the coins in @a h_coin_evs.
+ * If @e age_proof_required is true, the denominations MUST support age restriction.
+ */
+ uint64_t *denom_serials;
+
+ /**
+ * If true, no @e blinding_seed is set and @e num_cs_r_values is 0.
+ */
+ bool no_blinding_seed;
+
+ /**
+ * If @e no_blinding_seed is false, the blinding seed for the nonces needed for
+ * blind CS signatures.
+ */
+ struct TALER_BlindingMasterSeedP blinding_seed;
+
+ /**
+ * Number of elements in @e cs_r_values.
+ * Only non-zero IF @e age_proof_required is true AND any of the denomination
+ * has a cipher of type CS.
+ */
+ size_t num_cs_r_values;
+
+ /**
+ * Array @e num_r_pubs of public R-value pairs for CS that were generated from the
+ * @e blinding_seed, a coin's index and the denomination's private key during the
+ * the /withdraw request, to ensure idempotency in case of expiration of a denomination.
+ * NULL if @e num_r_pub is 0 (or @e age_proof_required is false).
+ */
+ struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values;
+
+ /**
+ * The bitvector encoding the choices per coin, made by the exchange,
+ * for the R-values in @e cs_r_values. The value is encoded in NBO
+ * and the lowest bit corresponds to the pair at index 0 in @e cs_r_values.
+ */
+ uint64_t cs_r_choices;
+
+ /**
+ * [out]-Array of @a num_coins hashes of the public keys of the denominations
+ * identified by @e denom_serials. This field is only set when calling
+ * get_reserve_history().
+ */
+ struct TALER_DenominationHashP *denom_pub_hashes;
+};
+
+
+/**
+ * Information the exchange records about a recoup request
+ * in a reserve history.
+ */
+struct TALER_EXCHANGEDB_Recoup
+{
+
+ /**
+ * Information about the coin that was paid back.
+ */
+ struct TALER_CoinPublicInfo coin;
+
+ /**
+ * Blinding factor supplied to prove to the exchange that
+ * the coin came from this reserve.
+ */
+ union GNUNET_CRYPTO_BlindingSecretP coin_blind;
+
+ /**
+ * Signature of the coin of type
+ * #TALER_SIGNATURE_WALLET_COIN_RECOUP.
+ */
+ struct TALER_CoinSpendSignatureP coin_sig;
+
+ /**
+ * Public key of the reserve the coin was paid back into.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * How much was the coin still worth at this time?
+ */
+ struct TALER_Amount value;
+
+ /**
+ * When did the recoup operation happen?
+ */
+ struct GNUNET_TIME_Timestamp timestamp;
+
+};
+
+
+/**
+ * Public key to which a nonce is locked.
+ */
+union TALER_EXCHANGEDB_NonceLockTargetP
+{
+ /**
+ * Nonce is locked to this coin key.
+ */
+ struct TALER_CoinSpendPublicKeyP coin;
+
+ /**
+ * Nonce is locked to this reserve key.
+ */
+ struct TALER_ReservePublicKeyP reserve;
+};
+
+
+/**
+ * Information the exchange records about a recoup request
+ * in a coin history.
+ */
+struct TALER_EXCHANGEDB_RecoupListEntry
+{
+
+ /**
+ * Blinding factor supplied to prove to the exchange that
+ * the coin came from this reserve.
+ */
+ union GNUNET_CRYPTO_BlindingSecretP coin_blind;
+
+ /**
+ * Signature of the coin of type
+ * #TALER_SIGNATURE_WALLET_COIN_RECOUP.
+ */
+ struct TALER_CoinSpendSignatureP coin_sig;
+
+ /**
+ * Hash of the public denomination key used to sign the coin.
+ */
+ struct TALER_DenominationHashP h_denom_pub;
+
+ /**
+ * Public key of the reserve the coin was paid back into.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * How much was the coin still worth at this time?
+ */
+ struct TALER_Amount value;
+
+ /**
+ * When did the /recoup operation happen?
+ */
+ struct GNUNET_TIME_Timestamp timestamp;
+
+};
+
+
+/**
+ * Information the exchange records about a recoup-refresh request in
+ * a coin transaction history.
+ */
+struct TALER_EXCHANGEDB_RecoupRefreshListEntry
+{
+
+ /**
+ * Information about the coin that was paid back
+ * (NOT the coin we are considering the history of!)
+ */
+ struct TALER_CoinPublicInfo coin;
+
+ /**
+ * Blinding factor supplied to prove to the exchange that
+ * the coin came from this @e old_coin_pub.
+ */
+ union GNUNET_CRYPTO_BlindingSecretP coin_blind;
+
+ /**
+ * Signature of the coin of type
+ * #TALER_SIGNATURE_WALLET_COIN_RECOUP.
+ */
+ struct TALER_CoinSpendSignatureP coin_sig;
+
+ /**
+ * Public key of the old coin that the refreshed coin was paid back to.
+ */
+ struct TALER_CoinSpendPublicKeyP old_coin_pub;
+
+ /**
+ * How much was the coin still worth at this time?
+ */
+ struct TALER_Amount value;
+
+ /**
+ * When did the recoup operation happen?
+ */
+ struct GNUNET_TIME_Timestamp timestamp;
+
+};
+
+
+/**
+ * Details about a purse merge operation.
+ */
+struct TALER_EXCHANGEDB_PurseMerge
+{
+
+ /**
+ * Public key of the reserve the coin was merged into.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Amount in the purse, with fees.
+ */
+ struct TALER_Amount amount_with_fee;
+
+ /**
+ * Fee paid for the purse.
+ */
+ struct TALER_Amount purse_fee;
+
+ /**
+ * Hash over the contract.
+ */
+ struct TALER_PrivateContractHashP h_contract_terms;
+
+ /**
+ * Merge capability key.
+ */
+ struct TALER_PurseMergePublicKeyP merge_pub;
+
+ /**
+ * Purse public key.
+ */
+ struct TALER_PurseContractPublicKeyP purse_pub;
+
+ /**
+ * Signature by the reserve approving the merge.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+
+ /**
+ * When was the merge made.
+ */
+ struct GNUNET_TIME_Timestamp merge_timestamp;
+
+ /**
+ * When was the purse set to expire.
+ */
+ struct GNUNET_TIME_Timestamp purse_expiration;
+
+ /**
+ * Minimum age required for depositing into the purse.
+ */
+ uint32_t min_age;
+
+ /**
+ * Flags of the purse.
+ */
+ enum TALER_WalletAccountMergeFlags flags;
+
+ /**
+ * true if the purse was actually successfully merged,
+ * false if the @e purse_fee was charged but the
+ * @e amount was not credited to the reserve.
+ */
+ bool merged;
+};
+
+
+/**
+ * Details about a (paid for) reserve history request.
+ */
+struct TALER_EXCHANGEDB_HistoryRequest
+{
+ /**
+ * Public key of the reserve the history request was for.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Fee paid for the request.
+ */
+ struct TALER_Amount history_fee;
+
+ /**
+ * When was the request made.
+ */
+ struct GNUNET_TIME_Timestamp request_timestamp;
+
+ /**
+ * Signature by the reserve approving the history request.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+};
+
+
+/**
+ * Details about a (paid for) reserve open request.
+ */
+struct TALER_EXCHANGEDB_OpenRequest
+{
+ /**
+ * Public key of the reserve the open request was for.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * Fee paid for the request from the reserve.
+ */
+ struct TALER_Amount open_fee;
+
+ /**
+ * When was the request made.
+ */
+ struct GNUNET_TIME_Timestamp request_timestamp;
+
+ /**
+ * How long was the reserve supposed to be open.
+ */
+ struct GNUNET_TIME_Timestamp reserve_expiration;
+
+ /**
+ * Signature by the reserve approving the open request,
+ * with purpose #TALER_SIGNATURE_WALLET_RESERVE_OPEN.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+
+ /**
+ * How many open purses should be included with the
+ * open reserve?
+ */
+ uint32_t purse_limit;
+
+};
+
+
+/**
+ * Details about an (explicit) reserve close request.
+ */
+struct TALER_EXCHANGEDB_CloseRequest
+{
+ /**
+ * Public key of the reserve the history request was for.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
+ /**
+ * When was the request made.
+ */
+ struct GNUNET_TIME_Timestamp request_timestamp;
+
+ /**
+ * Hash of the payto://-URI of the target account
+ * for the closure, or all zeros for the reserve
+ * origin account.
+ */
+ struct TALER_FullPaytoHashP target_account_h_payto;
+
+ /**
+ * Signature by the reserve approving the history request.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+
+};
+
+
+/**
+ * @brief Types of operations on a reserve.
+ */
+enum TALER_EXCHANGEDB_ReserveOperation
+{
+ /**
+ * Money was deposited into the reserve via a bank transfer.
+ * This is how customers establish a reserve at the exchange.
+ */
+ TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE = 0,
+
+ /**
+ * A batch of coins was withdrawn from the reserve using /withdraw.
+ */
+ TALER_EXCHANGEDB_RO_WITHDRAW_COINS = 1,
+
+ /**
+ * A coin was returned to the reserve using /recoup.
+ */
+ TALER_EXCHANGEDB_RO_RECOUP_COIN = 2,
+
+ /**
+ * The exchange send inactive funds back from the reserve to the
+ * customer's bank account. This happens when the exchange
+ * closes a reserve with a non-zero amount left in it.
+ */
+ TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK = 3,
+
+ /**
+ * Event where a purse was merged into a reserve.
+ */
+ TALER_EXCHANGEDB_RO_PURSE_MERGE = 4,
+
+ /**
+ * Event where a wallet paid for a full reserve history.
+ */
+ TALER_EXCHANGEDB_RO_HISTORY_REQUEST = 5,
+
+ /**
+ * Event where a wallet paid to open a reserve for longer.
+ */
+ TALER_EXCHANGEDB_RO_OPEN_REQUEST = 6,
+
+ /**
+ * Event where a wallet requested a reserve to be closed.
+ */
+ TALER_EXCHANGEDB_RO_CLOSE_REQUEST = 7,
+
+};
+
+
+/**
+ * @brief Reserve history as a linked list. Lists all of the transactions
+ * associated with this reserve (such as the bank transfers that
+ * established the reserve and all /withdraw operations we have done
+ * since).
+ */
+struct TALER_EXCHANGEDB_ReserveHistory
+{
+
+ /**
+ * Next entry in the reserve history.
+ */
+ struct TALER_EXCHANGEDB_ReserveHistory *next;
+
+ /**
+ * Offset of this entry in the reserve history.
+ * Corresponds to the reserve_history_serial_id in the database.
+ */
+ uint64_t history_offset;
+
+ /**
+ * Type of the event, determines @e details.
+ */
+ enum TALER_EXCHANGEDB_ReserveOperation type;
+
+ /**
+ * Details of the operation, depending on @e type.
+ */
+ union
+ {
+
+ /**
+ * Details about a bank transfer to the exchange (reserve
+ * was established).
+ */
+ struct TALER_EXCHANGEDB_BankTransfer *bank;
+
+ /**
+ * Details about a /withdraw operation.
+ */
+ struct TALER_EXCHANGEDB_Withdraw *withdraw;
+
+ /**
+ * Details about a /recoup operation.
+ */
+ struct TALER_EXCHANGEDB_Recoup *recoup;
+
+ /**
+ * Details about a bank transfer from the exchange (reserve
+ * was closed).
+ */
+ struct TALER_EXCHANGEDB_ClosingTransfer *closing;
+
+ /**
+ * Details about a purse merge operation.
+ */
+ struct TALER_EXCHANGEDB_PurseMerge *merge;
+
+ /**
+ * Details about a (paid for) reserve history request.
+ */
+ struct TALER_EXCHANGEDB_HistoryRequest *history;
+
+ /**
+ * Details about a (paid for) open reserve request.
+ */
+ struct TALER_EXCHANGEDB_OpenRequest *open_request;
+
+ /**
+ * Details about an (explicit) reserve close request.
+ */
+ struct TALER_EXCHANGEDB_CloseRequest *close_request;
+
+ } details;
+
+};
+
+
+/**
+ * @brief Data about a coin for a deposit operation.
+ */
+struct TALER_EXCHANGEDB_CoinDepositInformation
+{
+ /**
+ * Information about the coin that is being deposited.
+ */
+ struct TALER_CoinPublicInfo coin;
+
+ /**
+ * ECDSA signature affirming that the customer intends
+ * this coin to be deposited at the merchant identified
+ * by @e h_wire in relation to the proposal data identified
+ * by @e h_contract_terms.
+ */
+ struct TALER_CoinSpendSignatureP csig;
+
+ /**
+ * Fraction of the coin's remaining value to be deposited, including
+ * depositing fee (if any). The coin is identified by @e coin_pub.
+ */
+ struct TALER_Amount amount_with_fee;
+
+};
+
+
+/**
+ * @brief Data from a batch deposit operation.
+ */
+struct TALER_EXCHANGEDB_BatchDeposit
+{
+
+ /**
+ * Public key of the merchant. Enables later identification
+ * of the merchant in case of a need to rollback transactions.
+ */
+ struct TALER_MerchantPublicKeyP merchant_pub;
+
+ /**
+ * Signature of the merchant over the contract, of purpose
+ * #TALER_SIGNATURE_MERCHANT_CONTRACT.
+ */
+ struct TALER_MerchantSignatureP merchant_sig;
+
+ /**
+ * Hash over the proposal data between merchant and customer
+ * (remains unknown to the Exchange).
+ */
+ struct TALER_PrivateContractHashP h_contract_terms;
+
+ /**
+ * Hash over additional inputs by the wallet.
+ */
+ struct GNUNET_HashCode wallet_data_hash;
+
+ /**
+ * Unsalted hash over @e receiver_wire_account.
+ */
+ struct TALER_FullPaytoHashP wire_target_h_payto;
+
+ /**
+ * Salt used by the merchant to compute "h_wire".
+ */
+ struct TALER_WireSaltP wire_salt;
+
+ /**
+ * Time when this request was generated. Used, for example, to
+ * assess when (roughly) the income was achieved for tax purposes.
+ * Note that the Exchange will only check that the timestamp is not "too
+ * far" into the future (i.e. several days). The fact that the
+ * timestamp falls within the validity period of the coin's
+ * denomination key is irrelevant for the validity of the deposit
+ * request, as obviously the customer and merchant could conspire to
+ * set any timestamp. Also, the Exchange must accept very old deposit
+ * requests, as the merchant might have been unable to transmit the
+ * deposit request in a timely fashion (so back-dating is not
+ * prevented).
+ */
+ struct GNUNET_TIME_Timestamp wallet_timestamp;
+
+ /**
+ * How much time does the merchant have to issue a refund request?
+ * Zero if refunds are not allowed. After this time, the coin
+ * cannot be refunded.
+ */
+ struct GNUNET_TIME_Timestamp refund_deadline;
+
+ /**
+ * How much time does the merchant have to execute the wire transfer?
+ * This time is advisory for aggregating transactions, not a hard
+ * constraint (as the merchant can theoretically pick any time,
+ * including one in the past).
+ */
+ struct GNUNET_TIME_Timestamp wire_deadline;
+
+ /**
+ * Row ID of the policy details; 0 if no policy applies.
+ */
+ uint64_t policy_details_serial_id;
+
+ /**
+ * Information about the receiver for executing the transaction. URI in
+ * payto://-format.
+ */
+ struct TALER_FullPayto receiver_wire_account;
+
+ /**
+ * Optional extra information to include in the wire transfer
+ * subject.
+ */
+ const char *extra_wire_subject_metadata;
+
+ /**
+ * Array about the coins that are being deposited.
+ */
+ const struct TALER_EXCHANGEDB_CoinDepositInformation *cdis;
+
+ /**
+ * Length of the @e cdis array.
+ */
+ unsigned int num_cdis;
+
+ /**
+ * False if @e wallet_data_hash was provided
+ */
+ bool no_wallet_data_hash;
+
+ /**
+ * True if further processing is blocked by policy.
+ */
+ bool policy_blocked;
+
+};
+
+
+/**
+ * @brief Data from a deposit operation. The combination of
+ * the coin's public key, the merchant's public key and the
+ * transaction ID must be unique. While a coin can (theoretically) be
+ * deposited at the same merchant twice (with partial spending), the
+ * merchant must either use a different public key or a different
+ * transaction ID for the two transactions. The same coin must not
+ * be used twice at the same merchant for the same transaction
+ * (as determined by transaction ID).
+ */
+struct TALER_EXCHANGEDB_Deposit
+{
+ /**
+ * Information about the coin that is being deposited.
+ */
+ struct TALER_CoinPublicInfo coin;
+
+ /**
+ * ECDSA signature affirming that the customer intends
+ * this coin to be deposited at the merchant identified
+ * by @e h_wire in relation to the proposal data identified
+ * by @e h_contract_terms.
+ */
+ struct TALER_CoinSpendSignatureP csig;
+
+ /**
+ * Public key of the merchant. Enables later identification
+ * of the merchant in case of a need to rollback transactions.
+ */
+ struct TALER_MerchantPublicKeyP merchant_pub;
+
+ /**
+ * Hash over the proposal data between merchant and customer
+ * (remains unknown to the Exchange).
+ */
+ struct TALER_PrivateContractHashP h_contract_terms;
+
+ /**
+ * Salt used by the merchant to compute "h_wire".
+ */
+ struct TALER_WireSaltP wire_salt;
+
+ /**
+ * Hash over inputs from the wallet to customize the contract.
+ */
+ struct GNUNET_HashCode wallet_data_hash;
+
+ /**
+ * Hash over the policy data for this deposit (remains unknown to the
+ * Exchange). Needed for the verification of the deposit's signature
+ */
+ struct TALER_ExtensionPolicyHashP h_policy;
+
+ /**
+ * Time when this request was generated. Used, for example, to
+ * assess when (roughly) the income was achieved for tax purposes.
+ * Note that the Exchange will only check that the timestamp is not "too
+ * far" into the future (i.e. several days). The fact that the
+ * timestamp falls within the validity period of the coin's
+ * denomination key is irrelevant for the validity of the deposit
+ * request, as obviously the customer and merchant could conspire to
+ * set any timestamp. Also, the Exchange must accept very old deposit
+ * requests, as the merchant might have been unable to transmit the
+ * deposit request in a timely fashion (so back-dating is not
+ * prevented).
+ */
+ struct GNUNET_TIME_Timestamp timestamp;
+
+ /**
+ * How much time does the merchant have to issue a refund request?
+ * Zero if refunds are not allowed. After this time, the coin
+ * cannot be refunded.
+ */
+ struct GNUNET_TIME_Timestamp refund_deadline;
+
+ /**
+ * How much time does the merchant have to execute the wire transfer?
+ * This time is advisory for aggregating transactions, not a hard
+ * constraint (as the merchant can theoretically pick any time,
+ * including one in the past).
+ */
+ struct GNUNET_TIME_Timestamp wire_deadline;
+
+ /**
+ * Fraction of the coin's remaining value to be deposited, including
+ * depositing fee (if any). The coin is identified by @e coin_pub.
+ */
+ struct TALER_Amount amount_with_fee;
+
+ /**
+ * Depositing fee.
+ */
+ struct TALER_Amount deposit_fee;
+
+ /**
+ * Information about the receiver for executing the transaction. URI in
+ * payto://-format.
+ */
+ struct TALER_FullPayto receiver_wire_account;
+
+ /**
+ * True if @e policy_json was provided
+ */
+ bool has_policy;
+
+ /**
+ * True if @e wallet_data_hash is not in use.
+ */
+ bool no_wallet_data_hash;
+
+};
+
+
+/**
+ * @brief Specification for a deposit operation in the
+ * `struct TALER_EXCHANGEDB_TransactionList`.
+ */
+struct TALER_EXCHANGEDB_DepositListEntry
+{
+
+ /**
+ * ECDSA signature affirming that the customer intends
+ * this coin to be deposited at the merchant identified
+ * by @e h_wire in relation to the proposal data identified
+ * by @e h_contract_terms.
+ */
+ struct TALER_CoinSpendSignatureP csig;
+
+ /**
+ * Public key of the merchant. Enables later identification
+ * of the merchant in case of a need to rollback transactions.
+ */
+ struct TALER_MerchantPublicKeyP merchant_pub;
+
+ /**
+ * Hash over the proposa data between merchant and customer
+ * (remains unknown to the Exchange).
+ */
+ struct TALER_PrivateContractHashP h_contract_terms;
+
+ /**
+ * Hash over inputs from the wallet to customize the contract.
+ */
+ struct GNUNET_HashCode wallet_data_hash;
+
+ /**
+ * Hash of the public denomination key used to sign the coin.
+ */
+ struct TALER_DenominationHashP h_denom_pub;
+
+ /**
+ * Age commitment hash, if applicable to the denomination. Should be all
+ * zeroes if age commitment is not applicable to the denonimation.
+ */
+ struct TALER_AgeCommitmentHashP h_age_commitment;
+
+ /**
+ * Salt used to compute h_wire from the @e receiver_wire_account.
+ */
+ struct TALER_WireSaltP wire_salt;
+
+ /**
+ * Hash over the policy data for this deposit (remains unknown to the
+ * Exchange). Needed for the verification of the deposit's signature
+ */
+ struct TALER_ExtensionPolicyHashP h_policy;
+
+ /**
+ * Fraction of the coin's remaining value to be deposited, including
+ * depositing fee (if any). The coin is identified by @e coin_pub.
+ */
+ struct TALER_Amount amount_with_fee;
+
+ /**
+ * Depositing fee.
+ */
+ struct TALER_Amount deposit_fee;
+
+ /**
+ * Time when this request was generated. Used, for example, to
+ * assess when (roughly) the income was achieved for tax purposes.
+ * Note that the Exchange will only check that the timestamp is not "too
+ * far" into the future (i.e. several days). The fact that the
+ * timestamp falls within the validity period of the coin's
+ * denomination key is irrelevant for the validity of the deposit
+ * request, as obviously the customer and merchant could conspire to
+ * set any timestamp. Also, the Exchange must accept very old deposit
+ * requests, as the merchant might have been unable to transmit the
+ * deposit request in a timely fashion (so back-dating is not
+ * prevented).
+ */
+ struct GNUNET_TIME_Timestamp timestamp;
+
+ /**
+ * How much time does the merchant have to issue a refund request?
+ * Zero if refunds are not allowed. After this time, the coin
+ * cannot be refunded.
+ */
+ struct GNUNET_TIME_Timestamp refund_deadline;
+
+ /**
+ * How much time does the merchant have to execute the wire transfer?
+ * This time is advisory for aggregating transactions, not a hard
+ * constraint (as the merchant can theoretically pick any time,
+ * including one in the past).
+ */
+ struct GNUNET_TIME_Timestamp wire_deadline;
+
+ /**
+ * Detailed information about the receiver for executing the transaction.
+ * URL in payto://-format.
+ */
+ struct TALER_FullPayto receiver_wire_account;
+
+ /**
+ * true, if age commitment is not applicable
+ */
+ bool no_age_commitment;
+
+ /**
+ * true, if wallet data hash is not present
+ */
+ bool no_wallet_data_hash;
+
+ /**
+ * True if a policy was provided with the deposit request
+ */
+ bool has_policy;
+
+ /**
+ * Has the deposit been wired?
+ */
+ bool done;
+
+};
+
+
+/**
+ * @brief Specification for a refund operation in a coin's transaction list.
+ */
+struct TALER_EXCHANGEDB_RefundListEntry
+{
+
+ /**
+ * Public key of the merchant.
+ */
+ struct TALER_MerchantPublicKeyP merchant_pub;
+
+ /**
+ * Signature from the merchant affirming the refund.
+ */
+ struct TALER_MerchantSignatureP merchant_sig;
+
+ /**
+ * Hash over the proposal data between merchant and customer
+ * (remains unknown to the Exchange).
+ */
+ struct TALER_PrivateContractHashP h_contract_terms;
+
+ /**
+ * Merchant-generated REFUND transaction ID to detect duplicate
+ * refunds.
+ */
+ uint64_t rtransaction_id;
+
+ /**
+ * Fraction of the original deposit's value to be refunded, including
+ * refund fee (if any). The coin is identified by @e coin_pub.
+ */
+ struct TALER_Amount refund_amount;
+
+ /**
+ * Refund fee to be covered by the customer.
+ */
+ struct TALER_Amount refund_fee;
+
+};
+
+
+/**
+ * @brief Specification for a refund operation. The combination of
+ * the coin's public key, the merchant's public key and the
+ * transaction ID must be unique. While a coin can (theoretically) be
+ * deposited at the same merchant twice (with partial spending), the
+ * merchant must either use a different public key or a different
+ * transaction ID for the two transactions. The same goes for
+ * refunds, hence we also have a "rtransaction" ID which is disjoint
+ * from the transaction ID. The same coin must not be used twice at
+ * the same merchant for the same transaction or rtransaction ID.
+ */
+struct TALER_EXCHANGEDB_Refund
+{
+ /**
+ * Information about the coin that is being refunded.
+ */
+ struct TALER_CoinPublicInfo coin;
+
+ /**
+ * Details about the refund.
+ */
+ struct TALER_EXCHANGEDB_RefundListEntry details;
+
+};
+
+
+/**
+ * @brief Specification for coin in a melt operation.
+ */
+struct TALER_EXCHANGEDB_Refresh
+{
+ /**
+ * Information about the coin that is being melted.
+ */
+ struct TALER_CoinPublicInfo coin;
+
+ /**
+ * Signature over the melting operation.
+ */
+ struct TALER_CoinSpendSignatureP coin_sig;
+
+ /**
+ * Refresh commitment this coin is melted into.
+ */
+ struct TALER_RefreshCommitmentP rc;
+
+ /**
+ * How much value is being melted? This amount includes the fees,
+ * so the final amount contributed to the melt is this value minus
+ * the fee for melting the coin. We include the fee in what is
+ * being signed so that we can verify a reserve's remaining total
+ * balance without needing to access the respective denomination key
+ * information each time.
+ */
+ struct TALER_Amount amount_with_fee;
+
+ /**
+ * Index (smaller #TALER_CNC_KAPPA) which the exchange has chosen to not
+ * have revealed during cut and choose.
+ */
+ uint32_t noreveal_index;
+
+};
+
+
+/**
+ * Information about a /coins/$COIN_PUB/melt operation in a coin transaction history.
+ */
+struct TALER_EXCHANGEDB_MeltListEntry
+{
+
+ /**
+ * Signature over the melting operation.
+ */
+ struct TALER_CoinSpendSignatureP coin_sig;
+
+ /**
+ * Refresh commitment this coin is melted into.
+ */
+ struct TALER_RefreshCommitmentP rc;
+
+ /**
+ * Hash of the public denomination key used to sign the coin.
+ */
+ struct TALER_DenominationHashP h_denom_pub;
+
+ /**
+ * Hash of the age commitment used to sign the coin, if age restriction was
+ * applicable to the denomination. May be all zeroes if no age restriction
+ * applies.
+ */
+ struct TALER_AgeCommitmentHashP h_age_commitment;
+
+ /**
+ * true, if no @e h_age_commitment is applicable
+ */
+ bool no_age_commitment;
+
+ /**
+ * How much value is being melted? This amount includes the fees,
+ * so the final amount contributed to the melt is this value minus
+ * the fee for melting the coin. We include the fee in what is
+ * being signed so that we can verify a reserve's remaining total
+ * balance without needing to access the respective denomination key
+ * information each time.
+ */
+ struct TALER_Amount amount_with_fee;
+
+ /**
+ * Melt fee the exchange charged.
+ */
+ struct TALER_Amount melt_fee;
+
+ /**
+ * Index (smaller #TALER_CNC_KAPPA) which the exchange has chosen to not
+ * have revealed during cut and choose.
+ */
+ uint32_t noreveal_index;
+
+ /**
+ * The refresh seed that was used for the melt operation
+ */
+ struct TALER_PublicRefreshMasterSeedP refresh_seed;
+
+ /**
+ * If false, @e blinding_seed is present
+ */
+ bool no_blinding_seed;
+
+ /**
+ * If @e no_blinding_seed it false, the blinding seed that was used
+ * for the melt operation, in case of CS denominations.
+ */
+ struct TALER_BlindingMasterSeedP blinding_seed;
+
+};
+
+
+/**
+ * Information about a /purses/$PID/deposit operation in a coin transaction history.
+ */
+struct TALER_EXCHANGEDB_PurseDepositListEntry
+{
+
+ /**
+ * Exchange hosting the purse, NULL for this exchange.
+ */
+ char *exchange_base_url;
+
+ /**
+ * Public key of the purse.
+ */
+ struct TALER_PurseContractPublicKeyP purse_pub;
+
+ /**
+ * Contribution of the coin to the purse, including
+ * deposit fee.
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Depositing fee.
+ */
+ struct TALER_Amount deposit_fee;
+
+ /**
+ * Signature by the coin affirming the deposit.
+ */
+ struct TALER_CoinSpendSignatureP coin_sig;
+
+ /**
+ * Hash of the age commitment used to sign the coin, if age restriction was
+ * applicable to the denomination.
+ */
+ struct TALER_AgeCommitmentHashP h_age_commitment;
+
+ /**
+ * Hash of the public denomination key used to sign the coin.
+ */
+ struct TALER_DenominationHashP h_denom_pub;
+
+ /**
+ * Set to true if the coin was refunded.
+ */
+ bool refunded;
+
+ /**
+ * Set to true if there was no age commitment.
+ */
+ bool no_age_commitment;
+
+};
+
+
+/**
+ * @brief Specification for a purse refund operation in a coin's transaction list.
+ */
+struct TALER_EXCHANGEDB_PurseRefundListEntry
+{
+
+ /**
+ * Public key of the purse.
+ */
+ struct TALER_PurseContractPublicKeyP purse_pub;
+
+ /**
+ * Fraction of the original deposit's value to be refunded, including
+ * refund fee (if any). The coin is identified by @e coin_pub.
+ */
+ struct TALER_Amount refund_amount;
+
+ /**
+ * Refund fee to be covered by the customer.
+ */
+ struct TALER_Amount refund_fee;
+
+};
+
+
+/**
+ * Information about a /reserves/$RID/open operation in a coin transaction history.
+ */
+struct TALER_EXCHANGEDB_ReserveOpenListEntry
+{
+
+ /**
+ * Signature of the reserve.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+
+ /**
+ * Contribution of the coin to the open fee, including
+ * deposit fee.
+ */
+ struct TALER_Amount coin_contribution;
+
+ /**
+ * Signature by the coin affirming the open deposit.
+ */
+ struct TALER_CoinSpendSignatureP coin_sig;
+
+};
+
+
+/**
+ * Information about a /purses/$PID/deposit operation.
+ */
+struct TALER_EXCHANGEDB_PurseDeposit
+{
+
+ /**
+ * Exchange hosting the purse, NULL for this exchange.
+ */
+ char *exchange_base_url;
+
+ /**
+ * Public key of the purse.
+ */
+ struct TALER_PurseContractPublicKeyP purse_pub;
+
+ /**
+ * Contribution of the coin to the purse, including
+ * deposit fee.
+ */
+ struct TALER_Amount amount;
+
+ /**
+ * Depositing fee.
+ */
+ struct TALER_Amount deposit_fee;
+
+ /**
+ * Signature by the coin affirming the deposit.
+ */
+ struct TALER_CoinSpendSignatureP coin_sig;
+
+ /**
+ * Public key of the coin.
+ */
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+
+ /**
+ * Hash of the age commitment used to sign the coin, if age restriction was
+ * applicable to the denomination. May be all zeroes if no age restriction
+ * applies.
+ */
+ struct TALER_AgeCommitmentHashP h_age_commitment;
+
+ /**
+ * Set to true if @e h_age_commitment is not available.
+ */
+ bool no_age_commitment;
+
+};
+
+/**
+ * Information about a melt operation.
+ */
+struct TALER_EXCHANGEDB_Melt
+{
+
+ /**
+ * Overall session data.
+ */
+ struct TALER_EXCHANGEDB_Refresh session;
+
+ /**
+ * Melt fee the exchange charged.
+ */
+ struct TALER_Amount melt_fee;
+
+};
+
+
+/**
+ * Information about a melt operation since vDOLDPLUS of the protocol.
+ * This also includes the information for the reveal phase.
+ */
+struct TALER_EXCHANGEDB_Refresh_vDOLDPLUS
+{
+ /**
+ * Information about the coin that is being melted.
+ */
+ struct TALER_CoinPublicInfo coin;
+
+ /**
+ * Signature over the melting operation.
+ */
+ struct TALER_CoinSpendSignatureP coin_sig;
+
+ /**
+ * Refresh commitment this coin is melted into.
+ */
+ struct TALER_RefreshCommitmentP rc;
+
+ /**
+ * True if the client has successfully performed the reveal part
+ * of the refresh protocol, after the melt.
+ */
+ bool is_revealed;
+
+ /**
+ * @since vDOLDPLUS
+ * Mark if we have a v27 Refresh object.
+ * That is, the @a refresh_seed refers to the vDOLDPLUS master_refresh_seed
+ * from the original request, AND the client has provided transfer public keys,
+ * see below, @a transfer_public_keys
+ */
+ bool is_v27_refresh;
+
+ /**
+ * Public seed from which the refresh nonces (v27) or transfer secrets (vDOLDPLUS)
+ * per coin candidate were derived from.
+ */
+ struct TALER_PublicRefreshMasterSeedP refresh_seed;
+
+ /**
+ * How much value is being melted? This amount includes the fees,
+ * so the final amount contributed to the melt is this value minus
+ * the fee for melting the coin. We include the fee in what is
+ * being signed so that we can verify a reserve's remaining total
+ * balance without needing to access the respective denomination key
+ * information each time.
+ */
+ struct TALER_Amount amount_with_fee;
+
+ /**
+ * Number of coins to be refreshed into
+ */
+ size_t num_coins;
+
+ /**
+ * The running hash over all kappa * @a num_coins blinded coin envelopes, provided by
+ * the client.
+ */
+ struct TALER_HashBlindedPlanchetsP planchets_h;
+
+ /**
+ * The running hash over all chosen (noreveal_index) @a num_coins blinded coin envelopes.
+ */
+ struct TALER_HashBlindedPlanchetsP selected_h;
+
+ /**
+ * Array of @a num_coins denomination signatures of the blinded coins.
+ */
+ struct TALER_BlindedDenominationSignature *denom_sigs;
+
+ /**
+ * If @a is_v27_refresh is false, the client performed a vDOLDPLUS refresh,
+ * and has provided @a num_coins * kappa transfer public keys.
+ * This is the chosen (at index @a noreveal_index) array of @a num_coins transfer public keys.
+ */
+ struct TALER_TransferPublicKeyP *transfer_pubs;
+
+ /**
+ * Array of @a num_coins serial id's of the denominations.
+ * If @e coin.no_age_commitment is false, the denominations
+ * MUST support age restriction.
+ */
+ uint64_t *denom_serials;
+
+ /**
+ * Index (smaller #TALER_CNC_KAPPA) which the exchange chose to not
+ * to be revealed during cut and choose.
+ */
+ uint32_t noreveal_index;
+
+ /**
+ * True, if the client has successfully performed the reveal step
+ */
+ bool revealed;
+
+ /**
+ * If true, no @e blinding_seed is set and @e num_cs_r_values is 0.
+ */
+ bool no_blinding_seed;
+
+ /**
+ * If @e no_blinding_seed is false, the blinding seed for the nonces needed for
+ * blind CS signatures.
+ */
+ struct TALER_BlindingMasterSeedP blinding_seed;
+
+ /**
+ * Number of elements in @e cs_r_values.
+ */
+ size_t num_cs_r_values;
+
+ /**
+ * Array @e num_cs_r_values of public R-values for CS that were generated from the
+ * @e blinding_seed, a coin's index and the denomination's private key during the
+ * the /melt request, to ensure idempotency in case of expiration of a denomination.
+ * NULL if @e num_cs_r_values is 0.
+ */
+ struct GNUNET_CRYPTO_CSPublicRPairP *cs_r_values;
+
+ /**
+ * If @e num_cs_r_values is not 0, the bitvector of choices for the pairs
+ * in @e cs_r_values that was made by the exchange. The vector is in NBO
+ * and the lowest bit represents the choice for the pair at index 0 into @e cs_r_values;
+ */
+ uint64_t cs_r_choices;
+
+ /**
+ * [out]-Array of @a num_coins hashes of the public keys of the denominations
+ * identified by @e denom_serials. This field is set when calling
+ * get_refresh
+ */
+ struct TALER_DenominationHashP *denom_pub_hashes;
+};
+
+
+/**
+ * @brief Linked list of refresh information linked to a coin.
+ */
+struct TALER_EXCHANGEDB_LinkList
+{
+ /**
+ * Information is stored in a NULL-terminated linked list.
+ */
+ struct TALER_EXCHANGEDB_LinkList *next;
+
+ /**
+ * Denomination public key, determines the value of the coin.
+ */
+ struct TALER_DenominationPublicKey denom_pub;
+
+ /**
+ * Signature over the blinded envelope.
+ */
+ struct TALER_BlindedDenominationSignature ev_sig;
+
+ /**
+ * Exchange-provided values during the coin generation.
+ */
+ struct TALER_ExchangeBlindingValues alg_values;
+
+ /**
+ * Signature of the original coin being refreshed over the
+ * link data, of type #TALER_SIGNATURE_WALLET_COIN_LINK
+ */
+ struct TALER_CoinSpendSignatureP orig_coin_link_sig;
+
+ /**
+ * Session nonce, if cipher has one.
+ */
+ union GNUNET_CRYPTO_BlindSessionNonce nonce;
+
+ /**
+ * Offset that generated this coin in the refresh
+ * operation.
+ */
+ uint32_t coin_refresh_offset;
+
+ /**
+ * Set to true if @e nonce was initialized.
+ */
+ bool have_nonce;
+};
+
+
+/**
+ * @brief Enumeration to classify the different types of transactions
+ * that can be done with a coin.
+ */
+enum TALER_EXCHANGEDB_TransactionType
+{
+
+ /**
+ * Deposit operation.
+ */
+ TALER_EXCHANGEDB_TT_DEPOSIT = 0,
+
+ /**
+ * Melt operation.
+ */
+ TALER_EXCHANGEDB_TT_MELT = 1,
+
+ /**
+ * Refund operation.
+ */
+ TALER_EXCHANGEDB_TT_REFUND = 2,
+
+ /**
+ * Recoup-refresh operation (on the old coin, adding to the old coin's value)
+ */
+ TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER = 3,
+
+ /**
+ * Recoup operation.
+ */
+ TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW = 4,
+
+ /**
+ * Recoup-refresh operation (on the new coin, eliminating its value)
+ */
+ TALER_EXCHANGEDB_TT_RECOUP_REFRESH = 5,
+
+ /**
+ * Purse deposit operation.
+ */
+ TALER_EXCHANGEDB_TT_PURSE_DEPOSIT = 6,
+
+ /**
+ * Purse deposit operation.
+ */
+ TALER_EXCHANGEDB_TT_PURSE_REFUND = 7,
+
+ /**
+ * Reserve open deposit operation.
+ */
+ TALER_EXCHANGEDB_TT_RESERVE_OPEN = 8
+
+};
+
+
+/**
+ * @brief List of transactions we performed for a particular coin.
+ */
+struct TALER_EXCHANGEDB_TransactionList
+{
+
+ /**
+ * Next pointer in the NULL-terminated linked list.
+ */
+ struct TALER_EXCHANGEDB_TransactionList *next;
+
+ /**
+ * Type of the transaction, determines what is stored in @e details.
+ */
+ enum TALER_EXCHANGEDB_TransactionType type;
+
+ /**
+ * Serial ID of this entry in the @e type-specific table.
+ */
+ uint64_t serial_id;
+
+ /**
+ * Serial ID of this entry in the coin history table.
+ */
+ uint64_t coin_history_id;
+
+ /**
+ * Details about the transaction, depending on @e type.
+ */
+ union
+ {
+
+ /**
+ * Details if transaction was a deposit operation.
+ * (#TALER_EXCHANGEDB_TT_DEPOSIT)
+ */
+ struct TALER_EXCHANGEDB_DepositListEntry *deposit;
+
+ /**
+ * Details if transaction was a melt operation.
+ * (#TALER_EXCHANGEDB_TT_MELT)
+ */
+ struct TALER_EXCHANGEDB_MeltListEntry *melt;
+
+ /**
+ * Details if transaction was a refund operation.
+ * (#TALER_EXCHANGEDB_TT_REFUND)
+ */
+ struct TALER_EXCHANGEDB_RefundListEntry *refund;
+
+ /**
+ * Details if transaction was a recoup-refund operation where
+ * this coin was the OLD coin.
+ * (#TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER).
+ */
+ struct TALER_EXCHANGEDB_RecoupRefreshListEntry *old_coin_recoup;
+
+ /**
+ * Details if transaction was a recoup operation.
+ * (#TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW)
+ */
+ struct TALER_EXCHANGEDB_RecoupListEntry *recoup;
+
+ /**
+ * Details if transaction was a recoup-refund operation where
+ * this coin was the REFRESHED coin.
+ * (#TALER_EXCHANGEDB_TT_RECOUP_REFRESH)
+ */
+ struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup_refresh;
+
+ /**
+ * Coin was deposited into a purse.
+ * (#TALER_EXCHANGEDB_TT_PURSE_DEPOSIT)
+ */
+ struct TALER_EXCHANGEDB_PurseDepositListEntry *purse_deposit;
+
+ /**
+ * Coin was refunded upon purse expiration
+ * (#TALER_EXCHANGEDB_TT_PURSE_REFUND)
+ */
+ struct TALER_EXCHANGEDB_PurseRefundListEntry *purse_refund;
+
+ /**
+ * Coin was used to pay to open a reserve.
+ * (#TALER_EXCHANGEDB_TT_RESERVE_OPEN)
+ */
+ struct TALER_EXCHANGEDB_ReserveOpenListEntry *reserve_open;
+
+ } details;
+
+};
+
+
+/**
+ * Callback with data about a prepared wire transfer.
+ *
+ * @param cls closure
+ * @param rowid row identifier used to mark prepared transaction as done
+ * @param wire_method which wire method is this preparation data for
+ * @param buf transaction data that was persisted, NULL on error
+ * @param buf_size number of bytes in @a buf, 0 on error
+ */
+typedef void
+(*TALER_EXCHANGEDB_WirePreparationIterator) (void *cls,
+ uint64_t rowid,
+ const char *wire_method,
+ const char *buf,
+ size_t buf_size);
+
+/**
+ * Function called to get an unfinished wire transfer
+ * preparation data. Fetches at most one item.
+ *
+ * @param cls closure
+ * @param start_row offset to query table at
+ * @param limit maximum number of results to return
+ * @param cb function to call for ONE unfinished item
+ * @param cb_cls closure for @a cb
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_wire_prepare_data_get (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t start_row,
+ uint64_t limit,
+ TALER_EXCHANGEDB_WirePreparationIterator cb,
+ void *cb_cls);
+
+#endif
diff --git a/src/include/taler/exchange-database/wire_prepare_data_insert.h b/src/include/taler/exchange-database/wire_prepare_data_insert.h
@@ -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 src/include/taler/exchange-database/wire_prepare_data_insert.h
+ * @brief implementation of the wire_prepare_data_insert function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_WIRE_PREPARE_DATA_INSERT_H
+#define EXCHANGE_DATABASE_WIRE_PREPARE_DATA_INSERT_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to insert wire transfer commit data into the DB.
+ *
+ * @param cls closure
+ * @param type type of the wire transfer (i.e. "iban")
+ * @param buf buffer with wire transfer preparation data
+ * @param buf_size number of bytes in @a buf
+ * @return query status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_wire_prepare_data_insert (struct EXCHANGEDB_PostgresContext *ctx,
+ const char *type,
+ const char *buf,
+ size_t buf_size);
+
+#endif
diff --git a/src/include/taler/exchange-database/wire_prepare_data_mark_failed.h b/src/include/taler/exchange-database/wire_prepare_data_mark_failed.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/wire_prepare_data_mark_failed.h
+ * @brief implementation of the wire_prepare_data_mark_failed function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_WIRE_PREPARE_DATA_MARK_FAILED_H
+#define EXCHANGE_DATABASE_WIRE_PREPARE_DATA_MARK_FAILED_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to mark wire transfer commit data as failed.
+ *
+ * @param cls closure
+ * @param rowid which entry to mark as failed
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_wire_prepare_data_mark_failed (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t rowid);
+
+#endif
diff --git a/src/include/taler/exchange-database/wire_prepare_data_mark_finished.h b/src/include/taler/exchange-database/wire_prepare_data_mark_finished.h
@@ -0,0 +1,41 @@
+/*
+ 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 src/include/taler/exchange-database/wire_prepare_data_mark_finished.h
+ * @brief implementation of the wire_prepare_data_mark_finished function for Postgres
+ * @author Christian Grothoff
+ */
+#ifndef EXCHANGE_DATABASE_WIRE_PREPARE_DATA_MARK_FINISHED_H
+#define EXCHANGE_DATABASE_WIRE_PREPARE_DATA_MARK_FINISHED_H
+
+#include "taler/taler_util.h"
+#include "taler/taler_json_lib.h"
+#include "taler/taler_exchangedb_plugin.h"
+
+
+struct EXCHANGEDB_PostgresContext;
+/**
+ * Function called to mark wire transfer commit data as finished.
+ *
+ * @param cls closure
+ * @param rowid which entry to mark as finished
+ * @return transaction status code
+ */
+enum GNUNET_DB_QueryStatus
+EXCHANGEDB_wire_prepare_data_mark_finished (struct EXCHANGEDB_PostgresContext *ctx,
+ uint64_t rowid);
+
+#endif