gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated (f87eda14 -> 6af9fd66)


From: gnunet
Subject: [taler-exchange] branch master updated (f87eda14 -> 6af9fd66)
Date: Mon, 27 Mar 2023 15:55:06 +0200

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

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

    from f87eda14 new deb patch release
     new 5dfa5672 New spi files
     new 39f2d441 Spi files
     new 42258d57 nothing to update
     new fb70814d some changes for ensure known coin
     new d83c2539 some changes for known coins
     new cb87b6f6 New spi files
     new 6af9fd66 New spi files

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


Summary of changes:
 contrib/gana                                       |    2 +-
 src/exchangedb/.gitignore                          |    6 +
 .../exchange_do_batch2_reserves_in_insert.sql      |  186 ----
 .../exchange_do_batch4_reserves_in_insert.sql      |  287 ------
 .../exchange_do_batch8_reserves_in_insert.sql      |  509 ----------
 src/exchangedb/exchange_do_batch_coin_known.sql    |  477 +++++++++
 .../exchange_do_batch_reserves_in_insert.sql       |  120 ---
 src/exchangedb/exchange_do_reserves_in_insert.sql  | 1065 ++++++++++++++++++++
 ..._deposit.sql => exchange_get_ready_deposit.sql} |   53 +-
 src/exchangedb/pg_reserves_in_insert.c             |   67 +-
 src/exchangedb/plugin_exchangedb_postgres.c        |    1 +
 src/exchangedb/procedures.sql.in                   |    6 +-
 src/exchangedb/spi/README.md                       |   41 +
 src/exchangedb/spi/own_test.bc                     |  Bin 0 -> 22876 bytes
 src/exchangedb/spi/own_test.c                      |  826 +++++++++++++++
 src/exchangedb/spi/own_test.control                |    4 +
 src/exchangedb/spi/own_test.so                     |  Bin 0 -> 76824 bytes
 src/exchangedb/spi/own_test.sql                    |  216 ++++
 .../h.header => src/exchangedb/spi/perf_own_test.c |   24 +-
 src/exchangedb/spi/pg_aggregate.c                  |  389 +++++++
 20 files changed, 3080 insertions(+), 1199 deletions(-)
 delete mode 100644 src/exchangedb/exchange_do_batch2_reserves_in_insert.sql
 delete mode 100644 src/exchangedb/exchange_do_batch4_reserves_in_insert.sql
 delete mode 100644 src/exchangedb/exchange_do_batch8_reserves_in_insert.sql
 create mode 100644 src/exchangedb/exchange_do_batch_coin_known.sql
 delete mode 100644 src/exchangedb/exchange_do_batch_reserves_in_insert.sql
 create mode 100644 src/exchangedb/exchange_do_reserves_in_insert.sql
 copy src/exchangedb/{exchange_do_get_ready_deposit.sql => 
exchange_get_ready_deposit.sql} (66%)
 create mode 100644 src/exchangedb/spi/README.md
 create mode 100644 src/exchangedb/spi/own_test.bc
 create mode 100644 src/exchangedb/spi/own_test.c
 create mode 100644 src/exchangedb/spi/own_test.control
 create mode 100755 src/exchangedb/spi/own_test.so
 create mode 100644 src/exchangedb/spi/own_test.sql
 copy contrib/sigp/h.header => src/exchangedb/spi/perf_own_test.c (57%)
 create mode 100644 src/exchangedb/spi/pg_aggregate.c

diff --git a/contrib/gana b/contrib/gana
index 59de2acb..3a616a04 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 59de2acb7c716c816ed15786b5369e56c325770c
+Subproject commit 3a616a04f1cd946bf0641b54cd71f1b858174f74
diff --git a/src/exchangedb/.gitignore b/src/exchangedb/.gitignore
index 264217a3..fa833d81 100644
--- a/src/exchangedb/.gitignore
+++ b/src/exchangedb/.gitignore
@@ -7,3 +7,9 @@ perf_select_refunds_by_coin-postgres
 exchange-0002.sql
 procedures.sql
 exchange-0003.sql
+perf-exchangedb-reserves-in-insert-postgres
+test-exchangedb-batch-reserves-in-insert-postgres
+test-exchangedb-by-j-postgres
+test-exchangedb-populate-link-data-postgres
+test-exchangedb-populate-ready-deposit-postgres
+test-exchangedb-populate-select-refunds-by-coin-postgres
\ No newline at end of file
diff --git a/src/exchangedb/exchange_do_batch2_reserves_in_insert.sql 
b/src/exchangedb/exchange_do_batch2_reserves_in_insert.sql
deleted file mode 100644
index 6df8b755..00000000
--- a/src/exchangedb/exchange_do_batch2_reserves_in_insert.sql
+++ /dev/null
@@ -1,186 +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/>
---
-
-DROP FUNCTION IF EXISTS exchange_do_batch2_reserves_insert;
-CREATE OR REPLACE FUNCTION exchange_do_batch2_reserves_insert(
-  IN in_reserve_pub BYTEA,
-  IN in_expiration_date INT8,
-  IN in_gc_date INT8,
-  IN in_wire_ref INT8,
-  IN in_credit_val INT8,
-  IN in_credit_frac INT4,
-  IN in_exchange_account_name VARCHAR,
-  IN in_execution_date INT8,
-  IN in_wire_source_h_payto BYTEA,    ---h_payto
-  IN in_payto_uri VARCHAR,
-  IN in_reserve_expiration INT8,
-  IN in_notify text,
-  IN in2_notify text,
-  IN in2_reserve_pub BYTEA,
-  IN in2_wire_ref INT8,
-  IN in2_credit_val INT8,
-  IN in2_credit_frac INT4,
-  IN in2_exchange_account_name VARCHAR,
-  IN in2_execution_date INT8,
-  IN in2_wire_source_h_payto BYTEA,    ---h_payto
-  IN in2_payto_uri VARCHAR,
-  IN in2_reserve_expiration INT8,
-  OUT out_reserve_found BOOLEAN,
-  OUT out_reserve_found2 BOOLEAN,
-  OUT transaction_duplicate BOOLEAN,
-  OUT transaction_duplicate2 BOOLEAN,
-  OUT ruuid INT8,
-  OUT ruuid2 INT8)
-LANGUAGE plpgsql
-AS $$
-DECLARE
-  curs_reserve_exist REFCURSOR;
-DECLARE
-  curs_transaction_exist refcursor;
-DECLARE
-  i RECORD;
-DECLARE
-  r RECORD;
-DECLARE
-  k INT8;
-BEGIN
-  transaction_duplicate=TRUE;
-  transaction_duplicate2=TRUE;
-  out_reserve_found = TRUE;
-  out_reserve_found2 = TRUE;
-  ruuid=0;
-  ruuid2=0;
-  k=0;
-  INSERT INTO wire_targets
-    (wire_target_h_payto
-    ,payto_uri)
-    VALUES
-    (in_wire_source_h_payto
-    ,in_payto_uri),
-    (in2_wire_source_h_payto
-    ,in2_payto_uri)
-  ON CONFLICT DO NOTHING;
-
-  OPEN curs_reserve_exist FOR
-  WITH reserve_changes AS (
-    INSERT INTO reserves
-      (reserve_pub
-      ,current_balance_val
-      ,current_balance_frac
-      ,expiration_date
-      ,gc_date)
-      VALUES
-      (in_reserve_pub
-      ,in_credit_val
-      ,in_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in2_reserve_pub
-      ,in2_credit_val
-      ,in2_credit_frac
-      ,in_expiration_date
-      ,in_gc_date)
-     ON CONFLICT DO NOTHING
-     RETURNING reserve_uuid,reserve_pub)
-    SELECT * FROM reserve_changes;
-  WHILE k < 2 LOOP
-    FETCH FROM curs_reserve_exist INTO i;
-    IF FOUND
-    THEN
-      IF in_reserve_pub = i.reserve_pub
-      THEN
-        ruuid = i.reserve_uuid;
-        IF in_reserve_pub <> in2_reserve_pub
-        THEN
-          out_reserve_found = FALSE;
-         END IF;
-      END IF;
-      IF in2_reserve_pub = i.reserve_pub
-      THEN
-          out_reserve_found2 = FALSE;
-          ruuid2 = i.reserve_uuid;
-      END IF;
-    END IF;
-    k=k+1;
-  END LOOP;
-  CLOSE curs_reserve_exist;
-
--- FIXME: must be changed to EXECUTE FORMAT!
-  PERFORM pg_notify(in_notify, NULL);
-  PERFORM pg_notify(in2_notify, NULL);
-
-  OPEN curs_transaction_exist FOR
-  WITH reserve_in_exist AS (
-  INSERT INTO reserves_in
-    (reserve_pub
-    ,wire_reference
-    ,credit_val
-    ,credit_frac
-    ,exchange_account_section
-    ,wire_source_h_payto
-    ,execution_date)
-    VALUES
-    (in_reserve_pub
-    ,in_wire_ref
-    ,in_credit_val
-    ,in_credit_frac
-    ,in_exchange_account_name
-    ,in_wire_source_h_payto
-    ,in_execution_date),
-    (in2_reserve_pub
-    ,in2_wire_ref
-    ,in2_credit_val
-    ,in2_credit_frac
-    ,in2_exchange_account_name
-    ,in2_wire_source_h_payto
-    ,in_execution_date)
-    ON CONFLICT DO NOTHING
-    RETURNING reserve_pub)
-  SELECT * FROM reserve_in_exist;
-  FETCH FROM curs_transaction_exist INTO r;
-  IF FOUND
-  THEN
-    IF in_reserve_pub = r.reserve_pub
-    THEN
-       transaction_duplicate = FALSE;
-    END IF;
-    IF in2_reserve_pub = r.reserve_pub
-    THEN
-       transaction_duplicate2 = FALSE;
-    END IF;
-    FETCH FROM curs_transaction_exist INTO r;
-    IF FOUND
-    THEN
-      IF in_reserve_pub = r.reserve_pub
-      THEN
-        transaction_duplicate = FALSE;
-      END IF;
-      IF in2_reserve_pub = r.reserve_pub
-      THEN
-        transaction_duplicate2 = FALSE;
-      END IF;
-    END IF;
-  END IF;
-/*  IF transaction_duplicate
-  OR transaction_duplicate2
-  THEN
-    CLOSE curs_transaction_exist;
-    ROLLBACK;
-    RETURN;
-  END IF;*/
-  CLOSE curs_transaction_exist;
-  RETURN;
-END $$;
diff --git a/src/exchangedb/exchange_do_batch4_reserves_in_insert.sql 
b/src/exchangedb/exchange_do_batch4_reserves_in_insert.sql
deleted file mode 100644
index 6a570710..00000000
--- a/src/exchangedb/exchange_do_batch4_reserves_in_insert.sql
+++ /dev/null
@@ -1,287 +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/>
---
-
-DROP FUNCTION IF EXISTS exchange_do_batch4_reserves_insert;
-CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert(
-  IN in_reserve_pub BYTEA,
-  IN in_expiration_date INT8,
-  IN in_gc_date INT8,
-  IN in_wire_ref INT8,
-  IN in_credit_val INT8,
-  IN in_credit_frac INT4,
-  IN in_exchange_account_name VARCHAR,
-  IN in_execution_date INT8,
-  IN in_wire_source_h_payto BYTEA,    ---h_payto
-  IN in_payto_uri VARCHAR,
-  IN in_reserve_expiration INT8,
-  IN in_notify text,
-  IN in2_notify text,
-  IN in3_notify text,
-  IN in4_notify text,
-  IN in2_reserve_pub BYTEA,
-  IN in2_wire_ref INT8,
-  IN in2_credit_val INT8,
-  IN in2_credit_frac INT4,
-  IN in2_exchange_account_name VARCHAR,
-  IN in2_execution_date INT8,
-  IN in2_wire_source_h_payto BYTEA,    ---h_payto
-  IN in2_payto_uri VARCHAR,
-  IN in2_reserve_expiration INT8,
-  IN in3_reserve_pub BYTEA,
-  IN in3_wire_ref INT8,
-  IN in3_credit_val INT8,
-  IN in3_credit_frac INT4,
-  IN in3_exchange_account_name VARCHAR,
-  IN in3_execution_date INT8,
-  IN in3_wire_source_h_payto BYTEA,    ---h_payto
-  IN in3_payto_uri VARCHAR,
-  IN in3_reserve_expiration INT8,
-  IN in4_reserve_pub BYTEA,
-  IN in4_wire_ref INT8,
-  IN in4_credit_val INT8,
-  IN in4_credit_frac INT4,
-  IN in4_exchange_account_name VARCHAR,
-  IN in4_execution_date INT8,
-  IN in4_wire_source_h_payto BYTEA,    ---h_payto
-  IN in4_payto_uri VARCHAR,
-  IN in4_reserve_expiration INT8,
-  OUT out_reserve_found BOOLEAN,
-  OUT out_reserve_found2 BOOLEAN,
-  OUT out_reserve_found3 BOOLEAN,
-  OUT out_reserve_found4 BOOLEAN,
-  OUT transaction_duplicate BOOLEAN,
-  OUT transaction_duplicate2 BOOLEAN,
-  OUT transaction_duplicate3 BOOLEAN,
-  OUT transaction_duplicate4 BOOLEAN,
-  OUT ruuid INT8,
-  OUT ruuid2 INT8,
-  OUT ruuid3 INT8,
-  OUT ruuid4 INT8)
-LANGUAGE plpgsql
-AS $$
-DECLARE
-  curs_reserve_exist refcursor;
-DECLARE
-  k INT8;
-DECLARE
-  curs_transaction_exist refcursor;
-DECLARE
-  i RECORD;
-
-BEGIN
---INITIALIZATION
-  transaction_duplicate=TRUE;
-  transaction_duplicate2=TRUE;
-  transaction_duplicate3=TRUE;
-  transaction_duplicate4=TRUE;
-  out_reserve_found = TRUE;
-  out_reserve_found2 = TRUE;
-  out_reserve_found3 = TRUE;
-  out_reserve_found4 = TRUE;
-  ruuid=0;
-  ruuid2=0;
-  ruuid3=0;
-  ruuid4=0;
-  k=0;
-  --SIMPLE INSERT ON CONFLICT DO NOTHING
-  INSERT INTO wire_targets
-    (wire_target_h_payto
-    ,payto_uri)
-    VALUES
-    (in_wire_source_h_payto
-    ,in_payto_uri),
-    (in2_wire_source_h_payto
-    ,in2_payto_uri),
-    (in3_wire_source_h_payto
-    ,in3_payto_uri),
-    (in4_wire_source_h_payto
-    ,in4_payto_uri)
-  ON CONFLICT DO NOTHING;
-
-  OPEN curs_reserve_exist FOR
-  WITH reserve_changes AS (
-    INSERT INTO reserves
-      (reserve_pub
-      ,current_balance_val
-      ,current_balance_frac
-      ,expiration_date
-      ,gc_date)
-      VALUES
-      (in_reserve_pub
-      ,in_credit_val
-      ,in_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in2_reserve_pub
-      ,in2_credit_val
-      ,in2_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in3_reserve_pub
-      ,in3_credit_val
-      ,in3_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in4_reserve_pub
-      ,in4_credit_val
-      ,in4_credit_frac
-      ,in_expiration_date
-      ,in_gc_date)
-     ON CONFLICT DO NOTHING
-     RETURNING reserve_uuid,reserve_pub)
-    SELECT * FROM reserve_changes;
-
-  WHILE k < 4 LOOP
-    FETCH FROM curs_reserve_exist INTO i;
-    IF FOUND
-    THEN
-      IF in_reserve_pub = i.reserve_pub
-      THEN
-         ruuid = i.reserve_uuid;
-         IF in_reserve_pub
-         NOT IN (in2_reserve_pub
-                ,in3_reserve_pub
-                ,in4_reserve_pub)
-         THEN
-           out_reserve_found = FALSE;
-         END IF;
-      END IF;
-      IF in2_reserve_pub = i.reserve_pub
-      THEN
-         ruuid2 = i.reserve_uuid;
-         IF in2_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in3_reserve_pub
-                ,in4_reserve_pub)
-         THEN
-           out_reserve_found2 = FALSE;
-         END IF;
-      END IF;
-      IF in3_reserve_pub = i.reserve_pub
-      THEN
-         ruuid3 = i.reserve_uuid;
-         IF in3_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in2_reserve_pub
-                ,in4_reserve_pub)
-         THEN
-           out_reserve_found3 = FALSE;
-         END IF;
-      END IF;
-      IF in4_reserve_pub = i.reserve_pub
-      THEN
-         ruuid4 = i.reserve_uuid;
-         IF in4_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in2_reserve_pub
-                ,in3_reserve_pub)
-         THEN
-           out_reserve_found4 = FALSE;
-         END IF;
-      END IF;
-    END IF;
-  k=k+1;
-  END LOOP;
-  CLOSE curs_reserve_exist;
-
-
--- FIXME: must be changed to EXECUTE FORMAT!
-  PERFORM pg_notify(in_notify, NULL);
-  PERFORM pg_notify(in2_notify, NULL);
-  PERFORM pg_notify(in3_notify, NULL);
-  PERFORM pg_notify(in4_notify, NULL);
-
-  k=0;
-  OPEN curs_transaction_exist FOR
-  WITH reserve_in_changes AS (
-    INSERT INTO reserves_in
-    (reserve_pub
-    ,wire_reference
-    ,credit_val
-    ,credit_frac
-    ,exchange_account_section
-    ,wire_source_h_payto
-    ,execution_date)
-      VALUES
-    (in_reserve_pub
-    ,in_wire_ref
-    ,in_credit_val
-    ,in_credit_frac
-    ,in_exchange_account_name
-    ,in_wire_source_h_payto
-    ,in_execution_date),
-    (in2_reserve_pub
-    ,in2_wire_ref
-    ,in2_credit_val
-    ,in2_credit_frac
-    ,in2_exchange_account_name
-    ,in2_wire_source_h_payto
-    ,in_execution_date),
-    (in3_reserve_pub
-    ,in3_wire_ref
-    ,in3_credit_val
-    ,in3_credit_frac
-    ,in3_exchange_account_name
-    ,in3_wire_source_h_payto
-    ,in_execution_date),
-    (in4_reserve_pub
-    ,in4_wire_ref
-    ,in4_credit_val
-    ,in4_credit_frac
-    ,in4_exchange_account_name
-    ,in4_wire_source_h_payto
-    ,in_execution_date)
-     ON CONFLICT DO NOTHING
-     RETURNING reserve_pub)
-    SELECT * FROM reserve_in_changes;
-  WHILE k < 4 LOOP
-    FETCH FROM curs_transaction_exist INTO i;
-    IF FOUND
-    THEN
-      IF in_reserve_pub = i.reserve_pub
-      THEN
-         transaction_duplicate = FALSE;
-      END IF;
-      IF in2_reserve_pub = i.reserve_pub
-      THEN
-         transaction_duplicate2 = FALSE;
-      END IF;
-      IF in3_reserve_pub = i.reserve_pub
-      THEN
-         transaction_duplicate3 = FALSE;
-      END IF;
-      IF in4_reserve_pub = i.reserve_pub
-      THEN
-         transaction_duplicate4 = FALSE;
-      END IF;
-    END IF;
-  k=k+1;
-  END LOOP;
- /**ROLLBACK TRANSACTION IN SORTED PROCEDURE IS IT PROSSIBLE ?**/
-  /*IF transaction_duplicate
-  OR transaction_duplicate2
-  OR transaction_duplicate3
-  OR transaction_duplicate4
-  THEN
-    RAISE EXCEPTION 'Reserve did not exist, but INSERT into reserves_in gave 
conflict';
-    ROLLBACK;
-    CLOSE curs_transaction_exist;
-    RETURN;
-  END IF;*/
-  CLOSE curs_transaction_exist;
-  RETURN;
-
-END $$;
diff --git a/src/exchangedb/exchange_do_batch8_reserves_in_insert.sql 
b/src/exchangedb/exchange_do_batch8_reserves_in_insert.sql
deleted file mode 100644
index a9f34b89..00000000
--- a/src/exchangedb/exchange_do_batch8_reserves_in_insert.sql
+++ /dev/null
@@ -1,509 +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/>
---
-
-DROP FUNCTION IF EXISTS exchange_do_batch8_reserves_insert;
-CREATE OR REPLACE FUNCTION exchange_do_batch8_reserves_insert(
-  IN in_reserve_pub BYTEA,
-  IN in_expiration_date INT8,
-  IN in_gc_date INT8,
-  IN in_wire_ref INT8,
-  IN in_credit_val INT8,
-  IN in_credit_frac INT4,
-  IN in_exchange_account_name VARCHAR,
-  IN in_execution_date INT8,
-  IN in_wire_source_h_payto BYTEA,    ---h_payto
-  IN in_payto_uri VARCHAR,
-  IN in_reserve_expiration INT8,
-  IN in_notify text,
-  IN in2_notify text,
-  IN in3_notify text,
-  IN in4_notify text,
-  IN in5_notify text,
-  IN in6_notify text,
-  IN in7_notify text,
-  IN in8_notify text,
-  IN in2_reserve_pub BYTEA,
-  IN in2_wire_ref INT8,
-  IN in2_credit_val INT8,
-  IN in2_credit_frac INT4,
-  IN in2_exchange_account_name VARCHAR,
-  IN in2_execution_date INT8,
-  IN in2_wire_source_h_payto BYTEA,    ---h_payto
-  IN in2_payto_uri VARCHAR,
-  IN in2_reserve_expiration INT8,
-  IN in3_reserve_pub BYTEA,
-  IN in3_wire_ref INT8,
-  IN in3_credit_val INT8,
-  IN in3_credit_frac INT4,
-  IN in3_exchange_account_name VARCHAR,
-  IN in3_execution_date INT8,
-  IN in3_wire_source_h_payto BYTEA,    ---h_payto
-  IN in3_payto_uri VARCHAR,
-  IN in3_reserve_expiration INT8,
-  IN in4_reserve_pub BYTEA,
-  IN in4_wire_ref INT8,
-  IN in4_credit_val INT8,
-  IN in4_credit_frac INT4,
-  IN in4_exchange_account_name VARCHAR,
-  IN in4_execution_date INT8,
-  IN in4_wire_source_h_payto BYTEA,    ---h_payto
-  IN in4_payto_uri VARCHAR,
-  IN in4_reserve_expiration INT8,
-  IN in5_reserve_pub BYTEA,
-  IN in5_wire_ref INT8,
-  IN in5_credit_val INT8,
-  IN in5_credit_frac INT4,
-  IN in5_exchange_account_name VARCHAR,
-  IN in5_execution_date INT8,
-  IN in5_wire_source_h_payto BYTEA,    ---h_payto
-  IN in5_payto_uri VARCHAR,
-  IN in5_reserve_expiration INT8,
-  IN in6_reserve_pub BYTEA,
-  IN in6_wire_ref INT8,
-  IN in6_credit_val INT8,
-  IN in6_credit_frac INT4,
-  IN in6_exchange_account_name VARCHAR,
-  IN in6_execution_date INT8,
-  IN in6_wire_source_h_payto BYTEA,    ---h_payto
-  IN in6_payto_uri VARCHAR,
-  IN in6_reserve_expiration INT8,
-  IN in7_reserve_pub BYTEA,
-  IN in7_wire_ref INT8,
-  IN in7_credit_val INT8,
-  IN in7_credit_frac INT4,
-  IN in7_exchange_account_name VARCHAR,
-  IN in7_execution_date INT8,
-  IN in7_wire_source_h_payto BYTEA,    ---h_payto
-  IN in7_payto_uri VARCHAR,
-  IN in7_reserve_expiration INT8,
-  IN in8_reserve_pub BYTEA,
-  IN in8_wire_ref INT8,
-  IN in8_credit_val INT8,
-  IN in8_credit_frac INT4,
-  IN in8_exchange_account_name VARCHAR,
-  IN in8_execution_date INT8,
-  IN in8_wire_source_h_payto BYTEA,    ---h_payto
-  IN in8_payto_uri VARCHAR,
-  IN in8_reserve_expiration INT8,
-  OUT out_reserve_found BOOLEAN,
-  OUT out_reserve_found2 BOOLEAN,
-  OUT out_reserve_found3 BOOLEAN,
-  OUT out_reserve_found4 BOOLEAN,
-  OUT out_reserve_found5 BOOLEAN,
-  OUT out_reserve_found6 BOOLEAN,
-  OUT out_reserve_found7 BOOLEAN,
-  OUT out_reserve_found8 BOOLEAN,
-  OUT transaction_duplicate BOOLEAN,
-  OUT transaction_duplicate2 BOOLEAN,
-  OUT transaction_duplicate3 BOOLEAN,
-  OUT transaction_duplicate4 BOOLEAN,
-  OUT transaction_duplicate5 BOOLEAN,
-  OUT transaction_duplicate6 BOOLEAN,
-  OUT transaction_duplicate7 BOOLEAN,
-  OUT transaction_duplicate8 BOOLEAN,
-  OUT ruuid INT8,
-  OUT ruuid2 INT8,
-  OUT ruuid3 INT8,
-  OUT ruuid4 INT8,
-  OUT ruuid5 INT8,
-  OUT ruuid6 INT8,
-  OUT ruuid7 INT8,
-  OUT ruuid8 INT8)
-LANGUAGE plpgsql
-AS $$
-DECLARE
-  curs_reserve_existed refcursor;
-DECLARE
-  k INT8;
-DECLARE
-  curs_transaction_existed refcursor;
-
-DECLARE
-  i RECORD;
-DECLARE
-  r RECORD;
-
-BEGIN
---INITIALIZATION
-  transaction_duplicate=TRUE;
-  transaction_duplicate2=TRUE;
-  transaction_duplicate3=TRUE;
-  transaction_duplicate4=TRUE;
-  transaction_duplicate5=TRUE;
-  transaction_duplicate6=TRUE;
-  transaction_duplicate7=TRUE;
-  transaction_duplicate8=TRUE;
-  out_reserve_found = TRUE;
-  out_reserve_found2 = TRUE;
-  out_reserve_found3 = TRUE;
-  out_reserve_found4 = TRUE;
-  out_reserve_found5 = TRUE;
-  out_reserve_found6 = TRUE;
-  out_reserve_found7 = TRUE;
-  out_reserve_found8 = TRUE;
-  ruuid=0;
-  ruuid2=0;
-  ruuid3=0;
-  ruuid4=0;
-  ruuid5=0;
-  ruuid6=0;
-  ruuid7=0;
-  ruuid8=0;
-  k=0;
-
-  --SIMPLE INSERT ON CONFLICT DO NOTHING
-  INSERT INTO wire_targets
-    (wire_target_h_payto
-    ,payto_uri)
-    VALUES
-    (in_wire_source_h_payto
-    ,in_payto_uri),
-    (in2_wire_source_h_payto
-    ,in2_payto_uri),
-    (in3_wire_source_h_payto
-    ,in3_payto_uri),
-    (in4_wire_source_h_payto
-    ,in4_payto_uri),
-    (in5_wire_source_h_payto
-    ,in5_payto_uri),
-    (in6_wire_source_h_payto
-    ,in6_payto_uri),
-    (in7_wire_source_h_payto
-    ,in7_payto_uri),
-    (in8_wire_source_h_payto
-    ,in8_payto_uri)
-  ON CONFLICT DO NOTHING;
-
-  OPEN curs_reserve_existed FOR
-  WITH reserve_changes AS (
-    INSERT INTO reserves
-      (reserve_pub
-      ,current_balance_val
-      ,current_balance_frac
-      ,expiration_date
-      ,gc_date)
-      VALUES
-      (in_reserve_pub
-      ,in_credit_val
-      ,in_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in2_reserve_pub
-      ,in2_credit_val
-      ,in2_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in3_reserve_pub
-      ,in3_credit_val
-      ,in3_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in4_reserve_pub
-      ,in4_credit_val
-      ,in4_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in5_reserve_pub
-      ,in5_credit_val
-      ,in5_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in6_reserve_pub
-      ,in6_credit_val
-      ,in6_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in7_reserve_pub
-      ,in7_credit_val
-      ,in7_credit_frac
-      ,in_expiration_date
-      ,in_gc_date),
-      (in8_reserve_pub
-      ,in8_credit_val
-      ,in8_credit_frac
-      ,in_expiration_date
-      ,in_gc_date)
-     ON CONFLICT DO NOTHING
-     RETURNING reserve_uuid,reserve_pub)
-    SELECT * FROM reserve_changes;
-
-  WHILE k < 8 LOOP
-
-    FETCH FROM curs_reserve_existed INTO i;
-    IF FOUND
-    THEN
-      IF in_reserve_pub = i.reserve_pub
-      THEN
-         ruuid = i.reserve_uuid;
-         IF in_reserve_pub
-         NOT IN (in2_reserve_pub
-                ,in3_reserve_pub
-                ,in4_reserve_pub
-                ,in5_reserve_pub
-                ,in6_reserve_pub
-                ,in7_reserve_pub
-                ,in8_reserve_pub)
-         THEN
-           out_reserve_found = FALSE;
-         END IF;
-      END IF;
-      IF in2_reserve_pub = i.reserve_pub
-      THEN
-         ruuid2 = i.reserve_uuid;
-         IF in2_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in3_reserve_pub
-                ,in4_reserve_pub
-                ,in5_reserve_pub
-                ,in6_reserve_pub
-                ,in7_reserve_pub
-                ,in8_reserve_pub)
-         THEN
-           out_reserve_found2 = FALSE;
-         END IF;
-      END IF;
-      IF in3_reserve_pub = i.reserve_pub
-      THEN
-         ruuid3 = i.reserve_uuid;
-         IF in3_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in2_reserve_pub
-                ,in4_reserve_pub
-                ,in5_reserve_pub
-                ,in6_reserve_pub
-                ,in7_reserve_pub
-                ,in8_reserve_pub)
-         THEN
-           out_reserve_found3 = FALSE;
-         END IF;
-      END IF;
-      IF in4_reserve_pub = i.reserve_pub
-      THEN
-         ruuid4 = i.reserve_uuid;
-         IF in4_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in2_reserve_pub
-                ,in3_reserve_pub
-                ,in5_reserve_pub
-                ,in6_reserve_pub
-                ,in7_reserve_pub
-                ,in8_reserve_pub)
-         THEN
-           out_reserve_found4 = FALSE;
-         END IF;
-      END IF;
-      IF in5_reserve_pub = i.reserve_pub
-      THEN
-         ruuid5 = i.reserve_uuid;
-         IF in5_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in2_reserve_pub
-                ,in3_reserve_pub
-                ,in4_reserve_pub
-                ,in6_reserve_pub
-                ,in7_reserve_pub
-                ,in8_reserve_pub)
-         THEN
-           out_reserve_found5 = FALSE;
-         END IF;
-      END IF;
-      IF in6_reserve_pub = i.reserve_pub
-      THEN
-         ruuid6 = i.reserve_uuid;
-         IF in6_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in2_reserve_pub
-                ,in3_reserve_pub
-                ,in4_reserve_pub
-                ,in5_reserve_pub
-                ,in7_reserve_pub
-                ,in8_reserve_pub)
-         THEN
-           out_reserve_found6 = FALSE;
-         END IF;
-      END IF;
-      IF in7_reserve_pub = i.reserve_pub
-      THEN
-         ruuid7 = i.reserve_uuid;
-         IF in7_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in2_reserve_pub
-                ,in3_reserve_pub
-                ,in4_reserve_pub
-                ,in5_reserve_pub
-                ,in6_reserve_pub
-                ,in8_reserve_pub)
-         THEN
-           out_reserve_found7 = FALSE;
-         END IF;
-      END IF;
-      IF in8_reserve_pub = i.reserve_pub
-      THEN
-         ruuid8 = i.reserve_uuid;
-         IF in8_reserve_pub
-         NOT IN (in_reserve_pub
-                ,in2_reserve_pub
-                ,in3_reserve_pub
-                ,in4_reserve_pub
-                ,in5_reserve_pub
-                ,in6_reserve_pub
-                ,in7_reserve_pub)
-         THEN
-           out_reserve_found8 = FALSE;
-         END IF;
-      END IF;
-    END IF;
-  k=k+1;
-  END LOOP;
-
-  CLOSE curs_reserve_existed;
-
--- FIXME: must be changed to EXECUTE FORMAT!
-  PERFORM pg_notify(in_notify, NULL);
-  PERFORM pg_notify(in2_notify, NULL);
-  PERFORM pg_notify(in3_notify, NULL);
-  PERFORM pg_notify(in4_notify, NULL);
-  PERFORM pg_notify(in5_notify, NULL);
-  PERFORM pg_notify(in6_notify, NULL);
-  PERFORM pg_notify(in7_notify, NULL);
-  PERFORM pg_notify(in8_notify, NULL);
-  k=0;
-  OPEN curs_transaction_existed FOR
-  WITH reserve_in_changes AS (
-    INSERT INTO reserves_in
-    (reserve_pub
-    ,wire_reference
-    ,credit_val
-    ,credit_frac
-    ,exchange_account_section
-    ,wire_source_h_payto
-    ,execution_date)
-      VALUES
-    (in_reserve_pub
-    ,in_wire_ref
-    ,in_credit_val
-    ,in_credit_frac
-    ,in_exchange_account_name
-    ,in_wire_source_h_payto
-    ,in_execution_date),
-    (in2_reserve_pub
-    ,in2_wire_ref
-    ,in2_credit_val
-    ,in2_credit_frac
-    ,in2_exchange_account_name
-    ,in2_wire_source_h_payto
-    ,in_execution_date),
-    (in3_reserve_pub
-    ,in3_wire_ref
-    ,in3_credit_val
-    ,in3_credit_frac
-    ,in3_exchange_account_name
-    ,in3_wire_source_h_payto
-    ,in_execution_date),
-    (in4_reserve_pub
-    ,in4_wire_ref
-    ,in4_credit_val
-    ,in4_credit_frac
-    ,in4_exchange_account_name
-    ,in4_wire_source_h_payto
-    ,in_execution_date),
-    (in5_reserve_pub
-    ,in5_wire_ref
-    ,in5_credit_val
-    ,in5_credit_frac
-    ,in5_exchange_account_name
-    ,in5_wire_source_h_payto
-    ,in_execution_date),
-    (in6_reserve_pub
-    ,in6_wire_ref
-    ,in6_credit_val
-    ,in6_credit_frac
-    ,in6_exchange_account_name
-    ,in6_wire_source_h_payto
-    ,in_execution_date),
-    (in7_reserve_pub
-    ,in7_wire_ref
-    ,in7_credit_val
-    ,in7_credit_frac
-    ,in7_exchange_account_name
-    ,in7_wire_source_h_payto
-    ,in_execution_date),
-    (in8_reserve_pub
-    ,in8_wire_ref
-    ,in8_credit_val
-    ,in8_credit_frac
-    ,in8_exchange_account_name
-    ,in8_wire_source_h_payto
-    ,in_execution_date)
-     ON CONFLICT DO NOTHING
-     RETURNING reserve_pub)
-    SELECT * FROM reserve_in_changes;
-
-  WHILE k < 8 LOOP
-    FETCH FROM curs_transaction_existed INTO r;
-    IF FOUND
-    THEN
-      IF in_reserve_pub = r.reserve_pub
-      THEN
-         transaction_duplicate = FALSE;
-      END IF;
-      IF in2_reserve_pub = r.reserve_pub
-      THEN
-         transaction_duplicate2 = FALSE;
-      END IF;
-      IF in3_reserve_pub = r.reserve_pub
-      THEN
-         transaction_duplicate3 = FALSE;
-      END IF;
-      IF in4_reserve_pub = r.reserve_pub
-      THEN
-         transaction_duplicate4 = FALSE;
-      END IF;
-      IF in5_reserve_pub = r.reserve_pub
-      THEN
-         transaction_duplicate5 = FALSE;
-      END IF;
-      IF in6_reserve_pub = r.reserve_pub
-      THEN
-         transaction_duplicate6 = FALSE;
-      END IF;
-      IF in7_reserve_pub = r.reserve_pub
-      THEN
-         transaction_duplicate7 = FALSE;
-      END IF;
-      IF in8_reserve_pub = r.reserve_pub
-      THEN
-         transaction_duplicate8 = FALSE;
-      END IF;
-    END IF;
-  k=k+1;
-  END LOOP;
- /* IF transaction_duplicate
-  OR transaction_duplicate2
-  OR transaction_duplicate3
-  OR transaction_duplicate4
-  OR transaction_duplicate5
-  OR transaction_duplicate6
-  OR transaction_duplicate7
-  OR transaction_duplicate8
-  THEN
-    CLOSE curs_transaction_existed;
-    ROLLBACK;
-    RETURN;
-  END IF;*/
-  CLOSE curs_transaction_existed;
-  RETURN;
-END $$;
diff --git a/src/exchangedb/exchange_do_batch_coin_known.sql 
b/src/exchangedb/exchange_do_batch_coin_known.sql
new file mode 100644
index 00000000..38d79595
--- /dev/null
+++ b/src/exchangedb/exchange_do_batch_coin_known.sql
@@ -0,0 +1,477 @@
+--
+-- 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/>
+--
+
+CREATE OR REPLACE FUNCTION exchange_do_batch4_known_coin(
+  IN in_coin_pub1 BYTEA,
+  IN in_denom_pub_hash1 BYTEA,
+  IN in_h_age_commitment1 BYTEA,
+  IN in_denom_sig1 BYTEA,
+  IN in_coin_pub2 BYTEA,
+  IN in_denom_pub_hash2 BYTEA,
+  IN in_h_age_commitment2 BYTEA,
+  IN in_denom_sig2 BYTEA,
+  IN in_coin_pub3 BYTEA,
+  IN in_denom_pub_hash3 BYTEA,
+  IN in_h_age_commitment3 BYTEA,
+  IN in_denom_sig3 BYTEA,
+  IN in_coin_pub4 BYTEA,
+  IN in_denom_pub_hash4 BYTEA,
+  IN in_h_age_commitment4 BYTEA,
+  IN in_denom_sig4 BYTEA,
+  OUT existed1 BOOLEAN,
+  OUT existed2 BOOLEAN,
+  OUT existed3 BOOLEAN,
+  OUT existed4 BOOLEAN,
+  OUT known_coin_id1 INT8,
+  OUT known_coin_id2 INT8,
+  OUT known_coin_id3 INT8,
+  OUT known_coin_id4 INT8,
+  OUT denom_pub_hash1 BYTEA,
+  OUT denom_pub_hash2 BYTEA,
+  OUT denom_pub_hash3 BYTEA,
+  OUT denom_pub_hash4 BYTEA,
+  OUT age_commitment_hash1 BYTEA,
+  OUT age_commitment_hash2 BYTEA,
+  OUT age_commitment_hash3 BYTEA,
+  OUT age_commitment_hash4 BYTEA)
+LANGUAGE plpgsql
+AS $$
+BEGIN
+WITH dd AS (
+SELECT
+  denominations_serial,
+  coin_val, coin_frac
+  FROM denominations
+    WHERE denom_pub_hash
+    IN
+     (in_denom_pub_hash1,
+      in_denom_pub_hash2,
+      in_denom_pub_hash3,
+      in_denom_pub_hash4)
+     ),--dd
+     input_rows AS (
+     VALUES
+      (in_coin_pub1,
+      in_denom_pub_hash1,
+      in_h_age_commitment1,
+      in_denom_sig1),
+      (in_coin_pub2,
+      in_denom_pub_hash2,
+      in_h_age_commitment2,
+      in_denom_sig2),
+      (in_coin_pub3,
+      in_denom_pub_hash3,
+      in_h_age_commitment3,
+      in_denom_sig3),
+      (in_coin_pub4,
+      in_denom_pub_hash4,
+      in_h_age_commitment4,
+      in_denom_sig4)
+      ),--ir
+      ins AS (
+      INSERT INTO known_coins (
+      coin_pub,
+      denominations_serial,
+      age_commitment_hash,
+      denom_sig,
+      remaining_val,
+      remaining_frac
+      )
+      SELECT
+        ir.coin_pub,
+        dd.denominations_serial,
+        ir.age_commitment_hash,
+        ir.denom_sig,
+        dd.coin_val,
+        dd.coin_frac
+        FROM input_rows ir
+        JOIN dd
+          ON dd.denom_pub_hash = ir.denom_pub_hash
+          ON CONFLICT DO NOTHING
+          RETURNING known_coin_id
+      ),--kc
+       exists AS (
+         SELECT
+         CASE
+           WHEN
+             ins.known_coin_id IS NOT NULL
+             THEN
+               FALSE
+             ELSE
+               TRUE
+         END AS existed,
+         ins.known_coin_id,
+         dd.denom_pub_hash,
+         kc.age_commitment_hash
+         FROM input_rows ir
+         LEFT JOIN ins
+           ON ins.coin_pub = ir.coin_pub
+         LEFT JOIN known_coins kc
+           ON kc.coin_pub = ir.coin_pub
+         LEFT JOIN dd
+           ON dd.denom_pub_hash = ir.denom_pub_hash
+         )--exists
+SELECT
+ exists.existed AS existed1,
+ exists.known_coin_id AS known_coin_id1,
+ exists.denom_pub_hash AS denom_pub_hash1,
+ exists.age_commitment_hash AS age_commitment_hash1,
+ (
+   SELECT exists.existed
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash2
+ ) AS existed2,
+ (
+   SELECT exists.known_coin_id
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash2
+ ) AS known_coin_id2,
+ (
+   SELECT exists.denom_pub_hash
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash2
+ ) AS denom_pub_hash2,
+ (
+   SELECT exists.age_commitment_hash
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash2
+ )AS age_commitment_hash2,
+ (
+   SELECT exists.existed
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash3
+ ) AS existed3,
+ (
+   SELECT exists.known_coin_id
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash3
+ ) AS known_coin_id3,
+ (
+   SELECT exists.denom_pub_hash
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash3
+ ) AS denom_pub_hash3,
+ (
+   SELECT exists.age_commitment_hash
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash3
+ )AS age_commitment_hash3,
+ (
+   SELECT exists.existed
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash4
+ ) AS existed4,
+ (
+   SELECT exists.known_coin_id
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash4
+ ) AS known_coin_id4,
+ (
+   SELECT exists.denom_pub_hash
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash4
+ ) AS denom_pub_hash4,
+ (
+   SELECT exists.age_commitment_hash
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash4
+ )AS age_commitment_hash4
+FROM exists;
+
+RETURN;
+END $$;
+
+
+CREATE OR REPLACE FUNCTION exchange_do_batch2_known_coin(
+  IN in_coin_pub1 BYTEA,
+  IN in_denom_pub_hash1 BYTEA,
+  IN in_h_age_commitment1 BYTEA,
+  IN in_denom_sig1 BYTEA,
+  IN in_coin_pub2 BYTEA,
+  IN in_denom_pub_hash2 BYTEA,
+  IN in_h_age_commitment2 BYTEA,
+  IN in_denom_sig2 BYTEA,
+  OUT existed1 BOOLEAN,
+  OUT existed2 BOOLEAN,
+  OUT known_coin_id1 INT8,
+  OUT known_coin_id2 INT8,
+  OUT denom_pub_hash1 BYTEA,
+  OUT denom_pub_hash2 BYTEA,
+  OUT age_commitment_hash1 BYTEA,
+  OUT age_commitment_hash2 BYTEA)
+LANGUAGE plpgsql
+AS $$
+BEGIN
+WITH dd AS (
+SELECT
+  denominations_serial,
+  coin_val, coin_frac
+  FROM denominations
+    WHERE denom_pub_hash
+    IN
+     (in_denom_pub_hash1,
+      in_denom_pub_hash2)
+     ),--dd
+     input_rows AS (
+     VALUES
+      (in_coin_pub1,
+      in_denom_pub_hash1,
+      in_h_age_commitment1,
+      in_denom_sig1),
+      (in_coin_pub2,
+      in_denom_pub_hash2,
+      in_h_age_commitment2,
+      in_denom_sig2)
+      ),--ir
+      ins AS (
+      INSERT INTO known_coins (
+      coin_pub,
+      denominations_serial,
+      age_commitment_hash,
+      denom_sig,
+      remaining_val,
+      remaining_frac
+      )
+      SELECT
+        ir.coin_pub,
+        dd.denominations_serial,
+        ir.age_commitment_hash,
+        ir.denom_sig,
+        dd.coin_val,
+        dd.coin_frac
+        FROM input_rows ir
+        JOIN dd
+          ON dd.denom_pub_hash = ir.denom_pub_hash
+          ON CONFLICT DO NOTHING
+          RETURNING known_coin_id
+      ),--kc
+       exists AS (
+       SELECT
+        CASE
+          WHEN ins.known_coin_id IS NOT NULL
+          THEN
+            FALSE
+          ELSE
+            TRUE
+        END AS existed,
+        ins.known_coin_id,
+        dd.denom_pub_hash,
+        kc.age_commitment_hash
+        FROM input_rows ir
+        LEFT JOIN ins
+          ON ins.coin_pub = ir.coin_pub
+        LEFT JOIN known_coins kc
+          ON kc.coin_pub = ir.coin_pub
+        LEFT JOIN dd
+          ON dd.denom_pub_hash = ir.denom_pub_hash
+     )--exists
+SELECT
+ exists.existed AS existed1,
+ exists.known_coin_id AS known_coin_id1,
+ exists.denom_pub_hash AS denom_pub_hash1,
+ exists.age_commitment_hash AS age_commitment_hash1,
+ (
+   SELECT exists.existed
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash2
+ ) AS existed2,
+ (
+   SELECT exists.known_coin_id
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash2
+ ) AS known_coin_id2,
+ (
+   SELECT exists.denom_pub_hash
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash2
+ ) AS denom_pub_hash2,
+ (
+   SELECT exists.age_commitment_hash
+   FROM exists
+   WHERE exists.denom_pub_hash = in_denom_pub_hash2
+ )AS age_commitment_hash2
+FROM exists;
+
+RETURN;
+END $$;
+
+
+CREATE OR REPLACE FUNCTION exchange_do_batch1_known_coin(
+  IN in_coin_pub1 BYTEA,
+  IN in_denom_pub_hash1 BYTEA,
+  IN in_h_age_commitment1 BYTEA,
+  IN in_denom_sig1 BYTEA,
+  OUT existed1 BOOLEAN,
+  OUT known_coin_id1 INT8,
+  OUT denom_pub_hash1 BYTEA,
+  OUT age_commitment_hash1 BYTEA)
+LANGUAGE plpgsql
+AS $$
+BEGIN
+WITH dd AS (
+SELECT
+  denominations_serial,
+  coin_val, coin_frac
+  FROM denominations
+    WHERE denom_pub_hash
+    IN
+     (in_denom_pub_hash1,
+      in_denom_pub_hash2)
+     ),--dd
+     input_rows AS (
+     VALUES
+      (in_coin_pub1,
+      in_denom_pub_hash1,
+      in_h_age_commitment1,
+      in_denom_sig1)
+      ),--ir
+      ins AS (
+      INSERT INTO known_coins (
+      coin_pub,
+      denominations_serial,
+      age_commitment_hash,
+      denom_sig,
+      remaining_val,
+      remaining_frac
+      )
+      SELECT
+        ir.coin_pub,
+        dd.denominations_serial,
+        ir.age_commitment_hash,
+        ir.denom_sig,
+        dd.coin_val,
+        dd.coin_frac
+        FROM input_rows ir
+        JOIN dd
+          ON dd.denom_pub_hash = ir.denom_pub_hash
+          ON CONFLICT DO NOTHING
+          RETURNING known_coin_id
+      ),--kc
+       exists AS (
+       SELECT
+        CASE
+          WHEN ins.known_coin_id IS NOT NULL
+          THEN
+            FALSE
+          ELSE
+            TRUE
+        END AS existed,
+        ins.known_coin_id,
+        dd.denom_pub_hash,
+        kc.age_commitment_hash
+        FROM input_rows ir
+        LEFT JOIN ins
+          ON ins.coin_pub = ir.coin_pub
+        LEFT JOIN known_coins kc
+          ON kc.coin_pub = ir.coin_pub
+        LEFT JOIN dd
+          ON dd.denom_pub_hash = ir.denom_pub_hash
+       )--exists
+SELECT
+ exists.existed AS existed1,
+ exists.known_coin_id AS known_coin_id1,
+ exists.denom_pub_hash AS denom_pub_hash1,
+ exists.age_commitment_hash AS age_commitment_hash1
+FROM exists;
+
+RETURN;
+END $$;
+
+/*** THIS SQL CODE WORKS ***/
+/*
+CREATE OR REPLACE FUNCTION exchange_do_batch2_known_coin(
+  IN in_coin_pub1 BYTEA,
+  IN in_denom_pub_hash1 TEXT,
+  IN in_h_age_commitment1 TEXT,
+  IN in_denom_sig1 TEXT,
+  IN in_coin_pub2 BYTEA,
+  IN in_denom_pub_hash2 TEXT,
+  IN in_h_age_commitment2 TEXT,
+  IN in_denom_sig2 TEXT,
+  OUT existed1 BOOLEAN,
+  OUT existed2 BOOLEAN,
+  OUT known_coin_id1 INT8,
+  OUT known_coin_id2 INT8,
+  OUT denom_pub_hash1 TEXT,
+  OUT denom_pub_hash2 TEXT,
+  OUT age_commitment_hash1 TEXT,
+  OUT age_commitment_hash2 TEXT)
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  ins_values RECORD;
+BEGIN
+  FOR i IN 1..2 LOOP
+    ins_values := (
+      SELECT
+        in_coin_pub1 AS coin_pub,
+        in_denom_pub_hash1 AS denom_pub_hash,
+        in_h_age_commitment1 AS age_commitment_hash,
+        in_denom_sig1 AS denom_sig
+      WHERE i = 1
+      UNION
+      SELECT
+        in_coin_pub2 AS coin_pub,
+        in_denom_pub_hash2 AS denom_pub_hash,
+        in_h_age_commitment2 AS age_commitment_hash,
+        in_denom_sig2 AS denom_sig
+      WHERE i = 2
+    );
+    WITH dd (denominations_serial, coin_val, coin_frac) AS (
+      SELECT denominations_serial, coin_val, coin_frac
+      FROM denominations
+      WHERE denom_pub_hash = ins_values.denom_pub_hash
+    ),
+    input_rows(coin_pub) AS (
+      VALUES (ins_values.coin_pub)
+    ),
+    ins AS (
+      INSERT INTO known_coins (
+        coin_pub,
+        denominations_serial,
+        age_commitment_hash,
+        denom_sig,
+        remaining_val,
+        remaining_frac
+      ) SELECT
+        input_rows.coin_pub,
+        dd.denominations_serial,
+        ins_values.age_commitment_hash,
+        ins_values.denom_sig,
+        coin_val,
+        coin_frac
+      FROM dd
+      CROSS JOIN input_rows
+      ON CONFLICT DO NOTHING
+      RETURNING known_coin_id, denom_pub_hash
+    )
+    SELECT
+      CASE i
+        WHEN 1 THEN
+          COALESCE(ins.known_coin_id, 0) <> 0 AS existed1,
+          ins.known_coin_id AS known_coin_id1,
+          ins.denom_pub_hash AS denom_pub_hash1,
+          ins.age_commitment_hash AS age_commitment_hash1
+        WHEN 2 THEN
+          COALESCE(ins.known_coin_id, 0) <> 0 AS existed2,
+          ins.known_coin_id AS known_coin_id2,
+          ins.denom_pub_hash AS denom_pub_hash2,
+          ins.age_commitment_hash AS age_commitment_hash2
+      END
+    FROM ins;
+  END LOOP;
+END;
+$$;*/
diff --git a/src/exchangedb/exchange_do_batch_reserves_in_insert.sql 
b/src/exchangedb/exchange_do_batch_reserves_in_insert.sql
deleted file mode 100644
index 5ee81922..00000000
--- a/src/exchangedb/exchange_do_batch_reserves_in_insert.sql
+++ /dev/null
@@ -1,120 +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/>
---
-
-DROP FUNCTION IF EXISTS exchange_do_batch_reserves_in_insert;
-CREATE OR REPLACE FUNCTION exchange_do_batch_reserves_in_insert(
-  IN in_reserve_pub BYTEA,
-  IN in_expiration_date INT8,
-  IN in_gc_date INT8,
-  IN in_wire_ref INT8,
-  IN in_credit_val INT8,
-  IN in_credit_frac INT4,
-  IN in_exchange_account_name VARCHAR,
-  IN in_execution_date INT8,
-  IN in_wire_source_h_payto BYTEA,    ---h_payto
-  IN in_payto_uri VARCHAR,
-  IN in_reserve_expiration INT8,
-  IN in_notify text,
-  OUT out_reserve_found BOOLEAN,
-  OUT transaction_duplicate BOOLEAN,
-  OUT ruuid INT8)
-LANGUAGE plpgsql
-AS $$
-DECLARE
-  curs refcursor;
-DECLARE
-  i RECORD;
-DECLARE
-  curs_trans refcursor;
-BEGIN
-  ruuid = 0;
-  out_reserve_found = TRUE;
-  transaction_duplicate = TRUE;
-
---SIMPLE INSERT ON CONFLICT DO NOTHING
-  INSERT INTO wire_targets
-    (wire_target_h_payto
-    ,payto_uri)
-    VALUES
-    (in_wire_source_h_payto
-    ,in_payto_uri)
-  ON CONFLICT DO NOTHING;
-
-  OPEN curs FOR
-  WITH reserve_changes AS (
-    INSERT INTO reserves
-      (reserve_pub
-      ,current_balance_val
-      ,current_balance_frac
-      ,expiration_date
-      ,gc_date)
-      VALUES
-      (in_reserve_pub
-      ,in_credit_val
-      ,in_credit_frac
-      ,in_expiration_date
-      ,in_gc_date)
-     ON CONFLICT DO NOTHING
-     RETURNING reserve_uuid, reserve_pub)
-   SELECT * FROM reserve_changes;
-  FETCH FROM curs INTO i;
-  IF FOUND
-  THEN
-    -- We made a change, so the reserve did not previously exist.
-    IF in_reserve_pub = i.reserve_pub
-    THEN
-        out_reserve_found = FALSE;
-        ruuid = i.reserve_uuid;
-    END IF;
-  END IF;
-  CLOSE curs;
-
-  OPEN curs_trans FOR
-  WITH reserve_transaction AS(
-  INSERT INTO reserves_in
-    (reserve_pub
-    ,wire_reference
-    ,credit_val
-    ,credit_frac
-    ,exchange_account_section
-    ,wire_source_h_payto
-    ,execution_date)
-    VALUES
-    (in_reserve_pub
-    ,in_wire_ref
-    ,in_credit_val
-    ,in_credit_frac
-    ,in_exchange_account_name
-    ,in_wire_source_h_payto
-    ,in_execution_date)
-    ON CONFLICT DO NOTHING
-    RETURNING reserve_pub)
-  SELECT * FROM reserve_transaction;
-  FETCH FROM curs_trans INTO i;
-  IF FOUND
-  THEN
-    IF i.reserve_pub = in_reserve_pub
-    THEN
-    -- HAPPY PATH THERE IS NO DUPLICATE TRANS
-       transaction_duplicate = FALSE;
-       EXECUTE FORMAT (
-         'NOTIFY %s'
-         ,in_notify);
-    END IF;
-  END IF;
-  CLOSE curs_trans;
-  RETURN;
-END $$;
diff --git a/src/exchangedb/exchange_do_reserves_in_insert.sql 
b/src/exchangedb/exchange_do_reserves_in_insert.sql
new file mode 100644
index 00000000..3a217acc
--- /dev/null
+++ b/src/exchangedb/exchange_do_reserves_in_insert.sql
@@ -0,0 +1,1065 @@
+--
+-- This file is part of TALER
+-- 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
+-- Foundation; either version 3, or (at your option) any later version.
+--
+-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License along with
+-- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+--
+
+CREATE OR REPLACE FUNCTION exchange_do_batch_reserves_in_insert(
+  IN in_gc_date INT8,
+  IN in_reserve_expiration INT8,
+  IN in_reserve_pub BYTEA,
+  IN in_wire_ref INT8,
+  IN in_credit_val INT8,
+  IN in_credit_frac INT4,
+  IN in_exchange_account_name VARCHAR,
+  IN in_execution_date INT8,
+  IN in_wire_source_h_payto BYTEA,    ---h_payto
+  IN in_payto_uri VARCHAR,
+  IN in_notify text,
+  OUT out_reserve_found BOOLEAN,
+  OUT transaction_duplicate BOOLEAN,
+  OUT ruuid INT8)
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  curs refcursor;
+DECLARE
+  i RECORD;
+DECLARE
+  curs_trans refcursor;
+BEGIN
+  ruuid = 0;
+  out_reserve_found = TRUE;
+  transaction_duplicate = TRUE;
+
+--SIMPLE INSERT ON CONFLICT DO NOTHING
+  INSERT INTO wire_targets
+    (wire_target_h_payto
+    ,payto_uri)
+    VALUES
+    (in_wire_source_h_payto
+    ,in_payto_uri)
+  ON CONFLICT DO NOTHING;
+
+  OPEN curs FOR
+  WITH reserve_changes AS (
+    INSERT INTO reserves
+      (reserve_pub
+      ,current_balance_val
+      ,current_balance_frac
+      ,expiration_date
+      ,gc_date)
+      VALUES
+      (in_reserve_pub
+      ,in_credit_val
+      ,in_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date)
+     ON CONFLICT DO NOTHING
+     RETURNING reserve_uuid, reserve_pub)
+   SELECT * FROM reserve_changes;
+  FETCH FROM curs INTO i;
+  IF FOUND
+  THEN
+    -- We made a change, so the reserve did not previously exist.
+    IF in_reserve_pub = i.reserve_pub
+    THEN
+        out_reserve_found = FALSE;
+        ruuid = i.reserve_uuid;
+    END IF;
+  END IF;
+  CLOSE curs;
+
+  OPEN curs_trans FOR
+  WITH reserve_transaction AS(
+  INSERT INTO reserves_in
+    (reserve_pub
+    ,wire_reference
+    ,credit_val
+    ,credit_frac
+    ,exchange_account_section
+    ,wire_source_h_payto
+    ,execution_date)
+    VALUES
+    (in_reserve_pub
+    ,in_wire_ref
+    ,in_credit_val
+    ,in_credit_frac
+    ,in_exchange_account_name
+    ,in_wire_source_h_payto
+    ,in_execution_date)
+    ON CONFLICT DO NOTHING
+    RETURNING reserve_pub)
+  SELECT * FROM reserve_transaction;
+  FETCH FROM curs_trans INTO i;
+  IF FOUND
+  THEN
+    IF i.reserve_pub = in_reserve_pub
+    THEN
+    -- HAPPY PATH THERE IS NO DUPLICATE TRANS
+       transaction_duplicate = FALSE;
+       EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in_notify);
+    END IF;
+  END IF;
+  CLOSE curs_trans;
+  RETURN;
+END $$;
+
+CREATE OR REPLACE FUNCTION exchange_do_batch2_reserves_insert(
+  IN in_gc_date INT8,
+  IN in_reserve_expiration INT8,
+  IN in_reserve_pub BYTEA,
+  IN in_wire_ref INT8,
+  IN in_credit_val INT8,
+  IN in_credit_frac INT4,
+  IN in_exchange_account_name VARCHAR,
+  IN in_execution_date INT8,
+  IN in_wire_source_h_payto BYTEA,    ---h_payto
+  IN in_payto_uri VARCHAR,
+  IN in_notify text,
+  IN in2_notify text,
+  IN in2_reserve_pub BYTEA,
+  IN in2_wire_ref INT8,
+  IN in2_credit_val INT8,
+  IN in2_credit_frac INT4,
+  IN in2_exchange_account_name VARCHAR,
+  IN in2_execution_date INT8,
+  IN in2_wire_source_h_payto BYTEA,    ---h_payto
+  IN in2_payto_uri VARCHAR,
+  OUT out_reserve_found BOOLEAN,
+  OUT out_reserve_found2 BOOLEAN,
+  OUT transaction_duplicate BOOLEAN,
+  OUT transaction_duplicate2 BOOLEAN,
+  OUT ruuid INT8,
+  OUT ruuid2 INT8)
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  curs_reserve_exist REFCURSOR;
+DECLARE
+  curs_transaction_exist refcursor;
+DECLARE
+  i RECORD;
+DECLARE
+  r RECORD;
+DECLARE
+  k INT8;
+BEGIN
+  transaction_duplicate=TRUE;
+  transaction_duplicate2=TRUE;
+  out_reserve_found = TRUE;
+  out_reserve_found2 = TRUE;
+  ruuid=0;
+  ruuid2=0;
+  k=0;
+  INSERT INTO wire_targets
+    (wire_target_h_payto
+    ,payto_uri)
+    VALUES
+    (in_wire_source_h_payto
+    ,in_payto_uri),
+    (in2_wire_source_h_payto
+    ,in2_payto_uri)
+  ON CONFLICT DO NOTHING;
+
+  OPEN curs_reserve_exist FOR
+  WITH reserve_changes AS (
+    INSERT INTO reserves
+      (reserve_pub
+      ,current_balance_val
+      ,current_balance_frac
+      ,expiration_date
+      ,gc_date)
+      VALUES
+      (in_reserve_pub
+      ,in_credit_val
+      ,in_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in2_reserve_pub
+      ,in2_credit_val
+      ,in2_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date)
+     ON CONFLICT DO NOTHING
+     RETURNING reserve_uuid,reserve_pub)
+    SELECT * FROM reserve_changes;
+  WHILE k < 2 LOOP
+    FETCH FROM curs_reserve_exist INTO i;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = i.reserve_pub
+      THEN
+        ruuid = i.reserve_uuid;
+        IF in_reserve_pub <> in2_reserve_pub
+        THEN
+          out_reserve_found = FALSE;
+         END IF;
+      END IF;
+      IF in2_reserve_pub = i.reserve_pub
+      THEN
+          out_reserve_found2 = FALSE;
+          ruuid2 = i.reserve_uuid;
+      END IF;
+    END IF;
+    k=k+1;
+  END LOOP;
+  CLOSE curs_reserve_exist;
+
+  OPEN curs_transaction_exist FOR
+  WITH reserve_in_exist AS (
+  INSERT INTO reserves_in
+    (reserve_pub
+    ,wire_reference
+    ,credit_val
+    ,credit_frac
+    ,exchange_account_section
+    ,wire_source_h_payto
+    ,execution_date)
+    VALUES
+    (in_reserve_pub
+    ,in_wire_ref
+    ,in_credit_val
+    ,in_credit_frac
+    ,in_exchange_account_name
+    ,in_wire_source_h_payto
+    ,in_execution_date),
+    (in2_reserve_pub
+    ,in2_wire_ref
+    ,in2_credit_val
+    ,in2_credit_frac
+    ,in2_exchange_account_name
+    ,in2_wire_source_h_payto
+    ,in2_execution_date)
+    ON CONFLICT DO NOTHING
+    RETURNING reserve_pub)
+  SELECT * FROM reserve_in_exist;
+  FETCH FROM curs_transaction_exist INTO r;
+  IF FOUND
+  THEN
+    IF in_reserve_pub = r.reserve_pub
+    THEN
+       transaction_duplicate = FALSE;
+       EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in_notify);
+    END IF;
+    IF in2_reserve_pub = r.reserve_pub
+    THEN
+       transaction_duplicate2 = FALSE;
+       EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in2_notify);
+    END IF;
+    FETCH FROM curs_transaction_exist INTO r;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = r.reserve_pub
+      THEN
+        transaction_duplicate = FALSE;
+        EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in_notify);
+      END IF;
+      IF in2_reserve_pub = r.reserve_pub
+      THEN
+        transaction_duplicate2 = FALSE;
+        EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in2_notify);
+      END IF;
+    END IF;
+  END IF;
+/*  IF transaction_duplicate
+  OR transaction_duplicate2
+  THEN
+    CLOSE curs_transaction_exist;
+    ROLLBACK;
+    RETURN;
+  END IF;*/
+  CLOSE curs_transaction_exist;
+  RETURN;
+END $$;
+
+CREATE OR REPLACE FUNCTION exchange_do_batch4_reserves_insert(
+  IN in_gc_date INT8,
+  IN in_reserve_expiration INT8,
+  IN in_reserve_pub BYTEA,
+  IN in_wire_ref INT8,
+  IN in_credit_val INT8,
+  IN in_credit_frac INT4,
+  IN in_exchange_account_name VARCHAR,
+  IN in_execution_date INT8,
+  IN in_wire_source_h_payto BYTEA,    ---h_payto
+  IN in_payto_uri VARCHAR,
+  IN in_notify text,
+  IN in2_notify text,
+  IN in3_notify text,
+  IN in4_notify text,
+  IN in2_reserve_pub BYTEA,
+  IN in2_wire_ref INT8,
+  IN in2_credit_val INT8,
+  IN in2_credit_frac INT4,
+  IN in2_exchange_account_name VARCHAR,
+  IN in2_execute_date INT8,
+  IN in2_wire_source_h_payto BYTEA,    ---h_payto
+  IN in2_payto_uri VARCHAR,
+  IN in3_reserve_pub BYTEA,
+  IN in3_wire_ref INT8,
+  IN in3_credit_val INT8,
+  IN in3_credit_frac INT4,
+  IN in3_exchange_account_name VARCHAR,
+  IN in3_execute_date INT8,
+  IN in3_wire_source_h_payto BYTEA,    ---h_payto
+  IN in3_payto_uri VARCHAR,
+  IN in4_reserve_pub BYTEA,
+  IN in4_wire_ref INT8,
+  IN in4_credit_val INT8,
+  IN in4_credit_frac INT4,
+  IN in4_exchange_account_name VARCHAR,
+  IN in4_execution_date INT8,
+  IN in4_wire_source_h_payto BYTEA,    ---h_payto
+  IN in4_payto_uri VARCHAR,
+  OUT out_reserve_found BOOLEAN,
+  OUT out_reserve_found2 BOOLEAN,
+  OUT out_reserve_found3 BOOLEAN,
+  OUT out_reserve_found4 BOOLEAN,
+  OUT transaction_duplicate BOOLEAN,
+  OUT transaction_duplicate2 BOOLEAN,
+  OUT transaction_duplicate3 BOOLEAN,
+  OUT transaction_duplicate4 BOOLEAN,
+  OUT ruuid INT8,
+  OUT ruuid2 INT8,
+  OUT ruuid3 INT8,
+  OUT ruuid4 INT8)
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  curs_reserve_exist refcursor;
+DECLARE
+  k INT8;
+DECLARE
+  curs_transaction_exist refcursor;
+DECLARE
+  i RECORD;
+
+BEGIN
+--INITIALIZATION
+  transaction_duplicate=TRUE;
+  transaction_duplicate2=TRUE;
+  transaction_duplicate3=TRUE;
+  transaction_duplicate4=TRUE;
+  out_reserve_found = TRUE;
+  out_reserve_found2 = TRUE;
+  out_reserve_found3 = TRUE;
+  out_reserve_found4 = TRUE;
+  ruuid=0;
+  ruuid2=0;
+  ruuid3=0;
+  ruuid4=0;
+  k=0;
+  --SIMPLE INSERT ON CONFLICT DO NOTHING
+  INSERT INTO wire_targets
+    (wire_target_h_payto
+    ,payto_uri)
+    VALUES
+    (in_wire_source_h_payto
+    ,in_payto_uri),
+    (in2_wire_source_h_payto
+    ,in2_payto_uri),
+    (in3_wire_source_h_payto
+    ,in3_payto_uri),
+    (in4_wire_source_h_payto
+    ,in4_payto_uri)
+  ON CONFLICT DO NOTHING;
+
+  OPEN curs_reserve_exist FOR
+  WITH reserve_changes AS (
+    INSERT INTO reserves
+      (reserve_pub
+      ,current_balance_val
+      ,current_balance_frac
+      ,expiration_date
+      ,gc_date)
+      VALUES
+      (in_reserve_pub
+      ,in_credit_val
+      ,in_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in2_reserve_pub
+      ,in2_credit_val
+      ,in2_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in3_reserve_pub
+      ,in3_credit_val
+      ,in3_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in4_reserve_pub
+      ,in4_credit_val
+      ,in4_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date)
+     ON CONFLICT DO NOTHING
+     RETURNING reserve_uuid,reserve_pub)
+    SELECT * FROM reserve_changes;
+
+  WHILE k < 4 LOOP
+    FETCH FROM curs_reserve_exist INTO i;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = i.reserve_pub
+      THEN
+         ruuid = i.reserve_uuid;
+         IF in_reserve_pub
+         NOT IN (in2_reserve_pub
+                ,in3_reserve_pub
+                ,in4_reserve_pub)
+         THEN
+           out_reserve_found = FALSE;
+         END IF;
+      END IF;
+      IF in2_reserve_pub = i.reserve_pub
+      THEN
+         ruuid2 = i.reserve_uuid;
+         IF in2_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in3_reserve_pub
+                ,in4_reserve_pub)
+         THEN
+           out_reserve_found2 = FALSE;
+         END IF;
+      END IF;
+      IF in3_reserve_pub = i.reserve_pub
+      THEN
+         ruuid3 = i.reserve_uuid;
+         IF in3_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in2_reserve_pub
+                ,in4_reserve_pub)
+         THEN
+           out_reserve_found3 = FALSE;
+         END IF;
+      END IF;
+      IF in4_reserve_pub = i.reserve_pub
+      THEN
+         ruuid4 = i.reserve_uuid;
+         IF in4_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in2_reserve_pub
+                ,in3_reserve_pub)
+         THEN
+           out_reserve_found4 = FALSE;
+         END IF;
+      END IF;
+    END IF;
+  k=k+1;
+  END LOOP;
+  CLOSE curs_reserve_exist;
+
+  k=0;
+  OPEN curs_transaction_exist FOR
+  WITH reserve_in_changes AS (
+    INSERT INTO reserves_in
+    (reserve_pub
+    ,wire_reference
+    ,credit_val
+    ,credit_frac
+    ,exchange_account_section
+    ,wire_source_h_payto
+    ,execution_date)
+      VALUES
+    (in_reserve_pub
+    ,in_wire_ref
+    ,in_credit_val
+    ,in_credit_frac
+    ,in_exchange_account_name
+    ,in_wire_source_h_payto
+    ,in_execution_date),
+    (in2_reserve_pub
+    ,in2_wire_ref
+    ,in2_credit_val
+    ,in2_credit_frac
+    ,in2_exchange_account_name
+    ,in2_wire_source_h_payto
+    ,in2_execution_date),
+    (in3_reserve_pub
+    ,in3_wire_ref
+    ,in3_credit_val
+    ,in3_credit_frac
+    ,in3_exchange_account_name
+    ,in3_wire_source_h_payto
+    ,in3_execution_date),
+    (in4_reserve_pub
+    ,in4_wire_ref
+    ,in4_credit_val
+    ,in4_credit_frac
+    ,in4_exchange_account_name
+    ,in4_wire_source_h_payto
+    ,in4_execution_date)
+     ON CONFLICT DO NOTHING
+     RETURNING reserve_pub)
+    SELECT * FROM reserve_in_changes;
+  WHILE k < 4 LOOP
+    FETCH FROM curs_transaction_exist INTO i;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = i.reserve_pub
+      THEN
+         transaction_duplicate = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in_notify);
+      END IF;
+      IF in2_reserve_pub = i.reserve_pub
+      THEN
+         transaction_duplicate2 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in2_notify);
+      END IF;
+      IF in3_reserve_pub = i.reserve_pub
+      THEN
+         transaction_duplicate3 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in3_notify);
+      END IF;
+      IF in4_reserve_pub = i.reserve_pub
+      THEN
+         transaction_duplicate4 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in4_notify);
+      END IF;
+    END IF;
+  k=k+1;
+  END LOOP;
+ /**ROLLBACK TRANSACTION IN SORTED PROCEDURE IS IT PROSSIBLE ?**/
+  /*IF transaction_duplicate
+  OR transaction_duplicate2
+  OR transaction_duplicate3
+  OR transaction_duplicate4
+  THEN
+    RAISE EXCEPTION 'Reserve did not exist, but INSERT into reserves_in gave 
conflict';
+    ROLLBACK;
+    CLOSE curs_transaction_exist;
+    RETURN;
+  END IF;*/
+  CLOSE curs_transaction_exist;
+  RETURN;
+
+END $$;
+
+CREATE OR REPLACE FUNCTION exchange_do_batch8_reserves_insert(
+  IN in_gc_date INT8,
+  IN in_reserve_expiration INT8,
+  IN in_reserve_pub BYTEA,
+  IN in_wire_ref INT8,
+  IN in_credit_val INT8,
+  IN in_credit_frac INT4,
+  IN in_exchange_account_name VARCHAR,
+  IN in_execution_date INT8,
+  IN in_wire_source_h_payto BYTEA,    ---h_payto
+  IN in_payto_uri VARCHAR,
+  IN in_notify text,
+  IN in2_notify text,
+  IN in3_notify text,
+  IN in4_notify text,
+  IN in5_notify text,
+  IN in6_notify text,
+  IN in7_notify text,
+  IN in8_notify text,
+  IN in2_reserve_pub BYTEA,
+  IN in2_wire_ref INT8,
+  IN in2_credit_val INT8,
+  IN in2_credit_frac INT4,
+  IN in2_exchange_account_name VARCHAR,
+  IN in2_execution_date INT8,
+  IN in2_wire_source_h_payto BYTEA,    ---h_payto
+  IN in2_payto_uri VARCHAR,
+  IN in3_reserve_pub BYTEA,
+  IN in3_wire_ref INT8,
+  IN in3_credit_val INT8,
+  IN in3_credit_frac INT4,
+  IN in3_exchange_account_name VARCHAR,
+  IN in3_execution_date INT8,
+  IN in3_wire_source_h_payto BYTEA,    ---h_payto
+  IN in3_payto_uri VARCHAR,
+  IN in4_reserve_pub BYTEA,
+  IN in4_wire_ref INT8,
+  IN in4_credit_val INT8,
+  IN in4_credit_frac INT4,
+  IN in4_exchange_account_name VARCHAR,
+  IN in4_execution_date INT8,
+  IN in4_wire_source_h_payto BYTEA,    ---h_payto
+  IN in4_payto_uri VARCHAR,
+  IN in5_reserve_pub BYTEA,
+  IN in5_wire_ref INT8,
+  IN in5_credit_val INT8,
+  IN in5_credit_frac INT4,
+  IN in5_exchange_account_name VARCHAR,
+  IN in5_execution_date INT8,
+  IN in5_wire_source_h_payto BYTEA,    ---h_payto
+  IN in5_payto_uri VARCHAR,
+  IN in6_reserve_pub BYTEA,
+  IN in6_wire_ref INT8,
+  IN in6_credit_val INT8,
+  IN in6_credit_frac INT4,
+  IN in6_exchange_account_name VARCHAR,
+  IN in6_execution_date INT8,
+  IN in6_wire_source_h_payto BYTEA,    ---h_payto
+  IN in6_payto_uri VARCHAR,
+  IN in7_reserve_pub BYTEA,
+  IN in7_wire_ref INT8,
+  IN in7_credit_val INT8,
+  IN in7_credit_frac INT4,
+  IN in7_exchange_account_name VARCHAR,
+  IN in7_execution_date INT8,
+  IN in7_wire_source_h_payto BYTEA,    ---h_payto
+  IN in7_payto_uri VARCHAR,
+  IN in8_reserve_pub BYTEA,
+  IN in8_wire_ref INT8,
+  IN in8_credit_val INT8,
+  IN in8_credit_frac INT4,
+  IN in8_exchange_account_name VARCHAR,
+  IN in8_execution_date INT8,
+  IN in8_wire_source_h_payto BYTEA,    ---h_payto
+  IN in8_payto_uri VARCHAR,
+  OUT out_reserve_found BOOLEAN,
+  OUT out_reserve_found2 BOOLEAN,
+  OUT out_reserve_found3 BOOLEAN,
+  OUT out_reserve_found4 BOOLEAN,
+  OUT out_reserve_found5 BOOLEAN,
+  OUT out_reserve_found6 BOOLEAN,
+  OUT out_reserve_found7 BOOLEAN,
+  OUT out_reserve_found8 BOOLEAN,
+  OUT transaction_duplicate BOOLEAN,
+  OUT transaction_duplicate2 BOOLEAN,
+  OUT transaction_duplicate3 BOOLEAN,
+  OUT transaction_duplicate4 BOOLEAN,
+  OUT transaction_duplicate5 BOOLEAN,
+  OUT transaction_duplicate6 BOOLEAN,
+  OUT transaction_duplicate7 BOOLEAN,
+  OUT transaction_duplicate8 BOOLEAN,
+  OUT ruuid INT8,
+  OUT ruuid2 INT8,
+  OUT ruuid3 INT8,
+  OUT ruuid4 INT8,
+  OUT ruuid5 INT8,
+  OUT ruuid6 INT8,
+  OUT ruuid7 INT8,
+  OUT ruuid8 INT8)
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  curs_reserve_existed refcursor;
+DECLARE
+  k INT8;
+DECLARE
+  curs_transaction_existed refcursor;
+DECLARE
+  i RECORD;
+DECLARE
+  r RECORD;
+
+BEGIN
+--INITIALIZATION
+  transaction_duplicate=TRUE;
+  transaction_duplicate2=TRUE;
+  transaction_duplicate3=TRUE;
+  transaction_duplicate4=TRUE;
+  transaction_duplicate5=TRUE;
+  transaction_duplicate6=TRUE;
+  transaction_duplicate7=TRUE;
+  transaction_duplicate8=TRUE;
+  out_reserve_found = TRUE;
+  out_reserve_found2 = TRUE;
+  out_reserve_found3 = TRUE;
+  out_reserve_found4 = TRUE;
+  out_reserve_found5 = TRUE;
+  out_reserve_found6 = TRUE;
+  out_reserve_found7 = TRUE;
+  out_reserve_found8 = TRUE;
+  ruuid=0;
+  ruuid2=0;
+  ruuid3=0;
+  ruuid4=0;
+  ruuid5=0;
+  ruuid6=0;
+  ruuid7=0;
+  ruuid8=0;
+  k=0;
+
+  --SIMPLE INSERT ON CONFLICT DO NOTHING
+  INSERT INTO wire_targets
+    (wire_target_h_payto
+    ,payto_uri)
+    VALUES
+    (in_wire_source_h_payto
+    ,in_payto_uri),
+    (in2_wire_source_h_payto
+    ,in2_payto_uri),
+    (in3_wire_source_h_payto
+    ,in3_payto_uri),
+    (in4_wire_source_h_payto
+    ,in4_payto_uri),
+    (in5_wire_source_h_payto
+    ,in5_payto_uri),
+    (in6_wire_source_h_payto
+    ,in6_payto_uri),
+    (in7_wire_source_h_payto
+    ,in7_payto_uri),
+    (in8_wire_source_h_payto
+    ,in8_payto_uri)
+  ON CONFLICT DO NOTHING;
+
+  OPEN curs_reserve_existed FOR
+  WITH reserve_changes AS (
+    INSERT INTO reserves
+      (reserve_pub
+      ,current_balance_val
+      ,current_balance_frac
+      ,expiration_date
+      ,gc_date)
+      VALUES
+      (in_reserve_pub
+      ,in_credit_val
+      ,in_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in2_reserve_pub
+      ,in2_credit_val
+      ,in2_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in3_reserve_pub
+      ,in3_credit_val
+      ,in3_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in4_reserve_pub
+      ,in4_credit_val
+      ,in4_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in5_reserve_pub
+      ,in5_credit_val
+      ,in5_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in6_reserve_pub
+      ,in6_credit_val
+      ,in6_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in7_reserve_pub
+      ,in7_credit_val
+      ,in7_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date),
+      (in8_reserve_pub
+      ,in8_credit_val
+      ,in8_credit_frac
+      ,in_reserve_expiration
+      ,in_gc_date)
+     ON CONFLICT DO NOTHING
+     RETURNING reserve_uuid,reserve_pub)
+    SELECT * FROM reserve_changes;
+
+  WHILE k < 8 LOOP
+
+    FETCH FROM curs_reserve_existed INTO i;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = i.reserve_pub
+      THEN
+         ruuid = i.reserve_uuid;
+         IF in_reserve_pub
+         NOT IN (in2_reserve_pub
+                ,in3_reserve_pub
+                ,in4_reserve_pub
+                ,in5_reserve_pub
+                ,in6_reserve_pub
+                ,in7_reserve_pub
+                ,in8_reserve_pub)
+         THEN
+           out_reserve_found = FALSE;
+         END IF;
+      END IF;
+      IF in2_reserve_pub = i.reserve_pub
+      THEN
+         ruuid2 = i.reserve_uuid;
+         IF in2_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in3_reserve_pub
+                ,in4_reserve_pub
+                ,in5_reserve_pub
+                ,in6_reserve_pub
+                ,in7_reserve_pub
+                ,in8_reserve_pub)
+         THEN
+           out_reserve_found2 = FALSE;
+         END IF;
+      END IF;
+      IF in3_reserve_pub = i.reserve_pub
+      THEN
+         ruuid3 = i.reserve_uuid;
+         IF in3_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in2_reserve_pub
+                ,in4_reserve_pub
+                ,in5_reserve_pub
+                ,in6_reserve_pub
+                ,in7_reserve_pub
+                ,in8_reserve_pub)
+         THEN
+           out_reserve_found3 = FALSE;
+         END IF;
+      END IF;
+      IF in4_reserve_pub = i.reserve_pub
+      THEN
+         ruuid4 = i.reserve_uuid;
+         IF in4_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in2_reserve_pub
+                ,in3_reserve_pub
+                ,in5_reserve_pub
+                ,in6_reserve_pub
+                ,in7_reserve_pub
+                ,in8_reserve_pub)
+         THEN
+           out_reserve_found4 = FALSE;
+         END IF;
+      END IF;
+      IF in5_reserve_pub = i.reserve_pub
+      THEN
+         ruuid5 = i.reserve_uuid;
+         IF in5_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in2_reserve_pub
+                ,in3_reserve_pub
+                ,in4_reserve_pub
+                ,in6_reserve_pub
+                ,in7_reserve_pub
+                ,in8_reserve_pub)
+         THEN
+           out_reserve_found5 = FALSE;
+         END IF;
+      END IF;
+      IF in6_reserve_pub = i.reserve_pub
+      THEN
+         ruuid6 = i.reserve_uuid;
+         IF in6_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in2_reserve_pub
+                ,in3_reserve_pub
+                ,in4_reserve_pub
+                ,in5_reserve_pub
+                ,in7_reserve_pub
+                ,in8_reserve_pub)
+         THEN
+           out_reserve_found6 = FALSE;
+         END IF;
+      END IF;
+      IF in7_reserve_pub = i.reserve_pub
+      THEN
+         ruuid7 = i.reserve_uuid;
+         IF in7_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in2_reserve_pub
+                ,in3_reserve_pub
+                ,in4_reserve_pub
+                ,in5_reserve_pub
+                ,in6_reserve_pub
+                ,in8_reserve_pub)
+         THEN
+           out_reserve_found7 = FALSE;
+         END IF;
+      END IF;
+      IF in8_reserve_pub = i.reserve_pub
+      THEN
+         ruuid8 = i.reserve_uuid;
+         IF in8_reserve_pub
+         NOT IN (in_reserve_pub
+                ,in2_reserve_pub
+                ,in3_reserve_pub
+                ,in4_reserve_pub
+                ,in5_reserve_pub
+                ,in6_reserve_pub
+                ,in7_reserve_pub)
+         THEN
+           out_reserve_found8 = FALSE;
+         END IF;
+      END IF;
+    END IF;
+  k=k+1;
+  END LOOP;
+
+  CLOSE curs_reserve_existed;
+
+  k=0;
+  OPEN curs_transaction_existed FOR
+  WITH reserve_in_changes AS (
+    INSERT INTO reserves_in
+    (reserve_pub
+    ,wire_reference
+    ,credit_val
+    ,credit_frac
+    ,exchange_account_section
+    ,wire_source_h_payto
+    ,execution_date)
+      VALUES
+    (in_reserve_pub
+    ,in_wire_ref
+    ,in_credit_val
+    ,in_credit_frac
+    ,in_exchange_account_name
+    ,in_wire_source_h_payto
+    ,in_execution_date),
+    (in2_reserve_pub
+    ,in2_wire_ref
+    ,in2_credit_val
+    ,in2_credit_frac
+    ,in2_exchange_account_name
+    ,in2_wire_source_h_payto
+    ,in2_execution_date),
+    (in3_reserve_pub
+    ,in3_wire_ref
+    ,in3_credit_val
+    ,in3_credit_frac
+    ,in3_exchange_account_name
+    ,in3_wire_source_h_payto
+    ,in3_execution_date),
+    (in4_reserve_pub
+    ,in4_wire_ref
+    ,in4_credit_val
+    ,in4_credit_frac
+    ,in4_exchange_account_name
+    ,in4_wire_source_h_payto
+    ,in4_execution_date),
+    (in5_reserve_pub
+    ,in5_wire_ref
+    ,in5_credit_val
+    ,in5_credit_frac
+    ,in5_exchange_account_name
+    ,in5_wire_source_h_payto
+    ,in5_execution_date),
+    (in6_reserve_pub
+    ,in6_wire_ref
+    ,in6_credit_val
+    ,in6_credit_frac
+    ,in6_exchange_account_name
+    ,in6_wire_source_h_payto
+    ,in6_execution_date),
+    (in7_reserve_pub
+    ,in7_wire_ref
+    ,in7_credit_val
+    ,in7_credit_frac
+    ,in7_exchange_account_name
+    ,in7_wire_source_h_payto
+    ,in7_execution_date),
+    (in8_reserve_pub
+    ,in8_wire_ref
+    ,in8_credit_val
+    ,in8_credit_frac
+    ,in8_exchange_account_name
+    ,in8_wire_source_h_payto
+    ,in8_execution_date)
+     ON CONFLICT DO NOTHING
+     RETURNING reserve_pub)
+    SELECT * FROM reserve_in_changes;
+
+  WHILE k < 8 LOOP
+    FETCH FROM curs_transaction_existed INTO r;
+    IF FOUND
+    THEN
+      IF in_reserve_pub = r.reserve_pub
+      THEN
+         transaction_duplicate = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in_notify);
+      END IF;
+      IF in2_reserve_pub = r.reserve_pub
+      THEN
+         transaction_duplicate2 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in2_notify);
+      END IF;
+      IF in3_reserve_pub = r.reserve_pub
+      THEN
+         transaction_duplicate3 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in3_notify);
+      END IF;
+      IF in4_reserve_pub = r.reserve_pub
+      THEN
+         transaction_duplicate4 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in4_notify);
+      END IF;
+      IF in5_reserve_pub = r.reserve_pub
+      THEN
+         transaction_duplicate5 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in5_notify);
+      END IF;
+      IF in6_reserve_pub = r.reserve_pub
+      THEN
+         transaction_duplicate6 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in6_notify);
+      END IF;
+      IF in7_reserve_pub = r.reserve_pub
+      THEN
+         transaction_duplicate7 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in7_notify);
+      END IF;
+      IF in8_reserve_pub = r.reserve_pub
+      THEN
+         transaction_duplicate8 = FALSE;
+         EXECUTE FORMAT (
+         'NOTIFY %s'
+         ,in8_notify);
+      END IF;
+    END IF;
+  k=k+1;
+  END LOOP;
+ /* IF transaction_duplicate
+  OR transaction_duplicate2
+  OR transaction_duplicate3
+  OR transaction_duplicate4
+  OR transaction_duplicate5
+  OR transaction_duplicate6
+  OR transaction_duplicate7
+  OR transaction_duplicate8
+  THEN
+    CLOSE curs_transaction_existed;
+    ROLLBACK;
+    RETURN;
+  END IF;*/
+  CLOSE curs_transaction_existed;
+  RETURN;
+END $$;
diff --git a/src/exchangedb/exchange_do_get_ready_deposit.sql 
b/src/exchangedb/exchange_get_ready_deposit.sql
similarity index 66%
copy from src/exchangedb/exchange_do_get_ready_deposit.sql
copy to src/exchangedb/exchange_get_ready_deposit.sql
index 001b69cb..4f76463f 100644
--- a/src/exchangedb/exchange_do_get_ready_deposit.sql
+++ b/src/exchangedb/exchange_get_ready_deposit.sql
@@ -23,47 +23,38 @@ CREATE OR REPLACE FUNCTION exchange_do_get_ready_deposit(
 LANGUAGE plpgsql
 AS $$
 DECLARE
- var_wire_target_h_payto BYTEA;
-DECLARE
- var_coin_pub BYTEA;
-DECLARE
- var_deposit_serial_id INT8;
-DECLARE
- curs CURSOR
- FOR
- SELECT
-   coin_pub
-  ,deposit_serial_id
-  ,wire_deadline
-  ,shard
- FROM deposits_by_ready
- WHERE wire_deadline <= in_now
- AND shard >=in_start_shard_now
- AND shard <=in_end_shard_now
- LIMIT 1;
+  curs CURSOR
+  FOR
+  SELECT
+    coin_pub
+   ,deposit_serial_id
+   ,wire_deadline
+   ,shard
+  FROM deposits_by_ready dbr
+  WHERE wire_deadline <= in_now
+  AND shard >= in_start_shard_now
+  AND shard <=in_end_shard_now
+  ORDER BY
+     wire_deadline ASC
+    ,shard ASC
+  LIMIT 1;
 DECLARE
- i RECORD;
+  i RECORD;
 BEGIN
 OPEN curs;
 FETCH FROM curs INTO i;
-IF NOT FOUND
-THEN
-  RETURN;
-END IF;
 SELECT
    payto_uri
   ,merchant_pub
   INTO
    out_payto_uri
   ,out_merchant_pub
-  FROM deposits dep
+  FROM deposits
   JOIN wire_targets wt
-  ON (wt.wire_target_h_payto=dep.wire_target_h_payto)
-  WHERE dep.coin_pub=i.coin_pub
-  AND dep.deposit_serial_id=i.deposit_serial_id
-  ORDER BY
-   i.wire_deadline ASC
-  ,i.shard ASC;
-
+  USING (wire_target_h_payto)
+  WHERE
+  i.coin_pub = coin_pub
+  AND i.deposit_serial_id=deposit_serial_id;
+CLOSE curs;
 RETURN;
 END $$;
diff --git a/src/exchangedb/pg_reserves_in_insert.c 
b/src/exchangedb/pg_reserves_in_insert.c
index 1c578478..16d30d41 100644
--- a/src/exchangedb/pg_reserves_in_insert.c
+++ b/src/exchangedb/pg_reserves_in_insert.c
@@ -58,7 +58,6 @@ compute_notify_on_reserve (const struct 
TALER_ReservePublicKeyP *reserve_pub)
 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,
@@ -76,19 +75,18 @@ insert1 (struct PostgresClosure *pg,
            ",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);");
+           " ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11);");
 
   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_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
     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
   };
@@ -132,7 +130,6 @@ insert1 (struct PostgresClosure *pg,
 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,
@@ -153,20 +150,19 @@ insert2 (struct PostgresClosure *pg,
            ",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);");
+           " 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20);");
 
   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_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
     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]),
 
@@ -177,7 +173,6 @@ insert2 (struct PostgresClosure *pg,
     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[] = {
@@ -238,7 +233,6 @@ insert2 (struct PostgresClosure *pg,
 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,
@@ -265,19 +259,19 @@ insert4 (struct PostgresClosure *pg,
            ",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);");
+           " 
($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);");
 
   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_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
     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]),
@@ -290,7 +284,6 @@ insert4 (struct PostgresClosure *pg,
     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),
@@ -299,7 +292,6 @@ insert4 (struct PostgresClosure *pg,
     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),
@@ -308,7 +300,6 @@ insert4 (struct PostgresClosure *pg,
     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
   };
@@ -385,7 +376,6 @@ insert4 (struct PostgresClosure *pg,
 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,
@@ -398,8 +388,8 @@ insert8 (struct PostgresClosure *pg,
   enum GNUNET_DB_QueryStatus qs3;
   PREPARE (pg,
            "batch8_reserve_create",
-           "SELECT "
-           "out_reserve_found AS conflicted"
+           "SELECT"
+           " out_reserve_found AS conflicted"
            ",out_reserve_found2 AS conflicted2"
            ",out_reserve_found3 AS conflicted3"
            ",out_reserve_found4 AS conflicted4"
@@ -424,19 +414,18 @@ insert8 (struct PostgresClosure *pg,
            ",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);");
+           " 
($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);");
 
   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_timestamp (&reserve_expiration),
+    GNUNET_PQ_query_param_auto_from_type (reserves[0].reserve_pub),
     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]),
@@ -453,7 +442,6 @@ insert8 (struct PostgresClosure *pg,
     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),
@@ -462,7 +450,6 @@ insert8 (struct PostgresClosure *pg,
     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),
@@ -471,7 +458,6 @@ insert8 (struct PostgresClosure *pg,
     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),
@@ -489,7 +475,6 @@ insert8 (struct PostgresClosure *pg,
     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),
@@ -498,7 +483,6 @@ insert8 (struct PostgresClosure *pg,
     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),
@@ -507,7 +491,6 @@ insert8 (struct PostgresClosure *pg,
     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
   };
@@ -633,8 +616,6 @@ TEH_PG_reserves_in_insert (void *cls,
   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];
@@ -642,6 +623,8 @@ TEH_PG_reserves_in_insert (void *cls,
   bool t_duplicate = false;
   struct GNUNET_TIME_Timestamp reserve_expiration
     = GNUNET_TIME_relative_to_timestamp (pg->idle_reserve_expiration_time);
+  struct GNUNET_TIME_Timestamp gc
+    = GNUNET_TIME_relative_to_timestamp (pg->legal_reserve_expiration_time);
   bool conflicts[reserves_length];
   char *notify_s[reserves_length];
 
@@ -652,12 +635,6 @@ TEH_PG_reserves_in_insert (void *cls,
     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)),
@@ -694,7 +671,6 @@ TEH_PG_reserves_in_insert (void *cls,
     {
       qs1 = insert8 (pg,
                      &reserves[i],
-                     expiry,
                      gc,
                      h_payto,
                      &notify_s[i],
@@ -738,7 +714,6 @@ TEH_PG_reserves_in_insert (void *cls,
     case 4:
       qs4 = insert4 (pg,
                      &reserves[i],
-                     expiry,
                      gc,
                      h_payto,
                      &notify_s[i],
@@ -769,7 +744,6 @@ TEH_PG_reserves_in_insert (void *cls,
     case 2:
       qs5 = insert2 (pg,
                      &reserves[i],
-                     expiry,
                      gc,
                      h_payto,
                      &notify_s[i],
@@ -797,7 +771,6 @@ TEH_PG_reserves_in_insert (void *cls,
     case 1:
       qs2 = insert1 (pg,
                      &reserves[i],
-                     expiry,
                      gc,
                      h_payto,
                      &notify_s[i],
@@ -806,6 +779,7 @@ TEH_PG_reserves_in_insert (void *cls,
                      &conflicts[i],
                      &reserve_uuid[i],
                      &results[i]);
+      fprintf(stdout, "reserve uuid : %ld c :%d t:%d\n", reserve_uuid[i], 
conflicts[i], transaction_duplicate[i]);
       if (qs2<0)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -815,6 +789,7 @@ TEH_PG_reserves_in_insert (void *cls,
       }
       need_update |= conflicts[i];
       t_duplicate |= transaction_duplicate[i];
+
       i += 1;
       break;
     case 0:
@@ -864,7 +839,7 @@ TEH_PG_reserves_in_insert (void *cls,
       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_timestamp (&reserve_expiration),
         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),
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 2ef25077..2f331818 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -773,6 +773,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     = &TEH_PG_select_aml_history;
   plugin->insert_aml_decision
     = &TEH_PG_insert_aml_decision;
+
   return plugin;
 }
 
diff --git a/src/exchangedb/procedures.sql.in b/src/exchangedb/procedures.sql.in
index a53396c3..12ec3656 100644
--- a/src/exchangedb/procedures.sql.in
+++ b/src/exchangedb/procedures.sql.in
@@ -39,13 +39,11 @@ SET search_path TO exchange;
 #include "exchange_do_insert_or_update_policy_details.sql"
 #include "exchange_do_insert_aml_decision.sql"
 #include "exchange_do_insert_aml_officer.sql"
-#include "exchange_do_batch_reserves_in_insert.sql"
+#include "exchange_do_reserves_in_insert.sql"
 #include "exchange_do_batch_reserves_update.sql"
-#include "exchange_do_batch2_reserves_in_insert.sql"
-#include "exchange_do_batch4_reserves_in_insert.sql"
-#include "exchange_do_batch8_reserves_in_insert.sql"
 #include "exchange_do_refund_by_coin.sql"
 #include "exchange_do_get_ready_deposit.sql"
 #include "exchange_do_get_link_data.sql"
+#include "exchange_do_batch_coin_known.sql"
 
 COMMIT;
diff --git a/src/exchangedb/spi/README.md b/src/exchangedb/spi/README.md
new file mode 100644
index 00000000..ec6a9016
--- /dev/null
+++ b/src/exchangedb/spi/README.md
@@ -0,0 +1,41 @@
+                           Server Programming Interface (SPI)
+
+
+Dependencies:
+=============
+
+These are the direct dependencies for running SPI functions :
+
+
+
+Step 1:
+"postgresql-server-dev-<depends on your postgresql version>"
+-- sudo apt-get install libpq-dev postgresql-server-dev-13
+
+Step 2:
+To solve gssapi/gssapi.h, use the following command:
+apt-get install libkrb5-dev
+
+Step 3:
+apt-cache search openssl | grep -- -dev
+apt-get install libssl-dev
+
+Compile:
+========
+gcc -shared -o <file_name>.so <file_name>.c
+
+CALL FUNCTIONS:
+===============
+
+psql -c "SELECT <function_name>();" db_name
+
+Structure:
+==========
+
+usr/include/postgres/
+
+usr/include/postgres/13/server/
+
+make
+make install
+psql
\ No newline at end of file
diff --git a/src/exchangedb/spi/own_test.bc b/src/exchangedb/spi/own_test.bc
new file mode 100644
index 00000000..240c78cf
Binary files /dev/null and b/src/exchangedb/spi/own_test.bc differ
diff --git a/src/exchangedb/spi/own_test.c b/src/exchangedb/spi/own_test.c
new file mode 100644
index 00000000..10af02e3
--- /dev/null
+++ b/src/exchangedb/spi/own_test.c
@@ -0,0 +1,826 @@
+#include "postgres.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libpq-fe.h>
+#include <internal/libpq-int.h>
+#include <catalog/pg_type.h>
+#include <executor/spi.h>
+#include <funcapi.h>
+#include <fmgr.h>
+#include <utils/builtins.h>
+#include "utils/array.h"
+#include <sys/time.h>
+#include "utils/numeric.h"
+#include "utils/timestamp.h"
+#include <utils/bytea.h>
+
+#ifdef PG_MODULE_MAGIC
+PG_MODULE_MAGIC;
+#endif
+
+typedef struct {
+  Datum col1;
+  Datum col2;
+} valuest;
+
+void _PG_init(void);
+void _PG_fini(void);
+
+void _PG_init(void)
+{
+}
+
+PG_FUNCTION_INFO_V1(pg_spi_insert_int);
+PG_FUNCTION_INFO_V1(pg_spi_select_from_x);
+PG_FUNCTION_INFO_V1(pg_spi_select_pair_from_y);
+//PG_FUNCTION_INFO_V1(pg_spi_select_with_cond);
+PG_FUNCTION_INFO_V1(pg_spi_update_y);
+PG_FUNCTION_INFO_V1(pg_spi_prepare_example);
+PG_FUNCTION_INFO_V1(pg_spi_prepare_example_without_saveplan);
+PG_FUNCTION_INFO_V1(pg_spi_prepare_insert);
+PG_FUNCTION_INFO_V1(pg_spi_prepare_insert_without_saveplan);
+//PG_FUNCTION_INFO_V1(pg_spi_prepare_select_with_cond);
+PG_FUNCTION_INFO_V1(pg_spi_prepare_select_with_cond_without_saveplan);
+PG_FUNCTION_INFO_V1(pg_spi_prepare_update);
+PG_FUNCTION_INFO_V1(pg_spi_get_dep_ref_fees);
+// SIMPLE SELECT
+Datum
+pg_spi_prepare_example(PG_FUNCTION_ARGS)
+{
+  static SPIPlanPtr prepared_plan;
+  int ret;
+  int64 result;
+  char * value;
+  SPIPlanPtr new_plan;
+
+  ret=SPI_connect();
+  if (ret != SPI_OK_CONNECT) {
+    elog(ERROR, "DB connexion failed ! \n");
+  }
+  {
+    if (prepared_plan == NULL)
+    {
+      new_plan = SPI_prepare("SELECT 1 FROM joseph_test.X", 0, NULL);
+      prepared_plan = SPI_saveplan(new_plan);
+
+      if (prepared_plan == NULL)
+      {
+        elog(ERROR, "FAIL TO SAVE !\n");
+      }
+    }
+
+    ret = SPI_execute_plan(prepared_plan, NULL, 0,false, 0);
+    if (ret != SPI_OK_SELECT) {
+      elog(ERROR, "SELECT FAILED %d !\n", ret);
+    }
+
+    if (SPI_tuptable != NULL && SPI_tuptable->vals != NULL && 
SPI_tuptable->tupdesc != NULL)
+    {
+      value = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
+      result = atoi(value);
+    }
+    else
+    {
+      elog(ERROR, "EMPTY TABLE !\n");
+    }
+  }
+  SPI_finish();
+  PG_RETURN_INT64(result);
+}
+
+
+
+Datum
+pg_spi_prepare_example_without_saveplan(PG_FUNCTION_ARGS)
+{
+  int ret;
+  int64 result;
+  char * value;
+  SPIPlanPtr new_plan;
+
+  ret=SPI_connect();
+  if (ret != SPI_OK_CONNECT) {
+    elog(ERROR, "DB connexion failed ! \n");
+  }
+
+  {
+    new_plan = SPI_prepare("SELECT 1 FROM joseph_test.X", 0, NULL);
+    ret = SPI_execute_plan(new_plan, NULL, 0,false, 0);
+    if (ret != SPI_OK_SELECT) {
+      elog(ERROR, "SELECT FAILED %d !\n", ret);
+    }
+
+    if (SPI_tuptable != NULL
+        && SPI_tuptable->vals != NULL
+        && SPI_tuptable->tupdesc != NULL)
+    {
+      value = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
+      result = atoi(value);
+    }
+    else
+    {
+      elog(ERROR, "EMPTY TABLE !\n");
+    }
+  }
+  SPI_finish();
+  PG_RETURN_INT64(result);//  PG_RETURN_INT64(result);
+}
+
+
+//SELECT 1 FROM X
+//V1
+Datum
+pg_spi_select_from_x(PG_FUNCTION_ARGS)
+{
+  int ret;
+  char *query = "SELECT 1 FROM joseph_test.X";
+  uint64 proc;
+  ret = SPI_connect();
+
+  if (ret != SPI_OK_CONNECT)
+  {
+    elog(ERROR, "SPI_connect failed");
+  }
+
+  ret = SPI_exec(query, 10);
+  proc = SPI_processed;
+  if (ret != SPI_OK_SELECT)
+  {
+    elog(ERROR, "SPI_exec failed");
+  }
+
+  SPI_finish();
+
+  PG_RETURN_INT64(proc);
+}
+
+//INSERT INTO X VALUES (1)
+Datum
+pg_spi_insert_int(PG_FUNCTION_ARGS)
+{
+  int ret;
+  int nargs;
+  Oid argtypes[1];
+  Datum values[1];
+  char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)";
+
+  ret = SPI_connect();
+  if (ret != SPI_OK_CONNECT)
+  {
+    elog(ERROR, "SPI_connect failed");
+  }
+
+  nargs = 1;
+  argtypes[0] = INT4OID;
+  values[0] = Int32GetDatum(3);
+
+  ret = SPI_execute_with_args(query, nargs, argtypes, values, NULL, false, 0);
+  if (ret != SPI_OK_INSERT)
+  {
+    elog(ERROR, "SPI_execute_with_args failed");
+  }
+
+  SPI_finish();
+
+  PG_RETURN_VOID();
+}
+
+
+Datum
+pg_spi_prepare_insert(PG_FUNCTION_ARGS)
+{
+  static SPIPlanPtr prepared_plan = NULL;
+  int ret;
+  int nargs;
+  Oid argtypes[1];
+  Datum values[1];
+  char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)";
+  SPIPlanPtr new_plan;
+  ret = SPI_connect();
+  if (ret != SPI_OK_CONNECT)
+  {
+    elog(ERROR, "SPI_connect failed ! \n");
+  }
+  if (prepared_plan == NULL) {
+
+    argtypes[0] = INT4OID;
+    nargs = 1;
+    values[0] = Int32GetDatum(3);
+    new_plan = SPI_prepare(query, nargs, argtypes);
+    if (new_plan== NULL)
+    {
+      elog(ERROR, "SPI_prepare failed ! \n");
+    }
+    prepared_plan = SPI_saveplan(new_plan);
+    if (prepared_plan == NULL)
+    {
+      elog(ERROR, "SPI_saveplan failed ! \n");
+    }
+  }
+
+  ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0);
+  if (ret != SPI_OK_INSERT)
+  {
+    elog(ERROR, "SPI_execute_plan failed ! \n");
+  }
+
+  SPI_finish();
+
+  PG_RETURN_VOID();
+}
+/*
+Datum
+pg_spi_prepare_insert_bytea(PG_FUNCTION_ARGS)
+{
+  static SPIPlanPtr prepared_plan = NULL;
+  int ret;
+  int nargs;
+  Oid argtypes[1];
+  Datum values[1];
+  Oid argtypes2[1];
+  Datum val[1];
+  char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)";
+  SPIPlanPtr new_plan;
+  ret = SPI_connect();
+  if (ret != SPI_OK_CONNECT)
+  {
+    elog(ERROR, "SPI_connect failed ! \n");
+  }
+  if (prepared_plan == NULL) {
+    argtypes2[0] = BOOLOID;
+    val[0] = BoolGetDatum();
+    argtypes[0] = BYTEAOID;
+    nargs = 1;
+    values[0] = Int32GetDatum(3);
+    new_plan = SPI_prepare(query, nargs, argtypes);
+    if (new_plan== NULL)
+    {
+      elog(ERROR, "SPI_prepare failed ! \n");
+    }
+    prepared_plan = SPI_saveplan(new_plan);
+    if (prepared_plan == NULL)
+    {
+      elog(ERROR, "SPI_saveplan failed ! \n");
+    }
+  }
+
+  ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0);
+  if (ret != SPI_OK_INSERT)
+  {
+    elog(ERROR, "SPI_execute_plan failed ! \n");
+  }
+
+  SPI_finish();
+
+  PG_RETURN_VOID();
+}
+*/
+
+Datum
+pg_spi_prepare_insert_without_saveplan(PG_FUNCTION_ARGS)
+{
+  int ret;
+  int nargs;
+  Oid argtypes[1];
+  Datum values[1];
+  char *query = "INSERT INTO joseph_test.X (a) VALUES ($1)";
+  SPIPlanPtr new_plan;
+  ret = SPI_connect();
+  if (ret != SPI_OK_CONNECT)
+  {
+    elog(ERROR, "SPI_connect failed");
+  }
+  {
+    argtypes[0] = INT4OID;
+    nargs = 1;
+    values[0] = Int32GetDatum(3);
+    new_plan = SPI_prepare(query, nargs, argtypes);
+    if (new_plan== NULL)
+    {
+      elog(ERROR, "SPI_prepare failed");
+    }
+  }
+
+  ret = SPI_execute_plan(new_plan, values, NULL, false, 0);
+  if (ret != SPI_OK_INSERT)
+  {
+    elog(ERROR, "SPI_execute_plan failed");
+  }
+
+  SPI_finish();
+
+  PG_RETURN_VOID();
+}
+
+
+
+
+
+
+/*
+Datum
+pg_spi_select_pair_from_y(PG_FUNCTION_ARGS)
+{
+  int ret;
+  valuest result;
+  bool isnull;
+  char *query = "SELECT 1,1 FROM joseph_test.Y";
+  result.col1 = 0;
+  result.col2 = 0;
+
+  if ((ret = SPI_connect()) < 0) {
+    fprintf(stderr, "SPI_connect returned %d\n", ret);
+    exit(1);
+  }
+  ret = SPI_exec(query, 0);
+  if (ret == SPI_OK_SELECT && SPI_processed > 0) {
+    int i;
+    SPITupleTable *tuptable = SPI_tuptable;
+    TupleDesc tupdesc = tuptable->tupdesc;
+    for (i = 0; i < SPI_processed; i++) {
+      HeapTuple tuple = tuptable->vals[i];
+      result.col1 = SPI_getbinval(tuple, tupdesc, 1, &isnull);
+      result.col2 = SPI_getbinval(tuple, tupdesc, 2, &isnull);
+    }
+  }
+  SPI_finish();
+  PG_RETURN_TEXT_P(result);
+}
+*/
+
+//SELECT X FROM Y WHERE Z=$1
+/*
+Datum
+pg_spi_select_with_cond(PG_FUNCTION_ARGS)
+{
+    int ret;
+    char *query;
+    int nargs;
+    Oid argtypes[1];
+    Datum values[1];
+    uint64 proc;
+    query = "SELECT col1 FROM joseph_test.Y WHERE col2 = $1";
+
+    ret = SPI_connect();
+    if (ret != SPI_OK_CONNECT) {
+        elog(ERROR, "SPI_connect failed: %d", ret);
+    }
+    nargs = 1;
+    argtypes[0] = INT4OID;
+    values[0] = Int32GetDatum(2);
+
+    ret = SPI_execute_with_args(query, nargs, argtypes, values, NULL, false, 
0);
+    proc = SPI_processed;
+    if (ret != SPI_OK_SELECT)
+    {
+      elog(ERROR, "SPI_execute_with_args failed");
+    }
+
+    SPI_finish();
+
+
+    PG_RETURN_INT64(proc);
+    }*/
+
+////////SELECT WITH COND
+/*
+Datum pg_spi_prepare_select_with_cond(PG_FUNCTION_ARGS) {
+  static SPIPlanPtr prepared_plan = NULL;
+  SPIPlanPtr new_plan;
+  int ret;
+  Datum values[1];
+  uint64 proc;
+  int nargs;
+  Oid argtypes[1];
+  char *query = "SELECT col1 FROM joseph_test.Y WHERE col1 = $1";
+  int result = 0;
+
+  ret = SPI_connect();
+  if (ret != SPI_OK_CONNECT)
+    elog(ERROR, "SPI_connect failed ! \n");
+
+  if (prepared_plan == NULL) {
+
+    argtypes[0] = INT4OID;
+    nargs = 1;
+    values[0] = DatumGetByteaP(SPI_getbinval(tuptable->vals[0], tupdesc, 1, 
&isnull)); //Value col2
+
+    new_plan = SPI_prepare(query, nargs, argtypes);
+    if (new_plan == NULL)
+      elog(ERROR, "SPI_prepare failed ! \n");
+
+    prepared_plan = SPI_saveplan(new_plan);
+    if (prepared_plan == NULL)
+      elog(ERROR, "SPI_saveplan failed ! \n");
+  }
+
+
+  ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0);
+
+  if (ret != SPI_OK_SELECT) {
+    elog(ERROR, "SPI_execute_plan failed: %d \n", ret);
+    }
+
+  proc = SPI_processed;
+
+  if (proc > 0) {
+    SPITupleTable *tuptable = SPI_tuptable;
+    TupleDesc tupdesc = tuptable->tupdesc;
+    HeapTuple tuple;
+    int i;
+
+    for (i = 0; i < proc; i++) {
+      tuple = tuptable->vals[i];
+      for (int j = 1; j <= tupdesc->natts; j++) {
+        char * value = SPI_getvalue(tuple, tupdesc, j);
+        result += atoi(value);
+      }
+    }
+    }
+  SPI_finish();
+  PG_RETURN_INT64(result);
+}
+*/
+
+Datum pg_spi_prepare_select_with_cond_without_saveplan(PG_FUNCTION_ARGS) {
+
+  SPIPlanPtr new_plan;
+  int ret;
+  Datum values[1];
+  uint64 proc;
+  int nargs;
+  Oid argtypes[1];
+  char *query = "SELECT col1 FROM joseph_test.Y WHERE col2 = $1";
+  int result = 0;
+
+  ret = SPI_connect();
+  if (ret != SPI_OK_CONNECT)
+    elog(ERROR, "SPI_connect failed ! \n");
+
+  {
+
+    argtypes[0] = INT4OID;
+    nargs = 1;
+    values[0] = Int32GetDatum(2); //Value col2
+
+    new_plan = SPI_prepare(query, nargs, argtypes);
+    if (new_plan == NULL)
+      elog(ERROR, "SPI_prepare failed ! \n");
+
+  }
+
+
+  ret = SPI_execute_plan(new_plan, values, NULL, false, 0);
+
+  if (ret != SPI_OK_SELECT) {
+    elog(ERROR, "SPI_execute_plan failed: %d \n", ret);
+    }
+
+  proc = SPI_processed;
+
+  if (proc > 0) {
+    SPITupleTable *tuptable = SPI_tuptable;
+    TupleDesc tupdesc = tuptable->tupdesc;
+    HeapTuple tuple;
+    int i;
+
+    for (i = 0; i < proc; i++) {
+      tuple = tuptable->vals[i];
+      for (int j = 1; j <= tupdesc->natts; j++) {
+        char * value = SPI_getvalue(tuple, tupdesc, j);
+        result += atoi(value);
+      }
+    }
+  }
+  SPI_finish();
+  PG_RETURN_INT64(result);
+}
+
+
+
+
+Datum
+pg_spi_update_y(PG_FUNCTION_ARGS)
+{
+  int ret;
+  int nargs;
+  Oid argtypes[1];
+  Datum values[1];
+  char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)";
+
+  ret = SPI_connect();
+  if (ret != SPI_OK_CONNECT)
+  {
+    elog(ERROR, "SPI_connect failed ! \n");
+  }
+
+  nargs = 1;
+  argtypes[0] = INT4OID;
+  values[0] = Int32GetDatum(0);
+
+  ret = SPI_execute_with_args(query, nargs, argtypes, values, NULL, false, 0);
+  if (ret != SPI_OK_UPDATE)
+  {
+    elog(ERROR, "SPI_execute_with_args failed ! \n");
+  }
+
+  SPI_finish();
+
+  PG_RETURN_VOID();
+}
+
+
+
+
+
+
+Datum
+pg_spi_prepare_update(PG_FUNCTION_ARGS)
+{
+  static SPIPlanPtr prepared_plan = NULL;
+  SPIPlanPtr new_plan;
+  int ret;
+  int nargs;
+  Oid argtypes[1];
+  Datum values[1];
+  char *query = "UPDATE joseph_test.Y SET col1 = 4 WHERE (col2 = $1)";
+
+  ret = SPI_connect();
+  if (ret != SPI_OK_CONNECT)
+  {
+    elog(ERROR, "SPI_connect failed ! \n");
+  }
+
+  if ( prepared_plan == NULL)
+  {
+    argtypes[0] = INT4OID;
+    nargs = 1;
+    values[0] = Int32GetDatum(3);
+    //PREPARE
+    new_plan = SPI_prepare(query, nargs, argtypes);
+    if (new_plan == NULL)
+      elog(ERROR, "SPI_prepare failed ! \n");
+    //SAVEPLAN
+    prepared_plan = SPI_saveplan(new_plan);
+    if(prepared_plan == NULL)
+      elog(ERROR, "SPI_saveplan failed ! \n");
+  }
+  ret = SPI_execute_plan(prepared_plan, values, NULL, false, 0);
+  if (ret != SPI_OK_UPDATE)
+    elog(ERROR, "SPI_execute_plan failed ! \n");
+
+  SPI_finish();
+  PG_RETURN_VOID();
+}
+/*
+Datum
+pg_spi_prepare_update_without_saveplan(PG_FUNCTION_ARGS)
+{}*/
+void _PG_fini(void)
+{
+}
+
+/*
+
+*/
+
+
+
+
+Datum
+pg_spi_get_dep_ref_fees (PG_FUNCTION_ARGS) {
+  /* Define plan to save */
+  static SPIPlanPtr deposit_plan;
+  static SPIPlanPtr ref_plan;
+  static SPIPlanPtr fees_plan;
+  static SPIPlanPtr dummy_plan;
+  /* Define variables to update */
+  Timestamp refund_deadline = PG_GETARG_TIMESTAMP(0);
+  bytea *merchant_pub = PG_GETARG_BYTEA_P(1);
+  bytea *wire_target_h_payto = PG_GETARG_BYTEA_P(2);
+  bytea *wtid_raw = PG_GETARG_BYTEA_P(3);
+  bool is_null;
+  /* Define variables to store the results of each SPI query */
+  uint64_t sum_deposit_val  = 0;
+  uint32_t sum_deposit_frac = 0;
+  uint64_t s_refund_val     = 0;
+  uint32_t s_refund_frac    = 0;
+  uint64_t sum_dep_fee_val  = 0;
+  uint32_t sum_dep_fee_frac = 0;
+  uint64_t norm_refund_val  = 0;
+  uint32_t norm_refund_frac = 0;
+  uint64_t sum_refund_val   = 0;
+  uint32_t sum_refund_frac  = 0;
+  /* Define variables to store the Tuptable */
+  SPITupleTable *dep_res;
+  SPITupleTable *ref_res;
+  SPITupleTable *ref_by_coin_res;
+  SPITupleTable *norm_ref_by_coin_res;
+  SPITupleTable *fully_refunded_coins_res;
+  SPITupleTable *fees_res;
+  SPITupleTable *dummys_res;
+  /* Define variable to update */
+  Datum values_refund[2];
+  Datum values_deposit[3];
+  Datum values_fees[2];
+  Datum values_dummys[2];
+  TupleDesc tupdesc;
+  /* Define variables to replace some tables */
+  bytea *ref_by_coin_coin_pub;
+  int64 ref_by_coin_deposit_serial_id = 0;
+  bytea *norm_ref_by_coin_coin_pub;
+  int64_t norm_ref_by_coin_deposit_serial_id = 0;
+  bytea *new_dep_coin_pub = NULL;
+  int res = SPI_connect();
+
+  /* Connect to SPI */
+  if (res < 0) {
+    elog(ERROR, "Could not connect to SPI manager");
+  }
+  if (deposit_plan == NULL)
+  {
+    const char *dep_sql;
+    SPIPlanPtr new_plan;
+
+    // Execute first query and store results in variables
+    dep_sql =
+      "UPDATE deposits SET done=TRUE "
+      "WHERE NOT (done OR policy_blocked) "
+      "AND refund_deadline=$1 "
+      "AND merchant_pub=$2 "
+      "AND wire_target_h_payto=$3 "
+      "RETURNING "
+      "deposit_serial_id,"
+      "coin_pub,"
+      "amount_with_fee_val,"
+      "amount_with_fee_frac;";
+    fprintf(stderr, "dep sql %d\n", 1);
+    new_plan =
+      SPI_prepare(dep_sql, 4,(Oid[]){INT8OID, BYTEAOID, BYTEAOID});
+    fprintf(stderr, "dep sql %d\n", 2);
+    if (new_plan == NULL)
+      elog(ERROR, "SPI_prepare failed for dep \n");
+    deposit_plan = SPI_saveplan(new_plan);
+    if (deposit_plan == NULL)
+      elog(ERROR, "SPI_saveplan failed for dep \n");
+  }
+  fprintf(stdout, "dep sql %d\n", 3);
+
+  values_deposit[0] = Int64GetDatum(refund_deadline);
+  values_deposit[1] = PointerGetDatum(merchant_pub);
+  values_deposit[2] = PointerGetDatum(wire_target_h_payto);
+
+  res = SPI_execute_plan (deposit_plan,
+                          values_deposit,
+                          NULL,
+                          true,
+                          0);
+  fprintf(stdout, "dep sql %d\n", 4);
+  if (res != SPI_OK_UPDATE)
+  {
+    elog(ERROR, "Failed to execute subquery 1 \n");
+  }
+  // STORE TUPTABLE deposit
+  dep_res = SPI_tuptable;
+
+  for (unsigned int i = 0; i < SPI_processed; i++) {
+    int64 dep_deposit_serial_ids = 
DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, 
&is_null));
+    bytea *dep_coin_pub = DatumGetByteaP(SPI_getbinval(SPI_tuptable->vals[i], 
SPI_tuptable->tupdesc, 2, &is_null));
+    int64 dep_amount_val = DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[i], 
SPI_tuptable->tupdesc, 3, &is_null));
+    int32 dep_amount_frac = DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[i], 
SPI_tuptable->tupdesc, 4, &is_null));
+
+    if (is_null)
+      elog(ERROR, "Failed to retrive data from deposit \n");
+    if (ref_plan == NULL)
+    {
+      // Execute second query with parameters from first query and store 
results in variables
+      const char * ref_sql =
+        "SELECT amount_with_fee_val, amount_with_fee_frac, coin_pub, 
deposit_serial_id "
+        "FROM refunds "
+        "WHERE coin_pub=$1 "
+        "AND deposit_serial_id=$2;";
+      SPIPlanPtr new_plan = SPI_prepare(ref_sql, 3, (Oid[]){BYTEAOID, 
INT8OID});
+      if (new_plan == NULL)
+        elog(ERROR, "SPI_prepare failed for refund\n");
+      ref_plan = SPI_saveplan(new_plan);
+      if (ref_plan == NULL)
+        elog(ERROR, "SPI_saveplan failed for refund\n");
+    }
+    values_refund[0] = PointerGetDatum(dep_coin_pub);
+    values_refund[1] = Int64GetDatum(dep_deposit_serial_ids);
+    res = SPI_execute_plan(ref_plan,
+                           values_refund,
+                           NULL,
+                           false,
+                           0);
+    if (res != SPI_OK_SELECT)
+      elog(ERROR, "Failed to execute subquery 2\n");
+    // STORE TUPTABLE refund
+    ref_res = SPI_tuptable;
+    for (unsigned int j = 0; j < SPI_processed; j++) {
+      int64 ref_refund_val = 
DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 1, 
&is_null));
+      int32 ref_refund_frac = 
DatumGetInt32(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 2, 
&is_null));
+      bytea *ref_coin_pub = 
DatumGetByteaP(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 3, 
&is_null));
+      int64 ref_deposit_serial_id = 
DatumGetInt64(SPI_getbinval(SPI_tuptable->vals[j], SPI_tuptable->tupdesc, 4, 
&is_null));
+      // Execute third query with parameters from second query and store 
results in variables
+      ref_by_coin_coin_pub = ref_coin_pub;
+      ref_by_coin_deposit_serial_id = ref_deposit_serial_id;
+      // LOOP TO GET THE SUM FROM REFUND BY COIN
+      for (unsigned int i = 0; i<SPI_processed; i++)
+      {
+        if ((ref_by_coin_coin_pub ==
+             DatumGetByteaP(SPI_getbinval(SPI_tuptable->vals[i], 
SPI_tuptable->tupdesc, 1, &is_null)))
+            &&
+            (ref_by_coin_deposit_serial_id ==
+             DatumGetUInt64(SPI_getbinval(SPI_tuptable->vals[i], 
SPI_tuptable->tupdesc, 2, &is_null)))
+            )
+        {
+          sum_refund_val += ref_refund_val;
+          sum_refund_frac += ref_refund_frac;
+          norm_ref_by_coin_coin_pub = ref_by_coin_coin_pub;
+          norm_ref_by_coin_deposit_serial_id = ref_by_coin_deposit_serial_id;
+        }
+      }// END SUM CALCULATION
+      //NORMALIZE REFUND VAL FRAC
+      norm_refund_val =
+        (sum_refund_val + sum_refund_frac ) / 100000000;
+      norm_refund_frac =
+        sum_refund_frac % 100000000;
+      // Get refund values
+      s_refund_val += sum_refund_val;
+      s_refund_frac = sum_refund_frac;
+    }//END REFUND
+    if (norm_ref_by_coin_coin_pub == dep_coin_pub
+        && ref_by_coin_deposit_serial_id == dep_deposit_serial_ids
+        && norm_refund_val == dep_amount_val
+        && norm_refund_frac == dep_amount_frac)
+    {
+      new_dep_coin_pub = dep_coin_pub;
+    }
+    // Ensure we get the fee for each coin and not only once per denomination
+    if (fees_plan == NULL )
+    {
+      const char * fees_sql =
+        "SELECT "
+        "  denom.fee_deposit_val AS fee_val, "
+        "  denom.fee_deposit_frac AS fee_frac, "
+        "FROM known_coins kc"
+        "JOIN denominations denom USING (denominations_serial) "
+        "WHERE kc.coin_pub = $1 AND kc.coin_pub != $2;";
+      SPIPlanPtr new_plan = SPI_prepare(fees_sql, 3, (Oid[]){BYTEAOID, 
BYTEAOID});
+      if (new_plan == NULL)
+        {
+          elog(ERROR, "SPI_prepare for fees failed ! \n");
+        }
+      fees_plan = SPI_saveplan(new_plan);
+      if (fees_plan == NULL)
+        {
+          elog(ERROR, "SPI_saveplan for fees failed ! \n");
+        }
+    }
+    values_fees[0] = PointerGetDatum(dep_coin_pub);
+    values_fees[1] = PointerGetDatum(new_dep_coin_pub);
+    res = SPI_execute_plan(fees_plan, values_fees, NULL, false, 0);
+    if (res != SPI_OK_SELECT)
+      elog(ERROR, "SPI_execute_plan failed for fees \n");
+    fees_res = SPI_tuptable;
+    tupdesc = fees_res->tupdesc;
+    for (unsigned int i = 0; i<SPI_processed; i++)
+    {
+      HeapTuple tuple = fees_res->vals[i];
+      bool is_null;
+      uint64_t fee_val = DatumGetUInt64(SPI_getbinval(tuple, tupdesc, 1, 
&is_null));
+      uint32_t fee_frac = DatumGetUInt32(SPI_getbinval(tuple, tupdesc, 2, 
&is_null));
+      uint64_t fees_deposit_serial_id = DatumGetUInt64(SPI_getbinval(tuple, 
tupdesc, 3, &is_null));
+      if (dummy_plan == NULL)
+      {
+        const char *insert_dummy_sql =
+          "INSERT INTO "
+          "aggregation_tracking(deposit_serial_id, wtid_raw)"
+          " VALUES ($1, $2)";
+
+        SPIPlanPtr new_plan = SPI_prepare(insert_dummy_sql, 2, 
(Oid[]){INT8OID, BYTEAOID});
+        if (new_plan == NULL)
+          elog(ERROR, "FAILED to prepare aggregation tracking \n");
+        dummy_plan = SPI_saveplan(new_plan);
+        if ( dummy_plan == NULL )
+          elog(ERROR, "FAILED to saveplan aggregation tracking\n");
+      }
+      values_dummys[0] = Int64GetDatum(dep_deposit_serial_ids);
+      values_dummys[1] = PointerGetDatum(wtid_raw);
+      res = SPI_execute_plan(dummy_plan, values_dummys, NULL, false, 0);
+      if (res != SPI_OK_INSERT)
+        elog(ERROR, "Failed to insert dummy\n");
+      dummys_res = SPI_tuptable;
+      // Calculation of deposit fees for not fully refunded deposits
+      sum_dep_fee_val  += fee_val;
+      sum_dep_fee_frac += fee_frac;
+    }
+    // Get deposit values
+    sum_deposit_val += dep_amount_val;
+    sum_deposit_frac += dep_amount_frac;
+  }//END DEPOSIT
+  SPI_finish();
+  PG_RETURN_VOID();
+}
diff --git a/src/exchangedb/spi/own_test.control 
b/src/exchangedb/spi/own_test.control
new file mode 100644
index 00000000..4e73e207
--- /dev/null
+++ b/src/exchangedb/spi/own_test.control
@@ -0,0 +1,4 @@
+comment = 'Example extension for testing purposes'
+default_version = '1.0'
+module_pathname = '$libdir/own_test'
+relocatable = true
diff --git a/src/exchangedb/spi/own_test.so b/src/exchangedb/spi/own_test.so
new file mode 100755
index 00000000..09ae9959
Binary files /dev/null and b/src/exchangedb/spi/own_test.so differ
diff --git a/src/exchangedb/spi/own_test.sql b/src/exchangedb/spi/own_test.sql
new file mode 100644
index 00000000..9fe42c0a
--- /dev/null
+++ b/src/exchangedb/spi/own_test.sql
@@ -0,0 +1,216 @@
+
+DROP TABLE joseph_test.X;
+CREATE TABLE joseph_test.X (
+  a integer
+);
+
+INSERT INTO joseph_test.X (a) VALUES (1), (2), (3), (4), (5), (6), (7);
+
+DROP TABLE joseph_test.Y;
+CREATE TABLE joseph_test.Y (col1 INT, col2 INT);
+INSERT INTO joseph_test.Y (col1,col2) VALUES (1,2), (2,0), (0,4), (4,0), 
(0,6), (6,7), (7,8);
+
+DROP TABLE joseph_test.Z;
+CREATE TABLE joseph_test.Z(col1 BYTEA);
+DROP TABLE deposits;
+/*CREATE TABLE deposits(
+       deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY
+      ,shard INT8 NOT NULL
+      ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)
+      ,known_coin_id INT8 NOT NULL
+      ,amount_with_fee_val INT8 NOT NULL
+      ,amount_with_fee_frac INT4 NOT NULL
+      ,wallet_timestamp INT8 NOT NULL
+      ,exchange_timestamp INT8 NOT NULL
+      ,refund_deadline INT8 NOT NULL
+      ,wire_deadline INT8 NOT NULL
+      ,merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)
+      ,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)
+      ,coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)
+      ,wire_salt BYTEA NOT NULL CHECK (LENGTH(wire_salt)=16)
+      ,wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)
+      ,done BOOLEAN NOT NULL DEFAULT FALSE
+      ,policy_blocked BOOLEAN NOT NULL DEFAULT FALSE
+      ,policy_details_serial_id INT8);
+*/
+--INSERT INTO deposits VALUES ();
+
+
+
+CREATE TABLE deposits(
+       deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY
+      ,shard INT8 NOT NULL
+      ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)
+      ,known_coin_id INT8 NOT NULL
+      ,amount_with_fee_val INT8 NOT NULL
+      ,amount_with_fee_frac INT4 NOT NULL
+      ,wallet_timestamp INT8 NOT NULL
+      ,exchange_timestamp INT8 NOT NULL
+      ,refund_deadline INT8 NOT NULL
+      ,wire_deadline INT8 NOT NULL
+      ,merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)
+      ,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)
+      ,coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)
+      ,wire_salt BYTEA NOT NULL CHECK (LENGTH(wire_salt)=16)
+      ,wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)
+      ,done BOOLEAN NOT NULL DEFAULT FALSE
+      ,policy_blocked BOOLEAN NOT NULL DEFAULT FALSE
+      ,policy_details_serial_id INT8);
+
+
+CREATE OR REPLACE FUNCTION pg_spi_insert_int()
+  RETURNS VOID
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_insert_int';
+DROP FUNCTION pg_spi_select_from_x();
+CREATE OR REPLACE FUNCTION pg_spi_select_from_x()
+  RETURNS INT8
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_select_from_x';
+
+/*DROP FUNCTION pg_spi_select_pair_from_y();
+CREATE OR REPLACE FUNCTION pg_spi_select_pair_from_y()
+  RETURNS valuest
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_select_pair_from_y';
+*/
+/*CREATE OR REPLACE FUNCTION pg_spi_select_with_cond()
+  RETURNS INT8
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_select_with_cond';
+*/
+DROP FUNCTION pg_spi_update_y();
+CREATE OR REPLACE FUNCTION pg_spi_update_y()
+  RETURNS VOID
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_update_y';
+DROP FUNCTION pg_spi_prepare_example();
+
+CREATE OR REPLACE FUNCTION pg_spi_prepare_example()
+  RETURNS INT8
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_prepare_example';
+
+DROP FUNCTION pg_spi_prepare_example_without_saveplan();
+CREATE OR REPLACE FUNCTION pg_spi_prepare_example_without_saveplan()
+  RETURNS INT8
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_prepare_example_without_saveplan';
+
+CREATE OR REPLACE FUNCTION pg_spi_prepare_insert()
+  RETURNS VOID
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_prepare_insert';
+
+CREATE OR REPLACE FUNCTION pg_spi_prepare_insert_without_saveplan()
+  RETURNS VOID
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_prepare_insert_without_saveplan';
+
+/*DROP FUNCTION pg_spi_prepare_select_with_cond();
+CREATE OR REPLACE FUNCTION pg_spi_prepare_select_with_cond()
+  RETURNS INT8
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond';
+*/
+DROP FUNCTION pg_spi_prepare_select_with_cond_without_saveplan();
+CREATE OR REPLACE FUNCTION pg_spi_prepare_select_with_cond_without_saveplan()
+  RETURNS INT8
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_prepare_select_with_cond_without_saveplan';
+
+DROP FUNCTION pg_spi_prepare_update();
+CREATE OR REPLACE FUNCTION pg_spi_prepare_update()
+  RETURNS VOID
+  LANGUAGE c COST 100
+AS '$libdir/own_test', 'pg_spi_prepare_update';
+
+DROP FUNCTION pg_spi_get_dep_ref_fees(
+  IN in_timestamp INT8
+ ,IN merchant_pub BYTEA
+ ,IN wire_target_h_payto BYTEA
+ ,IN wtid BYTEA);
+CREATE OR REPLACE FUNCTION pg_spi_get_dep_ref_fees(
+  IN in_timestamp INT8
+ ,IN merchant_pub BYTEA
+ ,IN wire_target_h_payto BYTEA
+ ,IN wtid BYTEA
+)
+  RETURNS VOID
+  LANGUAGE c VOLATILE COST 100
+AS '$libdir/own_test', 'pg_spi_get_dep_ref_fees';
+
+CREATE OR REPLACE FUNCTION update_pg_spi_get_dep_ref_fees(
+ IN in_refund_deadline INT8,
+ IN in_merchant_pub BYTEA,
+ IN in_wire_target_h_payto BYTEA
+)
+RETURNS SETOF record
+LANGUAGE plpgsql VOLATILE
+AS $$
+DECLARE
+
+BEGIN
+RETURN QUERY
+  UPDATE deposits
+  SET done = TRUE
+  WHERE NOT (done OR policy_blocked)
+  AND refund_deadline < in_refund_deadline
+  AND merchant_pub = in_merchant_pub
+  AND wire_target_h_payto = in_wire_target_h_payto
+  RETURNING
+  deposit_serial_id,
+  coin_pub,
+  amount_with_fee_val,
+  amount_with_fee_frac;
+END $$;
+
+CREATE OR REPLACE FUNCTION stored_procedure_update(
+IN in_number INT8
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  UPDATE joseph_test.Y
+  SET col1 = 4
+  WHERE col2 = in_number;
+END $$;
+
+CREATE OR REPLACE FUNCTION stored_procedure_select(OUT out_value INT8)
+RETURNS INT8
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  SELECT 1
+    INTO out_value
+  FROM joseph_test.X;
+  RETURN;
+END $$;
+
+
+CREATE OR REPLACE FUNCTION stored_procedure_insert(
+IN in_number INT8,
+OUT out_number INT8)
+RETURNS INT8
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  INSERT INTO joseph_test.X (a)
+  VALUES (in_number)
+  RETURNING a INTO out_number;
+END $$;
+
+CREATE OR REPLACE FUNCTION stored_procedure_select_with_cond(
+IN in_number INT8,
+OUT out_number INT8
+)
+RETURNS INT8
+LANGUAGE plpgsql
+AS $$
+BEGIN
+ SELECT col1 INTO out_number
+ FROM joseph_test.Y
+ WHERE col2 = in_number;
+ RETURN;
+END $$;
diff --git a/contrib/sigp/h.header b/src/exchangedb/spi/perf_own_test.c
similarity index 57%
copy from contrib/sigp/h.header
copy to src/exchangedb/spi/perf_own_test.c
index 6ed22a63..92be2235 100644
--- a/contrib/sigp/h.header
+++ b/src/exchangedb/spi/perf_own_test.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,18 +14,12 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file taler_signatures.h
- * @brief message formats and signature constants used to define
- *        the binary formats of signatures in Taler
- * @author Florian Dold
- * @author Benedikt Mueller
- *
- * This file should define the constants and C structs that one needs
- * to know to implement Taler clients (wallets or merchants or
- * auditor) that need to produce or verify Taler signatures.
+ * @file exchangedb/spi/perf_own_test.c
+ * @brief benchmark for 'own_test'
+ * @author Joseph Xu
  */
-#ifndef TALER_SIGNATURES_H
-#define TALER_SIGNATURES_H
-
-
-
+#include "exchangedb/platform.h"
+#include "exchangedb/taler_exchangedb_lib.h"
+#include "exchangedb/taler_json_lib.h"
+#include "exchangedb/taler_exchangedb_plugin.h"
+#include "own_test.sql"
diff --git a/src/exchangedb/spi/pg_aggregate.c 
b/src/exchangedb/spi/pg_aggregate.c
new file mode 100644
index 00000000..262100ce
--- /dev/null
+++ b/src/exchangedb/spi/pg_aggregate.c
@@ -0,0 +1,389 @@
+#include "postgres.h"
+#include "fmgr.h"
+#include "utils/numeric.h"
+#include "utils/builtins.h"
+#include "executor/spi.h"
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(get_deposit_summary);
+
+Datum get_deposit_summary(PG_FUNCTION_ARGS)
+{
+
+  static SPIPlanPtr deposit_plan;
+  static SPIPlanPtr refund_plan;
+  static SPIPlanPtr refund_by_coin_plan;
+  static SPIPlanPtr norm_refund_by_coin_plan;
+  static SPIPlanPtr fully_refunded_by_coins_plan;
+  static SPIPlanPtr fees_plan;
+
+  int shard = PG_GETARG_INT32(0);
+  char * sql;
+  char *merchant_pub = text_to_cstring(PG_GETARG_TEXT_P(1));
+  char *wire_target_h_payto = text_to_cstring(PG_GETARG_TEXT_P(2));
+  char *wtid_raw = text_to_cstring(PG_GETARG_TEXT_P(3));
+  int refund_deadline = PG_GETARG_INT32(4);
+  int conn = SPI_connect();
+  if (conn != SPI_OK_CONNECT)
+  {
+    elog(ERROR, "DB connexion failed ! \n");
+  }
+
+  if ( deposit_plan == NULL
+       || refund_plan == NULL
+       || refund_by_coin_plan == NULL
+       || norm_refund_by_coin_plan = NULL
+       || fully_refunded_coins_plan = NULL
+       || fees_plan == NULL )
+  {
+    if (deposit_plan == NULL)
+    {
+      int nargs = 3;
+      Oid argtypes[3];
+      argtypes[0] = INT8OID;
+      argtypes[1] = BYTEAOID;
+      argtypes[2] = BYTEAOID;
+      const char *dep_sql =
+        "    UPDATE deposits"
+        "    SET done=TRUE"
+        "    WHERE NOT (done OR policy_blocked)"
+        "        AND refund_deadline < $1"
+        "        AND merchant_pub = $2"
+        "        AND wire_target_h_payto = $3"
+        "    RETURNING"
+        "        deposit_serial_id"
+        "        ,coin_pub"
+        "        ,amount_with_fee_val AS amount_val"
+        "        ,amount_with_fee_frac AS amount_frac";
+      SPIPlanPtr new_plan =
+        SPI_prepare(dep_sql, 4, argtypes});
+      if (new_plan == NULL)
+      {
+        elog(ERROR, "SPI_prepare for deposit failed ! \n");
+      }
+      deposit_plan = SPI_saveplan(new_plan);
+      if (deposit_plan == NULL)
+      {
+        elog(ERROR, "SPI_saveplan for deposit failed ! \n");
+      }
+    }
+
+    Datum values[4];
+    values[0] = Int64GetDatum(refund_deadline);
+    values[1] = CStringGetDatum(merchant_pub);
+    values[2] = CStringGetDatum(wire_target_h_payto);
+    int ret = SPI_execute_plan (deposit_plan,
+                                values,
+                                NULL,
+                                true,
+                                0);
+    if (ret != SPI_OK_UPDATE)
+    {
+        elog(ERROR, "Failed to execute subquery 1\n");
+    }
+    uint64_t *dep_deposit_serial_ids = palloc(sizeof(uint64_t) * 
SPI_processed);
+    BYTEA **dep_coin_pubs = palloc(sizeof(BYTEA *) * SPI_processed);
+    uint64_t *dep_amount_vals = palloc(sizeof(uint64_t) * SPI_processed);
+    uint32_t *dep_amount_fracs = palloc(sizeof(uint32_t) * SPI_processed);
+    for (unsigned int i = 0; i < SPI_processed; i++) {
+      HeapTuple tuple = SPI_tuptable->vals[i];
+      dep_deposit_serial_ids[i] =
+        DatumGetInt64(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 1, &ret));
+      dep_coin_pubs[i] =
+        DatumGetByteaP(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 2, &ret));
+      dep_amount_vals[i] =
+        DatumGetInt64(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 3, &ret));
+      dep_amount_fracs[i] =
+        DatumGetInt32(SPI_getbinval(tuple, SPI_tuptable->tupdesc, 4, &ret));
+    }
+
+
+    if (refund_plan == NULL)
+    {
+      const char *ref_sql =
+        "ref AS ("
+        "  SELECT"
+        "    amount_with_fee_val AS refund_val"
+        "   ,amount_with_fee_frac AS refund_frac"
+        "   ,coin_pub"
+        "   ,deposit_serial_id"
+        "    FROM refunds"
+        "   WHERE coin_pub IN (SELECT coin_pub FROM dep)"
+        "     AND deposit_serial_id IN (SELECT deposit_serial_id FROM dep)) ";
+      SPIPlanPtr new_plan = SPI_prepare(ref_sql, 0, NULL);
+      if (new_plan == NULL)
+        elog (ERROR, "SPI_prepare for refund failed ! \n");
+      refund_plan = SPI_saveplan(new_plan);
+      if (refund_plan == NULL)
+      {
+        elog(ERROR, "SPI_saveplan for refund failed ! \n");
+      }
+    }
+
+    int64t_t *ref_deposit_serial_ids = palloc(sizeof(int64_t) * SPI_processed);
+
+    int res = SPI_execute_plan (refund_plan, NULL, NULL, false, 0);
+    if (res != SPI_OK_SELECT)
+    {
+      elog(ERROR, "Failed to execute subquery 2\n");
+    }
+    SPITupleTable *tuptable = SPI_tuptable;
+    TupleDesc tupdesc = tuptable->tupdesc;
+    for (unsigned int i = 0; i < SPI_processed; i++)
+    {
+      HeapTuple tuple = tuptable->vals[i];
+      Datum refund_val = SPI_getbinval(tuple, tupdesc, 1, &refund_val_isnull);
+      Datum refund_frac = SPI_getbinval(tuple, tupdesc, 2, 
&refund_frac_isnull);
+      Datum coin_pub = SPI_getbinval(tuple, tupdesc, 3, &coin_pub_isnull);
+      Datum deposit_serial_id = SPI_getbinval(tuple, tupdesc, 4, 
&deposit_serial_id_isnull);
+      if (refund_val_isnull
+          || refund_frac_isnull
+          || coin_pub_isnull
+          || deposit_serial_id_isnull )
+      {
+        elog(ERROR, "Failed to retrieve data from subquery 2");
+      }
+      uint64_t refund_val_int = DatumGetUInt64(refund_val);
+      uint32_t refund_frac_int = DatumGetUInt32(refund_frac);
+      BYTEA coin_pub = DatumGetByteaP(coin_pub);
+      ref_deposit_serial_ids = DatumGetInt64(deposit_serial_id);
+
+      refund *new_refund = (refund*) palloc(sizeof(refund));
+      new_refund->coin_pub = coin_pub_str;
+      new_refund->deposit_serial_id = deposit_serial_id_int;
+      new_refund->amount_with_fee_val = refund_val_int;
+      new_refund->amount_with_fee_frac = refund_frac_int;
+    }
+
+
+    if (refund_by_coin_plan == NULL)
+    {
+      const char *ref_by_coin_sql =
+        "ref_by_coin AS ("
+        "  SELECT"
+        "    SUM(refund_val) AS sum_refund_val"
+        "   ,SUM(refund_frac) AS sum_refund_frac"
+        "   ,coin_pub"
+        "   ,deposit_serial_id"
+        "    FROM ref"
+        "   GROUP BY coin_pub, deposit_serial_id) ";
+      SPIPlanPtr new_plan = SPI_prepare (ref_by_coin_sql, 0, NULL);
+      if (new_plan == NULL)
+        elog(ERROR, "SPI_prepare for refund by coin failed ! \n");
+      refund_by_coin_plan = SPI_saveplan (new_plan);
+      if (refund_by_coin_plan == NULL)
+        elog(ERROR, "SPI_saveplan for refund failed");
+    }
+
+
+    int res = SPI_execute_plan (refund_by_coin_plan, NULL, NULL, false, 0);
+    if (res != SPI_OK_SELECT)
+    {
+      elog(ERROR, "Failed to execute subquery 2\n");
+    }
+
+    SPITupleTable *tuptable = SPI_tuptable;
+    TupleDesc tupdesc = tuptable->tupdesc;
+    for (unsigned int i = 0; i < SPI_processed; i++)
+    {
+      HeapTuple tuple = tuptable->vals[i];
+      Datum sum_refund_val = SPI_getbinval(tuple, tupdesc, 1, 
&refund_val_isnull);
+      Datum sum_refund_frac = SPI_getbinval(tuple, tupdesc, 2, 
&refund_frac_isnull);
+      Datum coin_pub = SPI_getbinval(tuple, tupdesc, 3, &coin_pub_isnull);
+      Datum deposit_serial_id_int = SPI_getbinval(tuple, tupdesc, 4, 
&deposit_serial_id_isnull);
+      if (refund_val_isnull
+          || refund_frac_isnull
+          || coin_pub_isnull
+          || deposit_serial_id_isnull )
+      {
+        elog(ERROR, "Failed to retrieve data from subquery 2");
+      }
+      uint64_t s_refund_val_int = DatumGetUInt64(sum_refund_val);
+      uint32_t s_refund_frac_int = DatumGetUInt32(sum_refund_frac);
+      BYTEA coin_pub = DatumGetByteaP(coin_pub);
+      uint64_t deposit_serial_id_int = DatumGetInt64(deposit_serial_id_int);
+      refund *new_refund_by_coin = (refund*) palloc(sizeof(refund));
+      new_refund_by_coin->coin_pub = coin_pub;
+      new_refund_by_coin->deposit_serial_id = deposit_serial_id_int;
+      new_refund_by_coin->refund_amount_with_fee_val = s_refund_val_int;
+      new_refund_by_coin->refund_amount_with_fee_frac = s_refund_frac_int;
+    }
+
+
+    if (norm_refund_by_coin_plan == NULL)
+    {
+      const char *norm_ref_by_coin_sql =
+        "norm_ref_by_coin AS ("
+        "  SELECT"
+        "   coin_pub"
+        "   ,deposit_serial_id"
+        "    FROM ref_by_coin) ";
+      SPIPlanPtr new_plan = SPI_prepare (norm_ref_by_coin_sql, 0, NULL);
+      if (new_plan == NULL)
+        elog(ERROR, "SPI_prepare for norm refund by coin failed ! \n");
+      norm_refund_by_coin_plan = SPI_saveplan(new_plan);
+      if (norm_refund_by_coin_plan == NULL)
+        elog(ERROR, "SPI_saveplan for norm refund by coin failed ! \n");
+    }
+
+    double norm_refund_val =
+      ((double)new_refund_by_coin->refund_amount_with_fee_val
+       + (double)new_refund_by_coin->refund_amount_with_fee_frac) / 100000000;
+    double norm_refund_frac =
+      (double)new_refund_by_coin->refund_amount_with_fee_frac % 100000000;
+
+    if (fully_refunded_coins_plan == NULL)
+    {
+      const char *fully_refunded_coins_sql =
+        "fully_refunded_coins AS ("
+        "  SELECT"
+        "    dep.coin_pub"
+        "    FROM norm_ref_by_coin norm"
+        "    JOIN dep"
+        "      ON (norm.coin_pub = dep.coin_pub"
+        "      AND norm.deposit_serial_id = dep.deposit_serial_id"
+        "      AND norm.norm_refund_val = dep.amount_val"
+        "      AND norm.norm_refund_frac = dep.amount_frac)) ";
+      SPIPlanPtr new_plan =
+        SPI_prepare(fully_refunded_coins_sql, 0, NULL);
+      if (new_plan == NULL)
+        elog (ERROR, "SPI_prepare for fully refunded coins failed ! \n");
+      fully_refunded_coins_plan = SPI_saveplan(new_plan);
+      if (fully_refunded_coins_plan == NULL)
+        elog (ERROR, "SPI_saveplan for fully refunded coins failed ! \n");
+    }
+
+    int res = SPI_execute_plan(fully_refunded_coins_sql);
+    if ( res != SPI_OK_SELECT)
+      elog(ERROR, "Failed to execute subquery 4\n");
+    SPITupleTable * tuptable = SPI_tuptable;
+    TupleDesc tupdesc = tuptable->tupdesc;
+
+    BYTEA coin_pub = SPI_getbinval(tuple, tupdesc, 1, &coin_pub_isnull);
+    if (fees_plan == NULL)
+    {
+      const char *fees_sql =
+        "SELECT "
+        "  denom.fee_deposit_val AS fee_val, "
+        "  denom.fee_deposit_frac AS fee_frac, "
+        "  cs.deposit_serial_id "
+        "FROM dep cs "
+        "JOIN known_coins kc USING (coin_pub) "
+        "JOIN denominations denom USING (denominations_serial) "
+        "WHERE coin_pub NOT IN (SELECT coin_pub FROM fully_refunded_coins)";
+      SPIPlanPtr new_plan =
+        SPI_prepare(fees_sql, 0, NULL);
+      if (new_plan == NULL)
+      {
+        elog(ERROR, "SPI_prepare for fees failed ! \n");
+      }
+      fees_plan = SPI_saveplan(new_plan);
+      if (fees_plan == NULL)
+      {
+        elog(ERROR, "SPI_saveplan for fees failed ! \n");
+      }
+    }
+  }
+  int fees_ntuples;
+  SPI_execute(fees_sql, true, 0);
+  if (SPI_result_code() != SPI_OK_SELECT)
+  {
+    ereport(
+            ERROR,
+            (errcode(ERRCODE_INTERNAL_ERROR),
+             errmsg("deposit fee query failed: error code %d \n", 
SPI_result_code())));
+  }
+  fees_ntuples = SPI_processed;
+
+  if (fees_ntuples > 0)
+  {
+    for (i = 0; i < fees_ntuples; i++)
+    {
+      Datum fee_val_datum =
+        SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, 
&fee_null);
+      Datum fee_frac_datum =
+        SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, 
&fee_null);
+      Datum deposit_id_datum =
+        SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 3, 
&deposit_null);
+      if (!fee_null && !deposit_null)
+      {
+        int64 fee_val = DatumGetInt64(fee_val_datum);
+        int32 fee_frac = DatumGetInt32(fee_frac_datum);
+        int64 deposit_id = DatumGetInt64(deposit_id_datum);
+        sum_fee_value += fee_val;
+        sum_fee_fraction += fee_frac;
+        char *insert_agg_sql =
+          psprintf(
+                   "INSERT INTO "
+                   "aggregation_tracking(deposit_serial_id, wtid_raw)"
+                   " VALUES (%lld, '%s')",
+                   deposit_id, wtid_raw);
+        SPI_execute(insert_agg_sql, false, 0);
+      }
+    }
+  }
+
+  TupleDesc tupdesc;
+  SPITupleTable *tuptable = SPI_tuptable;
+  HeapTuple tuple;
+  Datum result;
+
+  if (tuptable == NULL || SPI_processed != 1)
+  {
+    ereport(
+            ERROR,
+            (errcode(ERRCODE_INTERNAL_ERROR),
+             errmsg("Unexpected result \n")));
+  }
+  tupdesc = SPI_tuptable->tupdesc;
+  tuple = SPI_tuptable->vals[0];
+  result = HeapTupleGetDatum(tuple);
+
+  TupleDesc result_desc = CreateTemplateTupleDesc(6, false);
+  TupleDescInitEntry(result_desc, (AttrNumber) 1, "sum_deposit_value", 
INT8OID, -1, 0);
+  TupleDescInitEntry(result_desc, (AttrNumber) 2, "sum_deposit_fraction", 
INT4OID, -1, 0);
+  TupleDescInitEntry(result_desc, (AttrNumber) 3, "sum_refund_value", INT8OID, 
-1, 0);
+  TupleDescInitEntry(result_desc, (AttrNumber) 4, "sum_refund_fraction", 
INT4OID, -1, 0);
+  TupleDescInitEntry(result_desc, (AttrNumber) 5, "sum_fee_value", INT8OID, 
-1, 0);
+  TupleDescInitEntry(result_desc, (AttrNumber) 6, "sum_fee_fraction", INT4OID, 
-1, 0);
+
+  int ret = SPI_prepare(sql, 4, argtypes);
+  if (ret != SPI_OK_PREPARE)
+  {
+    elog(ERROR, "Failed to prepare statement: %s \n", sql);
+  }
+
+  ret = SPI_execute_plan(plan, args, nulls, true, 0);
+  if (ret != SPI_OK_SELECT)
+  {
+    elog(ERROR, "Failed to execute statement: %s \n", sql);
+  }
+
+  if (SPI_processed > 0)
+  {
+    HeapTuple tuple;
+    Datum values[6];
+    bool nulls[6] = {false};
+    values[0] =
+      SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, 
&nulls[0]);
+    values[1] =
+      SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2, 
&nulls[1]);
+    values[2] =
+      SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 3, 
&nulls[2]);
+    values[3] =
+      SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 4, 
&nulls[3]);
+    values[4] =
+      SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 5, 
&nulls[4]);
+    values[5] =
+      SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 6, 
&nulls[5]);
+    tuple = heap_form_tuple(result_desc, values, nulls);
+    PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
+  }
+  SPI_finish();
+
+  PG_RETURN_NULL();
+}
+
+
+

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