gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated (87198f12 -> b3a8ad3c)


From: gnunet
Subject: [taler-exchange] branch master updated (87198f12 -> b3a8ad3c)
Date: Tue, 06 Dec 2022 14:15:03 +0100

This is an automated email from the git hooks/post-receive script.

joseph-xu pushed a change to branch master
in repository exchange.

    from 87198f12 refactor procedures.sql
     new b6476ac8 batch modifications
     new 6e3d1bdc some modifications for batch test
     new a71893d5 plugin update
     new 4b7cb13c some modifications
     new b3a8ad3c new files for experimental batch insert

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 contrib/gana                                       |    2 +-
 src/exchangedb/Makefile.am                         |   33 +-
 src/exchangedb/pg_batch2_reserves_in_insert.c      |  282 ++
 ..._in_insert.h => pg_batch2_reserves_in_insert.h} |   16 +-
 src/exchangedb/pg_batch4_reserves_in_insert.c      |  266 ++
 ..._in_insert.h => pg_batch4_reserves_in_insert.h} |   19 +-
 src/exchangedb/pg_batch_reserves_in_insert.c       |  168 +-
 src/exchangedb/pg_get_link_data.c                  |   68 +-
 src/exchangedb/pg_get_policy_details.c             |    2 +-
 src/exchangedb/pg_select_refunds_by_coin.c         |   20 +-
 src/exchangedb/plugin_exchangedb_postgres.c        | 4558 +-------------------
 ... => test_exchangedb_batch_reserves_in_insert.c} |   51 +-
 src/exchangedb/test_exchangedb_by_j.c              |   35 +-
 src/include/taler_exchangedb_plugin.h              |   15 +
 14 files changed, 861 insertions(+), 4674 deletions(-)
 create mode 100644 src/exchangedb/pg_batch2_reserves_in_insert.c
 copy src/exchangedb/{pg_batch_reserves_in_insert.h => 
pg_batch2_reserves_in_insert.h} (69%)
 create mode 100644 src/exchangedb/pg_batch4_reserves_in_insert.c
 copy src/exchangedb/{pg_batch_reserves_in_insert.h => 
pg_batch4_reserves_in_insert.h} (62%)
 copy src/exchangedb/{test_exchangedb_by_j.c => 
test_exchangedb_batch_reserves_in_insert.c} (84%)

diff --git a/contrib/gana b/contrib/gana
index 20f8eb7a..212ee0a7 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 20f8eb7a72e2160409f0f78264ec5198e9caa193
+Subproject commit 212ee0a78adc43cb5c04d6ea96ccc2fe74fed62b
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index 4d9bfcb5..a6eb6747 100644
--- a/src/exchangedb/Makefile.am
+++ b/src/exchangedb/Makefile.am
@@ -243,6 +243,7 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
   pg_select_account_merges_above_serial_id.h 
pg_select_account_merges_above_serial_id.c \
   pg_select_all_purse_decisions_above_serial_id.h 
pg_select_all_purse_decisions_above_serial_id.c \
   pg_batch_reserves_in_insert.h pg_batch_reserves_in_insert.c \
+  pg_batch2_reserves_in_insert.h pg_batch2_reserves_in_insert.c \
   pg_select_reserve_open_above_serial_id.c 
pg_select_reserve_open_above_serial_id.h
 libtaler_plugin_exchangedb_postgres_la_LIBADD = \
   $(LTLIBINTL)
@@ -280,12 +281,16 @@ check_PROGRAMS = \
   test-exchangedb-postgres \
   bench-db-postgres\
   perf-exchangedb-reserves-in-insert-postgres\
-  test-exchangedb-by-j-postgres
+  test-exchangedb-by-j-postgres\
+  test-exchangedb-batch-reserves-in-insert-postgres
 AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export 
PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
 TESTS = \
   test-exchangedb-postgres\
   test-exchangedb-by-j-postgres\
-  perf-exchangedb-reserves-in-insert-postgres
+  perf-exchangedb-reserves-in-insert-postgres\
+  test-exchangedb-batch-reserves-in-insert-postgres
+
+
 test_exchangedb_postgres_SOURCES = \
   test_exchangedb.c
 test_exchangedb_postgres_LDADD = \
@@ -333,5 +338,29 @@ bench_db_postgres_LDADD = \
   -lgnunetutil \
   $(XLIB)
 
+
+test_exchangedb_batch_reserves_in_insert_postgres_SOURCES = \
+  test_exchangedb_batch_reserves_in_insert.c
+test_exchangedb_batch_reserves_in_insert_postgres_LDADD = \
+  libtalerexchangedb.la \
+  $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/util/libtalerutil.la \
+  $(top_builddir)/src/pq/libtalerpq.la \
+  -ljansson \
+  -lgnunetjson \
+  -lgnunetutil \
+  $(XLIB)
+
+bench_db_postgres_SOURCES = \
+  bench_db.c
+bench_db_postgres_LDADD = \
+  libtalerexchangedb.la \
+  $(top_builddir)/src/util/libtalerutil.la \
+  $(top_builddir)/src/pq/libtalerpq.la \
+  -lgnunetpq \
+  -lgnunetutil \
+  $(XLIB)
+
+
 EXTRA_test_exchangedb_postgres_DEPENDENCIES = \
   libtaler_plugin_exchangedb_postgres.la
diff --git a/src/exchangedb/pg_batch2_reserves_in_insert.c 
b/src/exchangedb/pg_batch2_reserves_in_insert.c
new file mode 100644
index 00000000..8aca11de
--- /dev/null
+++ b/src/exchangedb/pg_batch2_reserves_in_insert.c
@@ -0,0 +1,282 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 Taler Systems SA
+
+   TALER is free software; you can redistribute it and/or modify it under the
+   terms of the GNU General Public License as published by the Free Software
+   Foundation; either version 3, or (at your option) any later version.
+
+   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along with
+   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ * @file exchangedb/pg_batch_reserves_in_insert.c
+ * @brief Implementation of the reserves_in_insert function for Postgres
+ * @author Joseph Xu
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_batch_reserves_in_insert.h"
+#include "pg_helper.h"
+#include "pg_start.h"
+#include "pg_rollback.h"
+#include "pg_start_read_committed.h"
+#include "pg_commit.h"
+#include "pg_reserves_get.h"
+#include "pg_reserves_update.h"
+#include "pg_setup_wire_target.h"
+#include "pg_event_notify.h"
+#include "pg_preflight.h"
+
+/**
+ * Generate event notification for the reserve change.
+ *
+ * @param reserve_pub reserve to notfiy on
+ */
+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_PG_get_event_notify_channel (&rep.header);
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_batch2_reserves_in_insert (void *cls,
+                                 const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
+                                 unsigned int reserves_length,
+                                 enum GNUNET_DB_QueryStatus *results)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs1;
+  struct GNUNET_TIME_Timestamp expiry;
+  struct GNUNET_TIME_Timestamp gc;
+  struct TALER_PaytoHashP h_payto;
+  uint64_t reserve_uuid;
+  uint64_t reserve_uuid2;
+  bool conflicted;
+  bool conflicted2;
+  bool transaction_duplicate;
+  bool transaction_duplicate2;
+  bool need_update = false;
+  bool need_update2 = false;
+  struct GNUNET_TIME_Timestamp reserve_expiration
+    = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
+  bool conflicts[reserves_length];
+  bool conflicts2[reserves_length];
+  char *notify_s[reserves_length];
+
+  if (GNUNET_OK !=
+      TEH_PG_preflight (pg))
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  PREPARE (pg,
+           "reserve_create",
+           "SELECT "
+           "out_reserve_found AS conflicted"
+           ",out_reserve_found2 AS conflicted2"
+           ",transaction_duplicate"
+           ",transaction_duplicate2"
+           ",ruuid AS reserve_uuid"
+           ",ruuid2 AS reserve_uuid2"
+           " FROM batch2_reserves_insert"
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);");
+  expiry = GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
+                              pg->idle_reserve_expiration_time));
+  gc = GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                              pg->legal_reserve_expiration_time));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Creating reserve %s with expiration in %s\n",
+              TALER_B2S (&(reserves->reserve_pub)),
+              GNUNET_STRINGS_relative_time_to_string (
+                pg->idle_reserve_expiration_time,
+                GNUNET_NO));
+
+  {
+    if (GNUNET_OK !=
+        TEH_PG_start_read_committed(pg,
+                                   "READ_COMMITED"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
+  /* Optimistically assume this is a new reserve, create balance for the first
+     time; we do this before adding the actual transaction to "reserves_in",
+     as for a new reserve it can't be a duplicate 'add' operation, and as
+     the 'add' operation needs the reserve entry as a foreign key. */
+  for (unsigned int i=0;i<reserves_length;i++)
+  {
+    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+    notify_s[i] = compute_notify_on_reserve (&reserve->reserve_pub);
+  }
+
+  for (unsigned int i=0;i<(reserves_length & ~1);i+=2)
+  {
+    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve0 = &reserves[i];
+    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve1 = &reserves[i+1];
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&reserve0->reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserve0->wire_reference),
+      TALER_PQ_query_param_amount (&reserve0->balance),
+      GNUNET_PQ_query_param_string (reserve0->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve0->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve0->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+      GNUNET_PQ_query_param_string (notify_s[i]),
+      GNUNET_PQ_query_param_auto_from_type (&reserve1->reserve_pub),
+      GNUNET_PQ_query_param_uint64 (&reserve1->wire_reference),
+      TALER_PQ_query_param_amount (&reserve1->balance),
+      GNUNET_PQ_query_param_string (reserve1->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve1->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve1->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+      GNUNET_PQ_query_param_end
+    };
+
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_bool ("conflicted",
+                                  &conflicted),
+      GNUNET_PQ_result_spec_bool ("conflicted2",
+                                  &conflicted2),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                  &transaction_duplicate),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
+                                  &transaction_duplicate2),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                    &reserve_uuid),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
+                                    &reserve_uuid2),
+      GNUNET_PQ_result_spec_end
+    };
+
+    TALER_payto_hash (reserve0->sender_account_details,
+                      &h_payto);
+    TALER_payto_hash (reserve1->sender_account_details,
+                      &h_payto);
+
+    /* Note: query uses 'on conflict do nothing' */
+    qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                    "reserve_create",
+                                                    params,
+                                                    rs);
+
+    if (qs1 < 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to create reserves (%d)\n",
+                  qs1);
+      return qs1;
+    }
+    if (reserves_length & 1)
+    {
+      const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = 
&reserves[reserves_length-1];
+      // single insert logic here
+    }
+   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
+   results[i] = (transaction_duplicate)
+      ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+   conflicts[i] = conflicted;
+   conflicts2[i] = conflicted2;
+   //    fprintf(stdout, "%d", conflicts[i]);
+   // fprintf(stdout, "%d", conflicts2[i]);
+   if ((!conflicts[i] && transaction_duplicate) ||(!conflicts2[i] && 
transaction_duplicate2))
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+   need_update |= conflicted |= conflicted2;
+  }
+  // commit
+  {
+    enum GNUNET_DB_QueryStatus cs;
+
+    cs = TEH_PG_commit (pg);
+    if (cs < 0)
+      return cs;
+  }
+
+  if (!need_update)
+    goto exit;
+  // begin serializable
+  {
+    if (GNUNET_OK !=
+        TEH_PG_start(pg,
+                     "reserve-insert-continued"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
+
+  enum GNUNET_DB_QueryStatus qs2;
+  PREPARE (pg,
+           "reserves_in_add_transaction",
+           "SELECT batch_reserves_update"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
+  for (unsigned int i=0;i<reserves_length;i++)
+  {
+    if (! conflicts[i])
+      continue;
+    {
+      const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
+        GNUNET_PQ_query_param_timestamp (&expiry),
+        GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
+        TALER_PQ_query_param_amount (&reserve->balance),
+        GNUNET_PQ_query_param_string (reserve->exchange_account_name),
+        GNUNET_PQ_query_param_bool (conflicted),
+        GNUNET_PQ_query_param_auto_from_type (&h_payto),
+        GNUNET_PQ_query_param_string (notify_s[i]),
+        GNUNET_PQ_query_param_end
+      };
+
+      qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                                "reserves_in_add_transaction",
+                                                params);
+      if (qs2<0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to update reserves (%d)\n",
+                    qs2);
+        return qs2;
+      }
+    }
+  }
+  {
+    enum GNUNET_DB_QueryStatus cs;
+
+    cs = TEH_PG_commit (pg);
+    if (cs < 0)
+      return cs;
+  }
+
+ exit:
+  for (unsigned int i=0;i<reserves_length;i++)
+    GNUNET_free (notify_s[i]);
+
+  return reserves_length;
+}
diff --git a/src/exchangedb/pg_batch_reserves_in_insert.h 
b/src/exchangedb/pg_batch2_reserves_in_insert.h
similarity index 69%
copy from src/exchangedb/pg_batch_reserves_in_insert.h
copy to src/exchangedb/pg_batch2_reserves_in_insert.h
index 76679567..bb6be3f6 100644
--- a/src/exchangedb/pg_batch_reserves_in_insert.h
+++ b/src/exchangedb/pg_batch2_reserves_in_insert.h
@@ -14,22 +14,20 @@
    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 /**
- * @file exchangedb/pg_batch_reserves_in_insert.h
- * @brief implementation of the batch_reserves_in_insert function for Postgres
+ * @file exchangedb/pg_batch2_reserves_in_insert.h
+ * @brief implementation of the batch2_reserves_in_insert function for Postgres
  * @author Christian Grothoff
  */
-#ifndef PG_BATCH_RESERVES_IN_INSERT_H
-#define PG_BATCH_RESERVES_IN_INSERT_H
+#ifndef PG_BATCH2_RESERVES_IN_INSERT_H
+#define PG_BATCH2_RESERVES_IN_INSERT_H
 
 #include "taler_util.h"
 #include "taler_json_lib.h"
 #include "taler_exchangedb_plugin.h"
-
-
 enum GNUNET_DB_QueryStatus
-TEH_PG_batch_reserves_in_insert (void *cls,
-                              const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
-                              unsigned int reserves_length,
+TEH_PG_batch2_reserves_in_insert (void *cls,
+                                 const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
+                                 unsigned int reserves_length,
                                  enum GNUNET_DB_QueryStatus *results);
 
 #endif
diff --git a/src/exchangedb/pg_batch4_reserves_in_insert.c 
b/src/exchangedb/pg_batch4_reserves_in_insert.c
new file mode 100644
index 00000000..604a31e7
--- /dev/null
+++ b/src/exchangedb/pg_batch4_reserves_in_insert.c
@@ -0,0 +1,266 @@
+/*
+   This file is part of TALER
+   Copyright (C) 2022 Taler Systems SA
+
+   TALER is free software; you can redistribute it and/or modify it under the
+   terms of the GNU General Public License as published by the Free Software
+   Foundation; either version 3, or (at your option) any later version.
+
+   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+   You should have received a 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_batch4_reserves_in_insert.c
+ * @brief Implementation of the reserves_in_insert function for Postgres
+ * @author Joseph Xu
+ */
+#include "platform.h"
+#include "taler_error_codes.h"
+#include "taler_dbevents.h"
+#include "taler_pq_lib.h"
+#include "pg_batch_reserves_in_insert.h"
+#include "pg_helper.h"
+#include "pg_start.h"
+#include "pg_rollback.h"
+#include "pg_start_read_committed.h"
+#include "pg_commit.h"
+#include "pg_reserves_get.h"
+#include "pg_reserves_update.h"
+#include "pg_setup_wire_target.h"
+#include "pg_event_notify.h"
+#include "pg_preflight.h"
+
+/**
+ * Generate event notification for the reserve change.
+ *
+ * @param reserve_pub reserve to notfiy on
+ */
+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_PG_get_event_notify_channel (&rep.header);
+}
+
+
+enum GNUNET_DB_QueryStatus
+TEH_PG_batch4_reserves_in_insert (void *cls,
+                                 const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
+                                 unsigned int reserves_length,
+                                 enum GNUNET_DB_QueryStatus *results)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs1;
+  struct GNUNET_TIME_Timestamp expiry;
+  struct GNUNET_TIME_Timestamp gc;
+  struct TALER_PaytoHashP h_payto;
+  uint64_t reserve_uuid;
+  bool conflicted;
+  bool conflicted2;
+  bool transaction_duplicate;
+  bool transaction_duplicate2;
+  bool need_update = false;
+  bool need_update2 = false;
+  struct GNUNET_TIME_Timestamp reserve_expiration
+    = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
+  bool conflicts[reserves_length];
+  bool conflicts2[reserves_length];
+  char *notify_s[reserves_length];
+
+  if (GNUNET_OK !=
+      TEH_PG_preflight (pg))
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  PREPARE (pg,
+           "reserve_create",
+           "SELECT "
+           "out_reserve_found AS conflicted"
+           ",out_reserve_found2 AS conflicted2"
+           ",transaction_duplicate"
+           ",transaction_duplicate2"
+           ",ruuid AS reserve_uuid"
+           " FROM batch2_reserves_insert"
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);");
+  expiry = GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
+                              pg->idle_reserve_expiration_time));
+  gc = GNUNET_TIME_absolute_to_timestamp (
+    GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                              pg->legal_reserve_expiration_time));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Creating reserve %s with expiration in %s\n",
+              TALER_B2S (&(reserves->reserve_pub)),
+              GNUNET_STRINGS_relative_time_to_string (
+                pg->idle_reserve_expiration_time,
+                GNUNET_NO));
+
+  {
+    if (GNUNET_OK !=
+        TEH_PG_start_read_committed(pg,
+                                   "READ_COMMITED"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
+  /* Optimistically assume this is a new reserve, create balance for the first
+     time; we do this before adding the actual transaction to "reserves_in",
+     as for a new reserve it can't be a duplicate 'add' operation, and as
+     the 'add' operation needs the reserve entry as a foreign key. */
+  for (unsigned int i=0;i<reserves_length;i++)
+  {
+    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+    notify_s[i] = compute_notify_on_reserve (&reserve->reserve_pub);
+  }
+
+  for (unsigned int i=0;i<reserves_length;i++)
+  {
+    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
+      TALER_PQ_query_param_amount (&reserve->balance),
+      GNUNET_PQ_query_param_string (reserve->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+      GNUNET_PQ_query_param_string (notify_s[i]),
+      GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
+      GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
+      TALER_PQ_query_param_amount (&reserve->balance),
+      GNUNET_PQ_query_param_string (reserve->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+      GNUNET_PQ_query_param_end
+    };
+
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_bool ("conflicted",
+                                  &conflicted),
+            GNUNET_PQ_result_spec_bool ("conflicted2",
+                                  &conflicted2),
+      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                  &transaction_duplicate),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                    &reserve_uuid),
+      GNUNET_PQ_result_spec_end
+    };
+
+    TALER_payto_hash (reserve->sender_account_details,
+                      &h_payto);
+
+    /* Note: query uses 'on conflict do nothing' */
+    qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                    "reserve_create",
+                                                    params,
+                                                    rs);
+
+    if (qs1 < 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to create reserves (%d)\n",
+                  qs1);
+      return qs1;
+    }
+   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
+   results[i] = (transaction_duplicate)
+      ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+   conflicts[i] = conflicted;
+   conflicts2[i] = conflicted2;
+   //  fprintf(stdout, "%d", conflicts[i]);
+   if (!conflicts[i] && !conflicts2[i]&& transaction_duplicate)
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+   need_update |= conflicted |= conflicted2;
+  }
+  // commit
+  {
+    enum GNUNET_DB_QueryStatus cs;
+
+    cs = TEH_PG_commit (pg);
+    if (cs < 0)
+      return cs;
+  }
+
+  if (!need_update)
+    goto exit;
+  // begin serializable
+  {
+    if (GNUNET_OK !=
+        TEH_PG_start(pg,
+                     "reserve-insert-continued"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
+
+  enum GNUNET_DB_QueryStatus qs2;
+  PREPARE (pg,
+           "reserves_in_add_transaction",
+           "SELECT batch_reserves_update"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
+  for (unsigned int i=0;i<reserves_length;i++)
+  {
+    if (! conflicts[i])
+      continue;
+    {
+      const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
+        GNUNET_PQ_query_param_timestamp (&expiry),
+        GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
+        TALER_PQ_query_param_amount (&reserve->balance),
+        GNUNET_PQ_query_param_string (reserve->exchange_account_name),
+        GNUNET_PQ_query_param_bool (conflicted),
+        GNUNET_PQ_query_param_auto_from_type (&h_payto),
+        GNUNET_PQ_query_param_string (notify_s[i]),
+        GNUNET_PQ_query_param_end
+      };
+
+      qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                                "reserves_in_add_transaction",
+                                                params);
+      if (qs2<0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to update reserves (%d)\n",
+                    qs2);
+        return qs2;
+      }
+    }
+  }
+  {
+    enum GNUNET_DB_QueryStatus cs;
+
+    cs = TEH_PG_commit (pg);
+    if (cs < 0)
+      return cs;
+  }
+
+ exit:
+  for (unsigned int i=0;i<reserves_length;i++)
+    GNUNET_free (notify_s[i]);
+
+  return reserves_length;
+}
diff --git a/src/exchangedb/pg_batch_reserves_in_insert.h 
b/src/exchangedb/pg_batch4_reserves_in_insert.h
similarity index 62%
copy from src/exchangedb/pg_batch_reserves_in_insert.h
copy to src/exchangedb/pg_batch4_reserves_in_insert.h
index 76679567..3b3a629f 100644
--- a/src/exchangedb/pg_batch_reserves_in_insert.h
+++ b/src/exchangedb/pg_batch4_reserves_in_insert.h
@@ -14,22 +14,21 @@
    TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 /**
- * @file exchangedb/pg_batch_reserves_in_insert.h
- * @brief implementation of the batch_reserves_in_insert function for Postgres
- * @author Christian Grothoff
+ * @file exchangedb/pg_batch4_reserves_in_insert.h
+ * @brief implementation of the batch4_reserves_in_insert function for Postgres
+ * @author XU Joseph
  */
-#ifndef PG_BATCH_RESERVES_IN_INSERT_H
-#define PG_BATCH_RESERVES_IN_INSERT_H
+#ifndef PG_BATCH4_RESERVES_IN_INSERT_H
+#define PG_BATCH4_RESERVES_IN_INSERT_H
 
 #include "taler_util.h"
 #include "taler_json_lib.h"
 #include "taler_exchangedb_plugin.h"
 
-
 enum GNUNET_DB_QueryStatus
-TEH_PG_batch_reserves_in_insert (void *cls,
-                              const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
-                              unsigned int reserves_length,
-                                 enum GNUNET_DB_QueryStatus *results);
+TEH_PG_batch4_reserves_in_insert (void *cls,
+                                 const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
+                                 unsigned int reserves_length,
+                                  enum GNUNET_DB_QueryStatus *results);
 
 #endif
diff --git a/src/exchangedb/pg_batch_reserves_in_insert.c 
b/src/exchangedb/pg_batch_reserves_in_insert.c
index 455f080d..8a14022e 100644
--- a/src/exchangedb/pg_batch_reserves_in_insert.c
+++ b/src/exchangedb/pg_batch_reserves_in_insert.c
@@ -16,7 +16,7 @@
 /**
  * @file exchangedb/pg_batch_reserves_in_insert.c
  * @brief Implementation of the reserves_in_insert function for Postgres
- * @author JOSEPHxu
+ * @author Joseph Xu
  */
 #include "platform.h"
 #include "taler_error_codes.h"
@@ -32,18 +32,16 @@
 #include "pg_reserves_update.h"
 #include "pg_setup_wire_target.h"
 #include "pg_event_notify.h"
+#include "pg_preflight.h"
 
 
 /**
- * Generate event notification for the reserve
- * change.
+ * Generate event notification for the reserve change.
  *
- * @param pg plugin state
  * @param reserve_pub reserve to notfiy on
  */
-static void
-notify_on_reserve (struct PostgresClosure *pg,
-                   const struct TALER_ReservePublicKeyP *reserve_pub)
+static char *
+compute_notify_on_reserve (const struct TALER_ReservePublicKeyP *reserve_pub)
 {
   struct TALER_ReserveEventP rep = {
     .header.size = htons (sizeof (rep)),
@@ -51,12 +49,7 @@ notify_on_reserve (struct PostgresClosure *pg,
     .reserve_pub = *reserve_pub
   };
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Notifying on reserve!\n");
-  TEH_PG_event_notify (pg,
-                       &rep.header,
-                       NULL,
-                       0);
+  return GNUNET_PG_get_event_notify_channel (&rep.header);
 }
 
 
@@ -75,17 +68,26 @@ TEH_PG_batch_reserves_in_insert (void *cls,
   uint64_t reserve_uuid;
   bool conflicted;
   bool transaction_duplicate;
+  bool need_update = false;
   struct GNUNET_TIME_Timestamp reserve_expiration
     = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
+  bool conflicts[reserves_length];
+  char *notify_s[reserves_length];
 
+  if (GNUNET_OK !=
+      TEH_PG_preflight (pg))
+  {
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
   PREPARE (pg,
            "reserve_create",
            "SELECT "
            "out_reserve_found AS conflicted"
            ",transaction_duplicate"
            ",ruuid AS reserve_uuid"
-           " FROM exchange_do_batch_reserves_in"
-           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);");
+           " FROM batch_reserves_insert"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
   expiry = GNUNET_TIME_absolute_to_timestamp (
     GNUNET_TIME_absolute_add (reserves->execution_time.abs_time,
                               pg->idle_reserve_expiration_time));
@@ -98,54 +100,152 @@ TEH_PG_batch_reserves_in_insert (void *cls,
               GNUNET_STRINGS_relative_time_to_string (
                 pg->idle_reserve_expiration_time,
                 GNUNET_NO));
+
+  {
+    if (GNUNET_OK !=
+        TEH_PG_start_read_committed(pg,
+                                   "READ_COMMITED"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
   /* Optimistically assume this is a new reserve, create balance for the first
      time; we do this before adding the actual transaction to "reserves_in",
      as for a new reserve it can't be a duplicate 'add' operation, and as
      the 'add' operation needs the reserve entry as a foreign key. */
   for (unsigned int i = 0; i<reserves_length; i++)
+  {
+    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+    notify_s[i] = compute_notify_on_reserve (&reserve->reserve_pub);
+  }
+
+  for (unsigned int i=0;i<reserves_length;i++)
   {
     const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
     struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub), /*$1*/
-      GNUNET_PQ_query_param_timestamp (&expiry),  /*$4*/
-      GNUNET_PQ_query_param_timestamp (&gc),  /*$5*/
-      GNUNET_PQ_query_param_uint64 (&reserve->wire_reference), /*6*/
-      TALER_PQ_query_param_amount (&reserve->balance), /*7+8*/
-      GNUNET_PQ_query_param_string (reserve->exchange_account_name), /*9*/
-      GNUNET_PQ_query_param_timestamp (&reserve->execution_time), /*10*/
-      GNUNET_PQ_query_param_auto_from_type (&h_payto), /*11*/
-      GNUNET_PQ_query_param_string (reserve->sender_account_details),/*12*/
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),/*13*/
+      GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
+      GNUNET_PQ_query_param_timestamp (&expiry),
+      GNUNET_PQ_query_param_timestamp (&gc),
+      GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
+      TALER_PQ_query_param_amount (&reserve->balance),
+      GNUNET_PQ_query_param_string (reserve->exchange_account_name),
+      GNUNET_PQ_query_param_timestamp (&reserve->execution_time),
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_string (reserve->sender_account_details),
+      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+      GNUNET_PQ_query_param_string (notify_s[i]),
       GNUNET_PQ_query_param_end
     };
-    /* We should get all our results into results[]*/
+
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &reserve_uuid),
       GNUNET_PQ_result_spec_bool ("conflicted",
                                   &conflicted),
       GNUNET_PQ_result_spec_bool ("transaction_duplicate",
                                   &transaction_duplicate),
+      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                    &reserve_uuid),
       GNUNET_PQ_result_spec_end
     };
 
     TALER_payto_hash (reserve->sender_account_details,
                       &h_payto);
+
     /* Note: query uses 'on conflict do nothing' */
     qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
                                                     "reserve_create",
                                                     params,
                                                     rs);
+
     if (qs1 < 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to create reserves (%d)\n",
+                  qs1);
       return qs1;
-    notify_on_reserve (pg,
-                       &reserve->reserve_pub);
-    GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
-    results[i] = (transaction_duplicate)
+    }
+   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
+   results[i] = (transaction_duplicate)
       ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
       : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-    if ( (! conflicted) && transaction_duplicate)
-      TEH_PG_rollback (pg);
+   conflicts[i] = conflicted;
+   //  fprintf(stdout, "%d", conflicts[i]);
+   if (!conflicts[i] && transaction_duplicate)
+   {
+     GNUNET_break (0);
+     TEH_PG_rollback (pg);
+     return GNUNET_DB_STATUS_HARD_ERROR;
+   }
+   need_update |= conflicted;
   }
+  // commit
+  {
+    enum GNUNET_DB_QueryStatus cs;
+
+    cs = TEH_PG_commit (pg);
+    if (cs < 0)
+      return cs;
+  }
+
+  if (!need_update)
+    goto exit;
+  // begin serializable
+  {
+    if (GNUNET_OK !=
+        TEH_PG_start(pg,
+                     "reserve-insert-continued"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+  }
+
+  enum GNUNET_DB_QueryStatus qs2;
+  PREPARE (pg,
+           "reserves_in_add_transaction",
+           "SELECT batch_reserves_update"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9);");
+  for (unsigned int i=0;i<reserves_length;i++)
+  {
+    if (! conflicts[i])
+      continue;
+    {
+      const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (&reserve->reserve_pub),
+        GNUNET_PQ_query_param_timestamp (&expiry),
+        GNUNET_PQ_query_param_uint64 (&reserve->wire_reference),
+        TALER_PQ_query_param_amount (&reserve->balance),
+        GNUNET_PQ_query_param_string (reserve->exchange_account_name),
+        GNUNET_PQ_query_param_bool (conflicted),
+        GNUNET_PQ_query_param_auto_from_type (&h_payto),
+        GNUNET_PQ_query_param_string (notify_s[i]),
+        GNUNET_PQ_query_param_end
+      };
+
+      qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                                "reserves_in_add_transaction",
+                                                params);
+      if (qs2<0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to update reserves (%d)\n",
+                    qs2);
+        return qs2;
+      }
+    }
+  }
+  {
+    enum GNUNET_DB_QueryStatus cs;
+
+    cs = TEH_PG_commit (pg);
+    if (cs < 0)
+      return cs;
+  }
+
+ exit:
+  for (unsigned int i=0;i<reserves_length;i++)
+    GNUNET_free (notify_s[i]);
+
   return reserves_length;
 }
diff --git a/src/exchangedb/pg_get_link_data.c 
b/src/exchangedb/pg_get_link_data.c
index 93086289..f15bf35a 100644
--- a/src/exchangedb/pg_get_link_data.c
+++ b/src/exchangedb/pg_get_link_data.c
@@ -178,25 +178,55 @@ TEH_PG_get_link_data (void *cls,
   enum GNUNET_DB_QueryStatus qs;
   struct LinkDataContext ldctx;
 
-  PREPARE (pg,
-           "get_link",
-           "SELECT "
-           " tp.transfer_pub"
-           ",denoms.denom_pub"
-           ",rrc.ev_sig"
-           ",rrc.ewv"
-           ",rrc.link_sig"
-           ",rrc.freshcoin_index"
-           ",rrc.coin_ev"
-           " FROM refresh_commitments"
-           "     JOIN refresh_revealed_coins rrc"
-           "       USING (melt_serial_id)"
-           "     JOIN refresh_transfer_keys tp"
-           "       USING (melt_serial_id)"
-           "     JOIN denominations denoms"
-           "       ON (rrc.denominations_serial = denoms.denominations_serial)"
-           " WHERE old_coin_pub=$1"
-           " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
+  if (NULL == getenv ("NEW_LOGIC"))
+  {
+    PREPARE (pg,
+             "get_link",
+             "SELECT "
+             " tp.transfer_pub"
+             ",denoms.denom_pub"
+             ",rrc.ev_sig"
+             ",rrc.ewv"
+             ",rrc.link_sig"
+             ",rrc.freshcoin_index"
+             ",rrc.coin_ev"
+             " FROM refresh_commitments"
+             "     JOIN refresh_revealed_coins rrc"
+             "       USING (melt_serial_id)"
+             "     JOIN refresh_transfer_keys tp"
+             "       USING (melt_serial_id)"
+             "     JOIN denominations denoms"
+             "       ON (rrc.denominations_serial = 
denoms.denominations_serial)"
+             " WHERE old_coin_pub=$1"
+             " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
+  }
+
+  else
+  {
+    PREPARE (pg,
+             "get_link",
+             "WITH rc AS MATERIALIZED ("
+             "SELECT"
+             "* FROM refresh_commitments"
+             "WHERE old_coin_pub=$1"
+             ")"
+             "SELECT "
+             " tp.transfer_pub"
+             ",denoms.denom_pub"
+             ",rrc.ev_sig"
+             ",rrc.ewv"
+             ",rrc.link_sig"
+             ",rrc.freshcoin_index"
+             ",rrc.coin_ev"
+             " FROM refresh_revealed_coins rrc"
+             "       USING (melt_serial_id)"
+             "     JOIN refresh_transfer_keys tp"
+             "       USING (melt_serial_id)"
+             "     JOIN denominations denoms"
+             "       USING (denominations_serial)"
+             " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
+  }
+
   ldctx.ldc = ldc;
   ldctx.ldc_cls = ldc_cls;
   ldctx.last = NULL;
diff --git a/src/exchangedb/pg_get_policy_details.c 
b/src/exchangedb/pg_get_policy_details.c
index 5dacb600..fafdca53 100644
--- a/src/exchangedb/pg_get_policy_details.c
+++ b/src/exchangedb/pg_get_policy_details.c
@@ -57,7 +57,7 @@ TEH_PG_get_policy_details (
   };
 
 
-  
+
   return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
                                                    "get_policy_details",
                                                    params,
diff --git a/src/exchangedb/pg_select_refunds_by_coin.c 
b/src/exchangedb/pg_select_refunds_by_coin.c
index 6510ae4a..84b63a71 100644
--- a/src/exchangedb/pg_select_refunds_by_coin.c
+++ b/src/exchangedb/pg_select_refunds_by_coin.c
@@ -138,15 +138,19 @@ TEH_PG_select_refunds_by_coin (
     // FIXME-Joseph
     PREPARE (pg,
              "get_refunds_by_coin_and_contract",
+             "WITH rc AS MATERIALIZED("
              "SELECT"
-             " ref.amount_with_fee_val"
-             ",ref.amount_with_fee_frac"
-             " FROM refunds ref"
-             " JOIN deposits dep"
-             "   USING (coin_pub,deposit_serial_id)"
-             " WHERE ref.coin_pub=$1"
-             "   AND dep.merchant_pub=$2"
-             "   AND dep.h_contract_terms=$3;");
+             " * FROM refunds ref"
+             "WHERE ref.coin_pub=$1"
+                "AND dep.merchant_pub=$2"
+                "AND dep.h_contract_terms=$3"
+             ")"
+             "SELECT"
+             "   ref.amount_with_fee_val"
+             "  ,ref.amount_with_fee_frac"
+             "FROM deposits dep"
+             "JOIN rc"
+             "   USING (coin_pub,deposit_serial_id)");
   }
   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
                                              
"get_refunds_by_coin_and_contract",
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index d04df467..c805810b 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -60,7 +60,7 @@
 #include <pthread.h>
 #include <libpq-fe.h>
 
-/**WHAT I ADD**/
+/**NEW INCLUDES**/
 #include "pg_insert_purse_request.h"
 #include "pg_iterate_active_signkeys.h"
 #include "pg_preflight.h"
@@ -205,6 +205,7 @@
 #include "pg_setup_wire_target.h"
 #include "pg_compute_shard.h"
 #include "pg_batch_reserves_in_insert.h"
+#include "pg_batch2_reserves_in_insert.h"
 /**
  * Set to 1 to enable Postgres auto_explain module. This will
  * slow down things a _lot_, but also provide extensive logging
@@ -373,4484 +374,6 @@ TEH_PG_internal_setup (struct PostgresClosure *pg,
 }
 
 
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Set to #GNUNET_SYSERR on error.
-   */
-  int status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct SelectRefundContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-get_refunds_cb (void *cls,
-                PGresult *result,
-                unsigned int num_results)
-{
-  struct SelectRefundContext *srctx = cls;
-  struct PostgresClosure *pg = srctx->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_Amount amount_with_fee;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &amount_with_fee),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      srctx->status = GNUNET_SYSERR;
-      return;
-    }
-    if (GNUNET_OK !=
-        srctx->cb (srctx->cb_cls,
-                   &amount_with_fee))
-      return;
-  }
-}
-
-
-/* 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
- * */
-static enum GNUNET_DB_QueryStatus
-postgres_get_policy_details (
-  void *cls,
-  const struct GNUNET_HashCode *hc,
-  struct TALER_PolicyDetails *details)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (hc),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_timestamp ("deadline",
-                                     &details->deadline),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("commitment",
-                                 &details->commitment),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
-                                 &details->accumulated_total),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee",
-                                 &details->policy_fee),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount",
-                                 &details->transferable_amount),
-    GNUNET_PQ_result_spec_auto_from_type ("state",
-                                          &details->fulfillment_state),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id",
-                                    &details->policy_fulfillment_id),
-      &details->no_policy_fulfillment_id),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_policy_details",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Perform melt operation, checking for sufficient balance
- * of the coin and possibly persisting the melt details.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param rms client-contributed input for CS denominations that must be 
checked for idempotency, or NULL for non-CS withdrawals
- * @param[in,out] refresh refresh operation details; the noreveal_index
- *                is set in case the coin was already melted before
- * @param known_coin_id row of the coin in the known_coins table
- * @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] balance_ok set to true if the balance was sufficient
- * @return query execution status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_do_melt (
-  void *cls,
-  const struct TALER_RefreshMasterSecretP *rms,
-  struct TALER_EXCHANGEDB_Refresh *refresh,
-  uint64_t known_coin_id,
-  bool *zombie_required,
-  bool *balance_ok)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    NULL == rms
-    ? GNUNET_PQ_query_param_null ()
-    : GNUNET_PQ_query_param_auto_from_type (rms),
-    TALER_PQ_query_param_amount (&refresh->amount_with_fee),
-    GNUNET_PQ_query_param_auto_from_type (&refresh->rc),
-    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_uint64 (&known_coin_id),
-    GNUNET_PQ_query_param_uint32 (&refresh->noreveal_index),
-    GNUNET_PQ_query_param_bool (*zombie_required),
-    GNUNET_PQ_query_param_end
-  };
-  bool is_null;
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_bool ("balance_ok",
-                                balance_ok),
-    GNUNET_PQ_result_spec_bool ("zombie_required",
-                                zombie_required),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_uint32 ("noreveal_index",
-                                    &refresh->noreveal_index),
-      &is_null),
-    GNUNET_PQ_result_spec_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "call_melt",
-                                                 params,
-                                                 rs);
-  if (is_null)
-    refresh->noreveal_index = UINT32_MAX; /* set to very invalid value */
-  return qs;
-}
-
-
-/**
- * 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 re-used
- * @return query execution status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_do_refund (
-  void *cls,
-  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)
-{
-  struct PostgresClosure *pg = cls;
-  uint64_t deposit_shard = TEH_PG_compute_shard 
(&refund->details.merchant_pub);
-  struct TALER_Amount amount_without_fee;
-  struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_amount (&refund->details.refund_amount),
-    TALER_PQ_query_param_amount (&amount_without_fee),
-    TALER_PQ_query_param_amount (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;
-  }
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "call_refund",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * 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 reserve_out_serial_id row in the reserves_out 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_do_recoup (
-  void *cls,
-  const struct TALER_ReservePublicKeyP *reserve_pub,
-  uint64_t reserve_out_serial_id,
-  const union TALER_DenominationBlindingKeyP *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 PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Timestamp reserve_gc
-    = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
-  struct GNUNET_TIME_Timestamp reserve_expiration
-    = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-    GNUNET_PQ_query_param_uint64 (&reserve_out_serial_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
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "call_recoup",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_do_recoup_refresh (
-  void *cls,
-  const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
-  uint64_t rrc_serial,
-  const union TALER_DenominationBlindingKeyP *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 PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (old_coin_pub),
-    GNUNET_PQ_query_param_uint64 (&rrc_serial),
-    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
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "call_recoup_refresh",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * 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);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_add_policy_fulfillment_proof (
-  void *cls,
-  struct TALER_PolicyFulfillmentTransactionData *fulfillment)
-{
-  enum GNUNET_DB_QueryStatus qs;
-  struct PostgresClosure *pg = cls;
-  size_t count = fulfillment->details_count;
-  struct GNUNET_HashCode hcs[count];
-
-  /* Create the sorted policy_hash_codes */
-  {
-    size_t idx[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),
-      GNUNET_PQ_query_param_fixed_size (hcs,
-                                        count * sizeof(struct 
GNUNET_HashCode)),
-      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
-    };
-
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"insert_proof_into_policy_fulfillments",
-                                                   params,
-                                                   rs);
-    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
-      return qs;
-  }
-
-  /* Now, set the states of each entry corresponding to the hash_codes in
-   * policy_details accordingly */
-  for (size_t i = 0; i < count; i++)
-  {
-    struct TALER_PolicyDetails *pos = &fulfillment->details[i];
-    {
-      struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_auto_from_type (&pos->hash_code),
-        GNUNET_PQ_query_param_timestamp (&pos->deadline),
-        TALER_PQ_query_param_amount (&pos->commitment),
-        TALER_PQ_query_param_amount (&pos->accumulated_total),
-        TALER_PQ_query_param_amount (&pos->policy_fee),
-        TALER_PQ_query_param_amount (&pos->transferable_amount),
-        GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state),
-        GNUNET_PQ_query_param_end
-      };
-
-      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                               "update_policy_details",
-                                               params);
-      if (qs < 0)
-        return qs;
-    }
-  }
-
-  return qs;
-}
-
-
-/**
- * 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
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_reserve_balance (void *cls,
-                              const struct TALER_ReservePublicKeyP 
*reserve_pub,
-                              struct TALER_Amount *balance)
-{
-  struct PostgresClosure *pg = cls;
-  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",
-                                 balance),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_reserve_balance",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_have_deposit2 (
-  void *cls,
-  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 PostgresClosure *pg = cls;
-  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),
-    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));
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "get_deposit",
-                                                 params,
-                                                 rs);
-  if (0 >= qs)
-    return qs;
-  TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account,
-                                      &deposit2.wire_salt,
-                                      &h_wire2);
-  GNUNET_free (deposit2.receiver_wire_account);
-  /* 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;
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_aggregate (
-  void *cls,
-  const struct TALER_PaytoHashP *h_payto,
-  const struct TALER_MerchantPublicKeyP *merchant_pub,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  struct TALER_Amount *total)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Absolute now = {0};
-  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_end
-  };
-  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;
-  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
-  };
-  enum GNUNET_DB_QueryStatus qs;
-  struct TALER_Amount sum_deposit;
-  struct TALER_Amount sum_refund;
-  struct TALER_Amount sum_fee;
-  struct TALER_Amount delta;
-
-  now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
-                                         pg->aggregator_shift);
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "aggregate",
-                                                 params,
-                                                 rs);
-  if (qs < 0)
-  {
-    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-    return qs;
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
-  {
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_set_zero (pg->currency,
-                                          total));
-    return qs;
-  }
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_set_zero (pg->currency,
-                                        &sum_deposit));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_set_zero (pg->currency,
-                                        &sum_refund));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_set_zero (pg->currency,
-                                        &sum_fee));
-  sum_deposit.value    = sum_deposit_frac / TALER_AMOUNT_FRAC_BASE
-                         + sum_deposit_value;
-  sum_deposit.fraction = sum_deposit_frac % TALER_AMOUNT_FRAC_BASE;
-  sum_refund.value     = sum_refund_frac  / TALER_AMOUNT_FRAC_BASE
-                         + sum_refund_value;
-  sum_refund.fraction  = sum_refund_frac  % TALER_AMOUNT_FRAC_BASE;
-  sum_fee.value        = sum_fee_frac     / TALER_AMOUNT_FRAC_BASE
-                         + sum_fee_value;
-  sum_fee.fraction     = sum_fee_frac     % TALER_AMOUNT_FRAC_BASE; \
-  GNUNET_assert (0 <=
-                 TALER_amount_subtract (&delta,
-                                        &sum_deposit,
-                                        &sum_refund));
-  GNUNET_assert (0 <=
-                 TALER_amount_subtract (total,
-                                        &delta,
-                                        &sum_fee));
-  return qs;
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_create_aggregation_transient (
-  void *cls,
-  const struct TALER_PaytoHashP *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 PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_amount (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
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "create_aggregation_transient",
-                                             params);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_aggregation_transient (
-  void *cls,
-  const struct TALER_PaytoHashP *h_payto,
-  const struct TALER_MerchantPublicKeyP *merchant_pub,
-  const char *exchange_account_section,
-  struct TALER_WireTransferIdentifierRawP *wtid,
-  struct TALER_Amount *total)
-{
-  struct PostgresClosure *pg = cls;
-  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
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"select_aggregation_transient",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * Closure for #get_refunds_cb().
- */
-struct FindAggregationTransientContext
-{
-  /**
-   * Function to call on each result.
-   */
-  TALER_EXCHANGEDB_TransientAggregationCallback cb;
-
-  /**
-   * Closure for @a cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Set to #GNUNET_SYSERR on error.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct SelectRefundContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-get_transients_cb (void *cls,
-                   PGresult *result,
-                   unsigned int num_results)
-{
-  struct FindAggregationTransientContext *srctx = cls;
-  struct PostgresClosure *pg = srctx->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_Amount amount;
-    char *payto_uri;
-    struct TALER_WireTransferIdentifierRawP wtid;
-    struct TALER_MerchantPublicKeyP merchant_pub;
-    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),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
-                                   &amount),
-      GNUNET_PQ_result_spec_end
-    };
-    bool cont;
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      srctx->status = GNUNET_SYSERR;
-      return;
-    }
-    cont = srctx->cb (srctx->cb_cls,
-                      payto_uri,
-                      &wtid,
-                      &merchant_pub,
-                      &amount);
-    GNUNET_free (payto_uri);
-    if (! cont)
-      break;
-  }
-}
-
-
-/**
- * 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 cb function to call on each matching entry
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_find_aggregation_transient (
-  void *cls,
-  const struct TALER_PaytoHashP *h_payto,
-  TALER_EXCHANGEDB_TransientAggregationCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_payto),
-    GNUNET_PQ_query_param_end
-  };
-  struct FindAggregationTransientContext srctx = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "find_transient_aggregations",
-                                             params,
-                                             &get_transients_cb,
-                                             &srctx);
-  if (GNUNET_SYSERR == srctx.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_update_aggregation_transient (
-  void *cls,
-  const struct TALER_PaytoHashP *h_payto,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  uint64_t kyc_requirement_row,
-  const struct TALER_Amount *total)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    TALER_PQ_query_param_amount (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
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "update_aggregation_transient",
-                                             params);
-}
-
-
-/**
- * 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
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_ready_deposit (void *cls,
-                            uint64_t start_shard_row,
-                            uint64_t end_shard_row,
-                            struct TALER_MerchantPublicKeyP *merchant_pub,
-                            char **payto_uri)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Absolute now = {0};
-  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),
-    GNUNET_PQ_result_spec_end
-  };
-
-  now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
-                                         pg->aggregator_shift);
-  GNUNET_assert (start_shard_row < end_shard_row);
-  GNUNET_assert (end_shard_row <= INT32_MAX);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Finding ready deposits by deadline %s (%llu)\n",
-              GNUNET_TIME_absolute2s (now),
-              (unsigned long long) now.abs_value_us);
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "deposits_get_ready",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_known_coin (void *cls,
-                         const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                         struct TALER_CoinPublicInfo *coin_info)
-{
-  struct PostgresClosure *pg = cls;
-  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;
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_known_coin",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_coin_denomination (
-  void *cls,
-  const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  uint64_t *known_coin_id,
-  struct TALER_DenominationHashP *denom_hash)
-{
-  struct PostgresClosure *pg = cls;
-  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));
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_coin_denomination",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * 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`
- */
-static long long
-postgres_count_known_coins (void *cls,
-                            const struct
-                            TALER_DenominationHashP *denom_pub_hash)
-{
-  struct PostgresClosure *pg = cls;
-  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;
-
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "count_known_coins",
-                                                 params,
-                                                 rs);
-  if (0 > qs)
-    return (long long) qs;
-  return (long long) count;
-}
-
-
-/**
- * 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
- */
-static enum TALER_EXCHANGEDB_CoinKnownStatus
-postgres_ensure_coin_known (void *cls,
-                            const struct TALER_CoinPublicInfo *coin,
-                            uint64_t *known_coin_id,
-                            struct TALER_DenominationHashP *denom_hash,
-                            struct TALER_AgeCommitmentHash *h_age_commitment)
-{
-  struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs;
-  bool existed;
-  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->coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (&coin->denom_pub_hash),
-    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),
-      &is_denom_pub_hash_null),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                            h_age_commitment),
-      &is_age_hash_null),
-    GNUNET_PQ_result_spec_end
-  };
-
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "insert_known_coin",
-                                                 params,
-                                                 rs);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    GNUNET_break (0);
-    return TALER_EXCHANGEDB_CKS_HARD_FAIL;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    GNUNET_break (0); /* should be impossible */
-    return TALER_EXCHANGEDB_CKS_HARD_FAIL;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    if (! existed)
-      return TALER_EXCHANGEDB_CKS_ADDED;
-    break; /* continued below */
-  }
-
-  if ( (! is_denom_pub_hash_null) &&
-       (0 != GNUNET_memcmp (&denom_hash->hash,
-                            &coin->denom_pub_hash.hash)) )
-  {
-    GNUNET_break_op (0);
-    return TALER_EXCHANGEDB_CKS_DENOM_CONFLICT;
-  }
-
-  if ( (! is_age_hash_null) &&
-       (0 != GNUNET_memcmp (h_age_commitment,
-                            &coin->h_age_commitment)) )
-  {
-    GNUNET_break (GNUNET_is_zero (h_age_commitment));
-    GNUNET_break_op (0);
-    return TALER_EXCHANGEDB_CKS_AGE_CONFLICT;
-  }
-
-  return TALER_EXCHANGEDB_CKS_PRESENT;
-}
-
-
-enum GNUNET_DB_QueryStatus
-setup_wire_target (
-  struct PostgresClosure *pg,
-  const char *payto_uri,
-  struct TALER_PaytoHashP *h_payto)
-{
-  struct GNUNET_PQ_QueryParam iparams[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_payto),
-    GNUNET_PQ_query_param_string (payto_uri),
-    GNUNET_PQ_query_param_end
-  };
-
-  TALER_payto_hash (payto_uri,
-                    h_payto);
-
-  PREPARE (pg,
-           "insert_kyc_status",
-           "INSERT INTO wire_targets"
-           "  (wire_target_h_payto"
-           "  ,payto_uri"
-           "  ) VALUES "
-           "  ($1, $2)"
-           " ON CONFLICT DO NOTHING");
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_kyc_status",
-                                             iparams);
-}
-
-
-/**
- * Insert information about deposited coin into the database.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param exchange_timestamp time the exchange received the deposit request
- * @param deposit deposit information to store
- * @return query result status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_deposit (void *cls,
-                         struct GNUNET_TIME_Timestamp exchange_timestamp,
-                         const struct TALER_EXCHANGEDB_Deposit *deposit)
-{
-  struct PostgresClosure *pg = cls;
-  struct TALER_PaytoHashP h_payto;
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = setup_wire_target (pg,
-                          deposit->receiver_wire_account,
-                          &h_payto);
-  if (qs < 0)
-    return qs;
-  if (GNUNET_TIME_timestamp_cmp (deposit->wire_deadline,
-                                 <,
-                                 deposit->refund_deadline))
-  {
-    GNUNET_break (0);
-  }
-  {
-    uint64_t shard = TEH_PG_compute_shard (&deposit->merchant_pub);
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
-      TALER_PQ_query_param_amount (&deposit->amount_with_fee),
-      GNUNET_PQ_query_param_timestamp (&deposit->timestamp),
-      GNUNET_PQ_query_param_timestamp (&deposit->refund_deadline),
-      GNUNET_PQ_query_param_timestamp (&deposit->wire_deadline),
-      GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
-      GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms),
-      GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
-      GNUNET_PQ_query_param_timestamp (&exchange_timestamp),
-      GNUNET_PQ_query_param_uint64 (&shard),
-      GNUNET_PQ_query_param_end
-    };
-
-    GNUNET_assert (shard <= INT32_MAX);
-    GNUNET_log (
-      GNUNET_ERROR_TYPE_INFO,
-      "Inserting deposit to be executed at %s (%llu/%llu)\n",
-      GNUNET_TIME_timestamp2s (deposit->wire_deadline),
-      (unsigned long long) deposit->wire_deadline.abs_time.abs_value_us,
-      (unsigned long long) deposit->refund_deadline.abs_time.abs_value_us);
-    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                               "insert_deposit",
-                                               params);
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_refund (void *cls,
-                        const struct TALER_EXCHANGEDB_Refund *refund)
-{
-  struct PostgresClosure *pg = cls;
-  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 (&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));
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_refund",
-                                             params);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_refunds_by_coin (
-  void *cls,
-  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)
-{
-  struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_contract),
-    GNUNET_PQ_query_param_end
-  };
-  struct SelectRefundContext srctx = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"get_refunds_by_coin_and_contract",
-                                             params,
-                                             &get_refunds_cb,
-                                             &srctx);
-  if (GNUNET_SYSERR == srctx.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Lookup refresh melt 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] melt where to store the result; note that
- *             melt->session.coin.denom_sig will be set to NULL
- *             and is not fetched by this routine (as it is not needed by the 
client)
- * @param[out] melt_serial_id set to the row ID of @a rc in the 
refresh_commitments table
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_melt (void *cls,
-                   const struct TALER_RefreshCommitmentP *rc,
-                   struct TALER_EXCHANGEDB_Melt *melt,
-                   uint64_t *melt_serial_id)
-{
-  struct PostgresClosure *pg = cls;
-  bool h_age_commitment_is_null;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (rc),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                          &melt->session.coin.
-                                          denom_pub_hash),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
-                                 &melt->melt_fee),
-    GNUNET_PQ_result_spec_uint32 ("noreveal_index",
-                                  &melt->session.noreveal_index),
-    GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
-                                          &melt->session.coin.coin_pub),
-    GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
-                                          &melt->session.coin_sig),
-    GNUNET_PQ_result_spec_allow_null (
-      GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                            
&melt->session.coin.h_age_commitment),
-      &h_age_commitment_is_null),
-    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                 &melt->session.amount_with_fee),
-    GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
-                                  melt_serial_id),
-    GNUNET_PQ_result_spec_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  memset (&melt->session.coin.denom_sig,
-          0,
-          sizeof (melt->session.coin.denom_sig));
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "get_melt",
-                                                 params,
-                                                 rs);
-  if (h_age_commitment_is_null)
-    memset (&melt->session.coin.h_age_commitment,
-            0,
-            sizeof(melt->session.coin.h_age_commitment));
-
-  melt->session.rc = *rc;
-  return qs;
-}
-
-
-/**
- * Store in the database which coin(s) the wallet wanted to create
- * in a given refresh operation and all of the other information
- * we learned or created in the /refresh/reveal step.
- *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param melt_serial_id row ID of the commitment / melt operation in 
refresh_commitments
- * @param num_rrcs number of coins to generate, size of the @a rrcs array
- * @param rrcs information about the new coins
- * @param num_tprivs number of entries in @a tprivs, should be 
#TALER_CNC_KAPPA - 1
- * @param tprivs transfer private keys to store
- * @param tp public key to store
- * @return query status for the transaction
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_refresh_reveal (
-  void *cls,
-  uint64_t melt_serial_id,
-  uint32_t num_rrcs,
-  const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs,
-  unsigned int num_tprivs,
-  const struct TALER_TransferPrivateKeyP *tprivs,
-  const struct TALER_TransferPublicKeyP *tp)
-{
-  struct PostgresClosure *pg = cls;
-
-  if (TALER_CNC_KAPPA != num_tprivs + 1)
-  {
-    GNUNET_break (0);
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
-  for (uint32_t i = 0; i<num_rrcs; i++)
-  {
-    const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_uint64 (&melt_serial_id),
-      GNUNET_PQ_query_param_uint32 (&i),
-      GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig),
-      GNUNET_PQ_query_param_auto_from_type (&rrc->h_denom_pub),
-      TALER_PQ_query_param_blinded_planchet (&rrc->blinded_planchet),
-      TALER_PQ_query_param_exchange_withdraw_values (&rrc->exchange_vals),
-      GNUNET_PQ_query_param_auto_from_type (&rrc->coin_envelope_hash),
-      TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig),
-      GNUNET_PQ_query_param_end
-    };
-    enum GNUNET_DB_QueryStatus qs;
-
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_refresh_revealed_coin",
-                                             params);
-    if (0 > qs)
-      return qs;
-  }
-
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_uint64 (&melt_serial_id),
-      GNUNET_PQ_query_param_auto_from_type (tp),
-      GNUNET_PQ_query_param_fixed_size (
-        tprivs,
-        num_tprivs * sizeof (struct TALER_TransferPrivateKeyP)),
-      GNUNET_PQ_query_param_end
-    };
-
-    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                               "insert_refresh_transfer_keys",
-                                               params);
-  }
-}
-
-
-/**
- * Context where we aggregate data from the database.
- * Closure for #add_revealed_coins().
- */
-struct GetRevealContext
-{
-  /**
-   * Array of revealed coins we obtained from the DB.
-   */
-  struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs;
-
-  /**
-   * Length of the @a rrcs array.
-   */
-  unsigned int rrcs_len;
-
-  /**
-   * Set to an error code if we ran into trouble.
-   */
-  enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct GetRevealContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-add_revealed_coins (void *cls,
-                    PGresult *result,
-                    unsigned int num_results)
-{
-  struct GetRevealContext *grctx = cls;
-
-  if (0 == num_results)
-    return;
-  grctx->rrcs = GNUNET_new_array (num_results,
-                                  struct TALER_EXCHANGEDB_RefreshRevealedCoin);
-  grctx->rrcs_len = num_results;
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    uint32_t off;
-    struct GNUNET_PQ_ResultSpec rso[] = {
-      GNUNET_PQ_result_spec_uint32 ("freshcoin_index",
-                                    &off),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rso,
-                                  i))
-    {
-      GNUNET_break (0);
-      grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
-      return;
-    }
-    if (off >= num_results)
-    {
-      GNUNET_break (0);
-      grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
-      return;
-    }
-    {
-      struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx->rrcs[off];
-      struct GNUNET_PQ_ResultSpec rsi[] = {
-        /* NOTE: freshcoin_index selected and discarded here... */
-        GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                              &rrc->h_denom_pub),
-        GNUNET_PQ_result_spec_auto_from_type ("link_sig",
-                                              &rrc->orig_coin_link_sig),
-        GNUNET_PQ_result_spec_auto_from_type ("h_coin_ev",
-                                              &rrc->coin_envelope_hash),
-        TALER_PQ_result_spec_blinded_planchet ("coin_ev",
-                                               &rrc->blinded_planchet),
-        TALER_PQ_result_spec_exchange_withdraw_values ("ewv",
-                                                       &rrc->exchange_vals),
-        TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
-                                                &rrc->coin_sig),
-        GNUNET_PQ_result_spec_end
-      };
-
-      if (TALER_DENOMINATION_INVALID != rrc->blinded_planchet.cipher)
-      {
-        /* duplicate offset, not allowed */
-        GNUNET_break (0);
-        grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
-        return;
-      }
-      if (GNUNET_OK !=
-          GNUNET_PQ_extract_result (result,
-                                    rsi,
-                                    i))
-      {
-        GNUNET_break (0);
-        grctx->qs = GNUNET_DB_STATUS_HARD_ERROR;
-        return;
-      }
-    }
-  }
-}
-
-
-/**
- * Lookup in the database the coins that we want to
- * create in the given refresh operation.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param rc identify commitment and thus refresh operation
- * @param cb function to call with the results
- * @param cb_cls closure for @a cb
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_refresh_reveal (void *cls,
-                             const struct TALER_RefreshCommitmentP *rc,
-                             TALER_EXCHANGEDB_RefreshCallback cb,
-                             void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GetRevealContext grctx;
-  enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (rc),
-    GNUNET_PQ_query_param_end
-  };
-
-  memset (&grctx,
-          0,
-          sizeof (grctx));
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "get_refresh_revealed_coins",
-                                             params,
-                                             &add_revealed_coins,
-                                             &grctx);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    goto cleanup;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-  default: /* can have more than one result */
-    break;
-  }
-  switch (grctx.qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    goto cleanup;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: /* should be impossible */
-    break;
-  }
-
-  /* Pass result back to application */
-  cb (cb_cls,
-      grctx.rrcs_len,
-      grctx.rrcs);
-cleanup:
-  for (unsigned int i = 0; i < grctx.rrcs_len; i++)
-  {
-    struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i];
-
-    TALER_blinded_denom_sig_free (&rrc->coin_sig);
-    TALER_blinded_planchet_free (&rrc->blinded_planchet);
-  }
-  GNUNET_free (grctx.rrcs);
-  return qs;
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Set to #GNUNET_SYSERR on serious errors.
-   */
-  int status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.  Helper function
- * for #postgres_lookup_wire_transfer().
- *
- * @param cls closure of type `struct WireTransferResultContext *`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-handle_wt_result (void *cls,
-                  PGresult *result,
-                  unsigned int num_results)
-{
-  struct WireTransferResultContext *ctx = cls;
-  struct PostgresClosure *pg = ctx->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    uint64_t rowid;
-    struct TALER_PrivateContractHashP h_contract_terms;
-    struct TALER_CoinSpendPublicKeyP coin_pub;
-    struct TALER_PaytoHashP 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;
-    char *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),
-      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);
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_wire_transfer (
-  void *cls,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  TALER_EXCHANGEDB_AggregationDataCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (wtid),
-    GNUNET_PQ_query_param_end
-  };
-  struct WireTransferResultContext ctx;
-  enum GNUNET_DB_QueryStatus qs;
-
-  ctx.cb = cb;
-  ctx.cb_cls = cb_cls;
-  ctx.pg = pg;
-  ctx.status = GNUNET_OK;
-  /* check if the melt record exists and get it */
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "lookup_transactions",
-                                             params,
-                                             &handle_wt_result,
-                                             &ctx);
-  if (GNUNET_OK != ctx.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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)
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_lookup_transfer_by_deposit (
-  void *cls,
-  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)
-{
-  struct PostgresClosure *pg = 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 (h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_end
-  };
-  char *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),
-    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
-  };
-
-  memset (kyc,
-          0,
-          sizeof (*kyc));
-  /* check if the aggregation record exists and get it */
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "lookup_deposit_wtid",
-                                                 params,
-                                                 rs);
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
-  {
-    struct TALER_MerchantWireHashP wh;
-
-    TALER_merchant_wire_signature_hash (payto_uri,
-                                        &wire_salt,
-                                        &wh);
-    GNUNET_PQ_cleanup_result (rs);
-    if (0 ==
-        GNUNET_memcmp (&wh,
-                       h_wire))
-    {
-      *pending = false;
-      kyc->ok = true;
-      return qs;
-    }
-    qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-  }
-  if (0 > qs)
-    return qs;
-  *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),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_uint64 ("legitimization_requirement_serial_id",
-                                      &kyc->requirement_row),
-        NULL),
-      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_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_deposit_without_wtid",
-                                                   params,
-                                                   rs2);
-    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
-    {
-      struct TALER_MerchantWireHashP wh;
-
-      if (0 == kyc->requirement_row)
-        kyc->ok = true; /* technically: unknown */
-      TALER_merchant_wire_signature_hash (payto_uri,
-                                          &wire_salt,
-                                          &wh);
-      GNUNET_PQ_cleanup_result (rs);
-      if (0 !=
-          GNUNET_memcmp (&wh,
-                         h_wire))
-        return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-    }
-    return qs;
-  }
-}
-
-
-/**
- * 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] 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_wire_fee (void *cls,
-                       const char *type,
-                       struct GNUNET_TIME_Timestamp date,
-                       struct GNUNET_TIME_Timestamp *start_date,
-                       struct GNUNET_TIME_Timestamp *end_date,
-                       struct TALER_WireFeeSet *fees,
-                       struct TALER_MasterSignatureP *master_sig)
-{
-  struct PostgresClosure *pg = cls;
-  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_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
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_wire_fee",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_global_fee (void *cls,
-                         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 PostgresClosure *pg = cls;
-  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
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_global_fee",
-                                                   params,
-                                                   rs);
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Set to #GNUNET_SYSERR on error.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-global_fees_cb (void *cls,
-                PGresult *result,
-                unsigned int num_results)
-{
-  struct GlobalFeeContext *gctx = cls;
-  struct PostgresClosure *pg = gctx->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_GlobalFeeSet fees;
-    struct GNUNET_TIME_Relative purse_timeout;
-    struct GNUNET_TIME_Relative history_expiration;
-    uint32_t purse_account_limit;
-    struct GNUNET_TIME_Timestamp start_date;
-    struct GNUNET_TIME_Timestamp end_date;
-    struct TALER_MasterSignatureP master_sig;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_timestamp ("start_date",
-                                       &start_date),
-      GNUNET_PQ_result_spec_timestamp ("end_date",
-                                       &end_date),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
-                                   &fees.history),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("account_fee",
-                                   &fees.account),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee",
-                                   &fees.purse),
-      GNUNET_PQ_result_spec_relative_time ("purse_timeout",
-                                           &purse_timeout),
-      GNUNET_PQ_result_spec_relative_time ("history_expiration",
-                                           &history_expiration),
-      GNUNET_PQ_result_spec_uint32 ("purse_account_limit",
-                                    &purse_account_limit),
-      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                            &master_sig),
-      GNUNET_PQ_result_spec_end
-    };
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      gctx->status = GNUNET_SYSERR;
-      break;
-    }
-    gctx->cb (gctx->cb_cls,
-              &fees,
-              purse_timeout,
-              history_expiration,
-              purse_account_limit,
-              start_date,
-              end_date,
-              &master_sig);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_global_fees (void *cls,
-                          TALER_EXCHANGEDB_GlobalFeeCallback cb,
-                          void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Timestamp date
-    = GNUNET_TIME_absolute_to_timestamp (
-        GNUNET_TIME_absolute_subtract (
-          GNUNET_TIME_absolute_get (),
-          GNUNET_TIME_UNIT_YEARS));
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_timestamp (&date),
-    GNUNET_PQ_query_param_end
-  };
-  struct GlobalFeeContext gctx = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-
-  return GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                               "get_global_fees",
-                                               params,
-                                               &global_fees_cb,
-                                               &gctx);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_wire_fee (void *cls,
-                          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 PostgresClosure *pg = cls;
-  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 (&fees->wire),
-    TALER_PQ_query_param_amount (&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;
-
-  qs = postgres_get_wire_fee (pg,
-                              type,
-                              start_date,
-                              &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;
-  }
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_wire_fee",
-                                             params);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_global_fee (void *cls,
-                            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 PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_timestamp (&start_date),
-    GNUNET_PQ_query_param_timestamp (&end_date),
-    TALER_PQ_query_param_amount (&fees->history),
-    TALER_PQ_query_param_amount (&fees->account),
-    TALER_PQ_query_param_amount (&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 = postgres_get_global_fee (pg,
-                                start_date,
-                                &sd,
-                                &ed,
-                                &wx,
-                                &pt,
-                                &he,
-                                &pal,
-                                &sig);
-  if (qs < 0)
-    return qs;
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
-  {
-    if (0 != GNUNET_memcmp (&sig,
-                            master_sig))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if (0 !=
-        TALER_global_fee_set_cmp (fees,
-                                  &wx))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if ( (GNUNET_TIME_timestamp_cmp (sd,
-                                     !=,
-                                     start_date)) ||
-         (GNUNET_TIME_timestamp_cmp (ed,
-                                     !=,
-                                     end_date)) )
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if ( (GNUNET_TIME_relative_cmp (purse_timeout,
-                                    !=,
-                                    pt)) ||
-         (GNUNET_TIME_relative_cmp (history_expiration,
-                                    !=,
-                                    he)) )
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    if (purse_account_limit != pal)
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    /* equal record already exists */
-    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
-  }
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_global_fee",
-                                             params);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_insert_reserve_closed (
-  void *cls,
-  const struct TALER_ReservePublicKeyP *reserve_pub,
-  struct GNUNET_TIME_Timestamp execution_date,
-  const char *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 PostgresClosure *pg = cls;
-  struct TALER_EXCHANGEDB_Reserve reserve;
-  enum GNUNET_DB_QueryStatus qs;
-  struct TALER_PaytoHashP h_payto;
-
-  TALER_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 (amount_with_fee),
-      TALER_PQ_query_param_amount (closing_fee),
-      GNUNET_PQ_query_param_uint64 (&close_request_row),
-      GNUNET_PQ_query_param_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "reserves_close_insert",
-                                             params);
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
-    return qs;
-
-  /* update reserve balance */
-  reserve.pub = *reserve_pub;
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-      (qs = TEH_PG_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 TEH_PG_reserves_update (cls,
-                                 &reserve);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_wire_prepare_data_insert (void *cls,
-                                   const char *type,
-                                   const char *buf,
-                                   size_t buf_size)
-{
-  struct PostgresClosure *pg = cls;
-  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
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "wire_prepare_data_insert",
-                                             params);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_wire_prepare_data_mark_finished (
-  void *cls,
-  uint64_t rowid)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&rowid),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "wire_prepare_data_mark_done",
-                                             params);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_wire_prepare_data_mark_failed (
-  void *cls,
-  uint64_t rowid)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&rowid),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "wire_prepare_data_mark_failed",
-                                             params);
-}
-
-
-/**
- * Closure for #prewire_cb().
- */
-struct PrewireContext
-{
-  /**
-   * Function to call on each result.
-   */
-  TALER_EXCHANGEDB_WirePreparationIterator cb;
-
-  /**
-   * Closure for @a cb.
-   */
-  void *cb_cls;
-
-  /**
-   * #GNUNET_OK if everything went fine.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Invoke the callback for each result.
- *
- * @param cls a `struct MissingWireContext *`
- * @param result SQL result
- * @param num_results number of rows in @a result
- */
-static void
-prewire_cb (void *cls,
-            PGresult *result,
-            unsigned int num_results)
-{
-  struct PrewireContext *pc = cls;
-
-  for (unsigned int i = 0; i < num_results; i++)
-  {
-    uint64_t prewire_uuid;
-    char *wire_method;
-    void *buf = NULL;
-    size_t buf_size;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("prewire_uuid",
-                                    &prewire_uuid),
-      GNUNET_PQ_result_spec_string ("wire_method",
-                                    &wire_method),
-      GNUNET_PQ_result_spec_variable_size ("buf",
-                                           &buf,
-                                           &buf_size),
-      GNUNET_PQ_result_spec_end
-    };
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      pc->status = GNUNET_SYSERR;
-      return;
-    }
-    pc->cb (pc->cb_cls,
-            prewire_uuid,
-            wire_method,
-            buf,
-            buf_size);
-    GNUNET_PQ_cleanup_result (rs);
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_wire_prepare_data_get (void *cls,
-                                uint64_t start_row,
-                                uint64_t limit,
-                                TALER_EXCHANGEDB_WirePreparationIterator cb,
-                                void *cb_cls)
-{
-  struct PostgresClosure *pg = 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;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "wire_prepare_data_get",
-                                             params,
-                                             &prewire_cb,
-                                             &pc);
-  if (GNUNET_OK != pc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_GenericReturnValue
-postgres_start_deferred_wire_out (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  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 ==
-      TEH_PG_preflight (pg))
-    return GNUNET_SYSERR;
-  if (GNUNET_OK !=
-      GNUNET_PQ_exec_statements (pg->conn,
-                                 es))
-  {
-    TALER_LOG_ERROR (
-      "Failed to defer wire_out_ref constraint on transaction\n");
-    GNUNET_break (0);
-    TEH_PG_rollback (pg);
-    return GNUNET_SYSERR;
-  }
-  pg->transaction_name = "deferred wire out";
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Starting READ COMMITTED DEFERRED transaction `%s'\n",
-              pg->transaction_name);
-  return GNUNET_OK;
-}
-
-
-/**
- * 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
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_store_wire_transfer_out (
-  void *cls,
-  struct GNUNET_TIME_Timestamp date,
-  const struct TALER_WireTransferIdentifierRawP *wtid,
-  const struct TALER_PaytoHashP *h_payto,
-  const char *exchange_account_section,
-  const struct TALER_Amount *amount)
-{
-  struct PostgresClosure *pg = cls;
-  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 (amount),
-    GNUNET_PQ_query_param_end
-  };
-
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_wire_out",
-                                             params);
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_GenericReturnValue
-postgres_gc (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  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[] = {
-      /* Used in #postgres_gc() */
-      GNUNET_PQ_make_prepare ("run_gc",
-                              "CALL"
-                              " exchange_do_gc"
-                              " ($1,$2);"),
-      GNUNET_PQ_PREPARED_STATEMENT_END
-    };
-
-    conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
-                                       "exchangedb-postgres",
-                                       NULL,
-                                       es,
-                                       ps);
-  }
-  if (NULL == conn)
-    return GNUNET_SYSERR;
-  ret = GNUNET_OK;
-  if (0 > GNUNET_PQ_eval_prepared_non_select (conn,
-                                              "run_gc",
-                                              params))
-    ret = GNUNET_SYSERR;
-  GNUNET_PQ_disconnect (conn);
-  return ret;
-}
-
-
-/**
- * Closure for #deposit_serial_helper_cb().
- */
-struct DepositSerialContext
-{
-
-  /**
-   * Callback to call.
-   */
-  TALER_EXCHANGEDB_DepositCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct DepositSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-deposit_serial_helper_cb (void *cls,
-                          PGresult *result,
-                          unsigned int num_results)
-{
-  struct DepositSerialContext *dsc = cls;
-  struct PostgresClosure *pg = dsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_EXCHANGEDB_Deposit deposit;
-    struct GNUNET_TIME_Timestamp exchange_timestamp;
-    struct TALER_DenominationPublicKey denom_pub;
-    bool done;
-    uint64_t rowid;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &deposit.amount_with_fee),
-      GNUNET_PQ_result_spec_timestamp ("wallet_timestamp",
-                                       &deposit.timestamp),
-      GNUNET_PQ_result_spec_timestamp ("exchange_timestamp",
-                                       &exchange_timestamp),
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                            &deposit.merchant_pub),
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &deposit.coin.coin_pub),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash",
-                                              &deposit.coin.h_age_commitment),
-        &deposit.coin.no_age_commitment),
-      GNUNET_PQ_result_spec_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),
-      GNUNET_PQ_result_spec_bool ("done",
-                                  &done),
-      GNUNET_PQ_result_spec_uint64 ("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;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_deposits_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_DepositCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct DepositSerialContext dsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_deposits_incr",
-                                             params,
-                                             &deposit_serial_helper_cb,
-                                             &dsc);
-  if (GNUNET_OK != dsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Closure for #purse_deposit_serial_helper_cb().
- */
-struct HistoryRequestSerialContext
-{
-
-  /**
-   * Callback to call.
-   */
-  TALER_EXCHANGEDB_HistoryRequestCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct HistoryRequestSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-history_request_serial_helper_cb (void *cls,
-                                  PGresult *result,
-                                  unsigned int num_results)
-{
-  struct HistoryRequestSerialContext *dsc = cls;
-  struct PostgresClosure *pg = dsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    uint64_t rowid;
-    struct TALER_Amount history_fee;
-    struct GNUNET_TIME_Timestamp ts;
-    struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_ReserveSignatureP reserve_sig;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee",
-                                   &history_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_uint64 ("history_request_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_timestamp ("request_timestamp",
-                                       &ts),
-      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,
-                   &history_fee,
-                   ts,
-                   &reserve_pub,
-                   &reserve_sig);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
-}
-
-
-/**
- * Select history requests 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_history_requests_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_HistoryRequestCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct HistoryRequestSerialContext dsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_history_requests_incr",
-                                             params,
-                                             &history_request_serial_helper_cb,
-                                             &dsc);
-  if (GNUNET_OK != dsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseRefundSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-purse_decision_serial_helper_cb (void *cls,
-                                 PGresult *result,
-                                 unsigned int num_results)
-{
-  struct PurseDecisionSerialContext *dsc = cls;
-  struct PostgresClosure *pg = dsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_PurseContractPublicKeyP purse_pub;
-    struct TALER_ReservePublicKeyP reserve_pub;
-    bool no_reserve = true;
-    uint64_t rowid;
-    struct TALER_Amount val;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("purse_pub",
-                                            &purse_pub),
-      GNUNET_PQ_result_spec_allow_null (
-        GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                              &reserve_pub),
-        &no_reserve),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &val),
-      GNUNET_PQ_result_spec_uint64 ("purse_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,
-                   &purse_pub,
-                   no_reserve ? NULL : &reserve_pub,
-                   &val);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_purse_decisions_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  bool refunded,
-  TALER_EXCHANGEDB_PurseDecisionCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_bool (refunded),
-    GNUNET_PQ_query_param_end
-  };
-  struct PurseDecisionSerialContext dsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_purse_decisions_incr",
-                                             params,
-                                             &purse_decision_serial_helper_cb,
-                                             &dsc);
-  if (GNUNET_OK != dsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct PurseRefundCoinContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-purse_refund_coin_helper_cb (void *cls,
-                             PGresult *result,
-                             unsigned int num_results)
-{
-  struct PurseRefundCoinContext *dsc = cls;
-  struct PostgresClosure *pg = dsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_Amount amount_with_fee;
-    struct TALER_CoinSpendPublicKeyP coin_pub;
-    struct TALER_DenominationPublicKey denom_pub;
-    uint64_t rowid;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &amount_with_fee),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &coin_pub),
-      GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_end
-    };
-    enum GNUNET_GenericReturnValue ret;
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      dsc->status = GNUNET_SYSERR;
-      return;
-    }
-    ret = dsc->cb (dsc->cb_cls,
-                   rowid,
-                   &amount_with_fee,
-                   &coin_pub,
-                   &denom_pub);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_purse_deposits_by_purse (
-  void *cls,
-  const struct TALER_PurseContractPublicKeyP *purse_pub,
-  TALER_EXCHANGEDB_PurseRefundCoinCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (purse_pub),
-    GNUNET_PQ_query_param_end
-  };
-  struct PurseRefundCoinContext dsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"audit_get_purse_deposits_by_purse",
-                                             params,
-                                             &purse_refund_coin_helper_cb,
-                                             &dsc);
-  if (GNUNET_OK != dsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct RefreshsSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-refreshs_serial_helper_cb (void *cls,
-                           PGresult *result,
-                           unsigned int num_results)
-{
-  struct RefreshsSerialContext *rsc = cls;
-  struct PostgresClosure *pg = rsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_DenominationPublicKey denom_pub;
-    struct TALER_CoinSpendPublicKeyP coin_pub;
-    struct TALER_CoinSpendSignatureP coin_sig;
-    struct TALER_AgeCommitmentHash h_age_commitment;
-    bool ac_isnull;
-    struct TALER_Amount amount_with_fee;
-    uint32_t noreveal_index;
-    uint64_t rowid;
-    struct TALER_RefreshCommitmentP rc;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_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_pub",
-                                            &coin_pub),
-      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_uint32 ("noreveal_index",
-                                    &noreveal_index),
-      GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_auto_from_type ("rc",
-                                            &rc),
-      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,
-                   &denom_pub,
-                   ac_isnull ? NULL : &h_age_commitment,
-                   &coin_pub,
-                   &coin_sig,
-                   &amount_with_fee,
-                   noreveal_index,
-                   &rc);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_refreshes_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_RefreshesCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct RefreshsSerialContext rsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"audit_get_refresh_commitments_incr",
-                                             params,
-                                             &refreshs_serial_helper_cb,
-                                             &rsc);
-  if (GNUNET_OK != rsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct RefundsSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-refunds_serial_helper_cb (void *cls,
-                          PGresult *result,
-                          unsigned int num_results)
-{
-  struct RefundsSerialContext *rsc = cls;
-  struct PostgresClosure *pg = rsc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_EXCHANGEDB_Refund refund;
-    struct TALER_DenominationPublicKey denom_pub;
-    uint64_t rowid;
-    bool full_refund;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                            &refund.details.merchant_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
-                                            &refund.details.merchant_sig),
-      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
-                                            &refund.details.h_contract_terms),
-      GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
-                                    &refund.details.rtransaction_id),
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &refund.coin.coin_pub),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &refund.details.refund_amount),
-      GNUNET_PQ_result_spec_uint64 ("refund_serial_id",
-                                    &rowid),
-      GNUNET_PQ_result_spec_end
-    };
-    enum GNUNET_GenericReturnValue ret;
-
-    if (GNUNET_OK !=
-        GNUNET_PQ_extract_result (result,
-                                  rs,
-                                  i))
-    {
-      GNUNET_break (0);
-      rsc->status = GNUNET_SYSERR;
-      return;
-    }
-    {
-      struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_uint64 (&rowid),
-        GNUNET_PQ_query_param_end
-      };
-      struct TALER_Amount amount_with_fee;
-      uint64_t s_f;
-      uint64_t s_v;
-      struct GNUNET_PQ_ResultSpec rs2[] = {
-        GNUNET_PQ_result_spec_uint64 ("s_v",
-                                      &s_v),
-        GNUNET_PQ_result_spec_uint64 ("s_f",
-                                      &s_f),
-        TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                     &amount_with_fee),
-        GNUNET_PQ_result_spec_end
-      };
-      enum GNUNET_DB_QueryStatus qs;
-
-      qs = GNUNET_PQ_eval_prepared_singleton_select (
-        pg->conn,
-        "test_refund_full",
-        params,
-        rs2);
-      if (qs <= 0)
-      {
-        GNUNET_break (0);
-        rsc->status = GNUNET_SYSERR;
-        return;
-      }
-      /* normalize */
-      s_v += s_f / TALER_AMOUNT_FRAC_BASE;
-      s_f %= TALER_AMOUNT_FRAC_BASE;
-      full_refund = (s_v >= amount_with_fee.value) &&
-                    (s_f >= amount_with_fee.fraction);
-    }
-    ret = rsc->cb (rsc->cb_cls,
-                   rowid,
-                   &denom_pub,
-                   &refund.coin.coin_pub,
-                   &refund.details.merchant_pub,
-                   &refund.details.merchant_sig,
-                   &refund.details.h_contract_terms,
-                   refund.details.rtransaction_id,
-                   full_refund,
-                   &refund.details.refund_amount);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_refunds_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_RefundCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct RefundsSerialContext rsc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_refunds_incr",
-                                             params,
-                                             &refunds_serial_helper_cb,
-                                             &rsc);
-  if (GNUNET_OK != rsc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct ReservesInSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-reserves_in_serial_helper_cb (void *cls,
-                              PGresult *result,
-                              unsigned int num_results)
-{
-  struct ReservesInSerialContext *risc = cls;
-  struct PostgresClosure *pg = risc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_Amount credit;
-    char *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),
-      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;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_reserves_in_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_ReserveInCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct ReservesInSerialContext risc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"audit_reserves_in_get_transactions_incr",
-                                             params,
-                                             &reserves_in_serial_helper_cb,
-                                             &risc);
-  if (GNUNET_OK != risc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_reserves_in_above_serial_id_by_account (
-  void *cls,
-  const char *account_name,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_ReserveInCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_string (account_name),
-    GNUNET_PQ_query_param_end
-  };
-  struct ReservesInSerialContext risc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             
"audit_reserves_in_get_transactions_incr_by_account",
-                                             params,
-                                             &reserves_in_serial_helper_cb,
-                                             &risc);
-  if (GNUNET_OK != risc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Closure for #reserves_out_serial_helper_cb().
- */
-struct ReservesOutSerialContext
-{
-
-  /**
-   * Callback to call.
-   */
-  TALER_EXCHANGEDB_WithdrawCallback cb;
-
-  /**
-   * Closure for @e cb.
-   */
-  void *cb_cls;
-
-  /**
-   * Plugin context.
-   */
-  struct PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct ReservesOutSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-reserves_out_serial_helper_cb (void *cls,
-                               PGresult *result,
-                               unsigned int num_results)
-{
-  struct ReservesOutSerialContext *rosc = cls;
-  struct PostgresClosure *pg = rosc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    struct TALER_BlindedCoinHashP h_blind_ev;
-    struct TALER_DenominationPublicKey denom_pub;
-    struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_ReserveSignatureP reserve_sig;
-    struct GNUNET_TIME_Timestamp execution_date;
-    struct TALER_Amount amount_with_fee;
-    uint64_t rowid;
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
-                                            &h_blind_ev),
-      TALER_PQ_result_spec_denom_pub ("denom_pub",
-                                      &denom_pub),
-      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 ("execution_date",
-                                       &execution_date),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &amount_with_fee),
-      GNUNET_PQ_result_spec_uint64 ("reserve_out_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);
-      rosc->status = GNUNET_SYSERR;
-      return;
-    }
-    ret = rosc->cb (rosc->cb_cls,
-                    rowid,
-                    &h_blind_ev,
-                    &denom_pub,
-                    &reserve_pub,
-                    &reserve_sig,
-                    execution_date,
-                    &amount_with_fee);
-    GNUNET_PQ_cleanup_result (rs);
-    if (GNUNET_OK != ret)
-      break;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_withdrawals_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_WithdrawCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct ReservesOutSerialContext rosc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_reserves_out_incr",
-                                             params,
-                                             &reserves_out_serial_helper_cb,
-                                             &rosc);
-  if (GNUNET_OK != rosc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  int status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct WireOutSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-wire_out_serial_helper_cb (void *cls,
-                           PGresult *result,
-                           unsigned int num_results)
-{
-  struct WireOutSerialContext *wosc = cls;
-  struct PostgresClosure *pg = wosc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    uint64_t rowid;
-    struct GNUNET_TIME_Timestamp date;
-    struct TALER_WireTransferIdentifierRawP wtid;
-    char *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),
-      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;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_wire_out_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_WireTransferOutCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct WireOutSerialContext wosc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_wire_incr",
-                                             params,
-                                             &wire_out_serial_helper_cb,
-                                             &wosc);
-  if (GNUNET_OK != wosc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_wire_out_above_serial_id_by_account (
-  void *cls,
-  const char *account_name,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_WireTransferOutCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_string (account_name),
-    GNUNET_PQ_query_param_end
-  };
-  struct WireOutSerialContext wosc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "audit_get_wire_incr_by_account",
-                                             params,
-                                             &wire_out_serial_helper_cb,
-                                             &wosc);
-  if (GNUNET_OK != wosc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct RecoupSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-recoup_serial_helper_cb (void *cls,
-                         PGresult *result,
-                         unsigned int num_results)
-{
-  struct RecoupSerialContext *psc = cls;
-  struct PostgresClosure *pg = psc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    uint64_t rowid;
-    struct TALER_ReservePublicKeyP reserve_pub;
-    struct TALER_CoinPublicInfo coin;
-    struct TALER_CoinSpendSignatureP coin_sig;
-    union TALER_DenominationBlindingKeyP coin_blind;
-    struct TALER_Amount amount;
-    struct TALER_DenominationPublicKey denom_pub;
-    struct TALER_BlindedCoinHashP h_blind_ev;
-    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",
-                                       &timestamp),
-      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 ("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
-    };
-    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;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_recoup_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_RecoupCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct RecoupSerialContext psc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "recoup_get_incr",
-                                             params,
-                                             &recoup_serial_helper_cb,
-                                             &psc);
-  if (GNUNET_OK != psc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * 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 PostgresClosure *pg;
-
-  /**
-   * Status code, set to #GNUNET_SYSERR on hard errors.
-   */
-  enum GNUNET_GenericReturnValue status;
-};
-
-
-/**
- * Helper function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure of type `struct RecoupRefreshSerialContext`
- * @param result the postgres result
- * @param num_results the number of results in @a result
- */
-static void
-recoup_refresh_serial_helper_cb (void *cls,
-                                 PGresult *result,
-                                 unsigned int num_results)
-{
-  struct RecoupRefreshSerialContext *psc = cls;
-  struct PostgresClosure *pg = psc->pg;
-
-  for (unsigned int i = 0; i<num_results; i++)
-  {
-    uint64_t rowid;
-    struct TALER_CoinSpendPublicKeyP old_coin_pub;
-    struct TALER_CoinPublicInfo coin;
-    struct TALER_CoinSpendSignatureP coin_sig;
-    union TALER_DenominationBlindingKeyP 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",
-                                       &timestamp),
-      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;
-  }
-}
-
-
-/**
- * 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
- */
-static enum GNUNET_DB_QueryStatus
-postgres_select_recoup_refresh_above_serial_id (
-  void *cls,
-  uint64_t serial_id,
-  TALER_EXCHANGEDB_RecoupRefreshCallback cb,
-  void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&serial_id),
-    GNUNET_PQ_query_param_end
-  };
-  struct RecoupRefreshSerialContext psc = {
-    .cb = cb,
-    .cb_cls = cb_cls,
-    .pg = pg,
-    .status = GNUNET_OK
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
-                                             "recoup_refresh_get_incr",
-                                             params,
-                                             &recoup_refresh_serial_helper_cb,
-                                             &psc);
-  if (GNUNET_OK != psc.status)
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  return qs;
-}
-
-
-/**
- * Obtain information about which reserve a coin was generated
- * from given the hash of the blinded coin.
- *
- * @param cls closure
- * @param bch hash that uniquely identifies the withdraw request
- * @param[out] reserve_pub set to information about the reserve (on success 
only)
- * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in 
reserves_out
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_reserve_by_h_blind (
-  void *cls,
-  const struct TALER_BlindedCoinHashP *bch,
-  struct TALER_ReservePublicKeyP *reserve_pub,
-  uint64_t *reserve_out_serial_id)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (bch),
-    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 ("reserve_out_serial_id",
-                                  reserve_out_serial_id),
-    GNUNET_PQ_result_spec_end
-  };
-
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "reserve_by_h_blind",
-                                                   params,
-                                                   rs);
-}
-
-
 /**
  * Initialize Postgres database subsystem.
  *
@@ -4960,81 +483,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
   }
   plugin = GNUNET_new (struct TALER_EXCHANGEDB_Plugin);
   plugin->cls = pg;
-  plugin->get_policy_details = &postgres_get_policy_details;
-  plugin->add_policy_fulfillment_proof = 
&postgres_add_policy_fulfillment_proof;
-  plugin->do_melt = &postgres_do_melt;
-  plugin->do_refund = &postgres_do_refund;
-  plugin->do_recoup = &postgres_do_recoup;
-  plugin->do_recoup_refresh = &postgres_do_recoup_refresh;
-  plugin->get_reserve_balance = &postgres_get_reserve_balance;
-  plugin->count_known_coins = &postgres_count_known_coins;
-  plugin->ensure_coin_known = &postgres_ensure_coin_known;
-  plugin->get_known_coin = &postgres_get_known_coin;
-  plugin->get_coin_denomination = &postgres_get_coin_denomination;
-  plugin->have_deposit2 = &postgres_have_deposit2;
-  plugin->aggregate = &postgres_aggregate;
-  plugin->create_aggregation_transient
-    = &postgres_create_aggregation_transient;
-  plugin->select_aggregation_transient
-    = &postgres_select_aggregation_transient;
-  plugin->find_aggregation_transient
-    = &postgres_find_aggregation_transient;
-  plugin->update_aggregation_transient
-    = &postgres_update_aggregation_transient;
-  plugin->get_ready_deposit = &postgres_get_ready_deposit;
-  plugin->insert_deposit = &postgres_insert_deposit;
-  plugin->insert_refund = &postgres_insert_refund;
-  plugin->select_refunds_by_coin = &postgres_select_refunds_by_coin;
-  plugin->get_melt = &postgres_get_melt;
-  plugin->insert_refresh_reveal = &postgres_insert_refresh_reveal;
-  plugin->get_refresh_reveal = &postgres_get_refresh_reveal;
-  plugin->lookup_wire_transfer = &postgres_lookup_wire_transfer;
-  plugin->lookup_transfer_by_deposit = &postgres_lookup_transfer_by_deposit;
-  plugin->insert_wire_fee = &postgres_insert_wire_fee;
-  plugin->insert_global_fee = &postgres_insert_global_fee;
-  plugin->get_wire_fee = &postgres_get_wire_fee;
-  plugin->get_global_fee = &postgres_get_global_fee;
-  plugin->get_global_fees = &postgres_get_global_fees;
-  plugin->insert_reserve_closed = &postgres_insert_reserve_closed;
-  plugin->wire_prepare_data_insert = &postgres_wire_prepare_data_insert;
-  plugin->wire_prepare_data_mark_finished =
-    &postgres_wire_prepare_data_mark_finished;
-  plugin->wire_prepare_data_mark_failed =
-    &postgres_wire_prepare_data_mark_failed;
-  plugin->wire_prepare_data_get = &postgres_wire_prepare_data_get;
-  plugin->start_deferred_wire_out = &postgres_start_deferred_wire_out;
-  plugin->store_wire_transfer_out = &postgres_store_wire_transfer_out;
-  plugin->gc = &postgres_gc;
-
-  plugin->select_deposits_above_serial_id
-    = &postgres_select_deposits_above_serial_id;
-  plugin->select_history_requests_above_serial_id
-    = &postgres_select_history_requests_above_serial_id;
-  plugin->select_purse_decisions_above_serial_id
-    = &postgres_select_purse_decisions_above_serial_id;
-  plugin->select_purse_deposits_by_purse
-    = &postgres_select_purse_deposits_by_purse;
-  plugin->select_refreshes_above_serial_id
-    = &postgres_select_refreshes_above_serial_id;
-  plugin->select_refunds_above_serial_id
-    = &postgres_select_refunds_above_serial_id;
-  plugin->select_reserves_in_above_serial_id
-    = &postgres_select_reserves_in_above_serial_id;
-  plugin->select_reserves_in_above_serial_id_by_account
-    = &postgres_select_reserves_in_above_serial_id_by_account;
-  plugin->select_withdrawals_above_serial_id
-    = &postgres_select_withdrawals_above_serial_id;
-  plugin->select_wire_out_above_serial_id
-    = &postgres_select_wire_out_above_serial_id;
-  plugin->select_wire_out_above_serial_id_by_account
-    = &postgres_select_wire_out_above_serial_id_by_account;
-  plugin->select_recoup_above_serial_id
-    = &postgres_select_recoup_above_serial_id;
-  plugin->select_recoup_refresh_above_serial_id
-    = &postgres_select_recoup_refresh_above_serial_id;
-  plugin->get_reserve_by_h_blind
-    = &postgres_get_reserve_by_h_blind;
-
   /* New style, sort alphabetically! */
   plugin->do_reserve_open
     = &TEH_PG_do_reserve_open;
@@ -5376,6 +824,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     = &TEH_PG_set_purse_balance;
   plugin->batch_reserves_in_insert
     = &TEH_PG_batch_reserves_in_insert;
+  plugin->batch2_reserves_in_insert
+    = &TEH_PG_batch2_reserves_in_insert;
 
   return plugin;
 }
diff --git a/src/exchangedb/test_exchangedb_by_j.c 
b/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
similarity index 84%
copy from src/exchangedb/test_exchangedb_by_j.c
copy to src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
index 43f47167..460778b8 100644
--- a/src/exchangedb/test_exchangedb_by_j.c
+++ b/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
@@ -23,7 +23,7 @@
 #include "taler_json_lib.h"
 #include "taler_exchangedb_plugin.h"
 
-/**
+/**o
  * Global result from the testcase.
  */
 static int result;
@@ -33,7 +33,7 @@ static int result;
  */
 #define FAILIF(cond)                            \
   do {                                          \
-    if (! (cond)) {break;}                    \
+      if (! (cond)) {break;}                    \
     GNUNET_break (0);                           \
     goto drop;                                  \
   } while (0)
@@ -83,17 +83,24 @@ run (void *cls)
   }
   (void) plugin->drop_tables (plugin->cls);
   if (GNUNET_OK !=
-      plugin->create_tables (plugin->cls,
-                             true,
-                             num_partitions))
+      plugin->create_tables (plugin->cls))
   {
     GNUNET_break (0);
     result = 77;
     goto cleanup;
   }
-  for (unsigned int i = 0; i< 7; i++)
+  if (GNUNET_OK !=
+      plugin->setup_partitions (plugin->cls,
+                                num_partitions))
   {
-    static unsigned int batches[] = {1, 1, 2, 4, 16, 64, 256};
+    GNUNET_break (0);
+    result = 77;
+    goto cleanup;
+  }
+
+  for (unsigned int i = 0; i< 8; i++)
+  {
+    static unsigned int batches[] = {1, 1,0, 2, 4, 16, 64, 256};
     const char *sndr = "payto://x-taler-bank/localhost:8080/1";
     struct TALER_Amount value;
     unsigned int batch_size = batches[i];
@@ -107,10 +114,8 @@ run (void *cls)
                                            &value));
     now = GNUNET_TIME_absolute_get ();
     ts = GNUNET_TIME_timestamp_get ();
-    for (unsigned int r = 0; r<10; r++)
+    for (unsigned int r=0;r<10;r++)
     {
-      plugin->start_read_committed (plugin->cls,
-                                    "test_by_j");
 
       for (unsigned int k = 0; k<batch_size; k++)
       {
@@ -120,22 +125,21 @@ run (void *cls)
         reserves[k].sender_account_details = sndr;
         reserves[k].exchange_account_name = "name";
         reserves[k].wire_reference = k;
-
       }
       FAILIF (batch_size !=
-              plugin->batch_reserves_in_insert (plugin->cls,
-                                                reserves,
-                                                batch_size,
-                                                results));
+            plugin->batch_reserves_in_insert (plugin->cls,
+                                              reserves,
+                                              batch_size,
+                                              results));
+      }
 
-      plugin->commit (plugin->cls);
-    }
     duration = GNUNET_TIME_absolute_get_duration (now);
     fprintf (stdout,
              "for a batchsize equal to %d it took %s\n",
              batch_size,
              GNUNET_STRINGS_relative_time_to_string (duration,
                                                      GNUNET_NO) );
+
   }
   result = 0;
 drop:
@@ -155,22 +159,22 @@ main (int argc,
   char *config_filename;
   char *testname;
   struct GNUNET_CONFIGURATION_Handle *cfg;
-
   (void) argc;
   result = -1;
-  if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
+   if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
   {
     GNUNET_break (0);
     return -1;
-  }
+    }
+
   GNUNET_log_setup (argv[0],
                     "WARNING",
                     NULL);
-  plugin_name++;
-  (void) GNUNET_asprintf (&testname,
+   plugin_name++;
+    (void) GNUNET_asprintf (&testname,
                           "test-exchange-db-%s",
                           plugin_name);
-  (void) GNUNET_asprintf (&config_filename,
+    (void) GNUNET_asprintf (&config_filename,
                           "%s.conf",
                           testname);
   fprintf (stdout,
@@ -194,5 +198,4 @@ main (int argc,
   return result;
 }
 
-
 /* end of test_exchangedb_by_j.c */
diff --git a/src/exchangedb/test_exchangedb_by_j.c 
b/src/exchangedb/test_exchangedb_by_j.c
index 43f47167..834373b5 100644
--- a/src/exchangedb/test_exchangedb_by_j.c
+++ b/src/exchangedb/test_exchangedb_by_j.c
@@ -91,9 +91,22 @@ run (void *cls)
     result = 77;
     goto cleanup;
   }
+
   for (unsigned int i = 0; i< 7; i++)
+
+  if (GNUNET_OK !=
+      plugin->setup_partitions (plugin->cls,
+                                num_partitions))
+  {
+    GNUNET_break (0);
+    result = 77;
+    goto cleanup;
+  }
+
+  for (unsigned int i = 0; i< 8; i++)
+
   {
-    static unsigned int batches[] = {1, 1, 2, 4, 16, 64, 256};
+    static unsigned int batches[] = {1, 1,0, 2, 4, 16, 64, 256};
     const char *sndr = "payto://x-taler-bank/localhost:8080/1";
     struct TALER_Amount value;
     unsigned int batch_size = batches[i];
@@ -101,6 +114,7 @@ run (void *cls)
     struct GNUNET_TIME_Timestamp ts;
     struct GNUNET_TIME_Relative duration;
     struct TALER_EXCHANGEDB_ReserveInInfo reserves[batch_size];
+    /*   struct TALER_EXCHANGEDB_ReserveInInfo reserves2[batch_size];*/
     enum GNUNET_DB_QueryStatus results[batch_size];
     GNUNET_assert (GNUNET_OK ==
                    TALER_string_to_amount (CURRENCY ":1.000010",
@@ -109,10 +123,8 @@ run (void *cls)
     ts = GNUNET_TIME_timestamp_get ();
     for (unsigned int r = 0; r<10; r++)
     {
-      plugin->start_read_committed (plugin->cls,
-                                    "test_by_j");
 
-      for (unsigned int k = 0; k<batch_size; k++)
+       for (unsigned int k = 0; k<batch_size; k++)
       {
         RND_BLK (&reserves[k].reserve_pub);
         reserves[k].balance = value;
@@ -120,22 +132,21 @@ run (void *cls)
         reserves[k].sender_account_details = sndr;
         reserves[k].exchange_account_name = "name";
         reserves[k].wire_reference = k;
-
       }
       FAILIF (batch_size !=
-              plugin->batch_reserves_in_insert (plugin->cls,
-                                                reserves,
-                                                batch_size,
-                                                results));
-
-      plugin->commit (plugin->cls);
+            plugin->batch_reserves_in_insert (plugin->cls,
+                                              reserves,
+                                              batch_size,
+                                              results));
     }
+
     duration = GNUNET_TIME_absolute_get_duration (now);
     fprintf (stdout,
              "for a batchsize equal to %d it took %s\n",
              batch_size,
              GNUNET_STRINGS_relative_time_to_string (duration,
                                                      GNUNET_NO) );
+
   }
   result = 0;
 drop:
@@ -155,7 +166,6 @@ main (int argc,
   char *config_filename;
   char *testname;
   struct GNUNET_CONFIGURATION_Handle *cfg;
-
   (void) argc;
   result = -1;
   if (NULL == (plugin_name = strrchr (argv[0], (int) '-')))
@@ -163,6 +173,7 @@ main (int argc,
     GNUNET_break (0);
     return -1;
   }
+
   GNUNET_log_setup (argv[0],
                     "WARNING",
                     NULL);
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index a2e3237f..6951908e 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -3453,6 +3453,21 @@ struct TALER_EXCHANGEDB_Plugin
                               unsigned int reserves_length,
                               enum GNUNET_DB_QueryStatus *results);
 
+  /**
+   * Insert a batch of incoming transaction into reserves.  New reserves are
+   * also created through this function.
+   *
+   * @param cls the @e cls of this struct with the plugin-specific state
+   * @param reserves
+   * @param reserves_length length of the @a reserves array
+   * @param[out] results array of transaction status codes of length @a 
reserves_length,
+   *             set to the status of the
+   */
+  enum GNUNET_DB_QueryStatus
+  (*batch2_reserves_in_insert)(void *cls,
+                              const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
+                              unsigned int reserves_length,
+                              enum GNUNET_DB_QueryStatus *results);
 
   /**
    * Locate a nonce for use with a particular public key.

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]