gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: exchangedb: use partial index in


From: gnunet
Subject: [taler-exchange] branch master updated: exchangedb: use partial index instead of materialized tables deposits_by_ready and deposits_by_matching; remove now broken code; rename benchmarks to use perf_-prefix and correspond to function they benchmark
Date: Sun, 05 Feb 2023 19:11:51 +0100

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new ab03ba16 exchangedb: use partial index instead of materialized tables 
deposits_by_ready and deposits_by_matching; remove now broken code; rename 
benchmarks to use perf_-prefix and correspond to function they benchmark
ab03ba16 is described below

commit ab03ba16e9bc63eb5384e7b6b590fc029bf61152
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Feb 5 19:11:47 2023 +0100

    exchangedb: use partial index instead of materialized tables 
deposits_by_ready and deposits_by_matching; remove now broken code; rename 
benchmarks to use perf_-prefix and correspond to function they benchmark
---
 src/exchange/taler-exchange-wirewatch.c            |  422 +--------
 src/exchangedb/.gitignore                          |   16 +-
 src/exchangedb/0002-deposits.sql                   |   46 +-
 src/exchangedb/Makefile.am                         |   71 +-
 ...e_ready_deposit.c => perf_deposits_get_ready.c} |  382 ++++----
 ...b_populate_link_data.c => perf_get_link_data.c} |  234 ++---
 ...erves_in_insert.c => perf_reserves_in_insert.c} |  124 ++-
 ...nds_by_coin.c => perf_select_refunds_by_coin.c} |  302 +++---
 src/exchangedb/pg_aggregate.c                      |   22 +-
 src/exchangedb/pg_batch2_reserves_in_insert.c      |  914 ------------------
 src/exchangedb/pg_batch2_reserves_in_insert.h      |   34 -
 src/exchangedb/pg_batch4_reserves_in_insert.c      |  595 ------------
 src/exchangedb/pg_batch_reserves_in_insert.c       |  252 -----
 src/exchangedb/pg_batch_reserves_in_insert.h       |   35 -
 src/exchangedb/pg_get_link_data.c                  |   26 +-
 src/exchangedb/pg_get_ready_deposit.c              |  180 +---
 src/exchangedb/pg_reserves_in_insert.c             | 1000 ++++++++++++++++----
 src/exchangedb/pg_reserves_in_insert.h             |   30 +-
 src/exchangedb/pg_select_refunds_by_coin.c         |   17 +-
 src/exchangedb/plugin_exchangedb_postgres.c        |    6 -
 .../test_exchangedb_batch_reserves_in_insert.c     |  196 ----
 src/include/taler_exchangedb_plugin.h              |   49 +-
 22 files changed, 1480 insertions(+), 3473 deletions(-)

diff --git a/src/exchange/taler-exchange-wirewatch.c 
b/src/exchange/taler-exchange-wirewatch.c
index a1a3a4ff..a7a6b004 100644
--- a/src/exchange/taler-exchange-wirewatch.c
+++ b/src/exchange/taler-exchange-wirewatch.c
@@ -491,389 +491,6 @@ transaction_completed (void)
 }
 
 
-/**
- * We got incoming transaction details from the bank. Add them
- * to the database.
- *
- * @param details array of transaction details
- * @param details_length length of the @a details array
- */
-static void
-process_reply (const struct TALER_BANK_CreditDetails *details,
-               unsigned int details_length)
-{
-  enum GNUNET_DB_QueryStatus qs;
-  bool shard_done;
-  uint64_t lroff = latest_row_off;
-
-  if (0 == details_length)
-  {
-    /* Server should have used 204, not 200! */
-    GNUNET_break_op (0);
-    transaction_completed ();
-    return;
-  }
-  hh_returned_data = true;
-  /* check serial IDs for range constraints */
-  for (unsigned int i = 0; i<details_length; i++)
-  {
-    const struct TALER_BANK_CreditDetails *cd = &details[i];
-
-    if (cd->serial_id < lroff)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Serial ID %llu not monotonic (got %llu before). Failing!\n",
-                  (unsigned long long) cd->serial_id,
-                  (unsigned long long) lroff);
-      db_plugin->rollback (db_plugin->cls);
-      GNUNET_SCHEDULER_shutdown ();
-      return;
-    }
-    if (cd->serial_id > shard_end)
-    {
-      /* we are *past* the current shard (likely because the serial_id of the
-         shard_end happens to not exist in the DB). So commit and stop this
-         iteration! */
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Serial ID %llu past shard end at %llu, ending iteration 
early!\n",
-                  (unsigned long long) cd->serial_id,
-                  (unsigned long long) shard_end);
-      details_length = i;
-      progress = true;
-      lroff = cd->serial_id - 1;
-      break;
-    }
-    lroff = cd->serial_id;
-  }
-  if (GNUNET_OK !=
-      db_plugin->start_read_committed (db_plugin->cls,
-                                       "wirewatch check for incoming wire 
transfers"))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to start database transaction!\n");
-    global_ret = EXIT_FAILURE;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-  started_transaction = true;
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Importing %u transactions\n",
-              details_length);
-  for (unsigned int i = 0; i<details_length; i++)
-  {
-    const struct TALER_BANK_CreditDetails *cd = &details[i];
-
-    /* FIXME #7276: Consider using Postgres multi-valued insert here,
-   for up to 15x speed-up according to
-   
https://dba.stackexchange.com/questions/224989/multi-row-insert-vs-transactional-single-row-inserts#225006
-   (Note: this may require changing both the
-   plugin API as well as modifying how this function is called.) */
-    qs = db_plugin->reserves_in_insert (db_plugin->cls,
-                                        &cd->reserve_pub,
-                                        &cd->amount,
-                                        cd->execution_date,
-                                        cd->debit_account_uri,
-                                        ai->section_name,
-                                        cd->serial_id);
-    switch (qs)
-    {
-    case GNUNET_DB_STATUS_HARD_ERROR:
-      GNUNET_break (0);
-      GNUNET_SCHEDULER_shutdown ();
-      return;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Got DB soft error for reserves_in_insert. Rolling back.\n");
-      handle_soft_error ();
-      return;
-    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      /* Either wirewatch was freshly started after the system was
-         shutdown and we're going over an incomplete shard again
-         after being restarted, or the shard lock period was too
-         short (number of workers set incorrectly?) and a 2nd
-         wirewatcher has been stealing our work while we are still
-         at it. */
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Attempted to import transaction %llu (%s) twice. "
-                  "This should happen rarely (if not, ask for support).\n",
-                  (unsigned long long) cd->serial_id,
-                  job_name);
-      break;
-    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Imported transaction %llu.",
-                  (unsigned long long) cd->serial_id);
-      /* normal case */
-      progress = true;
-      break;
-    }
-  }
-  latest_row_off = lroff;
-  shard_done = (shard_end <= latest_row_off);
-  if (shard_done)
-  {
-    /* shard is complete, mark this as well */
-    qs = db_plugin->complete_shard (db_plugin->cls,
-                                    job_name,
-                                    shard_start,
-                                    shard_end);
-    switch (qs)
-    {
-    case GNUNET_DB_STATUS_HARD_ERROR:
-      GNUNET_break (0);
-      GNUNET_SCHEDULER_shutdown ();
-      return;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Got DB soft error for complete_shard. Rolling back.\n");
-      handle_soft_error ();
-      return;
-    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      GNUNET_break (0);
-      /* Not expected, but let's just continue */
-      break;
-    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-      /* normal case */
-      progress = true;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Completed shard %s (%llu,%llu] after %s\n",
-                  job_name,
-                  (unsigned long long) shard_start,
-                  (unsigned long long) shard_end,
-                  GNUNET_STRINGS_relative_time_to_string (
-                    GNUNET_TIME_absolute_get_duration (shard_start_time),
-                    true));
-      break;
-    }
-  }
-  if (! progress)
-  {
-    db_plugin->rollback (db_plugin->cls);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Committing %s progress (%llu,%llu] at %llu\n (%s)",
-                job_name,
-                (unsigned long long) shard_start,
-                (unsigned long long) shard_end,
-                (unsigned long long) latest_row_off,
-                shard_done
-              ? "shard done"
-              : "shard incomplete");
-    qs = db_plugin->commit (db_plugin->cls);
-    switch (qs)
-    {
-    case GNUNET_DB_STATUS_HARD_ERROR:
-      GNUNET_break (0);
-      GNUNET_SCHEDULER_shutdown ();
-      return;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      /* reduce transaction size to reduce rollback probability */
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Got DB soft error on commit. Reducing transaction size.\n");
-      handle_soft_error ();
-      return;
-    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-      started_transaction = false;
-      /* normal case */
-      break;
-    }
-  }
-  if (shard_done)
-  {
-    shard_delay = GNUNET_TIME_absolute_get_duration (shard_start_time);
-    shard_open = false;
-    transaction_completed ();
-    return;
-  }
-  GNUNET_assert (NULL == task);
-  task = GNUNET_SCHEDULER_add_now (&continue_with_shard,
-                                   NULL);
-}
-
-
-/**
- * We got incoming transaction details from the bank. Add them
- * to the database.
- *
- * @param details array of transaction details
- * @param details_length length of the @a details array
- */
-static void
-process_reply_batched (const struct TALER_BANK_CreditDetails *details,
-                       unsigned int details_length)
-{
-  enum GNUNET_DB_QueryStatus qs;
-  bool shard_done;
-  uint64_t lroff = latest_row_off;
-
-  if (0 == details_length)
-  {
-    /* Server should have used 204, not 200! */
-    GNUNET_break_op (0);
-    transaction_completed ();
-    return;
-  }
-  /* check serial IDs for range constraints */
-  for (unsigned int i = 0; i<details_length; i++)
-  {
-    const struct TALER_BANK_CreditDetails *cd = &details[i];
-
-    if (cd->serial_id < lroff)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Serial ID %llu not monotonic (got %llu before). Failing!\n",
-                  (unsigned long long) cd->serial_id,
-                  (unsigned long long) lroff);
-      db_plugin->rollback (db_plugin->cls);
-      GNUNET_SCHEDULER_shutdown ();
-      return;
-    }
-    if (cd->serial_id > shard_end)
-    {
-      /* we are *past* the current shard (likely because the serial_id of the
-         shard_end happens to not exist in the DB). So commit and stop this
-         iteration! */
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Serial ID %llu past shard end at %llu, ending iteration 
early!\n",
-                  (unsigned long long) cd->serial_id,
-                  (unsigned long long) shard_end);
-      details_length = i;
-      progress = true;
-      lroff = cd->serial_id - 1;
-      break;
-    }
-    lroff = cd->serial_id;
-  }
-  if (0 != details_length)
-  {
-    enum GNUNET_DB_QueryStatus qss[details_length];
-    struct TALER_EXCHANGEDB_ReserveInInfo reserves[details_length];
-
-    hh_returned_data = true;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Importing %u transactions\n",
-                details_length);
-    for (unsigned int i = 0; i<details_length; i++)
-    {
-      const struct TALER_BANK_CreditDetails *cd = &details[i];
-      struct TALER_EXCHANGEDB_ReserveInInfo *res = &reserves[i];
-
-      res->reserve_pub = &cd->reserve_pub;
-      res->balance = &cd->amount;
-      res->execution_time = cd->execution_date;
-      res->sender_account_details = cd->debit_account_uri;
-      res->exchange_account_name = ai->section_name;
-      res->wire_reference = cd->serial_id;
-    }
-    qs = db_plugin->batch_reserves_in_insert (db_plugin->cls,
-                                              reserves,
-                                              details_length,
-                                              qss);
-    switch (qs)
-    {
-    case GNUNET_DB_STATUS_HARD_ERROR:
-      GNUNET_break (0);
-      GNUNET_SCHEDULER_shutdown ();
-      return;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Got DB soft error for batch_reserves_in_insert. Rolling 
back.\n");
-      handle_soft_error ();
-      return;
-    default:
-      break;
-    }
-    for (unsigned int i = 0; i<details_length; i++)
-    {
-      const struct TALER_BANK_CreditDetails *cd = &details[i];
-
-      switch (qss[i])
-      {
-      case GNUNET_DB_STATUS_HARD_ERROR:
-        GNUNET_break (0);
-        GNUNET_SCHEDULER_shutdown ();
-        return;
-      case GNUNET_DB_STATUS_SOFT_ERROR:
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "Got DB soft error for batch_reserves_in_insert(%u). 
Rolling back.\n",
-                    i);
-        handle_soft_error ();
-        return;
-      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-        /* Either wirewatch was freshly started after the system was
-           shutdown and we're going over an incomplete shard again
-           after being restarted, or the shard lock period was too
-           short (number of workers set incorrectly?) and a 2nd
-           wirewatcher has been stealing our work while we are still
-           at it. */
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "Attempted to import transaction %llu (%s) twice. "
-                    "This should happen rarely (if not, ask for support).\n",
-                    (unsigned long long) cd->serial_id,
-                    job_name);
-        break;
-      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "Imported transaction %llu.",
-                    (unsigned long long) cd->serial_id);
-        /* normal case */
-        progress = true;
-        break;
-      }
-    }
-  }
-
-  latest_row_off = lroff;
-  shard_done = (shard_end <= latest_row_off);
-  if (shard_done)
-  {
-    /* shard is complete, mark this as well */
-    qs = db_plugin->complete_shard (db_plugin->cls,
-                                    job_name,
-                                    shard_start,
-                                    shard_end);
-    switch (qs)
-    {
-    case GNUNET_DB_STATUS_HARD_ERROR:
-      GNUNET_break (0);
-      GNUNET_SCHEDULER_shutdown ();
-      return;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Got DB soft error for complete_shard. Rolling back.\n");
-      handle_soft_error ();
-      return;
-    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      GNUNET_break (0);
-      /* Not expected, but let's just continue */
-      break;
-    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-      /* normal case */
-      progress = true;
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Completed shard %s (%llu,%llu] after %s\n",
-                  job_name,
-                  (unsigned long long) shard_start,
-                  (unsigned long long) shard_end,
-                  GNUNET_STRINGS_relative_time_to_string (
-                    GNUNET_TIME_absolute_get_duration (shard_start_time),
-                    true));
-      break;
-    }
-    shard_delay = GNUNET_TIME_absolute_get_duration (shard_start_time);
-    shard_open = false;
-    transaction_completed ();
-    return;
-  }
-  GNUNET_assert (NULL == task);
-  task = GNUNET_SCHEDULER_add_now (&continue_with_shard,
-                                   NULL);
-}
-
-
 /**
  * We got incoming transaction details from the bank. Add them
  * to the database.
@@ -883,9 +500,9 @@ process_reply_batched (const struct 
TALER_BANK_CreditDetails *details,
  * @param details_length length of the @a details array
  */
 static void
-process_reply_batched2 (unsigned int batch_size,
-                        const struct TALER_BANK_CreditDetails *details,
-                        unsigned int details_length)
+process_reply (unsigned int batch_size,
+               const struct TALER_BANK_CreditDetails *details,
+               unsigned int details_length)
 {
   enum GNUNET_DB_QueryStatus qs;
   bool shard_done;
@@ -950,11 +567,11 @@ process_reply_batched2 (unsigned int batch_size,
       res->exchange_account_name = ai->section_name;
       res->wire_reference = cd->serial_id;
     }
-    qs = db_plugin->batch2_reserves_in_insert (db_plugin->cls,
-                                               reserves,
-                                               details_length,
-                                               batch_size,
-                                               qss);
+    qs = db_plugin->reserves_in_insert (db_plugin->cls,
+                                        reserves,
+                                        details_length,
+                                        batch_size,
+                                        qss);
     switch (qs)
     {
     case GNUNET_DB_STATUS_HARD_ERROR:
@@ -1074,7 +691,7 @@ history_cb (void *cls,
   (void) cls;
   if (-2 == batch_mode)
   {
-    const char *mode = getenv ("TALER_USE_BATCH");
+    const char *mode = getenv ("TALER_WIREWATCH_BATCH_SIZE");
     char dummy;
 
     if ( (NULL == mode) ||
@@ -1087,7 +704,7 @@ history_cb (void *cls,
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                     "Bad batch mode `%s' specified\n",
                     mode);
-      batch_mode = -1;
+      batch_mode = 8; /* maximum supported is currently 8 */
     }
   }
   GNUNET_assert (NULL == task);
@@ -1098,22 +715,9 @@ history_cb (void *cls,
   switch (reply->http_status)
   {
   case MHD_HTTP_OK:
-    switch (batch_mode)
-    {
-    case -1:
-      process_reply (reply->details.success.details,
-                     reply->details.success.details_length);
-      break;
-    case 0:
-      process_reply_batched (reply->details.success.details,
-                             reply->details.success.details_length);
-      break;
-    default:
-      process_reply_batched2 ((unsigned int) batch_mode,
-                              reply->details.success.details,
-                              reply->details.success.details_length);
-      break;
-    }
+    process_reply (batch_mode,
+                   reply->details.success.details,
+                   reply->details.success.details_length);
     return;
   case MHD_HTTP_NO_CONTENT:
     transaction_completed ();
diff --git a/src/exchangedb/.gitignore b/src/exchangedb/.gitignore
index dd3c5ed1..264217a3 100644
--- a/src/exchangedb/.gitignore
+++ b/src/exchangedb/.gitignore
@@ -1,17 +1,9 @@
-test-exchangedb-auditors
-test-exchangedb-denomkeys
-test-exchangedb-fees
 test-exchangedb-postgres
-test-exchangedb-signkeys
-test-perf-taler-exchangedb
 bench-db-postgres
-shard-drop0001.sqltest-exchangedb-by-j-postgres
-test-exchangedb-by-j-postgres
-perf-exchangedb-reserves-in-insert-postgres
+perf_deposits_get_ready-postgres
+perf_get_link_data-postgres
+perf_reserves_in_insert-postgres
+perf_select_refunds_by_coin-postgres
 exchange-0002.sql
 procedures.sql
 exchange-0003.sql
-test-exchangedb-batch-reserves-in-insert-postgres
-test-exchangedb-populate-table-postgres
-test-exchangedb-populate-link-data-postgres
-test-exchangedb-populate-ready-deposit-postgres
diff --git a/src/exchangedb/0002-deposits.sql b/src/exchangedb/0002-deposits.sql
index 92210afa..d8afdac8 100644
--- a/src/exchangedb/0002-deposits.sql
+++ b/src/exchangedb/0002-deposits.sql
@@ -1,6 +1,6 @@
 --
 -- This file is part of TALER
--- Copyright (C) 2014--2022 Taler Systems SA
+-- Copyright (C) 2014--2023 Taler Systems SA
 --
 -- TALER is free software; you can redistribute it and/or modify it under the
 -- terms of the GNU General Public License as published by the Free Software
@@ -116,6 +116,22 @@ BEGIN
     ',ADD CONSTRAINT ' || table_name || 
'_coin_pub_merchant_pub_h_contract_terms_key'
     ' UNIQUE (coin_pub, merchant_pub, h_contract_terms)'
   );
+  EXECUTE FORMAT (
+    'CREATE INDEX ' || table_name || '_by_ready '
+    'ON ' || table_name || ' '
+    '(wire_deadline ASC'
+    ',shard ASC'
+    ',coin_pub'
+    ') WHERE NOT (done OR policy_blocked);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX ' || table_name || '_for_matching '
+    'ON ' || table_name || ' '
+    '(refund_deadline ASC'
+    ',merchant_pub'
+    ',coin_pub'
+    ') WHERE NOT (done OR policy_blocked);'
+  );
 END
 $$;
 
@@ -399,29 +415,5 @@ INSERT INTO exchange_tables
     ,'exchange-0002'
     ,'foreign'
     ,TRUE
-    ,FALSE),
-    ('deposits_by_ready'
-    ,'exchange-0002'
-    ,'create'
-    ,TRUE
-    ,TRUE),
-    ('deposits_by_ready'
-    ,'exchange-0002'
-    ,'constrain'
-    ,TRUE
-    ,TRUE),
-    ('deposits_for_matching'
-    ,'exchange-0002'
-    ,'create'
-    ,TRUE
-    ,TRUE),
-    ('deposits_for_matching'
-    ,'exchange-0002'
-    ,'constrain'
-    ,TRUE
-    ,TRUE),
-    ('deposits'
-    ,'exchange-0002'
-    ,'master'
-    ,TRUE
-    ,FALSE);
+    ,FALSE)
+    ;
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index e8ef104e..49bc649b 100644
--- a/src/exchangedb/Makefile.am
+++ b/src/exchangedb/Makefile.am
@@ -255,8 +255,6 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
   pg_select_purse_deposits_above_serial_id.h 
pg_select_purse_deposits_above_serial_id.c \
   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)
@@ -295,22 +293,14 @@ check_PROGRAMS = \
 
 noinst_PROGRAMS = \
   bench-db-postgres\
-  perf-exchangedb-reserves-in-insert-postgres\
-  test-exchangedb-by-j-postgres\
-  test-exchangedb-batch-reserves-in-insert-postgres\
-  test-exchangedb-populate-select-refunds-by-coin-postgres\
-  test-exchangedb-populate-link-data-postgres\
-  test-exchangedb-populate-ready-deposit-postgres
+  perf_get_link_data-postgres\
+  perf_select_refunds_by_coin-postgres\
+  perf_reserves_in_insert-postgres \
+  perf_deposits_get_ready-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\
-  test-exchangedb-batch-reserves-in-insert-postgres\
-  test-exchangedb-populate-select-refunds-by-coin-postgres\
-  test-exchangedb-populate-link-data-postgres\
-  test-exchangedb-populate-ready-deposit-postgres
+  (check_PROGRAMS)
 test_exchangedb_postgres_SOURCES = \
   test_exchangedb.c
 test_exchangedb_postgres_LDADD = \
@@ -323,32 +313,6 @@ test_exchangedb_postgres_LDADD = \
   -lgnunetutil \
   $(XLIB)
 
-test_exchangedb_by_j_postgres_SOURCES = \
-  test_exchangedb_by_j.c
-test_exchangedb_by_j_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 \
-  -lm \
-  $(XLIB)
-
-
-perf_exchangedb_reserves_in_insert_postgres_SOURCES = \
-  perf_exchangedb_reserves_in_insert.c
-perf_exchangedb_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 = \
@@ -359,9 +323,9 @@ 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 = \
+perf_reserves_in_insert_postgres_SOURCES = \
+  perf_reserves_in_insert.c
+perf_reserves_in_insert_postgres_LDADD = \
   libtalerexchangedb.la \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/util/libtalerutil.la \
@@ -369,11 +333,12 @@ test_exchangedb_batch_reserves_in_insert_postgres_LDADD = 
\
   -ljansson \
   -lgnunetjson \
   -lgnunetutil \
+  -lm \
   $(XLIB)
 
-test_exchangedb_populate_select_refunds_by_coin_postgres_SOURCES = \
-  test_exchangedb_populate_select_refunds_by_coin.c
-test_exchangedb_populate_select_refunds_by_coin_postgres_LDADD = \
+perf_select_refunds_by_coin_postgres_SOURCES = \
+  perf_select_refunds_by_coin.c
+perf_select_refunds_by_coin_postgres_LDADD = \
   libtalerexchangedb.la \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/util/libtalerutil.la \
@@ -384,9 +349,9 @@ 
test_exchangedb_populate_select_refunds_by_coin_postgres_LDADD = \
   -lm \
   $(XLIB)
 
-test_exchangedb_populate_link_data_postgres_SOURCES = \
-  test_exchangedb_populate_link_data.c
-test_exchangedb_populate_link_data_postgres_LDADD = \
+perf_get_link_data_postgres_SOURCES = \
+  perf_get_link_data.c
+perf_get_link_data_postgres_LDADD = \
   libtalerexchangedb.la \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/util/libtalerutil.la \
@@ -397,9 +362,9 @@ test_exchangedb_populate_link_data_postgres_LDADD = \
   -lm \
   $(XLIB)
 
-test_exchangedb_populate_ready_deposit_postgres_SOURCES = \
-  test_exchangedb_populate_ready_deposit.c
-test_exchangedb_populate_ready_deposit_postgres_LDADD = \
+perf_deposits_get_ready_postgres_SOURCES = \
+  perf_deposits_get_ready.c
+perf_deposits_get_ready_postgres_LDADD = \
   libtalerexchangedb.la \
   $(top_builddir)/src/json/libtalerjson.la \
   $(top_builddir)/src/util/libtalerutil.la \
diff --git a/src/exchangedb/test_exchangedb_populate_ready_deposit.c 
b/src/exchangedb/perf_deposits_get_ready.c
similarity index 57%
rename from src/exchangedb/test_exchangedb_populate_ready_deposit.c
rename to src/exchangedb/perf_deposits_get_ready.c
index 97273fc9..4ad08223 100644
--- a/src/exchangedb/test_exchangedb_populate_ready_deposit.c
+++ b/src/exchangedb/perf_deposits_get_ready.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2022 Taler Systems SA
+  Copyright (C) 2014-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -14,8 +14,8 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file exchangedb/test_exchangedb_populate_ready_deposit.c
- * @brief test cases for DB interaction functions
+ * @file exchangedb/perf_deposits_get_ready.c
+ * @brief benchmark for deposits_get_ready
  * @author Joseph Xu
  */
 #include "platform.h"
@@ -34,7 +34,7 @@ static int result;
  */
 #define FAILIF(cond)                            \
   do {                                          \
-      if (! (cond)) {break;}                    \
+    if (! (cond)) {break;}                    \
     GNUNET_break (0);                           \
     goto drop;                                  \
   } while (0)
@@ -57,21 +57,27 @@ static int result;
  */
 #define CURRENCY "EUR"
 #define RSA_KEY_SIZE 1024
-#define NUM_ROWS 1000000
-#define ROUNDS 10000
+#define NUM_ROWS 1000
+#define ROUNDS 100
 #define MELT_NEW_COINS 5
 #define MELT_NOREVEAL_INDEX 1
+
 /**
  * Database plugin under test.
  */
 static struct TALER_EXCHANGEDB_Plugin *plugin;
+
 static struct TALER_DenomFeeSet fees;
+
 static struct TALER_MerchantWireHashP h_wire_wt;
+
 /**
  * Denomination keys used for fresh coins in melt test.
  */
 static struct DenomKeyPair **new_dkp;
+
 static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
+
 struct DenomKeyPair
 {
   struct TALER_DenominationPrivateKey priv;
@@ -173,8 +179,6 @@ create_denom_key_pair (unsigned int size,
 }
 
 
-
-
 /**
  * Main function that will be run by the scheduler.
  *
@@ -191,19 +195,19 @@ run (void *cls)
   struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
   struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
   struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
-  unsigned long long sqrs=0;
-  struct TALER_EXCHANGEDB_Deposit *depos=NULL;
-  struct TALER_EXCHANGEDB_Refund *ref=NULL;
+  unsigned long long sqrs = 0;
+  struct TALER_EXCHANGEDB_Deposit *depos = NULL;
+  struct TALER_EXCHANGEDB_Refund *ref = NULL;
   unsigned int *perm;
   unsigned long long duration_sq;
   struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
   struct TALER_ExchangeWithdrawValues alg_values = {
     .cipher = TALER_DENOMINATION_RSA
-    };
+  };
 
-  ref = GNUNET_new_array (ROUNDS +1,
+  ref = GNUNET_new_array (ROUNDS + 1,
                           struct TALER_EXCHANGEDB_Refund);
-  depos = GNUNET_new_array (ROUNDS +1,
+  depos = GNUNET_new_array (ROUNDS + 1,
                             struct TALER_EXCHANGEDB_Deposit);
 
   if (NULL ==
@@ -245,194 +249,190 @@ run (void *cls)
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount (CURRENCY ":0.000010",
                                          &fees.refund));
-  //DENOMINATION
   {
     ZR_BLK (&cbc);
-    //PAIR KEY LIST
     new_dkp = GNUNET_new_array (MELT_NEW_COINS,
-                              struct DenomKeyPair *);
-    //PUBLIC KEY LIST
+                                struct DenomKeyPair *);
     new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
                                        struct TALER_DenominationPublicKey);
-    //REFRESH REVEAL COIN LIST
     revealed_coins
       = GNUNET_new_array (MELT_NEW_COINS,
                           struct TALER_EXCHANGEDB_RefreshRevealedCoin);
     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
-      {
-        struct GNUNET_TIME_Timestamp now;
-        struct TALER_BlindedRsaPlanchet *rp;
-        struct TALER_BlindedPlanchet *bp;
-
-        now = GNUNET_TIME_timestamp_get ();
-        //5 KEY PAIR
-        new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
-                                              now,
-                                              &value,
-                                              &fees);
-        GNUNET_assert (NULL != new_dkp[cnt]);
-        new_denom_pubs[cnt] = new_dkp[cnt]->pub;
-        ccoin = &revealed_coins[cnt];
-        bp = &ccoin->blinded_planchet;
-        bp->cipher = TALER_DENOMINATION_RSA;
-        rp = &bp->details.rsa_blinded_planchet;
-        rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
-                                                                      
GNUNET_CRYPTO_QUALITY_WEAK,
-                                                                      
(RSA_KEY_SIZE / 8) - 1);
-        rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
-        GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
-                                    rp->blinded_msg,
-                                    rp->blinded_msg_size);
-        TALER_denom_pub_hash (&new_dkp[cnt]->pub,
-                              &ccoin->h_denom_pub);
-        ccoin->exchange_vals = alg_values;
-        TALER_coin_ev_hash (bp,
-                            &ccoin->h_denom_pub,
-                            &ccoin->coin_envelope_hash);
-        GNUNET_assert (GNUNET_OK ==
+    {
+      struct GNUNET_TIME_Timestamp now;
+      struct TALER_BlindedRsaPlanchet *rp;
+      struct TALER_BlindedPlanchet *bp;
+
+      now = GNUNET_TIME_timestamp_get ();
+      new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
+                                            now,
+                                            &value,
+                                            &fees);
+      GNUNET_assert (NULL != new_dkp[cnt]);
+      new_denom_pubs[cnt] = new_dkp[cnt]->pub;
+      ccoin = &revealed_coins[cnt];
+      bp = &ccoin->blinded_planchet;
+      bp->cipher = TALER_DENOMINATION_RSA;
+      rp = &bp->details.rsa_blinded_planchet;
+      rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
+        GNUNET_CRYPTO_QUALITY_WEAK,
+        (RSA_KEY_SIZE / 8) - 1);
+      rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
+      GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                  rp->blinded_msg,
+                                  rp->blinded_msg_size);
+      TALER_denom_pub_hash (&new_dkp[cnt]->pub,
+                            &ccoin->h_denom_pub);
+      ccoin->exchange_vals = alg_values;
+      TALER_coin_ev_hash (bp,
+                          &ccoin->h_denom_pub,
+                          &ccoin->coin_envelope_hash);
+      GNUNET_assert (GNUNET_OK ==
                      TALER_denom_sign_blinded (&ccoin->coin_sig,
                                                &new_dkp[cnt]->priv,
                                                true,
                                                bp));
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_coin_ev_hash (bp,
-                                           &cbc.denom_pub_hash,
-                                           &cbc.h_coin_envelope));
-        GNUNET_assert (
-                       GNUNET_OK ==
-                       TALER_denom_sign_blinded (
-                                                 &cbc.sig,
-                                                 &new_dkp[cnt]->priv,
-                                                 false,
-                                                 bp));
-      }
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_coin_ev_hash (bp,
+                                         &cbc.denom_pub_hash,
+                                         &cbc.h_coin_envelope));
+      GNUNET_assert (
+        GNUNET_OK ==
+        TALER_denom_sign_blinded (
+          &cbc.sig,
+          &new_dkp[cnt]->priv,
+          false,
+          bp));
+    }
   }
   perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
                                        NUM_ROWS);
-  //BEGIN
   FAILIF (GNUNET_OK !=
           plugin->start (plugin->cls,
                          "Transaction"));
   for (unsigned int j = 0; j < NUM_ROWS; j++)
+  {
+    /*** NEED TO INSERT REFRESH COMMITMENTS + ENSURECOIN ***/
+    union TALER_DenominationBlindingKeyP bks;
+    struct GNUNET_TIME_Timestamp deadline;
+    struct TALER_CoinSpendPublicKeyP coin_pub;
+    struct TALER_ReservePublicKeyP reserve_pub;
+    struct TALER_CoinPubHashP c_hash;
+    unsigned int k = (unsigned int) rand () % 5;
+    unsigned int i = perm[j];
+    if (i >= ROUNDS)
+      i = ROUNDS;   /* throw-away slot, do not keep around */
+    depos[i].deposit_fee = fees.deposit;
+    RND_BLK (&coin_pub);
+    RND_BLK (&c_hash);
+    RND_BLK (&reserve_pub);
+    RND_BLK (&cbc.reserve_sig);
+    TALER_denom_pub_hash (&new_dkp[k]->pub,
+                          &cbc.denom_pub_hash);
+    deadline = GNUNET_TIME_timestamp_get ();
+    RND_BLK (&depos[i].coin.coin_pub);
+    TALER_denom_pub_hash (&new_dkp[k]->pub,
+                          &depos[i].coin.denom_pub_hash);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
+                                            &ccoin->coin_sig,
+                                            &bks,
+                                            &c_hash,
+                                            &alg_values,
+                                            &new_dkp[k]->pub));
+    RND_BLK (&depos[i].merchant_pub);
+    RND_BLK (&depos[i].csig);
+    RND_BLK (&depos[i].h_contract_terms);
+    RND_BLK (&depos[i].wire_salt);
+    depos[i].amount_with_fee = value;
+    depos[i].refund_deadline = deadline;
+    depos[i].wire_deadline = deadline;
+    depos[i].receiver_wire_account =
+      "payto://iban/DE67830654080004822650?receiver-name=Test";
+    TALER_merchant_wire_signature_hash (
+      "payto://iban/DE67830654080004822650?receiver-name=Test",
+      &depos[i].wire_salt,
+      &h_wire_wt);
+    cbc.reserve_pub = reserve_pub;
+    cbc.amount_with_fee = value;
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_amount_set_zero (CURRENCY,
+                                          &cbc.withdraw_fee));
     {
-      /*** NEED TO INSERT REFRESH COMMITMENTS + ENSURECOIN ***/
-      union TALER_DenominationBlindingKeyP bks;
-      struct GNUNET_TIME_Timestamp deadline;
-      struct TALER_CoinSpendPublicKeyP coin_pub;
-      struct TALER_ReservePublicKeyP reserve_pub;
-      struct TALER_CoinPubHashP c_hash;
-      unsigned int k = (unsigned int)rand()%5;
-      unsigned int i = perm[j];
-      if (i >= ROUNDS)
-        i = ROUNDS; /* throw-away slot, do not keep around */
-      depos[i].deposit_fee = fees.deposit;
-      RND_BLK (&coin_pub);
-      RND_BLK (&c_hash);
-      RND_BLK (&reserve_pub);
-      RND_BLK (&cbc.reserve_sig);
-      TALER_denom_pub_hash (&new_dkp[k]->pub,
-                            &cbc.denom_pub_hash);
-      deadline = GNUNET_TIME_timestamp_get ();
-      RND_BLK (&depos[i].coin.coin_pub);
-      TALER_denom_pub_hash (&new_dkp[k]->pub,
-                            &depos[i].coin.denom_pub_hash);
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
-                                              &ccoin->coin_sig,
-                                              &bks,
-                                              &c_hash,
-                                              &alg_values,
-                                              &new_dkp[k]->pub));
-      RND_BLK (&depos[i].merchant_pub);
-      RND_BLK (&depos[i].csig);
-      RND_BLK (&depos[i].h_contract_terms);
-      RND_BLK (&depos[i].wire_salt);
-      depos[i].amount_with_fee = value;
-      depos[i].refund_deadline = deadline;
-      depos[i].wire_deadline = deadline;
-      depos[i].receiver_wire_account =
-        "payto://iban/DE67830654080004822650?receiver-name=Test";
-      TALER_merchant_wire_signature_hash (
-                                          
"payto://iban/DE67830654080004822650?receiver-name=Test",
-                                          &depos[i].wire_salt,
-                                          &h_wire_wt);
-      cbc.reserve_pub = reserve_pub;
-      cbc.amount_with_fee = value;
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_set_zero (CURRENCY,
-                                            &cbc.withdraw_fee));
-      {
-        /* INSERT WIRE TARGETS */
-        bool found;
-        bool nonce_ok;
-        bool balance_ok;
-        uint64_t ruuid;
-        struct GNUNET_TIME_Timestamp now;
-        now = GNUNET_TIME_timestamp_get ();
-        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-                plugin->do_withdraw (plugin->cls,
-                                     NULL,
-                                     &cbc,
-                                     now,
-                                     &found,
-                                     &balance_ok,
-                                     &nonce_ok,
-                                     &ruuid));
-      }
-      {
-        /* ENSURE_COIN_KNOWN */
-        uint64_t known_coin_id;
-        struct TALER_DenominationHashP dph;
-        struct TALER_AgeCommitmentHash agh;
-        FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
-                plugin->ensure_coin_known (plugin->cls,
-                                           &depos[i].coin,
-                                           &known_coin_id,
-                                           &dph,
-                                           &agh));
-        refresh.coin = depos[i].coin;
-        RND_BLK (&refresh.coin_sig);
-        RND_BLK (&refresh.rc);
-        refresh.amount_with_fee = value;
-        refresh.noreveal_index = MELT_NOREVEAL_INDEX;
-      }
-        /*STORE INTO DEPOSIT*/
-      {
-        struct GNUNET_TIME_Timestamp now;
-        now = GNUNET_TIME_timestamp_get ();
-        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-                plugin->insert_deposit (plugin->cls,
-                                        now,
-                                        &depos[i]));
-      }
-      if (ROUNDS == i)
-        TALER_denom_sig_free (&depos[i].coin.denom_sig);
+      bool found;
+      bool nonce_ok;
+      bool balance_ok;
+      uint64_t ruuid;
+      struct GNUNET_TIME_Timestamp now;
+
+      now = GNUNET_TIME_timestamp_get ();
+      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+              plugin->do_withdraw (plugin->cls,
+                                   NULL,
+                                   &cbc,
+                                   now,
+                                   &found,
+                                   &balance_ok,
+                                   &nonce_ok,
+                                   &ruuid));
     }
-  /* End of benchmark setup */
-  GNUNET_free(perm);
-  // commit
+    {
+      /* ENSURE_COIN_KNOWN */
+      uint64_t known_coin_id;
+      struct TALER_DenominationHashP dph;
+      struct TALER_AgeCommitmentHash agh;
+      FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
+              plugin->ensure_coin_known (plugin->cls,
+                                         &depos[i].coin,
+                                         &known_coin_id,
+                                         &dph,
+                                         &agh));
+      refresh.coin = depos[i].coin;
+      RND_BLK (&refresh.coin_sig);
+      RND_BLK (&refresh.rc);
+      refresh.amount_with_fee = value;
+      refresh.noreveal_index = MELT_NOREVEAL_INDEX;
+    }
+    {
+      struct GNUNET_TIME_Timestamp now;
+
+      now = GNUNET_TIME_timestamp_get ();
+      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+              plugin->insert_deposit (plugin->cls,
+                                      now,
+                                      &depos[i]));
+    }
+    if (ROUNDS == i)
+      TALER_denom_sig_free (&depos[i].coin.denom_sig);
+  }
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->commit (plugin->cls));
+  GNUNET_free (perm);
+  /* End of benchmark setup */
+
   /**** CALL GET READY DEPOSIT ****/
-  for (unsigned int r=0; r< ROUNDS; r++)
+  for (unsigned int r = 0; r< ROUNDS; r++)
   {
     struct GNUNET_TIME_Absolute time;
     struct GNUNET_TIME_Relative duration;
     struct TALER_MerchantPublicKeyP merchant_pub;
     char *payto_uri;
-    time = GNUNET_TIME_absolute_get();
-    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-            plugin->get_ready_deposit (plugin->cls,
-                                       0,
-                                       INT32_MAX,
-                                       &merchant_pub,
-                                       &payto_uri));
+    enum GNUNET_DB_QueryStatus qs;
 
+    time = GNUNET_TIME_absolute_get ();
+    qs = plugin->get_ready_deposit (plugin->cls,
+                                    0,
+                                    INT32_MAX,
+                                    &merchant_pub,
+                                    &payto_uri);
+    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs);
     duration = GNUNET_TIME_absolute_get_duration (time);
     times = GNUNET_TIME_relative_add (times,
                                       duration);
     duration_sq = duration.rel_value_us * duration.rel_value_us;
-    GNUNET_assert (duration_sq / duration.rel_value_us == 
duration.rel_value_us);
+    GNUNET_assert (duration_sq / duration.rel_value_us ==
+                   duration.rel_value_us);
     GNUNET_assert (sqrs + duration_sq >= sqrs);
     sqrs += duration_sq;
   }
@@ -447,15 +447,14 @@ run (void *cls)
                                        ROUNDS);
     avg_dbl = avg.rel_value_us;
     variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
-    fprintf(stdout,
-            "%8llu ± %6.0f\n",
-            (unsigned long long) avg.rel_value_us,
-            sqrt (variance / (ROUNDS-1)));
+    fprintf (stdout,
+             "%8llu ± %6.0f\n",
+             (unsigned long long) avg.rel_value_us,
+             sqrt (variance / (ROUNDS - 1)));
   }
   result = 0;
 drop:
-  GNUNET_break (GNUNET_OK ==
-  plugin->drop_tables (plugin->cls));
+  // GNUNET_break (GNUNET_OK == plugin->drop_tables (plugin->cls));
 cleanup:
   if (NULL != revealed_coins)
   {
@@ -473,12 +472,12 @@ cleanup:
        cnt++)
     destroy_denom_key_pair (new_dkp[cnt]);
   GNUNET_free (new_dkp);
-  for (unsigned int i=0; i< ROUNDS ; i++)
-    {
-      TALER_denom_sig_free (&depos[i].coin.denom_sig);
-    }
-  GNUNET_free(depos);
-  GNUNET_free(ref);
+  for (unsigned int i = 0; i< ROUNDS; i++)
+  {
+    TALER_denom_sig_free (&depos[i].coin.denom_sig);
+  }
+  GNUNET_free (depos);
+  GNUNET_free (ref);
   TALER_EXCHANGEDB_plugin_unload (plugin);
   plugin = NULL;
 }
@@ -490,7 +489,6 @@ main (int argc,
 {
   const char *plugin_name;
   char *config_filename;
-  char *testname;
   struct GNUNET_CONFIGURATION_Handle *cfg;
 
   (void) argc;
@@ -504,15 +502,17 @@ main (int argc,
                     "WARNING",
                     NULL);
   plugin_name++;
-  (void) GNUNET_asprintf (&testname,
-                          "test-exchange-db-%s",
-                          plugin_name);
-  (void) GNUNET_asprintf (&config_filename,
-                          "%s.conf",
-                          testname);
-  fprintf (stdout,
-           "Using config: %s\n",
-           config_filename);
+  {
+    char *testname;
+
+    GNUNET_asprintf (&testname,
+                     "test-exchange-db-%s",
+                     plugin_name);
+    GNUNET_asprintf (&config_filename,
+                     "%s.conf",
+                     testname);
+    GNUNET_free (testname);
+  }
   cfg = GNUNET_CONFIGURATION_create ();
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_parse (cfg,
@@ -520,16 +520,14 @@ main (int argc,
   {
     GNUNET_break (0);
     GNUNET_free (config_filename);
-    GNUNET_free (testname);
     return 2;
   }
   GNUNET_SCHEDULER_run (&run,
                         cfg);
   GNUNET_CONFIGURATION_destroy (cfg);
   GNUNET_free (config_filename);
-  GNUNET_free (testname);
   return result;
 }
 
 
-/* end of test_exchangedb_by_j.c */
+/* end of perf_deposits_get_ready.c */
diff --git a/src/exchangedb/test_exchangedb_populate_link_data.c 
b/src/exchangedb/perf_get_link_data.c
similarity index 71%
rename from src/exchangedb/test_exchangedb_populate_link_data.c
rename to src/exchangedb/perf_get_link_data.c
index 84e5ab88..eb1f5f6e 100644
--- a/src/exchangedb/test_exchangedb_populate_link_data.c
+++ b/src/exchangedb/perf_get_link_data.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2022 Taler Systems SA
+  Copyright (C) 2014-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -14,8 +14,8 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file exchangedb/test_exchangedb_populate_link_data.c
- * @brief test cases for DB interaction functions
+ * @file exchangedb/perf_get_link_data.c
+ * @brief benchmark for get_link_data
  * @author Joseph Xu
  */
 #include "platform.h"
@@ -29,7 +29,7 @@
  */
 #define FAILIF(cond)                            \
   do {                                          \
-      if (! (cond)) {break;}                    \
+    if (! (cond)) {break;}                    \
     GNUNET_break (0);                           \
     goto drop;                                  \
   } while (0)
@@ -166,6 +166,8 @@ create_denom_key_pair (unsigned int size,
   }
   return dkp;
 }
+
+
 /**
  * Function called with the session hashes and transfer secret
  * information for a given coin.
@@ -199,22 +201,22 @@ run (void *cls)
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   const uint32_t num_partitions = 10;
   struct DenomKeyPair *dkp = NULL;
-  struct TALER_EXCHANGEDB_Deposit *depos=NULL;
+  struct TALER_EXCHANGEDB_Deposit *depos = NULL;
   struct TALER_Amount value;
   struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
-  unsigned long long sqrs=0;
-  struct TALER_EXCHANGEDB_Refund *ref=NULL;
+  unsigned long long sqrs = 0;
+  struct TALER_EXCHANGEDB_Refund *ref = NULL;
   unsigned int *perm;
   unsigned long long duration_sq;
   struct TALER_ExchangeWithdrawValues alg_values = {
     .cipher = TALER_DENOMINATION_RSA
-    };
+  };
 
-  ref = GNUNET_new_array (ROUNDS +1,
+  ref = GNUNET_new_array (ROUNDS + 1,
                           struct TALER_EXCHANGEDB_Refund);
-  depos = GNUNET_new_array (ROUNDS +1,
+  depos = GNUNET_new_array (ROUNDS + 1,
                             struct TALER_EXCHANGEDB_Deposit);
-  refresh = GNUNET_new_array (ROUNDS +1,
+  refresh = GNUNET_new_array (ROUNDS + 1,
                               struct TALER_EXCHANGEDB_Refresh);
 
   if (NULL ==
@@ -256,16 +258,14 @@ run (void *cls)
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount (CURRENCY ":0.000010",
                                          &fees.refund));
-  //DENOMINATION
   {
-    //PAIR KEY LIST
     new_dkp = GNUNET_new_array (MELT_NEW_COINS,
                                 struct DenomKeyPair *);
 
     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
     {
       struct GNUNET_TIME_Timestamp now = GNUNET_TIME_timestamp_get ();
-      
+
       new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
                                             now,
                                             &value,
@@ -275,7 +275,6 @@ run (void *cls)
   }
   perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
                                        NUM_ROWS);
-  //BEGIN
   FAILIF (GNUNET_OK !=
           plugin->start (plugin->cls,
                          "Transaction"));
@@ -290,89 +289,96 @@ run (void *cls)
       i = ROUNDS; /* throw-away slot, do not keep around */
     RND_BLK (&depos[i].coin.coin_pub);
     ZR_BLK (&cbc);
-    TALER_denom_pub_hash (&new_dkp[(unsigned int)rand()%MELT_NEW_COINS]->pub,
+    TALER_denom_pub_hash (&new_dkp[(unsigned int) rand ()
+                                   % MELT_NEW_COINS]->pub,
                           &depos[i].coin.denom_pub_hash);
 
 
-    
     {
-      struct TALER_EXCHANGEDB_RefreshRevealedCoin 
revealed_coins[MELT_NEW_COINS];
-      
-      for (unsigned int p=0;p<MELT_NEW_COINS;p++)
-        {
-          struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coin = 
&revealed_coins[p];
-          struct TALER_BlindedPlanchet *bp = &revealed_coin->blinded_planchet;
-          struct TALER_BlindedRsaPlanchet *rp = 
&bp->details.rsa_blinded_planchet;
-          
-          /* h_coin_ev must be unique, but we only have MELT_NEW_COINS created
-             above for NUM_ROWS iterations; instead of making "all new" coins,
-             we simply randomize the hash here as nobody is checking for 
consistency
-             anyway ;-) */
-          bp->cipher = TALER_DENOMINATION_RSA;
-          rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
-                                                                        
GNUNET_CRYPTO_QUALITY_WEAK,
-                                                                        
(RSA_KEY_SIZE / 8) - 1);
-          rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
-          GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
-                                      rp->blinded_msg,
-                                      rp->blinded_msg_size);
-          TALER_denom_pub_hash (&new_dkp[(unsigned 
int)rand()%MELT_NEW_COINS]->pub,
-                                &revealed_coin->h_denom_pub);
-          revealed_coin->exchange_vals = alg_values;
-          TALER_coin_ev_hash (bp,
-                              &revealed_coin->h_denom_pub,
-                              &revealed_coin->coin_envelope_hash); 
-          GNUNET_assert (GNUNET_OK ==
-                         TALER_denom_sign_blinded (&revealed_coin->coin_sig,
-                                                   &new_dkp[(unsigned 
int)rand()%MELT_NEW_COINS]->priv,
-                                                   true,
-                                                   bp));
-          GNUNET_assert (
-                         GNUNET_OK ==
-                         TALER_denom_sign_blinded (
-                                                   &cbc.sig,
-                                                   &new_dkp[(unsigned 
int)rand()%MELT_NEW_COINS]->priv,
-                                                   false,
-                                                   bp));
-        }
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
-                                            &cbc.sig,
-                                            &bks,
-                                            &c_hash,
-                                            &alg_values,
-                                            &new_dkp[(unsigned 
int)rand()%MELT_NEW_COINS]->pub));
-    {
-      /* ENSURE_COIN_KNOWN */
-      struct TALER_DenominationHashP dph;
-      struct TALER_AgeCommitmentHash agh;
-      bool zombie_required = false;
-      bool balance_ok;
-
-      FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
-              plugin->ensure_coin_known (plugin->cls,
-                                         &depos[i].coin,
-                                         &known_coin_id,
-                                         &dph,
-                                         &agh));
-      /**** INSERT REFRESH COMMITMENTS ****/
-      refresh[i].coin = depos[i].coin;
-      RND_BLK (&refresh[i].coin_sig);
-      RND_BLK (&refresh[i].rc);
-      refresh[i].amount_with_fee = value;
-      refresh[i].noreveal_index = MELT_NOREVEAL_INDEX;
-      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-              plugin->do_melt (plugin->cls,
-                               NULL,
-                               &refresh[i],
-                               known_coin_id,
-                               &zombie_required,
-                               &balance_ok));
-    }
+      struct TALER_EXCHANGEDB_RefreshRevealedCoin
+        revealed_coins[MELT_NEW_COINS];
+
+      for (unsigned int p = 0; p<MELT_NEW_COINS; p++)
+      {
+        struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coin =
+          &revealed_coins[p];
+        struct TALER_BlindedPlanchet *bp = &revealed_coin->blinded_planchet;
+        struct TALER_BlindedRsaPlanchet *rp = 
&bp->details.rsa_blinded_planchet;
+
+        /* h_coin_ev must be unique, but we only have MELT_NEW_COINS created
+           above for NUM_ROWS iterations; instead of making "all new" coins,
+           we simply randomize the hash here as nobody is checking for 
consistency
+           anyway ;-) */
+        bp->cipher = TALER_DENOMINATION_RSA;
+        rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
+          GNUNET_CRYPTO_QUALITY_WEAK,
+          (RSA_KEY_SIZE / 8) - 1);
+        rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
+        GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                    rp->blinded_msg,
+                                    rp->blinded_msg_size);
+        TALER_denom_pub_hash (&new_dkp[(unsigned int) rand ()
+                                       % MELT_NEW_COINS]->pub,
+                              &revealed_coin->h_denom_pub);
+        revealed_coin->exchange_vals = alg_values;
+        TALER_coin_ev_hash (bp,
+                            &revealed_coin->h_denom_pub,
+                            &revealed_coin->coin_envelope_hash);
+        GNUNET_assert (GNUNET_OK ==
+                       TALER_denom_sign_blinded (&revealed_coin->coin_sig,
+                                                 &new_dkp[(unsigned
+                                                           int) rand ()
+                                                          % MELT_NEW_COINS]->
+                                                 priv,
+                                                 true,
+                                                 bp));
+        GNUNET_assert (
+          GNUNET_OK ==
+          TALER_denom_sign_blinded (
+            &cbc.sig,
+            &new_dkp[(unsigned int) rand () % MELT_NEW_COINS]->priv,
+            false,
+            bp));
+      }
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
+                                              &cbc.sig,
+                                              &bks,
+                                              &c_hash,
+                                              &alg_values,
+                                              &new_dkp[(unsigned int) rand ()
+                                                       % 
MELT_NEW_COINS]->pub));
+      {
+        /* ENSURE_COIN_KNOWN */
+        struct TALER_DenominationHashP dph;
+        struct TALER_AgeCommitmentHash agh;
+        bool zombie_required = false;
+        bool balance_ok;
+
+        FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
+                plugin->ensure_coin_known (plugin->cls,
+                                           &depos[i].coin,
+                                           &known_coin_id,
+                                           &dph,
+                                           &agh));
+        /**** INSERT REFRESH COMMITMENTS ****/
+        refresh[i].coin = depos[i].coin;
+        RND_BLK (&refresh[i].coin_sig);
+        RND_BLK (&refresh[i].rc);
+        refresh[i].amount_with_fee = value;
+        refresh[i].noreveal_index = MELT_NOREVEAL_INDEX;
+        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+                plugin->do_melt (plugin->cls,
+                                 NULL,
+                                 &refresh[i],
+                                 known_coin_id,
+                                 &zombie_required,
+                                 &balance_ok));
+      }
       /****GET melt_serial_id generated by default****/
       {
         struct TALER_EXCHANGEDB_Melt ret_refresh_session;
-        
+
         FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
                 plugin->get_melt (plugin->cls,
                                   &refresh[i].rc,
@@ -382,7 +388,7 @@ run (void *cls)
       /**** INSERT REFRESH_REVEAL + TRANSFER_KEYS *****/
       {
         static unsigned int cnt;
-        
+
         RND_BLK (&tprivs);
         RND_BLK (&tpub);
         FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
@@ -398,14 +404,14 @@ run (void *cls)
       }
       for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
       {
-          TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
-          TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet);
+        TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
+        TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet);
       }
-    
+
       /*      {
         struct TALER_CoinSpendPublicKeyP ocp;
         uint64_t rrc_serial;
-        
+
         FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
                 plugin->get_old_coin_by_h_blind (plugin->cls,
                                                  
&revealed_coins->coin_envelope_hash,
@@ -417,17 +423,15 @@ run (void *cls)
       TALER_denom_sig_free (&depos[i].coin.denom_sig);
   }
   /* End of benchmark setup */
-  GNUNET_free(perm);
-  // commit
+  GNUNET_free (perm);
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->commit (plugin->cls));
-  /**** CALL GET LINK DATA ****/
-  for (unsigned int r=0; r< ROUNDS; r++)
+  for (unsigned int r = 0; r< ROUNDS; r++)
   {
     struct GNUNET_TIME_Absolute time;
     struct GNUNET_TIME_Relative duration;
     enum GNUNET_DB_QueryStatus qs;
-    time = GNUNET_TIME_absolute_get();
+    time = GNUNET_TIME_absolute_get ();
 
     qs = plugin->get_link_data (plugin->cls,
                                 &refresh[r].coin.coin_pub,
@@ -439,7 +443,8 @@ run (void *cls)
     times = GNUNET_TIME_relative_add (times,
                                       duration);
     duration_sq = duration.rel_value_us * duration.rel_value_us;
-    GNUNET_assert (duration_sq / duration.rel_value_us == 
duration.rel_value_us);
+    GNUNET_assert (duration_sq / duration.rel_value_us ==
+                   duration.rel_value_us);
     GNUNET_assert (sqrs + duration_sq >= sqrs);
     sqrs += duration_sq;
   }
@@ -454,10 +459,10 @@ run (void *cls)
                                        ROUNDS);
     avg_dbl = avg.rel_value_us;
     variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
-    fprintf(stdout,
-            "%8llu ± %6.0f\n",
-            (unsigned long long) avg.rel_value_us,
-            sqrt (variance / (ROUNDS-1)));
+    fprintf (stdout,
+             "%8llu ± %6.0f\n",
+             (unsigned long long) avg.rel_value_us,
+             sqrt (variance / (ROUNDS - 1)));
   }
   result = 0;
 drop:
@@ -470,13 +475,13 @@ cleanup:
        cnt++)
     destroy_denom_key_pair (new_dkp[cnt]);
   GNUNET_free (new_dkp);
-  for (unsigned int i=0; i< ROUNDS; i++)
-    {
-      TALER_denom_sig_free (&depos[i].coin.denom_sig);
-    }
-  GNUNET_free(depos);
-  GNUNET_free(ref);
-  GNUNET_free(refresh);
+  for (unsigned int i = 0; i< ROUNDS; i++)
+  {
+    TALER_denom_sig_free (&depos[i].coin.denom_sig);
+  }
+  GNUNET_free (depos);
+  GNUNET_free (ref);
+  GNUNET_free (refresh);
   dkp = NULL;
   TALER_EXCHANGEDB_plugin_unload (plugin);
   plugin = NULL;
@@ -509,9 +514,6 @@ main (int argc,
   (void) GNUNET_asprintf (&config_filename,
                           "%s.conf",
                           testname);
-  fprintf (stdout,
-           "Using config: %s\n",
-           config_filename);
   cfg = GNUNET_CONFIGURATION_create ();
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_parse (cfg,
diff --git a/src/exchangedb/perf_exchangedb_reserves_in_insert.c 
b/src/exchangedb/perf_reserves_in_insert.c
similarity index 53%
rename from src/exchangedb/perf_exchangedb_reserves_in_insert.c
rename to src/exchangedb/perf_reserves_in_insert.c
index fc2a0008..9f3ed460 100644
--- a/src/exchangedb/perf_exchangedb_reserves_in_insert.c
+++ b/src/exchangedb/perf_reserves_in_insert.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2022 Taler Systems SA
+  Copyright (C) 2014-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -14,8 +14,8 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file exchangedb/test_exchangedb_by_j.c
- * @brief test cases for DB interaction functions
+ * @file exchangedb/perf_reserves_in_insert.c
+ * @brief benchmark for 'reserves_in_insert'
  * @author Joseph Xu
  */
 #include "platform.h"
@@ -23,6 +23,7 @@
 #include "taler_json_lib.h"
 #include "taler_exchangedb_plugin.h"
 
+
 /**
  * Global result from the testcase.
  */
@@ -33,7 +34,7 @@ static int result;
  */
 #define FAILIF(cond)                            \
   do {                                          \
-    if (! (cond)) { break;}                     \
+    if (! (cond)) {break;}                    \
     GNUNET_break (0);                           \
     goto drop;                                  \
   } while (0)
@@ -51,6 +52,10 @@ static int result;
 #define ZR_BLK(ptr) \
   memset (ptr, 0, sizeof (*ptr))
 
+/**
+ * How many rounds do we average over?
+ */
+#define ROUNDS 5
 
 /**
  * Currency we use.  Must match test-exchange-db-*.conf.
@@ -73,6 +78,10 @@ run (void *cls)
 {
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   const uint32_t num_partitions = 10;
+  static unsigned int batches[] = {1, 1, 2, 3, 4, 16, 32 };
+  const unsigned int lcm = 3 * 32;
+  struct GNUNET_TIME_Relative times[sizeof (batches) / sizeof(*batches)];
+  unsigned long long sqrs[sizeof (batches) / sizeof(*batches)];
 
   if (NULL ==
       (plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
@@ -91,46 +100,78 @@ run (void *cls)
     result = 77;
     goto cleanup;
   }
-  for (unsigned int i = 0; i< 8; i++)
+
+  memset (times, 0, sizeof (times));
+  memset (sqrs, 0, sizeof (sqrs));
+  for (unsigned int r = 0; r < ROUNDS; r++)
   {
-    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];
-    struct GNUNET_TIME_Absolute now;
-    struct GNUNET_TIME_Timestamp ts;
-    struct GNUNET_TIME_Relative duration;
-    struct TALER_ReservePublicKeyP reserve_pub;
-
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_string_to_amount (CURRENCY ":1.000010",
-                                           &value));
-    now = GNUNET_TIME_absolute_get ();
-    ts = GNUNET_TIME_timestamp_get ();
-    for (unsigned int r = 0; r<10; r++)
+    for (unsigned int i = 0;
+         i< sizeof(batches) / sizeof(*batches);
+         i++)
     {
-      plugin->start (plugin->cls,
-                     "test_by_exchange_j");
-      for (unsigned int k = 0; k<batch_size; k++)
+      unsigned int batch_size = batches[i];
+      struct TALER_Amount value;
+      struct GNUNET_TIME_Absolute now;
+      struct GNUNET_TIME_Timestamp ts;
+      unsigned long long duration_sq;
+      struct GNUNET_TIME_Relative duration;
+
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_string_to_amount (CURRENCY ":1.000010",
+                                             &value));
+      now = GNUNET_TIME_absolute_get ();
+      ts = GNUNET_TIME_timestamp_get ();
       {
-        RND_BLK (&reserve_pub);
-        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+        const char *sndr = "payto://x-taler-bank/localhost:8080/1";
+        struct TALER_ReservePublicKeyP reserve_pubs[lcm];
+        struct TALER_EXCHANGEDB_ReserveInInfo reserves[lcm];
+        enum GNUNET_DB_QueryStatus results[lcm];
+
+        for (unsigned int k = 0; k<lcm; k++)
+        {
+          RND_BLK (&reserve_pubs[k]);
+          reserves[k].reserve_pub = &reserve_pubs[k];
+          reserves[k].balance = &value;
+          reserves[k].execution_time = ts;
+          reserves[k].sender_account_details = sndr;
+          reserves[k].exchange_account_name = "name";
+          reserves[k].wire_reference = k;
+        }
+        FAILIF (lcm !=
                 plugin->reserves_in_insert (plugin->cls,
-                                            &reserve_pub,
-                                            &value,
-                                            ts,
-                                            sndr,
-                                            "section",
-                                            4));
+                                            reserves,
+                                            lcm,
+                                            batch_size,
+                                            results));
       }
-      plugin->commit (plugin->cls);
-    }
-    duration = GNUNET_TIME_absolute_get_duration (now);
+      duration = GNUNET_TIME_absolute_get_duration (now);
+      times[i] = GNUNET_TIME_relative_add (times[i],
+                                           duration);
+      duration_sq = duration.rel_value_us * duration.rel_value_us;
+      GNUNET_assert (duration_sq / duration.rel_value_us ==
+                     duration.rel_value_us);
+      GNUNET_assert (sqrs[i] + duration_sq >= sqrs[i]);
+      sqrs[i] += duration_sq;
+    } /* for 'i' batch size */
+  } /* for 'r' ROUNDS */
+
+  for (unsigned int i = 0;
+       i< sizeof(batches) / sizeof(*batches);
+       i++)
+  {
+    struct GNUNET_TIME_Relative avg;
+    double avg_dbl;
+    double variance;
+
+    avg = GNUNET_TIME_relative_divide (times[i],
+                                       ROUNDS);
+    avg_dbl = avg.rel_value_us;
+    variance = sqrs[i] - (avg_dbl * avg_dbl * ROUNDS);
     fprintf (stdout,
-             "for a batchsize equal to %d it took %s\n",
-             batch_size,
-             GNUNET_STRINGS_relative_time_to_string (duration,
-                                                     GNUNET_NO) );
+             "Batch[%2u]: %8llu ± %6.0f\n",
+             batches[i],
+             (unsigned long long) avg.rel_value_us,
+             sqrt (variance / (ROUNDS - 1)));
   }
   result = 0;
 drop:
@@ -150,7 +191,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) '-')))
@@ -158,6 +198,7 @@ main (int argc,
     GNUNET_break (0);
     return -1;
   }
+
   GNUNET_log_setup (argv[0],
                     "WARNING",
                     NULL);
@@ -168,9 +209,6 @@ main (int argc,
   (void) GNUNET_asprintf (&config_filename,
                           "%s.conf",
                           testname);
-  fprintf (stdout,
-           "Using config: %s\n",
-           config_filename);
   cfg = GNUNET_CONFIGURATION_create ();
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_parse (cfg,
@@ -190,4 +228,4 @@ main (int argc,
 }
 
 
-/* end of test_exchangedb_by_j.c */
+/* end of perf_reserves_in_insert.c */
diff --git a/src/exchangedb/test_exchangedb_populate_select_refunds_by_coin.c 
b/src/exchangedb/perf_select_refunds_by_coin.c
similarity index 71%
rename from src/exchangedb/test_exchangedb_populate_select_refunds_by_coin.c
rename to src/exchangedb/perf_select_refunds_by_coin.c
index c094b204..85c92f4b 100644
--- a/src/exchangedb/test_exchangedb_populate_select_refunds_by_coin.c
+++ b/src/exchangedb/perf_select_refunds_by_coin.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2022 Taler Systems SA
+  Copyright (C) 2014-2023 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -14,8 +14,8 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file exchangedb/test_exchangedb_populate_table.c
- * @brief test cases for DB interaction functions
+ * @file exchangedb/perf_select_refunds_by_coin.c
+ * @brief benchmark for select_refunds_by_coin
  * @author Joseph Xu
  */
 #include "platform.h"
@@ -34,7 +34,7 @@ static int result;
  */
 #define FAILIF(cond)                            \
   do {                                          \
-      if (! (cond)) {break;}                    \
+    if (! (cond)) {break;}                    \
     GNUNET_break (0);                           \
     goto drop;                                  \
   } while (0)
@@ -56,24 +56,31 @@ static int result;
  */
 #define CURRENCY "EUR"
 #define RSA_KEY_SIZE 1024
-#define ROUNDS 10000
-#define NUM_ROWS 1000000
+#define ROUNDS 100
+#define NUM_ROWS 1000
 #define MELT_NEW_COINS 5
 #define MELT_NOREVEAL_INDEX 1
+
 /**
  * Database plugin under test.
  */
 static struct TALER_EXCHANGEDB_Plugin *plugin;
+
 static struct TALER_DenomFeeSet fees;
+
 static struct TALER_MerchantWireHashP h_wire_wt;
+
 static struct DenomKeyPair **new_dkp;
+
 static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
+
 struct DenomKeyPair
 {
   struct TALER_DenominationPrivateKey priv;
   struct TALER_DenominationPublicKey pub;
 };
 
+
 /**
  * Destroy a denomination key pair.  The key is not necessarily removed from 
the DB.
  *
@@ -166,6 +173,8 @@ create_denom_key_pair (unsigned int size,
   }
   return dkp;
 }
+
+
 /**
  * Callback invoked with information about refunds applicable
  * to a particular coin.
@@ -179,6 +188,7 @@ check_refund_cb (void *cls,
                  const struct TALER_Amount *amount_with_fee)
 {
   const struct TALER_EXCHANGEDB_Refund *refund = cls;
+
   if (0 != TALER_amount_cmp (amount_with_fee,
                              &refund->details.refund_amount))
   {
@@ -201,7 +211,7 @@ run (void *cls)
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   const uint32_t num_partitions = 10;
   struct GNUNET_TIME_Timestamp ts;
-  struct TALER_EXCHANGEDB_Deposit *depos=NULL;
+  struct TALER_EXCHANGEDB_Deposit *depos = NULL;
   struct GNUNET_TIME_Timestamp deadline;
   struct TALER_Amount value;
   union TALER_DenominationBlindingKeyP bks;
@@ -209,20 +219,20 @@ run (void *cls)
   struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
   struct TALER_ExchangeWithdrawValues alg_values = {
     .cipher = TALER_DENOMINATION_RSA
-    };
+  };
   struct GNUNET_TIME_Relative times = GNUNET_TIME_UNIT_ZERO;
   unsigned long long sqrs = 0;
-  struct TALER_EXCHANGEDB_Refund *ref=NULL;
+  struct TALER_EXCHANGEDB_Refund *ref = NULL;
   unsigned int *perm;
   unsigned long long duration_sq;
   struct TALER_CoinSpendPublicKeyP coin_pub;
   struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
   struct TALER_DenominationPublicKey *new_denom_pubs = NULL;
-  unsigned int count=0;
+  unsigned int count = 0;
 
-  ref = GNUNET_new_array (ROUNDS +1,
+  ref = GNUNET_new_array (ROUNDS + 1,
                           struct TALER_EXCHANGEDB_Refund);
-  depos = GNUNET_new_array (ROUNDS +1,
+  depos = GNUNET_new_array (ROUNDS + 1,
                             struct TALER_EXCHANGEDB_Deposit);
   ZR_BLK (&cbc);
 
@@ -249,8 +259,6 @@ run (void *cls)
     GNUNET_break (0);
     goto cleanup;
   }
-
-
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount (CURRENCY ":1.000010",
                                          &value));
@@ -270,78 +278,72 @@ run (void *cls)
 
   ts = GNUNET_TIME_timestamp_get ();
   deadline = GNUNET_TIME_timestamp_get ();
-  //DENOMINATION
   {
-    //PAIR KEY LIST
     new_dkp = GNUNET_new_array (MELT_NEW_COINS,
-                              struct DenomKeyPair *);
-    //PUBLIC KEY LIST
+                                struct DenomKeyPair *);
     new_denom_pubs = GNUNET_new_array (MELT_NEW_COINS,
                                        struct TALER_DenominationPublicKey);
-    //REFRESH REVEAL COIN LIST
     revealed_coins
       = GNUNET_new_array (MELT_NEW_COINS,
                           struct TALER_EXCHANGEDB_RefreshRevealedCoin);
     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
-      {
-        struct GNUNET_TIME_Timestamp now;
-        struct TALER_BlindedRsaPlanchet *rp;
-        struct TALER_BlindedPlanchet *bp;
-
-        now = GNUNET_TIME_timestamp_get ();
-        //5 KEY PAIR
-        new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
-                                              now,
-                                              &value,
-                                              &fees);
-        GNUNET_assert (NULL != new_dkp[cnt]);
-        new_denom_pubs[cnt] = new_dkp[cnt]->pub;
-        ccoin = &revealed_coins[cnt];
-        bp = &ccoin->blinded_planchet;
-        bp->cipher = TALER_DENOMINATION_RSA;
-        rp = &bp->details.rsa_blinded_planchet;
-        rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
-                                                                      
GNUNET_CRYPTO_QUALITY_WEAK,
-                                                                      
(RSA_KEY_SIZE / 8) - 1);
-        rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
-        GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
-                                    rp->blinded_msg,
-                                    rp->blinded_msg_size);
-        TALER_denom_pub_hash (&new_dkp[cnt]->pub,
-                              &ccoin->h_denom_pub);
-        ccoin->exchange_vals = alg_values;
-        TALER_coin_ev_hash (bp,
-                            &ccoin->h_denom_pub,
-                            &ccoin->coin_envelope_hash);
-        GNUNET_assert (GNUNET_OK ==
+    {
+      struct GNUNET_TIME_Timestamp now;
+      struct TALER_BlindedRsaPlanchet *rp;
+      struct TALER_BlindedPlanchet *bp;
+
+      now = GNUNET_TIME_timestamp_get ();
+      new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
+                                            now,
+                                            &value,
+                                            &fees);
+      GNUNET_assert (NULL != new_dkp[cnt]);
+      new_denom_pubs[cnt] = new_dkp[cnt]->pub;
+      ccoin = &revealed_coins[cnt];
+      bp = &ccoin->blinded_planchet;
+      bp->cipher = TALER_DENOMINATION_RSA;
+      rp = &bp->details.rsa_blinded_planchet;
+      rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 (
+        GNUNET_CRYPTO_QUALITY_WEAK,
+        (RSA_KEY_SIZE / 8) - 1);
+      rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size);
+      GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                                  rp->blinded_msg,
+                                  rp->blinded_msg_size);
+      TALER_denom_pub_hash (&new_dkp[cnt]->pub,
+                            &ccoin->h_denom_pub);
+      ccoin->exchange_vals = alg_values;
+      TALER_coin_ev_hash (bp,
+                          &ccoin->h_denom_pub,
+                          &ccoin->coin_envelope_hash);
+      GNUNET_assert (GNUNET_OK ==
                      TALER_denom_sign_blinded (&ccoin->coin_sig,
                                                &new_dkp[cnt]->priv,
                                                true,
                                                bp));
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_coin_ev_hash (bp,
-                                           &cbc.denom_pub_hash,
-                                           &cbc.h_coin_envelope));
-        GNUNET_assert (
-                       GNUNET_OK ==
-                       TALER_denom_sign_blinded (
-                                                 &cbc.sig,
-                                                 &new_dkp[cnt]->priv,
-                                                 false,
-                                                 bp));
-      }
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_coin_ev_hash (bp,
+                                         &cbc.denom_pub_hash,
+                                         &cbc.h_coin_envelope));
+      GNUNET_assert (
+        GNUNET_OK ==
+        TALER_denom_sign_blinded (
+          &cbc.sig,
+          &new_dkp[cnt]->priv,
+          false,
+          bp));
+    }
   }
 
   perm = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_NONCE,
                                        NUM_ROWS);
-  // begin
   FAILIF (GNUNET_OK !=
           plugin->start (plugin->cls,
                          "Transaction"));
-  for (unsigned int j=0; j< NUM_ROWS; j++)
+  for (unsigned int j = 0; j< NUM_ROWS; j++)
   {
     unsigned int i = perm[j];
-    unsigned int k = (unsigned int)rand()%5;
+    unsigned int k = (unsigned int) rand () % 5;
     if (i >= ROUNDS)
       i = ROUNDS; /* throw-away slot, do not keep around */
     RND_BLK (&coin_pub);
@@ -350,8 +352,6 @@ run (void *cls)
     RND_BLK (&depos[i].coin.coin_pub);
     TALER_denom_pub_hash (&new_dkp[k]->pub,
                           &depos[i].coin.denom_pub_hash);
-    // TALER_denom_pub_hash (&dkp->pub,
-    //                    &ref.coin.denom_pub_hash);
     GNUNET_assert (GNUNET_OK ==
                    TALER_denom_sig_unblind (&depos[i].coin.denom_sig,
                                             &cbc.sig,
@@ -369,15 +369,15 @@ run (void *cls)
     depos[i].receiver_wire_account =
       "payto://iban/DE67830654080004822650?receiver-name=Test";
     TALER_merchant_wire_signature_hash (
-                                        
"payto://iban/DE67830654080004822650?receiver-name=Test",
-                                        &depos[i].wire_salt,
-                                        &h_wire_wt);
+      "payto://iban/DE67830654080004822650?receiver-name=Test",
+      &depos[i].wire_salt,
+      &h_wire_wt);
     depos[i].timestamp = ts;
-      uint64_t known_coin_id;
-    {//ENSURE_COIN_KNOWN
-
+    uint64_t known_coin_id;
+    {
       struct TALER_DenominationHashP dph;
       struct TALER_AgeCommitmentHash agh;
+
       FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
               plugin->ensure_coin_known (plugin->cls,
                                          &depos[i].coin,
@@ -385,9 +385,9 @@ run (void *cls)
                                          &dph,
                                          &agh));
     }
-    /*STORE INTO DEPOSIT*/
     {
       struct GNUNET_TIME_Timestamp now;
+
       now = GNUNET_TIME_timestamp_get ();
       FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
               plugin->insert_deposit (plugin->cls,
@@ -399,12 +399,13 @@ run (void *cls)
       bool refund_ok;
       bool gone;
       bool conflict;
-      unsigned int refund_percent=0;
-      switch (refund_percent){
-      case 2 ://100% refund
+      unsigned int refund_percent = 0;
+      switch (refund_percent)
+      {
+      case 2: // 100% refund
         ref[i].coin = depos[i].coin;
         ref[i].details.merchant_pub = depos[i].merchant_pub;
-        RND_BLK(&ref[i].details.merchant_sig);
+        RND_BLK (&ref[i].details.merchant_sig);
         ref[i].details.h_contract_terms = depos[i].h_contract_terms;
         ref[i].coin.coin_pub = depos[i].coin.coin_pub;
         ref[i].details.rtransaction_id = i;
@@ -420,58 +421,58 @@ run (void *cls)
                                    &gone,
                                    &conflict));
         break;
-    case 1 ://10% refund
-      if (count < (NUM_ROWS/10))
-      {
-        ref[i].coin = depos[i].coin;
-        ref[i].details.merchant_pub = depos[i].merchant_pub;
-        RND_BLK(&ref[i].details.merchant_sig);
-        ref[i].details.h_contract_terms = depos[i].h_contract_terms;
-        ref[i].coin.coin_pub = depos[i].coin.coin_pub;
-        ref[i].details.rtransaction_id = i;
-        ref[i].details.refund_amount = value;
-        ref[i].details.refund_fee = fees.refund;
-      }
-      else
-      {
+      case 1:// 10% refund
+        if (count < (NUM_ROWS / 10))
+        {
+          ref[i].coin = depos[i].coin;
+          ref[i].details.merchant_pub = depos[i].merchant_pub;
+          RND_BLK (&ref[i].details.merchant_sig);
+          ref[i].details.h_contract_terms = depos[i].h_contract_terms;
+          ref[i].coin.coin_pub = depos[i].coin.coin_pub;
+          ref[i].details.rtransaction_id = i;
+          ref[i].details.refund_amount = value;
+          ref[i].details.refund_fee = fees.refund;
+        }
+        else
+        {
+          ref[i].coin = depos[i].coin;
+          RND_BLK (&ref[i].details.merchant_pub);
+          RND_BLK (&ref[i].details.merchant_sig);
+          RND_BLK (&ref[i].details.h_contract_terms);
+          RND_BLK (&ref[i].coin.coin_pub);
+          ref[i].details.rtransaction_id = i;
+          ref[i].details.refund_amount = value;
+          ref[i].details.refund_fee = fees.refund;
+        }
+        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+                plugin->do_refund (plugin->cls,
+                                   &ref[i],
+                                   &fees.deposit,
+                                   known_coin_id,
+                                   &not_found,
+                                   &refund_ok,
+                                   &gone,
+                                   &conflict));
+        count++;
+        break;
+      case 0:// no refund
         ref[i].coin = depos[i].coin;
-        RND_BLK(&ref[i].details.merchant_pub);
-        RND_BLK(&ref[i].details.merchant_sig);
-        RND_BLK(&ref[i].details.h_contract_terms);
-        RND_BLK(&ref[i].coin.coin_pub);
+        RND_BLK (&ref[i].details.merchant_pub);
+        RND_BLK (&ref[i].details.merchant_sig);
+        RND_BLK (&ref[i].details.h_contract_terms);
+        RND_BLK (&ref[i].coin.coin_pub);
         ref[i].details.rtransaction_id = i;
         ref[i].details.refund_amount = value;
         ref[i].details.refund_fee = fees.refund;
-      }
-      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-              plugin->do_refund (plugin->cls,
-                                 &ref[i],
-                                 &fees.deposit,
-                                 known_coin_id,
-                                 &not_found,
-                                 &refund_ok,
-                                 &gone,
-                                 &conflict));
-      count++;
-      break;
-    case 0://no refund
-      ref[i].coin=depos[i].coin;
-      RND_BLK(&ref[i].details.merchant_pub);
-      RND_BLK(&ref[i].details.merchant_sig);
-      RND_BLK(&ref[i].details.h_contract_terms);
-      RND_BLK(&ref[i].coin.coin_pub);
-      ref[i].details.rtransaction_id = i;
-      ref[i].details.refund_amount = value;
-      ref[i].details.refund_fee = fees.refund;
-      FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-              plugin->do_refund (plugin->cls,
-                                 &ref[i],
-                                 &fees.deposit,
-                                 known_coin_id,
-                                 &not_found,
-                                 &refund_ok,
-                                 &gone,
-                                 &conflict));
+        FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+                plugin->do_refund (plugin->cls,
+                                   &ref[i],
+                                   &fees.deposit,
+                                   known_coin_id,
+                                   &not_found,
+                                   &refund_ok,
+                                   &gone,
+                                   &conflict));
         break;
       }/* END OF SWITCH CASE */
     }
@@ -480,7 +481,6 @@ run (void *cls)
   }
   /* End of benchmark setup */
   GNUNET_free (perm);
-  // commit
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->commit (plugin->cls));
   for (unsigned int r = 0; r < ROUNDS; r++)
@@ -500,7 +500,8 @@ run (void *cls)
     times = GNUNET_TIME_relative_add (times,
                                       duration);
     duration_sq = duration.rel_value_us * duration.rel_value_us;
-    GNUNET_assert (duration_sq / duration.rel_value_us == 
duration.rel_value_us);
+    GNUNET_assert (duration_sq / duration.rel_value_us ==
+                   duration.rel_value_us);
     GNUNET_assert (sqrs + duration_sq >= sqrs);
     sqrs += duration_sq;
   }
@@ -514,10 +515,10 @@ run (void *cls)
                                        ROUNDS);
     avg_dbl = avg.rel_value_us;
     variance = sqrs - (avg_dbl * avg_dbl * ROUNDS);
-    fprintf(stdout,
-            "%8llu ± %6.0f\n",
-            (unsigned long long) avg.rel_value_us,
-            sqrt (variance / (ROUNDS-1)));
+    fprintf (stdout,
+             "%8llu ± %6.0f\n",
+             (unsigned long long) avg.rel_value_us,
+             sqrt (variance / (ROUNDS - 1)));
   }
   result = 0;
 drop:
@@ -540,12 +541,12 @@ cleanup:
        cnt++)
     destroy_denom_key_pair (new_dkp[cnt]);
   GNUNET_free (new_dkp);
-  for (unsigned int i=0; i< ROUNDS +1 ; i++)
-    {
-      TALER_denom_sig_free (&depos[i].coin.denom_sig);
-    }
-  GNUNET_free(depos);
-  GNUNET_free(ref);
+  for (unsigned int i = 0; i< ROUNDS + 1; i++)
+  {
+    TALER_denom_sig_free (&depos[i].coin.denom_sig);
+  }
+  GNUNET_free (depos);
+  GNUNET_free (ref);
   TALER_EXCHANGEDB_plugin_unload (plugin);
   plugin = NULL;
 }
@@ -557,7 +558,6 @@ main (int argc,
 {
   const char *plugin_name;
   char *config_filename;
-  char *testname;
   struct GNUNET_CONFIGURATION_Handle *cfg;
 
   (void) argc;
@@ -571,15 +571,17 @@ main (int argc,
                     "WARNING",
                     NULL);
   plugin_name++;
-  (void) GNUNET_asprintf (&testname,
-                          "test-exchange-db-%s",
-                          plugin_name);
-  (void) GNUNET_asprintf (&config_filename,
-                          "%s.conf",
-                          testname);
-  fprintf (stdout,
-           "Using config: %s\n",
-           config_filename);
+  {
+    char *testname;
+
+    GNUNET_asprintf (&testname,
+                     "test-exchange-db-%s",
+                     plugin_name);
+    GNUNET_asprintf (&config_filename,
+                     "%s.conf",
+                     testname);
+    GNUNET_free (testname);
+  }
   cfg = GNUNET_CONFIGURATION_create ();
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_parse (cfg,
@@ -587,16 +589,14 @@ main (int argc,
   {
     GNUNET_break (0);
     GNUNET_free (config_filename);
-    GNUNET_free (testname);
     return 2;
   }
   GNUNET_SCHEDULER_run (&run,
                         cfg);
   GNUNET_CONFIGURATION_destroy (cfg);
   GNUNET_free (config_filename);
-  GNUNET_free (testname);
   return result;
 }
 
 
-/* end of test_exchangedb_by_j.c */
+/* end of perf_select_refunds_by_coin.c */
diff --git a/src/exchangedb/pg_aggregate.c b/src/exchangedb/pg_aggregate.c
index f1c4d677..6e94cbeb 100644
--- a/src/exchangedb/pg_aggregate.c
+++ b/src/exchangedb/pg_aggregate.c
@@ -1,6 +1,6 @@
 /*
    This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
+   Copyright (C) 2022, 2023 Taler Systems SA
 
    TALER is free software; you can redistribute it and/or modify it under the
    terms of the GNU General Public License as published by the Free Software
@@ -72,26 +72,16 @@ TEH_PG_aggregate (
   now = GNUNET_TIME_absolute_round_down (GNUNET_TIME_absolute_get (),
                                          pg->aggregator_shift);
 
-    /* Used in #postgres_aggregate() */
+  /* Used in #postgres_aggregate() */
   PREPARE (pg,
            "aggregate",
-           "WITH rdy AS (" /* find deposits ready by merchant */
-           "  SELECT"
-           "    coin_pub"
-           "    FROM deposits_for_matching"
-           "    WHERE refund_deadline<$1" /* filter by shard, only actually 
executable deposits */
-           "      AND merchant_pub=$2" /* filter by target merchant */
-           "    ORDER BY refund_deadline ASC" /* ordering is not critical */
-           "    LIMIT "
-           TALER_QUOTE (TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) /* limits 
transaction size */
-           " )"
-           " ,dep AS (" /* restrict to our merchant and account and mark as 
done */
+           "WITH dep AS (" /* restrict to our merchant and account and mark as 
done */
            "  UPDATE deposits"
            "     SET done=TRUE"
-           "   WHERE coin_pub IN (SELECT coin_pub FROM rdy)"
-           "     AND merchant_pub=$2" /* theoretically, same coin could be 
spent at another merchant */
+           "   WHERE NOT (done OR policy_blocked)" /* only actually executable 
deposits */
+           "     AND refund_deadline<$1" /* filter by shard */
+           "     AND merchant_pub=$2" /* filter by target merchant */
            "     AND wire_target_h_payto=$3" /* merchant could have a 2nd bank 
account */
-           "     AND done=FALSE" /* theoretically, same coin could be spend at 
the same merchant a 2nd time */
            "   RETURNING"
            "     deposit_serial_id"
            "    ,coin_pub"
diff --git a/src/exchangedb/pg_batch2_reserves_in_insert.c 
b/src/exchangedb/pg_batch2_reserves_in_insert.c
deleted file mode 100644
index 1ef9045d..00000000
--- a/src/exchangedb/pg_batch2_reserves_in_insert.c
+++ /dev/null
@@ -1,914 +0,0 @@
-/*
-   This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
-
-   TALER is free software; you can redistribute it and/or modify it under the
-   terms of the GNU General Public License as published by the Free Software
-   Foundation; either version 3, or (at your option) any later version.
-
-   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
-   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along with
-   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_batch2_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_batch2_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);
-}
-
-
-static enum GNUNET_DB_QueryStatus
-insert1(struct PostgresClosure *pg,
-        const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1],
-        struct GNUNET_TIME_Timestamp expiry,
-        struct GNUNET_TIME_Timestamp gc,
-        struct TALER_PaytoHashP h_payto,
-        char *const * notify_s,
-        struct GNUNET_TIME_Timestamp reserve_expiration,
-        bool *transaction_duplicate,
-        bool *conflict,
-        uint64_t *reserve_uuid,
-        enum GNUNET_DB_QueryStatus results[1])
-{
-  enum GNUNET_DB_QueryStatus qs2;
-  PREPARE (pg,
-           "batch1_reserve_create",
-           "SELECT "
-           " out_reserve_found AS conflicted"
-           ",transaction_duplicate"
-           ",ruuid AS reserve_uuid"
-           " FROM exchange_do_batch_reserves_in_insert"
-           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
-
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
-      TALER_PQ_query_param_amount (reserves[0].balance),
-      GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-      GNUNET_PQ_query_param_string (notify_s[0]),
-      GNUNET_PQ_query_param_end
-    };
-
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_bool ("conflicted",
-                                  &conflict[0]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
-                                  &transaction_duplicate[0]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &reserve_uuid[0]),
-      GNUNET_PQ_result_spec_end
-    };
-
-
-    TALER_payto_hash (reserves[0].sender_account_details,
-                      &h_payto);
-
-    qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                    "batch1_reserve_create",
-                                                    params,
-                                                    rs);
-
-    if (qs2 < 0)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Failed to create reserves 1(%d)\n",
-                    qs2);
-        results[0] = qs2;
-        return qs2;
-      }
-    GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs2);
-    if ((! conflict[0]) && transaction_duplicate[0])
-      {
-        GNUNET_break (0);
-        TEH_PG_rollback (pg);
-        results[0] = GNUNET_DB_STATUS_HARD_ERROR;
-        return GNUNET_DB_STATUS_HARD_ERROR;
-      }
-    results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-    return qs2;
-}
-
-
-
-static enum GNUNET_DB_QueryStatus
-insert2 (struct PostgresClosure *pg,
-         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[2],
-         struct GNUNET_TIME_Timestamp expiry,
-         struct GNUNET_TIME_Timestamp gc,
-         struct TALER_PaytoHashP h_payto,
-         char *const*notify_s,
-         struct GNUNET_TIME_Timestamp reserve_expiration,
-         bool *transaction_duplicate,
-         bool *conflict,
-         uint64_t *reserve_uuid,
-         enum GNUNET_DB_QueryStatus results[1])
-{
-  enum GNUNET_DB_QueryStatus qs1;
-  PREPARE (pg,
-           "batch2_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 exchange_do_batch2_reserves_insert"
-           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22);");
-
-    struct GNUNET_PQ_QueryParam params[] = {
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
-      TALER_PQ_query_param_amount (reserves[0].balance),
-      GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-      GNUNET_PQ_query_param_string (notify_s[0]),
-      GNUNET_PQ_query_param_string (notify_s[1]),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
-      TALER_PQ_query_param_amount (reserves[1].balance),
-      GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[1].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",
-                                  &conflict[0]),
-      GNUNET_PQ_result_spec_bool ("conflicted2",
-                                  &conflict[1]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
-                                  &transaction_duplicate[0]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
-                                  &transaction_duplicate[1]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &reserve_uuid[0]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
-                                    &reserve_uuid[1]),
-      GNUNET_PQ_result_spec_end
-    };
-
-    TALER_payto_hash (reserves[0].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[1].sender_account_details,
-                      &h_payto);
-
-
-    qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                    "batch2_reserve_create",
-                                                    params,
-                                                    rs);
-    if (qs1 < 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to create reserves 2(%d)\n",
-                  qs1);
-      results[0]=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;*/
-
-    if (
-        ((! conflict[0]) && (transaction_duplicate[0]))
-        ||((! conflict[1]) && (transaction_duplicate[1]))
-        )
-   {
-     GNUNET_break (0);
-     TEH_PG_rollback (pg); //ROLLBACK
-     results[0] = GNUNET_DB_STATUS_HARD_ERROR;
-     return GNUNET_DB_STATUS_HARD_ERROR;
-   }
-    results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-    return qs1;
-}
-
-
-static enum GNUNET_DB_QueryStatus
-insert4 (struct PostgresClosure *pg,
-         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[4],
-         struct GNUNET_TIME_Timestamp expiry,
-         struct GNUNET_TIME_Timestamp gc,
-         struct TALER_PaytoHashP h_payto,
-         char *const*notify_s,
-         struct GNUNET_TIME_Timestamp reserve_expiration,
-         bool *transaction_duplicate,
-         bool *conflict,
-         uint64_t *reserve_uuid,
-         enum GNUNET_DB_QueryStatus results[1])
-{
-  enum GNUNET_DB_QueryStatus qs3;
-  PREPARE (pg,
-           "batch4_reserve_create",
-           "SELECT "
-           "out_reserve_found AS conflicted"
-           ",out_reserve_found2 AS conflicted2"
-           ",out_reserve_found3 AS conflicted3"
-           ",out_reserve_found4 AS conflicted4"
-           ",transaction_duplicate"
-           ",transaction_duplicate2"
-           ",transaction_duplicate3"
-           ",transaction_duplicate4"
-           ",ruuid AS reserve_uuid"
-           ",ruuid2 AS reserve_uuid2"
-           ",ruuid3 AS reserve_uuid3"
-           ",ruuid4 AS reserve_uuid4"
-           " FROM exchange_do_batch4_reserves_insert"
-           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,
 $40, $41,$42);");
-
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
-      TALER_PQ_query_param_amount (reserves[0].balance),
-      GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-      GNUNET_PQ_query_param_string (notify_s[0]),
-      GNUNET_PQ_query_param_string (notify_s[1]),
-      GNUNET_PQ_query_param_string (notify_s[2]),
-      GNUNET_PQ_query_param_string (notify_s[3]),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
-      TALER_PQ_query_param_amount (reserves[1].balance),
-      GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[1].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference),
-      TALER_PQ_query_param_amount (reserves[2].balance),
-      GNUNET_PQ_query_param_string (reserves[2].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[2].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference),
-      TALER_PQ_query_param_amount (reserves[3].balance),
-      GNUNET_PQ_query_param_string (reserves[3].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[3].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",
-                                  &conflict[0]),
-      GNUNET_PQ_result_spec_bool ("conflicted2",
-                                  &conflict[1]),
-      GNUNET_PQ_result_spec_bool ("conflicted3",
-                                  &conflict[2]),
-      GNUNET_PQ_result_spec_bool ("conflicted4",
-                                  &conflict[3]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
-                                  &transaction_duplicate[0]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
-                                  &transaction_duplicate[1]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
-                                  &transaction_duplicate[2]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
-                                  &transaction_duplicate[3]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &reserve_uuid[0]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
-                                    &reserve_uuid[1]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
-                                    &reserve_uuid[2]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
-                                    &reserve_uuid[3]),
-      GNUNET_PQ_result_spec_end
-    };
-
-    TALER_payto_hash (reserves[0].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[1].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[2].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[3].sender_account_details,
-                      &h_payto);
-
-    qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                    "batch4_reserve_create",
-                                                    params,
-                                                    rs);
-    if (qs3 < 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to create reserves4 (%d)\n",
-                  qs3);
-      results[0] = qs3;
-      return qs3;
-    }
-
-   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3);
-
-    if (
-        ((! conflict[0]) && (transaction_duplicate[0]))
-        ||((! conflict[1]) && (transaction_duplicate[1]))
-        ||((! conflict[2]) && (transaction_duplicate[2]))
-        ||((! conflict[3]) && (transaction_duplicate[3]))
-        )
-   {
-     GNUNET_break (0);
-     TEH_PG_rollback (pg);
-     results[0] = GNUNET_DB_STATUS_HARD_ERROR;
-     return GNUNET_DB_STATUS_HARD_ERROR;
-   }
-    results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-    return qs3;
-}
-
-
-static enum GNUNET_DB_QueryStatus
-insert8 (struct PostgresClosure *pg,
-         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[8],
-         struct GNUNET_TIME_Timestamp expiry,
-         struct GNUNET_TIME_Timestamp gc,
-         struct TALER_PaytoHashP h_payto,
-         char *const*notify_s,
-         struct GNUNET_TIME_Timestamp reserve_expiration,
-         bool *transaction_duplicate,
-         bool *conflict,
-         uint64_t *reserve_uuid,
-         enum GNUNET_DB_QueryStatus results[1])
-{
-  enum GNUNET_DB_QueryStatus qs3;
-  PREPARE (pg,
-           "batch8_reserve_create",
-           "SELECT "
-           "out_reserve_found AS conflicted"
-           ",out_reserve_found2 AS conflicted2"
-           ",out_reserve_found3 AS conflicted3"
-           ",out_reserve_found4 AS conflicted4"
-           ",out_reserve_found5 AS conflicted5"
-           ",out_reserve_found6 AS conflicted6"
-           ",out_reserve_found7 AS conflicted7"
-           ",out_reserve_found8 AS conflicted8"
-           ",transaction_duplicate"
-           ",transaction_duplicate2"
-           ",transaction_duplicate3"
-           ",transaction_duplicate4"
-           ",transaction_duplicate5"
-           ",transaction_duplicate6"
-           ",transaction_duplicate7"
-           ",transaction_duplicate8"
-           ",ruuid AS reserve_uuid"
-           ",ruuid2 AS reserve_uuid2"
-           ",ruuid3 AS reserve_uuid3"
-           ",ruuid4 AS reserve_uuid4"
-           ",ruuid5 AS reserve_uuid5"
-           ",ruuid6 AS reserve_uuid6"
-           ",ruuid7 AS reserve_uuid7"
-           ",ruuid8 AS reserve_uuid8"
-           " FROM exchange_do_batch8_reserves_insert"
-           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,
 $40, 
$41,$42,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$80,$81,$82);");
-
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
-      TALER_PQ_query_param_amount (reserves[0].balance),
-      GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-      GNUNET_PQ_query_param_string (notify_s[0]),
-      GNUNET_PQ_query_param_string (notify_s[1]),
-      GNUNET_PQ_query_param_string (notify_s[2]),
-      GNUNET_PQ_query_param_string (notify_s[3]),
-      GNUNET_PQ_query_param_string (notify_s[4]),
-      GNUNET_PQ_query_param_string (notify_s[5]),
-      GNUNET_PQ_query_param_string (notify_s[6]),
-      GNUNET_PQ_query_param_string (notify_s[7]),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
-      TALER_PQ_query_param_amount (reserves[1].balance),
-      GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[1].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference),
-      TALER_PQ_query_param_amount (reserves[2].balance),
-      GNUNET_PQ_query_param_string (reserves[2].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[2].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference),
-      TALER_PQ_query_param_amount (reserves[3].balance),
-      GNUNET_PQ_query_param_string (reserves[3].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[3].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[4].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[4].wire_reference),
-      TALER_PQ_query_param_amount (reserves[4].balance),
-      GNUNET_PQ_query_param_string (reserves[4].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[4].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[4].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[5].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[5].wire_reference),
-      TALER_PQ_query_param_amount (reserves[5].balance),
-      GNUNET_PQ_query_param_string (reserves[5].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[5].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[5].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[6].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[6].wire_reference),
-      TALER_PQ_query_param_amount (reserves[6].balance),
-      GNUNET_PQ_query_param_string (reserves[6].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[6].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[6].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
-      GNUNET_PQ_query_param_auto_from_type (reserves[7].reserve_pub),
-      GNUNET_PQ_query_param_uint64 (&reserves[7].wire_reference),
-      TALER_PQ_query_param_amount (reserves[7].balance),
-      GNUNET_PQ_query_param_string (reserves[7].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[7].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[7].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",
-                                  &conflict[0]),
-      GNUNET_PQ_result_spec_bool ("conflicted2",
-                                  &conflict[1]),
-      GNUNET_PQ_result_spec_bool ("conflicted3",
-                                  &conflict[2]),
-      GNUNET_PQ_result_spec_bool ("conflicted4",
-                                  &conflict[3]),
-      GNUNET_PQ_result_spec_bool ("conflicted5",
-                                  &conflict[4]),
-      GNUNET_PQ_result_spec_bool ("conflicted6",
-                                  &conflict[5]),
-      GNUNET_PQ_result_spec_bool ("conflicted7",
-                                  &conflict[6]),
-      GNUNET_PQ_result_spec_bool ("conflicted8",
-                                  &conflict[7]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
-                                  &transaction_duplicate[0]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
-                                  &transaction_duplicate[1]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
-                                  &transaction_duplicate[2]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
-                                  &transaction_duplicate[3]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate5",
-                                  &transaction_duplicate[4]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate6",
-                                  &transaction_duplicate[5]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate7",
-                                  &transaction_duplicate[6]),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate8",
-                                  &transaction_duplicate[7]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &reserve_uuid[0]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
-                                    &reserve_uuid[1]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
-                                    &reserve_uuid[2]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
-                                    &reserve_uuid[3]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid5",
-                                    &reserve_uuid[4]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid6",
-                                    &reserve_uuid[5]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid7",
-                                    &reserve_uuid[6]),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid8",
-                                    &reserve_uuid[7]),
-      GNUNET_PQ_result_spec_end
-    };
-
-    TALER_payto_hash (reserves[0].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[1].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[2].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[3].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[4].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[5].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[6].sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserves[7].sender_account_details,
-                      &h_payto);
-
-    qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                    "batch8_reserve_create",
-                                                    params,
-                                                    rs);
-    if (qs3 < 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to create reserves8 (%d)\n",
-                  qs3);
-      results[0]=qs3;
-      return qs3;
-    }
-
-   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3);
-   /*   results[i] = (transaction_duplicate)
-      ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
-      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
-
-    if (
-        ((! conflict[0]) && (transaction_duplicate[0]))
-        ||((! conflict[1]) && (transaction_duplicate[1]))
-        ||((! conflict[2]) && (transaction_duplicate[2]))
-        ||((! conflict[3]) && (transaction_duplicate[3]))
-        ||((! conflict[4]) && (transaction_duplicate[4]))
-        ||((! conflict[5]) && (transaction_duplicate[5]))
-        ||((! conflict[6]) && (transaction_duplicate[6]))
-        ||((! conflict[7]) && (transaction_duplicate[7]))
-        )
-   {
-     GNUNET_break (0);
-     TEH_PG_rollback (pg);
-     results[0]=GNUNET_DB_STATUS_HARD_ERROR;
-     return GNUNET_DB_STATUS_HARD_ERROR;
-   }
-    results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-    return qs3;
-}
-
-enum GNUNET_DB_QueryStatus
-TEH_PG_batch2_reserves_in_insert (void *cls,
-                                  const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
-                                  unsigned int reserves_length,
-                                  unsigned int batch_size,
-                                  enum GNUNET_DB_QueryStatus *results)
-{
-  struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs1;
-  enum GNUNET_DB_QueryStatus qs2;
-  enum GNUNET_DB_QueryStatus qs4;
-  enum GNUNET_DB_QueryStatus qs5;
-  struct GNUNET_TIME_Timestamp expiry;
-  struct GNUNET_TIME_Timestamp gc;
-  struct TALER_PaytoHashP h_payto;
-  uint64_t reserve_uuid[reserves_length];
-  bool transaction_duplicate[reserves_length];
-  bool need_update = false;
-  bool t_duplicate=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;
-  }
-
-  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);
-  }
-
-  unsigned int i=0;
-
-  while (i < reserves_length)
-  {
-    unsigned int bs = GNUNET_MIN (batch_size,
-                                  reserves_length - i);
-    if (bs >= 8)
-    {
-      qs1=insert8(pg,
-                  &reserves[i],
-                  expiry,
-                  gc,
-                  h_payto,
-                  &notify_s[i],
-                  reserve_expiration,
-                  &transaction_duplicate[i],
-                  &conflicts[i],
-                  &reserve_uuid[i],
-                  &results[i]);
-
-     if (qs1<0)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Failed to create reserve batch_8 (%d)\n",
-                    qs1);
-        return qs1;
-      }
-      need_update |= conflicts[i];
-      need_update |= conflicts[i+1];
-      need_update |= conflicts[i+2];
-      need_update |= conflicts[i+3];
-      need_update |= conflicts[i+4];
-      need_update |= conflicts[i+5];
-      need_update |= conflicts[i+6];
-      need_update |= conflicts[i+7];
-      t_duplicate |= transaction_duplicate[i];
-      t_duplicate |= transaction_duplicate[i+1];
-      t_duplicate |= transaction_duplicate[i+2];
-      t_duplicate |= transaction_duplicate[i+3];
-      t_duplicate |= transaction_duplicate[i+4];
-      t_duplicate |= transaction_duplicate[i+5];
-      t_duplicate |= transaction_duplicate[i+6];
-      t_duplicate |= transaction_duplicate[i+7];
-      i+=8;
-      continue;
-    }
-    switch (bs)
-      {
-    case 7:
-    case 6 :
-    case 5:
-    case 4 :
-      qs4=insert4(pg,
-                  &reserves[i],
-                  expiry,
-                  gc,
-                  h_payto,
-                  &notify_s[i],
-                  reserve_expiration,
-                  &transaction_duplicate[i],
-                  &conflicts[i],
-                  &reserve_uuid[i],
-                  &results[i]);
-
-     if (qs4<0)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Failed to create reserve batch_4 (%d)\n",
-                    qs4);
-        return qs4;
-      }
-      need_update |= conflicts[i];
-      need_update |= conflicts[i+1];
-      need_update |= conflicts[i+2];
-      need_update |= conflicts[i+3];
-      t_duplicate |= transaction_duplicate[i];
-      t_duplicate |= transaction_duplicate[i+1];
-      t_duplicate |= transaction_duplicate[i+2];
-      t_duplicate |= transaction_duplicate[i+3];
-      //  fprintf(stdout, "reserve_uuid : %ld %ld %ld %ld\n", reserve_uuid[i], 
reserve_uuid[i+1], reserve_uuid[i+2], reserve_uuid[i+3]);
-      i += 4;
-      break;
-    case 3:
-    case 2:
-      qs5=insert2(pg,
-                  &reserves[i],
-                  expiry,
-                  gc,
-                  h_payto,
-                  &notify_s[i],
-                  reserve_expiration,
-                  &transaction_duplicate[i],
-                  &conflicts[i],
-                  &reserve_uuid[i],
-                  &results[i]);
-      if (qs5<0)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Failed to create reserve batch_2 (%d)\n",
-                    qs5);
-        return qs5;
-      }
-      need_update |= conflicts[i];
-      need_update |= conflicts[i+1];
-      t_duplicate |= transaction_duplicate[i];
-      t_duplicate |= transaction_duplicate[i+1];
-      results[i] = (t_duplicate)
-      ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
-      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-      //   fprintf(stdout, "reserve_uuid : %ld %ld\n", reserve_uuid[i], 
reserve_uuid[i+1]);
-      i += 2;
-      break;
-    case 1:
-      qs2 = insert1(pg,
-                    &reserves[i],
-                    expiry,
-                    gc,
-                    h_payto,
-                    &notify_s[i],
-                    reserve_expiration,
-                    &transaction_duplicate[i],
-                    &conflicts[i],
-                    &reserve_uuid[i],
-                    &results[i]);
-      if (qs2<0)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Failed to create reserve batch_1 (%d)\n)"
-                    ,qs2);
-        return qs2;
-      }
-      need_update |= conflicts[i];
-      t_duplicate |= transaction_duplicate[i];
-      //  fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], 
conflicts[i], transaction_duplicate[i]);
-      i += 1;
-      break;
-    case 0:
-      GNUNET_assert (0);
-      break;
-    }
-  } /* end while */
-  // commit
-  {
-    enum GNUNET_DB_QueryStatus cs;
-
-    cs = TEH_PG_commit (pg);
-    if (cs < 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to commit\n");
-      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 qs3;
-  PREPARE (pg,
-           "reserves_update",
-           "SELECT"
-           " out_duplicate AS duplicate "
-           "FROM exchange_do_batch_reserves_update"
-           " ($1,$2,$3,$4,$5,$6,$7,$8);");
-  for (unsigned int i = 0; i<reserves_length; i++)
-    {
-      if (! conflicts[i])
-        continue;
-      {
-        bool duplicate;
-        struct GNUNET_PQ_QueryParam params[] = {
-          GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
-          GNUNET_PQ_query_param_timestamp (&expiry),
-          GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
-          TALER_PQ_query_param_amount (reserves[i].balance),
-          GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
-          GNUNET_PQ_query_param_auto_from_type (&h_payto),
-          GNUNET_PQ_query_param_string (notify_s[i]),
-          GNUNET_PQ_query_param_end
-        };
-        struct GNUNET_PQ_ResultSpec rs[] = {
-          GNUNET_PQ_result_spec_bool ("duplicate",
-                                      &duplicate),
-          GNUNET_PQ_result_spec_end
-        };
-        qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                        "reserves_update",
-                                                        params,
-                                                        rs);
-        if (qs3<0)
-          {
-            GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                        "Failed to update reserves (%d)\n",
-                        qs3);
-            results[i] = qs3;
-            return qs3;
-          }
-        results[i] = duplicate
-          ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
-          : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-      }
-    }
-
-  {
-    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_batch2_reserves_in_insert.h 
b/src/exchangedb/pg_batch2_reserves_in_insert.h
deleted file mode 100644
index 3191f867..00000000
--- a/src/exchangedb/pg_batch2_reserves_in_insert.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-   This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
-
-   TALER is free software; you can redistribute it and/or modify it under the
-   terms of the GNU General Public License as published by the Free Software
-   Foundation; either version 3, or (at your option) any later version.
-
-   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
-   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along with
-   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_batch2_reserves_in_insert.h
- * @brief implementation of the batch2_reserves_in_insert function for Postgres
- * @author Joseph XU
- */
-#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_batch2_reserves_in_insert (void *cls,
-                                 const struct TALER_EXCHANGEDB_ReserveInInfo 
*reserves,
-                                 unsigned int reserves_length,
-                                  unsigned int batch_size,
-                                 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
deleted file mode 100644
index 6536eb56..00000000
--- a/src/exchangedb/pg_batch4_reserves_in_insert.c
+++ /dev/null
@@ -1,595 +0,0 @@
-
-/*
-   This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
-
-   TALER is free software; you can redistribute it and/or modify it under the
-   terms of the GNU General Public License as published by the Free Software
-   Foundation; either version 3, or (at your option) any later version.
-
-   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
-   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along with
-   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_batch_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);
-}
-
-
-static enum GNUNET_DB_QueryStatus
-insert1(struct PostgresClosure *pg,
-        const struct TALER_EXCHANGEDB_ReserveInInfo *reserve,
-        struct GNUNET_TIME_Timestamp expiry,
-        struct GNUNET_TIME_Timestamp gc,
-        struct TALER_PaytoHashP h_payto,
-        const char *notify_s,
-        struct GNUNET_TIME_Timestamp reserve_expiration,
-        bool *transaction_duplicate,
-        bool *conflict,
-        uint64_t *reserve_uuid)
-{
-  enum GNUNET_DB_QueryStatus qs2;
-  PREPARE (pg,
-           "reserve_creates",
-           "SELECT "
-           "out_reserve_found AS conflicted"
-           ",transaction_duplicate"
-           ",ruuid AS reserve_uuid"
-           " FROM exchange_do_batch_reserves_in_insert"
-           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
-
-    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),
-      GNUNET_PQ_query_param_end
-    };
-
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_bool ("conflicted",
-                                  conflict),
-      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' */
-    qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                    "reserve_creates",
-                                                    params,
-                                                    rs);
-
-    if (qs2 < 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to create reserves (%d)\n",
-                  qs2);
-      return qs2;
-    }
-   GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs2);
-
-   if ((*conflict) && (*transaction_duplicate))
-   {
-     GNUNET_break (0);
-     TEH_PG_rollback (pg);
-     return GNUNET_DB_STATUS_HARD_ERROR;
-   }
-   return qs2;
-}
-
-
-
-static enum GNUNET_DB_QueryStatus
-insert2 (struct PostgresClosure *pg,
-         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve0,
-         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve1,
-         struct GNUNET_TIME_Timestamp expiry,
-         struct GNUNET_TIME_Timestamp gc,
-         struct TALER_PaytoHashP h_payto,
-         const char *notify_s,
-         struct GNUNET_TIME_Timestamp reserve_expiration,
-         bool *transaction_duplicate,
-         bool *transaction_duplicate2,
-         bool *conflict,
-         bool *conflict2,
-         uint64_t *reserve_uuid,
-         uint64_t *reserve_uuid2)
-{
-  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 exchange_do_batch2_reserves_insert"
-           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21);");
-
-    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),
-      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",
-                                  conflict),
-      GNUNET_PQ_result_spec_bool ("conflicted2",
-                                  conflict2),
-      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);
-
-
-    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;*/
-
-    if ((*conflict) && (*transaction_duplicate) ||((*conflict2) && 
(*transaction_duplicate2)))
-   {
-     GNUNET_break (0);
-     TEH_PG_rollback (pg);
-     return GNUNET_DB_STATUS_HARD_ERROR;
-   }
-
-}
-
-
-static enum GNUNET_DB_QueryStatus
-insert4 (struct PostgresClosure *pg,
-         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve0,
-         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve1,
-         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve2,
-         const struct TALER_EXCHANGEDB_ReserveInInfo *reserve3,
-         struct GNUNET_TIME_Timestamp expiry,
-         struct GNUNET_TIME_Timestamp gc,
-         struct TALER_PaytoHashP h_payto,
-         const char *notify_s,
-         struct GNUNET_TIME_Timestamp reserve_expiration,
-         bool *transaction_duplicate,
-         bool *transaction_duplicate2,
-         bool *transaction_duplicate3,
-         bool *transaction_duplicate4,
-         bool *conflict,
-         bool *conflict2,
-         bool *conflict3,
-         bool *conflict4,
-         uint64_t *reserve_uuid,
-         uint64_t *reserve_uuid2,
-         uint64_t *reserve_uuid3,
-         uint64_t *reserve_uuid4)
-{
-  PREPARE (pg,
-           "reserve_create",
-           "SELECT "
-           "out_reserve_found AS conflicted"
-           ",out_reserve_found2 AS conflicted2"
-           ",out_reserve_found3 AS conflicted3"
-           ",out_reserve_found4 AS conflicted4"
-           ",transaction_duplicate"
-           ",transaction_duplicate2"
-           ",transaction_duplicate3"
-           ",transaction_duplicate4"
-           ",ruuid AS reserve_uuid"
-           ",ruuid2 AS reserve_uuid2"
-           ",ruuid3 AS reserve_uuid3"
-           ",ruuid4 AS reserve_uuid4"
-           " FROM exchange_do_batch4_reserves_insert"
-           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39);");
-
-    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),
-
-      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_auto_from_type (&reserve2->reserve_pub),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_uint64 (&reserve2->wire_reference),
-      TALER_PQ_query_param_amount (&reserve2->balance),
-      GNUNET_PQ_query_param_string (reserve2->exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserve2->execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserve2->sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-
-      GNUNET_PQ_query_param_auto_from_type (&reserve3->reserve_pub),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_uint64 (&reserve3->wire_reference),
-      TALER_PQ_query_param_amount (&reserve3->balance),
-      GNUNET_PQ_query_param_string (reserve3->exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserve3->execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserve3->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",
-                                  conflict),
-      GNUNET_PQ_result_spec_bool ("conflicted2",
-                                  conflict2),
-      GNUNET_PQ_result_spec_bool ("conflicted3",
-                                  conflict3),
-      GNUNET_PQ_result_spec_bool ("conflicted4",
-                                  conflict4),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate",
-                                  transaction_duplicate),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
-                                  transaction_duplicate2),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
-                                  transaction_duplicate3),
-      GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
-                                  transaction_duplicate4),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    reserve_uuid),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
-                                    reserve_uuid2),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
-                                    reserve_uuid3),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
-                                    reserve_uuid4),
-      GNUNET_PQ_result_spec_end
-    };
-
-    TALER_payto_hash (reserve0->sender_account_details,
-                      &h_payto);
-    TALER_payto_hash (reserve1->sender_account_details,
-                      &h_payto);
-
-
-    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;*/
-
-    if ((*conflict) && (*transaction_duplicate) ||((*conflict2) && 
(*transaction_duplicate2)))
-   {
-     GNUNET_break (0);
-     TEH_PG_rollback (pg);
-     return GNUNET_DB_STATUS_HARD_ERROR;
-   }
-
-}
-
-
-
-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;
-  enum GNUNET_DB_QueryStatus qs2;
-  enum GNUNET_DB_QueryStatus qs4;
-  enum GNUNET_DB_QueryStatus qs5;
-  struct GNUNET_TIME_Timestamp expiry;
-  struct GNUNET_TIME_Timestamp gc;
-  struct TALER_PaytoHashP h_payto;
-  uint64_t reserve_uuid[reserves_length];
-  bool conflicted;
-  bool conflicted2;
-  bool transaction_duplicate[reserves_length];
-  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];
-  char *notify_s[reserves_length];
-
-  if (GNUNET_OK !=
-      TEH_PG_preflight (pg))
-  {
-    GNUNET_break (0);
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
-
-  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);
-  }
-
-  unsigned int i=0;
-
-  while (i < reserves_length)
-  {
-    if (reserves_length - i >= 4)
-    {
-      qs4=insert4(pg,
-              &reserves[i],
-              &reserves[i+2],
-              &reserves[i+3],
-              &reserves[i+4],
-              expiry,
-              gc,
-              h_payto,
-              &notify_s[i],
-              reserve_expiration,
-              &transaction_duplicate[i],
-              &transaction_duplicate[i+1],
-              &transaction_duplicate[i+2],
-              &transaction_duplicate[i+3],
-              &conflicts[i],
-              &conflicts[i+1],
-              &conflicts[i+2],
-              &conflicts[i+3],
-              &reserve_uuid[i],
-              &reserve_uuid[i+1],
-              &reserve_uuid[i+2],
-              &reserve_uuid[i+3]);
-
-      need_update |= conflicts[i];
-      need_update |= conflicts[i+1];
-      need_update |= conflicts[i+2];
-      need_update |= conflicts[i+3];
-      i += 4;
-      continue;
-    }
-    switch (reserves_length - i)
-    {
-    case 3:
-    case 2:
-      qs5=insert2(pg,
-              &reserves[i],
-              &reserves[i+1],
-              expiry,
-              gc,
-              h_payto,
-              notify_s[i],
-              reserve_expiration,
-              &transaction_duplicate[i],
-              &transaction_duplicate[i+1],
-              &conflicts[i],
-              &conflicts[i+1],
-              &reserve_uuid[i],
-              &reserve_uuid[i+1]);
-      need_update |= conflicts[i];
-      need_update |= conflicts[i+1];
-      i += 2;
-      break;
-    case 1:
-      qs2 = insert1(pg,
-                    &reserves[i],
-                    expiry,
-                    gc,
-                    h_payto,
-                    notify_s[i],
-                    reserve_expiration,
-                    &transaction_duplicate[i],
-                    &conflicts[i],
-                    &reserve_uuid[i]);
-      need_update |= conflicts[i];
-      i += 1;
-      break;
-    case 0:
-      GNUNET_assert (0);
-      break;
-    }
-  } /* end while */
-  // 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 qs3;
-  PREPARE (pg,
-           "reserves_in_add_transaction",
-           "CALL exchange_do_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
-      };
-
-      qs3 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                                "reserves_in_add_transaction",
-                                                params);
-      if (qs3<0)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Failed to update reserves (%d)\n",
-                    qs3);
-        return qs3;
-      }
-    }
-  }
-  {
-    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.c 
b/src/exchangedb/pg_batch_reserves_in_insert.c
deleted file mode 100644
index f1e4a936..00000000
--- a/src/exchangedb/pg_batch_reserves_in_insert.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
-   This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
-
-   TALER is free software; you can redistribute it and/or modify it under the
-   terms of the GNU General Public License as published by the Free Software
-   Foundation; either version 3, or (at your option) any later version.
-
-   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
-   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along with
-   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_batch_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_batch_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;
-  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_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));
-  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);
-  }
-  bool need_update = false;
-  for (unsigned int i = 0; i<reserves_length; i++)
-  {
-    bool conflicted;
-    bool transaction_duplicate;
-
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
-      TALER_PQ_query_param_amount (reserves[i].balance),
-      GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
-      GNUNET_PQ_query_param_timestamp (&reserves[i].execution_time),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_string (reserves[i].sender_account_details),
-      GNUNET_PQ_query_param_timestamp (&reserve_expiration),
-      GNUNET_PQ_query_param_string (notify_s[i]),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      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 (reserves[i].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);
-      results[i] = qs1;
-      return qs1;
-    }
-    GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1);
-    conflicts[i] = conflicted;
-    //   fprintf(stdout, "%d", conflicts[i]);
-    if (conflicts[i] && transaction_duplicate)
-    {
-      GNUNET_break (0);
-      results[i] = GNUNET_DB_STATUS_HARD_ERROR;
-      TEH_PG_rollback (pg);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    results[i] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-    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"
-           "  out_duplicate AS duplicate"
-           " FROM exchange_do_batch_reserves_update"
-           " ($1,$2,$3,$4,$5,$6,$7,$8);");
-  for (unsigned int i = 0; i<reserves_length; i++)
-  {
-    if (! conflicts[i])
-      continue;
-    {
-      bool duplicate;
-      struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
-        GNUNET_PQ_query_param_timestamp (&expiry),
-        GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
-        TALER_PQ_query_param_amount (reserves[i].balance),
-        GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
-        GNUNET_PQ_query_param_auto_from_type (&h_payto),
-        GNUNET_PQ_query_param_string (notify_s[i]),
-        GNUNET_PQ_query_param_end
-      };
-      struct GNUNET_PQ_ResultSpec rs[] = {
-        GNUNET_PQ_result_spec_bool ("duplicate",
-                                    &duplicate),
-        GNUNET_PQ_result_spec_end
-      };
-      qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                      
"reserves_in_add_transaction",
-                                                      params,
-                                                      rs);
-      if (qs2 < 0)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Failed to update reserves (%d)\n",
-                    qs2);
-        results[i] = qs2;
-        return qs2;
-      }
-      results[i] = duplicate
-        ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
-        : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-    }
-  }
-  {
-    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_batch_reserves_in_insert.h
deleted file mode 100644
index 76679567..00000000
--- a/src/exchangedb/pg_batch_reserves_in_insert.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-   This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
-
-   TALER is free software; you can redistribute it and/or modify it under the
-   terms of the GNU General Public License as published by the Free Software
-   Foundation; either version 3, or (at your option) any later version.
-
-   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
-   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along with
-   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-/**
- * @file exchangedb/pg_batch_reserves_in_insert.h
- * @brief implementation of the batch_reserves_in_insert function for Postgres
- * @author Christian Grothoff
- */
-#ifndef PG_BATCH_RESERVES_IN_INSERT_H
-#define PG_BATCH_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);
-
-#endif
diff --git a/src/exchangedb/pg_get_link_data.c 
b/src/exchangedb/pg_get_link_data.c
index 26225a13..a0795433 100644
--- a/src/exchangedb/pg_get_link_data.c
+++ b/src/exchangedb/pg_get_link_data.c
@@ -55,7 +55,7 @@ struct LinkDataContext
   /**
    * Status, set to #GNUNET_SYSERR on errors,
    */
-  int status;
+  enum GNUNET_GenericReturnValue status;
 };
 
 
@@ -190,20 +190,18 @@ TEH_PG_get_link_data (void *cls,
                        "%d%c",
                        &percent_refund,
                        &dummy)) )
-      {
-        if (NULL != mode)
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Bad mode `%s' specified\n",
-                      mode);
-      }
-      if (NULL==mode)
-        percent_refund=0;
+    {
+      if (NULL != mode)
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Bad mode `%s' specified\n",
+                    mode);
+      percent_refund = 0;
+    }
   }
-
   switch (percent_refund)
   {
   case 0:
-    query="get_link";
+    query = "get_link";
     PREPARE (pg,
              query,
              "SELECT "
@@ -225,7 +223,7 @@ TEH_PG_get_link_data (void *cls,
              " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
     break;
   case 1:
-    query="get_link_v1";
+    query = "get_link_v1";
     PREPARE (pg,
              query,
              "WITH rc AS MATERIALIZED ("
@@ -252,7 +250,7 @@ TEH_PG_get_link_data (void *cls,
              " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC");
     break;
   case 2:
-    query="get_link_v2";
+    query = "get_link_v2";
     PREPARE (pg,
              query,
              "SELECT"
@@ -300,5 +298,3 @@ TEH_PG_get_link_data (void *cls,
     return GNUNET_DB_STATUS_HARD_ERROR;
   return qs;
 }
-
-
diff --git a/src/exchangedb/pg_get_ready_deposit.c 
b/src/exchangedb/pg_get_ready_deposit.c
index 73ac9e47..91151c61 100644
--- a/src/exchangedb/pg_get_ready_deposit.c
+++ b/src/exchangedb/pg_get_ready_deposit.c
@@ -1,6 +1,6 @@
 /*
    This file is part of TALER
-   Copyright (C) 2022 Taler Systems SA
+   Copyright (C) 2022, 2023 Taler Systems SA
 
    TALER is free software; you can redistribute it and/or modify it under the
    terms of the GNU General Public License as published by the Free Software
@@ -33,15 +33,16 @@ TEH_PG_get_ready_deposit (void *cls,
                           struct TALER_MerchantPublicKeyP *merchant_pub,
                           char **payto_uri)
 {
+  static int choose_mode = -2;
   struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Absolute now = {0};
+  struct GNUNET_TIME_Absolute now
+    = GNUNET_TIME_absolute_get ();
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_absolute_time (&now),
     GNUNET_PQ_query_param_uint64 (&start_shard_row),
     GNUNET_PQ_query_param_uint64 (&end_shard_row),
     GNUNET_PQ_query_param_end
   };
-
   struct GNUNET_PQ_ResultSpec rs[] = {
     GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
                                           merchant_pub),
@@ -49,181 +50,70 @@ TEH_PG_get_ready_deposit (void *cls,
                                   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);
-  int choose_mode =-2;
   const char *query;
 
   if (-2 == choose_mode)
   {
-    const char *mode = getenv ("NEW_LOGIC");
+    const char *mode = getenv ("TALER_POSTGRES_GET_READY_LOGIC");
     char dummy;
+
     if ( (NULL==mode) ||
          (1 != sscanf (mode,
                        "%d%c",
                        &choose_mode,
                        &dummy)) )
-      {
-        if (NULL != mode)
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Bad mode `%s' specified\n",
-                      mode);
-      }
-    if (NULL==mode)
-      choose_mode=0;
-
-
+    {
+      if (NULL != mode)
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Bad mode `%s' specified\n",
+                    mode);
+      choose_mode = 0;
+    }
   }
   switch (choose_mode)
   {
   case 0:
-    query="deposits_get_ready";
+    query = "deposits_get_ready-v5";
     PREPARE (pg,
              query,
              "SELECT"
              " payto_uri"
              ",merchant_pub"
-             " FROM deposits_by_ready dbr"
-             "  JOIN deposits dep"
-             "    ON (dbr.coin_pub = dep.coin_pub AND"
-             "        dbr.deposit_serial_id = dep.deposit_serial_id)"
-             "  JOIN wire_targets wt"
-             "    USING (wire_target_h_payto)"
-             " WHERE dbr.wire_deadline<=$1"
-             "   AND dbr.shard >= $2"
-             "   AND dbr.shard <= $3"
+             " FROM deposits dep"
+             " JOIN wire_targets wt"
+             "   USING (wire_target_h_payto)"
+             " WHERE NOT (done OR policy_blocked)"
+             "   AND dep.wire_deadline<=$1"
+             "   AND dep.shard >= $2"
+             "   AND dep.shard <= $3"
              " ORDER BY "
-             "   dbr.wire_deadline ASC"
-             "  ,dbr.shard ASC"
+             "   dep.wire_deadline ASC"
+             "  ,dep.shard ASC"
              " LIMIT 1;");
     break;
   case 1:
-    query="deposits_get_ready_v1";
+    query = "deposits_get_ready-v6";
     PREPARE (pg,
              query,
              "WITH rc AS MATERIALIZED ("
              " SELECT"
-             " coin_pub"
-             ",deposit_serial_id"
-             " FROM deposits_by_ready"
-             " WHERE"
-             " wire_deadline<=$1"
-             " AND shard >= $2"
-             " AND shard <= $3"
-             " ORDER BY "
-             "   wire_deadline ASC"
-             "  ,shard ASC"
-             "  LIMIT 1"
-             ")"
-             "SELECT"
-             " wt.payto_uri"
-             ",dep.merchant_pub"
-             " FROM ("
-             " SELECT"
-             " wire_target_h_payto"
-             ",merchant_pub"
+             " merchant_pub"
+             ",wire_target_h_payto"
              " FROM deposits"
-             " WHERE coin_pub=(SELECT coin_pub FROM rc)"
-             " AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)"
-             ") dep"
-             "  JOIN wire_targets wt"
-             "    ON (dep.wire_target_h_payto = wt.wire_target_h_payto)"
-             );
-
-    break;
-  case 2:
-    query = "stored_procedure_get_ready_deposit";
-    PREPARE (pg,
-             query,
-             "SELECT"
-             " out_payto_uri AS payto_uri"
-             ",out_merchant_pub AS merchant_pub"
-             " FROM"
-             " exchange_do_get_ready_deposit"
-             " ($1, $2, $3) ");
-    break;
-  case 3:
-    query="deposits_get_ready_v3";
-    PREPARE (pg,
-             query,
-             "WITH rc AS MATERIALIZED ("
-             " SELECT"
-             " coin_pub"
-             ",deposit_serial_id"
-             " FROM deposits_by_ready"
-             " WHERE"
-             " wire_deadline<=$1"
-             " AND shard >= $2"
-             " AND shard <= $3"
-             " ORDER BY "
-             "   wire_deadline ASC"
+             " WHERE NOT (done OR policy_blocked)"
+             "   AND wire_deadline<=$1"
+             "   AND shard >= $2"
+             "   AND shard <= $3"
+             " ORDER BY wire_deadline ASC"
              "  ,shard ASC"
              "  LIMIT 1"
              ")"
              "SELECT"
              " wt.payto_uri"
-             ",dep.merchant_pub"
-             " FROM ("
-             " SELECT"
-             " wire_target_h_payto"
-             ",merchant_pub"
-             ",coin_pub"
-             " FROM deposits"
-             " WHERE coin_pub=(SELECT coin_pub FROM rc)"
-             " AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)"
-             ") dep"
-             "  JOIN wire_targets wt"
-             "    ON (dep.wire_target_h_payto = wt.wire_target_h_payto)"
-             "  JOIN rc"
-             "    ON (dep.coin_pub=rc.coin_pub)"
-             );
-
-    break;
-  case 4:
-    query="deposits_get_ready_v4";
-    PREPARE (pg,
-             query,
-             "WITH rc AS MATERIALIZED ("
-             " SELECT"
-             " coin_pub"
-             ",deposit_serial_id"
-             " FROM deposits_by_ready"
-             " WHERE"
-             " wire_deadline<=$1"
-             " AND shard >= $2"
-             " AND shard <= $3"
-             " ORDER BY "
-             "   wire_deadline ASC"
-             "  ,shard ASC"
-             "  LIMIT 1"
-             "),"
-             "WITH rv AS MATERIALIZED ("
-             " SELECT"
-             " payto_uri"
-             ",wire_target_h_payto"
-             " FROM wire_targets"
-             ")"
-             "SELECT"
-             " rv.payto_uri"
-             ",dep.merchant_pub"
-             " FROM ("
-             " SELECT"
-             " wire_target_h_payto"
-             ",merchant_pub"
-             " FROM deposits"
-             " WHERE coin_pub=(SELECT coin_pub FROM rc)"
-             " AND deposit_serial_id=(SELECT deposit_serial_id FROM rc)"
-             ") dep"
-             " JOIN rv"
-             "  ON (rv.wire_target_h_payto=dep.wire_target_h_payto)"
-             );
+             ",rc.merchant_pub"
+             " FROM wire_targets wt"
+             " JOIN rc"
+             "   USING (wire_target_h_payto);");
     break;
   default:
     GNUNET_break (0);
diff --git a/src/exchangedb/pg_reserves_in_insert.c 
b/src/exchangedb/pg_reserves_in_insert.c
index 0fdc4a16..314e89d8 100644
--- a/src/exchangedb/pg_reserves_in_insert.c
+++ b/src/exchangedb/pg_reserves_in_insert.c
@@ -27,6 +27,8 @@
 #include "pg_start.h"
 #include "pg_start_read_committed.h"
 #include "pg_commit.h"
+#include "pg_preflight.h"
+#include "pg_rollback.h"
 #include "pg_reserves_get.h"
 #include "pg_reserves_update.h"
 #include "pg_setup_wire_target.h"
@@ -34,15 +36,13 @@
 
 
 /**
- * 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
+ * @return string to pass to postgres for the notification
  */
-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)),
@@ -50,246 +50,868 @@ 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);
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert1 (struct PostgresClosure *pg,
+         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[1],
+         struct GNUNET_TIME_Timestamp expiry,
+         struct GNUNET_TIME_Timestamp gc,
+         struct TALER_PaytoHashP h_payto,
+         char *const *notify_s,
+         struct GNUNET_TIME_Timestamp reserve_expiration,
+         bool *transaction_duplicate,
+         bool *conflict,
+         uint64_t *reserve_uuid,
+         enum GNUNET_DB_QueryStatus results[1])
+{
+  enum GNUNET_DB_QueryStatus qs2;
+  PREPARE (pg,
+           "batch1_reserve_create",
+           "SELECT "
+           " out_reserve_found AS conflicted"
+           ",transaction_duplicate"
+           ",ruuid AS reserve_uuid"
+           " FROM exchange_do_batch_reserves_in_insert"
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);");
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
+    GNUNET_PQ_query_param_timestamp (&expiry),
+    GNUNET_PQ_query_param_timestamp (&gc),
+    GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
+    TALER_PQ_query_param_amount (reserves[0].balance),
+    GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_string (notify_s[0]),
+    GNUNET_PQ_query_param_end
+  };
+
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_bool ("conflicted",
+                                &conflict[0]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                &transaction_duplicate[0]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                  &reserve_uuid[0]),
+    GNUNET_PQ_result_spec_end
+  };
+
+
+  TALER_payto_hash (reserves[0].sender_account_details,
+                    &h_payto);
+
+  qs2 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                  "batch1_reserve_create",
+                                                  params,
+                                                  rs);
+
+  if (qs2 < 0)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to create reserves 1(%d)\n",
+                qs2);
+    results[0] = qs2;
+    return qs2;
+  }
+  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs2);
+  if ((! conflict[0]) && transaction_duplicate[0])
+  {
+    GNUNET_break (0);
+    TEH_PG_rollback (pg);
+    results[0] = GNUNET_DB_STATUS_HARD_ERROR;
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+  return qs2;
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert2 (struct PostgresClosure *pg,
+         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[2],
+         struct GNUNET_TIME_Timestamp expiry,
+         struct GNUNET_TIME_Timestamp gc,
+         struct TALER_PaytoHashP h_payto,
+         char *const*notify_s,
+         struct GNUNET_TIME_Timestamp reserve_expiration,
+         bool *transaction_duplicate,
+         bool *conflict,
+         uint64_t *reserve_uuid,
+         enum GNUNET_DB_QueryStatus results[1])
+{
+  enum GNUNET_DB_QueryStatus qs1;
+  PREPARE (pg,
+           "batch2_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 exchange_do_batch2_reserves_insert"
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22);");
+
+  struct GNUNET_PQ_QueryParam params[] = {
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
+    GNUNET_PQ_query_param_timestamp (&expiry),
+    GNUNET_PQ_query_param_timestamp (&gc),
+    GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
+    TALER_PQ_query_param_amount (reserves[0].balance),
+    GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_string (notify_s[0]),
+    GNUNET_PQ_query_param_string (notify_s[1]),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
+    TALER_PQ_query_param_amount (reserves[1].balance),
+    GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[1].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",
+                                &conflict[0]),
+    GNUNET_PQ_result_spec_bool ("conflicted2",
+                                &conflict[1]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                &transaction_duplicate[0]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
+                                &transaction_duplicate[1]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                  &reserve_uuid[0]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
+                                  &reserve_uuid[1]),
+    GNUNET_PQ_result_spec_end
+  };
+
+  TALER_payto_hash (reserves[0].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[1].sender_account_details,
+                    &h_payto);
+
+
+  qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                  "batch2_reserve_create",
+                                                  params,
+                                                  rs);
+  if (qs1 < 0)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to create reserves 2(%d)\n",
+                qs1);
+    results[0] = 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;*/
+
+  if (
+    ((! conflict[0]) && (transaction_duplicate[0]))
+    || ((! conflict[1]) && (transaction_duplicate[1]))
+    )
+  {
+    GNUNET_break (0);
+    TEH_PG_rollback (pg);  // ROLLBACK
+    results[0] = GNUNET_DB_STATUS_HARD_ERROR;
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+  return qs1;
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert4 (struct PostgresClosure *pg,
+         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[4],
+         struct GNUNET_TIME_Timestamp expiry,
+         struct GNUNET_TIME_Timestamp gc,
+         struct TALER_PaytoHashP h_payto,
+         char *const*notify_s,
+         struct GNUNET_TIME_Timestamp reserve_expiration,
+         bool *transaction_duplicate,
+         bool *conflict,
+         uint64_t *reserve_uuid,
+         enum GNUNET_DB_QueryStatus results[1])
+{
+  enum GNUNET_DB_QueryStatus qs3;
+  PREPARE (pg,
+           "batch4_reserve_create",
+           "SELECT "
+           "out_reserve_found AS conflicted"
+           ",out_reserve_found2 AS conflicted2"
+           ",out_reserve_found3 AS conflicted3"
+           ",out_reserve_found4 AS conflicted4"
+           ",transaction_duplicate"
+           ",transaction_duplicate2"
+           ",transaction_duplicate3"
+           ",transaction_duplicate4"
+           ",ruuid AS reserve_uuid"
+           ",ruuid2 AS reserve_uuid2"
+           ",ruuid3 AS reserve_uuid3"
+           ",ruuid4 AS reserve_uuid4"
+           " FROM exchange_do_batch4_reserves_insert"
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,
 $40, $41,$42);");
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
+    GNUNET_PQ_query_param_timestamp (&expiry),
+    GNUNET_PQ_query_param_timestamp (&gc),
+    GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
+    TALER_PQ_query_param_amount (reserves[0].balance),
+    GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_string (notify_s[0]),
+    GNUNET_PQ_query_param_string (notify_s[1]),
+    GNUNET_PQ_query_param_string (notify_s[2]),
+    GNUNET_PQ_query_param_string (notify_s[3]),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
+    TALER_PQ_query_param_amount (reserves[1].balance),
+    GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[1].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference),
+    TALER_PQ_query_param_amount (reserves[2].balance),
+    GNUNET_PQ_query_param_string (reserves[2].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[2].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference),
+    TALER_PQ_query_param_amount (reserves[3].balance),
+    GNUNET_PQ_query_param_string (reserves[3].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[3].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",
+                                &conflict[0]),
+    GNUNET_PQ_result_spec_bool ("conflicted2",
+                                &conflict[1]),
+    GNUNET_PQ_result_spec_bool ("conflicted3",
+                                &conflict[2]),
+    GNUNET_PQ_result_spec_bool ("conflicted4",
+                                &conflict[3]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                &transaction_duplicate[0]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
+                                &transaction_duplicate[1]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
+                                &transaction_duplicate[2]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
+                                &transaction_duplicate[3]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                  &reserve_uuid[0]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
+                                  &reserve_uuid[1]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
+                                  &reserve_uuid[2]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
+                                  &reserve_uuid[3]),
+    GNUNET_PQ_result_spec_end
+  };
+
+  TALER_payto_hash (reserves[0].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[1].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[2].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[3].sender_account_details,
+                    &h_payto);
+
+  qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                  "batch4_reserve_create",
+                                                  params,
+                                                  rs);
+  if (qs3 < 0)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to create reserves4 (%d)\n",
+                qs3);
+    results[0] = qs3;
+    return qs3;
+  }
+
+  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3);
+
+  if (
+    ((! conflict[0]) && (transaction_duplicate[0]))
+    || ((! conflict[1]) && (transaction_duplicate[1]))
+    || ((! conflict[2]) && (transaction_duplicate[2]))
+    || ((! conflict[3]) && (transaction_duplicate[3]))
+    )
+  {
+    GNUNET_break (0);
+    TEH_PG_rollback (pg);
+    results[0] = GNUNET_DB_STATUS_HARD_ERROR;
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+  return qs3;
+}
+
+
+static enum GNUNET_DB_QueryStatus
+insert8 (struct PostgresClosure *pg,
+         const struct TALER_EXCHANGEDB_ReserveInInfo reserves[8],
+         struct GNUNET_TIME_Timestamp expiry,
+         struct GNUNET_TIME_Timestamp gc,
+         struct TALER_PaytoHashP h_payto,
+         char *const*notify_s,
+         struct GNUNET_TIME_Timestamp reserve_expiration,
+         bool *transaction_duplicate,
+         bool *conflict,
+         uint64_t *reserve_uuid,
+         enum GNUNET_DB_QueryStatus results[1])
+{
+  enum GNUNET_DB_QueryStatus qs3;
+  PREPARE (pg,
+           "batch8_reserve_create",
+           "SELECT "
+           "out_reserve_found AS conflicted"
+           ",out_reserve_found2 AS conflicted2"
+           ",out_reserve_found3 AS conflicted3"
+           ",out_reserve_found4 AS conflicted4"
+           ",out_reserve_found5 AS conflicted5"
+           ",out_reserve_found6 AS conflicted6"
+           ",out_reserve_found7 AS conflicted7"
+           ",out_reserve_found8 AS conflicted8"
+           ",transaction_duplicate"
+           ",transaction_duplicate2"
+           ",transaction_duplicate3"
+           ",transaction_duplicate4"
+           ",transaction_duplicate5"
+           ",transaction_duplicate6"
+           ",transaction_duplicate7"
+           ",transaction_duplicate8"
+           ",ruuid AS reserve_uuid"
+           ",ruuid2 AS reserve_uuid2"
+           ",ruuid3 AS reserve_uuid3"
+           ",ruuid4 AS reserve_uuid4"
+           ",ruuid5 AS reserve_uuid5"
+           ",ruuid6 AS reserve_uuid6"
+           ",ruuid7 AS reserve_uuid7"
+           ",ruuid8 AS reserve_uuid8"
+           " FROM exchange_do_batch8_reserves_insert"
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,
 $40, 
$41,$42,$43,$44,$45,$46,$47,$48,$49,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$80,$81,$82);");
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
+    GNUNET_PQ_query_param_timestamp (&expiry),
+    GNUNET_PQ_query_param_timestamp (&gc),
+    GNUNET_PQ_query_param_uint64 (&reserves[0].wire_reference),
+    TALER_PQ_query_param_amount (reserves[0].balance),
+    GNUNET_PQ_query_param_string (reserves[0].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[0].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[0].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_string (notify_s[0]),
+    GNUNET_PQ_query_param_string (notify_s[1]),
+    GNUNET_PQ_query_param_string (notify_s[2]),
+    GNUNET_PQ_query_param_string (notify_s[3]),
+    GNUNET_PQ_query_param_string (notify_s[4]),
+    GNUNET_PQ_query_param_string (notify_s[5]),
+    GNUNET_PQ_query_param_string (notify_s[6]),
+    GNUNET_PQ_query_param_string (notify_s[7]),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[1].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[1].wire_reference),
+    TALER_PQ_query_param_amount (reserves[1].balance),
+    GNUNET_PQ_query_param_string (reserves[1].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[1].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[1].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[2].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[2].wire_reference),
+    TALER_PQ_query_param_amount (reserves[2].balance),
+    GNUNET_PQ_query_param_string (reserves[2].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[2].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[2].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[3].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[3].wire_reference),
+    TALER_PQ_query_param_amount (reserves[3].balance),
+    GNUNET_PQ_query_param_string (reserves[3].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[3].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[3].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[4].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[4].wire_reference),
+    TALER_PQ_query_param_amount (reserves[4].balance),
+    GNUNET_PQ_query_param_string (reserves[4].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[4].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[4].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[5].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[5].wire_reference),
+    TALER_PQ_query_param_amount (reserves[5].balance),
+    GNUNET_PQ_query_param_string (reserves[5].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[5].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[5].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[6].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[6].wire_reference),
+    TALER_PQ_query_param_amount (reserves[6].balance),
+    GNUNET_PQ_query_param_string (reserves[6].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[6].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[6].sender_account_details),
+    GNUNET_PQ_query_param_timestamp (&reserve_expiration),
+
+    GNUNET_PQ_query_param_auto_from_type (reserves[7].reserve_pub),
+    GNUNET_PQ_query_param_uint64 (&reserves[7].wire_reference),
+    TALER_PQ_query_param_amount (reserves[7].balance),
+    GNUNET_PQ_query_param_string (reserves[7].exchange_account_name),
+    GNUNET_PQ_query_param_timestamp (&reserves[7].execution_time),
+    GNUNET_PQ_query_param_auto_from_type (&h_payto),
+    GNUNET_PQ_query_param_string (reserves[7].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",
+                                &conflict[0]),
+    GNUNET_PQ_result_spec_bool ("conflicted2",
+                                &conflict[1]),
+    GNUNET_PQ_result_spec_bool ("conflicted3",
+                                &conflict[2]),
+    GNUNET_PQ_result_spec_bool ("conflicted4",
+                                &conflict[3]),
+    GNUNET_PQ_result_spec_bool ("conflicted5",
+                                &conflict[4]),
+    GNUNET_PQ_result_spec_bool ("conflicted6",
+                                &conflict[5]),
+    GNUNET_PQ_result_spec_bool ("conflicted7",
+                                &conflict[6]),
+    GNUNET_PQ_result_spec_bool ("conflicted8",
+                                &conflict[7]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate",
+                                &transaction_duplicate[0]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate2",
+                                &transaction_duplicate[1]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate3",
+                                &transaction_duplicate[2]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate4",
+                                &transaction_duplicate[3]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate5",
+                                &transaction_duplicate[4]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate6",
+                                &transaction_duplicate[5]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate7",
+                                &transaction_duplicate[6]),
+    GNUNET_PQ_result_spec_bool ("transaction_duplicate8",
+                                &transaction_duplicate[7]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
+                                  &reserve_uuid[0]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid2",
+                                  &reserve_uuid[1]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid3",
+                                  &reserve_uuid[2]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid4",
+                                  &reserve_uuid[3]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid5",
+                                  &reserve_uuid[4]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid6",
+                                  &reserve_uuid[5]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid7",
+                                  &reserve_uuid[6]),
+    GNUNET_PQ_result_spec_uint64 ("reserve_uuid8",
+                                  &reserve_uuid[7]),
+    GNUNET_PQ_result_spec_end
+  };
+
+  TALER_payto_hash (reserves[0].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[1].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[2].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[3].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[4].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[5].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[6].sender_account_details,
+                    &h_payto);
+  TALER_payto_hash (reserves[7].sender_account_details,
+                    &h_payto);
+
+  qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                  "batch8_reserve_create",
+                                                  params,
+                                                  rs);
+  if (qs3 < 0)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to create reserves8 (%d)\n",
+                qs3);
+    results[0] = qs3;
+    return qs3;
+  }
+
+  GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs3);
+  /*   results[i] = (transaction_duplicate)
+     ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+     : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;*/
+
+  if (
+    ((! conflict[0]) && (transaction_duplicate[0]))
+    || ((! conflict[1]) && (transaction_duplicate[1]))
+    || ((! conflict[2]) && (transaction_duplicate[2]))
+    || ((! conflict[3]) && (transaction_duplicate[3]))
+    || ((! conflict[4]) && (transaction_duplicate[4]))
+    || ((! conflict[5]) && (transaction_duplicate[5]))
+    || ((! conflict[6]) && (transaction_duplicate[6]))
+    || ((! conflict[7]) && (transaction_duplicate[7]))
+    )
+  {
+    GNUNET_break (0);
+    TEH_PG_rollback (pg);
+    results[0] = GNUNET_DB_STATUS_HARD_ERROR;
+    return GNUNET_DB_STATUS_HARD_ERROR;
+  }
+  results[0] = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+  return qs3;
 }
 
 
 enum GNUNET_DB_QueryStatus
 TEH_PG_reserves_in_insert (void *cls,
-                           const struct TALER_ReservePublicKeyP *reserve_pub,
-                           const struct TALER_Amount *balance,
-                           struct GNUNET_TIME_Timestamp execution_time,
-                           const char *sender_account_details,
-                           const char *exchange_account_section,
-                           uint64_t wire_ref)
+                           const struct
+                           TALER_EXCHANGEDB_ReserveInInfo *reserves,
+                           unsigned int reserves_length,
+                           unsigned int batch_size,
+                           enum GNUNET_DB_QueryStatus *results)
 {
   struct PostgresClosure *pg = cls;
   enum GNUNET_DB_QueryStatus qs1;
-  struct TALER_EXCHANGEDB_Reserve reserve;
+  enum GNUNET_DB_QueryStatus qs2;
+  enum GNUNET_DB_QueryStatus qs4;
+  enum GNUNET_DB_QueryStatus qs5;
   struct GNUNET_TIME_Timestamp expiry;
   struct GNUNET_TIME_Timestamp gc;
-  uint64_t reserve_uuid;
+  struct TALER_PaytoHashP h_payto;
+  uint64_t reserve_uuid[reserves_length];
+  bool transaction_duplicate[reserves_length];
+  bool need_update = false;
+  bool t_duplicate = 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;
+  }
 
-  reserve.pub = *reserve_pub;
   expiry = GNUNET_TIME_absolute_to_timestamp (
-    GNUNET_TIME_absolute_add (execution_time.abs_time,
+    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 (reserve_pub),
+              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++)
   {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-      TALER_PQ_query_param_amount (balance),
-      GNUNET_PQ_query_param_timestamp (&expiry),
-      GNUNET_PQ_query_param_timestamp (&gc),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &reserve_uuid),
-      GNUNET_PQ_result_spec_end
-    };
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Reserve does not exist; creating a new one\n");
-    /* Note: query uses 'on conflict do nothing' */
-    PREPARE (pg,
-             "reserve_create",
-             "INSERT INTO reserves "
-             "(reserve_pub"
-             ",current_balance_val"
-             ",current_balance_frac"
-             ",expiration_date"
-             ",gc_date"
-             ") VALUES "
-             "($1, $2, $3, $4, $5)"
-             " ON CONFLICT DO NOTHING"
-             " RETURNING reserve_uuid;");
-    qs1 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                    "reserve_create",
-                                                    params,
-                                                    rs);
-    if (qs1 < 0)
-      return qs1;
+    const struct TALER_EXCHANGEDB_ReserveInInfo *reserve = &reserves[i];
+
+    notify_s[i] = compute_notify_on_reserve (reserve->reserve_pub);
   }
 
-  /* Create new incoming transaction, "ON CONFLICT DO NOTHING"
-     is again used to guard against duplicates. */
+  unsigned int i = 0;
+
+  while (i < reserves_length)
   {
-    enum GNUNET_DB_QueryStatus qs2;
-    enum GNUNET_DB_QueryStatus qs3;
-    struct TALER_PaytoHashP h_payto;
-
-    qs3 = TEH_PG_setup_wire_target (pg,
-                                    sender_account_details,
-                                    &h_payto);
-    if (qs3 < 0)
-      return qs3;
-    /* We do not have the UUID, so insert by public key */
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (&reserve.pub),
-      GNUNET_PQ_query_param_uint64 (&wire_ref),
-      TALER_PQ_query_param_amount (balance),
-      GNUNET_PQ_query_param_string (exchange_account_section),
-      GNUNET_PQ_query_param_auto_from_type (&h_payto),
-      GNUNET_PQ_query_param_timestamp (&execution_time),
-      GNUNET_PQ_query_param_end
-    };
-
-    PREPARE (pg,
-             "reserves_in_add_transaction",
-             "INSERT INTO reserves_in "
-             "(reserve_pub"
-             ",wire_reference"
-             ",credit_val"
-             ",credit_frac"
-             ",exchange_account_section"
-             ",wire_source_h_payto"
-             ",execution_date"
-             ") VALUES ($1, $2, $3, $4, $5, $6, $7)"
-             " ON CONFLICT DO NOTHING;");
-    qs2 = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                              "reserves_in_add_transaction",
-                                              params);
-    /* qs2 could be 0 as statement used 'ON CONFLICT DO NOTHING' */
-    if (0 >= qs2)
+    unsigned int bs = GNUNET_MIN (batch_size,
+                                  reserves_length - i);
+    if (bs >= 8)
     {
-      if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs2) &&
-           (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs1) )
+      qs1 = insert8 (pg,
+                     &reserves[i],
+                     expiry,
+                     gc,
+                     h_payto,
+                     &notify_s[i],
+                     reserve_expiration,
+                     &transaction_duplicate[i],
+                     &conflicts[i],
+                     &reserve_uuid[i],
+                     &results[i]);
+
+      if (qs1<0)
       {
-        /* Conflict for the transaction, but the reserve was
-           just now created, that should be impossible. */
-        GNUNET_break (0); /* should be impossible: reserve was fresh,
-                             but transaction already known */
-        return GNUNET_DB_STATUS_HARD_ERROR;
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to create reserve batch_8 (%d)\n",
+                    qs1);
+        return qs1;
       }
-      /* Transaction was already known or error. We are finished. */
-      return qs2;
+      need_update |= conflicts[i];
+      need_update |= conflicts[i + 1];
+      need_update |= conflicts[i + 2];
+      need_update |= conflicts[i + 3];
+      need_update |= conflicts[i + 4];
+      need_update |= conflicts[i + 5];
+      need_update |= conflicts[i + 6];
+      need_update |= conflicts[i + 7];
+      t_duplicate |= transaction_duplicate[i];
+      t_duplicate |= transaction_duplicate[i + 1];
+      t_duplicate |= transaction_duplicate[i + 2];
+      t_duplicate |= transaction_duplicate[i + 3];
+      t_duplicate |= transaction_duplicate[i + 4];
+      t_duplicate |= transaction_duplicate[i + 5];
+      t_duplicate |= transaction_duplicate[i + 6];
+      t_duplicate |= transaction_duplicate[i + 7];
+      i += 8;
+      continue;
     }
-  }
-  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs1)
-  {
-    /* New reserve, we are finished */
-    notify_on_reserve (pg,
-                       reserve_pub);
-    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-  }
+    switch (bs)
+    {
+    case 7:
+    case 6:
+    case 5:
+    case 4:
+      qs4 = insert4 (pg,
+                     &reserves[i],
+                     expiry,
+                     gc,
+                     h_payto,
+                     &notify_s[i],
+                     reserve_expiration,
+                     &transaction_duplicate[i],
+                     &conflicts[i],
+                     &reserve_uuid[i],
+                     &results[i]);
 
-  /* we were wrong with our optimistic assumption:
-     reserve did already exist, need to do an update instead */
+      if (qs4<0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to create reserve batch_4 (%d)\n",
+                    qs4);
+        return qs4;
+      }
+      need_update |= conflicts[i];
+      need_update |= conflicts[i + 1];
+      need_update |= conflicts[i + 2];
+      need_update |= conflicts[i + 3];
+      t_duplicate |= transaction_duplicate[i];
+      t_duplicate |= transaction_duplicate[i + 1];
+      t_duplicate |= transaction_duplicate[i + 2];
+      t_duplicate |= transaction_duplicate[i + 3];
+      //  fprintf(stdout, "reserve_uuid : %ld %ld %ld %ld\n", reserve_uuid[i], 
reserve_uuid[i+1], reserve_uuid[i+2], reserve_uuid[i+3]);
+      i += 4;
+      break;
+    case 3:
+    case 2:
+      qs5 = insert2 (pg,
+                     &reserves[i],
+                     expiry,
+                     gc,
+                     h_payto,
+                     &notify_s[i],
+                     reserve_expiration,
+                     &transaction_duplicate[i],
+                     &conflicts[i],
+                     &reserve_uuid[i],
+                     &results[i]);
+      if (qs5<0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to create reserve batch_2 (%d)\n",
+                    qs5);
+        return qs5;
+      }
+      need_update |= conflicts[i];
+      need_update |= conflicts[i + 1];
+      t_duplicate |= transaction_duplicate[i];
+      t_duplicate |= transaction_duplicate[i + 1];
+      results[i] = (t_duplicate)
+      ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+      : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+      //   fprintf(stdout, "reserve_uuid : %ld %ld\n", reserve_uuid[i], 
reserve_uuid[i+1]);
+      i += 2;
+      break;
+    case 1:
+      qs2 = insert1 (pg,
+                     &reserves[i],
+                     expiry,
+                     gc,
+                     h_payto,
+                     &notify_s[i],
+                     reserve_expiration,
+                     &transaction_duplicate[i],
+                     &conflicts[i],
+                     &reserve_uuid[i],
+                     &results[i]);
+      if (qs2<0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to create reserve batch_1 (%d)\n)"
+                    ,qs2);
+        return qs2;
+      }
+      need_update |= conflicts[i];
+      t_duplicate |= transaction_duplicate[i];
+      //  fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], 
conflicts[i], transaction_duplicate[i]);
+      i += 1;
+      break;
+    case 0:
+      GNUNET_assert (0);
+      break;
+    }
+  } /* end while */
+  // commit
   {
-    /* We need to move away from 'read committed' to serializable.
-       Also, we know that it should be safe to commit at this point.
-       (We are only run in a larger transaction for performance.) */
     enum GNUNET_DB_QueryStatus cs;
 
     cs = TEH_PG_commit (pg);
     if (cs < 0)
-      return cs;
-    if (GNUNET_OK !=
-        TEH_PG_start (pg,
-                      "reserve-update-serializable"))
     {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to commit\n");
+      return cs;
     }
   }
+  if (! need_update)
   {
-    enum GNUNET_DB_QueryStatus reserve_exists;
-
-    reserve_exists = TEH_PG_reserves_get (pg,
-                                          &reserve);
-    switch (reserve_exists)
+    goto exit;
+  }
+  // begin serializable
+  {
+    if (GNUNET_OK !=
+        TEH_PG_start (pg,
+                      "reserve-insert-continued"))
     {
-    case GNUNET_DB_STATUS_HARD_ERROR:
       GNUNET_break (0);
-      return reserve_exists;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      return reserve_exists;
-    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      /* First we got a conflict, but then we cannot select? Very strange. */
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_SOFT_ERROR;
-    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-      /* continued below */
-      break;
+      return GNUNET_DB_STATUS_HARD_ERROR;
     }
   }
 
+  enum GNUNET_DB_QueryStatus qs3;
+  PREPARE (pg,
+           "reserves_update",
+           "SELECT"
+           " out_duplicate AS duplicate "
+           "FROM exchange_do_batch_reserves_update"
+           " ($1,$2,$3,$4,$5,$6,$7,$8);");
+  for (unsigned int i = 0; i<reserves_length; i++)
   {
-    struct TALER_EXCHANGEDB_Reserve updated_reserve;
-    enum GNUNET_DB_QueryStatus qs3;
-
-    /* If the reserve already existed, we need to still update the
-       balance; we do this after checking for duplication, as
-       otherwise we might have to actually pay the cost to roll this
-       back for duplicate transactions; like this, we should virtually
-       never actually have to rollback anything. */
-    updated_reserve.pub = reserve.pub;
-    if (0 >
-        TALER_amount_add (&updated_reserve.balance,
-                          &reserve.balance,
-                          balance))
+    if (! conflicts[i])
+      continue;
     {
-      /* currency overflow or incompatible currency */
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Attempt to deposit incompatible amount into reserve\n");
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    updated_reserve.expiry = GNUNET_TIME_timestamp_max (expiry,
-                                                        reserve.expiry);
-    updated_reserve.gc = GNUNET_TIME_timestamp_max (gc,
-                                                    reserve.gc);
-    qs3 = TEH_PG_reserves_update (pg,
-                                  &updated_reserve);
-    switch (qs3)
-    {
-    case GNUNET_DB_STATUS_HARD_ERROR:
-      GNUNET_break (0);
-      return qs3;
-    case GNUNET_DB_STATUS_SOFT_ERROR:
-      return qs3;
-    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      /* How can the UPDATE not work here? Very strange. */
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-      /* continued below */
-      break;
+      bool duplicate;
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (reserves[i].reserve_pub),
+        GNUNET_PQ_query_param_timestamp (&expiry),
+        GNUNET_PQ_query_param_uint64 (&reserves[i].wire_reference),
+        TALER_PQ_query_param_amount (reserves[i].balance),
+        GNUNET_PQ_query_param_string (reserves[i].exchange_account_name),
+        GNUNET_PQ_query_param_auto_from_type (&h_payto),
+        GNUNET_PQ_query_param_string (notify_s[i]),
+        GNUNET_PQ_query_param_end
+      };
+      struct GNUNET_PQ_ResultSpec rs[] = {
+        GNUNET_PQ_result_spec_bool ("duplicate",
+                                    &duplicate),
+        GNUNET_PQ_result_spec_end
+      };
+      qs3 = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                      "reserves_update",
+                                                      params,
+                                                      rs);
+      if (qs3<0)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Failed to update reserves (%d)\n",
+                    qs3);
+        results[i] = qs3;
+        return qs3;
+      }
+      results[i] = duplicate
+          ? GNUNET_DB_STATUS_SUCCESS_NO_RESULTS
+          : GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     }
   }
-  notify_on_reserve (pg,
-                     reserve_pub);
-  /* Go back to original transaction mode */
+
   {
     enum GNUNET_DB_QueryStatus cs;
 
     cs = TEH_PG_commit (pg);
     if (cs < 0)
       return cs;
-    if (GNUNET_OK !=
-        TEH_PG_start_read_committed (pg,
-                                     "reserve-insert-continued"))
-    {
-      GNUNET_break (0);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
   }
-  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+
+exit:
+  for (unsigned int i = 0; i<reserves_length; i++)
+    GNUNET_free (notify_s[i]);
+
+  return reserves_length;
 }
diff --git a/src/exchangedb/pg_reserves_in_insert.h 
b/src/exchangedb/pg_reserves_in_insert.h
index 85401938..f92843e7 100644
--- a/src/exchangedb/pg_reserves_in_insert.h
+++ b/src/exchangedb/pg_reserves_in_insert.h
@@ -24,28 +24,26 @@
 #include "taler_util.h"
 #include "taler_json_lib.h"
 #include "taler_exchangedb_plugin.h"
+
+
 /**
  * Insert an incoming transaction into reserves.  New reserves are also
- * created through this function. Started within the scope of an ongoing
- * transaction.
+ * created through this function. Runs its own transaction(s).
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param reserve_pub public key of the reserve
- * @param balance the amount that has to be added to the reserve
- * @param execution_time when was the amount added
- * @param sender_account_details account information for the sender 
(payto://-URL)
- * @param exchange_account_section name of the section in the configuration 
for the exchange's
- *                       account into which the deposit was made
- * @param wire_ref unique reference identifying the wire transfer
+ * @param reserves array of reserves to insert
+ * @param reserves_length length of the @a reserves array
+ * @param batch_size how many inserts to do in one go
+ * @param[out] results set to query status per reserve, must be of length @a 
reserves_length
  * @return transaction status code
  */
 enum GNUNET_DB_QueryStatus
-TEH_PG_reserves_in_insert (void *cls,
-                             const struct TALER_ReservePublicKeyP *reserve_pub,
-                             const struct TALER_Amount *balance,
-                             struct GNUNET_TIME_Timestamp execution_time,
-                             const char *sender_account_details,
-                             const char *exchange_account_section,
-                           uint64_t wire_ref);
+TEH_PG_reserves_in_insert (
+  void *cls,
+  const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
+  unsigned int reserves_length,
+  unsigned int batch_size,
+  enum GNUNET_DB_QueryStatus *results);
+
 
 #endif
diff --git a/src/exchangedb/pg_select_refunds_by_coin.c 
b/src/exchangedb/pg_select_refunds_by_coin.c
index 255cac34..7325b359 100644
--- a/src/exchangedb/pg_select_refunds_by_coin.c
+++ b/src/exchangedb/pg_select_refunds_by_coin.c
@@ -129,7 +129,7 @@ TEH_PG_select_refunds_by_coin (
 
   if (-2 == percent_refund)
   {
-    const char *mode = getenv ("NEW_LOGIC");
+    const char *mode = getenv ("TALER_POSTGRES_SELECT_REFUNDS_BY_COIN_LOGIC");
     char dummy;
 
     if ( (NULL==mode) ||
@@ -137,14 +137,13 @@ TEH_PG_select_refunds_by_coin (
                        "%d%c",
                        &percent_refund,
                        &dummy)) )
-      {
-        if (NULL != mode)
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Bad mode `%s' specified\n",
-                      mode);
-      }
-      if (NULL==mode)
-        percent_refund=0;
+    {
+      if (NULL != mode)
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Bad mode `%s' specified\n",
+                    mode);
+      percent_refund = 0;
+    }
   }
 
   switch (percent_refund)
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index a6e93221..b201ef55 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -203,8 +203,6 @@
 #include "pg_reserves_update.h"
 #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"
 #include "pg_insert_kyc_attributes.h"
 #include "pg_update_kyc_attributes.h"
 #include "pg_select_similar_kyc_attributes.h"
@@ -747,10 +745,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     = &TEH_PG_select_purse_by_merge_pub;
   plugin->set_purse_balance
     = &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;
   plugin->insert_kyc_attributes
     = &TEH_PG_insert_kyc_attributes;
   plugin->update_kyc_attributes
diff --git a/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c 
b/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
deleted file mode 100644
index 1a1c60f3..00000000
--- a/src/exchangedb/test_exchangedb_batch_reserves_in_insert.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2014-2022 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU General Public License as published by the Free Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along with
-  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchangedb/test_exchangedb_by_j.c
- * @brief test cases for DB interaction functions
- * @author Joseph Xu
- */
-#include "platform.h"
-#include "taler_exchangedb_lib.h"
-#include "taler_json_lib.h"
-#include "taler_exchangedb_plugin.h"
-
-/**o
- * Global result from the testcase.
- */
-static int result;
-
-/**
- * Report line of error if @a cond is true, and jump to label "drop".
- */
-#define FAILIF(cond)                            \
-  do {                                          \
-      if (! (cond)) {break;}                    \
-    GNUNET_break (0);                           \
-    goto drop;                                  \
-  } while (0)
-
-
-/**
- * Initializes @a ptr with random data.
- */
-#define RND_BLK(ptr)                                                    \
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr))
-
-/**
- * Initializes @a ptr with zeros.
- */
-#define ZR_BLK(ptr) \
-  memset (ptr, 0, sizeof (*ptr))
-
-
-/**
- * Currency we use.  Must match test-exchange-db-*.conf.
- */
-#define CURRENCY "EUR"
-
-/**
- * Database plugin under test.
- */
-static struct TALER_EXCHANGEDB_Plugin *plugin;
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure with config
- */
-static void
-run (void *cls)
-{
-  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  const uint32_t num_partitions = 10;
-
-  if (NULL ==
-      (plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
-  {
-    GNUNET_break (0);
-    result = 77;
-    return;
-  }
-  (void) plugin->drop_tables (plugin->cls);
-  if (GNUNET_OK !=
-      plugin->create_tables (plugin->cls,
-                             true,
-                             num_partitions))
-  {
-    GNUNET_break (0);
-    result = 77;
-    goto cleanup;
-  }
-
-  for (unsigned int i = 0; i< 8; i++)
-  {
-    static unsigned int batches[] = {1, 1, 2, 3, 4, 16, 64, 256};
-    const char *sndr = "payto://x-taler-bank/localhost:8080/1";
-    struct TALER_Amount value;
-    unsigned int batch_size = batches[i];
-    struct GNUNET_TIME_Absolute now;
-    struct GNUNET_TIME_Timestamp ts;
-    struct GNUNET_TIME_Relative duration;
-    struct TALER_ReservePublicKeyP reserve_pubs[batch_size];
-    struct TALER_EXCHANGEDB_ReserveInInfo reserves[batch_size];
-    enum GNUNET_DB_QueryStatus results[batch_size];
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_string_to_amount (CURRENCY ":1.000010",
-                                           &value));
-    now = GNUNET_TIME_absolute_get ();
-    ts = GNUNET_TIME_timestamp_get ();
-
-
-    for (unsigned int k = 0; k<batch_size; k++)
-      {
-        RND_BLK (&reserve_pubs[k]);
-        reserves[k].reserve_pub = &reserve_pubs[k];
-        reserves[k].balance = &value;
-        reserves[k].execution_time = ts;
-        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));
-
-
-    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:
-  GNUNET_break (GNUNET_OK ==
-                plugin->drop_tables (plugin->cls));
-cleanup:
-  TALER_EXCHANGEDB_plugin_unload (plugin);
-  plugin = NULL;
-}
-
-
-int
-main (int argc,
-      char *const argv[])
-{
-  const char *plugin_name;
-  char *config_filename;
-  char *testname;
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-  (void) argc;
-  result = -1;
-   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,
-                          "test-exchange-db-%s",
-                          plugin_name);
-    (void) GNUNET_asprintf (&config_filename,
-                          "%s.conf",
-                          testname);
-  fprintf (stdout,
-           "Using config: %s\n",
-           config_filename);
-  cfg = GNUNET_CONFIGURATION_create ();
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_parse (cfg,
-                                  config_filename))
-  {
-    GNUNET_break (0);
-    GNUNET_free (config_filename);
-    GNUNET_free (testname);
-    return 2;
-  }
-  GNUNET_SCHEDULER_run (&run,
-                        cfg);
-  GNUNET_CONFIGURATION_destroy (cfg);
-  GNUNET_free (config_filename);
-  GNUNET_free (testname);
-  return result;
-}
-
-/* end of test_exchangedb_by_j.c */
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 3e40c985..50a5c0ef 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -3479,46 +3479,6 @@ struct TALER_EXCHANGEDB_Plugin
                      struct TALER_PaytoHashP *h_payto);
 
 
-  /**
-   * Insert a 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 reserve_pub public key of the reserve
-   * @param balance the amount that has to be added to the reserve
-   * @param execution_time when was the amount added
-   * @param sender_account_details information about the sender's bank 
account, in payto://-format
-   * @param wire_reference unique reference identifying the wire transfer
-   * @return transaction status code
-   */
-  enum GNUNET_DB_QueryStatus
-  (*reserves_in_insert)(void *cls,
-                        const struct TALER_ReservePublicKeyP *reserve_pub,
-                        const struct TALER_Amount *balance,
-                        struct GNUNET_TIME_Timestamp execution_time,
-                        const char *sender_account_details,
-                        const char *exchange_account_name,
-                        uint64_t wire_reference);
-
-
-  /**
-   * 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
-  (*batch_reserves_in_insert)(
-    void *cls,
-    const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
-    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.
@@ -3530,7 +3490,7 @@ struct TALER_EXCHANGEDB_Plugin
    *             set to the status of the
    */
   enum GNUNET_DB_QueryStatus
-  (*batch2_reserves_in_insert)(
+  (*reserves_in_insert)(
     void *cls,
     const struct TALER_EXCHANGEDB_ReserveInInfo *reserves,
     unsigned int reserves_length,
@@ -4102,13 +4062,6 @@ struct TALER_EXCHANGEDB_Plugin
                        char **payto_uri);
 
 
-/**
- * Maximum number of results we return from iterate_matching_deposits().
- *
- * Limit on the number of transactions we aggregate at once.
- */
-#define TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT 10000
-
   /**
    * Aggregate all matching deposits for @a h_payto and
    * @a merchant_pub, returning the total amounts.

-- 
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]