gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated (07cb6ac2 -> 0f5fc95e)


From: gnunet
Subject: [taler-exchange] branch master updated (07cb6ac2 -> 0f5fc95e)
Date: Wed, 17 Nov 2021 12:24:08 +0100

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

grothoff pushed a change to branch master
in repository exchange.

 discard 07cb6ac2 crypto worker prototype
 discard ccad3328 improve logging, fix one wrong assertion, improve EC
 discard 3c8420a1 -try to optimize query
 discard c4306281 -fix synced flag on reconnect due to error
 discard 0fc621f1 add missing index
 discard b338ce6f add Access-Control-Expose-Headers to all responses, not just 
preflight
 discard 21370752 -need primary key; make sure to propagate to protocolv9
 discard ac79126f log nice message instead of crashing
     new dbb81241 database change -- breaks everything
     new 55632b1f brutally fixing types in src/include/, creating plenty of 
FTBFS issues
     new fc371ea1 start to work on transformation
     new 42bdb5aa -fixing more FTBFS
     new 17cf64df fix remaining libtalerutil FTBFS issues
     new 43223899 add missing file
     new 57c334fb fix remaining libtalerutil tests FTBFS issues
     new 868a4ce7 -resovling more FTBFS issues
     new 4d010241 work on FTBFS issues...
     new d4e03b12 -more changes towards fixing FTBFS
     new 464c1f80 -more changes towards fixing FTBFS
     new ec3d5a76 -more changes towards fixing FTBFS
     new 3af7bc0a -more FTBFS fixes
     new 091f1062 -fixing FTBFS
     new ab0b74f8 -fix aggregator ftbfs
     new 4b508a67 -fix more FTBFS issues
     new 201d6ea5 -fix more FTBFS issues
     new 58ea0416 -fix misc FTBFS
     new f7d08e8c -work on FTBFS;
     new f0951d34 -fix more FTBFS
     new 74234f75 -work on FTBFS
     new b6be9dc0 -work on FTBFS
     new 8a6d9da5 -work on FTBFS
     new fd615f3e -fix exchange FTBFS
     new f1237f19 -work on fTBFS
     new 7ac57acb fix auditor FTBFS
     new 3900531e eliminate HKDF when hashing paytos
     new b148a5a8 rename fest
     new 77142acb fix lib/ FTBFS
     new 4bfa68ef -fix warning
     new 3f630eaf the big macrofication of the traits
     new b449c735 work on testing ftbfs
     new 382fb837 -work on testing FTBFS
     new 0996b83a libtalertesting compiles
     new 5d0c6fa2 -FTBFS fix
     new fbb58ad8 fix rest of FTBFS issues in exchange
     new 16fe40a0 -fix test warnings
     new efd4e19b fix FTBFS of exchangedb
     new aa999277 fix FTBFS of auditordb
     new 07ea1c98 -fix testing FTBFS
     new fef26ec5 -fixes
     new 0a3731f4 add another amount trait
     new 9968a34a address most FIXMEs in pg plugin
     new ab304224 address most FIXMEs in pg plugin
     new 08b23fb7 fix SQL
     new 22e7dabe sql fixes
     new 55ea7fcb SQL fixes
     new 963a06c0 fix more FTBFS issues
     new d83a6532 -more work on FTBFS issues
     new bc57abc3 -more dB work
     new 2faf102a -more dB work
     new 41bfdb45 -fix FTBFS issues
     new b5e9523f fix test FTBFS
     new 43ee9da0 misc fixes
     new 35e35066 fixing SQL statements
     new 1d5edc68 SQL fixes
     new de8e0907 DB test passes again
     new 3eae999e distinguish between blind and non-blind denomination 
signatures
     new b1197c16 -fix tests
     new 783d07b4 consistently distinguish blinded/unblinded denomination sigs
     new b3606d00 -fix
     new d68dc69b -disable tests
     new f02b5b78 fix bug
     new c231e992 fix bug
     new b88b36ec style fixes
     new 5b3a468d -bugfix
     new 22ce5bff fix sharding
     new 8df5fba5 -code cleanup
     new 9358b886 bugfix!
     new 1408e158 introduce invalid key type
     new 766922f7 implement missing SQL statement
     new 32da809f abstract denomination keys a bit more
     new c787e28e more denom key refactoring
     new 9668e2e4 fix typo
     new 2549fb6d more RSA abstraction work
     new ebbc250f -brks
     new ba627bf8 -fixes
     new eaf9d728 more crypto refactoring
     new c3e24432 more crypto refactoring
     new f01ab790 RSA-despecialization
     new 938e2ce3 more RSA cleanup
     new 8175fdfa introduce TALER_wallet_deposit_verify
     new 0b370a68 add extension hashing
     new 57acad48 move extension options to external table
     new 9d6e1040 include h_extensions in deposit confirmation
     new bae7ddbf sql fix
     new 5b328363 SQL fix
     new 59a017db SQL fix
     new 81f9b2c9 -misc fixes
     new e8943b01 sql fix
     new fadfc735 -fix wire_deadline SQL
     new cd8d4bed add missing file
     new 4fff4895 prepare for KYC tests
     new 121bfe36 implement /kyc-proof client API
     new 659cd443 expose KYC traits for withdraw/get deposits commands
     new 4cde9e39 add kyc-wallet test command
     new f374a5cd add wallet for KYC status check
     new 98c30bee fix payto:// construction routine and move it to libtalerutil
     new 6ffb32aa add required payto URI traits
     new 6000339f fix comments
     new 6a611e39 add /kyc-proof cmd
     new 38c71808 add oauth service faker
     new 051deacb comment
     new 398ef9d9 implement OAuth 2.0 service
     new d9690fb0 add KYC test skeleton
     new b7f0d636 -fix NPE
     new e7d3d9a7 skip
     new a79cc160 sleep to get tests to pass
     new a9b2140b get first KYC test to pass
     new 016551db misc TODOs for KYC left
     new 77bab625 -fixes for test
     new 7c510388 age restriction progress 2/n
     new c97979d0 age restriction (load per denomination). 3/n
     new ee687c87 -better types
     new c67df636 -preparations for long polling support
     new 0325a796 avoid duplication
     new e5ead880 complete oauth logic (in theory)
     new 4b7ee484 -new option
     new 930e31e0 add CLIENT_DIR to make test_crypto pass
     new 591cefd3 [age restriction] progress 3/n
     new 91628260 fix warning
     new 0703ba87 readme
     new add9edbf -fix rval
     new 422b0ffd fix oauth_username issue
     new ed1db63a fix DB query and error handling
     new 7332403b -bump version
     new 6b8c7578 towards merging with master
     new b7a35e0d towards merging with master
     new 16a8b2f6 towards merging with master
     new 0f5fc95e towards merging with master

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (07cb6ac2)
            \
             N -- N -- N   refs/heads/master (0f5fc95e)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 130 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:
 Makefile.am                                        |    3 +-
 README.1st                                         |   19 +
 contrib/gana                                       |    2 +-
 src/auditor/Makefile.am                            |    3 +-
 src/auditor/report-lib.c                           |   20 +-
 src/auditor/report-lib.h                           |    4 +-
 src/auditor/taler-auditor-dbinit.c                 |    1 +
 .../taler-auditor-httpd_deposit-confirmation.c     |   48 +-
 src/auditor/taler-helper-auditor-aggregation.c     |   90 +-
 src/auditor/taler-helper-auditor-coins.c           |  187 +-
 src/auditor/taler-helper-auditor-deposits.c        |   22 +-
 src/auditor/taler-helper-auditor-reserves.c        |   11 +-
 src/auditor/taler-helper-auditor-wire.c            |  127 +-
 src/auditordb/auditor-0001.sql                     |   50 +-
 src/auditordb/plugin_auditordb_postgres.c          |   25 +-
 src/auditordb/test_auditordb.c                     |   45 +-
 src/bank-lib/fakebank.c                            |   30 +-
 src/benchmark/taler-aggregator-benchmark.c         |  119 +-
 src/curl/curl.c                                    |   16 +-
 src/exchange-tools/taler-auditor-offline.c         |   22 +-
 src/exchange-tools/taler-exchange-offline.c        |   54 +-
 src/exchange/exchange.conf                         |    9 +-
 src/exchange/taler-exchange-aggregator.c           |  104 +-
 src/exchange/taler-exchange-closer.c               |   21 +-
 src/exchange/taler-exchange-httpd.c                |   33 +-
 src/exchange/taler-exchange-httpd.h                |    7 +-
 src/exchange/taler-exchange-httpd_auditors.c       |    6 +-
 src/exchange/taler-exchange-httpd_auditors.h       |    2 +-
 src/exchange/taler-exchange-httpd_deposit.c        |  140 +-
 src/exchange/taler-exchange-httpd_deposits_get.c   |    4 +-
 src/exchange/taler-exchange-httpd_keys.c           |   82 +-
 src/exchange/taler-exchange-httpd_keys.h           |   17 +-
 src/exchange/taler-exchange-httpd_kyc-check.c      |  415 +-
 src/exchange/taler-exchange-httpd_kyc-check.h      |    7 +
 src/exchange/taler-exchange-httpd_kyc-proof.c      |  345 +-
 src/exchange/taler-exchange-httpd_link.c           |    8 +-
 src/exchange/taler-exchange-httpd_management.h     |    2 +-
 ...nge-httpd_management_denominations_HDP_revoke.c |    2 +-
 .../taler-exchange-httpd_management_post_keys.c    |   14 +-
 src/exchange/taler-exchange-httpd_melt.c           |    6 +-
 src/exchange/taler-exchange-httpd_recoup.c         |   71 +-
 .../taler-exchange-httpd_refreshes_reveal.c        |   28 +-
 src/exchange/taler-exchange-httpd_refund.c         |    2 +-
 src/exchange/taler-exchange-httpd_responses.c      |   46 +-
 src/exchange/taler-exchange-httpd_responses.h      |    4 +-
 src/exchange/taler-exchange-httpd_transfers_get.c  |   87 +-
 src/exchange/taler-exchange-httpd_withdraw.c       |   52 +-
 src/exchangedb/Makefile.am                         |    2 -
 src/exchangedb/drop0001.sql                        |   22 +-
 src/exchangedb/exchange-0001.sql                   |  390 +-
 src/exchangedb/exchange-0002.sql                   |  474 --
 src/exchangedb/exchange-0003.sql                   |   78 -
 src/exchangedb/irbt_callbacks.c                    |   97 +-
 src/exchangedb/lrbt_callbacks.c                    |  319 +-
 src/exchangedb/plugin_exchangedb_common.c          |   13 +-
 src/exchangedb/plugin_exchangedb_postgres.c        | 5346 +++++++++++---------
 src/exchangedb/test-exchange-db-postgres.conf      |    2 +
 src/exchangedb/test_exchangedb.c                   |  515 +-
 src/include/taler_amount_lib.h                     |    3 +
 src/include/taler_auditor_service.h                |   10 +-
 src/include/taler_auditordb_plugin.h               |   41 +-
 src/include/taler_crypto_lib.h                     |  726 ++-
 src/include/taler_exchange_service.h               |  168 +-
 src/include/taler_exchangedb_plugin.h              |  330 +-
 .../{taler_auditordb_lib.h => taler_extensions.h}  |   38 +-
 src/include/taler_json_lib.h                       |   45 +-
 src/include/taler_pq_lib.h                         |   82 +-
 src/include/taler_signatures.h                     |  120 +-
 src/include/taler_testing_lib.h                    | 1218 +----
 src/include/taler_util.h                           |   15 +-
 src/json/json.c                                    |    4 +-
 src/json/json_helper.c                             |  292 +-
 src/json/json_pack.c                               |   88 +-
 src/json/json_wire.c                               |    2 +-
 src/json/test_json.c                               |    4 +-
 src/lib/Makefile.am                                |    1 +
 src/lib/auditor_api_deposit_confirmation.c         |  105 +-
 src/lib/auditor_api_exchanges.c                    |   15 +-
 src/lib/exchange_api_auditor_add_denomination.c    |    2 +-
 src/lib/exchange_api_common.c                      |   85 +-
 src/lib/exchange_api_deposit.c                     |  288 +-
 src/lib/exchange_api_deposits_get.c                |   27 +-
 src/lib/exchange_api_handle.c                      |   95 +-
 src/lib/exchange_api_kyc_check.c                   |    4 +-
 src/lib/exchange_api_kyc_proof.c                   |  213 +
 src/lib/exchange_api_kyc_wallet.c                  |   11 +-
 src/lib/exchange_api_link.c                        |   42 +-
 src/lib/exchange_api_management_get_keys.c         |   31 +-
 ...change_api_management_revoke_denomination_key.c |    2 +-
 src/lib/exchange_api_melt.c                        |   29 +-
 src/lib/exchange_api_recoup.c                      |   16 +-
 src/lib/exchange_api_refresh_common.c              |  628 +--
 src/lib/exchange_api_refresh_common.h              |  101 +-
 src/lib/exchange_api_refreshes_reveal.c            |   45 +-
 src/lib/exchange_api_refund.c                      |   60 +-
 src/lib/exchange_api_transfers_get.c               |    8 +-
 src/lib/exchange_api_withdraw.c                    |   18 +-
 src/lib/exchange_api_withdraw2.c                   |   10 +-
 src/mhd/mhd_responses.c                            |    1 -
 src/pq/pq_query_helper.c                           |  352 +-
 src/pq/pq_result_helper.c                          |  393 +-
 src/testing/Makefile.am                            |   49 +-
 src/testing/test_auditor_api.c                     |   49 +-
 src/testing/test_exchange_api.c                    |    7 +-
 src/testing/test_exchange_api_revocation.c         |    3 +-
 src/testing/test_kyc_api.c                         |  288 ++
 .../{test_auditor_api.conf => test_kyc_api.conf}   |   17 +
 .../testing_api_cmd_auditor_add_denom_sig.c        |   25 +-
 .../testing_api_cmd_auditor_deposit_confirmation.c |   71 +-
 src/testing/testing_api_cmd_auditor_exec_auditor.c |   11 +-
 .../testing_api_cmd_auditor_exec_auditor_dbinit.c  |    9 +-
 .../testing_api_cmd_bank_admin_add_incoming.c      |   76 +-
 src/testing/testing_api_cmd_bank_admin_check.c     |   31 +-
 src/testing/testing_api_cmd_bank_check.c           |   52 +-
 src/testing/testing_api_cmd_bank_history_credit.c  |   97 +-
 src/testing/testing_api_cmd_bank_history_debit.c   |   98 +-
 src/testing/testing_api_cmd_bank_transfer.c        |   40 +-
 src/testing/testing_api_cmd_batch.c                |   48 +-
 src/testing/testing_api_cmd_deposit.c              |  178 +-
 src/testing/testing_api_cmd_deposits_get.c         |   45 +-
 src/testing/testing_api_cmd_exec_aggregator.c      |   44 +-
 src/testing/testing_api_cmd_exec_closer.c          |   33 +-
 src/testing/testing_api_cmd_exec_transfer.c        |   12 +-
 src/testing/testing_api_cmd_exec_wirewatch.c       |   13 +-
 src/testing/testing_api_cmd_insert_deposit.c       |  134 +-
 src/testing/testing_api_cmd_kyc_check_get.c        |  252 +
 src/testing/testing_api_cmd_kyc_proof.c            |  249 +
 src/testing/testing_api_cmd_kyc_wallet_get.c       |  266 +
 src/testing/testing_api_cmd_oauth.c                |  373 ++
 src/testing/testing_api_cmd_offline_sign_fees.c    |   14 +-
 src/testing/testing_api_cmd_offline_sign_keys.c    |    5 +-
 src/testing/testing_api_cmd_recoup.c               |   29 +-
 src/testing/testing_api_cmd_refresh.c              |  199 +-
 src/testing/testing_api_cmd_refund.c               |   33 +-
 src/testing/testing_api_cmd_revoke.c               |   15 +-
 src/testing/testing_api_cmd_rewind.c               |   38 +-
 src/testing/testing_api_cmd_serialize_keys.c       |   22 +-
 src/testing/testing_api_cmd_stat.c                 |   62 +-
 src/testing/testing_api_cmd_status.c               |   27 +-
 src/testing/testing_api_cmd_transfer_get.c         |   80 +-
 src/testing/testing_api_cmd_twister_exec_client.c  |  270 +-
 src/testing/testing_api_cmd_withdraw.c             |  142 +-
 src/testing/testing_api_helpers_bank.c             |    6 +-
 src/testing/testing_api_loop.c                     |  108 +-
 src/testing/testing_api_trait_amount.c             |   76 -
 src/testing/testing_api_trait_blinding_key.c       |   77 -
 src/testing/testing_api_trait_cmd.c                |   80 -
 src/testing/testing_api_trait_coin_priv.c          |   78 -
 src/testing/testing_api_trait_contract.c           |   74 -
 src/testing/testing_api_trait_denom_pub.c          |   77 -
 src/testing/testing_api_trait_denom_sig.c          |   79 -
 src/testing/testing_api_trait_exchange_pub.c       |   77 -
 src/testing/testing_api_trait_exchange_sig.c       |   77 -
 src/testing/testing_api_trait_fresh_coin.c         |   77 -
 src/testing/testing_api_trait_json.c               |  165 -
 src/testing/testing_api_trait_merchant_key.c       |  127 -
 src/testing/testing_api_trait_number.c             |  229 -
 src/testing/testing_api_trait_process.c            |   82 -
 src/testing/testing_api_trait_reserve_history.c    |   76 -
 src/testing/testing_api_trait_reserve_priv.c       |   76 -
 src/testing/testing_api_trait_reserve_pub.c        |   78 -
 src/testing/testing_api_trait_string.c             |  231 -
 src/testing/testing_api_trait_time.c               |  120 -
 src/testing/testing_api_trait_uuid.c               |  117 -
 src/testing/testing_api_trait_wtid.c               |   76 -
 src/testing/testing_api_traits.c                   |   25 +-
 src/util/.gitignore                                |    2 +-
 src/util/Makefile.am                               |   29 +-
 src/util/auditor_signatures.c                      |    4 +-
 src/util/crypto.c                                  |  146 +-
 src/util/crypto_helper_denom.c                     |   79 +-
 src/util/crypto_helper_esign.c                     |   17 +-
 src/util/crypto_wire.c                             |   58 +-
 src/util/denom.c                                   |  511 ++
 src/util/exchange_signatures.c                     |   69 +
 src/util/extension_age_restriction.c               |   49 +
 src/util/mhd.c                                     |    2 +-
 src/util/offline_signatures.c                      |   26 +-
 src/util/payto.c                                   |   84 +-
 src/util/secmod_signatures.c                       |   10 +-
 src/util/taler-crypto-worker.c                     |   42 +-
 src/util/taler-exchange-secmod-rsa.c               |  158 +-
 src/util/taler-exchange-secmod-rsa.h               |    6 +-
 src/util/test_crypto.c                             |   37 +-
 src/util/test_helper_eddsa.conf                    |    1 +
 src/util/test_helper_rsa.c                         |  120 +-
 src/util/wallet_signatures.c                       |   99 +-
 187 files changed, 11722 insertions(+), 11059 deletions(-)
 create mode 100644 README.1st
 delete mode 100644 src/exchangedb/exchange-0002.sql
 delete mode 100644 src/exchangedb/exchange-0003.sql
 copy src/include/{taler_auditordb_lib.h => taler_extensions.h} (50%)
 create mode 100644 src/lib/exchange_api_kyc_proof.c
 create mode 100644 src/testing/test_kyc_api.c
 copy src/testing/{test_auditor_api.conf => test_kyc_api.conf} (89%)
 create mode 100644 src/testing/testing_api_cmd_kyc_check_get.c
 create mode 100644 src/testing/testing_api_cmd_kyc_proof.c
 create mode 100644 src/testing/testing_api_cmd_kyc_wallet_get.c
 create mode 100644 src/testing/testing_api_cmd_oauth.c
 delete mode 100644 src/testing/testing_api_trait_amount.c
 delete mode 100644 src/testing/testing_api_trait_blinding_key.c
 delete mode 100644 src/testing/testing_api_trait_cmd.c
 delete mode 100644 src/testing/testing_api_trait_coin_priv.c
 delete mode 100644 src/testing/testing_api_trait_contract.c
 delete mode 100644 src/testing/testing_api_trait_denom_pub.c
 delete mode 100644 src/testing/testing_api_trait_denom_sig.c
 delete mode 100644 src/testing/testing_api_trait_exchange_pub.c
 delete mode 100644 src/testing/testing_api_trait_exchange_sig.c
 delete mode 100644 src/testing/testing_api_trait_fresh_coin.c
 delete mode 100644 src/testing/testing_api_trait_json.c
 delete mode 100644 src/testing/testing_api_trait_merchant_key.c
 delete mode 100644 src/testing/testing_api_trait_number.c
 delete mode 100644 src/testing/testing_api_trait_process.c
 delete mode 100644 src/testing/testing_api_trait_reserve_history.c
 delete mode 100644 src/testing/testing_api_trait_reserve_priv.c
 delete mode 100644 src/testing/testing_api_trait_reserve_pub.c
 delete mode 100644 src/testing/testing_api_trait_string.c
 delete mode 100644 src/testing/testing_api_trait_time.c
 delete mode 100644 src/testing/testing_api_trait_uuid.c
 delete mode 100644 src/testing/testing_api_trait_wtid.c
 create mode 100644 src/util/denom.c
 create mode 100644 src/util/exchange_signatures.c
 create mode 100644 src/util/extension_age_restriction.c

diff --git a/Makefile.am b/Makefile.am
index 4530bdb2..0bfe4ee0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,4 +24,5 @@ src/include/taler_error_codes.h: 
contrib/gana/gnu-taler-error-codes/registry.rec
 
 ACLOCAL_AMFLAGS = -I m4
 EXTRA_DIST = build-aux/config.rpath   \
-  AUTHORS
+  AUTHORS \
+  README.1st
diff --git a/README.1st b/README.1st
new file mode 100644
index 00000000..e1925d7e
--- /dev/null
+++ b/README.1st
@@ -0,0 +1,19 @@
+Building Taler
+==============
+
+Contributions are welcome. Please submit bugs you find to
+https://bugs.taler.net/ or our bugs mailinglist.  Submit patches via E-Mail to
+taler@gnu.org, formatted with `git format-patch`.
+
+In order to run the unit tests by hand (instead of using "make check"),
+you need to set the environment variable "TALER_PREFIX" to the
+directory where Taler's libraries are installed.
+Before running any testcases, you must complete the installation.
+
+Quick summary:
+
+$ ./configure --prefix=$SOMEWHERE
+$ make
+$ make install
+$ export $GNUNET_PREFIX=$SOMEWHERE
+$ make check
diff --git a/contrib/gana b/contrib/gana
index 478c0bd9..597e273c 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 478c0bd987c8c1135e5691c31abaa3f4ddce6f24
+Subproject commit 597e273cc73122ba5cd0023f37b43b4f3784fe0c
diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am
index 09a0deec..b876805b 100644
--- a/src/auditor/Makefile.am
+++ b/src/auditor/Makefile.am
@@ -196,7 +196,8 @@ check_SCRIPTS = \
   test-sync.sh
 
 .NOTPARALLEL:
-TESTS = $(check_SCRIPTS)
+# Disabled for now: need working wallet first!
+# TESTS = $(check_SCRIPTS)
 
 EXTRA_DIST = \
   taler-auditor.in \
diff --git a/src/auditor/report-lib.c b/src/auditor/report-lib.c
index 4addce9e..e6468f69 100644
--- a/src/auditor/report-lib.c
+++ b/src/auditor/report-lib.c
@@ -141,7 +141,7 @@ add_denomination (
   (void) denom_pub;
   if (NULL !=
       GNUNET_CONTAINER_multihashmap_get (denominations,
-                                         &issue->denom_hash))
+                                         &issue->denom_hash.hash))
     return; /* value already known */
 #if GNUNET_EXTRA_LOGGING >= 1
   {
@@ -151,7 +151,7 @@ add_denomination (
                        &issue->value);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Tracking denomination `%s' (%s)\n",
-                GNUNET_h2s (&issue->denom_hash),
+                GNUNET_h2s (&issue->denom_hash.hash),
                 TALER_amount2s (&value));
     TALER_amount_ntoh (&value,
                        &issue->fee_withdraw);
@@ -176,7 +176,7 @@ add_denomination (
     i->master = TALER_ARL_master_pub;
     GNUNET_assert (GNUNET_OK ==
                    GNUNET_CONTAINER_multihashmap_put (denominations,
-                                                      &issue->denom_hash,
+                                                      &issue->denom_hash.hash,
                                                       i,
                                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
   }
@@ -193,7 +193,7 @@ add_denomination (
  */
 enum GNUNET_DB_QueryStatus
 TALER_ARL_get_denomination_info_by_hash (
-  const struct GNUNET_HashCode *dh,
+  const struct TALER_DenominationHash *dh,
   const struct TALER_DenominationKeyValidityPS **issue)
 {
   enum GNUNET_DB_QueryStatus qs;
@@ -215,7 +215,7 @@ TALER_ARL_get_denomination_info_by_hash (
     const struct TALER_DenominationKeyValidityPS *i;
 
     i = GNUNET_CONTAINER_multihashmap_get (denominations,
-                                           dh);
+                                           &dh->hash);
     if (NULL != i)
     {
       /* cache hit */
@@ -246,7 +246,7 @@ TALER_ARL_get_denomination_info_by_hash (
     const struct TALER_DenominationKeyValidityPS *i;
 
     i = GNUNET_CONTAINER_multihashmap_get (denominations,
-                                           dh);
+                                           &dh->hash);
     if (NULL != i)
     {
       /* cache hit */
@@ -275,14 +275,14 @@ enum GNUNET_DB_QueryStatus
 TALER_ARL_get_denomination_info (
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_DenominationKeyValidityPS **issue,
-  struct GNUNET_HashCode *dh)
+  struct TALER_DenominationHash *dh)
 {
-  struct GNUNET_HashCode hc;
+  struct TALER_DenominationHash hc;
 
   if (NULL == dh)
     dh = &hc;
-  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
-                                     dh);
+  TALER_denom_pub_hash (denom_pub,
+                        dh);
   return TALER_ARL_get_denomination_info_by_hash (dh,
                                                   issue);
 }
diff --git a/src/auditor/report-lib.h b/src/auditor/report-lib.h
index 7c01b168..3f448976 100644
--- a/src/auditor/report-lib.h
+++ b/src/auditor/report-lib.h
@@ -101,7 +101,7 @@ TALER_ARL_report (json_t *array,
  */
 enum GNUNET_DB_QueryStatus
 TALER_ARL_get_denomination_info_by_hash (
-  const struct GNUNET_HashCode *dh,
+  const struct TALER_DenominationHash *dh,
   const struct TALER_DenominationKeyValidityPS **issue);
 
 
@@ -118,7 +118,7 @@ enum GNUNET_DB_QueryStatus
 TALER_ARL_get_denomination_info (
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_DenominationKeyValidityPS **issue,
-  struct GNUNET_HashCode *dh);
+  struct TALER_DenominationHash *dh);
 
 
 /**
diff --git a/src/auditor/taler-auditor-dbinit.c 
b/src/auditor/taler-auditor-dbinit.c
index ab97b739..54f8152a 100644
--- a/src/auditor/taler-auditor-dbinit.c
+++ b/src/auditor/taler-auditor-dbinit.c
@@ -21,6 +21,7 @@
  */
 #include "platform.h"
 #include <gnunet/gnunet_util_lib.h>
+#include "taler_util.h"
 #include "taler_auditordb_plugin.h"
 
 
diff --git a/src/auditor/taler-auditor-httpd_deposit-confirmation.c 
b/src/auditor/taler-auditor-httpd_deposit-confirmation.c
index c7a23d71..8f16f36f 100644
--- a/src/auditor/taler-auditor-httpd_deposit-confirmation.c
+++ b/src/auditor/taler-auditor-httpd_deposit-confirmation.c
@@ -183,33 +183,25 @@ verify_and_execute_deposit_confirmation (
   }
 
   /* check deposit confirmation signature */
+  if (GNUNET_OK !=
+      TALER_exchange_deposit_confirm_verify (&dc->h_contract_terms,
+                                             &dc->h_wire,
+                                             NULL /* h_extensions! */,
+                                             dc->exchange_timestamp,
+                                             dc->wire_deadline,
+                                             dc->refund_deadline,
+                                             &dc->amount_without_fee,
+                                             &dc->coin_pub,
+                                             &dc->merchant,
+                                             &dc->exchange_pub,
+                                             &dc->exchange_sig))
   {
-    struct TALER_DepositConfirmationPS dcs = {
-      .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
-      .purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
-      .h_contract_terms = dc->h_contract_terms,
-      .h_wire = dc->h_wire,
-      .exchange_timestamp = GNUNET_TIME_absolute_hton (dc->exchange_timestamp),
-      .refund_deadline = GNUNET_TIME_absolute_hton (dc->refund_deadline),
-      .coin_pub = dc->coin_pub,
-      .merchant = dc->merchant
-    };
-
-    TALER_amount_hton (&dcs.amount_without_fee,
-                       &dc->amount_without_fee);
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
-                                    &dcs,
-                                    &dc->exchange_sig.eddsa_signature,
-                                    &dc->exchange_pub.eddsa_pub))
-    {
-      TALER_LOG_WARNING (
-        "Invalid signature on /deposit-confirmation request\n");
-      return TALER_MHD_reply_with_error (connection,
-                                         MHD_HTTP_FORBIDDEN,
-                                         
TALER_EC_AUDITOR_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID,
-                                         "exchange signature invalid");
-    }
+    TALER_LOG_WARNING (
+      "Invalid signature on /deposit-confirmation request\n");
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_FORBIDDEN,
+                                       
TALER_EC_AUDITOR_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID,
+                                       "exchange signature invalid");
   }
 
   /* execute transaction */
@@ -257,12 +249,16 @@ TAH_DEPOSIT_CONFIRMATION_handler (struct 
TAH_RequestHandler *rh,
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
                                  &dc.h_contract_terms),
+    GNUNET_JSON_spec_fixed_auto ("h_extensions",
+                                 &dc.h_extensions),
     GNUNET_JSON_spec_fixed_auto ("h_wire",
                                  &dc.h_wire),
     TALER_JSON_spec_absolute_time ("exchange_timestamp",
                                    &dc.exchange_timestamp),
     TALER_JSON_spec_absolute_time ("refund_deadline",
                                    &dc.refund_deadline),
+    TALER_JSON_spec_absolute_time ("wire_deadline",
+                                   &dc.wire_deadline),
     TALER_JSON_spec_amount ("amount_without_fee",
                             TAH_currency,
                             &dc.amount_without_fee),
diff --git a/src/auditor/taler-helper-auditor-aggregation.c 
b/src/auditor/taler-helper-auditor-aggregation.c
index 468f66b4..d4ad08aa 100644
--- a/src/auditor/taler-helper-auditor-aggregation.c
+++ b/src/auditor/taler-helper-auditor-aggregation.c
@@ -358,9 +358,9 @@ struct WireCheckContext
   struct TALER_Amount total_deposits;
 
   /**
-   * Hash of the wire transfer details of the receiver.
+   * Target account details of the receiver.
    */
-  struct GNUNET_HashCode h_wire;
+  const char *payto_uri;
 
   /**
    * Execution time of the wire transfer.
@@ -393,7 +393,7 @@ struct WireCheckContext
 static int
 check_transaction_history_for_deposit (
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_PrivateContractHash *h_contract_terms,
   const struct TALER_MerchantPublicKeyP *merchant_pub,
   const struct TALER_DenominationKeyValidityPS *issue,
   const struct TALER_EXCHANGEDB_TransactionList *tl_head,
@@ -440,27 +440,6 @@ check_transaction_history_for_deposit (
     {
     case TALER_EXCHANGEDB_TT_DEPOSIT:
       /* check wire and h_wire are consistent */
-      {
-        struct GNUNET_HashCode hw;
-
-        if (GNUNET_OK !=
-            TALER_JSON_merchant_wire_signature_hash (
-              tl->details.deposit->receiver_wire_account,
-              &hw))
-        {
-          report_row_inconsistency ("deposits",
-                                    tl->serial_id,
-                                    "wire account given is malformed");
-        }
-        else if (0 !=
-                 GNUNET_memcmp (&hw,
-                                &tl->details.deposit->h_wire))
-        {
-          report_row_inconsistency ("deposits",
-                                    tl->serial_id,
-                                    "h(wire) does not match wire");
-        }
-      }
       amount_with_fee = &tl->details.deposit->amount_with_fee; /* according to 
exchange*/
       fee_claimed = &tl->details.deposit->deposit_fee; /* Fee according to 
exchange DB */
       TALER_ARL_amount_add (&expenditures,
@@ -691,7 +670,7 @@ check_transaction_history_for_deposit (
               "Coin %s contributes %s to contract %s\n",
               TALER_B2S (coin_pub),
               TALER_amount2s (merchant_gain),
-              GNUNET_h2s (h_contract_terms));
+              GNUNET_h2s (&h_contract_terms->hash));
   return GNUNET_OK;
 }
 
@@ -703,8 +682,7 @@ check_transaction_history_for_deposit (
  * @param[in,out] cls a `struct WireCheckContext`
  * @param rowid which row in the table is the information from (for 
diagnostics)
  * @param merchant_pub public key of the merchant (should be same for all 
callbacks with the same @e cls)
- * @param h_wire hash of wire transfer details of the merchant (should be same 
for all callbacks with the same @e cls)
- * @param account_details where did we transfer the funds?
+ * @param account_pay_uri where did we transfer the funds?
  * @param exec_time execution time of the wire transfer (should be same for 
all callbacks with the same @e cls)
  * @param h_contract_terms which proposal was this payment about
  * @param denom_pub denomination of @a coin_pub
@@ -719,10 +697,9 @@ wire_transfer_information_cb (
   void *cls,
   uint64_t rowid,
   const struct TALER_MerchantPublicKeyP *merchant_pub,
-  const struct GNUNET_HashCode *h_wire,
-  const json_t *account_details,
+  const char *account_pay_uri,
   struct GNUNET_TIME_Absolute exec_time,
-  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_PrivateContractHash *h_contract_terms,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_Amount *coin_value,
@@ -735,24 +712,6 @@ wire_transfer_information_cb (
   struct TALER_EXCHANGEDB_TransactionList *tl;
   struct TALER_CoinPublicInfo coin;
   enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_HashCode hw;
-
-  if (GNUNET_OK !=
-      TALER_JSON_merchant_wire_signature_hash (account_details,
-                                               &hw))
-  {
-    report_row_inconsistency ("aggregation",
-                              rowid,
-                              "failed to compute hash of given wire data");
-  }
-  else if (0 !=
-           GNUNET_memcmp (&hw,
-                          h_wire))
-  {
-    report_row_inconsistency ("aggregation",
-                              rowid,
-                              "database contains wrong hash code for wire 
details");
-  }
 
   /* Obtain coin's transaction history */
   qs = TALER_ARL_edb->get_coin_transactions (TALER_ARL_edb->cls,
@@ -788,7 +747,7 @@ wire_transfer_information_cb (
                                                 &issue);
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
-    GNUNET_CRYPTO_rsa_signature_free (coin.denom_sig.rsa_signature);
+    TALER_denom_sig_free (&coin.denom_sig);
     TALER_ARL_edb->free_coin_transaction_list (TALER_ARL_edb->cls,
                                                tl);
     if (0 == qs)
@@ -819,7 +778,7 @@ wire_transfer_information_cb (
     TALER_ARL_amount_add (&total_bad_sig_loss,
                           &total_bad_sig_loss,
                           coin_value);
-    GNUNET_CRYPTO_rsa_signature_free (coin.denom_sig.rsa_signature);
+    TALER_denom_sig_free (&coin.denom_sig);
     TALER_ARL_edb->free_coin_transaction_list (TALER_ARL_edb->cls,
                                                tl);
     report_row_inconsistency ("deposit",
@@ -827,8 +786,7 @@ wire_transfer_information_cb (
                               "coin denomination signature invalid");
     return;
   }
-  GNUNET_CRYPTO_rsa_signature_free (coin.denom_sig.rsa_signature);
-  coin.denom_sig.rsa_signature = NULL; /* just to be sure */
+  TALER_denom_sig_free (&coin.denom_sig);
   GNUNET_assert (NULL != issue); /* mostly to help static analysis */
   /* Check transaction history to see if it supports aggregate
      valuation */
@@ -879,14 +837,13 @@ wire_transfer_information_cb (
         "aggregation (contribution)",
         rowid,
         &coin_value_without_fee,
-        &
-        total_deposit_without_refunds,
+        &total_deposit_without_refunds,
         -1);
     }
   }
   /* Check other details of wire transfer match */
-  if (0 != GNUNET_memcmp (h_wire,
-                          &wcc->h_wire))
+  if (0 != strcmp (account_pay_uri,
+                   wcc->payto_uri))
   {
     report_row_inconsistency ("aggregation",
                               rowid,
@@ -1029,16 +986,16 @@ get_wire_fee (struct AggregationContext *ac,
  * @param rowid identifier of the respective row in the database
  * @param date timestamp of the wire transfer (roughly)
  * @param wtid wire transfer subject
- * @param wire wire transfer details of the receiver
+ * @param payto_uri bank account details of the receiver
  * @param amount amount that was wired
  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
  */
-static int
+static enum GNUNET_GenericReturnValue
 check_wire_out_cb (void *cls,
                    uint64_t rowid,
                    struct GNUNET_TIME_Absolute date,
                    const struct TALER_WireTransferIdentifierRawP *wtid,
-                   const json_t *wire,
+                   const char *payto_uri,
                    const struct TALER_Amount *amount)
 {
   struct AggregationContext *ac = cls;
@@ -1057,7 +1014,7 @@ check_wire_out_cb (void *cls,
               TALER_B2S (wtid),
               TALER_amount2s (amount),
               GNUNET_STRINGS_absolute_time_to_string (date));
-  if (NULL == (method = TALER_JSON_wire_to_method (wire)))
+  if (NULL == (method = TALER_payto_get_method (payto_uri)))
   {
     report_row_inconsistency ("wire_out",
                               rowid,
@@ -1071,14 +1028,7 @@ check_wire_out_cb (void *cls,
   GNUNET_assert (GNUNET_OK ==
                  TALER_amount_set_zero (amount->currency,
                                         &wcc.total_deposits));
-  if (GNUNET_OK !=
-      TALER_JSON_merchant_wire_signature_hash (wire,
-                                               &wcc.h_wire))
-  {
-    GNUNET_break (0);
-    GNUNET_free (method);
-    return GNUNET_SYSERR;
-  }
+  wcc.payto_uri = payto_uri;
   qs = TALER_ARL_edb->lookup_wire_transfer (TALER_ARL_edb->cls,
                                             wtid,
                                             &wire_transfer_information_cb,
@@ -1178,8 +1128,8 @@ check_wire_out_cb (void *cls,
 
     TALER_ARL_report (report_wire_out_inconsistencies,
                       GNUNET_JSON_PACK (
-                        GNUNET_JSON_pack_object_incref ("destination_account",
-                                                        (json_t *) wire),
+                        GNUNET_JSON_pack_string ("destination_account",
+                                                 payto_uri),
                         GNUNET_JSON_pack_uint64 ("rowid",
                                                  rowid),
                         TALER_JSON_pack_amount ("expected",
diff --git a/src/auditor/taler-helper-auditor-coins.c 
b/src/auditor/taler-helper-auditor-coins.c
index ba9cf6d1..56683e58 100644
--- a/src/auditor/taler-helper-auditor-coins.c
+++ b/src/auditor/taler-helper-auditor-coins.c
@@ -282,7 +282,7 @@ report_emergency_by_amount (
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Reporting emergency on denomination `%s' over loss of %s\n",
-              GNUNET_h2s (&issue->denom_hash),
+              GNUNET_h2s (&issue->denom_hash.hash),
               TALER_amount2s (loss));
   TALER_ARL_report (report_emergencies,
                     GNUNET_JSON_PACK (
@@ -671,7 +671,7 @@ struct CoinContext
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-init_denomination (const struct GNUNET_HashCode *denom_hash,
+init_denomination (const struct TALER_DenominationHash *denom_hash,
                    struct DenominationSummary *ds)
 {
   enum GNUNET_DB_QueryStatus qs;
@@ -711,7 +711,7 @@ init_denomination (const struct GNUNET_HashCode *denom_hash,
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Starting balance for denomination `%s' is %s (%llu)\n",
-              GNUNET_h2s (denom_hash),
+              GNUNET_h2s (&denom_hash->hash),
               TALER_amount2s (&ds->denom_balance),
               (unsigned long long) ds->num_issued);
   qs = TALER_ARL_edb->get_denomination_revocation (TALER_ARL_edb->cls,
@@ -758,12 +758,12 @@ init_denomination (const struct GNUNET_HashCode 
*denom_hash,
 static struct DenominationSummary *
 get_denomination_summary (struct CoinContext *cc,
                           const struct TALER_DenominationKeyValidityPS *issue,
-                          const struct GNUNET_HashCode *dh)
+                          const struct TALER_DenominationHash *dh)
 {
   struct DenominationSummary *ds;
 
   ds = GNUNET_CONTAINER_multihashmap_get (cc->denom_summaries,
-                                          dh);
+                                          &dh->hash);
   if (NULL != ds)
     return ds;
   ds = GNUNET_new (struct DenominationSummary);
@@ -777,7 +777,7 @@ get_denomination_summary (struct CoinContext *cc,
   }
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONTAINER_multihashmap_put (cc->denom_summaries,
-                                                    dh,
+                                                    &dh->hash,
                                                     ds,
                                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
   return ds;
@@ -800,6 +800,9 @@ sync_denomination (void *cls,
                    void *value)
 {
   struct CoinContext *cc = cls;
+  struct TALER_DenominationHash denom_h = {
+    .hash = *denom_hash
+  };
   struct DenominationSummary *ds = value;
   const struct TALER_DenominationKeyValidityPS *issue = ds->issue;
   struct GNUNET_TIME_Absolute now;
@@ -818,7 +821,7 @@ sync_denomination (void *cls,
        outstanding coins as revenue; and reduce cc->risk exposure. */
     if (ds->in_db)
       qs = TALER_ARL_adb->del_denomination_balance (TALER_ARL_adb->cls,
-                                                    denom_hash);
+                                                    &denom_h);
     else
       qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) &&
@@ -850,7 +853,7 @@ sync_denomination (void *cls,
           (qs = TALER_ARL_adb->insert_historic_denom_revenue (
              TALER_ARL_adb->cls,
              &TALER_ARL_master_pub,
-             denom_hash,
+             &denom_h,
              expire_deposit,
              &ds->denom_balance,
              &ds->denom_recoup)))
@@ -873,7 +876,7 @@ sync_denomination (void *cls,
                 TALER_amount2s (&ds->denom_balance),
                 (unsigned long long) ds->num_issued);
     cnt = TALER_ARL_edb->count_known_coins (TALER_ARL_edb->cls,
-                                            denom_hash);
+                                            &denom_h);
     if (0 > cnt)
     {
       /* Failed to obtain count? Bad database */
@@ -902,7 +905,7 @@ sync_denomination (void *cls,
       }
       if (ds->in_db)
         qs = TALER_ARL_adb->update_denomination_balance (TALER_ARL_adb->cls,
-                                                         denom_hash,
+                                                         &denom_h,
                                                          &ds->denom_balance,
                                                          &ds->denom_loss,
                                                          &ds->denom_risk,
@@ -910,7 +913,7 @@ sync_denomination (void *cls,
                                                          ds->num_issued);
       else
         qs = TALER_ARL_adb->insert_denomination_balance (TALER_ARL_adb->cls,
-                                                         denom_hash,
+                                                         &denom_h,
                                                          &ds->denom_balance,
                                                          &ds->denom_loss,
                                                          &ds->denom_risk,
@@ -953,10 +956,10 @@ sync_denomination (void *cls,
  * @param amount_with_fee amount that was withdrawn
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
-static int
+static enum GNUNET_GenericReturnValue
 withdraw_cb (void *cls,
              uint64_t rowid,
-             const struct GNUNET_HashCode *h_blind_ev,
+             const struct TALER_BlindedCoinHash *h_blind_ev,
              const struct TALER_DenominationPublicKey *denom_pub,
              const struct TALER_ReservePublicKeyP *reserve_pub,
              const struct TALER_ReserveSignatureP *reserve_sig,
@@ -965,7 +968,7 @@ withdraw_cb (void *cls,
 {
   struct CoinContext *cc = cls;
   struct DenominationSummary *ds;
-  struct GNUNET_HashCode dh;
+  struct TALER_DenominationHash dh;
   const struct TALER_DenominationKeyValidityPS *issue;
   struct TALER_Amount value;
   enum GNUNET_DB_QueryStatus qs;
@@ -1013,7 +1016,7 @@ withdraw_cb (void *cls,
                      &issue->value);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Issued coin in denomination `%s' of total value %s\n",
-              GNUNET_h2s (&dh),
+              GNUNET_h2s (&dh.hash),
               TALER_amount2s (&value));
   ds->num_issued++;
   TALER_ARL_amount_add (&ds->denom_balance,
@@ -1021,7 +1024,7 @@ withdraw_cb (void *cls,
                         &value);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "New balance of denomination `%s' is %s\n",
-              GNUNET_h2s (&dh),
+              GNUNET_h2s (&dh.hash),
               TALER_amount2s (&ds->denom_balance));
   TALER_ARL_amount_add (&total_escrow_balance,
                         &total_escrow_balance,
@@ -1204,7 +1207,7 @@ check_known_coin (const char *operation,
                           &total_bad_sig_loss,
                           loss_potential);
   }
-  GNUNET_CRYPTO_rsa_signature_free (ci.denom_sig.rsa_signature);
+  TALER_denom_sig_free (&ci.denom_sig);
   return qs;
 }
 
@@ -1288,8 +1291,8 @@ refresh_session_cb (void *cls,
       .coin_pub = *coin_pub
     };
 
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
-                                       &rmc.h_denom_pub);
+    TALER_denom_pub_hash (denom_pub,
+                          &rmc.h_denom_pub);
     TALER_amount_hton (&rmc.amount_with_fee,
                        amount_with_fee);
     if (GNUNET_OK !=
@@ -1316,7 +1319,7 @@ refresh_session_cb (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Melting coin %s in denomination `%s' of value %s\n",
               TALER_B2S (coin_pub),
-              GNUNET_h2s (&issue->denom_hash),
+              GNUNET_h2s (&issue->denom_hash.hash),
               TALER_amount2s (amount_with_fee));
 
   {
@@ -1452,7 +1455,7 @@ refresh_session_cb (void *cls,
                            &reveal_ctx.new_issues[i]->value);
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                     "Created fresh coin in denomination `%s' of value %s\n",
-                    GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash),
+                    GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash.hash),
                     TALER_amount2s (&value));
         dsi->num_issued++;
         TALER_ARL_amount_add (&dsi->denom_balance,
@@ -1463,7 +1466,7 @@ refresh_session_cb (void *cls,
                               &value);
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                     "New balance of denomination `%s' is %s\n",
-                    GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash),
+                    GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash.hash),
                     TALER_amount2s (&dsi->denom_balance));
         TALER_ARL_amount_add (&total_escrow_balance,
                               &total_escrow_balance,
@@ -1526,7 +1529,7 @@ refresh_session_cb (void *cls,
     }
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "New balance of denomination `%s' after melt is %s\n",
-                GNUNET_h2s (&issue->denom_hash),
+                GNUNET_h2s (&issue->denom_hash.hash),
                 TALER_amount2s (&dso->denom_balance));
   }
 
@@ -1553,36 +1556,18 @@ refresh_session_cb (void *cls,
  * @param cls closure
  * @param rowid unique serial ID for the deposit in our DB
  * @param exchange_timestamp when did the exchange get the deposit
- * @param wallet_timestamp when did the contract signing happen
- * @param merchant_pub public key of the merchant
+ * @param deposit deposit details
  * @param denom_pub denomination public key of @a coin_pub
- * @param coin_pub public key of the coin
- * @param coin_sig signature from the coin
- * @param amount_with_fee amount that was deposited including fee
- * @param h_contract_terms hash of the proposal data known to merchant and 
customer
- * @param refund_deadline by which the merchant advised that he might want
- *        to get a refund
- * @param wire_deadline by which the merchant advised that he would like the
- *        wire transfer to be executed
- * @param receiver_wire_account wire details for the merchant, NULL from 
iterate_matching_deposits()
  * @param done flag set if the deposit was already executed (or not)
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
-static int
+static enum GNUNET_GenericReturnValue
 deposit_cb (void *cls,
             uint64_t rowid,
             struct GNUNET_TIME_Absolute exchange_timestamp,
-            struct GNUNET_TIME_Absolute wallet_timestamp,
-            const struct TALER_MerchantPublicKeyP *merchant_pub,
+            const struct TALER_EXCHANGEDB_Deposit *deposit,
             const struct TALER_DenominationPublicKey *denom_pub,
-            const struct TALER_CoinSpendPublicKeyP *coin_pub,
-            const struct TALER_CoinSpendSignatureP *coin_sig,
-            const struct TALER_Amount *amount_with_fee,
-            const struct GNUNET_HashCode *h_contract_terms,
-            struct GNUNET_TIME_Absolute refund_deadline,
-            struct GNUNET_TIME_Absolute wire_deadline,
-            const json_t *receiver_wire_account,
-            int done)
+            bool done)
 {
   struct CoinContext *cc = cls;
   const struct TALER_DenominationKeyValidityPS *issue;
@@ -1605,8 +1590,8 @@ deposit_cb (void *cls,
       return GNUNET_SYSERR;
     return GNUNET_OK;
   }
-  if (refund_deadline.abs_value_us >
-      wire_deadline.abs_value_us)
+  if (deposit->refund_deadline.abs_value_us >
+      deposit->wire_deadline.abs_value_us)
   {
     report_row_inconsistency ("deposits",
                               rowid,
@@ -1622,9 +1607,9 @@ deposit_cb (void *cls,
   qs = check_known_coin ("deposit",
                          issue,
                          rowid,
-                         coin_pub,
+                         &deposit->coin.coin_pub,
                          denom_pub,
-                         amount_with_fee);
+                         &deposit->amount_with_fee);
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
@@ -1634,50 +1619,32 @@ deposit_cb (void *cls,
 
   /* Verify deposit signature */
   {
-    struct TALER_DepositRequestPS dr = {
-      .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
-      .purpose.size = htonl (sizeof (dr)),
-      .h_contract_terms = *h_contract_terms,
-      .wallet_timestamp = GNUNET_TIME_absolute_hton (wallet_timestamp),
-      .refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
-      .deposit_fee = issue->fee_deposit,
-      .merchant = *merchant_pub,
-      .coin_pub = *coin_pub
-    };
+    struct TALER_MerchantWireHash h_wire;
+    struct TALER_DenominationHash h_denom_pub;
+    struct TALER_Amount deposit_fee;
 
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
-                                       &dr.h_denom_pub);
-    if (GNUNET_OK !=
-        TALER_JSON_merchant_wire_signature_hash (receiver_wire_account,
-                                                 &dr.h_wire))
-    {
-      TALER_ARL_report (report_bad_sig_losses,
-                        GNUNET_JSON_PACK (
-                          GNUNET_JSON_pack_string ("operation",
-                                                   "deposit"),
-                          GNUNET_JSON_pack_uint64 ("row",
-                                                   rowid),
-                          TALER_JSON_pack_amount ("loss",
-                                                  amount_with_fee),
-                          GNUNET_JSON_pack_data_auto ("coin_pub",
-                                                      coin_pub)));
-      TALER_ARL_amount_add (&total_bad_sig_loss,
-                            &total_bad_sig_loss,
-                            amount_with_fee);
-      if (TALER_ARL_do_abort ())
-        return GNUNET_SYSERR;
-      return GNUNET_OK;
-    }
-    TALER_amount_hton (&dr.amount_with_fee,
-                       amount_with_fee);
+    TALER_denom_pub_hash (denom_pub,
+                          &h_denom_pub);
+    TALER_merchant_wire_signature_hash (deposit->receiver_wire_account,
+                                        &deposit->wire_salt,
+                                        &h_wire);
+    TALER_amount_ntoh (&deposit_fee,
+                       &issue->fee_deposit);
     /* NOTE: This is one of the operations we might eventually
        want to do in parallel in the background to improve
        auditor performance! */
     if (GNUNET_OK !=
-        GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
-                                    &dr,
-                                    &coin_sig->eddsa_signature,
-                                    &coin_pub->eddsa_pub))
+        TALER_wallet_deposit_verify (&deposit->amount_with_fee,
+                                     &deposit_fee,
+                                     &h_wire,
+                                     &deposit->h_contract_terms,
+                                     NULL /* h_extensions! */,
+                                     &h_denom_pub,
+                                     deposit->timestamp,
+                                     &deposit->merchant_pub,
+                                     deposit->refund_deadline,
+                                     &deposit->coin.coin_pub,
+                                     &deposit->csig))
     {
       TALER_ARL_report (report_bad_sig_losses,
                         GNUNET_JSON_PACK (
@@ -1686,12 +1653,12 @@ deposit_cb (void *cls,
                           GNUNET_JSON_pack_uint64 ("row",
                                                    rowid),
                           TALER_JSON_pack_amount ("loss",
-                                                  amount_with_fee),
+                                                  &deposit->amount_with_fee),
                           GNUNET_JSON_pack_data_auto ("coin_pub",
-                                                      coin_pub)));
+                                                      
&deposit->coin.coin_pub)));
       TALER_ARL_amount_add (&total_bad_sig_loss,
                             &total_bad_sig_loss,
-                            amount_with_fee);
+                            &deposit->amount_with_fee);
       if (TALER_ARL_do_abort ())
         return GNUNET_SYSERR;
       return GNUNET_OK;
@@ -1699,9 +1666,9 @@ deposit_cb (void *cls,
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Deposited coin %s in denomination `%s' of value %s\n",
-              TALER_B2S (coin_pub),
-              GNUNET_h2s (&issue->denom_hash),
-              TALER_amount2s (amount_with_fee));
+              TALER_B2S (&deposit->coin.coin_pub),
+              GNUNET_h2s (&issue->denom_hash.hash),
+              TALER_amount2s (&deposit->amount_with_fee));
 
   /* update old coin's denomination balance */
   ds = get_denomination_summary (cc,
@@ -1720,11 +1687,11 @@ deposit_cb (void *cls,
     if (TALER_ARL_SR_INVALID_NEGATIVE ==
         TALER_ARL_amount_subtract_neg (&tmp,
                                        &ds->denom_balance,
-                                       amount_with_fee))
+                                       &deposit->amount_with_fee))
     {
       TALER_ARL_amount_add (&ds->denom_loss,
                             &ds->denom_loss,
-                            amount_with_fee);
+                            &deposit->amount_with_fee);
       ds->report_emergency = GNUNET_YES;
     }
     else
@@ -1733,7 +1700,7 @@ deposit_cb (void *cls,
     }
 
     if (-1 == TALER_amount_cmp (&total_escrow_balance,
-                                amount_with_fee))
+                                &deposit->amount_with_fee))
     {
       /* This can theoretically happen if for example the exchange
          never issued any coins (i.e. escrow balance is zero), but
@@ -1745,19 +1712,19 @@ deposit_cb (void *cls,
         "subtracting deposit fee from escrow balance",
         rowid,
         &total_escrow_balance,
-        amount_with_fee,
+        &deposit->amount_with_fee,
         0);
     }
     else
     {
       TALER_ARL_amount_subtract (&total_escrow_balance,
                                  &total_escrow_balance,
-                                 amount_with_fee);
+                                 &deposit->amount_with_fee);
     }
 
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "New balance of denomination `%s' after deposit is %s\n",
-                GNUNET_h2s (&issue->denom_hash),
+                GNUNET_h2s (&issue->denom_hash.hash),
                 TALER_amount2s (&ds->denom_balance));
   }
 
@@ -1794,14 +1761,14 @@ deposit_cb (void *cls,
  * @param amount_with_fee amount that was deposited including fee
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
-static int
+static enum GNUNET_GenericReturnValue
 refund_cb (void *cls,
            uint64_t rowid,
            const struct TALER_DenominationPublicKey *denom_pub,
            const struct TALER_CoinSpendPublicKeyP *coin_pub,
            const struct TALER_MerchantPublicKeyP *merchant_pub,
            const struct TALER_MerchantSignatureP *merchant_sig,
-           const struct GNUNET_HashCode *h_contract_terms,
+           const struct TALER_PrivateContractHash *h_contract_terms,
            uint64_t rtransaction_id,
            const struct TALER_Amount *amount_with_fee)
 {
@@ -1891,7 +1858,7 @@ refund_cb (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Refunding coin %s in denomination `%s' value %s\n",
               TALER_B2S (coin_pub),
-              GNUNET_h2s (&issue->denom_hash),
+              GNUNET_h2s (&issue->denom_hash.hash),
               TALER_amount2s (amount_with_fee));
 
   /* update coin's denomination balance */
@@ -1920,7 +1887,7 @@ refund_cb (void *cls,
                           &amount_without_fee);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "New balance of denomination `%s' after refund is %s\n",
-                GNUNET_h2s (&issue->denom_hash),
+                GNUNET_h2s (&issue->denom_hash.hash),
                 TALER_amount2s (&ds->denom_balance));
   }
   /* update total refund fee balance */
@@ -1955,7 +1922,7 @@ check_recoup (struct CoinContext *cc,
               const struct TALER_CoinPublicInfo *coin,
               const struct TALER_DenominationPublicKey *denom_pub,
               const struct TALER_CoinSpendSignatureP *coin_sig,
-              const struct TALER_DenominationBlindingKeyP *coin_blind)
+              const union TALER_DenominationBlindingKeyP *coin_blind)
 {
   struct DenominationSummary *ds;
   enum GNUNET_DB_QueryStatus qs;
@@ -2109,7 +2076,7 @@ recoup_cb (void *cls,
            const struct TALER_CoinPublicInfo *coin,
            const struct TALER_DenominationPublicKey *denom_pub,
            const struct TALER_CoinSpendSignatureP *coin_sig,
-           const struct TALER_DenominationBlindingKeyP *coin_blind)
+           const union TALER_DenominationBlindingKeyP *coin_blind)
 {
   struct CoinContext *cc = cls;
 
@@ -2150,11 +2117,11 @@ recoup_refresh_cb (void *cls,
                    struct GNUNET_TIME_Absolute timestamp,
                    const struct TALER_Amount *amount,
                    const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
-                   const struct GNUNET_HashCode *old_denom_pub_hash,
+                   const struct TALER_DenominationHash *old_denom_pub_hash,
                    const struct TALER_CoinPublicInfo *coin,
                    const struct TALER_DenominationPublicKey *denom_pub,
                    const struct TALER_CoinSpendSignatureP *coin_sig,
-                   const struct TALER_DenominationBlindingKeyP *coin_blind)
+                   const union TALER_DenominationBlindingKeyP *coin_blind)
 {
   struct CoinContext *cc = cls;
   const struct TALER_DenominationKeyValidityPS *issue;
@@ -2203,7 +2170,7 @@ recoup_refresh_cb (void *cls,
                             amount);
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "New balance of denomination `%s' after refresh-recoup is 
%s\n",
-                  GNUNET_h2s (&issue->denom_hash),
+                  GNUNET_h2s (&issue->denom_hash.hash),
                   TALER_amount2s (&dso->denom_balance));
     }
   }
@@ -2247,7 +2214,7 @@ check_denomination (
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Encountered denomination `%s' that this auditor is not 
auditing!\n",
-                GNUNET_h2s (&issue->denom_hash));
+                GNUNET_h2s (&issue->denom_hash.hash));
     return; /* skip! */
   }
   {
diff --git a/src/auditor/taler-helper-auditor-deposits.c 
b/src/auditor/taler-helper-auditor-deposits.c
index 58f8226f..f7e1cb0d 100644
--- a/src/auditor/taler-helper-auditor-deposits.c
+++ b/src/auditor/taler-helper-auditor-deposits.c
@@ -112,26 +112,22 @@ test_dc (void *cls,
   dcc->last_seen_coin_serial = serial_id;
   {
     enum GNUNET_DB_QueryStatus qs;
-    struct TALER_EXCHANGEDB_Deposit dep = {
-      .coin.coin_pub = dc->coin_pub,
-      .h_contract_terms = dc->h_contract_terms,
-      .merchant_pub = dc->merchant,
-      .h_wire = dc->h_wire,
-      .refund_deadline = dc->refund_deadline
-    };
     struct GNUNET_TIME_Absolute exchange_timestamp;
     struct TALER_Amount deposit_fee;
 
-    qs = TALER_ARL_edb->have_deposit (TALER_ARL_edb->cls,
-                                      &dep,
-                                      GNUNET_NO /* do not check refund 
deadline */,
-                                      &deposit_fee,
-                                      &exchange_timestamp);
+    qs = TALER_ARL_edb->have_deposit2 (TALER_ARL_edb->cls,
+                                       &dc->h_contract_terms,
+                                       &dc->h_wire,
+                                       &dc->coin_pub,
+                                       &dc->merchant,
+                                       dc->refund_deadline,
+                                       &deposit_fee,
+                                       &exchange_timestamp);
     if (qs > 0)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Found deposit %s in exchange database\n",
-                  GNUNET_h2s (&dc->h_contract_terms));
+                  GNUNET_h2s (&dc->h_contract_terms.hash));
       if (TALER_ARL_do_abort ())
         return GNUNET_SYSERR;
       return GNUNET_OK; /* found, all good */
diff --git a/src/auditor/taler-helper-auditor-reserves.c 
b/src/auditor/taler-helper-auditor-reserves.c
index c27574d1..52a7b074 100644
--- a/src/auditor/taler-helper-auditor-reserves.c
+++ b/src/auditor/taler-helper-auditor-reserves.c
@@ -487,10 +487,10 @@ handle_reserve_in (void *cls,
  * @param amount_with_fee amount that was withdrawn
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
-static int
+static enum GNUNET_GenericReturnValue
 handle_reserve_out (void *cls,
                     uint64_t rowid,
-                    const struct GNUNET_HashCode *h_blind_ev,
+                    const struct TALER_BlindedCoinHash *h_blind_ev,
                     const struct TALER_DenominationPublicKey *denom_pub,
                     const struct TALER_ReservePublicKeyP *reserve_pub,
                     const struct TALER_ReserveSignatureP *reserve_sig,
@@ -689,7 +689,7 @@ handle_recoup_by_reserve (
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const struct TALER_DenominationBlindingKeyP *coin_blind)
+  const union TALER_DenominationBlindingKeyP *coin_blind)
 {
   struct ReserveContext *rc = cls;
   struct GNUNET_HashCode key;
@@ -739,7 +739,7 @@ handle_recoup_by_reserve (
 
   /* check that the coin was eligible for recoup!*/
   rev = GNUNET_CONTAINER_multihashmap_get (rc->revoked,
-                                           &coin->denom_pub_hash);
+                                           &coin->denom_pub_hash.hash);
   if (NULL == rev)
   {
     qs = TALER_ARL_edb->get_denomination_revocation (TALER_ARL_edb->cls,
@@ -777,7 +777,8 @@ handle_recoup_by_reserve (
       }
       GNUNET_assert (GNUNET_OK ==
                      GNUNET_CONTAINER_multihashmap_put (rc->revoked,
-                                                        &coin->denom_pub_hash,
+                                                        &coin->denom_pub_hash.
+                                                        hash,
                                                         (void *) rev,
                                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
     }
diff --git a/src/auditor/taler-helper-auditor-wire.c 
b/src/auditor/taler-helper-auditor-wire.c
index 2cd076ac..f275a453 100644
--- a/src/auditor/taler-helper-auditor-wire.c
+++ b/src/auditor/taler-helper-auditor-wire.c
@@ -775,7 +775,7 @@ commit (enum GNUNET_DB_QueryStatus qs)
  * @param rowid deposit table row of the coin's deposit
  * @param coin_pub public key of the coin
  * @param amount value of the deposit, including fee
- * @param wire where should the funds be wired
+ * @param payto_uri where should the funds be wired
  * @param deadline what was the requested wire transfer deadline
  * @param tiny did the exchange defer this transfer because it is too small?
  *             NOTE: only valid in internal audit mode!
@@ -787,10 +787,10 @@ wire_missing_cb (void *cls,
                  uint64_t rowid,
                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
                  const struct TALER_Amount *amount,
-                 const json_t *wire,
+                 const char *payto_uri,
                  struct GNUNET_TIME_Absolute deadline,
-                 /* bool? */ int tiny,
-                 /* bool? */ int done)
+                 bool tiny,
+                 bool done)
 {
   json_t *rep;
 
@@ -802,9 +802,9 @@ wire_missing_cb (void *cls,
   {
     /* In internal mode, we insist that the entry was
        actually marked as tiny. */
-    if ( (GNUNET_YES == tiny) &&
-         (0 > TALER_amount_cmp (amount,
-                                &tiny_amount)) )
+    if (tiny &&
+        (0 > TALER_amount_cmp (amount,
+                               &tiny_amount)) )
       return; /* acceptable, amount was tiny */
   }
   else
@@ -824,8 +824,8 @@ wire_missing_cb (void *cls,
                                     deadline),
     GNUNET_JSON_pack_data_auto ("coin_pub",
                                 coin_pub),
-    GNUNET_JSON_pack_object_incref ("account",
-                                    (json_t *) wire));
+    GNUNET_JSON_pack_string ("account",
+                             payto_uri));
   if (internal_checks)
   {
     /* the 'done' bit is only useful in 'internal' mode */
@@ -942,16 +942,16 @@ check_time_difference (const char *table,
  * @param rowid unique serial ID for the refresh session in our DB
  * @param date timestamp of the transfer (roughly)
  * @param wtid wire transfer subject
- * @param wire wire transfer details of the receiver
+ * @param payto_uri wire transfer details of the receiver
  * @param amount amount that was wired
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
-static int
+static enum GNUNET_GenericReturnValue
 wire_out_cb (void *cls,
              uint64_t rowid,
              struct GNUNET_TIME_Absolute date,
              const struct TALER_WireTransferIdentifierRawP *wtid,
-             const json_t *wire,
+             const char *payto_uri,
              const struct TALER_Amount *amount)
 {
   struct WireAccount *wa = cls;
@@ -997,62 +997,55 @@ wire_out_cb (void *cls,
       return GNUNET_SYSERR;
     return GNUNET_OK;
   }
+  if (0 != strcasecmp (payto_uri,
+                       roi->details.credit_account_uri))
   {
-    char *payto_uri;
-
-    payto_uri = TALER_JSON_wire_to_payto (wire);
-    if (0 != strcasecmp (payto_uri,
-                         roi->details.credit_account_uri))
-    {
-      /* Destination bank account is wrong in actual wire transfer, so
-         we should count the wire transfer as entirely spurious, and
-         additionally consider the justified wire transfer as missing. */
-      TALER_ARL_report (report_wire_out_inconsistencies,
-                        GNUNET_JSON_PACK (
-                          GNUNET_JSON_pack_uint64 ("row",
-                                                   rowid),
-                          TALER_JSON_pack_amount ("amount_wired",
-                                                  &roi->details.amount),
-                          TALER_JSON_pack_amount ("amount_justified",
-                                                  &zero),
-                          GNUNET_JSON_pack_data_auto ("wtid", wtid),
-                          TALER_JSON_pack_time_abs_human ("timestamp",
-                                                          date),
-                          GNUNET_JSON_pack_string ("diagnostic",
-                                                   "receiver account 
mismatch"),
-                          GNUNET_JSON_pack_string ("target",
-                                                   payto_uri),
-                          GNUNET_JSON_pack_string ("account_section",
-                                                   wa->ai->section_name)));
-      TALER_ARL_amount_add (&total_bad_amount_out_plus,
-                            &total_bad_amount_out_plus,
-                            &roi->details.amount);
-      TALER_ARL_report (report_wire_out_inconsistencies,
-                        GNUNET_JSON_PACK (
-                          GNUNET_JSON_pack_uint64 ("row",
-                                                   rowid),
-                          TALER_JSON_pack_amount ("amount_wired",
-                                                  &zero),
-                          TALER_JSON_pack_amount ("amount_justified",
-                                                  amount),
-                          GNUNET_JSON_pack_data_auto ("wtid",
-                                                      wtid),
-                          TALER_JSON_pack_time_abs_human ("timestamp",
-                                                          date),
-                          GNUNET_JSON_pack_string ("diagnostic",
-                                                   "receiver account 
mismatch"),
-                          GNUNET_JSON_pack_string ("target",
-                                                   roi->details.
-                                                   credit_account_uri),
-                          GNUNET_JSON_pack_string ("account_section",
-                                                   wa->ai->section_name)));
-      TALER_ARL_amount_add (&total_bad_amount_out_minus,
-                            &total_bad_amount_out_minus,
-                            amount);
-      GNUNET_free (payto_uri);
-      goto cleanup;
-    }
-    GNUNET_free (payto_uri);
+    /* Destination bank account is wrong in actual wire transfer, so
+       we should count the wire transfer as entirely spurious, and
+       additionally consider the justified wire transfer as missing. */
+    TALER_ARL_report (report_wire_out_inconsistencies,
+                      GNUNET_JSON_PACK (
+                        GNUNET_JSON_pack_uint64 ("row",
+                                                 rowid),
+                        TALER_JSON_pack_amount ("amount_wired",
+                                                &roi->details.amount),
+                        TALER_JSON_pack_amount ("amount_justified",
+                                                &zero),
+                        GNUNET_JSON_pack_data_auto ("wtid", wtid),
+                        TALER_JSON_pack_time_abs_human ("timestamp",
+                                                        date),
+                        GNUNET_JSON_pack_string ("diagnostic",
+                                                 "receiver account mismatch"),
+                        GNUNET_JSON_pack_string ("target",
+                                                 payto_uri),
+                        GNUNET_JSON_pack_string ("account_section",
+                                                 wa->ai->section_name)));
+    TALER_ARL_amount_add (&total_bad_amount_out_plus,
+                          &total_bad_amount_out_plus,
+                          &roi->details.amount);
+    TALER_ARL_report (report_wire_out_inconsistencies,
+                      GNUNET_JSON_PACK (
+                        GNUNET_JSON_pack_uint64 ("row",
+                                                 rowid),
+                        TALER_JSON_pack_amount ("amount_wired",
+                                                &zero),
+                        TALER_JSON_pack_amount ("amount_justified",
+                                                amount),
+                        GNUNET_JSON_pack_data_auto ("wtid",
+                                                    wtid),
+                        TALER_JSON_pack_time_abs_human ("timestamp",
+                                                        date),
+                        GNUNET_JSON_pack_string ("diagnostic",
+                                                 "receiver account mismatch"),
+                        GNUNET_JSON_pack_string ("target",
+                                                 roi->details.
+                                                 credit_account_uri),
+                        GNUNET_JSON_pack_string ("account_section",
+                                                 wa->ai->section_name)));
+    TALER_ARL_amount_add (&total_bad_amount_out_minus,
+                          &total_bad_amount_out_minus,
+                          amount);
+    goto cleanup;
   }
   if (0 != TALER_amount_cmp (&roi->details.amount,
                              amount))
diff --git a/src/auditordb/auditor-0001.sql b/src/auditordb/auditor-0001.sql
index 3a0d7dd9..0faa890d 100644
--- a/src/auditordb/auditor-0001.sql
+++ b/src/auditordb/auditor-0001.sql
@@ -30,7 +30,7 @@ COMMENT ON TABLE auditor_exchanges
 
 
 CREATE TABLE IF NOT EXISTS auditor_exchange_signkeys
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,ep_start INT8 NOT NULL
   ,ep_expire INT8 NOT NULL
   ,ep_end INT8 NOT NULL
@@ -42,7 +42,7 @@ COMMENT ON TABLE auditor_exchange_signkeys
 
 
 CREATE TABLE IF NOT EXISTS auditor_progress_reserve
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,last_reserve_in_serial_id INT8 NOT NULL DEFAULT 0
   ,last_reserve_out_serial_id INT8 NOT NULL DEFAULT 0
   ,last_reserve_recoup_serial_id INT8 NOT NULL DEFAULT 0
@@ -65,7 +65,7 @@ COMMENT ON TABLE auditor_progress_aggregation
 
 
 CREATE TABLE IF NOT EXISTS auditor_progress_deposit_confirmation
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,last_deposit_confirmation_serial_id INT8 NOT NULL DEFAULT 0
   ,PRIMARY KEY (master_pub)
   );
@@ -75,7 +75,7 @@ COMMENT ON TABLE auditor_progress_deposit_confirmation
 
 
 CREATE TABLE IF NOT EXISTS auditor_progress_coin
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,last_withdraw_serial_id INT8 NOT NULL DEFAULT 0
   ,last_deposit_serial_id INT8 NOT NULL DEFAULT 0
   ,last_melt_serial_id INT8 NOT NULL DEFAULT 0
@@ -90,12 +90,12 @@ COMMENT ON TABLE auditor_progress_coin
 
 
 CREATE TABLE IF NOT EXISTS wire_auditor_account_progress
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,account_name TEXT NOT NULL
   ,last_wire_reserve_in_serial_id INT8 NOT NULL DEFAULT 0
   ,last_wire_wire_out_serial_id INT8 NOT NULL DEFAULT 0
-  ,wire_in_off INT8
-  ,wire_out_off INT8
+  ,wire_in_off INT8 NOT NULL
+  ,wire_out_off INT8 NOT NULL
   ,PRIMARY KEY (master_pub,account_name)
   );
 COMMENT ON TABLE wire_auditor_account_progress
@@ -104,7 +104,7 @@ COMMENT ON TABLE wire_auditor_account_progress
 
 
 CREATE TABLE IF NOT EXISTS wire_auditor_progress
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,last_timestamp INT8 NOT NULL
   ,last_reserve_close_uuid INT8 NOT NULL
   ,PRIMARY KEY (master_pub)
@@ -113,7 +113,7 @@ CREATE TABLE IF NOT EXISTS wire_auditor_progress
 
 CREATE TABLE IF NOT EXISTS auditor_reserves
   (reserve_pub BYTEA NOT NULL CHECK(LENGTH(reserve_pub)=32)
-  ,master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  ,master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,reserve_balance_val INT8 NOT NULL
   ,reserve_balance_frac INT4 NOT NULL
   ,withdraw_fee_balance_val INT8 NOT NULL
@@ -131,7 +131,7 @@ CREATE INDEX IF NOT EXISTS auditor_reserves_by_reserve_pub
 
 
 CREATE TABLE IF NOT EXISTS auditor_reserve_balance
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,reserve_balance_val INT8 NOT NULL
   ,reserve_balance_frac INT4 NOT NULL
   ,withdraw_fee_balance_val INT8 NOT NULL
@@ -142,7 +142,7 @@ COMMENT ON TABLE auditor_reserve_balance
 
 
 CREATE TABLE IF NOT EXISTS auditor_wire_fee_balance
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,wire_fee_balance_val INT8 NOT NULL
   ,wire_fee_balance_frac INT4 NOT NULL
   );
@@ -173,7 +173,7 @@ COMMENT ON COLUMN 
auditor_denomination_pending.recoup_loss_val
 
 
 CREATE TABLE IF NOT EXISTS auditor_balance_summary
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,denom_balance_val INT8 NOT NULL
   ,denom_balance_frac INT4 NOT NULL
   ,deposit_fee_balance_val INT8 NOT NULL
@@ -194,7 +194,7 @@ COMMENT ON TABLE auditor_balance_summary
 
 
 CREATE TABLE IF NOT EXISTS auditor_historic_denomination_revenue
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)
   ,revenue_timestamp INT8 NOT NULL
   ,revenue_balance_val INT8 NOT NULL
@@ -209,7 +209,7 @@ COMMENT ON COLUMN 
auditor_historic_denomination_revenue.revenue_balance_val
 
 
 CREATE TABLE IF NOT EXISTS auditor_historic_reserve_summary
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,start_date INT8 NOT NULL
   ,end_date INT8 NOT NULL
   ,reserve_profits_val INT8 NOT NULL
@@ -225,19 +225,21 @@ CREATE INDEX IF NOT EXISTS 
auditor_historic_reserve_summary_by_master_pub_start_
 
 
 CREATE TABLE IF NOT EXISTS deposit_confirmations
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
-  ,serial_id BIGSERIAL UNIQUE
-  ,h_contract_terms BYTEA CHECK (LENGTH(h_contract_terms)=64)
-  ,h_wire BYTEA CHECK (LENGTH(h_wire)=64)
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  ,serial_id BIGSERIAL NOT NULL UNIQUE
+  ,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)
+  ,h_extensions BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)
+  ,h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)
   ,exchange_timestamp INT8 NOT NULL
   ,refund_deadline INT8 NOT NULL
+  ,wire_deadline INT8 NOT NULL
   ,amount_without_fee_val INT8 NOT NULL
   ,amount_without_fee_frac INT4 NOT NULL
-  ,coin_pub BYTEA CHECK (LENGTH(coin_pub)=32)
-  ,merchant_pub BYTEA CHECK (LENGTH(merchant_pub)=32)
-  ,exchange_sig BYTEA CHECK (LENGTH(exchange_sig)=64)
-  ,exchange_pub BYTEA CHECK (LENGTH(exchange_pub)=32)
-  ,master_sig BYTEA CHECK (LENGTH(master_sig)=64)
+  ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)
+  ,merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)
+  ,exchange_sig BYTEA NOT NULL CHECK (LENGTH(exchange_sig)=64)
+  ,exchange_pub BYTEA NOT NULL CHECK (LENGTH(exchange_pub)=32)
+  ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
   ,PRIMARY KEY 
(h_contract_terms,h_wire,coin_pub,merchant_pub,exchange_sig,exchange_pub,master_sig)
   );
 COMMENT ON TABLE deposit_confirmations
@@ -245,7 +247,7 @@ COMMENT ON TABLE deposit_confirmations
 
 
 CREATE TABLE IF NOT EXISTS auditor_predicted_result
-  (master_pub BYTEA CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
+  (master_pub BYTEA NOT NULL CONSTRAINT master_pub_ref REFERENCES 
auditor_exchanges(master_pub) ON DELETE CASCADE
   ,balance_val INT8 NOT NULL
   ,balance_frac INT4 NOT NULL
   );
diff --git a/src/auditordb/plugin_auditordb_postgres.c 
b/src/auditordb/plugin_auditordb_postgres.c
index be221a8b..5817c880 100644
--- a/src/auditordb/plugin_auditordb_postgres.c
+++ b/src/auditordb/plugin_auditordb_postgres.c
@@ -188,8 +188,10 @@ setup_connection (struct PostgresClosure *pg)
                             "INSERT INTO deposit_confirmations "
                             "(master_pub"
                             ",h_contract_terms"
+                            ",h_extensions"
                             ",h_wire"
                             ",exchange_timestamp"
+                            ",wire_deadline"
                             ",refund_deadline"
                             ",amount_without_fee_val"
                             ",amount_without_fee_frac"
@@ -198,15 +200,17 @@ setup_connection (struct PostgresClosure *pg)
                             ",exchange_sig"
                             ",exchange_pub"
                             ",master_sig" /* master_sig could be normalized... 
*/
-                            ") VALUES 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12);",
-                            12),
+                            ") VALUES 
($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14);",
+                            14),
     /* Used in #postgres_get_deposit_confirmations() */
     GNUNET_PQ_make_prepare ("auditor_deposit_confirmation_select",
                             "SELECT"
                             " serial_id"
                             ",h_contract_terms"
+                            ",h_extensions"
                             ",h_wire"
                             ",exchange_timestamp"
+                            ",wire_deadline"
                             ",refund_deadline"
                             ",amount_without_fee_val"
                             ",amount_without_fee_frac"
@@ -1029,8 +1033,10 @@ postgres_insert_deposit_confirmation (
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (&dc->master_public_key),
     GNUNET_PQ_query_param_auto_from_type (&dc->h_contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (&dc->h_extensions),
     GNUNET_PQ_query_param_auto_from_type (&dc->h_wire),
     TALER_PQ_query_param_absolute_time (&dc->exchange_timestamp),
+    TALER_PQ_query_param_absolute_time (&dc->wire_deadline),
     TALER_PQ_query_param_absolute_time (&dc->refund_deadline),
     TALER_PQ_query_param_amount (&dc->amount_without_fee),
     GNUNET_PQ_query_param_auto_from_type (&dc->coin_pub),
@@ -1108,12 +1114,16 @@ deposit_confirmation_cb (void *cls,
                                     &serial_id),
       GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
                                             &dc.h_contract_terms),
+      GNUNET_PQ_result_spec_auto_from_type ("h_extensions",
+                                            &dc.h_extensions),
       GNUNET_PQ_result_spec_auto_from_type ("h_wire",
                                             &dc.h_wire),
       GNUNET_PQ_result_spec_absolute_time ("exchange_timestamp",
                                            &dc.exchange_timestamp),
       GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
                                            &dc.refund_deadline),
+      GNUNET_PQ_result_spec_absolute_time ("wire_deadline",
+                                           &dc.wire_deadline),
       TALER_PQ_RESULT_SPEC_AMOUNT ("amount_without_fee",
                                    &dc.amount_without_fee),
       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
@@ -2153,7 +2163,7 @@ postgres_get_wire_fee_summary (void *cls,
 static enum GNUNET_DB_QueryStatus
 postgres_insert_denomination_balance (
   void *cls,
-  const struct GNUNET_HashCode *denom_pub_hash,
+  const struct TALER_DenominationHash *denom_pub_hash,
   const struct TALER_Amount *denom_balance,
   const struct TALER_Amount *denom_loss,
   const struct TALER_Amount *denom_risk,
@@ -2193,7 +2203,7 @@ postgres_insert_denomination_balance (
 static enum GNUNET_DB_QueryStatus
 postgres_update_denomination_balance (
   void *cls,
-  const struct GNUNET_HashCode *denom_pub_hash,
+  const struct TALER_DenominationHash *denom_pub_hash,
   const struct TALER_Amount *denom_balance,
   const struct TALER_Amount *denom_loss,
   const struct TALER_Amount *denom_risk,
@@ -2231,7 +2241,8 @@ postgres_update_denomination_balance (
  */
 static enum GNUNET_DB_QueryStatus
 postgres_get_denomination_balance (void *cls,
-                                   const struct GNUNET_HashCode 
*denom_pub_hash,
+                                   const struct
+                                   TALER_DenominationHash *denom_pub_hash,
                                    struct TALER_Amount *denom_balance,
                                    struct TALER_Amount *denom_loss,
                                    struct TALER_Amount *denom_risk,
@@ -2428,7 +2439,7 @@ static enum GNUNET_DB_QueryStatus
 postgres_insert_historic_denom_revenue (
   void *cls,
   const struct TALER_MasterPublicKeyP *master_pub,
-  const struct GNUNET_HashCode *denom_pub_hash,
+  const struct TALER_DenominationHash *denom_pub_hash,
   struct GNUNET_TIME_Absolute revenue_timestamp,
   const struct TALER_Amount *revenue_balance,
   const struct TALER_Amount *loss_balance)
@@ -2495,7 +2506,7 @@ historic_denom_revenue_cb (void *cls,
 
   for (unsigned int i = 0; i < num_results; i++)
   {
-    struct GNUNET_HashCode denom_pub_hash;
+    struct TALER_DenominationHash denom_pub_hash;
     struct GNUNET_TIME_Absolute revenue_timestamp;
     struct TALER_Amount revenue_balance;
     struct TALER_Amount loss;
diff --git a/src/auditordb/test_auditordb.c b/src/auditordb/test_auditordb.c
index 237d8ec8..38f0c24f 100644
--- a/src/auditordb/test_auditordb.c
+++ b/src/auditordb/test_auditordb.c
@@ -130,23 +130,28 @@ run (void *cls)
 
   struct TALER_MasterPublicKeyP master_pub;
   struct TALER_ReservePublicKeyP reserve_pub;
-  struct GNUNET_HashCode rnd_hash;
-  RND_BLK (&master_pub);
-  RND_BLK (&reserve_pub);
-  RND_BLK (&rnd_hash);
-
+  struct TALER_DenominationHash rnd_hash;
   struct TALER_DenominationPrivateKey denom_priv;
   struct TALER_DenominationPublicKey denom_pub;
-  struct GNUNET_HashCode denom_pub_hash;
+  struct TALER_DenominationHash denom_pub_hash;
+  struct GNUNET_TIME_Absolute now;
+  struct GNUNET_TIME_Absolute past;
+  struct GNUNET_TIME_Absolute future;
+  struct GNUNET_TIME_Absolute date;
 
-  denom_priv.rsa_private_key = GNUNET_CRYPTO_rsa_private_key_create (1024);
-  denom_pub.rsa_public_key = GNUNET_CRYPTO_rsa_private_key_get_public (
-    denom_priv.rsa_private_key);
-  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key, 
&denom_pub_hash);
-  GNUNET_CRYPTO_rsa_private_key_free (denom_priv.rsa_private_key);
-  GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key);
+  RND_BLK (&master_pub);
+  RND_BLK (&reserve_pub);
+  RND_BLK (&rnd_hash);
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_denom_priv_create (&denom_priv,
+                                          &denom_pub,
+                                          TALER_DENOMINATION_RSA,
+                                          1024));
+  TALER_denom_pub_hash (&denom_pub,
+                        &denom_pub_hash);
+  TALER_denom_priv_free (&denom_priv);
+  TALER_denom_pub_free (&denom_pub);
 
-  struct GNUNET_TIME_Absolute now, past, future, date;
   now = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&now);
   past = GNUNET_TIME_absolute_subtract (now,
@@ -480,14 +485,12 @@ run (void *cls)
               "Test: select_historic_denom_revenue\n");
 
   int
-  select_historic_denom_revenue_result (void *cls,
-                                        const struct
-                                        GNUNET_HashCode *denom_pub_hash2,
-                                        struct GNUNET_TIME_Absolute
-                                        revenue_timestamp2,
-                                        const struct
-                                        TALER_Amount *revenue_balance2,
-                                        const struct TALER_Amount *loss2)
+  select_historic_denom_revenue_result (
+    void *cls,
+    const struct TALER_DenominationHash *denom_pub_hash2,
+    struct GNUNET_TIME_Absolute revenue_timestamp2,
+    const struct TALER_Amount *revenue_balance2,
+    const struct TALER_Amount *loss2)
   {
     static int n = 0;
 
diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c
index 8d9a82b1..19c5e14f 100644
--- a/src/bank-lib/fakebank.c
+++ b/src/bank-lib/fakebank.c
@@ -1507,28 +1507,18 @@ handle_transfer (struct TALER_FAKEBANK_Handle *h,
       return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
     }
     {
-      enum GNUNET_GenericReturnValue ret;
+      int ret;
 
       credit = TALER_xtalerbank_account_from_payto (credit_account);
-      if (NULL == credit)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "`%s' is not a valid x-taler-bank account\n",
-                    credit_account);
-        ret = GNUNET_SYSERR;
-      }
-      else
-      {
-        ret = make_transfer (h,
-                             account,
-                             credit,
-                             &amount,
-                             &wtid,
-                             base_url,
-                             &uuid,
-                             &row_id,
-                             &ts);
-      }
+      ret = make_transfer (h,
+                           account,
+                           credit,
+                           &amount,
+                           &wtid,
+                           base_url,
+                           &uuid,
+                           &row_id,
+                           &ts);
       if (GNUNET_OK != ret)
       {
         MHD_RESULT res;
diff --git a/src/benchmark/taler-aggregator-benchmark.c 
b/src/benchmark/taler-aggregator-benchmark.c
index e432d8f5..16a0ad5b 100644
--- a/src/benchmark/taler-aggregator-benchmark.c
+++ b/src/benchmark/taler-aggregator-benchmark.c
@@ -58,11 +58,6 @@ static unsigned int refund_rate = 0;
  */
 static char *currency;
 
-/**
- * Merchant JSON wire details.
- */
-static json_t *json_wire;
-
 /**
  * Configuration.
  */
@@ -81,7 +76,7 @@ static struct GNUNET_SCHEDULER_Task *task;
 /**
  * Hash of the denomination.
  */
-static struct GNUNET_HashCode h_denom_pub;
+static struct TALER_DenominationHash h_denom_pub;
 
 /**
  * "signature" to use for the coin(s).
@@ -212,16 +207,7 @@ do_shutdown (void *cls)
     GNUNET_SCHEDULER_cancel (task);
     task = NULL;
   }
-  if (NULL !=denom_sig.rsa_signature)
-  {
-    GNUNET_CRYPTO_rsa_signature_free (denom_sig.rsa_signature);
-    denom_sig.rsa_signature = NULL;
-  }
-  if (NULL != json_wire)
-  {
-    json_decref (json_wire);
-    json_wire = NULL;
-  }
+  TALER_denom_sig_free (&denom_sig);
 }
 
 
@@ -240,7 +226,17 @@ struct Merchant
    * the exchange from the detailed wire data provided by the
    * merchant.
    */
-  struct GNUNET_HashCode h_wire;
+  struct TALER_MerchantWireHash h_wire;
+
+  /**
+   * Salt used when computing @e h_wire.
+   */
+  struct TALER_WireSalt wire_salt;
+
+  /**
+   * Account information for the merchant.
+   */
+  char *payto_uri;
 
 };
 
@@ -256,7 +252,7 @@ struct Deposit
    * Hash over the proposal data between merchant and customer
    * (remains unknown to the Exchange).
    */
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
 
 };
 
@@ -324,9 +320,8 @@ add_deposit (const struct Merchant *m)
   RANDOMIZE (&deposit.csig);
   deposit.merchant_pub = m->merchant_pub;
   deposit.h_contract_terms = d.h_contract_terms;
-  deposit.h_wire = m->h_wire;
-  deposit.receiver_wire_account
-    = json_wire;
+  deposit.wire_salt = m->wire_salt;
+  deposit.receiver_wire_account = m->payto_uri;
   deposit.timestamp = random_time ();
   deposit.refund_deadline = random_time ();
   deposit.wire_deadline = random_time ();
@@ -359,7 +354,6 @@ static void
 work (void *cls)
 {
   struct Merchant m;
-  char *acc;
   uint64_t rnd1;
   uint64_t rnd2;
 
@@ -369,33 +363,22 @@ work (void *cls)
                                    UINT64_MAX);
   rnd2 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
                                    UINT64_MAX);
-  GNUNET_asprintf (&acc,
+  GNUNET_asprintf (&m.payto_uri,
                    "payto://x-taler-bank/localhost:8082/account-%llX-%llX",
                    (unsigned long long) rnd1,
                    (unsigned long long) rnd2);
-  json_wire = GNUNET_JSON_PACK (
-    GNUNET_JSON_pack_string ("payto_uri",
-                             acc),
-    GNUNET_JSON_pack_string ("salt",
-                             "thesalty"));
-  GNUNET_free (acc);
   RANDOMIZE (&m.merchant_pub);
-  if (GNUNET_OK !=
-      TALER_JSON_merchant_wire_signature_hash (json_wire,
-                                               &m.h_wire))
-  {
-    GNUNET_break (0);
-    global_ret = EXIT_FAILURE;
-    GNUNET_SCHEDULER_shutdown ();
-    return;
-  }
-
+  RANDOMIZE (&m.wire_salt);
+  TALER_merchant_wire_signature_hash (m.payto_uri,
+                                      &m.wire_salt,
+                                      &m.h_wire);
   if (GNUNET_OK !=
       plugin->start (plugin->cls,
                      "aggregator-benchmark-fill"))
   {
     GNUNET_break (0);
     global_ret = EXIT_FAILURE;
+    GNUNET_free (m.payto_uri);
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
@@ -405,6 +388,7 @@ work (void *cls)
     {
       global_ret = EXIT_FAILURE;
       GNUNET_SCHEDULER_shutdown ();
+      GNUNET_free (m.payto_uri);
       return;
     }
   }
@@ -414,6 +398,7 @@ work (void *cls)
     if (0 == --howmany_merchants)
     {
       GNUNET_SCHEDULER_shutdown ();
+      GNUNET_free (m.payto_uri);
       return;
     }
   }
@@ -422,8 +407,7 @@ work (void *cls)
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Failed to commit, will try again\n");
   }
-  json_decref (json_wire);
-  json_wire = NULL;
+  GNUNET_free (m.payto_uri);
   task = GNUNET_SCHEDULER_add_now (&work,
                                    NULL);
 }
@@ -495,17 +479,22 @@ run (void *cls,
         GNUNET_TIME_absolute_add (end,
                                   GNUNET_TIME_UNIT_YEARS));
   {
-    struct GNUNET_CRYPTO_RsaPrivateKey *pk;
-    struct GNUNET_CRYPTO_RsaPublicKey *pub;
-    struct GNUNET_HashCode hc;
+    struct TALER_DenominationPrivateKey pk;
     struct TALER_DenominationPublicKey denom_pub;
-
-    RANDOMIZE (&hc);
-    pk = GNUNET_CRYPTO_rsa_private_key_create (1024);
-    pub = GNUNET_CRYPTO_rsa_private_key_get_public (pk);
-    denom_pub.rsa_public_key = pub;
-    GNUNET_CRYPTO_rsa_public_key_hash (pub,
-                                       &h_denom_pub);
+    struct TALER_CoinPubHash c_hash;
+    struct TALER_PlanchetDetail pd;
+    struct TALER_BlindedDenominationSignature bds;
+    union TALER_DenominationBlindingKeyP bks;
+    struct TALER_CoinSpendPublicKeyP coin_pub;
+
+    RANDOMIZE (&coin_pub);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_priv_create (&pk,
+                                            &denom_pub,
+                                            TALER_DENOMINATION_RSA,
+                                            1024));
+    TALER_denom_pub_hash (&denom_pub,
+                          &h_denom_pub);
     make_amountN (2, 0, &issue.properties.value);
     make_amountN (0, 5, &issue.properties.fee_withdraw);
     make_amountN (0, 5, &issue.properties.fee_deposit);
@@ -523,11 +512,29 @@ run (void *cls,
       return;
     }
 
-    denom_sig.rsa_signature
-      = GNUNET_CRYPTO_rsa_sign_fdh (pk,
-                                    &hc);
-    GNUNET_CRYPTO_rsa_public_key_free (pub);
-    GNUNET_CRYPTO_rsa_private_key_free (pk);
+    TALER_blinding_secret_create (&bks);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_blind (&denom_pub,
+                                      &bks,
+                                      NULL, /* FIXME-oec */
+                                      &coin_pub,
+                                      &c_hash,
+                                      &pd.coin_ev,
+                                      &pd.coin_ev_size));
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sign_blinded (&bds,
+                                             &pk,
+                                             pd.coin_ev,
+                                             pd.coin_ev_size));
+    GNUNET_free (pd.coin_ev);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sig_unblind (&denom_sig,
+                                            &bds,
+                                            &bks,
+                                            &denom_pub));
+    TALER_blinded_denom_sig_free (&bds);
+    TALER_denom_pub_free (&denom_pub);
+    TALER_denom_priv_free (&pk);
   }
 
   {
diff --git a/src/curl/curl.c b/src/curl/curl.c
index 73fcf86a..424c41fd 100644
--- a/src/curl/curl.c
+++ b/src/curl/curl.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2019-2020 Taler Systems SA
+  Copyright (C) 2019-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published
@@ -24,6 +24,7 @@
 #include "platform.h"
 #include "taler_curl_lib.h"
 
+
 #if TALER_CURL_COMPRESS_BODIES
 #include <zlib.h>
 #endif
@@ -76,18 +77,17 @@ TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx,
     slen = (size_t) cbuf_size;
     ctx->json_enc = (char *) cbuf;
   }
-  GNUNET_assert
-    (NULL != (ctx->headers = curl_slist_append
-                               (ctx->headers,
-                               "Content-Encoding: deflate")));
+  GNUNET_assert (NULL != (ctx->headers = curl_slist_append (
+                            ctx->headers,
+                            "Content-Encoding: deflate")));
 #else
   ctx->json_enc = str;
 #endif
 
   GNUNET_assert
-    (NULL != (ctx->headers = curl_slist_append
-                               (ctx->headers,
-                               "Content-Type: application/json")));
+    (NULL != (ctx->headers = curl_slist_append (
+                ctx->headers,
+                "Content-Type: application/json")));
 
   GNUNET_assert (CURLE_OK ==
                  curl_easy_setopt (eh,
diff --git a/src/exchange-tools/taler-auditor-offline.c 
b/src/exchange-tools/taler-auditor-offline.c
index 45bf271b..74e17efc 100644
--- a/src/exchange-tools/taler-auditor-offline.c
+++ b/src/exchange-tools/taler-auditor-offline.c
@@ -430,7 +430,7 @@ upload_denomination_add (const char *exchange_url,
                          const json_t *value)
 {
   struct TALER_AuditorSignatureP auditor_sig;
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
   struct DenominationAddRequest *dar;
   const char *err_name;
   unsigned int err_line;
@@ -760,8 +760,8 @@ show_denomkeys (const json_t *denomkeys)
     struct TALER_Amount fee_refund;
     struct TALER_MasterSignatureP master_sig;
     struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_rsa_public_key ("denom_pub",
-                                       &denom_pub.rsa_public_key),
+      TALER_JSON_spec_denom_pub ("denom_pub",
+                                 &denom_pub),
       TALER_JSON_spec_amount ("value",
                               currency,
                               &coin_value),
@@ -790,7 +790,7 @@ show_denomkeys (const json_t *denomkeys)
       GNUNET_JSON_spec_end ()
     };
     struct GNUNET_TIME_Relative duration;
-    struct GNUNET_HashCode h_denom_pub;
+    struct TALER_DenominationHash h_denom_pub;
 
     if (GNUNET_OK !=
         GNUNET_JSON_parse (value,
@@ -810,8 +810,8 @@ show_denomkeys (const json_t *denomkeys)
     }
     duration = GNUNET_TIME_absolute_get_difference (stamp_start,
                                                     stamp_expire_withdraw);
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
-                                       &h_denom_pub);
+    TALER_denom_pub_hash (&denom_pub,
+                          &h_denom_pub);
     if (GNUNET_OK !=
         TALER_exchange_offline_denom_validity_verify (
           &h_denom_pub,
@@ -1060,8 +1060,8 @@ sign_denomkeys (const json_t *denomkeys)
     struct TALER_Amount fee_refund;
     struct TALER_MasterSignatureP master_sig;
     struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_rsa_public_key ("denom_pub",
-                                       &denom_pub.rsa_public_key),
+      TALER_JSON_spec_denom_pub ("denom_pub",
+                                 &denom_pub),
       TALER_JSON_spec_amount ("value",
                               currency,
                               &coin_value),
@@ -1089,7 +1089,7 @@ sign_denomkeys (const json_t *denomkeys)
                                    &master_sig),
       GNUNET_JSON_spec_end ()
     };
-    struct GNUNET_HashCode h_denom_pub;
+    struct TALER_DenominationHash h_denom_pub;
 
     if (GNUNET_OK !=
         GNUNET_JSON_parse (value,
@@ -1107,8 +1107,8 @@ sign_denomkeys (const json_t *denomkeys)
       test_shutdown ();
       return GNUNET_SYSERR;
     }
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
-                                       &h_denom_pub);
+    TALER_denom_pub_hash (&denom_pub,
+                          &h_denom_pub);
     if (GNUNET_OK !=
         TALER_exchange_offline_denom_validity_verify (
           &h_denom_pub,
diff --git a/src/exchange-tools/taler-exchange-offline.c 
b/src/exchange-tools/taler-exchange-offline.c
index 4558f00b..89117758 100644
--- a/src/exchange-tools/taler-exchange-offline.c
+++ b/src/exchange-tools/taler-exchange-offline.c
@@ -761,7 +761,7 @@ struct UploadHandler
  * @param do_create #GNUNET_YES if the key may be created
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 load_offline_key (int do_create)
 {
   static bool done;
@@ -852,7 +852,7 @@ upload_denom_revocation (const char *exchange_url,
                          const json_t *value)
 {
   struct TALER_MasterSignatureP master_sig;
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
   struct DenomRevocationRequest *drr;
   const char *err_name;
   unsigned int err_line;
@@ -1824,7 +1824,7 @@ do_upload (char *const *args)
 static void
 do_revoke_denomination_key (char *const *args)
 {
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
   struct TALER_MasterSignatureP master_sig;
 
   if (NULL != in)
@@ -2604,8 +2604,8 @@ show_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub,
     struct GNUNET_JSON_Specification spec[] = {
       GNUNET_JSON_spec_string ("section_name",
                                &section_name),
-      GNUNET_JSON_spec_rsa_public_key ("denom_pub",
-                                       &denom_pub.rsa_public_key),
+      TALER_JSON_spec_denom_pub ("denom_pub",
+                                 &denom_pub),
       TALER_JSON_spec_amount ("value",
                               currency,
                               &coin_value),
@@ -2634,7 +2634,7 @@ show_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub,
       GNUNET_JSON_spec_end ()
     };
     struct GNUNET_TIME_Relative duration;
-    struct GNUNET_HashCode h_denom_pub;
+    struct TALER_DenominationHash h_denom_pub;
 
     if (GNUNET_OK !=
         GNUNET_JSON_parse (value,
@@ -2657,19 +2657,19 @@ show_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub,
     }
     duration = GNUNET_TIME_absolute_get_difference (stamp_start,
                                                     stamp_expire_withdraw);
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
-                                       &h_denom_pub);
+    TALER_denom_pub_hash (&denom_pub,
+                          &h_denom_pub);
     if (GNUNET_OK !=
-        TALER_exchange_secmod_rsa_verify (&h_denom_pub,
-                                          section_name,
-                                          stamp_start,
-                                          duration,
-                                          secm_pub,
-                                          &secm_sig))
+        TALER_exchange_secmod_denom_verify (&h_denom_pub,
+                                            section_name,
+                                            stamp_start,
+                                            duration,
+                                            secm_pub,
+                                            &secm_sig))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Invalid security module signature for denomination key %s 
(aborting)\n",
-                  GNUNET_h2s (&h_denom_pub));
+                  GNUNET_h2s (&h_denom_pub.hash));
       global_ret = EXIT_FAILURE;
       test_shutdown ();
       return GNUNET_SYSERR;
@@ -3023,8 +3023,8 @@ sign_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub,
     struct GNUNET_JSON_Specification spec[] = {
       GNUNET_JSON_spec_string ("section_name",
                                &section_name),
-      GNUNET_JSON_spec_rsa_public_key ("denom_pub",
-                                       &denom_pub.rsa_public_key),
+      TALER_JSON_spec_denom_pub ("denom_pub",
+                                 &denom_pub),
       TALER_JSON_spec_amount ("value",
                               currency,
                               &coin_value),
@@ -3053,7 +3053,7 @@ sign_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub,
       GNUNET_JSON_spec_end ()
     };
     struct GNUNET_TIME_Relative duration;
-    struct GNUNET_HashCode h_denom_pub;
+    struct TALER_DenominationHash h_denom_pub;
 
     if (GNUNET_OK !=
         GNUNET_JSON_parse (value,
@@ -3076,19 +3076,19 @@ sign_denomkeys (const struct 
TALER_SecurityModulePublicKeyP *secm_pub,
     }
     duration = GNUNET_TIME_absolute_get_difference (stamp_start,
                                                     stamp_expire_withdraw);
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
-                                       &h_denom_pub);
+    TALER_denom_pub_hash (&denom_pub,
+                          &h_denom_pub);
     if (GNUNET_OK !=
-        TALER_exchange_secmod_rsa_verify (&h_denom_pub,
-                                          section_name,
-                                          stamp_start,
-                                          duration,
-                                          secm_pub,
-                                          &secm_sig))
+        TALER_exchange_secmod_denom_verify (&h_denom_pub,
+                                            section_name,
+                                            stamp_start,
+                                            duration,
+                                            secm_pub,
+                                            &secm_sig))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Invalid security module signature for denomination key %s 
(aborting)\n",
-                  GNUNET_h2s (&h_denom_pub));
+                  GNUNET_h2s (&h_denom_pub.hash));
       global_ret = EXIT_FAILURE;
       test_shutdown ();
       GNUNET_JSON_parse_free (spec);
diff --git a/src/exchange/exchange.conf b/src/exchange/exchange.conf
index 3bcea08f..4d353ace 100644
--- a/src/exchange/exchange.conf
+++ b/src/exchange/exchange.conf
@@ -90,13 +90,18 @@ KYC_MODE = NONE
 # Balance threshold above which wallets are told
 # to undergo a KYC check at the exchange. Optional,
 # if not given there is no limit.
-# KYC_WALLET_BALANCE_LIMIT = 150:CURRENCY
+# KYC_WALLET_BALANCE_LIMIT = CURRENCY:150
+#
+# KYC_WITHDRAW_PERIOD = 1 month
 
 [exchange-kyc-oauth2]
 
 # URL of the OAuth endpoint for KYC checks
 # KYC_OAUTH2_URL =
 
+# URL of the "information" endpoint for KYC checks
+# KYC_INFO_URL =
+
 # KYC Oauth client ID.
 # KYC_OAUTH2_CLIENT_ID =
 
@@ -105,4 +110,4 @@ KYC_MODE = NONE
 
 # Where to redirect clients after successful
 # authorization?
-# KYC_OAUTH_POST_URL = https://bank.com/
+# KYC_OAUTH2_POST_URL = https://bank.com/
diff --git a/src/exchange/taler-exchange-aggregator.c 
b/src/exchange/taler-exchange-aggregator.c
index afedd7e3..73bbcc59 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -57,11 +57,6 @@ struct AggregationUnit
    */
   struct TALER_Amount wire_fee;
 
-  /**
-   * Hash of @e wire.
-   */
-  struct GNUNET_HashCode h_wire;
-
   /**
    * Wire transfer identifier we use.
    */
@@ -81,7 +76,12 @@ struct AggregationUnit
   /**
    * Wire details of the merchant.
    */
-  json_t *wire;
+  char *payto_uri;
+
+  /**
+   * Selected wire target for the aggregation.
+   */
+  uint64_t wire_target;
 
   /**
    * Exchange wire account to be used for the preparation and
@@ -149,6 +149,13 @@ static struct TALER_Amount currency_round_unit;
  */
 static char *exchange_base_url;
 
+/**
+ * Set to #GNUNET_YES if this exchange does not support KYC checks
+ * and thus deposits are to be aggregated regardless of the
+ * KYC status of the target account.
+ */
+static int kyc_off;
+
 /**
  * The exchange's configuration.
  */
@@ -216,8 +223,7 @@ static void
 cleanup_au (struct AggregationUnit *au)
 {
   GNUNET_assert (NULL != au);
-  if (NULL != au->wire)
-    json_decref (au->wire);
+  GNUNET_free (au->payto_uri);
   memset (au,
           0,
           sizeof (*au));
@@ -320,7 +326,7 @@ parse_wirewatch_config (void)
  * @param amount_with_fee what was the refunded amount with the fee
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
-static int
+static enum GNUNET_GenericReturnValue
 refund_by_coin_cb (void *cls,
                    const struct TALER_Amount *amount_with_fee)
 {
@@ -353,7 +359,8 @@ refund_by_coin_cb (void *cls,
  * @param amount_with_fee amount that was deposited including fee
  * @param deposit_fee amount the exchange gets to keep as transaction fees
  * @param h_contract_terms hash of the proposal data known to merchant and 
customer
- * @param wire target account for the wire transfer
+ * @param wire_target target account for the wire transfer
+ * @param payto_uri URI of the target account
  * @return transaction status code,  #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to 
continue to iterate
  */
 static enum GNUNET_DB_QueryStatus
@@ -363,8 +370,9 @@ deposit_cb (void *cls,
             const struct TALER_CoinSpendPublicKeyP *coin_pub,
             const struct TALER_Amount *amount_with_fee,
             const struct TALER_Amount *deposit_fee,
-            const struct GNUNET_HashCode *h_contract_terms,
-            const json_t *wire)
+            const struct TALER_PrivateContractHash *h_contract_terms,
+            uint64_t wire_target,
+            const char *payto_uri)
 {
   struct AggregationUnit *au = cls;
   enum GNUNET_DB_QueryStatus qs;
@@ -416,21 +424,9 @@ deposit_cb (void *cls,
     }
   }
 
-  GNUNET_assert (NULL == au->wire);
-  if (NULL == (au->wire = json_incref ((json_t *) wire)))
-  {
-    GNUNET_break (0);
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
-  if (GNUNET_OK !=
-      TALER_JSON_merchant_wire_signature_hash (wire,
-                                               &au->h_wire))
-  {
-    GNUNET_break (0);
-    json_decref (au->wire);
-    au->wire = NULL;
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
+  GNUNET_assert (NULL == au->payto_uri);
+  au->payto_uri = GNUNET_strdup (payto_uri);
+  au->wire_target = wire_target;
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
                               &au->wtid,
                               sizeof (au->wtid));
@@ -439,20 +435,13 @@ deposit_cb (void *cls,
               TALER_B2S (&au->wtid),
               TALER_amount2s (amount_with_fee),
               (unsigned long long) row_id);
+  au->wa = TALER_EXCHANGEDB_find_account_by_payto_uri (payto_uri);
+  if (NULL == au->wa)
   {
-    char *url;
-
-    url = TALER_JSON_wire_to_payto (au->wire);
-    au->wa = TALER_EXCHANGEDB_find_account_by_payto_uri (url);
-    if (NULL == au->wa)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "No exchange account configured for `%s', please fix your 
setup to continue!\n",
-                  url);
-      GNUNET_free (url);
-      return GNUNET_DB_STATUS_HARD_ERROR;
-    }
-    GNUNET_free (url);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "No exchange account configured for `%s', please fix your 
setup to continue!\n",
+                payto_uri);
+    return GNUNET_DB_STATUS_HARD_ERROR;
   }
 
   /* make sure we have current fees */
@@ -528,7 +517,7 @@ aggregate_cb (void *cls,
               const struct TALER_CoinSpendPublicKeyP *coin_pub,
               const struct TALER_Amount *amount_with_fee,
               const struct TALER_Amount *deposit_fee,
-              const struct GNUNET_HashCode *h_contract_terms)
+              const struct TALER_PrivateContractHash *h_contract_terms)
 {
   struct AggregationUnit *au = cls;
   struct TALER_Amount old;
@@ -724,6 +713,7 @@ run_aggregation (void *cls)
     db_plugin->cls,
     s->shard_start,
     s->shard_end,
+    kyc_off ? true : false,
     &deposit_cb,
     &au_active);
   switch (qs)
@@ -786,10 +776,11 @@ run_aggregation (void *cls)
 
   /* Now try to find other deposits to aggregate */
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Found ready deposit for %s, aggregating\n",
-              TALER_B2S (&au_active.merchant_pub));
+              "Found ready deposit for %s, aggregating by target %llu\n",
+              TALER_B2S (&au_active.merchant_pub),
+              (unsigned long long) au_active.wire_target);
   qs = db_plugin->iterate_matching_deposits (db_plugin->cls,
-                                             &au_active.h_wire,
+                                             au_active.wire_target,
                                              &au_active.merchant_pub,
                                              &aggregate_cb,
                                              &au_active,
@@ -908,19 +899,12 @@ run_aggregation (void *cls)
     void *buf;
     size_t buf_size;
 
-    {
-      char *url;
-
-      url = TALER_JSON_wire_to_payto (au_active.wire);
-      TALER_BANK_prepare_transfer (url,
-                                   &au_active.final_amount,
-                                   exchange_base_url,
-                                   &au_active.wtid,
-                                   &buf,
-                                   &buf_size);
-      GNUNET_free (url);
-    }
-
+    TALER_BANK_prepare_transfer (au_active.payto_uri,
+                                 &au_active.final_amount,
+                                 exchange_base_url,
+                                 &au_active.wtid,
+                                 &buf,
+                                 &buf_size);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Storing %u bytes of wire prepare data\n",
                 (unsigned int) buf_size);
@@ -937,7 +921,7 @@ run_aggregation (void *cls)
     qs = db_plugin->store_wire_transfer_out (db_plugin->cls,
                                              au_active.execution_time,
                                              &au_active.wtid,
-                                             au_active.wire,
+                                             au_active.wire_target,
                                              au_active.wa->section_name,
                                              &au_active.final_amount);
   cleanup_au (&au_active);
@@ -1130,6 +1114,10 @@ main (int argc,
                                "test",
                                "run in test mode and exit when idle",
                                &test_mode),
+    GNUNET_GETOPT_option_flag ('y',
+                               "kyc-off",
+                               "perform wire transfers without KYC checks",
+                               &kyc_off),
     GNUNET_GETOPT_OPTION_END
   };
   enum GNUNET_GenericReturnValue ret;
diff --git a/src/exchange/taler-exchange-closer.c 
b/src/exchange/taler-exchange-closer.c
index 91ececc8..3f30db7b 100644
--- a/src/exchange/taler-exchange-closer.c
+++ b/src/exchange/taler-exchange-closer.c
@@ -217,7 +217,7 @@ expired_reserve_cb (void *cls,
   struct TALER_WireTransferIdentifierRawP wtid;
   struct TALER_Amount amount_without_fee;
   struct TALER_Amount closing_fee;
-  int ret;
+  enum TALER_AmountArithmeticResult ret;
   enum GNUNET_DB_QueryStatus qs;
   const struct TALER_EXCHANGEDB_AccountInfo *wa;
 
@@ -273,8 +273,8 @@ expired_reserve_cb (void *cls,
   ret = TALER_amount_subtract (&amount_without_fee,
                                left,
                                &closing_fee);
-  if ( (GNUNET_SYSERR == ret) ||
-       (GNUNET_NO == ret) )
+  if ( (TALER_AAR_INVALID_NEGATIVE_RESULT == ret) ||
+       (TALER_AAR_RESULT_ZERO == ret) )
   {
     /* Closing fee higher than or equal to remaining balance, close
        without wire transfer. */
@@ -283,6 +283,7 @@ expired_reserve_cb (void *cls,
                    TALER_amount_set_zero (left->currency,
                                           &amount_without_fee));
   }
+  GNUNET_assert (TALER_AAR_RESULT_POSITIVE == ret);
   /* round down to enable transfer */
   if (GNUNET_SYSERR ==
       TALER_amount_round_down (&amount_without_fee,
@@ -293,10 +294,6 @@ expired_reserve_cb (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  if ( (0 == amount_without_fee.value) &&
-       (0 == amount_without_fee.fraction) )
-    ret = GNUNET_NO;
-
   /* NOTE: sizeof (*reserve_pub) == sizeof (wtid) right now, but to
      be future-compatible, we use the memset + min construction */
   memset (&wtid,
@@ -306,7 +303,7 @@ expired_reserve_cb (void *cls,
           reserve_pub,
           GNUNET_MIN (sizeof (wtid),
                       sizeof (*reserve_pub)));
-  if (GNUNET_SYSERR != ret)
+  if (TALER_AAR_INVALID_NEGATIVE_RESULT != ret)
     qs = db_plugin->insert_reserve_closed (db_plugin->cls,
                                            reserve_pub,
                                            now,
@@ -320,10 +317,10 @@ expired_reserve_cb (void *cls,
               "Closing reserve %s over %s (%d, %d)\n",
               TALER_B2S (reserve_pub),
               TALER_amount2s (left),
-              ret,
+              (int) ret,
               qs);
   /* Check for hard failure */
-  if ( (GNUNET_SYSERR == ret) ||
+  if ( (TALER_AAR_INVALID_NEGATIVE_RESULT == ret) ||
        (GNUNET_DB_STATUS_HARD_ERROR == qs) )
   {
     GNUNET_break (0);
@@ -331,10 +328,10 @@ expired_reserve_cb (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  if ( (GNUNET_OK != ret) ||
+  if ( (TALER_AAR_RESULT_ZERO == ret) ||
        (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) )
   {
-    /* Reserve balance was almost zero OR soft error */
+    /* Reserve balance was zero OR soft error */
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Reserve was virtually empty, moving on\n");
     (void) commit_or_warn ();
diff --git a/src/exchange/taler-exchange-httpd.c 
b/src/exchange/taler-exchange-httpd.c
index 1feede1a..c29984e2 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -540,7 +540,7 @@ handle_post_management (struct TEH_RequestContext *rc,
   if (0 == strcmp (args[0],
                    "denominations"))
   {
-    struct GNUNET_HashCode h_denom_pub;
+    struct TALER_DenominationHash h_denom_pub;
 
     if ( (NULL == args[0]) ||
          (NULL == args[1]) ||
@@ -681,7 +681,7 @@ handle_post_auditors (struct TEH_RequestContext *rc,
                       const char *const args[])
 {
   struct TALER_AuditorPublicKeyP auditor_pub;
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   if ( (NULL == args[0]) ||
        (NULL == args[1]) ||
@@ -1194,6 +1194,34 @@ parse_kyc_oauth_cfg (void)
   }
   TEH_kyc_config.details.oauth2.url = s;
 
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
+                                             "exchange-kyc-oauth2",
+                                             "KYC_INFO_URL",
+                                             &s))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange-kyc-oauth2",
+                               "KYC_INFO_URL");
+    return GNUNET_SYSERR;
+  }
+  if ( (! TALER_url_valid_charset (s)) ||
+       ( (0 != strncasecmp (s,
+                            "http://";,
+                            strlen ("http://";))) &&
+         (0 != strncasecmp (s,
+                            "https://";,
+                            strlen ("https://";))) ) )
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange-kyc-oauth2",
+                               "KYC_INFO_URL",
+                               "not a valid URL");
+    GNUNET_free (s);
+    return GNUNET_SYSERR;
+  }
+  TEH_kyc_config.details.oauth2.info_url = s;
+
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
                                              "exchange-kyc-oauth2",
@@ -1642,6 +1670,7 @@ do_shutdown (void *cls)
   mhd = TALER_MHD_daemon_stop ();
   TEH_resume_keys_requests (true);
   TEH_reserves_get_cleanup ();
+  TEH_kyc_check_cleanup ();
   TEH_kyc_proof_cleanup ();
   if (NULL != mhd)
     MHD_stop_daemon (mhd);
diff --git a/src/exchange/taler-exchange-httpd.h 
b/src/exchange/taler-exchange-httpd.h
index f66626b3..d52ce1a0 100644
--- a/src/exchange/taler-exchange-httpd.h
+++ b/src/exchange/taler-exchange-httpd.h
@@ -91,10 +91,15 @@ struct TEH_KycOptions
     {
 
       /**
-       * URL of tue OAuth2.0 endpoint for KYC checks.
+       * URL of the OAuth2.0 endpoint for KYC checks.
        */
       char *url;
 
+      /**
+       * URL of the user info access endpoint.
+       */
+      char *info_url;
+
       /**
        * Our client ID for OAuth2.0.
        */
diff --git a/src/exchange/taler-exchange-httpd_auditors.c 
b/src/exchange/taler-exchange-httpd_auditors.c
index 34e640ad..bf4a9b2c 100644
--- a/src/exchange/taler-exchange-httpd_auditors.c
+++ b/src/exchange/taler-exchange-httpd_auditors.c
@@ -45,7 +45,7 @@ struct AddAuditorDenomContext
   /**
    * Denomination this is about.
    */
-  const struct GNUNET_HashCode *h_denom_pub;
+  const struct TALER_DenominationHash *h_denom_pub;
 
   /**
    * Auditor this is about.
@@ -101,7 +101,7 @@ add_auditor_denom_sig (void *cls,
       connection,
       MHD_HTTP_NOT_FOUND,
       TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
-      GNUNET_h2s (awc->h_denom_pub));
+      GNUNET_h2s (&awc->h_denom_pub->hash));
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
 
@@ -192,7 +192,7 @@ MHD_RESULT
 TEH_handler_auditors (
   struct MHD_Connection *connection,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const json_t *root)
 {
   struct AddAuditorDenomContext awc = {
diff --git a/src/exchange/taler-exchange-httpd_auditors.h 
b/src/exchange/taler-exchange-httpd_auditors.h
index f8191f8a..00a2e57a 100644
--- a/src/exchange/taler-exchange-httpd_auditors.h
+++ b/src/exchange/taler-exchange-httpd_auditors.h
@@ -39,7 +39,7 @@ MHD_RESULT
 TEH_handler_auditors (
   struct MHD_Connection *connection,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const json_t *root);
 
 
diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index 38dfd447..e9851de7 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -57,10 +57,12 @@
 static MHD_RESULT
 reply_deposit_success (struct MHD_Connection *connection,
                        const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                       const struct GNUNET_HashCode *h_wire,
-                       const struct GNUNET_HashCode *h_contract_terms,
+                       const struct TALER_MerchantWireHash *h_wire,
+                       const struct TALER_ExtensionContractHash *h_extensions,
+                       const struct TALER_PrivateContractHash 
*h_contract_terms,
                        struct GNUNET_TIME_Absolute exchange_timestamp,
                        struct GNUNET_TIME_Absolute refund_deadline,
+                       struct GNUNET_TIME_Absolute wire_deadline,
                        const struct TALER_MerchantPublicKeyP *merchant,
                        const struct TALER_Amount *amount_without_fee)
 {
@@ -73,11 +75,14 @@ reply_deposit_success (struct MHD_Connection *connection,
     .h_wire = *h_wire,
     .exchange_timestamp = GNUNET_TIME_absolute_hton (exchange_timestamp),
     .refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
+    .wire_deadline = GNUNET_TIME_absolute_hton (wire_deadline),
     .coin_pub = *coin_pub,
-    .merchant = *merchant
+    .merchant_pub = *merchant
   };
   enum TALER_ErrorCode ec;
 
+  if (NULL != h_extensions)
+    dc.h_extensions = *h_extensions;
   TALER_amount_hton (&dc.amount_without_fee,
                      amount_without_fee);
   if (TALER_EC_NONE !=
@@ -116,6 +121,11 @@ struct DepositContext
    */
   struct GNUNET_TIME_Absolute exchange_timestamp;
 
+  /**
+   * Calculated hash over the wire details.
+   */
+  struct TALER_MerchantWireHash h_wire;
+
   /**
    * Value of the coin.
    */
@@ -124,7 +134,7 @@ struct DepositContext
   /**
    * payto:// URI of the credited account.
    */
-  char *payto_uri;
+  const char *payto_uri;
 };
 
 
@@ -152,7 +162,6 @@ deposit_precheck (void *cls,
 
   qs = TEH_plugin->have_deposit (TEH_plugin->cls,
                                  deposit,
-                                 GNUNET_YES /* check refund deadline */,
                                  &deposit_fee,
                                  &dc->exchange_timestamp);
   if (qs < 0)
@@ -179,10 +188,12 @@ deposit_precheck (void *cls,
                                           &deposit_fee));
     *mhd_ret = reply_deposit_success (connection,
                                       &deposit->coin.coin_pub,
-                                      &deposit->h_wire,
+                                      &dc->h_wire,
+                                      NULL /* h_extensions! */,
                                       &deposit->h_contract_terms,
                                       dc->exchange_timestamp,
                                       deposit->refund_deadline,
+                                      deposit->wire_deadline,
                                       &deposit->merchant_pub,
                                       &amount_without_fee);
     /* Treat as 'hard' DB error as we want to rollback and
@@ -318,25 +329,24 @@ TEH_handler_deposit (struct MHD_Connection *connection,
                      const struct TALER_CoinSpendPublicKeyP *coin_pub,
                      const json_t *root)
 {
-  json_t *wire;
   struct DepositContext dc;
   struct TALER_EXCHANGEDB_Deposit deposit;
-  struct GNUNET_HashCode my_h_wire;
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_json ("wire", &wire),
+    GNUNET_JSON_spec_string ("merchant_payto_uri",
+                             &dc.payto_uri),
+    GNUNET_JSON_spec_fixed_auto ("wire_salt",
+                                 &deposit.wire_salt),
     TALER_JSON_spec_amount ("contribution",
                             TEH_currency,
                             &deposit.amount_with_fee),
     GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
                                  &deposit.coin.denom_pub_hash),
-    TALER_JSON_spec_denomination_signature ("ub_sig",
-                                            &deposit.coin.denom_sig),
+    TALER_JSON_spec_denom_sig ("ub_sig",
+                               &deposit.coin.denom_sig),
     GNUNET_JSON_spec_fixed_auto ("merchant_pub",
                                  &deposit.merchant_pub),
     GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
                                  &deposit.h_contract_terms),
-    GNUNET_JSON_spec_fixed_auto ("h_wire",
-                                 &deposit.h_wire),
     GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                  &deposit.csig),
     TALER_JSON_spec_absolute_time ("timestamp",
@@ -374,16 +384,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
   {
     char *emsg;
 
-    dc.payto_uri = TALER_JSON_wire_to_payto (wire);
-    if (NULL == dc.payto_uri)
-    {
-      GNUNET_break_op (0);
-      GNUNET_JSON_parse_free (spec);
-      return TALER_MHD_reply_with_error (connection,
-                                         MHD_HTTP_BAD_REQUEST,
-                                         TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                                         "wire");
-    }
     emsg = TALER_payto_validate (dc.payto_uri);
     if (NULL != emsg)
     {
@@ -396,46 +396,22 @@ TEH_handler_deposit (struct MHD_Connection *connection,
                                         TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                         emsg);
       GNUNET_free (emsg);
-      GNUNET_free (dc.payto_uri);
       return ret;
     }
   }
-  deposit.receiver_wire_account = wire;
+  deposit.receiver_wire_account = (char *) dc.payto_uri;
   if (deposit.refund_deadline.abs_value_us > 
deposit.wire_deadline.abs_value_us)
   {
     GNUNET_break_op (0);
     GNUNET_JSON_parse_free (spec);
-    GNUNET_free (dc.payto_uri);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE,
                                        NULL);
   }
-  if (GNUNET_OK !=
-      TALER_JSON_merchant_wire_signature_hash (wire,
-                                               &my_h_wire))
-  {
-    TALER_LOG_WARNING (
-      "Failed to parse JSON wire format specification for /deposit request\n");
-    GNUNET_JSON_parse_free (spec);
-    GNUNET_free (dc.payto_uri);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_BAD_REQUEST,
-                                       
TALER_EC_EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_JSON,
-                                       NULL);
-  }
-  if (0 != GNUNET_memcmp (&deposit.h_wire,
-                          &my_h_wire))
-  {
-    /* Client hashed wire details differently than we did, reject */
-    GNUNET_JSON_parse_free (spec);
-    GNUNET_free (dc.payto_uri);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_BAD_REQUEST,
-                                       
TALER_EC_EXCHANGE_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT,
-                                       NULL);
-  }
-
+  TALER_merchant_wire_signature_hash (dc.payto_uri,
+                                      &deposit.wire_salt,
+                                      &dc.h_wire);
   /* Check for idempotency: did we get this request before? */
   dc.deposit = &deposit;
   {
@@ -449,7 +425,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
                                 &dc))
     {
       GNUNET_JSON_parse_free (spec);
-      GNUNET_free (dc.payto_uri);
       return mhd_ret;
     }
   }
@@ -468,7 +443,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
     if (NULL == dk)
     {
       GNUNET_JSON_parse_free (spec);
-      GNUNET_free (dc.payto_uri);
       return mret;
     }
     if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit))
@@ -479,7 +453,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
       now = GNUNET_TIME_absolute_get ();
       (void) GNUNET_TIME_round_abs (&now);
       GNUNET_JSON_parse_free (spec);
-      GNUNET_free (dc.payto_uri);
       return TEH_RESPONSE_reply_expired_denom_pub_hash (
         connection,
         &deposit.coin.denom_pub_hash,
@@ -495,7 +468,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
       now = GNUNET_TIME_absolute_get ();
       (void) GNUNET_TIME_round_abs (&now);
       GNUNET_JSON_parse_free (spec);
-      GNUNET_free (dc.payto_uri);
       return TEH_RESPONSE_reply_expired_denom_pub_hash (
         connection,
         &deposit.coin.denom_pub_hash,
@@ -511,7 +483,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
       (void) GNUNET_TIME_round_abs (&now);
       /* This denomination has been revoked */
       GNUNET_JSON_parse_free (spec);
-      GNUNET_free (dc.payto_uri);
       return TEH_RESPONSE_reply_expired_denom_pub_hash (
         connection,
         &deposit.coin.denom_pub_hash,
@@ -528,7 +499,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
     {
       TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
       GNUNET_JSON_parse_free (spec);
-      GNUNET_free (dc.payto_uri);
       return TALER_MHD_reply_with_error (connection,
                                          MHD_HTTP_UNAUTHORIZED,
                                          
TALER_EC_EXCHANGE_DENOMINATION_SIGNATURE_INVALID,
@@ -541,45 +511,31 @@ TEH_handler_deposit (struct MHD_Connection *connection,
   {
     GNUNET_break_op (0);
     GNUNET_JSON_parse_free (spec);
-    GNUNET_free (dc.payto_uri);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE,
                                        NULL);
   }
 
-  /* check deposit signature */
+  if (GNUNET_OK !=
+      TALER_wallet_deposit_verify (&deposit.amount_with_fee,
+                                   &deposit.deposit_fee,
+                                   &dc.h_wire,
+                                   &deposit.h_contract_terms,
+                                   NULL /* h_extensions! */,
+                                   &deposit.coin.denom_pub_hash,
+                                   deposit.timestamp,
+                                   &deposit.merchant_pub,
+                                   deposit.refund_deadline,
+                                   &deposit.coin.coin_pub,
+                                   &deposit.csig))
   {
-    struct TALER_DepositRequestPS dr = {
-      .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
-      .purpose.size = htonl (sizeof (dr)),
-      .h_contract_terms = deposit.h_contract_terms,
-      .h_wire = deposit.h_wire,
-      .h_denom_pub = deposit.coin.denom_pub_hash,
-      .wallet_timestamp = GNUNET_TIME_absolute_hton (deposit.timestamp),
-      .refund_deadline = GNUNET_TIME_absolute_hton (deposit.refund_deadline),
-      .merchant = deposit.merchant_pub,
-      .coin_pub = deposit.coin.coin_pub
-    };
-
-    TALER_amount_hton (&dr.amount_with_fee,
-                       &deposit.amount_with_fee);
-    TALER_amount_hton (&dr.deposit_fee,
-                       &deposit.deposit_fee);
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
-                                    &dr,
-                                    &deposit.csig.eddsa_signature,
-                                    &deposit.coin.coin_pub.eddsa_pub))
-    {
-      TALER_LOG_WARNING ("Invalid signature on /deposit request\n");
-      GNUNET_JSON_parse_free (spec);
-      GNUNET_free (dc.payto_uri);
-      return TALER_MHD_reply_with_error (connection,
-                                         MHD_HTTP_UNAUTHORIZED,
-                                         
TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID,
-                                         NULL);
-    }
+    TALER_LOG_WARNING ("Invalid signature on /deposit request\n");
+    GNUNET_JSON_parse_free (spec);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_UNAUTHORIZED,
+                                       
TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID,
+                                       NULL);
   }
 
   /* execute transaction */
@@ -594,11 +550,9 @@ TEH_handler_deposit (struct MHD_Connection *connection,
                                 &dc))
     {
       GNUNET_JSON_parse_free (spec);
-      GNUNET_free (dc.payto_uri);
       return mhd_ret;
     }
   }
-  GNUNET_free (dc.payto_uri);
 
   /* generate regular response */
   {
@@ -611,10 +565,12 @@ TEH_handler_deposit (struct MHD_Connection *connection,
                                           &deposit.deposit_fee));
     res = reply_deposit_success (connection,
                                  &deposit.coin.coin_pub,
-                                 &deposit.h_wire,
+                                 &dc.h_wire,
+                                 NULL /* h_extensions! */,
                                  &deposit.h_contract_terms,
                                  dc.exchange_timestamp,
                                  deposit.refund_deadline,
+                                 deposit.wire_deadline,
                                  &deposit.merchant_pub,
                                  &amount_without_fee);
     GNUNET_JSON_parse_free (spec);
diff --git a/src/exchange/taler-exchange-httpd_deposits_get.c 
b/src/exchange/taler-exchange-httpd_deposits_get.c
index 2423cc96..d981a8dd 100644
--- a/src/exchange/taler-exchange-httpd_deposits_get.c
+++ b/src/exchange/taler-exchange-httpd_deposits_get.c
@@ -47,8 +47,8 @@
  */
 static MHD_RESULT
 reply_deposit_details (struct MHD_Connection *connection,
-                       const struct GNUNET_HashCode *h_contract_terms,
-                       const struct GNUNET_HashCode *h_wire,
+                       const struct TALER_PrivateContractHash 
*h_contract_terms,
+                       const struct TALER_MerchantWireHash *h_wire,
                        const struct TALER_CoinSpendPublicKeyP *coin_pub,
                        const struct TALER_Amount *coin_contribution,
                        const struct TALER_WireTransferIdentifierRawP *wtid,
diff --git a/src/exchange/taler-exchange-httpd_keys.c 
b/src/exchange/taler-exchange-httpd_keys.c
index 41c664b3..e094f273 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -50,7 +50,7 @@
  * #TALER_PROTOCOL_CURRENT and #TALER_PROTOCOL_AGE in
  * exchange_api_handle.c!
  */
-#define EXCHANGE_PROTOCOL_VERSION "9:0:0"
+#define EXCHANGE_PROTOCOL_VERSION "10:0:0"
 
 
 /**
@@ -73,7 +73,7 @@ struct HelperDenomination
   /**
    * Hash of the denomination key.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Signature over this key from the security module's key.
@@ -549,7 +549,7 @@ free_denom_cb (void *cls,
 
   (void) cls;
   (void) h_denom_pub;
-  GNUNET_CRYPTO_rsa_public_key_free (hd->denom_pub.rsa_public_key);
+  TALER_denom_pub_free (&hd->denom_pub);
   GNUNET_free (hd->section_name);
   GNUNET_free (hd);
   return GNUNET_OK;
@@ -635,7 +635,7 @@ helper_denom_cb (
   const char *section_name,
   struct GNUNET_TIME_Absolute start_time,
   struct GNUNET_TIME_Relative validity_duration,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_SecurityModulePublicKeyP *sm_pub,
   const struct TALER_SecurityModuleSignatureP *sm_sig)
@@ -645,14 +645,14 @@ helper_denom_cb (
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "RSA helper announces key %s for denomination type %s with 
validity %s\n",
-              GNUNET_h2s (h_denom_pub),
+              GNUNET_h2s (&h_denom_pub->hash),
               section_name,
               GNUNET_STRINGS_relative_time_to_string (validity_duration,
                                                       GNUNET_NO));
   key_generation++;
   TEH_resume_keys_requests (false);
   hd = GNUNET_CONTAINER_multihashmap_get (hs->denom_keys,
-                                          h_denom_pub);
+                                          &h_denom_pub->hash);
   if (NULL != hd)
   {
     /* should be just an update (revocation!), so update existing entry */
@@ -666,14 +666,14 @@ helper_denom_cb (
   hd->validity_duration = validity_duration;
   hd->h_denom_pub = *h_denom_pub;
   hd->sm_sig = *sm_sig;
-  hd->denom_pub.rsa_public_key
-    = GNUNET_CRYPTO_rsa_public_key_dup (denom_pub->rsa_public_key);
+  TALER_denom_pub_deep_copy (&hd->denom_pub,
+                             denom_pub);
   hd->section_name = GNUNET_strdup (section_name);
   GNUNET_assert (
     GNUNET_OK ==
     GNUNET_CONTAINER_multihashmap_put (
       hs->denom_keys,
-      &hd->h_denom_pub,
+      &hd->h_denom_pub.hash,
       hd,
       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 }
@@ -806,7 +806,7 @@ clear_denomination_cb (void *cls,
 
   (void) cls;
   (void) h_denom_pub;
-  GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub.rsa_public_key);
+  TALER_denom_pub_free (&dk->denom_pub);
   while (NULL != (as = dk->as_head))
   {
     GNUNET_CONTAINER_DLL_remove (dk->as_head,
@@ -964,7 +964,7 @@ static void
 denomination_info_cb (
   void *cls,
   const struct TALER_DenominationPublicKey *denom_pub,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
   const struct TALER_MasterSignatureP *master_sig,
   bool recoup_possible)
@@ -979,12 +979,12 @@ denomination_info_cb (
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Database contains invalid denomination key %s\n",
-                GNUNET_h2s (h_denom_pub));
+                GNUNET_h2s (&h_denom_pub->hash));
     return;
   }
   dk = GNUNET_new (struct TEH_DenominationKey);
-  dk->denom_pub.rsa_public_key
-    = GNUNET_CRYPTO_rsa_public_key_dup (denom_pub->rsa_public_key);
+  TALER_denom_pub_deep_copy (&dk->denom_pub,
+                             denom_pub);
   dk->h_denom_pub = *h_denom_pub;
   dk->meta = *meta;
   dk->master_sig = *master_sig;
@@ -992,7 +992,7 @@ denomination_info_cb (
   GNUNET_assert (
     GNUNET_OK ==
     GNUNET_CONTAINER_multihashmap_put (ksh->denomkey_map,
-                                       &dk->h_denom_pub,
+                                       &dk->h_denom_pub.hash,
                                        dk,
                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 }
@@ -1138,7 +1138,7 @@ static void
 auditor_denom_cb (
   void *cls,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_AuditorSignatureP *auditor_sig)
 {
   struct TEH_KeyStateHandle *ksh = cls;
@@ -1146,7 +1146,7 @@ auditor_denom_cb (
   struct TEH_AuditorSignature *as;
 
   dk = GNUNET_CONTAINER_multihashmap_get (ksh->denomkey_map,
-                                          h_denom_pub);
+                                          &h_denom_pub->hash);
   if (NULL == dk)
   {
     /* Odd, this should be impossible as per foreign key
@@ -1638,8 +1638,8 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
                                        dk->meta.expire_deposit),
             GNUNET_JSON_pack_time_abs ("stamp_expire_legal",
                                        dk->meta.expire_legal),
-            GNUNET_JSON_pack_rsa_public_key ("denom_pub",
-                                             dk->denom_pub.rsa_public_key),
+            TALER_JSON_pack_denom_pub ("denom_pub",
+                                       &dk->denom_pub),
             TALER_JSON_pack_amount ("value",
                                     &dk->meta.value),
             TALER_JSON_pack_amount ("fee_withdraw",
@@ -1874,7 +1874,7 @@ TEH_keys_get_state (void)
 
 
 struct TEH_DenominationKey *
-TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
+TEH_keys_denomination_by_hash (const struct TALER_DenominationHash 
*h_denom_pub,
                                struct MHD_Connection *conn,
                                MHD_RESULT *mret)
 {
@@ -1897,15 +1897,16 @@ TEH_keys_denomination_by_hash (const struct 
GNUNET_HashCode *h_denom_pub,
 
 
 struct TEH_DenominationKey *
-TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
-                                const struct GNUNET_HashCode *h_denom_pub,
-                                struct MHD_Connection *conn,
-                                MHD_RESULT *mret)
+TEH_keys_denomination_by_hash2 (
+  struct TEH_KeyStateHandle *ksh,
+  const struct TALER_DenominationHash *h_denom_pub,
+  struct MHD_Connection *conn,
+  MHD_RESULT *mret)
 {
   struct TEH_DenominationKey *dk;
 
   dk = GNUNET_CONTAINER_multihashmap_get (ksh->denomkey_map,
-                                          h_denom_pub);
+                                          &h_denom_pub->hash);
   if (NULL == dk)
   {
     *mret = TEH_RESPONSE_reply_unknown_denom_pub_hash (conn,
@@ -1916,15 +1917,18 @@ TEH_keys_denomination_by_hash2 (struct 
TEH_KeyStateHandle *ksh,
 }
 
 
-struct TALER_DenominationSignature
-TEH_keys_denomination_sign (const struct GNUNET_HashCode *h_denom_pub,
+struct TALER_BlindedDenominationSignature
+TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
                             const void *msg,
                             size_t msg_size,
                             enum TALER_ErrorCode *ec)
 {
   struct TEH_KeyStateHandle *ksh;
-  struct TALER_DenominationSignature none = { NULL };
+  struct TALER_BlindedDenominationSignature none;
 
+  memset (&none,
+          0,
+          sizeof (none));
   ksh = TEH_keys_get_state ();
   if (NULL == ksh)
   {
@@ -1940,7 +1944,7 @@ TEH_keys_denomination_sign (const struct GNUNET_HashCode 
*h_denom_pub,
 
 
 void
-TEH_keys_denomination_revoke (const struct GNUNET_HashCode *h_denom_pub)
+TEH_keys_denomination_revoke (const struct TALER_DenominationHash *h_denom_pub)
 {
   struct TEH_KeyStateHandle *ksh;
 
@@ -2283,7 +2287,7 @@ load_fees (const char *section_name,
 
 
 enum GNUNET_GenericReturnValue
-TEH_keys_load_fees (const struct GNUNET_HashCode *h_denom_pub,
+TEH_keys_load_fees (const struct TALER_DenominationHash *h_denom_pub,
                     struct TALER_DenominationPublicKey *denom_pub,
                     struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
 {
@@ -2299,12 +2303,12 @@ TEH_keys_load_fees (const struct GNUNET_HashCode 
*h_denom_pub,
   }
 
   hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys,
-                                          h_denom_pub);
+                                          &h_denom_pub->hash);
   if (NULL == hd)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Denomination %s not known\n",
-                GNUNET_h2s (h_denom_pub));
+                GNUNET_h2s (&h_denom_pub->hash));
     return GNUNET_NO;
   }
   meta->start = hd->start_time;
@@ -2313,15 +2317,17 @@ TEH_keys_load_fees (const struct GNUNET_HashCode 
*h_denom_pub,
   ok = load_fees (hd->section_name,
                   meta);
   if (GNUNET_OK == ok)
-    denom_pub->rsa_public_key
-      = GNUNET_CRYPTO_rsa_public_key_dup (hd->denom_pub.rsa_public_key);
+    TALER_denom_pub_deep_copy (denom_pub,
+                               &hd->denom_pub);
   else
-    denom_pub->rsa_public_key = NULL;
+    memset (denom_pub,
+            0,
+            sizeof (*denom_pub));
   return ok;
 }
 
 
-int
+enum GNUNET_GenericReturnValue
 TEH_keys_get_timing (const struct TALER_ExchangePublicKeyP *exchange_pub,
                      struct TALER_EXCHANGEDB_SignkeyMetaData *meta)
 {
@@ -2423,8 +2429,8 @@ add_future_denomkey_cb (void *cls,
                                    meta.expire_deposit),
         GNUNET_JSON_pack_time_abs ("stamp_expire_legal",
                                    meta.expire_legal),
-        GNUNET_JSON_pack_rsa_public_key ("denom_pub",
-                                         hd->denom_pub.rsa_public_key),
+        TALER_JSON_pack_denom_pub ("denom_pub",
+                                   &hd->denom_pub),
         TALER_JSON_pack_amount ("fee_withdraw",
                                 &meta.fee_withdraw),
         TALER_JSON_pack_amount ("fee_deposit",
diff --git a/src/exchange/taler-exchange-httpd_keys.h 
b/src/exchange/taler-exchange-httpd_keys.h
index ce5e2b73..9ad0c6a3 100644
--- a/src/exchange/taler-exchange-httpd_keys.h
+++ b/src/exchange/taler-exchange-httpd_keys.h
@@ -50,7 +50,7 @@ struct TEH_DenominationKey
   /**
    * Hash code of the denomination public key.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Meta data about the type of the denomination, such as fees and validity
@@ -135,7 +135,7 @@ TEH_keys_update_states (void);
  *         or NULL if @a h_denom_pub could not be found
  */
 struct TEH_DenominationKey *
-TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
+TEH_keys_denomination_by_hash (const struct TALER_DenominationHash 
*h_denom_pub,
                                struct MHD_Connection *conn,
                                MHD_RESULT *mret);
 
@@ -155,7 +155,8 @@ TEH_keys_denomination_by_hash (const struct GNUNET_HashCode 
*h_denom_pub,
  */
 struct TEH_DenominationKey *
 TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
-                                const struct GNUNET_HashCode *h_denom_pub,
+                                const struct
+                                TALER_DenominationHash *h_denom_pub,
                                 struct MHD_Connection *conn,
                                 MHD_RESULT *mret);
 
@@ -170,8 +171,8 @@ TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle 
*ksh,
  * @return signature, the value inside the structure will be NULL on failure,
  *         see @a ec for details about the failure
  */
-struct TALER_DenominationSignature
-TEH_keys_denomination_sign (const struct GNUNET_HashCode *h_denom_pub,
+struct TALER_BlindedDenominationSignature
+TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
                             const void *msg,
                             size_t msg_size,
                             enum TALER_ErrorCode *ec);
@@ -189,7 +190,7 @@ TEH_keys_denomination_sign (const struct GNUNET_HashCode 
*h_denom_pub,
  * @param h_denom_pub hash of the public key to revoke
  */
 void
-TEH_keys_denomination_revoke (const struct GNUNET_HashCode *h_denom_pub);
+TEH_keys_denomination_revoke (const struct TALER_DenominationHash 
*h_denom_pub);
 
 
 /**
@@ -366,7 +367,7 @@ TEH_keys_management_get_keys_handler (const struct 
TEH_RequestHandler *rh,
  *         #GNUNET_SYSERR on hard errors
  */
 enum GNUNET_GenericReturnValue
-TEH_keys_load_fees (const struct GNUNET_HashCode *h_denom_pub,
+TEH_keys_load_fees (const struct TALER_DenominationHash *h_denom_pub,
                     struct TALER_DenominationPublicKey *denom_pub,
                     struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta);
 
@@ -378,7 +379,7 @@ TEH_keys_load_fees (const struct GNUNET_HashCode 
*h_denom_pub,
  * @param[out] meta set to meta data about the key
  * @return #GNUNET_OK on success
  */
-int
+enum GNUNET_GenericReturnValue
 TEH_keys_get_timing (const struct TALER_ExchangePublicKeyP *exchange_pub,
                      struct TALER_EXCHANGEDB_SignkeyMetaData *meta);
 
diff --git a/src/exchange/taler-exchange-httpd_kyc-check.c 
b/src/exchange/taler-exchange-httpd_kyc-check.c
index ae1ab34f..69798a56 100644
--- a/src/exchange/taler-exchange-httpd_kyc-check.c
+++ b/src/exchange/taler-exchange-httpd_kyc-check.c
@@ -27,16 +27,38 @@
 #include "taler_json_lib.h"
 #include "taler_mhd_lib.h"
 #include "taler_signatures.h"
+#include "taler_dbevents.h"
 #include "taler-exchange-httpd_keys.h"
 #include "taler-exchange-httpd_kyc-wallet.h"
 #include "taler-exchange-httpd_responses.h"
 
 
 /**
- * Context for the request.
+ * Reserve GET request that is long-polling.
  */
-struct KycCheckContext
+struct KycPoller
 {
+  /**
+   * Kept in a DLL.
+   */
+  struct KycPoller *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct KycPoller *prev;
+
+  /**
+   * Connection we are handling.
+   */
+  struct MHD_Connection *connection;
+
+  /**
+   * Subscription for the database event we are
+   * waiting for.
+   */
+  struct GNUNET_DB_EventHandler *eh;
+
   /**
    * UUID being checked.
    */
@@ -51,10 +73,80 @@ struct KycCheckContext
    * Hash of the payto:// URI we are confirming to
    * have finished the KYC for.
    */
-  struct GNUNET_HashCode h_payto;
+  struct TALER_PaytoHash h_payto;
+
+  /**
+   * Hash of the payto:// URI that was given to us for auth.
+   */
+  struct TALER_PaytoHash auth_h_payto;
+
+  /**
+   * When will this request time out?
+   */
+  struct GNUNET_TIME_Absolute timeout;
+
+  /**
+   * True if we are still suspended.
+   */
+  bool suspended;
+
 };
 
 
+/**
+ * Head of list of requests in long polling.
+ */
+static struct KycPoller *kyp_head;
+
+/**
+ * Tail of list of requests in long polling.
+ */
+static struct KycPoller *kyp_tail;
+
+
+void
+TEH_kyc_check_cleanup ()
+{
+  struct KycPoller *kyp;
+
+  while (NULL != (kyp = kyp_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (kyp_head,
+                                 kyp_tail,
+                                 kyp);
+    if (kyp->suspended)
+    {
+      kyp->suspended = false;
+      MHD_resume_connection (kyp->connection);
+    }
+  }
+}
+
+
+/**
+ * Function called once a connection is done to
+ * clean up the `struct ReservePoller` state.
+ *
+ * @param rc context to clean up for
+ */
+static void
+kyp_cleanup (struct TEH_RequestContext *rc)
+{
+  struct KycPoller *kyp = rc->rh_ctx;
+
+  GNUNET_assert (! kyp->suspended);
+  if (NULL != kyp->eh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Cancelling DB event listening\n");
+    TEH_plugin->event_listen_cancel (TEH_plugin->cls,
+                                     kyp->eh);
+    kyp->eh = NULL;
+  }
+  GNUNET_free (kyp);
+}
+
+
 /**
  * Function implementing database transaction to check wallet's KYC status.
  * Runs the transaction logic; IF it returns a non-error code, the transaction
@@ -63,7 +155,7 @@ struct KycCheckContext
  * returns the soft error code, the function MAY be called again to retry and
  * MUST not queue a MHD response.
  *
- * @param cls closure with a `struct KycCheckContext *`
+ * @param cls closure with a `struct KycPoller *`
  * @param connection MHD request which triggered the transaction
  * @param[out] mhd_ret set to MHD response status for @a connection,
  *             if transaction failed (!)
@@ -74,13 +166,13 @@ kyc_check (void *cls,
            struct MHD_Connection *connection,
            MHD_RESULT *mhd_ret)
 {
-  struct KycCheckContext *kcc = cls;
+  struct KycPoller *kyp = cls;
   enum GNUNET_DB_QueryStatus qs;
 
   qs = TEH_plugin->select_kyc_status (TEH_plugin->cls,
-                                      kcc->payment_target_uuid,
-                                      &kcc->h_payto,
-                                      &kcc->kyc);
+                                      kyp->payment_target_uuid,
+                                      &kyp->h_payto,
+                                      &kyp->kyc);
   if (qs < 0)
   {
     if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -96,27 +188,132 @@ kyc_check (void *cls,
 }
 
 
+/**
+ * Function called on events received from Postgres.
+ * Wakes up long pollers.
+ *
+ * @param cls the `struct TEH_RequestContext *`
+ * @param extra additional event data provided
+ * @param extra_size number of bytes in @a extra
+ */
+static void
+db_event_cb (void *cls,
+             const void *extra,
+             size_t extra_size)
+{
+  struct TEH_RequestContext *rc = cls;
+  struct KycPoller *kyp = rc->rh_ctx;
+  struct GNUNET_AsyncScopeSave old_scope;
+
+  (void) extra;
+  (void) extra_size;
+  if (! kyp->suspended)
+    return; /* event triggered while main transaction
+               was still running, or got multiple wake-up events */
+  kyp->suspended = false;
+  GNUNET_async_scope_enter (&rc->async_scope_id,
+                            &old_scope);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Resuming from long-polling on KYC status\n");
+  GNUNET_CONTAINER_DLL_remove (kyp_head,
+                               kyp_tail,
+                               kyp);
+  MHD_resume_connection (kyp->connection);
+  TALER_MHD_daemon_trigger ();
+  GNUNET_async_scope_restore (&old_scope);
+}
+
+
 MHD_RESULT
 TEH_handler_kyc_check (
   struct TEH_RequestContext *rc,
   const char *const args[])
 {
-  unsigned long long payment_target_uuid;
+  struct KycPoller *kyp = rc->rh_ctx;
   MHD_RESULT res;
   enum GNUNET_GenericReturnValue ret;
-  char dummy;
+  struct GNUNET_TIME_Absolute now;
 
-  if (1 !=
-      sscanf (args[0],
-              "%llu%c",
-              &payment_target_uuid,
-              &dummy))
+  if (NULL == kyp)
   {
-    GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (rc->connection,
-                                       MHD_HTTP_BAD_REQUEST,
-                                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
-                                       "payment_target_uuid");
+    kyp = GNUNET_new (struct KycPoller);
+    kyp->connection = rc->connection;
+    rc->rh_ctx = kyp;
+    rc->rh_cleaner = &kyp_cleanup;
+
+    {
+      unsigned long long payment_target_uuid;
+      char dummy;
+
+      if (1 !=
+          sscanf (args[0],
+                  "%llu%c",
+                  &payment_target_uuid,
+                  &dummy))
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (rc->connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           
TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                           "payment_target_uuid");
+      }
+      kyp->payment_target_uuid = (uint64_t) payment_target_uuid;
+    }
+    {
+      const char *ts;
+
+      ts = MHD_lookup_connection_value (rc->connection,
+                                        MHD_GET_ARGUMENT_KIND,
+                                        "timeout_ms");
+      if (NULL != ts)
+      {
+        char dummy;
+        unsigned long long tms;
+
+        if (1 !=
+            sscanf (ts,
+                    "%llu%c",
+                    &tms,
+                    &dummy))
+        {
+          GNUNET_break_op (0);
+          return TALER_MHD_reply_with_error (rc->connection,
+                                             MHD_HTTP_BAD_REQUEST,
+                                             
TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                             "timeout_ms");
+        }
+        kyp->timeout = GNUNET_TIME_relative_to_absolute (
+          GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+                                         tms));
+      }
+    }
+    {
+      const char *hps;
+
+      hps = MHD_lookup_connection_value (rc->connection,
+                                         MHD_GET_ARGUMENT_KIND,
+                                         "h_payto");
+      if (NULL == hps)
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (rc->connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           TALER_EC_GENERIC_PARAMETER_MISSING,
+                                           "h_payto");
+      }
+      if (GNUNET_OK !=
+          GNUNET_STRINGS_string_to_data (hps,
+                                         strlen (hps),
+                                         &kyp->auth_h_payto,
+                                         sizeof (kyp->auth_h_payto)))
+      {
+        GNUNET_break_op (0);
+        return TALER_MHD_reply_with_error (rc->connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           
TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                                           "h_payto");
+      }
+    }
   }
 
   if (TEH_KYC_NONE == TEH_kyc_config.mode)
@@ -126,80 +323,120 @@ TEH_handler_kyc_check (
       NULL,
       NULL,
       0);
+
+  if ( (NULL == kyp->eh) &&
+       GNUNET_TIME_absolute_is_future (kyp->timeout) )
   {
-    struct GNUNET_TIME_Absolute now;
-    struct KycCheckContext kcc = {
-      .payment_target_uuid = payment_target_uuid
+    struct TALER_KycCompletedEventP rep = {
+      .header.size = htons (sizeof (rep)),
+      .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
+      .h_payto = kyp->auth_h_payto
     };
 
-    now = GNUNET_TIME_absolute_get ();
-    (void) GNUNET_TIME_round_abs (&now);
-    ret = TEH_DB_run_transaction (rc->connection,
-                                  "kyc check",
-                                  &res,
-                                  &kyc_check,
-                                  &kcc);
-    if (GNUNET_SYSERR == ret)
-      return res;
-    if (! kcc.kyc.ok)
-    {
-      char *url;
-      char *redirect_uri;
-      char *redirect_uri_encoded;
-
-      GNUNET_assert (TEH_KYC_OAUTH2 == TEH_kyc_config.mode);
-      GNUNET_asprintf (&redirect_uri,
-                       "%s/kyc-proof/%llu",
-                       TEH_base_url,
-                       payment_target_uuid);
-      redirect_uri_encoded = TALER_urlencode (redirect_uri);
-      GNUNET_free (redirect_uri);
-      GNUNET_asprintf (&url,
-                       "%s/login?client_id=%s&redirect_uri=%s",
-                       TEH_kyc_config.details.oauth2.url,
-                       TEH_kyc_config.details.oauth2.client_id,
-                       redirect_uri_encoded);
-      GNUNET_free (redirect_uri_encoded);
-
-      res = TALER_MHD_REPLY_JSON_PACK (
-        rc->connection,
-        MHD_HTTP_ACCEPTED,
-        GNUNET_JSON_pack_string ("kyc_url",
-                                 url));
-      GNUNET_free (url);
-      return res;
-    }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Starting DB event listening\n");
+    kyp->eh = TEH_plugin->event_listen (
+      TEH_plugin->cls,
+      GNUNET_TIME_absolute_get_remaining (kyp->timeout),
+      &rep.header,
+      &db_event_cb,
+      rc);
+  }
+
+  now = GNUNET_TIME_absolute_get ();
+  (void) GNUNET_TIME_round_abs (&now);
+  ret = TEH_DB_run_transaction (rc->connection,
+                                "kyc check",
+                                &res,
+                                &kyc_check,
+                                kyp);
+  if (GNUNET_SYSERR == ret)
+    return res;
+  if (0 !=
+      GNUNET_memcmp (&kyp->h_payto,
+                     &kyp->auth_h_payto))
+  {
+    GNUNET_break_op (0);
+    return TALER_MHD_reply_with_error (rc->connection,
+                                       MHD_HTTP_UNAUTHORIZED,
+                                       
TALER_EC_EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED,
+                                       "h_payto");
+  }
+
+  /* long polling? */
+  if ( (! kyp->kyc.ok) &&
+       GNUNET_TIME_absolute_is_future (kyp->timeout))
+  {
+    GNUNET_assert (NULL != kyp->eh);
+    kyp->suspended = true;
+    GNUNET_CONTAINER_DLL_insert (kyp_head,
+                                 kyp_tail,
+                                 kyp);
+    MHD_suspend_connection (kyp->connection);
+    return MHD_YES;
+  }
+
+  /* KYC failed? */
+  if (! kyp->kyc.ok)
+  {
+    char *url;
+    char *redirect_uri;
+    char *redirect_uri_encoded;
+
+    GNUNET_assert (TEH_KYC_OAUTH2 == TEH_kyc_config.mode);
+    GNUNET_asprintf (&redirect_uri,
+                     "%s/kyc-proof/%llu",
+                     TEH_base_url,
+                     (unsigned long long) kyp->payment_target_uuid);
+    redirect_uri_encoded = TALER_urlencode (redirect_uri);
+    GNUNET_free (redirect_uri);
+    GNUNET_asprintf (&url,
+                     "%s/login?client_id=%s&redirect_uri=%s",
+                     TEH_kyc_config.details.oauth2.url,
+                     TEH_kyc_config.details.oauth2.client_id,
+                     redirect_uri_encoded);
+    GNUNET_free (redirect_uri_encoded);
+
+    res = TALER_MHD_REPLY_JSON_PACK (
+      rc->connection,
+      MHD_HTTP_ACCEPTED,
+      GNUNET_JSON_pack_string ("kyc_url",
+                               url));
+    GNUNET_free (url);
+    return res;
+  }
+
+  /* KYC succeeded! */
+  {
+    struct TALER_ExchangePublicKeyP pub;
+    struct TALER_ExchangeSignatureP sig;
+    struct TALER_ExchangeAccountSetupSuccessPS as = {
+      .purpose.purpose = htonl (
+        TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
+      .purpose.size = htonl (sizeof (as)),
+      .h_payto = kyp->h_payto,
+      .timestamp = GNUNET_TIME_absolute_hton (now)
+    };
+    enum TALER_ErrorCode ec;
+
+    if (TALER_EC_NONE !=
+        (ec = TEH_keys_exchange_sign (&as,
+                                      &pub,
+                                      &sig)))
     {
-      struct TALER_ExchangePublicKeyP pub;
-      struct TALER_ExchangeSignatureP sig;
-      struct TALER_ExchangeAccountSetupSuccessPS as = {
-        .purpose.purpose = htonl (
-          TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
-        .purpose.size = htonl (sizeof (as)),
-        .h_payto = kcc.h_payto,
-        .timestamp = GNUNET_TIME_absolute_hton (now)
-      };
-      enum TALER_ErrorCode ec;
-
-      if (TALER_EC_NONE !=
-          (ec = TEH_keys_exchange_sign (&as,
-                                        &pub,
-                                        &sig)))
-      {
-        return TALER_MHD_reply_with_ec (rc->connection,
-                                        ec,
-                                        NULL);
-      }
-      return TALER_MHD_REPLY_JSON_PACK (
-        rc->connection,
-        MHD_HTTP_OK,
-        GNUNET_JSON_pack_data_auto ("exchange_sig",
-                                    &sig),
-        GNUNET_JSON_pack_data_auto ("exchange_pub",
-                                    &pub),
-        GNUNET_JSON_pack_time_abs ("now",
-                                   now));
+      return TALER_MHD_reply_with_ec (rc->connection,
+                                      ec,
+                                      NULL);
     }
+    return TALER_MHD_REPLY_JSON_PACK (
+      rc->connection,
+      MHD_HTTP_OK,
+      GNUNET_JSON_pack_data_auto ("exchange_sig",
+                                  &sig),
+      GNUNET_JSON_pack_data_auto ("exchange_pub",
+                                  &pub),
+      GNUNET_JSON_pack_time_abs ("now",
+                                 now));
   }
 }
 
diff --git a/src/exchange/taler-exchange-httpd_kyc-check.h 
b/src/exchange/taler-exchange-httpd_kyc-check.h
index 8120a173..52fe5f16 100644
--- a/src/exchange/taler-exchange-httpd_kyc-check.h
+++ b/src/exchange/taler-exchange-httpd_kyc-check.h
@@ -39,4 +39,11 @@ TEH_handler_kyc_check (
   const char *const args[]);
 
 
+/**
+ * Clean up long-polling KYC requests during shutdown.
+ */
+void
+TEH_kyc_check_cleanup (void);
+
+
 #endif
diff --git a/src/exchange/taler-exchange-httpd_kyc-proof.c 
b/src/exchange/taler-exchange-httpd_kyc-proof.c
index 842e5dfd..6bd98abf 100644
--- a/src/exchange/taler-exchange-httpd_kyc-proof.c
+++ b/src/exchange/taler-exchange-httpd_kyc-proof.c
@@ -72,6 +72,11 @@ struct KycProofContext
    */
   char *post_body;
 
+  /**
+   * User ID extracted from the OAuth 2.0 service, or NULL.
+   */
+  char *id;
+
   /**
    * Payment target this is about.
    */
@@ -108,6 +113,24 @@ static struct KycProofContext *kpc_head;
 static struct KycProofContext *kpc_tail;
 
 
+/**
+ * Resume processing the @a kpc request.
+ *
+ * @param kpc request to resume
+ */
+static void
+kpc_resume (struct KycProofContext *kpc)
+{
+  GNUNET_assert (GNUNET_YES == kpc->suspended);
+  kpc->suspended = GNUNET_NO;
+  GNUNET_CONTAINER_DLL_remove (kpc_head,
+                               kpc_tail,
+                               kpc);
+  MHD_resume_connection (kpc->rc->connection);
+  TALER_MHD_daemon_trigger ();
+}
+
+
 void
 TEH_kyc_proof_cleanup (void)
 {
@@ -120,11 +143,7 @@ TEH_kyc_proof_cleanup (void)
       GNUNET_CURL_job_cancel (kpc->job);
       kpc->job = NULL;
     }
-    GNUNET_CONTAINER_DLL_remove (kpc_head,
-                                 kpc_tail,
-                                 kpc);
-    kpc->suspended = GNUNET_NO;
-    MHD_resume_connection (kpc->rc->connection);
+    kpc_resume (kpc);
   }
 }
 
@@ -149,15 +168,197 @@ persist_kyc_ok (void *cls,
                 MHD_RESULT *mhd_ret)
 {
   struct KycProofContext *kpc = cls;
+  enum GNUNET_DB_QueryStatus qs;
 
-  return TEH_plugin->set_kyc_ok (TEH_plugin->cls,
-                                 kpc->payment_target_uuid);
+  qs = TEH_plugin->set_kyc_ok (TEH_plugin->cls,
+                               kpc->payment_target_uuid,
+                               kpc->id);
+  if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+  {
+    GNUNET_break (0);
+    *mhd_ret = TALER_MHD_reply_with_ec (connection,
+                                        TALER_EC_GENERIC_DB_STORE_FAILED,
+                                        "set_kyc_ok");
+  }
+  return qs;
+}
+
+
+/**
+ * The request for @a kpc failed. We may have gotten a useful error
+ * message in @a j. Generate a failure response.
+ *
+ * @param[in,out] kpc request that failed
+ * @param j reply from the server (or NULL)
+ */
+static void
+handle_error (struct KycProofContext *kpc,
+              const json_t *j)
+{
+  const char *msg;
+  const char *desc;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_string ("error",
+                             &msg),
+    GNUNET_JSON_spec_string ("error_description",
+                             &desc),
+    GNUNET_JSON_spec_end ()
+  };
+
+  {
+    enum GNUNET_GenericReturnValue res;
+    const char *emsg;
+    unsigned int line;
+
+    res = GNUNET_JSON_parse (j,
+                             spec,
+                             &emsg,
+                             &line);
+    if (GNUNET_OK != res)
+    {
+      GNUNET_break_op (0);
+      kpc->response
+        = TALER_MHD_make_error (
+            TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+            "Unexpected response from KYC gateway");
+      kpc->response_code
+        = MHD_HTTP_BAD_GATEWAY;
+      return;
+    }
+  }
+  /* case TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_AUTHORZATION_FAILED,
+     we MAY want to in the future look at the requested content type
+     and possibly respond in JSON if indicated. */
+  {
+    char *reply;
+
+    GNUNET_asprintf (&reply,
+                     
"<html><head><title>%s</title></head><body><h1>%s</h1><p>%s</p></body></html>",
+                     msg,
+                     msg,
+                     desc);
+    kpc->response
+      = MHD_create_response_from_buffer (strlen (reply),
+                                         reply,
+                                         MHD_RESPMEM_MUST_COPY);
+    GNUNET_assert (NULL != kpc->response);
+    GNUNET_free (reply);
+  }
+  kpc->response_code = MHD_HTTP_FORBIDDEN;
+}
+
+
+/**
+ * The request for @a kpc succeeded (presumably).
+ * Parse the user ID and store it in @a kpc (if possible).
+ *
+ * @param[in,out] kpc request that succeeded
+ * @param j reply from the server
+ */
+static void
+parse_success_reply (struct KycProofContext *kpc,
+                     const json_t *j)
+{
+  const char *state;
+  json_t *data;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_string ("status",
+                             &state),
+    GNUNET_JSON_spec_json ("data",
+                           &data),
+    GNUNET_JSON_spec_end ()
+  };
+  enum GNUNET_GenericReturnValue res;
+  const char *emsg;
+  unsigned int line;
+
+  res = GNUNET_JSON_parse (j,
+                           spec,
+                           &emsg,
+                           &line);
+  if (GNUNET_OK != res)
+  {
+    GNUNET_break_op (0);
+    kpc->response
+      = TALER_MHD_make_error (
+          TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+          "Unexpected response from KYC gateway");
+    kpc->response_code
+      = MHD_HTTP_BAD_GATEWAY;
+    return;
+  }
+  if (0 != strcasecmp (state,
+                       "success"))
+  {
+    GNUNET_break_op (0);
+    handle_error (kpc,
+                  j);
+    return;
+  }
+  {
+    const char *id;
+    struct GNUNET_JSON_Specification ispec[] = {
+      GNUNET_JSON_spec_string ("id",
+                               &id),
+      GNUNET_JSON_spec_end ()
+    };
+
+    res = GNUNET_JSON_parse (data,
+                             ispec,
+                             &emsg,
+                             &line);
+    if (GNUNET_OK != res)
+    {
+      GNUNET_break_op (0);
+      kpc->response
+        = TALER_MHD_make_error (
+            TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+            "Unexpected response from KYC gateway");
+      kpc->response_code
+        = MHD_HTTP_BAD_GATEWAY;
+      return;
+    }
+    kpc->id = GNUNET_strdup (id);
+  }
 }
 
 
 /**
  * After we are done with the CURL interaction we
- * need to update our database state.
+ * need to update our database state with the information
+ * retrieved.
+ *
+ * @param cls our `struct KycProofContext`
+ * @param response_code HTTP response code from server, 0 on hard error
+ * @param response in JSON, NULL if response was not in JSON format
+ */
+static void
+handle_curl_fetch_finished (void *cls,
+                            long response_code,
+                            const void *response)
+{
+  struct KycProofContext *kpc = cls;
+  const json_t *j = response;
+
+  kpc->job = NULL;
+  switch (response_code)
+  {
+  case MHD_HTTP_OK:
+    parse_success_reply (kpc,
+                         j);
+    break;
+  default:
+    handle_error (kpc,
+                  j);
+    break;
+  }
+  kpc_resume (kpc);
+}
+
+
+/**
+ * After we are done with the CURL interaction we
+ * need to fetch the user's account details.
  *
  * @param cls our `struct KycProofContext`
  * @param response_code HTTP response code from server, 0 on hard error
@@ -191,6 +392,7 @@ handle_curl_login_finished (void *cls,
                                  &refresh_token),
         GNUNET_JSON_spec_end ()
       };
+      CURL *eh;
 
       {
         enum GNUNET_GenericReturnValue res;
@@ -210,9 +412,7 @@ handle_curl_login_finished (void *cls,
                 "Unexpected response from KYC gateway");
           kpc->response_code
             = MHD_HTTP_BAD_GATEWAY;
-          MHD_resume_connection (kpc->rc->connection);
-          TALER_MHD_daemon_trigger ();
-          return;
+          break;
         }
       }
       if (0 != strcasecmp (token_type,
@@ -225,78 +425,72 @@ handle_curl_login_finished (void *cls,
               "Unexpected token type in response from KYC gateway");
         kpc->response_code
           = MHD_HTTP_BAD_GATEWAY;
-        MHD_resume_connection (kpc->rc->connection);
-        TALER_MHD_daemon_trigger ();
-        return;
+        break;
       }
 
-      /* TODO: Here we might want to keep something to persist in the DB, and
-         possibly use the access_token to download information we should
-         persist; then continue! */
-
-      MHD_resume_connection (kpc->rc->connection);
-      TALER_MHD_daemon_trigger ();
-      return;
-    }
-  default:
-    {
-      const char *msg;
-      const char *desc;
-      struct GNUNET_JSON_Specification spec[] = {
-        GNUNET_JSON_spec_string ("error",
-                                 &msg),
-        GNUNET_JSON_spec_string ("error_description",
-                                 &desc),
-        GNUNET_JSON_spec_end ()
-      };
-
+      /* We guard against a few characters that could
+         conceivably be abused to mess with the HTTP header */
+      if ( (NULL != strchr (access_token,
+                            '\n')) ||
+           (NULL != strchr (access_token,
+                            '\r')) ||
+           (NULL != strchr (access_token,
+                            ' ')) ||
+           (NULL != strchr (access_token,
+                            ';')) )
       {
-        enum GNUNET_GenericReturnValue res;
-        const char *emsg;
-        unsigned int line;
-
-        res = GNUNET_JSON_parse (j,
-                                 spec,
-                                 &emsg,
-                                 &line);
-        if (GNUNET_OK != res)
-        {
-          GNUNET_break_op (0);
-          kpc->response
-            = TALER_MHD_make_error (
-                TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
-                "Unexpected response from KYC gateway");
-          kpc->response_code
-            = MHD_HTTP_BAD_GATEWAY;
-          MHD_resume_connection (kpc->rc->connection);
-          TALER_MHD_daemon_trigger ();
-          return;
-        }
+        GNUNET_break_op (0);
+        kpc->response
+          = TALER_MHD_make_error (
+              TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
+              "Illegal character in access token");
+        kpc->response_code
+          = MHD_HTTP_BAD_GATEWAY;
+        break;
       }
-      /* case TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_AUTHORZATION_FAILED,
-         we MAY want to in the future look at the requested content type
-         and possibly respond in JSON if indicated. */
-      {
-        char *reply;
 
-        GNUNET_asprintf (&reply,
-                         
"<html><head><title>%s</title></head><body><h1>%s</h1><p>%s</p></body></html>",
-                         msg,
-                         msg,
-                         desc);
+      eh = curl_easy_init ();
+      if (NULL == eh)
+      {
+        GNUNET_break_op (0);
         kpc->response
-          = MHD_create_response_from_buffer (strlen (reply),
-                                             reply,
-                                             MHD_RESPMEM_MUST_COPY);
-        GNUNET_assert (NULL != kpc->response);
-        GNUNET_free (reply);
+          = TALER_MHD_make_error (
+              TALER_EC_GENERIC_ALLOCATION_FAILURE,
+              "curl_easy_init");
+        kpc->response_code
+          = MHD_HTTP_INTERNAL_SERVER_ERROR;
+        break;
       }
-      kpc->response_code = MHD_HTTP_FORBIDDEN;
-      MHD_resume_connection (kpc->rc->connection);
-      TALER_MHD_daemon_trigger ();
+      GNUNET_assert (CURLE_OK ==
+                     curl_easy_setopt (eh,
+                                       CURLOPT_URL,
+                                       
TEH_kyc_config.details.oauth2.info_url));
+      {
+        char *hdr;
+        struct curl_slist *slist;
+
+        GNUNET_asprintf (&hdr,
+                         "%s: Bearer %s",
+                         MHD_HTTP_HEADER_AUTHORIZATION,
+                         access_token);
+        slist = curl_slist_append (NULL,
+                                   hdr);
+        kpc->job = GNUNET_CURL_job_add2 (TEH_curl_ctx,
+                                         eh,
+                                         slist,
+                                         &handle_curl_fetch_finished,
+                                         kpc);
+        curl_slist_free_all (slist);
+        GNUNET_free (hdr);
+      }
+      return;
     }
+  default:
+    handle_error (kpc,
+                  j);
     break;
   }
+  kpc_resume (kpc);
 }
 
 
@@ -322,6 +516,7 @@ clean_kpc (struct TEH_RequestContext *rc)
   }
   GNUNET_free (kpc->post_body);
   GNUNET_free (kpc->token_url);
+  GNUNET_free (kpc->id);
   GNUNET_free (kpc);
 }
 
@@ -387,7 +582,7 @@ TEH_handler_kyc_proof (
                                            "curl_easy_init");
       }
       GNUNET_asprintf (&kpc->token_url,
-                       "%s/token",
+                       "%stoken",
                        TEH_kyc_config.details.oauth2.url);
       GNUNET_assert (CURLE_OK ==
                      curl_easy_setopt (eh,
@@ -411,7 +606,7 @@ TEH_handler_kyc_proof (
           char *request_uri;
 
           GNUNET_asprintf (&request_uri,
-                           "%s/login?client_id=%s",
+                           "%slogin?client_id=%s",
                            TEH_kyc_config.details.oauth2.url,
                            TEH_kyc_config.details.oauth2.client_id);
           redirect_uri = curl_easy_escape (eh,
diff --git a/src/exchange/taler-exchange-httpd_link.c 
b/src/exchange/taler-exchange-httpd_link.c
index 75d32e56..3393e068 100644
--- a/src/exchange/taler-exchange-httpd_link.c
+++ b/src/exchange/taler-exchange-httpd_link.c
@@ -82,10 +82,10 @@ handle_link_data (void *cls,
     json_t *obj;
 
     obj = GNUNET_JSON_PACK (
-      GNUNET_JSON_pack_rsa_public_key ("denom_pub",
-                                       pos->denom_pub.rsa_public_key),
-      GNUNET_JSON_pack_rsa_signature ("ev_sig",
-                                      pos->ev_sig.rsa_signature),
+      TALER_JSON_pack_denom_pub ("denom_pub",
+                                 &pos->denom_pub),
+      TALER_JSON_pack_blinded_denom_sig ("ev_sig",
+                                         &pos->ev_sig),
       GNUNET_JSON_pack_data_auto ("link_sig",
                                   &pos->orig_coin_link_sig));
     if ( (NULL == obj) ||
diff --git a/src/exchange/taler-exchange-httpd_management.h 
b/src/exchange/taler-exchange-httpd_management.h
index 3f58083e..d46aad9e 100644
--- a/src/exchange/taler-exchange-httpd_management.h
+++ b/src/exchange/taler-exchange-httpd_management.h
@@ -64,7 +64,7 @@ TEH_handler_management_auditors_AP_disable (
 MHD_RESULT
 TEH_handler_management_denominations_HDP_revoke (
   struct MHD_Connection *connection,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const json_t *root);
 
 
diff --git 
a/src/exchange/taler-exchange-httpd_management_denominations_HDP_revoke.c 
b/src/exchange/taler-exchange-httpd_management_denominations_HDP_revoke.c
index 6519404d..a8acf2f7 100644
--- a/src/exchange/taler-exchange-httpd_management_denominations_HDP_revoke.c
+++ b/src/exchange/taler-exchange-httpd_management_denominations_HDP_revoke.c
@@ -34,7 +34,7 @@
 MHD_RESULT
 TEH_handler_management_denominations_HDP_revoke (
   struct MHD_Connection *connection,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const json_t *root)
 {
   struct TALER_MasterSignatureP master_sig;
diff --git a/src/exchange/taler-exchange-httpd_management_post_keys.c 
b/src/exchange/taler-exchange-httpd_management_post_keys.c
index 311fff78..b8f8922f 100644
--- a/src/exchange/taler-exchange-httpd_management_post_keys.c
+++ b/src/exchange/taler-exchange-httpd_management_post_keys.c
@@ -40,7 +40,7 @@ struct DenomSig
   /**
    * Hash of a denomination public key.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Master signature for the @e h_denom_pub.
@@ -156,14 +156,14 @@ add_keys (void *cls,
           connection,
           MHD_HTTP_INTERNAL_SERVER_ERROR,
           TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
-          GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+          GNUNET_h2s (&akc->d_sigs[i].h_denom_pub.hash));
         return GNUNET_DB_STATUS_HARD_ERROR;
       case GNUNET_NO:
         *mhd_ret = TALER_MHD_reply_with_error (
           connection,
           MHD_HTTP_NOT_FOUND,
           TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
-          GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+          GNUNET_h2s (&akc->d_sigs[i].h_denom_pub.hash));
         return GNUNET_DB_STATUS_HARD_ERROR;
       case GNUNET_OK:
         break;
@@ -196,7 +196,7 @@ add_keys (void *cls,
           connection,
           MHD_HTTP_FORBIDDEN,
           TALER_EC_EXCHANGE_MANAGEMENT_KEYS_DENOMKEY_ADD_SIGNATURE_INVALID,
-          GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+          GNUNET_h2s (&akc->d_sigs[i].h_denom_pub.hash));
         return GNUNET_DB_STATUS_HARD_ERROR;
       }
     }
@@ -208,7 +208,7 @@ add_keys (void *cls,
       &denom_pub,
       &meta,
       &akc->d_sigs[i].master_sig);
-    GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key);
+    TALER_denom_pub_free (&denom_pub);
     if (qs < 0)
     {
       if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -222,7 +222,7 @@ add_keys (void *cls,
     }
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Added offline signature for denomination `%s'\n",
-                GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+                GNUNET_h2s (&akc->d_sigs[i].h_denom_pub.hash));
     GNUNET_assert (0 != qs);
   }
 
@@ -284,7 +284,7 @@ add_keys (void *cls,
           connection,
           MHD_HTTP_FORBIDDEN,
           TALER_EC_EXCHANGE_MANAGEMENT_KEYS_SIGNKEY_ADD_SIGNATURE_INVALID,
-          GNUNET_h2s (&akc->d_sigs[i].h_denom_pub));
+          GNUNET_h2s (&akc->d_sigs[i].h_denom_pub.hash));
         return GNUNET_DB_STATUS_HARD_ERROR;
       }
     }
diff --git a/src/exchange/taler-exchange-httpd_melt.c 
b/src/exchange/taler-exchange-httpd_melt.c
index af0a0a63..c33473b4 100644
--- a/src/exchange/taler-exchange-httpd_melt.c
+++ b/src/exchange/taler-exchange-httpd_melt.c
@@ -494,7 +494,7 @@ check_for_denomination_key (struct MHD_Connection 
*connection,
   if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit))
   {
     /* We are past deposit expiration time, but maybe this is a zombie? */
-    struct GNUNET_HashCode denom_hash;
+    struct TALER_DenominationHash denom_hash;
     enum GNUNET_DB_QueryStatus qs;
 
     /* Check that the coin is dirty (we have seen it before), as we will
@@ -590,8 +590,8 @@ TEH_handler_melt (struct MHD_Connection *connection,
   enum GNUNET_GenericReturnValue ret;
   MHD_RESULT res;
   struct GNUNET_JSON_Specification spec[] = {
-    TALER_JSON_spec_denomination_signature ("denom_sig",
-                                            
&rmc.refresh_session.coin.denom_sig),
+    TALER_JSON_spec_denom_sig ("denom_sig",
+                               &rmc.refresh_session.coin.denom_sig),
     GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
                                  &rmc.refresh_session.coin.denom_pub_hash),
     GNUNET_JSON_spec_fixed_auto ("confirm_sig",
diff --git a/src/exchange/taler-exchange-httpd_recoup.c 
b/src/exchange/taler-exchange-httpd_recoup.c
index 137034a4..b5074ce3 100644
--- a/src/exchange/taler-exchange-httpd_recoup.c
+++ b/src/exchange/taler-exchange-httpd_recoup.c
@@ -41,7 +41,7 @@ struct RecoupContext
   /**
    * Hash of the blinded coin.
    */
-  struct GNUNET_HashCode h_blind;
+  struct TALER_BlindedCoinHash h_blind;
 
   /**
    * Full value of the coin.
@@ -56,7 +56,7 @@ struct RecoupContext
   /**
    * Key used to blind the coin.
    */
-  const struct TALER_DenominationBlindingKeyP *coin_bks;
+  const union TALER_DenominationBlindingKeyP *coin_bks;
 
   /**
    * Signature of the coin requesting recoup.
@@ -179,7 +179,7 @@ recoup_transaction (void *cls,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Recoup requested for unknown envelope %s\n",
-                GNUNET_h2s (&pc->h_blind));
+                GNUNET_h2s (&pc->h_blind.hash));
     *mhd_ret = TALER_MHD_reply_with_error (connection,
                                            MHD_HTTP_NOT_FOUND,
                                            
TALER_EC_EXCHANGE_RECOUP_WITHDRAW_NOT_FOUND,
@@ -342,18 +342,16 @@ recoup_transaction (void *cls,
  * @return MHD result code
  */
 static MHD_RESULT
-verify_and_execute_recoup (struct MHD_Connection *connection,
-                           const struct TALER_CoinPublicInfo *coin,
-                           const struct
-                           TALER_DenominationBlindingKeyP *coin_bks,
-                           const struct TALER_CoinSpendSignatureP *coin_sig,
-                           int refreshed)
+verify_and_execute_recoup (
+  struct MHD_Connection *connection,
+  const struct TALER_CoinPublicInfo *coin,
+  const union TALER_DenominationBlindingKeyP *coin_bks,
+  const struct TALER_CoinSpendSignatureP *coin_sig,
+  int refreshed)
 {
   struct RecoupContext pc;
   const struct TEH_DenominationKey *dk;
-  struct GNUNET_HashCode c_hash;
-  void *coin_ev;
-  size_t coin_ev_size;
+  struct TALER_CoinPubHash c_hash;
   MHD_RESULT mret;
 
   /* check denomination exists and is in recoup mode */
@@ -423,7 +421,7 @@ verify_and_execute_recoup (struct MHD_Connection 
*connection,
   {
     struct TALER_RecoupRequestPS pr = {
       .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
-      .purpose.size = htonl (sizeof (struct TALER_RecoupRequestPS)),
+      .purpose.size = htonl (sizeof (pr)),
       .coin_pub = coin->coin_pub,
       .h_denom_pub = coin->denom_pub_hash,
       .coin_blind = *coin_bks
@@ -442,26 +440,31 @@ verify_and_execute_recoup (struct MHD_Connection 
*connection,
                                          NULL);
     }
   }
-  GNUNET_CRYPTO_hash (&coin->coin_pub.eddsa_pub,
-                      sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
-                      &c_hash);
-  if (GNUNET_YES !=
-      TALER_rsa_blind (&c_hash,
-                       &coin_bks->bks,
-                       dk->denom_pub.rsa_public_key,
-                       &coin_ev,
-                       &coin_ev_size))
+
   {
-    GNUNET_break (0);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                       
TALER_EC_EXCHANGE_RECOUP_BLINDING_FAILED,
-                                       NULL);
+    void *coin_ev;
+    size_t coin_ev_size;
+
+    if (GNUNET_OK !=
+        TALER_denom_blind (&dk->denom_pub,
+                           coin_bks,
+                           NULL, /* FIXME-Oec: TALER_AgeHash * */
+                           &coin->coin_pub,
+                           &c_hash,
+                           &coin_ev,
+                           &coin_ev_size))
+    {
+      GNUNET_break (0);
+      return TALER_MHD_reply_with_error (connection,
+                                         MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                         
TALER_EC_EXCHANGE_RECOUP_BLINDING_FAILED,
+                                         NULL);
+    }
+    TALER_coin_ev_hash (coin_ev,
+                        coin_ev_size,
+                        &pc.h_blind);
+    GNUNET_free (coin_ev);
   }
-  GNUNET_CRYPTO_hash (coin_ev,
-                      coin_ev_size,
-                      &pc.h_blind);
-  GNUNET_free (coin_ev);
 
   /* Perform actual recoup transaction */
   pc.coin_sig = coin_sig;
@@ -516,14 +519,14 @@ TEH_handler_recoup (struct MHD_Connection *connection,
 {
   enum GNUNET_GenericReturnValue ret;
   struct TALER_CoinPublicInfo coin;
-  struct TALER_DenominationBlindingKeyP coin_bks;
+  union TALER_DenominationBlindingKeyP coin_bks;
   struct TALER_CoinSpendSignatureP coin_sig;
   int refreshed = GNUNET_NO;
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
                                  &coin.denom_pub_hash),
-    TALER_JSON_spec_denomination_signature ("denom_sig",
-                                            &coin.denom_sig),
+    TALER_JSON_spec_denom_sig ("denom_sig",
+                               &coin.denom_sig),
     GNUNET_JSON_spec_fixed_auto ("coin_blind_key_secret",
                                  &coin_bks),
     GNUNET_JSON_spec_fixed_auto ("coin_sig",
diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c 
b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
index 4ca6bd15..4ec70313 100644
--- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
@@ -55,7 +55,8 @@
 static MHD_RESULT
 reply_refreshes_reveal_success (struct MHD_Connection *connection,
                                 unsigned int num_freshcoins,
-                                const struct TALER_DenominationSignature *sigs)
+                                const struct
+                                TALER_BlindedDenominationSignature *sigs)
 {
   json_t *list;
 
@@ -68,8 +69,8 @@ reply_refreshes_reveal_success (struct MHD_Connection 
*connection,
     json_t *obj;
 
     obj = GNUNET_JSON_PACK (
-      GNUNET_JSON_pack_rsa_signature ("ev_sig",
-                                      sigs[freshcoin_index].rsa_signature));
+      TALER_JSON_pack_blinded_denom_sig ("ev_sig",
+                                         &sigs[freshcoin_index]));
     GNUNET_assert (0 ==
                    json_array_append_new (list,
                                           obj));
@@ -123,7 +124,7 @@ struct RevealContext
   /**
    * Envelopes with the signatures to be returned.  Initially NULL.
    */
-  struct TALER_DenominationSignature *ev_sigs;
+  struct TALER_BlindedDenominationSignature *ev_sigs;
 
   /**
    * Size of the @e dks, @e rcds and @e ev_sigs arrays (if non-NULL).
@@ -187,10 +188,10 @@ check_exists_cb (void *cls,
   if (NULL == rctx->ev_sigs)
   {
     rctx->ev_sigs = GNUNET_new_array (num_freshcoins,
-                                      struct TALER_DenominationSignature);
+                                      struct 
TALER_BlindedDenominationSignature);
     for (unsigned int i = 0; i<num_freshcoins; i++)
-      rctx->ev_sigs[i].rsa_signature
-        = GNUNET_CRYPTO_rsa_signature_dup (rrcs[i].coin_sig.rsa_signature);
+      TALER_blinded_denom_sig_deep_copy (&rctx->ev_sigs[i],
+                                         &rrcs[i].coin_sig);
   }
 }
 
@@ -334,7 +335,7 @@ refreshes_reveal_transaction (void *cls,
           struct TALER_RefreshCoinData *rcd = &rce->new_coins[j];
           struct TALER_PlanchetSecretsP ps;
           struct TALER_PlanchetDetail pd;
-          struct GNUNET_HashCode c_hash;
+          struct TALER_CoinPubHash c_hash;
 
           rcd->dk = &rctx->dks[j]->denom_pub;
           TALER_planchet_setup_refresh (&ts,
@@ -500,7 +501,7 @@ resolve_refreshes_reveal_denominations (struct 
MHD_Connection *connection,
   unsigned int num_fresh_coins = json_array_size (new_denoms_h_json);
   /* We know num_fresh_coins is bounded by #MAX_FRESH_COINS, so this is safe */
   const struct TEH_DenominationKey *dks[num_fresh_coins];
-  struct GNUNET_HashCode dk_h[num_fresh_coins];
+  struct TALER_DenominationHash dk_h[num_fresh_coins];
   struct TALER_RefreshCoinData rcds[num_fresh_coins];
   struct TALER_CoinSpendSignatureP link_sigs[num_fresh_coins];
   struct TALER_EXCHANGEDB_Melt melt;
@@ -683,10 +684,10 @@ resolve_refreshes_reveal_denominations (struct 
MHD_Connection *connection,
 
   /* sign _early_ (optimistic!) to keep out of transaction scope! */
   rctx->ev_sigs = GNUNET_new_array (rctx->num_fresh_coins,
-                                    struct TALER_DenominationSignature);
+                                    struct TALER_BlindedDenominationSignature);
   for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
   {
-    enum TALER_ErrorCode ec;
+    enum TALER_ErrorCode ec = TALER_EC_NONE;
 
     rctx->ev_sigs[i]
       = TEH_keys_denomination_sign (
@@ -694,7 +695,7 @@ resolve_refreshes_reveal_denominations (struct 
MHD_Connection *connection,
           rctx->rcds[i].coin_ev,
           rctx->rcds[i].coin_ev_size,
           &ec);
-    if (NULL == rctx->ev_sigs[i].rsa_signature)
+    if (TALER_EC_NONE != ec)
     {
       GNUNET_break (0);
       ret = TALER_MHD_reply_with_ec (connection,
@@ -769,8 +770,7 @@ cleanup:
   if (NULL != rctx->ev_sigs)
   {
     for (unsigned int i = 0; i<num_fresh_coins; i++)
-      if (NULL != rctx->ev_sigs[i].rsa_signature)
-        GNUNET_CRYPTO_rsa_signature_free (rctx->ev_sigs[i].rsa_signature);
+      TALER_blinded_denom_sig_free (&rctx->ev_sigs[i]);
     GNUNET_free (rctx->ev_sigs);
     rctx->ev_sigs = NULL; /* just to be safe... */
   }
diff --git a/src/exchange/taler-exchange-httpd_refund.c 
b/src/exchange/taler-exchange-httpd_refund.c
index 73b4b251..be8a88df 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -370,7 +370,7 @@ static MHD_RESULT
 verify_and_execute_refund (struct MHD_Connection *connection,
                            struct TALER_EXCHANGEDB_Refund *refund)
 {
-  struct GNUNET_HashCode denom_hash;
+  struct TALER_DenominationHash denom_hash;
 
   {
     struct TALER_RefundRequestPS rr = {
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index 66da1216..cb1179d6 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -61,30 +61,25 @@ TEH_RESPONSE_compile_transaction_history (
       {
         const struct TALER_EXCHANGEDB_DepositListEntry *deposit =
           pos->details.deposit;
-        struct TALER_DepositRequestPS dr = {
-          .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
-          .purpose.size = htonl (sizeof (dr)),
-          .h_contract_terms = deposit->h_contract_terms,
-          .h_wire = deposit->h_wire,
-          .h_denom_pub = deposit->h_denom_pub,
-          .wallet_timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp),
-          .refund_deadline = GNUNET_TIME_absolute_hton (
-            deposit->refund_deadline),
-          .merchant = deposit->merchant_pub,
-          .coin_pub = *coin_pub
-        };
+        struct TALER_MerchantWireHash h_wire;
 
-        TALER_amount_hton (&dr.amount_with_fee,
-                           &deposit->amount_with_fee);
-        TALER_amount_hton (&dr.deposit_fee,
-                           &deposit->deposit_fee);
+        TALER_merchant_wire_signature_hash (deposit->receiver_wire_account,
+                                            &deposit->wire_salt,
+                                            &h_wire);
 #if ENABLE_SANITY_CHECKS
         /* internal sanity check before we hand out a bogus sig... */
         if (GNUNET_OK !=
-            GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
-                                        &dr,
-                                        &deposit->csig.eddsa_signature,
-                                        &coin_pub->eddsa_pub))
+            TALER_wallet_deposit_verify (&deposit->amount_with_fee,
+                                         &deposit->deposit_fee,
+                                         &h_wire,
+                                         &deposit->h_contract_terms,
+                                         NULL /* h_extensions! */,
+                                         &deposit->h_denom_pub,
+                                         deposit->timestamp,
+                                         &deposit->merchant_pub,
+                                         deposit->refund_deadline,
+                                         coin_pub,
+                                         &deposit->csig))
         {
           GNUNET_break (0);
           json_decref (history);
@@ -111,7 +106,7 @@ TEH_RESPONSE_compile_transaction_history (
                 GNUNET_JSON_pack_data_auto ("h_contract_terms",
                                             &deposit->h_contract_terms),
                 GNUNET_JSON_pack_data_auto ("h_wire",
-                                            &deposit->h_wire),
+                                            &h_wire),
                 GNUNET_JSON_pack_data_auto ("h_denom_pub",
                                             &deposit->h_denom_pub),
                 GNUNET_JSON_pack_data_auto ("coin_sig",
@@ -419,7 +414,7 @@ TEH_RESPONSE_compile_transaction_history (
 MHD_RESULT
 TEH_RESPONSE_reply_unknown_denom_pub_hash (
   struct MHD_Connection *connection,
-  const struct GNUNET_HashCode *dph)
+  const struct TALER_DenominationHash *dph)
 {
   struct TALER_ExchangePublicKeyP epub;
   struct TALER_ExchangeSignatureP esig;
@@ -466,7 +461,7 @@ TEH_RESPONSE_reply_unknown_denom_pub_hash (
 MHD_RESULT
 TEH_RESPONSE_reply_expired_denom_pub_hash (
   struct MHD_Connection *connection,
-  const struct GNUNET_HashCode *dph,
+  const struct TALER_DenominationHash *dph,
   struct GNUNET_TIME_Absolute now,
   enum TALER_ErrorCode ec,
   const char *oper)
@@ -779,9 +774,8 @@ TEH_RESPONSE_compile_reserve_history (
                              &value);
           TALER_amount_hton (&rcc.closing_fee,
                              &closing->closing_fee);
-          GNUNET_CRYPTO_hash (closing->receiver_account_details,
-                              strlen (closing->receiver_account_details) + 1,
-                              &rcc.h_wire);
+          TALER_payto_hash (closing->receiver_account_details,
+                            &rcc.h_payto);
           if (TALER_EC_NONE !=
               TEH_keys_exchange_sign (&rcc,
                                       &pub,
diff --git a/src/exchange/taler-exchange-httpd_responses.h 
b/src/exchange/taler-exchange-httpd_responses.h
index b46e85ce..09d566af 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -59,7 +59,7 @@ TEH_RESPONSE_compile_reserve_history (
 MHD_RESULT
 TEH_RESPONSE_reply_unknown_denom_pub_hash (
   struct MHD_Connection *connection,
-  const struct GNUNET_HashCode *dph);
+  const struct TALER_DenominationHash *dph);
 
 
 /**
@@ -76,7 +76,7 @@ TEH_RESPONSE_reply_unknown_denom_pub_hash (
 MHD_RESULT
 TEH_RESPONSE_reply_expired_denom_pub_hash (
   struct MHD_Connection *connection,
-  const struct GNUNET_HashCode *dph,
+  const struct TALER_DenominationHash *dph,
   struct GNUNET_TIME_Absolute now,
   enum TALER_ErrorCode ec,
   const char *oper);
diff --git a/src/exchange/taler-exchange-httpd_transfers_get.c 
b/src/exchange/taler-exchange-httpd_transfers_get.c
index abf0fdbc..e63acdc2 100644
--- a/src/exchange/taler-exchange-httpd_transfers_get.c
+++ b/src/exchange/taler-exchange-httpd_transfers_get.c
@@ -51,7 +51,7 @@ struct AggregatedDepositDetail
   /**
    * Hash of the contract terms.
    */
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
 
   /**
    * Coin's public key of the deposited coin.
@@ -77,7 +77,7 @@ struct AggregatedDepositDetail
  * @param connection connection to the client
  * @param total total amount that was transferred
  * @param merchant_pub public key of the merchant
- * @param h_wire destination account
+ * @param payto_uri destination account
  * @param wire_fee wire fee that was charged
  * @param exec_time execution time of the wire transfer
  * @param wdd_head linked list with details about the combined deposits
@@ -87,7 +87,7 @@ static MHD_RESULT
 reply_transfer_details (struct MHD_Connection *connection,
                         const struct TALER_Amount *total,
                         const struct TALER_MerchantPublicKeyP *merchant_pub,
-                        const struct GNUNET_HashCode *h_wire,
+                        const char *payto_uri,
                         const struct TALER_Amount *wire_fee,
                         struct GNUNET_TIME_Absolute exec_time,
                         const struct AggregatedDepositDetail *wdd_head)
@@ -145,7 +145,8 @@ reply_transfer_details (struct MHD_Connection *connection,
   TALER_amount_hton (&wdp.wire_fee,
                      wire_fee);
   wdp.merchant_pub = *merchant_pub;
-  wdp.h_wire = *h_wire;
+  TALER_payto_hash (payto_uri,
+                    &wdp.h_payto);
   GNUNET_CRYPTO_hash_context_finish (hash_context,
                                      &wdp.h_details);
   {
@@ -172,8 +173,8 @@ reply_transfer_details (struct MHD_Connection *connection,
                             wire_fee),
     GNUNET_JSON_pack_data_auto ("merchant_pub",
                                 merchant_pub),
-    GNUNET_JSON_pack_data_auto ("h_wire",
-                                h_wire),
+    GNUNET_JSON_pack_data_auto ("h_payto",
+                                &wdp.h_payto),
     GNUNET_JSON_pack_time_abs ("execution_time",
                                exec_time),
     GNUNET_JSON_pack_array_steal ("deposits",
@@ -210,12 +211,6 @@ struct WtidTransactionContext
    */
   struct TALER_MerchantPublicKeyP merchant_pub;
 
-  /**
-   * Hash of the wire details of the merchant (identical for all
-   * deposits), only valid if @e is_valid is #GNUNET_YES.
-   */
-  struct GNUNET_HashCode h_wire;
-
   /**
    * Wire fee applicable at @e exec_time.
    */
@@ -237,9 +232,9 @@ struct WtidTransactionContext
   struct AggregatedDepositDetail *wdd_tail;
 
   /**
-   * Which method was used to wire the funds?
+   * Where were the funds wired?
    */
-  char *wire_method;
+  char *payto_uri;
 
   /**
    * JSON array with details about the individual deposits.
@@ -253,7 +248,7 @@ struct WtidTransactionContext
    * (as they should).  Set to #GNUNET_SYSERR if we encountered an
    * internal error.
    */
-  int is_valid;
+  enum GNUNET_GenericReturnValue is_valid;
 
 };
 
@@ -265,8 +260,7 @@ struct WtidTransactionContext
  * @param cls our context for transmission
  * @param rowid which row in the DB is the information from (for diagnostics), 
ignored
  * @param merchant_pub public key of the merchant (should be same for all 
callbacks with the same @e cls)
- * @param h_wire hash of wire transfer details of the merchant (should be same 
for all callbacks with the same @e cls)
- * @param wire where the funds were sent
+ * @param account_payto_uri where the funds were sent
  * @param exec_time execution time of the wire transfer (should be same for 
all callbacks with the same @e cls)
  * @param h_contract_terms which proposal was this payment about
  * @param denom_pub denomination public key of the @a coin_pub (ignored)
@@ -278,35 +272,26 @@ static void
 handle_deposit_data (void *cls,
                      uint64_t rowid,
                      const struct TALER_MerchantPublicKeyP *merchant_pub,
-                     const struct GNUNET_HashCode *h_wire,
-                     const json_t *wire,
+                     const char *account_payto_uri,
                      struct GNUNET_TIME_Absolute exec_time,
-                     const struct GNUNET_HashCode *h_contract_terms,
+                     const struct TALER_PrivateContractHash *h_contract_terms,
                      const struct TALER_DenominationPublicKey *denom_pub,
                      const struct TALER_CoinSpendPublicKeyP *coin_pub,
                      const struct TALER_Amount *deposit_value,
                      const struct TALER_Amount *deposit_fee)
 {
   struct WtidTransactionContext *ctx = cls;
-  char *wire_method;
 
   (void) rowid;
   (void) denom_pub;
   if (GNUNET_SYSERR == ctx->is_valid)
     return;
-  if (NULL == (wire_method = TALER_JSON_wire_to_method (wire)))
-  {
-    GNUNET_break (0);
-    ctx->is_valid = GNUNET_SYSERR;
-    return;
-  }
   if (GNUNET_NO == ctx->is_valid)
   {
     /* First one we encounter, setup general information in 'ctx' */
     ctx->merchant_pub = *merchant_pub;
-    ctx->h_wire = *h_wire;
+    ctx->payto_uri = GNUNET_strdup (account_payto_uri);
     ctx->exec_time = exec_time;
-    ctx->wire_method = wire_method; /* captures the reference */
     ctx->is_valid = GNUNET_YES;
     if (0 >
         TALER_amount_subtract (&ctx->total,
@@ -326,17 +311,13 @@ handle_deposit_data (void *cls,
        (it should, otherwise the deposits should not have been aggregated) */
     if ( (0 != GNUNET_memcmp (&ctx->merchant_pub,
                               merchant_pub)) ||
-         (0 != strcmp (wire_method,
-                       ctx->wire_method)) ||
-         (0 != GNUNET_memcmp (&ctx->h_wire,
-                              h_wire)) )
+         (0 != strcmp (account_payto_uri,
+                       ctx->payto_uri)) )
     {
       GNUNET_break (0);
       ctx->is_valid = GNUNET_SYSERR;
-      GNUNET_free (wire_method);
       return;
     }
-    GNUNET_free (wire_method);
     if (0 >
         TALER_amount_subtract (&delta,
                                deposit_value,
@@ -389,8 +370,7 @@ free_ctx (struct WtidTransactionContext *ctx)
                                  wdd);
     GNUNET_free (wdd);
   }
-  GNUNET_free (ctx->wire_method);
-  ctx->wire_method = NULL;
+  GNUNET_free (ctx->payto_uri);
 }
 
 
@@ -458,14 +438,29 @@ get_transfer_deposits (void *cls,
                                            NULL);
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  qs = TEH_plugin->get_wire_fee (TEH_plugin->cls,
-                                 ctx->wire_method,
-                                 ctx->exec_time,
-                                 &wire_fee_start_date,
-                                 &wire_fee_end_date,
-                                 &ctx->wire_fee,
-                                 &closing_fee,
-                                 &wire_fee_master_sig);
+  {
+    char *wire_method;
+
+    wire_method = TALER_payto_get_method (ctx->payto_uri);
+    if (NULL == wire_method)
+    {
+      GNUNET_break (0);
+      *mhd_ret = TALER_MHD_reply_with_error (connection,
+                                             MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                             
TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
+                                             "payto:// without wire method 
encountered");
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    qs = TEH_plugin->get_wire_fee (TEH_plugin->cls,
+                                   wire_method,
+                                   ctx->exec_time,
+                                   &wire_fee_start_date,
+                                   &wire_fee_end_date,
+                                   &ctx->wire_fee,
+                                   &closing_fee,
+                                   &wire_fee_master_sig);
+    GNUNET_free (wire_method);
+  }
   if (0 >= qs)
   {
     if ( (GNUNET_DB_STATUS_HARD_ERROR == qs) ||
@@ -530,7 +525,7 @@ TEH_handler_transfers_get (struct TEH_RequestContext *rc,
   mhd_ret = reply_transfer_details (rc->connection,
                                     &ctx.total,
                                     &ctx.merchant_pub,
-                                    &ctx.h_wire,
+                                    ctx.payto_uri,
                                     &ctx.wire_fee,
                                     ctx.exec_time,
                                     ctx.wdd_head);
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c 
b/src/exchange/taler-exchange-httpd_withdraw.c
index 4839ec97..d393567e 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -107,7 +107,7 @@ struct WithdrawContext
   /**
    * Hash of the denomination public key.
    */
-  struct GNUNET_HashCode denom_pub_hash;
+  struct TALER_DenominationHash denom_pub_hash;
 
   /**
    * Signature over the request.
@@ -199,13 +199,15 @@ withdraw_transaction (void *cls,
   struct WithdrawContext *wc = cls;
   struct TALER_EXCHANGEDB_Reserve r;
   enum GNUNET_DB_QueryStatus qs;
-  struct TALER_DenominationSignature denom_sig;
+  struct TALER_BlindedDenominationSignature denom_sig;
 
 #if OPTIMISTIC_SIGN
   /* store away optimistic signature to protect
      it from being overwritten by get_withdraw_info */
   denom_sig = wc->collectable.sig;
-  wc->collectable.sig.rsa_signature = NULL;
+  memset (&wc->collectable.sig,
+          0,
+          sizeof (wc->collectable.sig));
 #endif
   qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls,
                                       &wc->wsrd.h_coin_envelope,
@@ -222,6 +224,10 @@ withdraw_transaction (void *cls,
     return qs;
   }
 
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Asked to withdraw from %s amount of %s\n",
+              TALER_B2S (&wc->wsrd.reserve_pub),
+              TALER_amount2s (&wc->amount_required));
   /* Don't sign again if we have already signed the coin */
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
   {
@@ -229,7 +235,7 @@ withdraw_transaction (void *cls,
        optimization trade-off loses in this case: we unnecessarily computed
        a signature :-( */
 #if OPTIMISTIC_SIGN
-    GNUNET_CRYPTO_rsa_signature_free (denom_sig.rsa_signature);
+    TALER_blinded_denom_sig_free (&denom_sig);
 #endif
     return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   }
@@ -304,6 +310,10 @@ withdraw_transaction (void *cls,
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
 
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "KYC status is %s for %s\n",
+              wc->kyc.ok ? "ok" : "missing",
+              TALER_B2S (&r.pub));
   if ( (! wc->kyc.ok) &&
        (TEH_KYC_NONE != TEH_kyc_config.mode) &&
        (TALER_EXCHANGEDB_KYC_W2W == wc->kyc.type) )
@@ -321,10 +331,7 @@ withdraw_transaction (void *cls,
     struct TALER_Amount acc;
     enum GNUNET_DB_QueryStatus qs2;
 
-    TALER_amount_set_zero (TEH_currency,
-                           &acc);
-    accumulate_withdraws (&acc,
-                          &wc->amount_required);
+    acc = wc->amount_required;
     qs2 = TEH_plugin->select_withdraw_amounts_by_account (
       TEH_plugin->cls,
       &wc->wsrd.reserve_pub,
@@ -351,6 +358,9 @@ withdraw_transaction (void *cls,
                                           NULL);
       return GNUNET_DB_STATUS_HARD_ERROR;
     }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Amount withdrawn so far is %s\n",
+                TALER_amount2s (&acc));
     if (1 == /* 1: acc > withdraw_limit */
         TALER_amount_cmp (&acc,
                           &TEH_kyc_config.withdraw_limit))
@@ -364,14 +374,14 @@ withdraw_transaction (void *cls,
 #if ! OPTIMISTIC_SIGN
   if (NULL == wc->collectable.sig.rsa_signature)
   {
-    enum TALER_ErrorCode ec;
+    enum TALER_ErrorCode ec = TALER_EC_NONE;
 
     wc->collectable.sig
       = TEH_keys_denomination_sign (&wc->denom_pub_hash,
                                     wc->blinded_msg,
                                     wc->blinded_msg_len,
                                     &ec);
-    if (NULL == wc->collectable.sig.rsa_signature)
+    if (TALER_EC_NONE != ec)
     {
       GNUNET_break (0);
       *mhd_ret = TALER_MHD_reply_with_ec (connection,
@@ -386,6 +396,10 @@ withdraw_transaction (void *cls,
   wc->collectable.reserve_pub = wc->wsrd.reserve_pub;
   wc->collectable.h_coin_envelope = wc->wsrd.h_coin_envelope;
   wc->collectable.reserve_sig = wc->signature;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Persisting withdraw from %s over %s\n",
+              TALER_B2S (&r.pub),
+              TALER_amount2s (&wc->amount_required));
   qs = TEH_plugin->insert_withdraw_info (TEH_plugin->cls,
                                          &wc->collectable);
   if (0 > qs)
@@ -530,7 +544,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
     = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
   wc.wsrd.h_denomination_pub
     = wc.denom_pub_hash;
-  GNUNET_CRYPTO_hash (wc.blinded_msg,
+  TALER_coin_ev_hash (wc.blinded_msg,
                       wc.blinded_msg_len,
                       &wc.wsrd.h_coin_envelope);
   if (GNUNET_OK !=
@@ -550,12 +564,13 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
 
 #if OPTIMISTIC_SIGN
   /* Sign before transaction! */
+  ec = TALER_EC_NONE;
   wc.collectable.sig
     = TEH_keys_denomination_sign (&wc.denom_pub_hash,
                                   wc.blinded_msg,
                                   wc.blinded_msg_len,
                                   &ec);
-  if (NULL == wc.collectable.sig.rsa_signature)
+  if (TALER_EC_NONE != ec)
   {
     GNUNET_break (0);
     GNUNET_JSON_parse_free (spec);
@@ -579,8 +594,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
     {
       /* Even if #withdraw_transaction() failed, it may have created a 
signature
          (or we might have done it optimistically above). */
-      if (NULL != wc.collectable.sig.rsa_signature)
-        GNUNET_CRYPTO_rsa_signature_free (wc.collectable.sig.rsa_signature);
+      TALER_blinded_denom_sig_free (&wc.collectable.sig);
       GNUNET_JSON_parse_free (spec);
       return mhd_ret;
     }
@@ -591,9 +605,7 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
 
   if (wc.kyc_denied)
   {
-    if (NULL != wc.collectable.sig.rsa_signature)
-      GNUNET_CRYPTO_rsa_signature_free (wc.collectable.sig.rsa_signature);
-
+    TALER_blinded_denom_sig_free (&wc.collectable.sig);
     return TALER_MHD_REPLY_JSON_PACK (
       rc->connection,
       MHD_HTTP_ACCEPTED,
@@ -607,9 +619,9 @@ TEH_handler_withdraw (struct TEH_RequestContext *rc,
     ret = TALER_MHD_REPLY_JSON_PACK (
       rc->connection,
       MHD_HTTP_OK,
-      GNUNET_JSON_pack_rsa_signature ("ev_sig",
-                                      wc.collectable.sig.rsa_signature));
-    GNUNET_CRYPTO_rsa_signature_free (wc.collectable.sig.rsa_signature);
+      TALER_JSON_pack_blinded_denom_sig ("ev_sig",
+                                         &wc.collectable.sig));
+    TALER_blinded_denom_sig_free (&wc.collectable.sig);
     return ret;
   }
 }
diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am
index 37b5f015..2a3721ac 100644
--- a/src/exchangedb/Makefile.am
+++ b/src/exchangedb/Makefile.am
@@ -17,8 +17,6 @@ sqldir = $(prefix)/share/taler/sql/exchange/
 sql_DATA = \
   exchange-0000.sql \
   exchange-0001.sql \
-  exchange-0002.sql \
-  exchange-0003.sql \
   drop0001.sql
 
 EXTRA_DIST = \
diff --git a/src/exchangedb/drop0001.sql b/src/exchangedb/drop0001.sql
index 507393e5..52079e52 100644
--- a/src/exchangedb/drop0001.sql
+++ b/src/exchangedb/drop0001.sql
@@ -1,6 +1,6 @@
 --
 -- This file is part of TALER
--- Copyright (C) 2014--2020 Taler Systems SA
+-- Copyright (C) 2014--2021 Taler Systems SA
 --
 -- TALER is free software; you can redistribute it and/or modify it under the
 -- terms of the GNU General Public License as published by the Free Software
@@ -22,27 +22,26 @@ BEGIN;
 -- Unlike the other SQL files, it SHOULD be updated to reflect the
 -- latest requirements for dropping tables.
 
+-- Unregister patch (exchange-0001.sql)
+SELECT _v.unregister_patch('exchange-0001');
 
--- Drops for exchange-0003.sql
+-- Drops for exchange-0001.sql
 DROP TABLE IF EXISTS revolving_work_shards CASCADE;
-
-
--- Drops for exchange-0002.sql
 DROP TABLE IF EXISTS auditors CASCADE;
 DROP TABLE IF EXISTS auditor_denom_sigs CASCADE;
 DROP TABLE IF EXISTS exchange_sign_keys CASCADE;
 DROP TABLE IF EXISTS wire_accounts CASCADE;
 DROP TABLE IF EXISTS signkey_revocations CASCADE;
 DROP TABLE IF EXISTS work_shards CASCADE;
-
--- Drops for 0001.sql
 DROP TABLE IF EXISTS prewire CASCADE;
 DROP TABLE IF EXISTS recoup CASCADE;
 DROP TABLE IF EXISTS recoup_refresh CASCADE;
 DROP TABLE IF EXISTS aggregation_tracking CASCADE;
 DROP TABLE IF EXISTS wire_out CASCADE;
+DROP TABLE IF EXISTS wire_targets CASCADE;
 DROP TABLE IF EXISTS wire_fee CASCADE;
 DROP TABLE IF EXISTS deposits CASCADE;
+DROP TABLE IF EXISTS extension_details CASCADE;
 DROP TABLE IF EXISTS refunds CASCADE;
 DROP TABLE IF EXISTS refresh_commitments CASCADE;
 DROP TABLE IF EXISTS refresh_revealed_coins CASCADE;
@@ -56,14 +55,5 @@ DROP TABLE IF EXISTS denomination_revocations CASCADE;
 DROP TABLE IF EXISTS denominations CASCADE;
 
 
--- Unregister patch (exchange-0001.sql)
-SELECT _v.unregister_patch('exchange-0001');
-
--- Unregister patch (exchange-0002.sql)
-SELECT _v.unregister_patch('exchange-0002');
-
--- Unregister patch (exchange-0003.sql)
-SELECT _v.unregister_patch('exchange-0003');
-
 -- And we're out of here...
 COMMIT;
diff --git a/src/exchangedb/exchange-0001.sql b/src/exchangedb/exchange-0001.sql
index c8438d5c..0426dc50 100644
--- a/src/exchangedb/exchange-0001.sql
+++ b/src/exchangedb/exchange-0001.sql
@@ -1,6 +1,6 @@
 --
 -- This file is part of TALER
--- Copyright (C) 2014--2020 Taler Systems SA
+-- Copyright (C) 2014--2021 Taler Systems SA
 --
 -- TALER is free software; you can redistribute it and/or modify it under the
 -- terms of the GNU General Public License as published by the Free Software
@@ -22,9 +22,11 @@ SELECT _v.register_patch('exchange-0001', NULL, NULL);
 
 
 CREATE TABLE IF NOT EXISTS denominations
-  (denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)
+  (denominations_serial BIGSERIAL UNIQUE
+  ,denom_pub_hash BYTEA PRIMARY KEY CHECK (LENGTH(denom_pub_hash)=64)
+  ,denom_type INT4 NOT NULL DEFAULT (1) -- 1 == RSA (for now, remove default 
later!)
+  ,age_restrictions INT4 NOT NULL DEFAULT (0)
   ,denom_pub BYTEA NOT NULL
-  ,master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)
   ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
   ,valid_from INT8 NOT NULL
   ,expire_withdraw INT8 NOT NULL
@@ -43,6 +45,12 @@ CREATE TABLE IF NOT EXISTS denominations
   );
 COMMENT ON TABLE denominations
   IS 'Main denominations table. All the valid denominations the exchange knows 
about.';
+COMMENT ON COLUMN denominations.denom_type
+  IS 'determines cipher type for blind signatures used with this denomination; 
0 is for RSA';
+COMMENT ON COLUMN denominations.age_restrictions
+  IS 'bitmask with the age restrictions that are being used for this 
denomination; 0 if denomination does not support the use of age restrictions';
+COMMENT ON COLUMN denominations.denominations_serial
+  IS 'needed for exchange-auditor replication logic';
 
 CREATE INDEX IF NOT EXISTS denominations_expire_legal_index
   ON denominations
@@ -51,16 +59,36 @@ CREATE INDEX IF NOT EXISTS denominations_expire_legal_index
 
 CREATE TABLE IF NOT EXISTS denomination_revocations
   (denom_revocations_serial_id BIGSERIAL UNIQUE
-  ,denom_pub_hash BYTEA PRIMARY KEY REFERENCES denominations (denom_pub_hash) 
ON DELETE CASCADE
+  ,denominations_serial INT8 PRIMARY KEY REFERENCES denominations 
(denominations_serial) ON DELETE CASCADE
   ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
   );
 COMMENT ON TABLE denomination_revocations
   IS 'remembering which denomination keys have been revoked';
 
 
+CREATE TABLE IF NOT EXISTS wire_targets
+(wire_target_serial_id BIGSERIAL UNIQUE
+,h_payto BYTEA NOT NULL CHECK (LENGTH(h_payto)=64)
+,payto_uri VARCHAR NOT NULL
+,kyc_ok BOOLEAN NOT NULL DEFAULT (FALSE)
+,external_id VARCHAR
+,PRIMARY KEY (h_payto)
+);
+COMMENT ON TABLE wire_targets
+  IS 'All recipients of money via the exchange';
+COMMENT ON COLUMN wire_targets.payto_uri
+  IS 'Can be a regular bank account, or also be a URI identifying a 
reserve-account (for P2P payments)';
+COMMENT ON COLUMN wire_targets.h_payto
+  IS 'Unsalted hash of payto_uri';
+COMMENT ON COLUMN wire_targets.kyc_ok
+  IS 'true if the KYC check was passed successfully';
+COMMENT ON COLUMN wire_targets.external_id
+  IS 'Name of the user that was used for OAuth 2.0-based legitimization';
+
+
 CREATE TABLE IF NOT EXISTS reserves
-  (reserve_pub BYTEA PRIMARY KEY CHECK(LENGTH(reserve_pub)=32)
-  ,account_details TEXT NOT NULL
+  (reserve_uuid BIGSERIAL UNIQUE
+  ,reserve_pub BYTEA PRIMARY KEY CHECK(LENGTH(reserve_pub)=32)
   ,current_balance_val INT8 NOT NULL
   ,current_balance_frac INT4 NOT NULL
   ,expiration_date INT8 NOT NULL
@@ -73,7 +101,6 @@ COMMENT ON COLUMN reserves.expiration_date
 COMMENT ON COLUMN reserves.gc_date
   IS 'Used to forget all information about a reserve during garbage 
collection';
 
-
 CREATE INDEX IF NOT EXISTS reserves_expiration_index
   ON reserves
   (expiration_date
@@ -92,18 +119,19 @@ COMMENT ON INDEX reserves_gc_index
 
 CREATE TABLE IF NOT EXISTS reserves_in
   (reserve_in_serial_id BIGSERIAL UNIQUE
-  ,reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE 
CASCADE
+  ,reserve_uuid INT8 NOT NULL REFERENCES reserves (reserve_uuid) ON DELETE 
CASCADE
   ,wire_reference INT8 NOT NULL
   ,credit_val INT8 NOT NULL
   ,credit_frac INT4 NOT NULL
-  ,sender_account_details TEXT NOT NULL
+  ,wire_source_serial_id INT8 NOT NULL REFERENCES wire_targets 
(wire_target_serial_id)
   ,exchange_account_section TEXT NOT NULL
   ,execution_date INT8 NOT NULL
-  ,PRIMARY KEY (reserve_pub, wire_reference)
+  ,PRIMARY KEY (reserve_uuid, wire_reference)
   );
 COMMENT ON TABLE reserves_in
   IS 'list of transfers of funds into the reserves, one per incoming wire 
transfer';
--- FIXME: explain 'wire_reference'!
+COMMENT ON COLUMN reserves_in.wire_source_serial_id
+  IS 'Identifies the debited bank account and KYC status';-- FIXME: explain 
'wire_reference'!
 CREATE INDEX IF NOT EXISTS reserves_in_execution_index
   ON reserves_in
   (exchange_account_section
@@ -118,28 +146,30 @@ CREATE INDEX IF NOT EXISTS 
reserves_in_exchange_account_serial
 
 CREATE TABLE IF NOT EXISTS reserves_close
   (close_uuid BIGSERIAL PRIMARY KEY
-  ,reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE 
CASCADE
+  ,reserve_uuid INT8 NOT NULL REFERENCES reserves (reserve_uuid) ON DELETE 
CASCADE
   ,execution_date INT8 NOT NULL
   ,wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32)
-  ,receiver_account TEXT NOT NULL
+  ,wire_target_serial_id INT8 NOT NULL REFERENCES wire_targets 
(wire_target_serial_id)
   ,amount_val INT8 NOT NULL
   ,amount_frac INT4 NOT NULL
   ,closing_fee_val INT8 NOT NULL
   ,closing_fee_frac INT4 NOT NULL);
 COMMENT ON TABLE reserves_close
   IS 'wire transfers executed by the reserve to close reserves';
+COMMENT ON COLUMN reserves_close.wire_target_serial_id
+  IS 'Identifies the credited bank account (and KYC status). Note that closing 
does not depend on KYC.';
 
-CREATE INDEX IF NOT EXISTS reserves_close_by_reserve
+CREATE INDEX IF NOT EXISTS reserves_close_by_uuid
   ON reserves_close
-  (reserve_pub);
+  (reserve_uuid);
 
 
 CREATE TABLE IF NOT EXISTS reserves_out
   (reserve_out_serial_id BIGSERIAL UNIQUE
   ,h_blind_ev BYTEA PRIMARY KEY CHECK (LENGTH(h_blind_ev)=64)
-  ,denom_pub_hash BYTEA NOT NULL REFERENCES denominations (denom_pub_hash)
+  ,denominations_serial INT8 NOT NULL REFERENCES denominations 
(denominations_serial)
   ,denom_sig BYTEA NOT NULL
-  ,reserve_pub BYTEA NOT NULL REFERENCES reserves (reserve_pub) ON DELETE 
CASCADE
+  ,reserve_uuid INT8 NOT NULL REFERENCES reserves (reserve_uuid) ON DELETE 
CASCADE
   ,reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)
   ,execution_date INT8 NOT NULL
   ,amount_with_fee_val INT8 NOT NULL
@@ -149,42 +179,118 @@ COMMENT ON TABLE reserves_out
   IS 'Withdraw operations performed on reserves.';
 COMMENT ON COLUMN reserves_out.h_blind_ev
   IS 'Hash of the blinded coin, used as primary key here so that broken 
clients that use a non-random coin or blinding factor fail to withdraw 
(otherwise they would fail on deposit when the coin is not unique there).';
-COMMENT ON COLUMN reserves_out.denom_pub_hash
+COMMENT ON COLUMN reserves_out.denominations_serial
   IS 'We do not CASCADE ON DELETE here, we may keep the denomination data 
alive';
 
-CREATE INDEX IF NOT EXISTS reserves_out_reserve_pub_index
+CREATE INDEX IF NOT EXISTS reserves_out_reserve_uuid_index
   ON reserves_out
-  (reserve_pub);
-COMMENT ON INDEX reserves_out_reserve_pub_index
+  (reserve_uuid);
+COMMENT ON INDEX reserves_out_reserve_uuid_index
   IS 'for get_reserves_out';
+
 CREATE INDEX IF NOT EXISTS reserves_out_execution_date
   ON reserves_out
   (execution_date);
+
 CREATE INDEX IF NOT EXISTS reserves_out_for_get_withdraw_info
   ON reserves_out
-  (denom_pub_hash
+  (denominations_serial
   ,h_blind_ev
   );
 
+CREATE TABLE IF NOT EXISTS auditors
+  (auditor_uuid BIGSERIAL UNIQUE
+  ,auditor_pub BYTEA PRIMARY KEY CHECK (LENGTH(auditor_pub)=32)
+  ,auditor_name VARCHAR NOT NULL
+  ,auditor_url VARCHAR NOT NULL
+  ,is_active BOOLEAN NOT NULL
+  ,last_change INT8 NOT NULL
+  );
+COMMENT ON TABLE auditors
+  IS 'Table with auditors the exchange uses or has used in the past. Entries 
never expire as we need to remember the last_change column indefinitely.';
+COMMENT ON COLUMN auditors.auditor_pub
+  IS 'Public key of the auditor.';
+COMMENT ON COLUMN auditors.auditor_url
+  IS 'The base URL of the auditor.';
+COMMENT ON COLUMN auditors.is_active
+  IS 'true if we are currently supporting the use of this auditor.';
+COMMENT ON COLUMN auditors.last_change
+  IS 'Latest time when active status changed. Used to detect replays of old 
messages.';
+
+
+CREATE TABLE IF NOT EXISTS auditor_denom_sigs
+  (auditor_denom_serial BIGSERIAL UNIQUE
+  ,auditor_uuid INT8 NOT NULL REFERENCES auditors (auditor_uuid) ON DELETE 
CASCADE
+  ,denominations_serial INT8 NOT NULL REFERENCES denominations 
(denominations_serial) ON DELETE CASCADE
+  ,auditor_sig BYTEA CHECK (LENGTH(auditor_sig)=64)
+  ,PRIMARY KEY (denominations_serial, auditor_uuid)
+  );
+COMMENT ON TABLE auditor_denom_sigs
+  IS 'Table with auditor signatures on exchange denomination keys.';
+COMMENT ON COLUMN auditor_denom_sigs.auditor_uuid
+  IS 'Identifies the auditor.';
+COMMENT ON COLUMN auditor_denom_sigs.denominations_serial
+  IS 'Denomination the signature is for.';
+COMMENT ON COLUMN auditor_denom_sigs.auditor_sig
+  IS 'Signature of the auditor, of purpose 
TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS.';
+
+
+CREATE TABLE IF NOT EXISTS exchange_sign_keys
+  (esk_serial BIGSERIAL UNIQUE
+  ,exchange_pub BYTEA PRIMARY KEY CHECK (LENGTH(exchange_pub)=32)
+  ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
+  ,valid_from INT8 NOT NULL
+  ,expire_sign INT8 NOT NULL
+  ,expire_legal INT8 NOT NULL
+  );
+COMMENT ON TABLE exchange_sign_keys
+  IS 'Table with master public key signatures on exchange online signing 
keys.';
+COMMENT ON COLUMN exchange_sign_keys.exchange_pub
+  IS 'Public online signing key of the exchange.';
+COMMENT ON COLUMN exchange_sign_keys.master_sig
+  IS 'Signature affirming the validity of the signing key of purpose 
TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY.';
+COMMENT ON COLUMN exchange_sign_keys.valid_from
+  IS 'Time when this online signing key will first be used to sign messages.';
+COMMENT ON COLUMN exchange_sign_keys.expire_sign
+  IS 'Time when this online signing key will no longer be used to sign.';
+COMMENT ON COLUMN exchange_sign_keys.expire_legal
+  IS 'Time when this online signing key legally expires.';
+
+
+CREATE TABLE IF NOT EXISTS signkey_revocations
+  (signkey_revocations_serial_id BIGSERIAL UNIQUE
+  ,esk_serial INT8 PRIMARY KEY REFERENCES exchange_sign_keys (esk_serial) ON 
DELETE CASCADE
+  ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
+  );
+COMMENT ON TABLE signkey_revocations
+  IS 'remembering which online signing keys have been revoked';
+
 
 CREATE TABLE IF NOT EXISTS known_coins
   (known_coin_id BIGSERIAL UNIQUE
   ,coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (LENGTH(coin_pub)=32)
-  ,denom_pub_hash BYTEA NOT NULL REFERENCES denominations (denom_pub_hash) ON 
DELETE CASCADE
+  ,age_hash BYTEA CHECK (LENGTH(age_hash)=32)
+  ,denominations_serial INT8 NOT NULL REFERENCES denominations 
(denominations_serial) ON DELETE CASCADE
   ,denom_sig BYTEA NOT NULL
   );
 COMMENT ON TABLE known_coins
   IS 'information about coins and their signatures, so we do not have to store 
the signatures more than once if a coin is involved in multiple operations';
+COMMENT ON COLUMN known_coins.coin_pub
+  IS 'EdDSA public key of the coin';
+COMMENT ON COLUMN known_coins.age_hash
+  IS 'Optional hash for age restrictions as per DD 24 (active if denom_type 
has the respective bit set)';
+COMMENT ON COLUMN known_coins.denom_sig
+  IS 'This is the signature of the exchange that affirms that the coin is a 
valid coin. The specific signature type depends on denom_type of the 
denomination.';
 
 CREATE INDEX IF NOT EXISTS known_coins_by_denomination
   ON known_coins
-  (denom_pub_hash);
+  (denominations_serial);
 
 
 CREATE TABLE IF NOT EXISTS refresh_commitments
   (melt_serial_id BIGSERIAL UNIQUE
   ,rc BYTEA PRIMARY KEY CHECK (LENGTH(rc)=64)
-  ,old_coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE 
CASCADE
+  ,old_known_coin_id INT8 NOT NULL REFERENCES known_coins (known_coin_id) ON 
DELETE CASCADE
   ,old_coin_sig BYTEA NOT NULL CHECK(LENGTH(old_coin_sig)=64)
   ,amount_with_fee_val INT8 NOT NULL
   ,amount_with_fee_frac INT4 NOT NULL
@@ -193,26 +299,29 @@ CREATE TABLE IF NOT EXISTS refresh_commitments
 COMMENT ON TABLE refresh_commitments
   IS 'Commitments made when melting coins and the gamma value chosen by the 
exchange.';
 
-CREATE INDEX IF NOT EXISTS refresh_commitments_old_coin_pub_index
+CREATE INDEX IF NOT EXISTS refresh_commitments_old_coin_id_index
   ON refresh_commitments
-  (old_coin_pub);
+  (old_known_coin_id);
 
 
 CREATE TABLE IF NOT EXISTS refresh_revealed_coins
-  (rc BYTEA NOT NULL REFERENCES refresh_commitments (rc) ON DELETE CASCADE
+  (rrc_serial BIGSERIAL UNIQUE
+  ,melt_serial_id INT8 NOT NULL REFERENCES refresh_commitments 
(melt_serial_id) ON DELETE CASCADE
   ,freshcoin_index INT4 NOT NULL
   ,link_sig BYTEA NOT NULL CHECK(LENGTH(link_sig)=64)
-  ,denom_pub_hash BYTEA NOT NULL REFERENCES denominations (denom_pub_hash) ON 
DELETE CASCADE
+  ,denominations_serial INT8 NOT NULL REFERENCES denominations 
(denominations_serial) ON DELETE CASCADE
   ,coin_ev BYTEA UNIQUE NOT NULL
   ,h_coin_ev BYTEA NOT NULL CHECK(LENGTH(h_coin_ev)=64)
   ,ev_sig BYTEA NOT NULL
-  ,PRIMARY KEY (rc, freshcoin_index)
+  ,PRIMARY KEY (melt_serial_id, freshcoin_index)
   ,UNIQUE (h_coin_ev)
   );
 COMMENT ON TABLE refresh_revealed_coins
   IS 'Revelations about the new coins that are to be created during a melting 
session.';
-COMMENT ON COLUMN refresh_revealed_coins.rc
-  IS 'refresh commitment identifying the melt operation';
+COMMENT ON COLUMN refresh_revealed_coins.rrc_serial
+  IS 'needed for exchange-auditor replication logic';
+COMMENT ON COLUMN refresh_revealed_coins.melt_serial_id
+  IS 'Identifies the refresh commitment (rc) of the melt operation.';
 COMMENT ON COLUMN refresh_revealed_coins.freshcoin_index
   IS 'index of the fresh coin being created (one melt operation may result in 
multiple fresh coins)';
 COMMENT ON COLUMN refresh_revealed_coins.coin_ev
@@ -222,20 +331,23 @@ COMMENT ON COLUMN refresh_revealed_coins.h_coin_ev
 COMMENT ON COLUMN refresh_revealed_coins.ev_sig
   IS 'exchange signature over the envelope';
 
-CREATE INDEX IF NOT EXISTS refresh_revealed_coins_coin_pub_index
+CREATE INDEX IF NOT EXISTS refresh_revealed_coins_denominations_index
   ON refresh_revealed_coins
-  (denom_pub_hash);
+  (denominations_serial);
 
 
 CREATE TABLE IF NOT EXISTS refresh_transfer_keys
-  (rc BYTEA NOT NULL PRIMARY KEY REFERENCES refresh_commitments (rc) ON DELETE 
CASCADE
+  (rtc_serial BIGSERIAL UNIQUE
+  ,melt_serial_id INT8 PRIMARY KEY REFERENCES refresh_commitments 
(melt_serial_id) ON DELETE CASCADE
   ,transfer_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)
   ,transfer_privs BYTEA NOT NULL
   );
 COMMENT ON TABLE refresh_transfer_keys
   IS 'Transfer keys of a refresh operation (the data revealed to the 
exchange).';
-COMMENT ON COLUMN refresh_transfer_keys.rc
-  IS 'refresh commitment identifying the melt operation';
+COMMENT ON COLUMN refresh_transfer_keys.rtc_serial
+  IS 'needed for exchange-auditor replication logic';
+COMMENT ON COLUMN refresh_transfer_keys.melt_serial_id
+  IS 'Identifies the refresh commitment (rc) of the operation.';
 COMMENT ON COLUMN refresh_transfer_keys.transfer_pub
   IS 'transfer public key for the gamma index';
 COMMENT ON COLUMN refresh_transfer_keys.transfer_privs
@@ -243,16 +355,25 @@ COMMENT ON COLUMN refresh_transfer_keys.transfer_privs
 
 CREATE INDEX IF NOT EXISTS refresh_transfer_keys_coin_tpub
   ON refresh_transfer_keys
-  (rc
+  (melt_serial_id
   ,transfer_pub
   );
 COMMENT ON INDEX refresh_transfer_keys_coin_tpub
   IS 'for get_link (unsure if this helps or hurts for performance as there 
should be very few transfer public keys per rc, but at least in theory this 
helps the ORDER BY clause)';
 
+CREATE TABLE IF NOT EXISTS extension_details
+  (extension_details_serial_id BIGSERIAL PRIMARY KEY
+  ,extension_options VARCHAR);
+COMMENT ON TABLE extension_details
+  IS 'Extensions that were provided with deposits (not yet used).';
+COMMENT ON COLUMN extension_details.extension_options
+  IS 'JSON object with options set that the exchange needs to consider when 
executing a deposit. Supported details depend on the extensions supported by 
the exchange.';
+
 
 CREATE TABLE IF NOT EXISTS deposits
   (deposit_serial_id BIGSERIAL PRIMARY KEY
-  ,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE
+  ,shard INT8 NOT NULL DEFAULT 0
+  ,known_coin_id INT8 NOT NULL REFERENCES known_coins (known_coin_id) ON 
DELETE CASCADE
   ,amount_with_fee_val INT8 NOT NULL
   ,amount_with_fee_frac INT4 NOT NULL
   ,wallet_timestamp INT8 NOT NULL
@@ -261,23 +382,34 @@ CREATE TABLE IF NOT EXISTS deposits
   ,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)
-  ,h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)
   ,coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)
-  ,wire TEXT NOT NULL
+  ,wire_salt BYTEA NOT NULL CHECK (LENGTH(wire_salt)=16)
+  ,wire_target_serial_id INT8 NOT NULL REFERENCES wire_targets 
(wire_target_serial_id)
   ,tiny BOOLEAN NOT NULL DEFAULT FALSE
   ,done BOOLEAN NOT NULL DEFAULT FALSE
-  ,UNIQUE (coin_pub, merchant_pub, h_contract_terms)
+  ,extension_blocked BOOLEAN NOT NULL DEFAULT FALSE
+  ,extension_details_serial_id INT8 REFERENCES extension_details 
(extension_details_serial_id)
+  ,UNIQUE (known_coin_id, merchant_pub, h_contract_terms)
   );
 COMMENT ON TABLE deposits
   IS 'Deposits we have received and for which we need to make (aggregate) wire 
transfers (and manage refunds).';
+COMMENT ON COLUMN deposits.shard
+  IS 'Used for load sharding. Should be set based on h_payto and merchant_pub. 
Default of 0 onlyapplies for columns migrated from a previous version without 
sharding support. 64-bit value because we need an *unsigned* 32-bit value.';
+COMMENT ON COLUMN deposits.wire_target_serial_id
+  IS 'Identifies the target bank account and KYC status';COMMENT ON COLUMN 
deposits.wire_salt
+  IS 'Salt used when hashing the payto://-URI to get the h_wire';
 COMMENT ON COLUMN deposits.done
   IS 'Set to TRUE once we have included this deposit in some aggregate wire 
transfer to the merchant';
+COMMENT ON COLUMN deposits.extension_blocked
+  IS 'True if the aggregation of the deposit is currently blocked by some 
extension mechanism. Used to filter out deposits that must not be processed by 
the canonical deposit logic.';
+COMMENT ON COLUMN deposits.extension_details_serial_id
+  IS 'References extensions table, NULL if extensions are not used';
 COMMENT ON COLUMN deposits.tiny
   IS 'Set to TRUE if we decided that the amount is too small to ever trigger a 
wire transfer by itself (requires real aggregation)';
 
 CREATE INDEX IF NOT EXISTS deposits_coin_pub_merchant_contract_index
   ON deposits
-  (coin_pub
+  (known_coin_id
   ,merchant_pub
   ,h_contract_terms
   );
@@ -285,8 +417,10 @@ COMMENT ON INDEX deposits_coin_pub_merchant_contract_index
   IS 'for get_deposit_for_wtid and test_deposit_done';
 CREATE INDEX IF NOT EXISTS deposits_get_ready_index
   ON deposits
-  (tiny
+  (shard
+  ,tiny
   ,done
+  ,extension_blocked
   ,wire_deadline
   ,refund_deadline
   );
@@ -295,8 +429,9 @@ COMMENT ON INDEX deposits_coin_pub_merchant_contract_index
 CREATE INDEX IF NOT EXISTS deposits_iterate_matching_index
   ON deposits
   (merchant_pub
-  ,h_wire
+  ,wire_target_serial_id
   ,done
+  ,extension_blocked
   ,wire_deadline
   );
 COMMENT ON INDEX deposits_iterate_matching_index
@@ -305,30 +440,26 @@ COMMENT ON INDEX deposits_iterate_matching_index
 
 CREATE TABLE IF NOT EXISTS refunds
   (refund_serial_id BIGSERIAL UNIQUE
-  ,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE
-  ,merchant_pub BYTEA NOT NULL CHECK(LENGTH(merchant_pub)=32)
+  ,deposit_serial_id INT8 NOT NULL REFERENCES deposits (deposit_serial_id) ON 
DELETE CASCADE
   ,merchant_sig BYTEA NOT NULL CHECK(LENGTH(merchant_sig)=64)
-  ,h_contract_terms BYTEA NOT NULL CHECK(LENGTH(h_contract_terms)=64)
   ,rtransaction_id INT8 NOT NULL
   ,amount_with_fee_val INT8 NOT NULL
   ,amount_with_fee_frac INT4 NOT NULL
-  ,PRIMARY KEY (coin_pub, merchant_pub, h_contract_terms, rtransaction_id)
+  ,PRIMARY KEY (deposit_serial_id, rtransaction_id)
   );
 COMMENT ON TABLE refunds
   IS 'Data on coins that were refunded. Technically, refunds always apply 
against specific deposit operations involving a coin. The combination of 
coin_pub, merchant_pub, h_contract_terms and rtransaction_id MUST be unique, 
and we usually select by coin_pub so that one goes first.';
+COMMENT ON COLUMN refunds.deposit_serial_id
+  IS 'Identifies ONLY the merchant_pub, h_contract_terms and known_coin_id. 
Multiple deposits may match a refund, this only identifies one of them.';
 COMMENT ON COLUMN refunds.rtransaction_id
   IS 'used by the merchant to make refunds unique in case the same coin for 
the same deposit gets a subsequent (higher) refund';
 
-CREATE INDEX IF NOT EXISTS refunds_coin_pub_index
-  ON refunds
-  (coin_pub);
-
 
 CREATE TABLE IF NOT EXISTS wire_out
   (wireout_uuid BIGSERIAL PRIMARY KEY
   ,execution_date INT8 NOT NULL
   ,wtid_raw BYTEA UNIQUE NOT NULL CHECK (LENGTH(wtid_raw)=32)
-  ,wire_target TEXT NOT NULL
+  ,wire_target_serial_id INT8 NOT NULL REFERENCES wire_targets 
(wire_target_serial_id)
   ,exchange_account_section TEXT NOT NULL
   ,amount_val INT8 NOT NULL
   ,amount_frac INT4 NOT NULL
@@ -337,6 +468,8 @@ COMMENT ON TABLE wire_out
   IS 'wire transfers the exchange has executed';
 COMMENT ON COLUMN wire_out.exchange_account_section
   IS 'identifies the configuration section with the debit account of this 
payment';
+COMMENT ON COLUMN wire_out.wire_target_serial_id
+  IS 'Identifies the credited bank account and KYC status';
 
 CREATE TABLE IF NOT EXISTS aggregation_tracking
   (aggregation_serial_id BIGSERIAL UNIQUE
@@ -356,7 +489,8 @@ COMMENT ON INDEX aggregation_tracking_wtid_index
 
 
 CREATE TABLE IF NOT EXISTS wire_fee
-  (wire_method VARCHAR NOT NULL
+  (wire_fee_serial BIGSERIAL UNIQUE
+  ,wire_method VARCHAR NOT NULL
   ,start_date INT8 NOT NULL
   ,end_date INT8 NOT NULL
   ,wire_fee_val INT8 NOT NULL
@@ -368,6 +502,8 @@ CREATE TABLE IF NOT EXISTS wire_fee
   );
 COMMENT ON TABLE wire_fee
   IS 'list of the wire fees of this exchange, by date';
+COMMENT ON COLUMN wire_fee.wire_fee_serial
+  IS 'needed for exchange-auditor replication logic';
 
 CREATE INDEX IF NOT EXISTS wire_fee_gc_index
   ON wire_fee
@@ -376,60 +512,53 @@ CREATE INDEX IF NOT EXISTS wire_fee_gc_index
 
 CREATE TABLE IF NOT EXISTS recoup
   (recoup_uuid BIGSERIAL UNIQUE
-  ,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub)
+  ,known_coin_id INT8 NOT NULL REFERENCES known_coins (known_coin_id)
   ,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
   ,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)
   ,amount_val INT8 NOT NULL
   ,amount_frac INT4 NOT NULL
   ,timestamp INT8 NOT NULL
-  ,h_blind_ev BYTEA NOT NULL REFERENCES reserves_out (h_blind_ev) ON DELETE 
CASCADE
+  ,reserve_out_serial_id INT8 NOT NULL REFERENCES reserves_out 
(reserve_out_serial_id) ON DELETE CASCADE
   );
 COMMENT ON TABLE recoup
   IS 'Information about recoups that were executed';
-COMMENT ON COLUMN recoup.coin_pub
-  IS 'Do not CASCADE ON DROP on the coin_pub, as we may keep the coin alive!';
+COMMENT ON COLUMN recoup.known_coin_id
+  IS 'Do not CASCADE ON DROP on the known_coin_id, as we may keep the coin 
alive!';
+COMMENT ON COLUMN recoup.reserve_out_serial_id
+  IS 'Identifies the h_blind_ev of the recouped coin.';
 
--- Note: this first index is redundant;
--- It is implicitly removed by the exchange-0002.sql
--- schema changes.
-CREATE INDEX IF NOT EXISTS recoup_by_coin_index
-  ON recoup
-  (coin_pub);
 CREATE INDEX IF NOT EXISTS recoup_by_h_blind_ev
   ON recoup
-  (h_blind_ev);
+  (reserve_out_serial_id);
 CREATE INDEX IF NOT EXISTS recoup_for_by_reserve
   ON recoup
-  (coin_pub
-  ,h_blind_ev
+  (known_coin_id
+  ,reserve_out_serial_id
   );
 
 
 CREATE TABLE IF NOT EXISTS recoup_refresh
   (recoup_refresh_uuid BIGSERIAL UNIQUE
-  ,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub)
+  ,known_coin_id INT8 NOT NULL REFERENCES known_coins (known_coin_id)
   ,coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)
   ,coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)
   ,amount_val INT8 NOT NULL
   ,amount_frac INT4 NOT NULL
   ,timestamp INT8 NOT NULL
-  ,h_blind_ev BYTEA NOT NULL REFERENCES refresh_revealed_coins (h_coin_ev) ON 
DELETE CASCADE
+  ,rrc_serial INT8 NOT NULL UNIQUE REFERENCES refresh_revealed_coins 
(rrc_serial) ON DELETE CASCADE
   );
-COMMENT ON COLUMN recoup_refresh.coin_pub
-  IS 'Do not CASCADE ON DROP on the coin_pub, as we may keep the coin alive!';
+COMMENT ON COLUMN recoup_refresh.known_coin_id
+  IS 'Do not CASCADE ON DROP on the known_coin_id, as we may keep the coin 
alive!';
+COMMENT ON COLUMN recoup_refresh.rrc_serial
+  IS 'Identifies the h_blind_ev of the recouped coin (as h_coin_ev).';
 
--- Note: this index is redundant; implicitly removed
--- by the exchange-0002.sql update!
-CREATE INDEX IF NOT EXISTS recoup_refresh_by_coin_index
-  ON recoup_refresh
-  (coin_pub);
 CREATE INDEX IF NOT EXISTS recoup_refresh_by_h_blind_ev
   ON recoup_refresh
-  (h_blind_ev);
+  (rrc_serial);
 CREATE INDEX IF NOT EXISTS recoup_refresh_for_by_reserve
   ON recoup_refresh
-  (coin_pub
-  ,h_blind_ev
+  (known_coin_id
+  ,rrc_serial
   );
 
 
@@ -437,16 +566,115 @@ CREATE TABLE IF NOT EXISTS prewire
   (prewire_uuid BIGSERIAL PRIMARY KEY
   ,type TEXT NOT NULL
   ,finished BOOLEAN NOT NULL DEFAULT false
+  ,failed BOOLEAN NOT NULL DEFAULT false
   ,buf BYTEA NOT NULL
   );
 COMMENT ON TABLE prewire
   IS 'pre-commit data for wire transfers we are about to execute';
+COMMENT ON COLUMN prewire.failed
+  IS 'set to TRUE if the bank responded with a non-transient failure to our 
transfer request';
+COMMENT ON COLUMN prewire.finished
+  IS 'set to TRUE once bank confirmed receiving the wire transfer request';
+COMMENT ON COLUMN prewire.buf
+  IS 'serialized data to send to the bank to execute the wire transfer';
 
 CREATE INDEX IF NOT EXISTS prepare_iteration_index
   ON prewire
   (finished);
 COMMENT ON INDEX prepare_iteration_index
-  IS 'for wire_prepare_data_get and gc_prewire';
+  IS 'for gc_prewire';
+
+CREATE INDEX IF NOT EXISTS prepare_get_index
+  ON prewire
+  (failed,finished);
+COMMENT ON INDEX prepare_get_index
+  IS 'for wire_prepare_data_get';
+
+
+CREATE TABLE IF NOT EXISTS wire_accounts
+  (payto_uri VARCHAR PRIMARY KEY
+  ,master_sig BYTEA CHECK (LENGTH(master_sig)=64)
+  ,is_active BOOLEAN NOT NULL
+  ,last_change INT8 NOT NULL
+  );
+COMMENT ON TABLE wire_accounts
+  IS 'Table with current and historic bank accounts of the exchange. Entries 
never expire as we need to remember the last_change column indefinitely.';
+COMMENT ON COLUMN wire_accounts.payto_uri
+  IS 'payto URI (RFC 8905) with the bank account of the exchange.';
+COMMENT ON COLUMN wire_accounts.master_sig
+  IS 'Signature of purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS';
+COMMENT ON COLUMN wire_accounts.is_active
+  IS 'true if we are currently supporting the use of this account.';
+COMMENT ON COLUMN wire_accounts.last_change
+  IS 'Latest time when active status changed. Used to detect replays of old 
messages.';
+-- "wire_accounts" has no BIGSERIAL because it is a 'mutable' table
+--            and is of no concern to the auditor
+
+
+CREATE TABLE IF NOT EXISTS work_shards
+  (shard_serial_id BIGSERIAL UNIQUE
+  ,last_attempt INT8 NOT NULL
+  ,start_row INT8 NOT NULL
+  ,end_row INT8 NOT NULL
+  ,completed BOOLEAN NOT NULL DEFAULT FALSE
+  ,job_name VARCHAR NOT NULL
+  ,PRIMARY KEY (job_name, start_row)
+  );
+COMMENT ON TABLE work_shards
+  IS 'coordinates work between multiple processes working on the same job';
+COMMENT ON COLUMN work_shards.shard_serial_id
+  IS 'unique serial number identifying the shard';
+COMMENT ON COLUMN work_shards.last_attempt
+  IS 'last time a worker attempted to work on the shard';
+COMMENT ON COLUMN work_shards.completed
+  IS 'set to TRUE once the shard is finished by a worker';
+COMMENT ON COLUMN work_shards.start_row
+  IS 'row at which the shard scope starts, inclusive';
+COMMENT ON COLUMN work_shards.end_row
+  IS 'row at which the shard scope ends, exclusive';
+COMMENT ON COLUMN work_shards.job_name
+  IS 'unique name of the job the workers on this shard are performing';
+
+CREATE INDEX IF NOT EXISTS work_shards_index
+  ON work_shards
+  (job_name
+  ,completed
+  ,last_attempt
+  );
+
+
+CREATE UNLOGGED TABLE IF NOT EXISTS revolving_work_shards
+  (shard_serial_id BIGSERIAL UNIQUE
+  ,last_attempt INT8 NOT NULL
+  ,start_row INT4 NOT NULL
+  ,end_row INT4 NOT NULL
+  ,active BOOLEAN NOT NULL DEFAULT FALSE
+  ,job_name VARCHAR NOT NULL
+  ,PRIMARY KEY (job_name, start_row)
+  );
+COMMENT ON TABLE revolving_work_shards
+  IS 'coordinates work between multiple processes working on the same job with 
partitions that need to be repeatedly processed; unlogged because on system 
crashes the locks represented by this table will have to be cleared anyway, 
typically using "taler-exchange-dbinit -s"';
+COMMENT ON COLUMN revolving_work_shards.shard_serial_id
+  IS 'unique serial number identifying the shard';
+COMMENT ON COLUMN revolving_work_shards.last_attempt
+  IS 'last time a worker attempted to work on the shard';
+COMMENT ON COLUMN revolving_work_shards.active
+  IS 'set to TRUE when a worker is active on the shard';
+COMMENT ON COLUMN revolving_work_shards.start_row
+  IS 'row at which the shard scope starts, inclusive';
+COMMENT ON COLUMN revolving_work_shards.end_row
+  IS 'row at which the shard scope ends, exclusive';
+COMMENT ON COLUMN revolving_work_shards.job_name
+  IS 'unique name of the job the workers on this shard are performing';
+
+CREATE INDEX IF NOT EXISTS revolving_work_shards_index
+  ON revolving_work_shards
+  (job_name
+  ,active
+  ,last_attempt
+  );
+
+
 
 
 -- Complete transaction
diff --git a/src/exchangedb/exchange-0002.sql b/src/exchangedb/exchange-0002.sql
deleted file mode 100644
index fef5fa64..00000000
--- a/src/exchangedb/exchange-0002.sql
+++ /dev/null
@@ -1,474 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2020-2021 Taler Systems SA
---
--- TALER is free software; you can redistribute it and/or modify it under the
--- terms of the GNU General Public License as published by the Free Software
--- Foundation; either version 3, or (at your option) any later version.
---
--- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
--- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
--- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License along with
--- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
---
-
--- Everything in one big transaction
-BEGIN;
-
--- Check patch versioning is in place.
-SELECT _v.register_patch('exchange-0002', NULL, NULL);
-
--- Need 'failed' bit to prevent hanging transfer tool in case
--- bank API fails.
-ALTER TABLE prewire
-  ADD failed BOOLEAN NOT NULL DEFAULT false;
-
-COMMENT ON COLUMN prewire.failed
-  IS 'set to TRUE if the bank responded with a non-transient failure to our 
transfer request';
-COMMENT ON COLUMN prewire.finished
-  IS 'set to TRUE once bank confirmed receiving the wire transfer request';
-COMMENT ON COLUMN prewire.buf
-  IS 'serialized data to send to the bank to execute the wire transfer';
-
--- change comment, existing index is still useful, but only for gc_prewire.
-COMMENT ON INDEX prepare_iteration_index
-  IS 'for gc_prewire';
-
--- need a new index for updated wire_prepare_data_get statement:
-CREATE INDEX IF NOT EXISTS prepare_get_index
-  ON prewire
-  (failed,finished);
-COMMENT ON INDEX prepare_get_index
-  IS 'for wire_prepare_data_get';
-
-
--- we do not actually need the master public key, it is always the same
-ALTER TABLE denominations
-  DROP COLUMN master_pub;
-
--- need serial IDs on various tables for exchange-auditor replication
-ALTER TABLE denominations
-  ADD COLUMN denominations_serial BIGSERIAL UNIQUE;
-COMMENT ON COLUMN denominations.denominations_serial
-  IS 'needed for exchange-auditor replication logic';
-ALTER TABLE refresh_revealed_coins
-  ADD COLUMN rrc_serial BIGSERIAL UNIQUE;
-COMMENT ON COLUMN refresh_revealed_coins.rrc_serial
-  IS 'needed for exchange-auditor replication logic';
-ALTER TABLE refresh_transfer_keys
-  ADD COLUMN rtc_serial BIGSERIAL UNIQUE;
-COMMENT ON COLUMN refresh_transfer_keys.rtc_serial
-  IS 'needed for exchange-auditor replication logic';
-ALTER TABLE wire_fee
-  ADD COLUMN wire_fee_serial BIGSERIAL UNIQUE;
-COMMENT ON COLUMN wire_fee.wire_fee_serial
-  IS 'needed for exchange-auditor replication logic';
-
--- for the reserves, we add the new reserve_uuid, and also
--- change the foreign keys to use the new BIGSERIAL instead
--- of the public key to reference the entry
-ALTER TABLE reserves
-  ADD COLUMN reserve_uuid BIGSERIAL UNIQUE;
-ALTER TABLE reserves_in
-  ADD COLUMN reserve_uuid INT8 REFERENCES reserves (reserve_uuid) ON DELETE 
CASCADE;
-UPDATE reserves_in
-  SET reserve_uuid=r.reserve_uuid
-  FROM reserves_in rin
-  INNER JOIN reserves r USING(reserve_pub);
-ALTER TABLE reserves_in
-  ALTER COLUMN reserve_uuid SET NOT NULL;
-ALTER TABLE reserves_in
-  DROP COLUMN reserve_pub,
-  ADD CONSTRAINT unique_in PRIMARY KEY (reserve_uuid, wire_reference);
-
-ALTER TABLE reserves_out
-  ADD COLUMN reserve_uuid INT8 REFERENCES reserves (reserve_uuid) ON DELETE 
CASCADE;
-UPDATE reserves_out
-  SET reserve_uuid=r.reserve_uuid
-  FROM reserves_out rout
-  INNER JOIN reserves r USING(reserve_pub);
-ALTER TABLE reserves_out
-  ALTER COLUMN reserve_uuid SET NOT NULL;
-ALTER TABLE reserves_out
-  DROP COLUMN reserve_pub;
-ALTER TABLE reserves_close
-  ADD COLUMN reserve_uuid INT8 REFERENCES reserves (reserve_uuid) ON DELETE 
CASCADE;
-CREATE INDEX IF NOT EXISTS reserves_out_reserve_uuid_index
-  ON reserves_out
-  (reserve_uuid);
-COMMENT ON INDEX reserves_out_reserve_uuid_index
-  IS 'for get_reserves_out';
-
-UPDATE reserves_close
-  SET reserve_uuid=r.reserve_uuid
-  FROM reserves_close rclose
-  INNER JOIN reserves r USING(reserve_pub);
-ALTER TABLE reserves_close
-  ALTER COLUMN reserve_uuid SET NOT NULL;
-ALTER TABLE reserves_close
-  DROP COLUMN reserve_pub;
-CREATE INDEX IF NOT EXISTS reserves_close_by_uuid
-  ON reserves_close
-  (reserve_uuid);
-
-
-
--- change all foreign keys using 'denom_pub_hash' to using 
'denominations_serial' instead
-ALTER TABLE reserves_out
-  ADD COLUMN denominations_serial INT8 REFERENCES denominations 
(denominations_serial) ON DELETE CASCADE;
-UPDATE reserves_out
-  SET denominations_serial=d.denominations_serial
-  FROM reserves_out o
-  INNER JOIN denominations d USING(denom_pub_hash);
-ALTER TABLE reserves_out
-  ALTER COLUMN denominations_serial SET NOT NULL;
-ALTER TABLE reserves_out
-  DROP COLUMN denom_pub_hash;
-CREATE INDEX IF NOT EXISTS reserves_out_for_get_withdraw_info
-  ON reserves_out
-  (denominations_serial
-  ,h_blind_ev
-  );
-
-ALTER TABLE known_coins
-  ADD COLUMN denominations_serial INT8 REFERENCES denominations 
(denominations_serial) ON DELETE CASCADE;
-UPDATE known_coins
-  SET denominations_serial=d.denominations_serial
-  FROM known_coins o
-  INNER JOIN denominations d USING(denom_pub_hash);
-ALTER TABLE known_coins
-  ALTER COLUMN denominations_serial SET NOT NULL;
-ALTER TABLE known_coins
-  DROP COLUMN denom_pub_hash;
-CREATE INDEX IF NOT EXISTS known_coins_by_denomination
-  ON known_coins
-  (denominations_serial);
-
-ALTER TABLE denomination_revocations
-  ADD COLUMN denominations_serial INT8 REFERENCES denominations 
(denominations_serial) ON DELETE CASCADE;
-UPDATE denomination_revocations
-  SET denominations_serial=d.denominations_serial
-  FROM denomination_revocations o
-  INNER JOIN denominations d USING(denom_pub_hash);
-ALTER TABLE denomination_revocations
-  ALTER COLUMN denominations_serial SET NOT NULL;
-ALTER TABLE denomination_revocations
-  DROP COLUMN denom_pub_hash;
-ALTER TABLE denomination_revocations
-  ADD CONSTRAINT denominations_serial_pk PRIMARY KEY (denominations_serial);
-CREATE INDEX IF NOT EXISTS denomination_revocations_by_denomination
-  ON denomination_revocations
-  (denominations_serial);
-
-ALTER TABLE refresh_revealed_coins
-  ADD COLUMN denominations_serial INT8 REFERENCES denominations 
(denominations_serial) ON DELETE CASCADE;
-UPDATE refresh_revealed_coins
-  SET denominations_serial=d.denominations_serial
-  FROM refresh_revealed_coins o
-  INNER JOIN denominations d USING(denom_pub_hash);
-ALTER TABLE refresh_revealed_coins
-  ALTER COLUMN denominations_serial SET NOT NULL;
-ALTER TABLE refresh_revealed_coins
-  DROP COLUMN denom_pub_hash;
-CREATE INDEX IF NOT EXISTS refresh_revealed_coins_denominations_index
-  ON refresh_revealed_coins
-  (denominations_serial);
-
--- Change all foreign keys involving 'coin_pub' to use known_coin_id instead.
-ALTER TABLE recoup_refresh
-  ADD COLUMN known_coin_id INT8 REFERENCES known_coins (known_coin_id) ON 
DELETE CASCADE;
-UPDATE recoup_refresh
-  SET known_coin_id=d.known_coin_id
-  FROM recoup_refresh o
-  INNER JOIN known_coins d USING(coin_pub);
-ALTER TABLE recoup_refresh
-  ALTER COLUMN known_coin_id SET NOT NULL;
-ALTER TABLE recoup_refresh
-  DROP COLUMN coin_pub;
-
-
-ALTER TABLE recoup
-  ADD COLUMN known_coin_id INT8 REFERENCES known_coins (known_coin_id) ON 
DELETE CASCADE;
-UPDATE recoup
-  SET known_coin_id=d.known_coin_id
-  FROM recoup o
-  INNER JOIN known_coins d USING(coin_pub);
-ALTER TABLE recoup
-  ALTER COLUMN known_coin_id SET NOT NULL;
-ALTER TABLE recoup
-  DROP COLUMN coin_pub;
-
-
-ALTER TABLE refresh_commitments
-  ADD COLUMN old_known_coin_id INT8 REFERENCES known_coins (known_coin_id) ON 
DELETE CASCADE;
-UPDATE refresh_commitments
-  SET old_known_coin_id=d.known_coin_id
-  FROM refresh_commitments o
-  INNER JOIN known_coins d ON(o.old_coin_pub=d.coin_pub);
-ALTER TABLE refresh_commitments
-  ALTER COLUMN old_known_coin_id SET NOT NULL;
-ALTER TABLE refresh_commitments
-  DROP COLUMN old_coin_pub;
-CREATE INDEX IF NOT EXISTS refresh_commitments_old_coin_pub_index
-  ON refresh_commitments
-  (old_known_coin_id);
-
-
-ALTER TABLE deposits
-  ADD COLUMN known_coin_id INT8 REFERENCES known_coins (known_coin_id) ON 
DELETE CASCADE;
-UPDATE deposits
-  SET known_coin_id=d.known_coin_id
-  FROM deposits o
-  INNER JOIN known_coins d USING(coin_pub);
-ALTER TABLE deposits
-  ALTER COLUMN known_coin_id SET NOT NULL,
-  ADD CONSTRAINT deposit_unique UNIQUE (known_coin_id, merchant_pub, 
h_contract_terms);
-ALTER TABLE deposits
-  DROP COLUMN coin_pub;
-
-ALTER TABLE refunds
-  ADD COLUMN known_coin_id INT8 REFERENCES known_coins (known_coin_id) ON 
DELETE CASCADE;
-UPDATE refunds
-  SET known_coin_id=d.known_coin_id
-  FROM refunds o
-  INNER JOIN known_coins d USING(coin_pub);
-ALTER TABLE refunds
-  ALTER COLUMN known_coin_id SET NOT NULL;
-ALTER TABLE refunds
-  DROP COLUMN coin_pub;
-
--- Change 'h_blind_ev' in recoup table to 'reserve_out_serial_id'
-ALTER TABLE recoup
-  ADD COLUMN reserve_out_serial_id INT8 REFERENCES reserves_out 
(reserve_out_serial_id) ON DELETE CASCADE;
-UPDATE recoup
-  SET reserve_out_serial_id=d.reserve_out_serial_id
-  FROM recoup o
-  INNER JOIN reserves_out d USING(h_blind_ev);
-ALTER TABLE recoup
-  ALTER COLUMN reserve_out_serial_id SET NOT NULL;
-ALTER TABLE recoup
-  DROP COLUMN h_blind_ev;
-CREATE INDEX IF NOT EXISTS recoup_by_h_blind_ev
-  ON recoup
-  (reserve_out_serial_id);
-CREATE INDEX IF NOT EXISTS recoup_for_by_reserve
-  ON recoup
-  (known_coin_id
-  ,reserve_out_serial_id
-  );
-
-
-COMMENT ON COLUMN recoup.reserve_out_serial_id
-  IS 'Identifies the h_blind_ev of the recouped coin.';
-
-
--- Change 'h_blind_ev' in recoup_refresh table to 'rrc_serial'
-ALTER TABLE recoup_refresh
-  ADD COLUMN rrc_serial INT8 REFERENCES refresh_revealed_coins (rrc_serial) ON 
DELETE CASCADE;
-UPDATE recoup_refresh
-  SET rrc_serial=d.rrc_serial
-  FROM recoup_refresh o
-  INNER JOIN refresh_revealed_coins d ON (d.h_coin_ev = o.h_blind_ev);
-ALTER TABLE recoup_refresh
-  ALTER COLUMN rrc_serial SET NOT NULL,
-  ADD CONSTRAINT recoup_unique UNIQUE (rrc_serial);
-ALTER TABLE recoup_refresh
-  DROP COLUMN h_blind_ev;
-COMMENT ON COLUMN recoup_refresh.rrc_serial
-  IS 'Identifies the h_blind_ev of the recouped coin (as h_coin_ev).';
-CREATE INDEX IF NOT EXISTS recoup_refresh_by_h_blind_ev
-  ON recoup_refresh
-  (rrc_serial);
-CREATE INDEX IF NOT EXISTS recoup_refresh_for_by_reserve
-  ON recoup_refresh
-  (known_coin_id
-  ,rrc_serial
-  );
-
-
--- Change 'rc' in refresh_transfer_keys and refresh_revealed_coins tables to 
'melt_serial_id'
-ALTER TABLE refresh_transfer_keys
-  ADD COLUMN melt_serial_id INT8 REFERENCES refresh_commitments 
(melt_serial_id) ON DELETE CASCADE;
-UPDATE refresh_transfer_keys
-  SET melt_serial_id=d.melt_serial_id
-  FROM refresh_transfer_keys o
-  INNER JOIN refresh_commitments d ON (d.rc = o.rc);
-ALTER TABLE refresh_transfer_keys
-  ALTER COLUMN melt_serial_id SET NOT NULL;
-ALTER TABLE refresh_transfer_keys
-  DROP COLUMN rc;
-COMMENT ON COLUMN refresh_transfer_keys.melt_serial_id
-  IS 'Identifies the refresh commitment (rc) of the operation.';
-CREATE INDEX IF NOT EXISTS refresh_transfer_keys_coin_tpub
-  ON refresh_transfer_keys
-  (melt_serial_id
-  ,transfer_pub
-  );
-COMMENT ON INDEX refresh_transfer_keys_coin_tpub
-  IS 'for get_link (unsure if this helps or hurts for performance as there 
should be very few transfer public keys per rc, but at least in theory this 
helps the ORDER BY clause)';
-
-
-ALTER TABLE refresh_revealed_coins
-  ADD COLUMN melt_serial_id INT8 REFERENCES refresh_commitments 
(melt_serial_id) ON DELETE CASCADE;
-UPDATE refresh_revealed_coins
-  SET melt_serial_id=d.melt_serial_id
-  FROM refresh_revealed_coins o
-  INNER JOIN refresh_commitments d ON (d.rc = o.rc);
-ALTER TABLE refresh_revealed_coins
-  ALTER COLUMN melt_serial_id SET NOT NULL;
-ALTER TABLE refresh_revealed_coins
-  DROP COLUMN rc;
-COMMENT ON COLUMN refresh_revealed_coins.melt_serial_id
-  IS 'Identifies the refresh commitment (rc) of the operation.';
-
-
-
--- Change 'merchant_pub' and 'h_contract_terms' and 'known_coin_id' in 
'refunds' table
--- to 'deposit_serial_id' instead!
-ALTER TABLE refunds
-  ADD COLUMN deposit_serial_id INT8 REFERENCES deposits (deposit_serial_id) ON 
DELETE CASCADE;
-UPDATE refunds
-  SET deposit_serial_id=d.deposit_serial_id
-  FROM refunds o
-  INNER JOIN deposits d
-    ON ( (d.known_coin_id = o.known_coin_id) AND
-         (d.h_contract_terms = o.h_contract_terms) AND
-         (d.merchant_pub = o.merchant_pub) );
-ALTER TABLE refunds
-  ALTER COLUMN deposit_serial_id SET NOT NULL;
-ALTER TABLE refunds
-  DROP COLUMN merchant_pub,
-  DROP COLUMN h_contract_terms,
-  DROP COLUMN known_coin_id;
-ALTER TABLE refunds
-  ADD CONSTRAINT refunds_primary_key PRIMARY KEY (deposit_serial_id, 
rtransaction_id);
-COMMENT ON COLUMN refunds.deposit_serial_id
-  IS 'Identifies ONLY the merchant_pub, h_contract_terms and known_coin_id. 
Multiple deposits may match a refund, this only identifies one of them.';
-
-
--- Create additional tables...
-
-CREATE TABLE IF NOT EXISTS auditors
-  (auditor_uuid BIGSERIAL UNIQUE
-  ,auditor_pub BYTEA PRIMARY KEY CHECK (LENGTH(auditor_pub)=32)
-  ,auditor_name VARCHAR NOT NULL
-  ,auditor_url VARCHAR NOT NULL
-  ,is_active BOOLEAN NOT NULL
-  ,last_change INT8 NOT NULL
-  );
-COMMENT ON TABLE auditors
-  IS 'Table with auditors the exchange uses or has used in the past. Entries 
never expire as we need to remember the last_change column indefinitely.';
-COMMENT ON COLUMN auditors.auditor_pub
-  IS 'Public key of the auditor.';
-COMMENT ON COLUMN auditors.auditor_url
-  IS 'The base URL of the auditor.';
-COMMENT ON COLUMN auditors.is_active
-  IS 'true if we are currently supporting the use of this auditor.';
-COMMENT ON COLUMN auditors.last_change
-  IS 'Latest time when active status changed. Used to detect replays of old 
messages.';
-
-
-CREATE TABLE IF NOT EXISTS auditor_denom_sigs
-  (auditor_denom_serial BIGSERIAL UNIQUE
-  ,auditor_uuid INT8 NOT NULL REFERENCES auditors (auditor_uuid) ON DELETE 
CASCADE
-  ,denominations_serial INT8 NOT NULL REFERENCES denominations 
(denominations_serial) ON DELETE CASCADE
-  ,auditor_sig BYTEA CHECK (LENGTH(auditor_sig)=64)
-  ,PRIMARY KEY (denominations_serial, auditor_uuid)
-  );
-COMMENT ON TABLE auditor_denom_sigs
-  IS 'Table with auditor signatures on exchange denomination keys.';
-COMMENT ON COLUMN auditor_denom_sigs.auditor_uuid
-  IS 'Identifies the auditor.';
-COMMENT ON COLUMN auditor_denom_sigs.denominations_serial
-  IS 'Denomination the signature is for.';
-COMMENT ON COLUMN auditor_denom_sigs.auditor_sig
-  IS 'Signature of the auditor, of purpose 
TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS.';
-
-
-CREATE TABLE IF NOT EXISTS exchange_sign_keys
-  (esk_serial BIGSERIAL UNIQUE
-  ,exchange_pub BYTEA PRIMARY KEY CHECK (LENGTH(exchange_pub)=32)
-  ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
-  ,valid_from INT8 NOT NULL
-  ,expire_sign INT8 NOT NULL
-  ,expire_legal INT8 NOT NULL
-  );
-COMMENT ON TABLE exchange_sign_keys
-  IS 'Table with master public key signatures on exchange online signing 
keys.';
-COMMENT ON COLUMN exchange_sign_keys.exchange_pub
-  IS 'Public online signing key of the exchange.';
-COMMENT ON COLUMN exchange_sign_keys.master_sig
-  IS 'Signature affirming the validity of the signing key of purpose 
TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY.';
-COMMENT ON COLUMN exchange_sign_keys.valid_from
-  IS 'Time when this online signing key will first be used to sign messages.';
-COMMENT ON COLUMN exchange_sign_keys.expire_sign
-  IS 'Time when this online signing key will no longer be used to sign.';
-COMMENT ON COLUMN exchange_sign_keys.expire_legal
-  IS 'Time when this online signing key legally expires.';
-
-
-CREATE TABLE IF NOT EXISTS wire_accounts
-  (payto_uri VARCHAR PRIMARY KEY
-  ,master_sig BYTEA CHECK (LENGTH(master_sig)=64)
-  ,is_active BOOLEAN NOT NULL
-  ,last_change INT8 NOT NULL
-  );
-COMMENT ON TABLE wire_accounts
-  IS 'Table with current and historic bank accounts of the exchange. Entries 
never expire as we need to remember the last_change column indefinitely.';
-COMMENT ON COLUMN wire_accounts.payto_uri
-  IS 'payto URI (RFC 8905) with the bank account of the exchange.';
-COMMENT ON COLUMN wire_accounts.master_sig
-  IS 'Signature of purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS';
-COMMENT ON COLUMN wire_accounts.is_active
-  IS 'true if we are currently supporting the use of this account.';
-COMMENT ON COLUMN wire_accounts.last_change
-  IS 'Latest time when active status changed. Used to detect replays of old 
messages.';
--- "wire_accounts" has no BIGSERIAL because it is a 'mutable' table
---            and is of no concern to the auditor
-
-
-CREATE TABLE IF NOT EXISTS signkey_revocations
-  (signkey_revocations_serial_id BIGSERIAL UNIQUE
-  ,esk_serial INT8 PRIMARY KEY REFERENCES exchange_sign_keys (esk_serial) ON 
DELETE CASCADE
-  ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
-  );
-COMMENT ON TABLE signkey_revocations
-  IS 'remembering which online signing keys have been revoked';
-
-
-
-CREATE TABLE IF NOT EXISTS work_shards
-  (shard_serial_id BIGSERIAL UNIQUE
-  ,last_attempt INT8 NOT NULL
-  ,start_row INT8 NOT NULL
-  ,end_row INT8 NOT NULL
-  ,completed BOOLEAN NOT NULL DEFAULT FALSE
-  ,job_name VARCHAR NOT NULL
-  ,PRIMARY KEY (job_name, start_row)
-  );
-CREATE INDEX IF NOT EXISTS work_shards_index
-  ON work_shards
-  (job_name
-  ,completed
-  ,last_attempt
-  );
-COMMENT ON TABLE work_shards
-  IS 'coordinates work between multiple processes working on the same job';
-COMMENT ON COLUMN work_shards.shard_serial_id
-  IS 'unique serial number identifying the shard';
-COMMENT ON COLUMN work_shards.last_attempt
-  IS 'last time a worker attempted to work on the shard';
-COMMENT ON COLUMN work_shards.completed
-  IS 'set to TRUE once the shard is finished by a worker';
-COMMENT ON COLUMN work_shards.start_row
-  IS 'row at which the shard scope starts, inclusive';
-COMMENT ON COLUMN work_shards.end_row
-  IS 'row at which the shard scope ends, exclusive';
-COMMENT ON COLUMN work_shards.job_name
-  IS 'unique name of the job the workers on this shard are performing';
-
-
--- Complete transaction
-COMMIT;
diff --git a/src/exchangedb/exchange-0003.sql b/src/exchangedb/exchange-0003.sql
deleted file mode 100644
index fa4d4c76..00000000
--- a/src/exchangedb/exchange-0003.sql
+++ /dev/null
@@ -1,78 +0,0 @@
---
--- This file is part of TALER
--- Copyright (C) 2021 Taler Systems SA
---
--- TALER is free software; you can redistribute it and/or modify it under the
--- terms of the GNU General Public License as published by the Free Software
--- Foundation; either version 3, or (at your option) any later version.
---
--- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
--- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
--- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License along with
--- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
---
-
--- Everything in one big transaction
-BEGIN;
-
--- Check patch versioning is in place.
-SELECT _v.register_patch('exchange-0003', NULL, NULL);
-
-
-
-ALTER TABLE deposits
-  ADD COLUMN shard INT4 NOT NULL DEFAULT 0;
-COMMENT ON COLUMN deposits.shard
-  IS 'Used for load sharding. Should be set based on h_wire, merchant_pub and 
a service salt. Default of 0 onlyapplies for columns migrated from a previous 
version without sharding support. 64-bit value because we need an *unsigned* 
32-bit value.';
-
-DROP INDEX deposits_get_ready_index;
-CREATE INDEX deposits_get_ready_index
-  ON deposits
-  (shard
-  ,tiny
-  ,done
-  ,wire_deadline
-  ,refund_deadline
-  );
-COMMENT ON INDEX deposits_get_ready_index
-  IS 'for deposits_get_ready';
-
--- add index lost in v2
-ALTER TABLE refresh_revealed_coins
-  ADD CONSTRAINT rrc_primary_key PRIMARY KEY (melt_serial_id, freshcoin_index);
-
-
-CREATE UNLOGGED TABLE IF NOT EXISTS revolving_work_shards
-  (shard_serial_id BIGSERIAL UNIQUE
-  ,last_attempt INT8 NOT NULL
-  ,start_row INT4 NOT NULL
-  ,end_row INT4 NOT NULL
-  ,active BOOLEAN NOT NULL DEFAULT FALSE
-  ,job_name VARCHAR NOT NULL
-  ,PRIMARY KEY (job_name, start_row)
-  );
-CREATE INDEX IF NOT EXISTS revolving_work_shards_index
-  ON revolving_work_shards
-  (job_name
-  ,active
-  ,last_attempt
-  );
-COMMENT ON TABLE revolving_work_shards
-  IS 'coordinates work between multiple processes working on the same job with 
partitions that need to be repeatedly processed; unlogged because on system 
crashes the locks represented by this table will have to be cleared anyway, 
typically using "taler-exchange-dbinit -s"';
-COMMENT ON COLUMN revolving_work_shards.shard_serial_id
-  IS 'unique serial number identifying the shard';
-COMMENT ON COLUMN revolving_work_shards.last_attempt
-  IS 'last time a worker attempted to work on the shard';
-COMMENT ON COLUMN revolving_work_shards.active
-  IS 'set to TRUE when a worker is active on the shard';
-COMMENT ON COLUMN revolving_work_shards.start_row
-  IS 'row at which the shard scope starts, inclusive';
-COMMENT ON COLUMN revolving_work_shards.end_row
-  IS 'row at which the shard scope ends, exclusive';
-COMMENT ON COLUMN revolving_work_shards.job_name
-  IS 'unique name of the job the workers on this shard are performing';
-
--- Complete transaction
-COMMIT;
diff --git a/src/exchangedb/irbt_callbacks.c b/src/exchangedb/irbt_callbacks.c
index 63d64f31..4b126960 100644
--- a/src/exchangedb/irbt_callbacks.c
+++ b/src/exchangedb/irbt_callbacks.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet
-   Copyright (C) 2020 Taler Systems SA
+   Copyright (C) 2020, 2021 Taler Systems SA
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -35,12 +35,12 @@ static enum GNUNET_DB_QueryStatus
 irbt_cb_table_denominations (struct PostgresClosure *pg,
                              const struct TALER_EXCHANGEDB_TableData *td)
 {
-  struct GNUNET_HashCode denom_hash;
+  struct TALER_DenominationHash denom_hash;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&td->serial),
     GNUNET_PQ_query_param_auto_from_type (&denom_hash),
-    GNUNET_PQ_query_param_rsa_public_key (
-      td->details.denominations.denom_pub.rsa_public_key),
+    TALER_PQ_query_param_denom_pub (
+      &td->details.denominations.denom_pub),
     GNUNET_PQ_query_param_auto_from_type (
       &td->details.denominations.master_sig),
     TALER_PQ_query_param_absolute_time (
@@ -63,8 +63,8 @@ irbt_cb_table_denominations (struct PostgresClosure *pg,
     GNUNET_PQ_query_param_end
   };
 
-  GNUNET_CRYPTO_rsa_public_key_hash (
-    td->details.denominations.denom_pub.rsa_public_key,
+  TALER_denom_pub_hash (
+    &td->details.denominations.denom_pub,
     &denom_hash);
 
   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
@@ -99,6 +99,37 @@ irbt_cb_table_denomination_revocations (
 }
 
 
+/**
+ * Function called with denominations records to insert into table.
+ *
+ * @param pg plugin context
+ * @param td record to insert
+ */
+static enum GNUNET_DB_QueryStatus
+irbt_cb_table_wire_targets (struct PostgresClosure *pg,
+                            const struct TALER_EXCHANGEDB_TableData *td)
+{
+  struct TALER_PaytoHash payto_hash;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (&payto_hash),
+    GNUNET_PQ_query_param_string (
+      td->details.wire_targets.payto_uri),
+    GNUNET_PQ_query_param_auto_from_type (
+      &td->details.wire_targets.kyc_ok),
+    GNUNET_PQ_query_param_string (
+      td->details.wire_targets.external_id),
+    GNUNET_PQ_query_param_end
+  };
+
+  TALER_payto_hash (
+    td->details.wire_targets.payto_uri,
+    &payto_hash);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "insert_into_table_wire_targets",
+                                             params);
+}
+
+
 /**
  * Function called with reserves records to insert into table.
  *
@@ -112,7 +143,6 @@ irbt_cb_table_reserves (struct PostgresClosure *pg,
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&td->serial),
     GNUNET_PQ_query_param_auto_from_type (&td->details.reserves.reserve_pub),
-    GNUNET_PQ_query_param_string (td->details.reserves.account_details),
     TALER_PQ_query_param_amount (&td->details.reserves.current_balance),
     TALER_PQ_query_param_absolute_time (&td->details.reserves.expiration_date),
     TALER_PQ_query_param_absolute_time (&td->details.reserves.gc_date),
@@ -139,8 +169,7 @@ irbt_cb_table_reserves_in (struct PostgresClosure *pg,
     GNUNET_PQ_query_param_uint64 (&td->serial),
     GNUNET_PQ_query_param_uint64 (&td->details.reserves_in.wire_reference),
     TALER_PQ_query_param_amount (&td->details.reserves_in.credit),
-    GNUNET_PQ_query_param_string (
-      td->details.reserves_in.sender_account_details),
+    GNUNET_PQ_query_param_uint64 (&td->details.reserves_in.sender_account),
     GNUNET_PQ_query_param_string (
       td->details.reserves_in.exchange_account_section),
     TALER_PQ_query_param_absolute_time (
@@ -169,8 +198,10 @@ irbt_cb_table_reserves_close (struct PostgresClosure *pg,
     GNUNET_PQ_query_param_uint64 (&td->serial),
     TALER_PQ_query_param_absolute_time (
       &td->details.reserves_close.execution_date),
-    GNUNET_PQ_query_param_auto_from_type (&td->details.reserves_close.wtid),
-    GNUNET_PQ_query_param_string (td->details.reserves_close.receiver_account),
+    GNUNET_PQ_query_param_auto_from_type (
+      &td->details.reserves_close.wtid),
+    GNUNET_PQ_query_param_uint64 (
+      &td->details.reserves_close.wire_target_serial_id),
     TALER_PQ_query_param_amount (&td->details.reserves_close.amount),
     TALER_PQ_query_param_amount (&td->details.reserves_close.closing_fee),
     GNUNET_PQ_query_param_uint64 (&td->details.reserves_close.reserve_uuid),
@@ -195,17 +226,20 @@ irbt_cb_table_reserves_out (struct PostgresClosure *pg,
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&td->serial),
-    GNUNET_PQ_query_param_auto_from_type 
(&td->details.reserves_out.h_blind_ev),
-    GNUNET_PQ_query_param_rsa_signature (
-      td->details.reserves_out.denom_sig.rsa_signature),
+    GNUNET_PQ_query_param_auto_from_type (
+      &td->details.reserves_out.h_blind_ev),
+    GNUNET_PQ_query_param_uint64 (
+      &td->details.reserves_out.denominations_serial),
+    TALER_PQ_query_param_blinded_denom_sig (
+      &td->details.reserves_out.denom_sig),
+    GNUNET_PQ_query_param_uint64 (
+      &td->details.reserves_out.reserve_uuid),
     GNUNET_PQ_query_param_auto_from_type (
       &td->details.reserves_out.reserve_sig),
     TALER_PQ_query_param_absolute_time (
       &td->details.reserves_out.execution_date),
-    TALER_PQ_query_param_amount (&td->details.reserves_out.amount_with_fee),
-    GNUNET_PQ_query_param_uint64 (&td->details.reserves_out.reserve_uuid),
-    GNUNET_PQ_query_param_uint64 (
-      &td->details.reserves_out.denominations_serial),
+    TALER_PQ_query_param_amount (
+      &td->details.reserves_out.amount_with_fee),
     GNUNET_PQ_query_param_end
   };
 
@@ -335,9 +369,10 @@ irbt_cb_table_known_coins (struct PostgresClosure *pg,
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&td->serial),
-    GNUNET_PQ_query_param_auto_from_type (&td->details.known_coins.coin_pub),
-    GNUNET_PQ_query_param_rsa_signature (
-      td->details.known_coins.denom_sig.rsa_signature),
+    GNUNET_PQ_query_param_auto_from_type (
+      &td->details.known_coins.coin_pub),
+    TALER_PQ_query_param_denom_sig (
+      &td->details.known_coins.denom_sig),
     GNUNET_PQ_query_param_uint64 (
       &td->details.known_coins.denominations_serial),
     GNUNET_PQ_query_param_end
@@ -402,8 +437,8 @@ irbt_cb_table_refresh_revealed_coins (
       td->details.refresh_revealed_coins.
       coin_ev_size),
     GNUNET_PQ_query_param_auto_from_type (&h_coin_ev),
-    GNUNET_PQ_query_param_rsa_signature (
-      td->details.refresh_revealed_coins.ev_sig.rsa_signature),
+    TALER_PQ_query_param_blinded_denom_sig (
+      &td->details.refresh_revealed_coins.ev_sig),
     GNUNET_PQ_query_param_uint64 (
       &td->details.refresh_revealed_coins.denominations_serial),
     GNUNET_PQ_query_param_uint64 (
@@ -462,9 +497,11 @@ irbt_cb_table_deposits (struct PostgresClosure *pg,
 {
   uint8_t tiny = td->details.deposits.tiny ? 1 : 0;
   uint8_t done = td->details.deposits.done ? 1 : 0;
-  struct GNUNET_HashCode h_wire;
+  uint8_t extension_blocked = td->details.deposits.extension_blocked ? 1 : 0;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&td->serial),
+    GNUNET_PQ_query_param_uint64 (&td->details.deposits.shard),
+    GNUNET_PQ_query_param_uint64 (&td->details.deposits.known_coin_id),
     TALER_PQ_query_param_amount (&td->details.deposits.amount_with_fee),
     TALER_PQ_query_param_absolute_time 
(&td->details.deposits.wallet_timestamp),
     TALER_PQ_query_param_absolute_time (
@@ -474,17 +511,17 @@ irbt_cb_table_deposits (struct PostgresClosure *pg,
     GNUNET_PQ_query_param_auto_from_type (&td->details.deposits.merchant_pub),
     GNUNET_PQ_query_param_auto_from_type (
       &td->details.deposits.h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (&h_wire),
     GNUNET_PQ_query_param_auto_from_type (&td->details.deposits.coin_sig),
-    TALER_PQ_query_param_json (td->details.deposits.wire),
+    GNUNET_PQ_query_param_auto_from_type (&td->details.deposits.wire_salt),
+    GNUNET_PQ_query_param_uint64 (&td->details.deposits.wire_target_serial_id),
     GNUNET_PQ_query_param_auto_from_type (&tiny),
     GNUNET_PQ_query_param_auto_from_type (&done),
-    GNUNET_PQ_query_param_uint64 (&td->details.deposits.known_coin_id),
+    GNUNET_PQ_query_param_auto_from_type (&extension_blocked),
+    GNUNET_PQ_query_param_uint64 (
+      &td->details.deposits.extension_details_serial_id),
     GNUNET_PQ_query_param_end
   };
 
-  TALER_JSON_merchant_wire_signature_hash (td->details.deposits.wire,
-                                           &h_wire);
   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                              "insert_into_table_deposits",
                                              params);
@@ -530,7 +567,7 @@ irbt_cb_table_wire_out (struct PostgresClosure *pg,
     GNUNET_PQ_query_param_uint64 (&td->serial),
     TALER_PQ_query_param_absolute_time (&td->details.wire_out.execution_date),
     GNUNET_PQ_query_param_auto_from_type (&td->details.wire_out.wtid_raw),
-    TALER_PQ_query_param_json (td->details.wire_out.wire_target),
+    GNUNET_PQ_query_param_uint64 (&td->details.wire_out.wire_target_serial_id),
     GNUNET_PQ_query_param_string (
       td->details.wire_out.exchange_account_section),
     TALER_PQ_query_param_amount (&td->details.wire_out.amount),
diff --git a/src/exchangedb/lrbt_callbacks.c b/src/exchangedb/lrbt_callbacks.c
index b5e53c83..5a26a5d6 100644
--- a/src/exchangedb/lrbt_callbacks.c
+++ b/src/exchangedb/lrbt_callbacks.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet
-   Copyright (C) 2020 Taler Systems SA
+   Copyright (C) 2020, 2021 Taler Systems SA
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -46,33 +46,50 @@ lrbt_cb_table_denominations (void *cls,
   for (unsigned int i = 0; i<num_results; i++)
   {
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("serial",
-                                    &td.serial),
-      GNUNET_PQ_result_spec_rsa_public_key (
+      GNUNET_PQ_result_spec_uint64 (
+        "serial",
+        &td.serial),
+      GNUNET_PQ_result_spec_uint32 (
+        "denom_type",
+        &td.details.denominations.denom_type),
+      GNUNET_PQ_result_spec_uint32 (
+        "age_restrictions",
+        &td.details.denominations.age_restrictions),
+      TALER_PQ_result_spec_denom_pub (
         "denom_pub",
-        &td.details.denominations.denom_pub.rsa_public_key),
-      GNUNET_PQ_result_spec_auto_from_type ("master_sig",
-                                            
&td.details.denominations.master_sig),
-      TALER_PQ_result_spec_absolute_time ("valid_from",
-                                          
&td.details.denominations.valid_from),
-      TALER_PQ_result_spec_absolute_time ("expire_withdraw",
-                                          &td.details.denominations.
-                                          expire_withdraw),
-      TALER_PQ_result_spec_absolute_time ("expire_deposit",
-                                          &td.details.denominations.
-                                          expire_deposit),
-      TALER_PQ_result_spec_absolute_time ("expire_legal",
-                                          
&td.details.denominations.expire_legal),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("coin",
-                                   &td.details.denominations.coin),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_withdraw",
-                                   &td.details.denominations.fee_withdraw),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
-                                   &td.details.denominations.fee_deposit),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
-                                   &td.details.denominations.fee_refresh),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
-                                   &td.details.denominations.fee_refund),
+        &td.details.denominations.denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type (
+        "master_sig",
+        &td.details.denominations.master_sig),
+      TALER_PQ_result_spec_absolute_time (
+        "valid_from",
+        &td.details.denominations.valid_from),
+      TALER_PQ_result_spec_absolute_time (
+        "expire_withdraw",
+        &td.details.denominations.
+        expire_withdraw),
+      TALER_PQ_result_spec_absolute_time (
+        "expire_deposit",
+        &td.details.denominations.
+        expire_deposit),
+      TALER_PQ_result_spec_absolute_time (
+        "expire_legal",
+        &td.details.denominations.expire_legal),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "coin",
+        &td.details.denominations.coin),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "fee_withdraw",
+        &td.details.denominations.fee_withdraw),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "fee_deposit",
+        &td.details.denominations.fee_deposit),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "fee_refresh",
+        &td.details.denominations.fee_refresh),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "fee_refund",
+        &td.details.denominations.fee_refund),
       GNUNET_PQ_result_spec_end
     };
 
@@ -139,6 +156,53 @@ lrbt_cb_table_denomination_revocations (void *cls,
 }
 
 
+/**
+ * Function called with wire_targets table entries.
+ *
+ * @param cls closure
+ * @param result the postgres result
+ * @param num_results the number of results in @a result
+ */
+static void
+lrbt_cb_table_wire_targets (void *cls,
+                            PGresult *result,
+                            unsigned int num_results)
+{
+  struct LookupRecordsByTableContext *ctx = cls;
+  struct TALER_EXCHANGEDB_TableData td = {
+    .table = TALER_EXCHANGEDB_RT_WIRE_TARGETS
+  };
+
+  for (unsigned int i = 0; i<num_results; i++)
+  {
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("serial",
+                                    &td.serial),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &td.details.wire_targets.payto_uri),
+      GNUNET_PQ_result_spec_auto_from_type ("kyc_ok",
+                                            &td.details.wire_targets.kyc_ok),
+      GNUNET_PQ_result_spec_string ("external_id",
+                                    &td.details.wire_targets.external_id),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      ctx->error = true;
+      return;
+    }
+    ctx->cb (ctx->cb_cls,
+             &td);
+    GNUNET_PQ_cleanup_result (rs);
+  }
+}
+
+
 /**
  * Function called with reserves table entries.
  *
@@ -164,8 +228,6 @@ lrbt_cb_table_reserves (void *cls,
                                     &td.serial),
       GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
                                             &td.details.reserves.reserve_pub),
-      GNUNET_PQ_result_spec_string ("account_details",
-                                    &td.details.reserves.account_details),
       TALER_PQ_RESULT_SPEC_AMOUNT ("current_balance",
                                    &td.details.reserves.current_balance),
       TALER_PQ_result_spec_absolute_time ("expiration_date",
@@ -212,22 +274,27 @@ lrbt_cb_table_reserves_in (void *cls,
   for (unsigned int i = 0; i<num_results; i++)
   {
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("serial",
-                                    &td.serial),
-      GNUNET_PQ_result_spec_uint64 ("wire_reference",
-                                    &td.details.reserves_in.wire_reference),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("credit",
-                                   &td.details.reserves_in.credit),
-      GNUNET_PQ_result_spec_string ("sender_account_details",
-                                    &td.details.reserves_in.
-                                    sender_account_details),
-      GNUNET_PQ_result_spec_string ("exchange_account_section",
-                                    &td.details.reserves_in.
-                                    exchange_account_section),
-      TALER_PQ_result_spec_absolute_time ("execution_date",
-                                          
&td.details.reserves_in.execution_date),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &td.details.reserves_in.reserve_uuid),
+      GNUNET_PQ_result_spec_uint64 (
+        "serial",
+        &td.serial),
+      GNUNET_PQ_result_spec_uint64 (
+        "reserve_uuid",
+        &td.details.reserves_in.reserve_uuid),
+      GNUNET_PQ_result_spec_uint64 (
+        "wire_reference",
+        &td.details.reserves_in.wire_reference),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "credit",
+        &td.details.reserves_in.credit),
+      GNUNET_PQ_result_spec_uint64 (
+        "wire_source_serial_id",
+        &td.details.reserves_in.sender_account),
+      GNUNET_PQ_result_spec_string (
+        "exchange_account_section",
+        &td.details.reserves_in.exchange_account_section),
+      TALER_PQ_result_spec_absolute_time (
+        "execution_date",
+        &td.details.reserves_in.execution_date),
       GNUNET_PQ_result_spec_end
     };
 
@@ -268,23 +335,27 @@ lrbt_cb_table_reserves_close (void *cls,
   for (unsigned int i = 0; i<num_results; i++)
   {
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("serial",
-                                    &td.serial),
+      GNUNET_PQ_result_spec_uint64 (
+        "serial",
+        &td.serial),
+      GNUNET_PQ_result_spec_uint64 (
+        "reserve_uuid",
+        &td.details.reserves_close.reserve_uuid),
       TALER_PQ_result_spec_absolute_time (
         "execution_date",
         &td.details.reserves_close.execution_date),
-      GNUNET_PQ_result_spec_auto_from_type ("wtid",
-                                            &td.details.reserves_close.wtid),
-      GNUNET_PQ_result_spec_string (
-        "receiver_account",
-        &td.details.reserves_close.receiver_account),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
-                                   &td.details.reserves_close.amount),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
-                                   &td.details.reserves_close.closing_fee),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &td.details.reserves_close.reserve_uuid),
-
+      GNUNET_PQ_result_spec_auto_from_type (
+        "wtid",
+        &td.details.reserves_close.wtid),
+      GNUNET_PQ_result_spec_uint64 (
+        "wire_target_serial_id",
+        &td.details.reserves_close.wire_target_serial_id),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "amount",
+        &td.details.reserves_close.amount),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "closing_fee",
+        &td.details.reserves_close.closing_fee),
       GNUNET_PQ_result_spec_end
     };
 
@@ -325,25 +396,30 @@ lrbt_cb_table_reserves_out (void *cls,
   for (unsigned int i = 0; i<num_results; i++)
   {
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("serial",
-                                    &td.serial),
-      GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
-                                            
&td.details.reserves_out.h_blind_ev),
-      GNUNET_PQ_result_spec_rsa_signature (
+      GNUNET_PQ_result_spec_uint64 (
+        "serial",
+        &td.serial),
+      GNUNET_PQ_result_spec_auto_from_type (
+        "h_blind_ev",
+        &td.details.reserves_out.h_blind_ev),
+      GNUNET_PQ_result_spec_uint64 (
+        "denominations_serial",
+        &td.details.reserves_out.denominations_serial),
+      TALER_PQ_result_spec_blinded_denom_sig (
         "denom_sig",
-        &td.details.reserves_out.denom_sig.rsa_signature),
-      GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
-                                            
&td.details.reserves_out.reserve_sig),
+        &td.details.reserves_out.denom_sig),
+      GNUNET_PQ_result_spec_uint64 (
+        "reserve_uuid",
+        &td.details.reserves_out.reserve_uuid),
+      GNUNET_PQ_result_spec_auto_from_type (
+        "reserve_sig",
+        &td.details.reserves_out.reserve_sig),
       TALER_PQ_result_spec_absolute_time (
         "execution_date",
         &td.details.reserves_out.execution_date),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &td.details.reserves_out.amount_with_fee),
-      GNUNET_PQ_result_spec_uint64 ("reserve_uuid",
-                                    &td.details.reserves_out.reserve_uuid),
-      GNUNET_PQ_result_spec_uint64 ("denominations_serial",
-                                    &td.details.reserves_out.
-                                    denominations_serial),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "amount_with_fee",
+        &td.details.reserves_out.amount_with_fee),
       GNUNET_PQ_result_spec_end
     };
 
@@ -589,15 +665,18 @@ lrbt_cb_table_known_coins (void *cls,
   for (unsigned int i = 0; i<num_results; i++)
   {
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("serial",
-                                    &td.serial),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
-                                            &td.details.known_coins.coin_pub),
-      GNUNET_PQ_result_spec_rsa_signature (
+      GNUNET_PQ_result_spec_uint64 (
+        "serial",
+        &td.serial),
+      GNUNET_PQ_result_spec_auto_from_type (
+        "coin_pub",
+        &td.details.known_coins.coin_pub),
+      TALER_PQ_result_spec_denom_sig (
         "denom_sig",
-        &td.details.known_coins.denom_sig.rsa_signature),
-      GNUNET_PQ_result_spec_uint64 ("denominations_serial",
-                                    
&td.details.known_coins.denominations_serial),
+        &td.details.known_coins.denom_sig),
+      GNUNET_PQ_result_spec_uint64 (
+        "denominations_serial",
+        &td.details.known_coins.denominations_serial),
       GNUNET_PQ_result_spec_end
     };
 
@@ -708,9 +787,9 @@ lrbt_cb_table_refresh_revealed_coins (void *cls,
         "coin_ev",
         (void **) &td.details.refresh_revealed_coins.coin_ev,
         &td.details.refresh_revealed_coins.coin_ev_size),
-      GNUNET_PQ_result_spec_rsa_signature (
+      TALER_PQ_result_spec_blinded_denom_sig (
         "ev_sig",
-        &td.details.refresh_revealed_coins.ev_sig.rsa_signature),
+        &td.details.refresh_revealed_coins.ev_sig),
       GNUNET_PQ_result_spec_uint64 (
         "denominations_serial",
         &td.details.refresh_revealed_coins.denominations_serial),
@@ -828,6 +907,12 @@ lrbt_cb_table_deposits (void *cls,
       GNUNET_PQ_result_spec_uint64 (
         "serial",
         &td.serial),
+      GNUNET_PQ_result_spec_uint64 (
+        "shard",
+        &td.details.deposits.shard),
+      GNUNET_PQ_result_spec_uint64 (
+        "known_coin_id",
+        &td.details.deposits.known_coin_id),
       TALER_PQ_RESULT_SPEC_AMOUNT (
         "amount_with_fee",
         &td.details.deposits.amount_with_fee),
@@ -852,18 +937,24 @@ lrbt_cb_table_deposits (void *cls,
       GNUNET_PQ_result_spec_auto_from_type (
         "coin_sig",
         &td.details.deposits.coin_sig),
-      TALER_PQ_result_spec_json (
-        "wire",
-        &td.details.deposits.wire),
+      GNUNET_PQ_result_spec_auto_from_type (
+        "wire_salt",
+        &td.details.deposits.wire_salt),
+      GNUNET_PQ_result_spec_uint64 (
+        "wire_target_serial_id",
+        &td.details.deposits.wire_target_serial_id),
       GNUNET_PQ_result_spec_auto_from_type (
         "tiny",
         &td.details.deposits.tiny),
       GNUNET_PQ_result_spec_auto_from_type (
         "done",
         &td.details.deposits.done),
+      GNUNET_PQ_result_spec_auto_from_type (
+        "extension_blocked",
+        &td.details.deposits.extension_blocked),
       GNUNET_PQ_result_spec_uint64 (
-        "known_coin_id",
-        &td.details.deposits.known_coin_id),
+        "extension_details_serial_id",
+        &td.details.deposits.extension_details_serial_id),
       GNUNET_PQ_result_spec_end
     };
 
@@ -906,16 +997,21 @@ lrbt_cb_table_refunds (void *cls,
   for (unsigned int i = 0; i<num_results; i++)
   {
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("serial",
-                                    &td.serial),
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
-                                            &td.details.refunds.merchant_sig),
-      GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
-                                    &td.details.refunds.rtransaction_id),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &td.details.refunds.amount_with_fee),
-      GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
-                                    &td.details.refunds.deposit_serial_id),
+      GNUNET_PQ_result_spec_uint64 (
+        "serial",
+        &td.serial),
+      GNUNET_PQ_result_spec_auto_from_type (
+        "merchant_sig",
+        &td.details.refunds.merchant_sig),
+      GNUNET_PQ_result_spec_uint64 (
+        "rtransaction_id",
+        &td.details.refunds.rtransaction_id),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "amount_with_fee",
+        &td.details.refunds.amount_with_fee),
+      GNUNET_PQ_result_spec_uint64 (
+        "deposit_serial_id",
+        &td.details.refunds.deposit_serial_id),
       GNUNET_PQ_result_spec_end
     };
 
@@ -958,17 +1054,21 @@ lrbt_cb_table_wire_out (void *cls,
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint64 ("serial",
                                     &td.serial),
-      TALER_PQ_result_spec_absolute_time ("execution_date",
-                                          &td.details.wire_out.execution_date),
-      GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
-                                            &td.details.wire_out.wtid_raw),
-      TALER_PQ_result_spec_json ("wire_target",
-                                 &td.details.wire_out.wire_target),
+      TALER_PQ_result_spec_absolute_time (
+        "execution_date",
+        &td.details.wire_out.execution_date),
+      GNUNET_PQ_result_spec_auto_from_type (
+        "wtid_raw",
+        &td.details.wire_out.wtid_raw),
+      GNUNET_PQ_result_spec_uint64 (
+        "wire_target_serial_id",
+        &td.details.wire_out.wire_target_serial_id),
       GNUNET_PQ_result_spec_string (
         "exchange_account_section",
         &td.details.wire_out.exchange_account_section),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
-                                   &td.details.wire_out.amount),
+      TALER_PQ_RESULT_SPEC_AMOUNT (
+        "amount",
+        &td.details.wire_out.amount),
       GNUNET_PQ_result_spec_end
     };
 
@@ -1008,8 +1108,9 @@ lrbt_cb_table_aggregation_tracking (void *cls,
   for (unsigned int i = 0; i<num_results; i++)
   {
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint64 ("serial",
-                                    &td.serial),
+      GNUNET_PQ_result_spec_uint64 (
+        "serial",
+        &td.serial),
       GNUNET_PQ_result_spec_uint64 (
         "deposit_serial_id",
         &td.details.aggregation_tracking.deposit_serial_id),
diff --git a/src/exchangedb/plugin_exchangedb_common.c 
b/src/exchangedb/plugin_exchangedb_common.c
index fb697dae..a07ae78c 100644
--- a/src/exchangedb/plugin_exchangedb_common.c
+++ b/src/exchangedb/plugin_exchangedb_common.c
@@ -49,7 +49,7 @@ common_free_reserve_history (void *cls,
         struct TALER_EXCHANGEDB_CollectableBlindcoin *cbc;
 
         cbc = rh->details.withdraw;
-        GNUNET_CRYPTO_rsa_signature_free (cbc->sig.rsa_signature);
+        TALER_blinded_denom_sig_free (&cbc->sig);
         GNUNET_free (cbc);
         break;
       }
@@ -58,7 +58,7 @@ common_free_reserve_history (void *cls,
         struct TALER_EXCHANGEDB_Recoup *recoup;
 
         recoup = rh->details.recoup;
-        GNUNET_CRYPTO_rsa_signature_free 
(recoup->coin.denom_sig.rsa_signature);
+        TALER_denom_sig_free (&recoup->coin.denom_sig);
         GNUNET_free (recoup);
         break;
       }
@@ -103,8 +103,7 @@ common_free_coin_transaction_list (void *cls,
         struct TALER_EXCHANGEDB_DepositListEntry *deposit;
 
         deposit = tl->details.deposit;
-        if (NULL != deposit->receiver_wire_account)
-          json_decref (deposit->receiver_wire_account);
+        GNUNET_free (deposit->receiver_wire_account);
         GNUNET_free (deposit);
         break;
       }
@@ -116,8 +115,7 @@ common_free_coin_transaction_list (void *cls,
         struct TALER_EXCHANGEDB_RecoupRefreshListEntry *rr;
 
         rr = tl->details.old_coin_recoup;
-        if (NULL != rr->coin.denom_sig.rsa_signature)
-          GNUNET_CRYPTO_rsa_signature_free (rr->coin.denom_sig.rsa_signature);
+        TALER_denom_sig_free (&rr->coin.denom_sig);
         GNUNET_free (rr);
         break;
       }
@@ -132,8 +130,7 @@ common_free_coin_transaction_list (void *cls,
         struct TALER_EXCHANGEDB_RecoupRefreshListEntry *rr;
 
         rr = tl->details.recoup_refresh;
-        if (NULL != rr->coin.denom_sig.rsa_signature)
-          GNUNET_CRYPTO_rsa_signature_free (rr->coin.denom_sig.rsa_signature);
+        TALER_denom_sig_free (&rr->coin.denom_sig);
         GNUNET_free (rr);
         break;
       }
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index b35e2a4f..57c22245 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -26,6 +26,7 @@
 #include "taler_error_codes.h"
 #include "taler_dbevents.h"
 #include "taler_pq_lib.h"
+#include "taler_util.h"
 #include "taler_json_lib.h"
 #include "taler_exchangedb_plugin.h"
 #include <poll.h>
@@ -120,6 +121,11 @@ struct PostgresClosure
    */
   char *currency;
 
+  /**
+   * Our base URL.
+   */
+  char *exchange_url;
+
   /**
    * Postgres connection handle.
    */
@@ -200,312 +206,345 @@ prepare_statements (struct PostgresClosure *pg)
   struct GNUNET_PQ_PreparedStatement ps[] = {
     /* Used in #postgres_insert_denomination_info() and
        #postgres_add_denomination_key() */
-    GNUNET_PQ_make_prepare ("denomination_insert",
-                            "INSERT INTO denominations "
-                            "(denom_pub_hash"
-                            ",denom_pub"
-                            ",master_sig"
-                            ",valid_from"
-                            ",expire_withdraw"
-                            ",expire_deposit"
-                            ",expire_legal"
-                            ",coin_val"                                        
    /* value of this denom */
-                            ",coin_frac"                                       
     /* fractional value of this denom */
-                            ",fee_withdraw_val"
-                            ",fee_withdraw_frac"
-                            ",fee_deposit_val"
-                            ",fee_deposit_frac"
-                            ",fee_refresh_val"
-                            ",fee_refresh_frac"
-                            ",fee_refund_val"
-                            ",fee_refund_frac"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
-                            " $11, $12, $13, $14, $15, $16, $17);",
-                            17),
+    GNUNET_PQ_make_prepare (
+      "denomination_insert",
+      "INSERT INTO denominations "
+      "(denom_pub_hash"
+      ",denom_pub"
+      ",master_sig"
+      ",valid_from"
+      ",expire_withdraw"
+      ",expire_deposit"
+      ",expire_legal"
+      ",coin_val"                                                              
    /* value of this denom */
+      ",coin_frac"                                                             
     /* fractional value of this denom */
+      ",fee_withdraw_val"
+      ",fee_withdraw_frac"
+      ",fee_deposit_val"
+      ",fee_deposit_frac"
+      ",fee_refresh_val"
+      ",fee_refresh_frac"
+      ",fee_refund_val"
+      ",fee_refund_frac"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
+      " $11, $12, $13, $14, $15, $16, $17);",
+      17),
     /* Used in #postgres_iterate_denomination_info() */
-    GNUNET_PQ_make_prepare ("denomination_iterate",
-                            "SELECT"
-                            " master_sig"
-                            ",valid_from"
-                            ",expire_withdraw"
-                            ",expire_deposit"
-                            ",expire_legal"
-                            ",coin_val"                                        
    /* value of this denom */
-                            ",coin_frac"                                       
     /* fractional value of this denom */
-                            ",fee_withdraw_val"
-                            ",fee_withdraw_frac"
-                            ",fee_deposit_val"
-                            ",fee_deposit_frac"
-                            ",fee_refresh_val"
-                            ",fee_refresh_frac"
-                            ",fee_refund_val"
-                            ",fee_refund_frac"
-                            ",denom_pub"
-                            " FROM denominations;",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "denomination_iterate",
+      "SELECT"
+      " master_sig"
+      ",valid_from"
+      ",expire_withdraw"
+      ",expire_deposit"
+      ",expire_legal"
+      ",coin_val"                                                              
    /* value of this denom */
+      ",coin_frac"                                                             
     /* fractional value of this denom */
+      ",fee_withdraw_val"
+      ",fee_withdraw_frac"
+      ",fee_deposit_val"
+      ",fee_deposit_frac"
+      ",fee_refresh_val"
+      ",fee_refresh_frac"
+      ",fee_refund_val"
+      ",fee_refund_frac"
+      ",denom_pub"
+      " FROM denominations;",
+      0),
     /* Used in #postgres_iterate_denominations() */
-    GNUNET_PQ_make_prepare ("select_denominations",
-                            "SELECT"
-                            " denominations.master_sig"
-                            ",denom_revocations_serial_id IS NOT NULL AS 
revoked"
-                            ",valid_from"
-                            ",expire_withdraw"
-                            ",expire_deposit"
-                            ",expire_legal"
-                            ",coin_val"                                        
    /* value of this denom */
-                            ",coin_frac"                                       
     /* fractional value of this denom */
-                            ",fee_withdraw_val"
-                            ",fee_withdraw_frac"
-                            ",fee_deposit_val"
-                            ",fee_deposit_frac"
-                            ",fee_refresh_val"
-                            ",fee_refresh_frac"
-                            ",fee_refund_val"
-                            ",fee_refund_frac"
-                            ",denom_pub"
-                            " FROM denominations"
-                            " LEFT JOIN "
-                            "   denomination_revocations USING 
(denominations_serial);",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "select_denominations",
+      "SELECT"
+      " denominations.master_sig"
+      ",denom_revocations_serial_id IS NOT NULL AS revoked"
+      ",valid_from"
+      ",expire_withdraw"
+      ",expire_deposit"
+      ",expire_legal"
+      ",coin_val"                                                              
    /* value of this denom */
+      ",coin_frac"                                                             
     /* fractional value of this denom */
+      ",fee_withdraw_val"
+      ",fee_withdraw_frac"
+      ",fee_deposit_val"
+      ",fee_deposit_frac"
+      ",fee_refresh_val"
+      ",fee_refresh_frac"
+      ",fee_refund_val"
+      ",fee_refund_frac"
+      ",denom_pub"
+      " FROM denominations"
+      " LEFT JOIN "
+      "   denomination_revocations USING (denominations_serial);",
+      0),
     /* Used in #postgres_iterate_active_signkeys() */
-    GNUNET_PQ_make_prepare ("select_signkeys",
-                            "SELECT"
-                            " master_sig"
-                            ",exchange_pub"
-                            ",valid_from"
-                            ",expire_sign"
-                            ",expire_legal"
-                            " FROM exchange_sign_keys esk"
-                            " WHERE"
-                            "   expire_sign > $1"
-                            " AND NOT EXISTS "
-                            "  (SELECT esk_serial "
-                            "     FROM signkey_revocations skr"
-                            "    WHERE esk.esk_serial = skr.esk_serial);",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "select_signkeys",
+      "SELECT"
+      " master_sig"
+      ",exchange_pub"
+      ",valid_from"
+      ",expire_sign"
+      ",expire_legal"
+      " FROM exchange_sign_keys esk"
+      " WHERE"
+      "   expire_sign > $1"
+      " AND NOT EXISTS "
+      "  (SELECT esk_serial "
+      "     FROM signkey_revocations skr"
+      "    WHERE esk.esk_serial = skr.esk_serial);",
+      1),
     /* Used in #postgres_iterate_auditor_denominations() */
-    GNUNET_PQ_make_prepare ("select_auditor_denoms",
-                            "SELECT"
-                            " auditors.auditor_pub"
-                            ",denominations.denom_pub_hash"
-                            ",auditor_denom_sigs.auditor_sig"
-                            " FROM auditor_denom_sigs"
-                            " JOIN auditors USING (auditor_uuid)"
-                            " JOIN denominations USING (denominations_serial)"
-                            " WHERE auditors.is_active;",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "select_auditor_denoms",
+      "SELECT"
+      " auditors.auditor_pub"
+      ",denominations.denom_pub_hash"
+      ",auditor_denom_sigs.auditor_sig"
+      " FROM auditor_denom_sigs"
+      " JOIN auditors USING (auditor_uuid)"
+      " JOIN denominations USING (denominations_serial)"
+      " WHERE auditors.is_active;",
+      0),
     /* Used in #postgres_iterate_active_auditors() */
-    GNUNET_PQ_make_prepare ("select_auditors",
-                            "SELECT"
-                            " auditor_pub"
-                            ",auditor_url"
-                            ",auditor_name"
-                            " FROM auditors"
-                            " WHERE"
-                            "   is_active;",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "select_auditors",
+      "SELECT"
+      " auditor_pub"
+      ",auditor_url"
+      ",auditor_name"
+      " FROM auditors"
+      " WHERE"
+      "   is_active;",
+      0),
     /* Used in #postgres_get_denomination_info() */
-    GNUNET_PQ_make_prepare ("denomination_get",
-                            "SELECT"
-                            " master_sig"
-                            ",valid_from"
-                            ",expire_withdraw"
-                            ",expire_deposit"
-                            ",expire_legal"
-                            ",coin_val"                                        
    /* value of this denom */
-                            ",coin_frac"                                       
     /* fractional value of this denom */
-                            ",fee_withdraw_val"
-                            ",fee_withdraw_frac"
-                            ",fee_deposit_val"
-                            ",fee_deposit_frac"
-                            ",fee_refresh_val"
-                            ",fee_refresh_frac"
-                            ",fee_refund_val"
-                            ",fee_refund_frac"
-                            " FROM denominations"
-                            " WHERE denom_pub_hash=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "denomination_get",
+      "SELECT"
+      " master_sig"
+      ",valid_from"
+      ",expire_withdraw"
+      ",expire_deposit"
+      ",expire_legal"
+      ",coin_val"                                                              
    /* value of this denom */
+      ",coin_frac"                                                             
     /* fractional value of this denom */
+      ",fee_withdraw_val"
+      ",fee_withdraw_frac"
+      ",fee_deposit_val"
+      ",fee_deposit_frac"
+      ",fee_refresh_val"
+      ",fee_refresh_frac"
+      ",fee_refund_val"
+      ",fee_refund_frac"
+      " FROM denominations"
+      " WHERE denom_pub_hash=$1;",
+      1),
     /* Used in #postgres_insert_denomination_revocation() */
-    GNUNET_PQ_make_prepare ("denomination_revocation_insert",
-                            "INSERT INTO denomination_revocations "
-                            "(denominations_serial"
-                            ",master_sig"
-                            ") SELECT denominations_serial,$2"
-                            "    FROM denominations"
-                            "   WHERE denom_pub_hash=$1;",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "denomination_revocation_insert",
+      "INSERT INTO denomination_revocations "
+      "(denominations_serial"
+      ",master_sig"
+      ") SELECT denominations_serial,$2"
+      "    FROM denominations"
+      "   WHERE denom_pub_hash=$1;",
+      2),
     /* Used in #postgres_get_denomination_revocation() */
-    GNUNET_PQ_make_prepare ("denomination_revocation_get",
-                            "SELECT"
-                            " master_sig"
-                            ",denom_revocations_serial_id"
-                            " FROM denomination_revocations"
-                            " WHERE denominations_serial="
-                            "  (SELECT denominations_serial"
-                            "    FROM denominations"
-                            "    WHERE denom_pub_hash=$1);",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "denomination_revocation_get",
+      "SELECT"
+      " master_sig"
+      ",denom_revocations_serial_id"
+      " FROM denomination_revocations"
+      " WHERE denominations_serial="
+      "  (SELECT denominations_serial"
+      "    FROM denominations"
+      "    WHERE denom_pub_hash=$1);",
+      1),
     /* Used in #postgres_reserves_get() */
-    GNUNET_PQ_make_prepare ("reserves_get_with_kyc",
-                            "SELECT"
-                            " current_balance_val"
-                            ",current_balance_frac"
-                            ",expiration_date"
-                            ",gc_date"
-                            ",FALSE AS kyc_ok" // FIXME
-                            ",CAST (0 AS INT8) AS payment_target_uuid" // FIXME
-                            " FROM reserves"
-                            " WHERE reserve_pub=$1"
-                            " LIMIT 1;",
-                            1),
-#if FIXME_DD23
+    GNUNET_PQ_make_prepare (
+      "reserves_get_with_kyc",
+      "SELECT"
+      " current_balance_val"
+      ",current_balance_frac"
+      ",expiration_date"
+      ",gc_date"
+      ",kyc_ok"
+      ",wire_target_serial_id AS payment_target_uuid"
+      " FROM reserves"
+      " JOIN reserves_in ri USING (reserve_uuid)"
+      " JOIN wire_targets wt "
+      "  ON (ri.wire_source_serial_id = wt.wire_target_serial_id)"
+      " WHERE reserve_pub=$1"
+      " LIMIT 1;",
+      1),
     /* Used in #postgres_set_kyc_ok() */
-    GNUNET_PQ_make_prepare ("set_kyc_ok",
-                            "UPDATE wire_targets"
-                            " SET kyc_ok=TRUE"
-                            " WHERE wire_target_serial_id=$1",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "set_kyc_ok",
+      "UPDATE wire_targets"
+      " SET kyc_ok=TRUE"
+      ",external_id=$2"
+      " WHERE wire_target_serial_id=$1",
+      2),
+    GNUNET_PQ_make_prepare (
+      "get_kyc_h_payto",
+      "SELECT"
+      " h_payto"
+      " FROM wire_targets"
+      " WHERE wire_target_serial_id=$1"
+      " LIMIT 1;",
+      1),
     /* Used in #postgres_get_kyc_status() */
-    GNUNET_PQ_make_prepare ("get_kyc_status",
-                            "SELECT"
-                            ",kyc_ok"
-                            ",wire_target_serial_id AS payment_target_uuid"
-                            " FROM wire_targets"
-                            " WHERE payto_uri=$1"
-                            " LIMIT 1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_kyc_status",
+      "SELECT"
+      " kyc_ok"
+      ",wire_target_serial_id AS payment_target_uuid"
+      " FROM wire_targets"
+      " WHERE payto_uri=$1"
+      " LIMIT 1;",
+      1),
     /* Used in #postgres_select_kyc_status() */
-    GNUNET_PQ_make_prepare ("select_kyc_status",
-                            "SELECT"
-                            ",kyc_ok"
-                            ",h_payto"
-                            " FROM wire_targets"
-                            " WHERE"
-                            " wire_target_serial_id=$1",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "select_kyc_status",
+      "SELECT"
+      " kyc_ok"
+      ",h_payto"
+      " FROM wire_targets"
+      " WHERE"
+      " wire_target_serial_id=$1",
+      1),
     /* Used in #postgres_inselect_wallet_kyc_status() */
-    // FIXME: Note that this statement has not been debugged at all...
-    // It just represents the _idea_.
-    GNUNET_PQ_make_prepare ("inselect_wallet_kyc_status",
-                            "INSERT INTO wire_targets"
-                            "(payto_uri"
-                            ") VALUES "
-                            "($1)"
-                            " ON CONFLICT (wire_target_serial_id) DO "
-                            " (SELECT "
-                            "  kyc_ok"
-                            " ,wire_target_serial_id"
-                            " )"
-                            " RETURNING "
-                            "   FALSE AS kyc_ok"
-                            "   wire_target_serial_id;",
-                            1),
-#endif
+    GNUNET_PQ_make_prepare (
+      "insert_kyc_status",
+      "INSERT INTO wire_targets"
+      "  (h_payto"
+      "  ,payto_uri"
+      "  ) VALUES "
+      "  ($1, $2)"
+      " RETURNING wire_target_serial_id",
+      2),
+    GNUNET_PQ_make_prepare (
+      "select_kyc_status_by_payto",
+      "SELECT "
+      " kyc_ok"
+      ",wire_target_serial_id"
+      " FROM wire_targets"
+      " WHERE h_payto=$1;",
+      1),
     /* Used in #reserves_get() */
-    GNUNET_PQ_make_prepare ("reserves_get",
-                            "SELECT"
-                            " current_balance_val"
-                            ",current_balance_frac"
-                            ",expiration_date"
-                            ",gc_date"
-                            " FROM reserves"
-                            " WHERE reserve_pub=$1"
-                            " LIMIT 1;",
-                            1),
-    GNUNET_PQ_make_prepare ("reserve_create",
-                            "INSERT INTO reserves "
-                            "(reserve_pub"
-                            ",account_details"
-                            ",current_balance_val"
-                            ",current_balance_frac"
-                            ",expiration_date"
-                            ",gc_date"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6)"
-                            " ON CONFLICT DO NOTHING"
-                            " RETURNING reserve_uuid;",
-                            6),
+    GNUNET_PQ_make_prepare (
+      "reserves_get",
+      "SELECT"
+      " current_balance_val"
+      ",current_balance_frac"
+      ",expiration_date"
+      ",gc_date"
+      " FROM reserves"
+      " WHERE reserve_pub=$1"
+      " LIMIT 1;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "reserve_create",
+      "INSERT INTO reserves "
+      "(reserve_pub"
+      ",current_balance_val"
+      ",current_balance_frac"
+      ",expiration_date"
+      ",gc_date"
+      ") VALUES "
+      "($1, $2, $3, $4, $5)"
+      " ON CONFLICT DO NOTHING"
+      " RETURNING reserve_uuid;",
+      5),
     /* Used in #postgres_insert_reserve_closed() */
-    GNUNET_PQ_make_prepare ("reserves_close_insert",
-                            "INSERT INTO reserves_close "
-                            "(reserve_uuid"
-                            ",execution_date"
-                            ",wtid"
-                            ",receiver_account"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            ") SELECT reserve_uuid, $2, $3, $4, $5, $6, $7, $8"
-                            "  FROM reserves"
-                            "  WHERE reserve_pub=$1;",
-                            8),
+    GNUNET_PQ_make_prepare (
+      "reserves_close_insert",
+      "INSERT INTO reserves_close "
+      "(reserve_uuid"
+      ",execution_date"
+      ",wtid"
+      ",wire_target_serial_id"
+      ",amount_val"
+      ",amount_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      ") SELECT reserve_uuid, $2, $3, $4, $5, $6, $7, $8"
+      "  FROM reserves"
+      "  WHERE reserve_pub=$1;",
+      8),
     /* Used in #reserves_update() when the reserve is updated */
-    GNUNET_PQ_make_prepare ("reserve_update",
-                            "UPDATE reserves"
-                            " SET"
-                            " expiration_date=$1"
-                            ",gc_date=$2"
-                            ",current_balance_val=$3"
-                            ",current_balance_frac=$4"
-                            " WHERE reserve_pub=$5;",
-                            5),
+    GNUNET_PQ_make_prepare (
+      "reserve_update",
+      "UPDATE reserves"
+      " SET"
+      " expiration_date=$1"
+      ",gc_date=$2"
+      ",current_balance_val=$3"
+      ",current_balance_frac=$4"
+      " WHERE reserve_pub=$5;",
+      5),
     /* Used in #postgres_reserves_in_insert() to store transaction details */
-    GNUNET_PQ_make_prepare ("reserves_in_add_transaction",
-                            "INSERT INTO reserves_in "
-                            "(reserve_uuid"
-                            ",wire_reference"
-                            ",credit_val"
-                            ",credit_frac"
-                            ",exchange_account_section"
-                            ",sender_account_details"
-                            ",execution_date"
-                            ") SELECT reserve_uuid, $2, $3, $4, $5, $6, $7"
-                            "  FROM reserves"
-                            "  WHERE reserve_pub=$1"
-                            " ON CONFLICT DO NOTHING;",
-                            7),
+    GNUNET_PQ_make_prepare (
+      "reserves_in_add_transaction",
+      "INSERT INTO reserves_in "
+      "(reserve_uuid"
+      ",wire_reference"
+      ",credit_val"
+      ",credit_frac"
+      ",exchange_account_section"
+      ",wire_source_serial_id"
+      ",execution_date"
+      ") SELECT reserve_uuid, $2, $3, $4, $5, $6, $7"
+      "  FROM reserves"
+      "  WHERE reserve_pub=$1"
+      " ON CONFLICT DO NOTHING;",
+      7),
     /* Used in #postgres_reserves_in_insert() to store transaction details */
-    GNUNET_PQ_make_prepare ("reserves_in_add_by_uuid",
-                            "INSERT INTO reserves_in "
-                            "(reserve_uuid"
-                            ",wire_reference"
-                            ",credit_val"
-                            ",credit_frac"
-                            ",exchange_account_section"
-                            ",sender_account_details"
-                            ",execution_date"
-                            ") VALUES ($1, $2, $3, $4, $5, $6, $7)"
-                            " ON CONFLICT DO NOTHING;",
-                            7),
+    GNUNET_PQ_make_prepare (
+      "reserves_in_add_by_uuid",
+      "INSERT INTO reserves_in "
+      "(reserve_uuid"
+      ",wire_reference"
+      ",credit_val"
+      ",credit_frac"
+      ",exchange_account_section"
+      ",wire_source_serial_id"
+      ",execution_date"
+      ") VALUES ($1, $2, $3, $4, $5, $6, $7)"
+      " ON CONFLICT DO NOTHING;",
+      7),
     /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound
        transactions for reserves with serial id '\geq' the given parameter */
-    GNUNET_PQ_make_prepare ("reserves_in_get_latest_wire_reference",
-                            "SELECT"
-                            " wire_reference"
-                            " FROM reserves_in"
-                            " WHERE exchange_account_section=$1"
-                            " ORDER BY reserve_in_serial_id DESC"
-                            " LIMIT 1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "reserves_in_get_latest_wire_reference",
+      "SELECT"
+      " wire_reference"
+      " FROM reserves_in"
+      " WHERE exchange_account_section=$1"
+      " ORDER BY reserve_in_serial_id DESC"
+      " LIMIT 1;",
+      1),
     /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound
        transactions for reserves with serial id '\geq' the given parameter */
-    GNUNET_PQ_make_prepare ("audit_reserves_in_get_transactions_incr",
-                            "SELECT"
-                            " reserves.reserve_pub"
-                            ",wire_reference"
-                            ",credit_val"
-                            ",credit_frac"
-                            ",execution_date"
-                            ",sender_account_details"
-                            ",reserve_in_serial_id"
-                            " FROM reserves_in"
-                            " JOIN reserves"
-                            "   USING (reserve_uuid)"
-                            " WHERE reserve_in_serial_id>=$1"
-                            " ORDER BY reserve_in_serial_id;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "audit_reserves_in_get_transactions_incr",
+      "SELECT"
+      " reserves.reserve_pub"
+      ",wire_reference"
+      ",credit_val"
+      ",credit_frac"
+      ",execution_date"
+      ",payto_uri AS sender_account_details"
+      ",reserve_in_serial_id"
+      " FROM reserves_in"
+      " JOIN reserves"
+      "   USING (reserve_uuid)"
+      " JOIN wire_targets"
+      "   ON (wire_source_serial_id = wire_target_serial_id)"
+      " WHERE reserve_in_serial_id>=$1"
+      " ORDER BY reserve_in_serial_id;",
+      1),
     /* Used in postgres_select_reserves_in_above_serial_id() to obtain inbound
        transactions for reserves with serial id '\geq' the given parameter */
     GNUNET_PQ_make_prepare (
@@ -516,35 +555,41 @@ prepare_statements (struct PostgresClosure *pg)
       ",credit_val"
       ",credit_frac"
       ",execution_date"
-      ",sender_account_details"
+      ",payto_uri AS sender_account_details"
       ",reserve_in_serial_id"
       " FROM reserves_in"
       " JOIN reserves "
       "   USING (reserve_uuid)"
+      " JOIN wire_targets"
+      "   ON (wire_source_serial_id = wire_target_serial_id)"
       " WHERE reserve_in_serial_id>=$1 AND exchange_account_section=$2"
       " ORDER BY reserve_in_serial_id;",
       2),
     /* Used in #postgres_get_reserve_history() to obtain inbound transactions
        for a reserve */
-    GNUNET_PQ_make_prepare ("reserves_in_get_transactions",
-                            "SELECT"
-                            " wire_reference"
-                            ",credit_val"
-                            ",credit_frac"
-                            ",execution_date"
-                            ",sender_account_details"
-                            " FROM reserves_in"
-                            " WHERE reserve_uuid="
-                            " (SELECT reserve_uuid "
-                            "   FROM reserves"
-                            "   WHERE reserve_pub=$1);",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "reserves_in_get_transactions",
+      "SELECT"
+      " wire_reference"
+      ",credit_val"
+      ",credit_frac"
+      ",execution_date"
+      ",payto_uri AS sender_account_details"
+      " FROM reserves_in"
+      " JOIN wire_targets"
+      "   ON (wire_source_serial_id = wire_target_serial_id)"
+      " WHERE reserve_uuid="
+      " (SELECT reserve_uuid "
+      "   FROM reserves"
+      "   WHERE reserve_pub=$1);",
+      1),
     /* Lock withdraw table; NOTE: we may want to eventually shard the
        deposit table to avoid this lock being the main point of
        contention limiting transaction performance. */
-    GNUNET_PQ_make_prepare ("lock_withdraw",
-                            "LOCK TABLE reserves_out;",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "lock_withdraw",
+      "LOCK TABLE reserves_out;",
+      0),
     /* Used in #postgres_insert_withdraw_info() to store
        the signature of a blinded coin with the blinded coin's
        details before returning it during /reserve/withdraw. We store
@@ -552,1379 +597,1532 @@ prepare_statements (struct PostgresClosure *pg)
        and the blinded message as well as the reserve that the coin
        is being withdrawn from and the signature of the message
        authorizing the withdrawal. */
-    GNUNET_PQ_make_prepare ("insert_withdraw_info",
-                            "WITH ds AS"
-                            " (SELECT denominations_serial"
-                            "    FROM denominations"
-                            "   WHERE denom_pub_hash=$2)"
-                            "INSERT INTO reserves_out "
-                            "(h_blind_ev"
-                            ",denominations_serial"
-                            ",denom_sig"
-                            ",reserve_uuid"
-                            ",reserve_sig"
-                            ",execution_date"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ") SELECT $1, ds.denominations_serial, $3, 
reserve_uuid, $5, $6, $7, $8"
-                            "    FROM reserves"
-                            "    CROSS JOIN ds"
-                            "    WHERE reserve_pub=$4;",
-                            8),
+    GNUNET_PQ_make_prepare (
+      "insert_withdraw_info",
+      "WITH ds AS"
+      " (SELECT denominations_serial"
+      "    FROM denominations"
+      "   WHERE denom_pub_hash=$2)"
+      "INSERT INTO reserves_out "
+      "(h_blind_ev"
+      ",denominations_serial"
+      ",denom_sig"
+      ",reserve_uuid"
+      ",reserve_sig"
+      ",execution_date"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ") SELECT $1, ds.denominations_serial, $3, reserve_uuid, $5, $6, $7, $8"
+      "    FROM reserves"
+      "    CROSS JOIN ds"
+      "    WHERE reserve_pub=$4;",
+      8),
     /* Used in #postgres_get_withdraw_info() to
        locate the response for a /reserve/withdraw request
        using the hash of the blinded message.  Used to
        make sure /reserve/withdraw requests are idempotent. */
-    GNUNET_PQ_make_prepare ("get_withdraw_info",
-                            "SELECT"
-                            " denom.denom_pub_hash"
-                            ",denom_sig"
-                            ",reserve_sig"
-                            ",reserves.reserve_pub"
-                            ",execution_date"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",denom.fee_withdraw_val"
-                            ",denom.fee_withdraw_frac"
-                            " FROM reserves_out"
-                            "    JOIN reserves"
-                            "      USING (reserve_uuid)"
-                            "    JOIN denominations denom"
-                            "      USING (denominations_serial)"
-                            " WHERE h_blind_ev=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_withdraw_info",
+      "SELECT"
+      " denom.denom_pub_hash"
+      ",denom_sig"
+      ",reserve_sig"
+      ",reserves.reserve_pub"
+      ",execution_date"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",denom.fee_withdraw_val"
+      ",denom.fee_withdraw_frac"
+      " FROM reserves_out"
+      "    JOIN reserves"
+      "      USING (reserve_uuid)"
+      "    JOIN denominations denom"
+      "      USING (denominations_serial)"
+      " WHERE h_blind_ev=$1;",
+      1),
     /* Used during #postgres_get_reserve_history() to
        obtain all of the /reserve/withdraw operations that
        have been performed on a given reserve. (i.e. to
        demonstrate double-spending) */
-    GNUNET_PQ_make_prepare ("get_reserves_out",
-                            "SELECT"
-                            " h_blind_ev"
-                            ",denom.denom_pub_hash"
-                            ",denom_sig"
-                            ",reserve_sig"
-                            ",execution_date"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",denom.fee_withdraw_val"
-                            ",denom.fee_withdraw_frac"
-                            " FROM reserves_out"
-                            "    JOIN denominations denom"
-                            "      USING (denominations_serial)"
-                            " WHERE reserve_uuid="
-                            "   (SELECT reserve_uuid"
-                            "      FROM reserves"
-                            "     WHERE reserve_pub=$1);",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_reserves_out",
+      "SELECT"
+      " h_blind_ev"
+      ",denom.denom_pub_hash"
+      ",denom_sig"
+      ",reserve_sig"
+      ",execution_date"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",denom.fee_withdraw_val"
+      ",denom.fee_withdraw_frac"
+      " FROM reserves_out"
+      "    JOIN denominations denom"
+      "      USING (denominations_serial)"
+      " WHERE reserve_uuid="
+      "   (SELECT reserve_uuid"
+      "      FROM reserves"
+      "     WHERE reserve_pub=$1);",
+      1),
     /* Used in #postgres_select_withdrawals_above_serial_id() */
-    GNUNET_PQ_make_prepare ("audit_get_reserves_out_incr",
-                            "SELECT"
-                            " h_blind_ev"
-                            ",denom.denom_pub"
-                            ",reserve_sig"
-                            ",reserves.reserve_pub"
-                            ",execution_date"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",reserve_out_serial_id"
-                            " FROM reserves_out"
-                            "    JOIN reserves"
-                            "      USING (reserve_uuid)"
-                            "    JOIN denominations denom"
-                            "      USING (denominations_serial)"
-                            " WHERE reserve_out_serial_id>=$1"
-                            " ORDER BY reserve_out_serial_id ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "audit_get_reserves_out_incr",
+      "SELECT"
+      " h_blind_ev"
+      ",denom.denom_pub"
+      ",reserve_sig"
+      ",reserves.reserve_pub"
+      ",execution_date"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",reserve_out_serial_id"
+      " FROM reserves_out"
+      "    JOIN reserves"
+      "      USING (reserve_uuid)"
+      "    JOIN denominations denom"
+      "      USING (denominations_serial)"
+      " WHERE reserve_out_serial_id>=$1"
+      " ORDER BY reserve_out_serial_id ASC;",
+      1),
 
     /* Used in #postgres_count_known_coins() */
-    GNUNET_PQ_make_prepare ("count_known_coins",
-                            "SELECT"
-                            " COUNT(*) AS count"
-                            " FROM known_coins"
-                            " WHERE denominations_serial="
-                            "  (SELECT denominations_serial"
-                            "    FROM denominations"
-                            "    WHERE denom_pub_hash=$1);",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "count_known_coins",
+      "SELECT"
+      " COUNT(*) AS count"
+      " FROM known_coins"
+      " WHERE denominations_serial="
+      "  (SELECT denominations_serial"
+      "    FROM denominations"
+      "    WHERE denom_pub_hash=$1);",
+      1),
     /* Used in #postgres_get_known_coin() to fetch
        the denomination public key and signature for
        a coin known to the exchange. */
-    GNUNET_PQ_make_prepare ("get_known_coin",
-                            "SELECT"
-                            " denominations.denom_pub_hash"
-                            ",denom_sig"
-                            " FROM known_coins"
-                            " JOIN denominations USING (denominations_serial)"
-                            " WHERE coin_pub=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_known_coin",
+      "SELECT"
+      " denominations.denom_pub_hash"
+      ",denom_sig"
+      " FROM known_coins"
+      " JOIN denominations USING (denominations_serial)"
+      " WHERE coin_pub=$1;",
+      1),
     /* Used in #postgres_ensure_coin_known() */
-    GNUNET_PQ_make_prepare ("get_known_coin_dh",
-                            "SELECT"
-                            " denominations.denom_pub_hash"
-                            " FROM known_coins"
-                            " JOIN denominations USING (denominations_serial)"
-                            " WHERE coin_pub=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_known_coin_dh",
+      "SELECT"
+      " denominations.denom_pub_hash"
+      " FROM known_coins"
+      " JOIN denominations USING (denominations_serial)"
+      " WHERE coin_pub=$1;",
+      1),
     /* Used in #postgres_get_coin_denomination() to fetch
        the denomination public key hash for
        a coin known to the exchange. */
-    GNUNET_PQ_make_prepare ("get_coin_denomination",
-                            "SELECT"
-                            " denominations.denom_pub_hash"
-                            " FROM known_coins"
-                            " JOIN denominations USING (denominations_serial)"
-                            " WHERE coin_pub=$1"
-                            " FOR SHARE;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_coin_denomination",
+      "SELECT"
+      " denominations.denom_pub_hash"
+      " FROM known_coins"
+      " JOIN denominations USING (denominations_serial)"
+      " WHERE coin_pub=$1"
+      " FOR SHARE;",
+      1),
     /* Lock deposit table; NOTE: we may want to eventually shard the
        deposit table to avoid this lock being the main point of
        contention limiting transaction performance. */
-    GNUNET_PQ_make_prepare ("lock_known_coins",
-                            "LOCK TABLE known_coins;",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "lock_known_coins",
+      "LOCK TABLE known_coins;",
+      0),
     /* Used in #postgres_insert_known_coin() to store
        the denomination public key and signature for
        a coin known to the exchange. */
-    GNUNET_PQ_make_prepare ("insert_known_coin",
-                            "INSERT INTO known_coins "
-                            "(coin_pub"
-                            ",denominations_serial"
-                            ",denom_sig"
-                            ") SELECT $1, denominations_serial, $3 "
-                            "    FROM denominations"
-                            "   WHERE denom_pub_hash=$2;",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "insert_known_coin",
+      "INSERT INTO known_coins "
+      "(coin_pub"
+      ",denominations_serial"
+      ",denom_sig"
+      ") SELECT $1, denominations_serial, $3 "
+      "    FROM denominations"
+      "   WHERE denom_pub_hash=$2;",
+      3),
 
     /* Used in #postgres_insert_melt() to store
        high-level information about a melt operation */
-    GNUNET_PQ_make_prepare ("insert_melt",
-                            "INSERT INTO refresh_commitments "
-                            "(rc "
-                            ",old_known_coin_id "
-                            ",old_coin_sig "
-                            ",amount_with_fee_val "
-                            ",amount_with_fee_frac "
-                            ",noreveal_index "
-                            ") SELECT $1, known_coin_id, $3, $4, $5, $6"
-                            "    FROM known_coins"
-                            "   WHERE coin_pub=$2",
-                            6),
+    GNUNET_PQ_make_prepare (
+      "insert_melt",
+      "INSERT INTO refresh_commitments "
+      "(rc "
+      ",old_known_coin_id "
+      ",old_coin_sig "
+      ",amount_with_fee_val "
+      ",amount_with_fee_frac "
+      ",noreveal_index "
+      ") SELECT $1, known_coin_id, $3, $4, $5, $6"
+      "    FROM known_coins"
+      "   WHERE coin_pub=$2",
+      6),
     /* Used in #postgres_get_melt() to fetch
        high-level information about a melt operation */
-    GNUNET_PQ_make_prepare ("get_melt",
-                            "SELECT"
-                            " denoms.denom_pub_hash"
-                            ",denoms.fee_refresh_val"
-                            ",denoms.fee_refresh_frac"
-                            ",kc.coin_pub AS old_coin_pub"
-                            ",old_coin_sig"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",noreveal_index"
-                            " FROM refresh_commitments"
-                            "   JOIN known_coins kc"
-                            "     ON (refresh_commitments.old_known_coin_id = 
kc.known_coin_id)"
-                            "   JOIN denominations denoms"
-                            "     ON (kc.denominations_serial = 
denoms.denominations_serial)"
-                            " WHERE rc=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_melt",
+      "SELECT"
+      " denoms.denom_pub_hash"
+      ",denoms.fee_refresh_val"
+      ",denoms.fee_refresh_frac"
+      ",kc.coin_pub AS old_coin_pub"
+      ",old_coin_sig"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",noreveal_index"
+      " FROM refresh_commitments"
+      "   JOIN known_coins kc"
+      "     ON (refresh_commitments.old_known_coin_id = kc.known_coin_id)"
+      "   JOIN denominations denoms"
+      "     ON (kc.denominations_serial = denoms.denominations_serial)"
+      " WHERE rc=$1;",
+      1),
     /* Used in #postgres_get_melt_index() to fetch
        the noreveal index from a previous melt operation */
-    GNUNET_PQ_make_prepare ("get_melt_index",
-                            "SELECT"
-                            " noreveal_index"
-                            " FROM refresh_commitments"
-                            " WHERE rc=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_melt_index",
+      "SELECT"
+      " noreveal_index"
+      " FROM refresh_commitments"
+      " WHERE rc=$1;",
+      1),
     /* Used in #postgres_select_refreshes_above_serial_id() to fetch
        refresh session with id '\geq' the given parameter */
-    GNUNET_PQ_make_prepare ("audit_get_refresh_commitments_incr",
-                            "SELECT"
-                            " denom.denom_pub"
-                            ",kc.coin_pub AS old_coin_pub"
-                            ",old_coin_sig"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",noreveal_index"
-                            ",melt_serial_id"
-                            ",rc"
-                            " FROM refresh_commitments"
-                            "   JOIN known_coins kc"
-                            "     ON (refresh_commitments.old_known_coin_id = 
kc.known_coin_id)"
-                            "   JOIN denominations denom"
-                            "     ON (kc.denominations_serial = 
denom.denominations_serial)"
-                            " WHERE melt_serial_id>=$1"
-                            " ORDER BY melt_serial_id ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "audit_get_refresh_commitments_incr",
+      "SELECT"
+      " denom.denom_pub"
+      ",kc.coin_pub AS old_coin_pub"
+      ",old_coin_sig"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",noreveal_index"
+      ",melt_serial_id"
+      ",rc"
+      " FROM refresh_commitments"
+      "   JOIN known_coins kc"
+      "     ON (refresh_commitments.old_known_coin_id = kc.known_coin_id)"
+      "   JOIN denominations denom"
+      "     ON (kc.denominations_serial = denom.denominations_serial)"
+      " WHERE melt_serial_id>=$1"
+      " ORDER BY melt_serial_id ASC;",
+      1),
     /* Query the 'refresh_commitments' by coin public key */
-    GNUNET_PQ_make_prepare ("get_refresh_session_by_coin",
-                            "SELECT"
-                            " rc"
-                            ",old_coin_sig"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",denoms.denom_pub_hash"
-                            ",denoms.fee_refresh_val"
-                            ",denoms.fee_refresh_frac"
-                            ",melt_serial_id"
-                            " FROM refresh_commitments"
-                            " JOIN known_coins kc"
-                            "   ON (refresh_commitments.old_known_coin_id = 
kc.known_coin_id)"
-                            " JOIN denominations denoms"
-                            "   USING (denominations_serial)"
-                            " WHERE old_known_coin_id="
-                            "(SELECT known_coin_id"
-                            "   FROM known_coins"
-                            "  WHERE coin_pub=$1);",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_refresh_session_by_coin",
+      "SELECT"
+      " rc"
+      ",old_coin_sig"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",denoms.denom_pub_hash"
+      ",denoms.fee_refresh_val"
+      ",denoms.fee_refresh_frac"
+      ",melt_serial_id"
+      " FROM refresh_commitments"
+      " JOIN known_coins kc"
+      "   ON (refresh_commitments.old_known_coin_id = kc.known_coin_id)"
+      " JOIN denominations denoms"
+      "   USING (denominations_serial)"
+      " WHERE old_known_coin_id="
+      "(SELECT known_coin_id"
+      "   FROM known_coins"
+      "  WHERE coin_pub=$1);",
+      1),
     /* Store information about the desired denominations for a
        refresh operation, used in #postgres_insert_refresh_reveal() */
-    GNUNET_PQ_make_prepare ("insert_refresh_revealed_coin",
-                            "WITH rcx AS"
-                            " (SELECT melt_serial_id"
-                            "    FROM refresh_commitments"
-                            "   WHERE rc=$1)"
-                            "INSERT INTO refresh_revealed_coins "
-                            "(melt_serial_id "
-                            ",freshcoin_index "
-                            ",link_sig "
-                            ",denominations_serial "
-                            ",coin_ev"
-                            ",h_coin_ev"
-                            ",ev_sig"
-                            ") SELECT rcx.melt_serial_id, $2, $3, "
-                            "         denominations_serial, $5, $6, $7"
-                            "    FROM denominations"
-                            "   CROSS JOIN rcx"
-                            "   WHERE denom_pub_hash=$4;",
-                            7),
+    GNUNET_PQ_make_prepare (
+      "insert_refresh_revealed_coin",
+      "WITH rcx AS"
+      " (SELECT melt_serial_id"
+      "    FROM refresh_commitments"
+      "   WHERE rc=$1)"
+      "INSERT INTO refresh_revealed_coins "
+      "(melt_serial_id "
+      ",freshcoin_index "
+      ",link_sig "
+      ",denominations_serial "
+      ",coin_ev"
+      ",h_coin_ev"
+      ",ev_sig"
+      ") SELECT rcx.melt_serial_id, $2, $3, "
+      "         denominations_serial, $5, $6, $7"
+      "    FROM denominations"
+      "   CROSS JOIN rcx"
+      "   WHERE denom_pub_hash=$4;",
+      7),
     /* Obtain information about the coins created in a refresh
        operation, used in #postgres_get_refresh_reveal() */
-    GNUNET_PQ_make_prepare ("get_refresh_revealed_coins",
-                            "SELECT "
-                            " rrc.freshcoin_index"
-                            ",denom.denom_pub"
-                            ",rrc.link_sig"
-                            ",rrc.coin_ev"
-                            ",rrc.ev_sig"
-                            " FROM refresh_commitments"
-                            "    JOIN refresh_revealed_coins rrc"
-                            "      USING (melt_serial_id)"
-                            "    JOIN denominations denom "
-                            "      USING (denominations_serial)"
-                            " WHERE rc=$1"
-                            "   ORDER BY freshcoin_index ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_refresh_revealed_coins",
+      "SELECT "
+      " rrc.freshcoin_index"
+      ",denom.denom_pub"
+      ",rrc.link_sig"
+      ",rrc.coin_ev"
+      ",rrc.ev_sig"
+      " FROM refresh_commitments"
+      "    JOIN refresh_revealed_coins rrc"
+      "      USING (melt_serial_id)"
+      "    JOIN denominations denom "
+      "      USING (denominations_serial)"
+      " WHERE rc=$1"
+      "   ORDER BY freshcoin_index ASC;",
+      1),
 
     /* Used in #postgres_insert_refresh_reveal() to store the transfer
        keys we learned */
-    GNUNET_PQ_make_prepare ("insert_refresh_transfer_keys",
-                            "INSERT INTO refresh_transfer_keys "
-                            "(melt_serial_id"
-                            ",transfer_pub"
-                            ",transfer_privs"
-                            ") SELECT melt_serial_id, $2, $3"
-                            "    FROM refresh_commitments"
-                            "   WHERE rc=$1",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "insert_refresh_transfer_keys",
+      "INSERT INTO refresh_transfer_keys "
+      "(melt_serial_id"
+      ",transfer_pub"
+      ",transfer_privs"
+      ") SELECT melt_serial_id, $2, $3"
+      "    FROM refresh_commitments"
+      "   WHERE rc=$1",
+      3),
     /* Used in #postgres_get_refresh_reveal() to retrieve transfer
        keys from /refresh/reveal */
-    GNUNET_PQ_make_prepare ("get_refresh_transfer_keys",
-                            "SELECT"
-                            " transfer_pub"
-                            ",transfer_privs"
-                            " FROM refresh_transfer_keys"
-                            " JOIN refresh_commitments"
-                            "   USING (melt_serial_id)"
-                            " WHERE rc=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_refresh_transfer_keys",
+      "SELECT"
+      " transfer_pub"
+      ",transfer_privs"
+      " FROM refresh_transfer_keys"
+      " JOIN refresh_commitments"
+      "   USING (melt_serial_id)"
+      " WHERE rc=$1;",
+      1),
     /* Used in #postgres_insert_refund() to store refund information */
-    GNUNET_PQ_make_prepare ("insert_refund",
-                            "INSERT INTO refunds "
-                            "(deposit_serial_id "
-                            ",merchant_sig "
-                            ",rtransaction_id "
-                            ",amount_with_fee_val "
-                            ",amount_with_fee_frac "
-                            ") SELECT deposit_serial_id, $3, $5, $6, $7"
-                            "    FROM deposits"
-                            "    JOIN known_coins USING (known_coin_id)"
-                            "   WHERE coin_pub=$1"
-                            "     AND h_contract_terms=$4"
-                            "     AND merchant_pub=$2",
-                            7),
+    GNUNET_PQ_make_prepare (
+      "insert_refund",
+      "INSERT INTO refunds "
+      "(deposit_serial_id "
+      ",merchant_sig "
+      ",rtransaction_id "
+      ",amount_with_fee_val "
+      ",amount_with_fee_frac "
+      ") SELECT deposit_serial_id, $3, $5, $6, $7"
+      "    FROM deposits"
+      "    JOIN known_coins USING (known_coin_id)"
+      "   WHERE coin_pub=$1"
+      "     AND h_contract_terms=$4"
+      "     AND merchant_pub=$2",
+      7),
     /* Query the 'refunds' by coin public key */
-    GNUNET_PQ_make_prepare ("get_refunds_by_coin",
-                            "SELECT"
-                            " merchant_pub"
-                            ",merchant_sig"
-                            ",h_contract_terms"
-                            ",rtransaction_id"
-                            ",refunds.amount_with_fee_val"
-                            ",refunds.amount_with_fee_frac"
-                            ",denom.fee_refund_val "
-                            ",denom.fee_refund_frac "
-                            ",refund_serial_id"
-                            " FROM refunds"
-                            " JOIN deposits USING (deposit_serial_id)"
-                            " JOIN known_coins USING (known_coin_id)"
-                            " JOIN denominations denom USING 
(denominations_serial)"
-                            " WHERE coin_pub=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_refunds_by_coin",
+      "SELECT"
+      " merchant_pub"
+      ",merchant_sig"
+      ",h_contract_terms"
+      ",rtransaction_id"
+      ",refunds.amount_with_fee_val"
+      ",refunds.amount_with_fee_frac"
+      ",denom.fee_refund_val "
+      ",denom.fee_refund_frac "
+      ",refund_serial_id"
+      " FROM refunds"
+      " JOIN deposits USING (deposit_serial_id)"
+      " JOIN known_coins USING (known_coin_id)"
+      " JOIN denominations denom USING (denominations_serial)"
+      " WHERE coin_pub=$1;",
+      1),
     /* Query the 'refunds' by coin public key, merchant_pub and contract hash 
*/
-    GNUNET_PQ_make_prepare ("get_refunds_by_coin_and_contract",
-                            "SELECT"
-                            " refunds.amount_with_fee_val"
-                            ",refunds.amount_with_fee_frac"
-                            " FROM refunds"
-                            " JOIN deposits USING (deposit_serial_id)"
-                            " JOIN known_coins USING (known_coin_id)"
-                            " WHERE coin_pub=$1"
-                            "   AND merchant_pub=$2"
-                            "   AND h_contract_terms=$3;",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "get_refunds_by_coin_and_contract",
+      "SELECT"
+      " refunds.amount_with_fee_val"
+      ",refunds.amount_with_fee_frac"
+      " FROM refunds"
+      " JOIN deposits USING (deposit_serial_id)"
+      " JOIN known_coins USING (known_coin_id)"
+      " WHERE coin_pub=$1"
+      "   AND merchant_pub=$2"
+      "   AND h_contract_terms=$3;",
+      3),
     /* Fetch refunds with rowid '\geq' the given parameter */
-    GNUNET_PQ_make_prepare ("audit_get_refunds_incr",
-                            "SELECT"
-                            " merchant_pub"
-                            ",merchant_sig"
-                            ",h_contract_terms"
-                            ",rtransaction_id"
-                            ",denom.denom_pub"
-                            ",kc.coin_pub"
-                            ",refunds.amount_with_fee_val"
-                            ",refunds.amount_with_fee_frac"
-                            ",refund_serial_id"
-                            " FROM refunds"
-                            "   JOIN deposits USING (deposit_serial_id)"
-                            "   JOIN known_coins kc USING (known_coin_id)"
-                            "   JOIN denominations denom ON 
(kc.denominations_serial = denom.denominations_serial)"
-                            " WHERE refund_serial_id>=$1"
-                            " ORDER BY refund_serial_id ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "audit_get_refunds_incr",
+      "SELECT"
+      " merchant_pub"
+      ",merchant_sig"
+      ",h_contract_terms"
+      ",rtransaction_id"
+      ",denom.denom_pub"
+      ",kc.coin_pub"
+      ",refunds.amount_with_fee_val"
+      ",refunds.amount_with_fee_frac"
+      ",refund_serial_id"
+      " FROM refunds"
+      "   JOIN deposits USING (deposit_serial_id)"
+      "   JOIN known_coins kc USING (known_coin_id)"
+      "   JOIN denominations denom ON (kc.denominations_serial = 
denom.denominations_serial)"
+      " WHERE refund_serial_id>=$1"
+      " ORDER BY refund_serial_id ASC;",
+      1),
     /* Lock deposit table; NOTE: we may want to eventually shard the
        deposit table to avoid this lock being the main point of
        contention limiting transaction performance. */
-    GNUNET_PQ_make_prepare ("lock_deposit",
-                            "LOCK TABLE deposits;",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "lock_deposit",
+      "LOCK TABLE deposits;",
+      0),
     /* Store information about a /deposit the exchange is to execute.
        Used in #postgres_insert_deposit(). */
-    GNUNET_PQ_make_prepare ("insert_deposit",
-                            "INSERT INTO deposits "
-                            "(known_coin_id"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",wallet_timestamp"
-                            ",refund_deadline"
-                            ",wire_deadline"
-                            ",merchant_pub"
-                            ",h_contract_terms"
-                            ",h_wire"
-                            ",coin_sig"
-                            ",wire"
-                            ",exchange_timestamp"
-                            ",shard"
-                            ") SELECT known_coin_id, $2, $3, $4, $5, $6, "
-                            " $7, $8, $9, $10, $11, $12, $13"
-                            "    FROM known_coins"
-                            "   WHERE coin_pub=$1;",
-                            13),
+    GNUNET_PQ_make_prepare (
+      "insert_deposit",
+      "INSERT INTO deposits "
+      "(known_coin_id"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",wallet_timestamp"
+      ",refund_deadline"
+      ",wire_deadline"
+      ",merchant_pub"
+      ",h_contract_terms"
+      ",wire_salt"
+      ",wire_target_serial_id"
+      ",coin_sig"
+      ",exchange_timestamp"
+      ",shard"
+      ") SELECT known_coin_id, $2, $3, $4, $5, $6, "
+      " $7, $8, $9, $10, $11, $12, $13"
+      "    FROM known_coins"
+      "   WHERE coin_pub=$1;",
+      13),
     /* Fetch an existing deposit request, used to ensure idempotency
        during /deposit processing. Used in #postgres_have_deposit(). */
-    GNUNET_PQ_make_prepare ("get_deposit",
-                            "SELECT"
-                            " amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",denominations.fee_deposit_val"
-                            ",denominations.fee_deposit_frac"
-                            ",wallet_timestamp"
-                            ",exchange_timestamp"
-                            ",refund_deadline"
-                            ",wire_deadline"
-                            ",h_contract_terms"
-                            ",h_wire"
-                            " FROM deposits"
-                            " JOIN known_coins USING (known_coin_id)"
-                            " JOIN denominations USING (denominations_serial)"
-                            " WHERE ((coin_pub=$1)"
-                            "    AND (merchant_pub=$3)"
-                            "    AND (h_contract_terms=$2));",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "get_deposit",
+      "SELECT"
+      " amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",denominations.fee_deposit_val"
+      ",denominations.fee_deposit_frac"
+      ",wallet_timestamp"
+      ",exchange_timestamp"
+      ",refund_deadline"
+      ",wire_deadline"
+      ",h_contract_terms"
+      ",wire_salt"
+      ",payto_uri AS receiver_wire_account"
+      " FROM deposits"
+      " JOIN known_coins USING (known_coin_id)"
+      " JOIN denominations USING (denominations_serial)"
+      " JOIN wire_targets USING (wire_target_serial_id)"
+      " WHERE ((coin_pub=$1)"
+      "    AND (merchant_pub=$3)"
+      "    AND (h_contract_terms=$2));",
+      3),
     /* Fetch deposits with rowid '\geq' the given parameter */
-    GNUNET_PQ_make_prepare ("audit_get_deposits_incr",
-                            "SELECT"
-                            " amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",wallet_timestamp"
-                            ",exchange_timestamp"
-                            ",merchant_pub"
-                            ",denom.denom_pub"
-                            ",kc.coin_pub"
-                            ",coin_sig"
-                            ",refund_deadline"
-                            ",wire_deadline"
-                            ",h_contract_terms"
-                            ",wire"
-                            ",done"
-                            ",deposit_serial_id"
-                            " FROM deposits"
-                            "    JOIN known_coins kc USING (known_coin_id)"
-                            "    JOIN denominations denom USING 
(denominations_serial)"
-                            " WHERE ("
-                            "  (deposit_serial_id>=$1)"
-                            " )"
-                            " ORDER BY deposit_serial_id ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "audit_get_deposits_incr",
+      "SELECT"
+      " amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",wallet_timestamp"
+      ",exchange_timestamp"
+      ",merchant_pub"
+      ",denom.denom_pub"
+      ",kc.coin_pub"
+      ",coin_sig"
+      ",refund_deadline"
+      ",wire_deadline"
+      ",h_contract_terms"
+      ",wire_salt"
+      ",payto_uri AS receiver_wire_account"
+      ",done"
+      ",deposit_serial_id"
+      " FROM deposits"
+      "    JOIN wire_targets USING (wire_target_serial_id)"
+      "    JOIN known_coins kc USING (known_coin_id)"
+      "    JOIN denominations denom USING (denominations_serial)"
+      " WHERE ("
+      "  (deposit_serial_id>=$1)"
+      " )"
+      " ORDER BY deposit_serial_id ASC;",
+      1),
     /* Fetch an existing deposit request.
        Used in #postgres_lookup_transfer_by_deposit(). */
-    GNUNET_PQ_make_prepare ("get_deposit_for_wtid",
-                            "SELECT"
-                            " FALSE AS kyc_ok" // FIXME
-                            ",CAST (0 AS INT8) AS payment_target_uuid" // FIXME
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",denom.fee_deposit_val"
-                            ",denom.fee_deposit_frac"
-                            ",wire_deadline"
-                            " FROM deposits"
-                            "    JOIN known_coins USING (known_coin_id)"
-                            "    JOIN denominations denom USING 
(denominations_serial)"
-                            " WHERE ((coin_pub=$1)"
-                            "    AND (merchant_pub=$4)"
-                            "    AND (h_contract_terms=$2)"
-                            "    AND (h_wire=$3)"
-                            " );",
-                            4),
+    GNUNET_PQ_make_prepare (
+      "get_deposit_without_wtid",
+      "SELECT"
+      " kyc_ok"
+      ",wire_target_serial_id AS payment_target_uuid"
+      ",wire_salt"
+      ",payto_uri"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",denom.fee_deposit_val"
+      ",denom.fee_deposit_frac"
+      ",wire_deadline"
+      " FROM deposits"
+      "    JOIN wire_targets USING (wire_target_serial_id)"
+      "    JOIN known_coins USING (known_coin_id)"
+      "    JOIN denominations denom USING (denominations_serial)"
+      " WHERE ((coin_pub=$1)"
+      "    AND (merchant_pub=$3)"
+      "    AND (h_contract_terms=$2)"
+      " );",
+      3),
     /* Used in #postgres_get_ready_deposit() */
-    GNUNET_PQ_make_prepare ("deposits_get_ready",
-                            "SELECT"
-                            " deposit_serial_id"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",denom.fee_deposit_val"
-                            ",denom.fee_deposit_frac"
-                            ",h_contract_terms"
-                            ",wire"
-                            ",merchant_pub"
-                            ",kc.coin_pub"
-                            " FROM deposits"
-                            "    JOIN known_coins kc USING (known_coin_id)"
-                            "    JOIN denominations denom USING 
(denominations_serial)"
-                            " WHERE "
-                            "       shard >= $2"
-                            "   AND shard <= $3"
-                            "   AND tiny=FALSE"
-                            "   AND done=FALSE"
-                            "   AND wire_deadline<=$1"
-                            "   AND refund_deadline<$1"
-                            " ORDER BY "
-                            "   shard ASC"
-                            "  ,wire_deadline ASC"
-                            " LIMIT 1;",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "deposits_get_ready",
+      "SELECT"
+      " deposit_serial_id"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",denom.fee_deposit_val"
+      ",denom.fee_deposit_frac"
+      ",h_contract_terms"
+      ",payto_uri"
+      ",wire_target_serial_id"
+      ",merchant_pub"
+      ",kc.coin_pub"
+      " FROM deposits"
+      "  JOIN wire_targets "
+      "    USING (wire_target_serial_id)"
+      "  JOIN known_coins kc"
+      "    USING (known_coin_id)"
+      "  JOIN denominations denom"
+      "    USING (denominations_serial)"
+      " WHERE "
+      "       shard >= $2"
+      "   AND shard <= $3"
+      "   AND tiny=FALSE"
+      "   AND done=FALSE"
+      "   AND (kyc_ok OR $4)"
+      "   AND wire_deadline<=$1"
+      "   AND refund_deadline<$1"
+      " ORDER BY "
+      "   shard ASC"
+      "  ,wire_deadline ASC"
+      " LIMIT 1;",
+      4),
     /* Used in #postgres_iterate_matching_deposits() */
-    GNUNET_PQ_make_prepare ("deposits_iterate_matching",
-                            "SELECT"
-                            " deposit_serial_id"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",denom.fee_deposit_val"
-                            ",denom.fee_deposit_frac"
-                            ",h_contract_terms"
-                            ",kc.coin_pub"
-                            " FROM deposits"
-                            "    JOIN known_coins kc USING (known_coin_id)"
-                            "    JOIN denominations denom USING 
(denominations_serial)"
-                            " WHERE"
-                            "     merchant_pub=$1 AND"
-                            "     h_wire=$2 AND"
-                            "     done=FALSE"
-                            " ORDER BY wire_deadline ASC"
-                            " LIMIT "
-                            TALER_QUOTE (
-                              TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) ";",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "deposits_iterate_matching",
+      "SELECT"
+      " deposit_serial_id"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",denom.fee_deposit_val"
+      ",denom.fee_deposit_frac"
+      ",h_contract_terms"
+      ",kc.coin_pub"
+      " FROM deposits"
+      "    JOIN known_coins kc USING (known_coin_id)"
+      "    JOIN denominations denom USING (denominations_serial)"
+      " WHERE"
+      "     merchant_pub=$1 AND"
+      "     wire_target_serial_id=$2 AND"
+      "     done=FALSE"
+      " ORDER BY wire_deadline ASC"
+      " LIMIT "
+      TALER_QUOTE (
+        TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT) ";",
+      2),
     /* Used in #postgres_mark_deposit_tiny() */
-    GNUNET_PQ_make_prepare ("mark_deposit_tiny",
-                            "UPDATE deposits"
-                            " SET tiny=TRUE"
-                            " WHERE deposit_serial_id=$1",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "mark_deposit_tiny",
+      "UPDATE deposits"
+      " SET tiny=TRUE"
+      " WHERE deposit_serial_id=$1",
+      1),
     /* Used in #postgres_mark_deposit_done() */
-    GNUNET_PQ_make_prepare ("mark_deposit_done",
-                            "UPDATE deposits"
-                            " SET done=TRUE"
-                            " WHERE deposit_serial_id=$1;",
-                            1),
-    /* Used in #postgres_test_deposit_done() */
-    GNUNET_PQ_make_prepare ("test_deposit_done",
-                            "SELECT done"
-                            " FROM deposits"
-                            " JOIN known_coins USING (known_coin_id)"
-                            " WHERE coin_pub=$1"
-                            "   AND merchant_pub=$2"
-                            "   AND h_contract_terms=$3"
-                            "   AND h_wire=$4;",
-                            5),
+    GNUNET_PQ_make_prepare (
+      "mark_deposit_done",
+      "UPDATE deposits"
+      " SET done=TRUE"
+      " WHERE deposit_serial_id=$1;",
+      1),
     /* Used in #postgres_get_coin_transactions() to obtain information
        about how a coin has been spend with /deposit requests. */
-    GNUNET_PQ_make_prepare ("get_deposit_with_coin_pub",
-                            "SELECT"
-                            " amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",denoms.fee_deposit_val"
-                            ",denoms.fee_deposit_frac"
-                            ",denoms.denom_pub_hash"
-                            ",wallet_timestamp"
-                            ",refund_deadline"
-                            ",wire_deadline"
-                            ",merchant_pub"
-                            ",h_contract_terms"
-                            ",h_wire"
-                            ",wire"
-                            ",coin_sig"
-                            ",deposit_serial_id"
-                            ",done"
-                            " FROM deposits"
-                            "    JOIN known_coins kc"
-                            "      USING (known_coin_id)"
-                            "    JOIN denominations denoms"
-                            "      USING (denominations_serial)"
-                            " WHERE coin_pub=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_deposit_with_coin_pub",
+      "SELECT"
+      " amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",denoms.fee_deposit_val"
+      ",denoms.fee_deposit_frac"
+      ",denoms.denom_pub_hash"
+      ",wallet_timestamp"
+      ",refund_deadline"
+      ",wire_deadline"
+      ",merchant_pub"
+      ",h_contract_terms"
+      ",wire_salt"
+      ",payto_uri"
+      ",coin_sig"
+      ",deposit_serial_id"
+      ",done"
+      " FROM deposits"
+      "    JOIN wire_targets"
+      "      USING (wire_target_serial_id)"
+      "    JOIN known_coins kc"
+      "      USING (known_coin_id)"
+      "    JOIN denominations denoms"
+      "      USING (denominations_serial)"
+      " WHERE coin_pub=$1;",
+      1),
 
     /* Used in #postgres_get_link_data(). */
-    GNUNET_PQ_make_prepare ("get_link",
-                            "SELECT "
-                            " tp.transfer_pub"
-                            ",denoms.denom_pub"
-                            ",rrc.ev_sig"
-                            ",rrc.link_sig"
-                            " FROM refresh_commitments"
-                            "     JOIN refresh_revealed_coins rrc"
-                            "       USING (melt_serial_id)"
-                            "     JOIN refresh_transfer_keys tp"
-                            "       USING (melt_serial_id)"
-                            "     JOIN denominations denoms"
-                            "       ON (rrc.denominations_serial = 
denoms.denominations_serial)"
-                            " WHERE old_known_coin_id="
-                            "   (SELECT known_coin_id "
-                            "      FROM known_coins"
-                            "     WHERE coin_pub=$1)"
-                            " ORDER BY tp.transfer_pub, rrc.freshcoin_index 
ASC",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_link",
+      "SELECT "
+      " tp.transfer_pub"
+      ",denoms.denom_pub"
+      ",rrc.ev_sig"
+      ",rrc.link_sig"
+      " FROM refresh_commitments"
+      "     JOIN refresh_revealed_coins rrc"
+      "       USING (melt_serial_id)"
+      "     JOIN refresh_transfer_keys tp"
+      "       USING (melt_serial_id)"
+      "     JOIN denominations denoms"
+      "       ON (rrc.denominations_serial = denoms.denominations_serial)"
+      " WHERE old_known_coin_id="
+      "   (SELECT known_coin_id "
+      "      FROM known_coins"
+      "     WHERE coin_pub=$1)"
+      " ORDER BY tp.transfer_pub, rrc.freshcoin_index ASC",
+      1),
     /* Used in #postgres_lookup_wire_transfer */
-    GNUNET_PQ_make_prepare ("lookup_transactions",
-                            "SELECT"
-                            " aggregation_serial_id"
-                            ",deposits.h_contract_terms"
-                            ",deposits.wire"
-                            ",deposits.h_wire"
-                            ",kc.coin_pub"
-                            ",deposits.merchant_pub"
-                            ",wire_out.execution_date"
-                            ",deposits.amount_with_fee_val"
-                            ",deposits.amount_with_fee_frac"
-                            ",denom.fee_deposit_val"
-                            ",denom.fee_deposit_frac"
-                            ",denom.denom_pub"
-                            " FROM aggregation_tracking"
-                            "    JOIN deposits"
-                            "      USING (deposit_serial_id)"
-                            "    JOIN known_coins kc"
-                            "      USING (known_coin_id)"
-                            "    JOIN denominations denom"
-                            "      USING (denominations_serial)"
-                            "    JOIN wire_out"
-                            "      USING (wtid_raw)"
-                            " WHERE wtid_raw=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "lookup_transactions",
+      "SELECT"
+      " aggregation_serial_id"
+      ",deposits.h_contract_terms"
+      ",payto_uri"
+      ",kc.coin_pub"
+      ",deposits.merchant_pub"
+      ",wire_out.execution_date"
+      ",deposits.amount_with_fee_val"
+      ",deposits.amount_with_fee_frac"
+      ",denom.fee_deposit_val"
+      ",denom.fee_deposit_frac"
+      ",denom.denom_pub"
+      " FROM aggregation_tracking"
+      "    JOIN deposits"
+      "      USING (deposit_serial_id)"
+      "    JOIN wire_targets"
+      "      USING (wire_target_serial_id)"
+      "    JOIN known_coins kc"
+      "      USING (known_coin_id)"
+      "    JOIN denominations denom"
+      "      USING (denominations_serial)"
+      "    JOIN wire_out"
+      "      USING (wtid_raw)"
+      " WHERE wtid_raw=$1;",
+      1),
     /* Used in #postgres_lookup_transfer_by_deposit */
-    GNUNET_PQ_make_prepare ("lookup_deposit_wtid",
-                            "SELECT"
-                            " aggregation_tracking.wtid_raw"
-                            ",wire_out.execution_date"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",denom.fee_deposit_val"
-                            ",denom.fee_deposit_frac"
-                            " FROM deposits"
-                            "    JOIN aggregation_tracking"
-                            "      USING (deposit_serial_id)"
-                            "    JOIN known_coins"
-                            "      USING (known_coin_id)"
-                            "    JOIN denominations denom"
-                            "      USING (denominations_serial)"
-                            "    JOIN wire_out"
-                            "      USING (wtid_raw)"
-                            " WHERE coin_pub=$1"
-                            "  AND h_contract_terms=$2"
-                            "  AND h_wire=$3"
-                            "  AND merchant_pub=$4;",
-                            4),
+    GNUNET_PQ_make_prepare (
+      "lookup_deposit_wtid",
+      "SELECT"
+      " aggregation_tracking.wtid_raw"
+      ",wire_out.execution_date"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",wire_salt"
+      ",payto_uri"
+      ",denom.fee_deposit_val"
+      ",denom.fee_deposit_frac"
+      " FROM deposits"
+      "    JOIN wire_targets"
+      "      USING (wire_target_serial_id)"
+      "    JOIN aggregation_tracking"
+      "      USING (deposit_serial_id)"
+      "    JOIN known_coins"
+      "      USING (known_coin_id)"
+      "    JOIN denominations denom"
+      "      USING (denominations_serial)"
+      "    JOIN wire_out"
+      "      USING (wtid_raw)"
+      " WHERE coin_pub=$1"
+      "  AND merchant_pub=$3"
+      "  AND h_contract_terms=$2",
+      3),
     /* Used in #postgres_insert_aggregation_tracking */
-    GNUNET_PQ_make_prepare ("insert_aggregation_tracking",
-                            "INSERT INTO aggregation_tracking "
-                            "(deposit_serial_id"
-                            ",wtid_raw"
-                            ") VALUES "
-                            "($1, $2);",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "insert_aggregation_tracking",
+      "INSERT INTO aggregation_tracking "
+      "(deposit_serial_id"
+      ",wtid_raw"
+      ") VALUES "
+      "($1, $2);",
+      2),
     /* Used in #postgres_get_wire_fee() */
-    GNUNET_PQ_make_prepare ("get_wire_fee",
-                            "SELECT "
-                            " start_date"
-                            ",end_date"
-                            ",wire_fee_val"
-                            ",wire_fee_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            ",master_sig"
-                            " FROM wire_fee"
-                            " WHERE wire_method=$1"
-                            "   AND start_date <= $2"
-                            "   AND end_date > $2;",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "get_wire_fee",
+      "SELECT "
+      " start_date"
+      ",end_date"
+      ",wire_fee_val"
+      ",wire_fee_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      ",master_sig"
+      " FROM wire_fee"
+      " WHERE wire_method=$1"
+      "   AND start_date <= $2"
+      "   AND end_date > $2;",
+      2),
     /* Used in #postgres_insert_wire_fee */
-    GNUNET_PQ_make_prepare ("insert_wire_fee",
-                            "INSERT INTO wire_fee "
-                            "(wire_method"
-                            ",start_date"
-                            ",end_date"
-                            ",wire_fee_val"
-                            ",wire_fee_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            ",master_sig"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8);",
-                            8),
+    GNUNET_PQ_make_prepare (
+      "insert_wire_fee",
+      "INSERT INTO wire_fee "
+      "(wire_method"
+      ",start_date"
+      ",end_date"
+      ",wire_fee_val"
+      ",wire_fee_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      ",master_sig"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8);",
+      8),
     /* Used in #postgres_store_wire_transfer_out */
-    GNUNET_PQ_make_prepare ("insert_wire_out",
-                            "INSERT INTO wire_out "
-                            "(execution_date"
-                            ",wtid_raw"
-                            ",wire_target"
-                            ",exchange_account_section"
-                            ",amount_val"
-                            ",amount_frac"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6);",
-                            6),
+    GNUNET_PQ_make_prepare (
+      "insert_wire_out",
+      "INSERT INTO wire_out "
+      "(execution_date"
+      ",wtid_raw"
+      ",wire_target_serial_id"
+      ",exchange_account_section"
+      ",amount_val"
+      ",amount_frac"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6);",
+      6),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_wire_out",
+      "INSERT INTO wire_out"
+      "(wireout_uuid"
+      ",execution_date"
+      ",wtid_raw"
+      ",wire_target_serial_id"
+      ",exchange_account_section"
+      ",amount_val"
+      ",amount_frac"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7);",
+      7),
     /* Used in #postgres_wire_prepare_data_insert() to store
        wire transfer information before actually committing it with the bank */
-    GNUNET_PQ_make_prepare ("wire_prepare_data_insert",
-                            "INSERT INTO prewire "
-                            "(type"
-                            ",buf"
-                            ") VALUES "
-                            "($1, $2);",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "wire_prepare_data_insert",
+      "INSERT INTO prewire "
+      "(type"
+      ",buf"
+      ") VALUES "
+      "($1, $2);",
+      2),
     /* Used in #postgres_wire_prepare_data_mark_finished() */
-    GNUNET_PQ_make_prepare ("wire_prepare_data_mark_done",
-                            "UPDATE prewire"
-                            " SET finished=TRUE"
-                            " WHERE prewire_uuid=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "wire_prepare_data_mark_done",
+      "UPDATE prewire"
+      " SET finished=TRUE"
+      " WHERE prewire_uuid=$1;",
+      1),
     /* Used in #postgres_wire_prepare_data_mark_failed() */
-    GNUNET_PQ_make_prepare ("wire_prepare_data_mark_failed",
-                            "UPDATE prewire"
-                            " SET failed=TRUE"
-                            " WHERE prewire_uuid=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "wire_prepare_data_mark_failed",
+      "UPDATE prewire"
+      " SET failed=TRUE"
+      " WHERE prewire_uuid=$1;",
+      1),
     /* Used in #postgres_wire_prepare_data_get() */
-    GNUNET_PQ_make_prepare ("wire_prepare_data_get",
-                            "SELECT"
-                            " prewire_uuid"
-                            ",type"
-                            ",buf"
-                            " FROM prewire"
-                            " WHERE prewire_uuid >= $1"
-                            "   AND finished=FALSE"
-                            "   AND failed=FALSE"
-                            " ORDER BY prewire_uuid ASC"
-                            " LIMIT $2;",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "wire_prepare_data_get",
+      "SELECT"
+      " prewire_uuid"
+      ",type"
+      ",buf"
+      " FROM prewire"
+      " WHERE prewire_uuid >= $1"
+      "   AND finished=FALSE"
+      "   AND failed=FALSE"
+      " ORDER BY prewire_uuid ASC"
+      " LIMIT $2;",
+      2),
     /* Used in #postgres_select_deposits_missing_wire */
-    GNUNET_PQ_make_prepare ("deposits_get_overdue",
-                            "SELECT"
-                            " deposit_serial_id"
-                            ",coin_pub"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",wire"
-                            ",wire_deadline"
-                            ",tiny"
-                            ",done"
-                            " FROM deposits d"
-                            " JOIN known_coins USING (known_coin_id)"
-                            " WHERE wire_deadline >= $1"
-                            " AND wire_deadline < $2"
-                            " AND NOT (EXISTS (SELECT 1"
-                            "            FROM refunds"
-                            "            JOIN deposits dx USING 
(deposit_serial_id)"
-                            "            WHERE (dx.known_coin_id = 
d.known_coin_id))"
-                            "       OR EXISTS (SELECT 1"
-                            "            FROM aggregation_tracking"
-                            "            WHERE 
(aggregation_tracking.deposit_serial_id = d.deposit_serial_id)))"
-                            " ORDER BY wire_deadline ASC",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "deposits_get_overdue",
+      "SELECT"
+      " deposit_serial_id"
+      ",coin_pub"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",payto_uri"
+      ",wire_deadline"
+      ",tiny"
+      ",done"
+      " FROM deposits d"
+      "   JOIN known_coins"
+      "     USING (known_coin_id)"
+      "   JOIN wire_targets"
+      "     USING (wire_target_serial_id)"
+      " WHERE wire_deadline >= $1"
+      " AND wire_deadline < $2"
+      " AND NOT (EXISTS (SELECT 1"
+      "            FROM refunds"
+      "            JOIN deposits dx USING (deposit_serial_id)"
+      "            WHERE (dx.known_coin_id = d.known_coin_id))"
+      "       OR EXISTS (SELECT 1"
+      "            FROM aggregation_tracking"
+      "            WHERE (aggregation_tracking.deposit_serial_id = 
d.deposit_serial_id)))"
+      " ORDER BY wire_deadline ASC",
+      2),
     /* Used in #postgres_select_wire_out_above_serial_id() */
-    GNUNET_PQ_make_prepare ("audit_get_wire_incr",
-                            "SELECT"
-                            " wireout_uuid"
-                            ",execution_date"
-                            ",wtid_raw"
-                            ",wire_target"
-                            ",amount_val"
-                            ",amount_frac"
-                            " FROM wire_out"
-                            " WHERE wireout_uuid>=$1"
-                            " ORDER BY wireout_uuid ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "audit_get_wire_incr",
+      "SELECT"
+      " wireout_uuid"
+      ",execution_date"
+      ",wtid_raw"
+      ",payto_uri"
+      ",amount_val"
+      ",amount_frac"
+      " FROM wire_out"
+      "   JOIN wire_targets"
+      "     USING (wire_target_serial_id)"
+      " WHERE wireout_uuid>=$1"
+      " ORDER BY wireout_uuid ASC;",
+      1),
     /* Used in #postgres_select_wire_out_above_serial_id_by_account() */
-    GNUNET_PQ_make_prepare ("audit_get_wire_incr_by_account",
-                            "SELECT"
-                            " wireout_uuid"
-                            ",execution_date"
-                            ",wtid_raw"
-                            ",wire_target"
-                            ",amount_val"
-                            ",amount_frac"
-                            " FROM wire_out"
-                            " WHERE wireout_uuid>=$1 AND 
exchange_account_section=$2"
-                            " ORDER BY wireout_uuid ASC;",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "audit_get_wire_incr_by_account",
+      "SELECT"
+      " wireout_uuid"
+      ",execution_date"
+      ",wtid_raw"
+      ",payto_uri"
+      ",amount_val"
+      ",amount_frac"
+      " FROM wire_out"
+      "   JOIN wire_targets"
+      "     USING (wire_target_serial_id)"
+      " WHERE "
+      "      wireout_uuid>=$1 "
+      "  AND exchange_account_section=$2"
+      " ORDER BY wireout_uuid ASC;",
+      2),
     /* Used in #postgres_insert_recoup_request() to store recoup
        information */
-    GNUNET_PQ_make_prepare ("recoup_insert",
-                            "WITH rx AS"
-                            " (SELECT reserve_out_serial_id"
-                            "    FROM reserves_out"
-                            "   WHERE h_blind_ev=$7)"
-                            "INSERT INTO recoup "
-                            "(known_coin_id"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",reserve_out_serial_id"
-                            ") SELECT known_coin_id, $2, $3, $4, $5, $6, 
rx.reserve_out_serial_id"
-                            "    FROM known_coins"
-                            "   CROSS JOIN rx"
-                            "   WHERE coin_pub=$1;",
-                            7),
+    GNUNET_PQ_make_prepare (
+      "recoup_insert",
+      "WITH rx AS"
+      " (SELECT reserve_out_serial_id"
+      "    FROM reserves_out"
+      "   WHERE h_blind_ev=$7)"
+      "INSERT INTO recoup "
+      "(known_coin_id"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",reserve_out_serial_id"
+      ") SELECT known_coin_id, $2, $3, $4, $5, $6, rx.reserve_out_serial_id"
+      "    FROM known_coins"
+      "   CROSS JOIN rx"
+      "   WHERE coin_pub=$1;",
+      7),
     /* Used in #postgres_insert_recoup_refresh_request() to store 
recoup-refresh
        information */
-    GNUNET_PQ_make_prepare ("recoup_refresh_insert",
-                            "WITH rrx AS"
-                            " (SELECT rrc_serial"
-                            "    FROM refresh_revealed_coins"
-                            "   WHERE h_coin_ev=$7)"
-                            "INSERT INTO recoup_refresh "
-                            "(known_coin_id"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",rrc_serial"
-                            ") SELECT known_coin_id, $2, $3, $4, $5, $6, 
rrx.rrc_serial"
-                            "    FROM known_coins"
-                            "   CROSS JOIN rrx"
-                            "   WHERE coin_pub=$1;",
-                            7),
+    GNUNET_PQ_make_prepare (
+      "recoup_refresh_insert",
+      "WITH rrx AS"
+      " (SELECT rrc_serial"
+      "    FROM refresh_revealed_coins"
+      "   WHERE h_coin_ev=$7)"
+      "INSERT INTO recoup_refresh "
+      "(known_coin_id"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",rrc_serial"
+      ") SELECT known_coin_id, $2, $3, $4, $5, $6, rrx.rrc_serial"
+      "    FROM known_coins"
+      "   CROSS JOIN rrx"
+      "   WHERE coin_pub=$1;",
+      7),
     /* Used in #postgres_select_recoup_above_serial_id() to obtain recoup 
transactions */
-    GNUNET_PQ_make_prepare ("recoup_get_incr",
-                            "SELECT"
-                            " recoup_uuid"
-                            ",timestamp"
-                            ",reserves.reserve_pub"
-                            ",coins.coin_pub"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",ro.h_blind_ev"
-                            ",denoms.denom_pub_hash"
-                            ",coins.denom_sig"
-                            ",denoms.denom_pub"
-                            ",amount_val"
-                            ",amount_frac"
-                            " FROM recoup"
-                            "    JOIN known_coins coins"
-                            "      USING (known_coin_id)"
-                            "    JOIN reserves_out ro"
-                            "      USING (reserve_out_serial_id)"
-                            "    JOIN reserves"
-                            "      USING (reserve_uuid)"
-                            "    JOIN denominations denoms"
-                            "      ON (coins.denominations_serial = 
denoms.denominations_serial)"
-                            " WHERE recoup_uuid>=$1"
-                            " ORDER BY recoup_uuid ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "recoup_get_incr",
+      "SELECT"
+      " recoup_uuid"
+      ",timestamp"
+      ",reserves.reserve_pub"
+      ",coins.coin_pub"
+      ",coin_sig"
+      ",coin_blind"
+      ",ro.h_blind_ev"
+      ",denoms.denom_pub_hash"
+      ",coins.denom_sig"
+      ",denoms.denom_pub"
+      ",amount_val"
+      ",amount_frac"
+      " FROM recoup"
+      "    JOIN known_coins coins"
+      "      USING (known_coin_id)"
+      "    JOIN reserves_out ro"
+      "      USING (reserve_out_serial_id)"
+      "    JOIN reserves"
+      "      USING (reserve_uuid)"
+      "    JOIN denominations denoms"
+      "      ON (coins.denominations_serial = denoms.denominations_serial)"
+      " WHERE recoup_uuid>=$1"
+      " ORDER BY recoup_uuid ASC;",
+      1),
     /* Used in #postgres_select_recoup_refresh_above_serial_id() to obtain
        recoup-refresh transactions */
-    GNUNET_PQ_make_prepare ("recoup_refresh_get_incr",
-                            "SELECT"
-                            " recoup_refresh_uuid"
-                            ",timestamp"
-                            ",old_coins.coin_pub AS old_coin_pub"
-                            ",old_denoms.denom_pub_hash AS old_denom_pub_hash"
-                            ",new_coins.coin_pub As coin_pub"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",new_denoms.denom_pub AS denom_pub"
-                            ",rrc.h_coin_ev AS h_blind_ev"
-                            ",new_denoms.denom_pub_hash"
-                            ",new_coins.denom_sig AS denom_sig"
-                            ",amount_val"
-                            ",amount_frac"
-                            " FROM recoup_refresh"
-                            "    INNER JOIN refresh_revealed_coins rrc"
-                            "      USING (rrc_serial)"
-                            "    INNER JOIN refresh_commitments rfc"
-                            "      ON (rrc.melt_serial_id = 
rfc.melt_serial_id)"
-                            "    INNER JOIN known_coins old_coins"
-                            "      ON (rfc.old_known_coin_id = 
old_coins.known_coin_id)"
-                            "    INNER JOIN known_coins new_coins"
-                            "      ON (new_coins.known_coin_id = 
recoup_refresh.known_coin_id)"
-                            "    INNER JOIN denominations new_denoms"
-                            "      ON (new_coins.denominations_serial = 
new_denoms.denominations_serial)"
-                            "    INNER JOIN denominations old_denoms"
-                            "      ON (old_coins.denominations_serial = 
old_denoms.denominations_serial)"
-                            " WHERE recoup_refresh_uuid>=$1"
-                            " ORDER BY recoup_refresh_uuid ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "recoup_refresh_get_incr",
+      "SELECT"
+      " recoup_refresh_uuid"
+      ",timestamp"
+      ",old_coins.coin_pub AS old_coin_pub"
+      ",old_denoms.denom_pub_hash AS old_denom_pub_hash"
+      ",new_coins.coin_pub As coin_pub"
+      ",coin_sig"
+      ",coin_blind"
+      ",new_denoms.denom_pub AS denom_pub"
+      ",rrc.h_coin_ev AS h_blind_ev"
+      ",new_denoms.denom_pub_hash"
+      ",new_coins.denom_sig AS denom_sig"
+      ",amount_val"
+      ",amount_frac"
+      " FROM recoup_refresh"
+      "    INNER JOIN refresh_revealed_coins rrc"
+      "      USING (rrc_serial)"
+      "    INNER JOIN refresh_commitments rfc"
+      "      ON (rrc.melt_serial_id = rfc.melt_serial_id)"
+      "    INNER JOIN known_coins old_coins"
+      "      ON (rfc.old_known_coin_id = old_coins.known_coin_id)"
+      "    INNER JOIN known_coins new_coins"
+      "      ON (new_coins.known_coin_id = recoup_refresh.known_coin_id)"
+      "    INNER JOIN denominations new_denoms"
+      "      ON (new_coins.denominations_serial = 
new_denoms.denominations_serial)"
+      "    INNER JOIN denominations old_denoms"
+      "      ON (old_coins.denominations_serial = 
old_denoms.denominations_serial)"
+      " WHERE recoup_refresh_uuid>=$1"
+      " ORDER BY recoup_refresh_uuid ASC;",
+      1),
     /* Used in #postgres_select_reserve_closed_above_serial_id() to
        obtain information about closed reserves */
-    GNUNET_PQ_make_prepare ("reserves_close_get_incr",
-                            "SELECT"
-                            " close_uuid"
-                            ",reserves.reserve_pub"
-                            ",execution_date"
-                            ",wtid"
-                            ",receiver_account"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            " FROM reserves_close"
-                            " JOIN reserves"
-                            "   USING (reserve_uuid)"
-                            " WHERE close_uuid>=$1"
-                            " ORDER BY close_uuid ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "reserves_close_get_incr",
+      "SELECT"
+      " close_uuid"
+      ",reserves.reserve_pub"
+      ",execution_date"
+      ",wtid"
+      ",payto_uri AS receiver_account"
+      ",amount_val"
+      ",amount_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      " FROM reserves_close"
+      "   JOIN wire_targets"
+      "     USING (wire_target_serial_id)"
+      "   JOIN reserves"
+      "     USING (reserve_uuid)"
+      " WHERE close_uuid>=$1"
+      " ORDER BY close_uuid ASC;",
+      1),
     /* Used in #postgres_get_reserve_history() to obtain recoup transactions
        for a reserve */
-    GNUNET_PQ_make_prepare ("recoup_by_reserve",
-                            "SELECT"
-                            " coins.coin_pub"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",denoms.denom_pub_hash"
-                            ",coins.denom_sig"
-                            " FROM recoup"
-                            "    JOIN known_coins coins"
-                            "      USING (known_coin_id)"
-                            "    JOIN denominations denoms"
-                            "      USING (denominations_serial)"
-                            "    JOIN reserves_out ro"
-                            "      USING (reserve_out_serial_id)"
-                            " WHERE ro.reserve_uuid="
-                            "   (SELECT reserve_uuid"
-                            "     FROM reserves"
-                            "    WHERE reserve_pub=$1);",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "recoup_by_reserve",
+      "SELECT"
+      " coins.coin_pub"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",denoms.denom_pub_hash"
+      ",coins.denom_sig"
+      " FROM recoup"
+      "    JOIN known_coins coins"
+      "      USING (known_coin_id)"
+      "    JOIN denominations denoms"
+      "      USING (denominations_serial)"
+      "    JOIN reserves_out ro"
+      "      USING (reserve_out_serial_id)"
+      " WHERE ro.reserve_uuid="
+      "   (SELECT reserve_uuid"
+      "     FROM reserves"
+      "    WHERE reserve_pub=$1);",
+      1),
     /* Used in #postgres_get_coin_transactions() to obtain recoup transactions
        affecting old coins of refreshed coins */
-    GNUNET_PQ_make_prepare ("recoup_by_old_coin",
-                            "SELECT"
-                            " coins.coin_pub"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",denoms.denom_pub_hash"
-                            ",coins.denom_sig"
-                            ",recoup_refresh_uuid"
-                            " FROM recoup_refresh"
-                            " JOIN known_coins coins"
-                            "   USING (known_coin_id)"
-                            " JOIN denominations denoms"
-                            "   USING (denominations_serial)"
-                            " WHERE rrc_serial IN"
-                            "   (SELECT rrc.rrc_serial"
-                            "    FROM refresh_commitments"
-                            "       JOIN refresh_revealed_coins rrc"
-                            "           USING (melt_serial_id)"
-                            "    WHERE old_known_coin_id="
-                            "       (SELECT known_coin_id"
-                            "          FROM known_coins"
-                            "         WHERE coin_pub=$1));",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "recoup_by_old_coin",
+      "SELECT"
+      " coins.coin_pub"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",denoms.denom_pub_hash"
+      ",coins.denom_sig"
+      ",recoup_refresh_uuid"
+      " FROM recoup_refresh"
+      " JOIN known_coins coins"
+      "   USING (known_coin_id)"
+      " JOIN denominations denoms"
+      "   USING (denominations_serial)"
+      " WHERE rrc_serial IN"
+      "   (SELECT rrc.rrc_serial"
+      "    FROM refresh_commitments"
+      "       JOIN refresh_revealed_coins rrc"
+      "           USING (melt_serial_id)"
+      "    WHERE old_known_coin_id="
+      "       (SELECT known_coin_id"
+      "          FROM known_coins"
+      "         WHERE coin_pub=$1));",
+      1),
     /* Used in #postgres_get_reserve_history() */
-    GNUNET_PQ_make_prepare ("close_by_reserve",
-                            "SELECT"
-                            " amount_val"
-                            ",amount_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            ",execution_date"
-                            ",receiver_account"
-                            ",wtid"
-                            " FROM reserves_close"
-                            " WHERE reserve_uuid="
-                            "   (SELECT reserve_uuid"
-                            "     FROM reserves"
-                            "    WHERE reserve_pub=$1);",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "close_by_reserve",
+      "SELECT"
+      " amount_val"
+      ",amount_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      ",execution_date"
+      ",payto_uri AS receiver_account"
+      ",wtid"
+      " FROM reserves_close"
+      "   JOIN wire_targets"
+      "     USING (wire_target_serial_id)"
+      " WHERE reserve_uuid="
+      "   (SELECT reserve_uuid"
+      "     FROM reserves"
+      "    WHERE reserve_pub=$1);",
+      1),
     /* Used in #postgres_get_expired_reserves() */
-    GNUNET_PQ_make_prepare ("get_expired_reserves",
-                            "SELECT"
-                            " expiration_date"
-                            ",account_details"
-                            ",reserve_pub"
-                            ",current_balance_val"
-                            ",current_balance_frac"
-                            " FROM reserves"
-                            " WHERE expiration_date<=$1"
-                            "   AND (current_balance_val != 0 "
-                            "        OR current_balance_frac != 0)"
-                            " ORDER BY expiration_date ASC"
-                            " LIMIT 1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_expired_reserves",
+      "SELECT"
+      " expiration_date"
+      ",payto_uri AS account_details"
+      ",reserve_pub"
+      ",current_balance_val"
+      ",current_balance_frac"
+      " FROM reserves"
+      "   JOIN reserves_in ri"
+      "     USING (reserve_uuid)"
+      "   JOIN wire_targets wt"
+      "     ON (ri.wire_source_serial_id = wt.wire_target_serial_id)"
+      " WHERE expiration_date<=$1"
+      "   AND (current_balance_val != 0 "
+      "        OR current_balance_frac != 0)"
+      " ORDER BY expiration_date ASC"
+      " LIMIT 1;",
+      1),
     /* Used in #postgres_get_coin_transactions() to obtain recoup transactions
        for a coin */
-    GNUNET_PQ_make_prepare ("recoup_by_coin",
-                            "SELECT"
-                            " reserves.reserve_pub"
-                            ",denoms.denom_pub_hash"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",recoup_uuid"
-                            " FROM recoup"
-                            " JOIN reserves_out ro"
-                            "   USING (reserve_out_serial_id)"
-                            " JOIN reserves"
-                            "   USING (reserve_uuid)"
-                            " JOIN known_coins coins"
-                            "   USING (known_coin_id)"
-                            " JOIN denominations denoms"
-                            "   ON (denoms.denominations_serial = 
coins.denominations_serial)"
-                            " WHERE coins.coin_pub=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "recoup_by_coin",
+      "SELECT"
+      " reserves.reserve_pub"
+      ",denoms.denom_pub_hash"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",recoup_uuid"
+      " FROM recoup"
+      " JOIN reserves_out ro"
+      "   USING (reserve_out_serial_id)"
+      " JOIN reserves"
+      "   USING (reserve_uuid)"
+      " JOIN known_coins coins"
+      "   USING (known_coin_id)"
+      " JOIN denominations denoms"
+      "   ON (denoms.denominations_serial = coins.denominations_serial)"
+      " WHERE coins.coin_pub=$1;",
+      1),
     /* Used in #postgres_get_coin_transactions() to obtain recoup transactions
        for a refreshed coin */
-    GNUNET_PQ_make_prepare ("recoup_by_refreshed_coin",
-                            "SELECT"
-                            " old_coins.coin_pub AS old_coin_pub"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",denoms.denom_pub_hash"
-                            ",coins.denom_sig"
-                            ",recoup_refresh_uuid"
-                            " FROM recoup_refresh"
-                            "    JOIN refresh_revealed_coins rrc"
-                            "      USING (rrc_serial)"
-                            "    JOIN refresh_commitments rfc"
-                            "      ON (rrc.melt_serial_id = 
rfc.melt_serial_id)"
-                            "    JOIN known_coins old_coins"
-                            "      ON (rfc.old_known_coin_id = 
old_coins.known_coin_id)"
-                            "    JOIN known_coins coins"
-                            "      ON (recoup_refresh.known_coin_id = 
coins.known_coin_id)"
-                            "    JOIN denominations denoms"
-                            "      ON (denoms.denominations_serial = 
coins.denominations_serial)"
-                            " WHERE coins.coin_pub=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "recoup_by_refreshed_coin",
+      "SELECT"
+      " old_coins.coin_pub AS old_coin_pub"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",denoms.denom_pub_hash"
+      ",coins.denom_sig"
+      ",recoup_refresh_uuid"
+      " FROM recoup_refresh"
+      "    JOIN refresh_revealed_coins rrc"
+      "      USING (rrc_serial)"
+      "    JOIN refresh_commitments rfc"
+      "      ON (rrc.melt_serial_id = rfc.melt_serial_id)"
+      "    JOIN known_coins old_coins"
+      "      ON (rfc.old_known_coin_id = old_coins.known_coin_id)"
+      "    JOIN known_coins coins"
+      "      ON (recoup_refresh.known_coin_id = coins.known_coin_id)"
+      "    JOIN denominations denoms"
+      "      ON (denoms.denominations_serial = coins.denominations_serial)"
+      " WHERE coins.coin_pub=$1;",
+      1),
     /* Used in #postgres_get_reserve_by_h_blind() */
-    GNUNET_PQ_make_prepare ("reserve_by_h_blind",
-                            "SELECT"
-                            " reserves.reserve_pub"
-                            " FROM reserves_out"
-                            " JOIN reserves"
-                            "   USING (reserve_uuid)"
-                            " WHERE h_blind_ev=$1"
-                            " LIMIT 1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "reserve_by_h_blind",
+      "SELECT"
+      " reserves.reserve_pub"
+      " FROM reserves_out"
+      " JOIN reserves"
+      "   USING (reserve_uuid)"
+      " WHERE h_blind_ev=$1"
+      " LIMIT 1;",
+      1),
     /* Used in #postgres_get_old_coin_by_h_blind() */
-    GNUNET_PQ_make_prepare ("old_coin_by_h_blind",
-                            "SELECT"
-                            " okc.coin_pub AS old_coin_pub"
-                            " FROM refresh_revealed_coins rrc"
-                            " JOIN refresh_commitments rcom USING 
(melt_serial_id)"
-                            " JOIN known_coins okc ON (rcom.old_known_coin_id 
= okc.known_coin_id)"
-                            " WHERE h_coin_ev=$1"
-                            " LIMIT 1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "old_coin_by_h_blind",
+      "SELECT"
+      " okc.coin_pub AS old_coin_pub"
+      " FROM refresh_revealed_coins rrc"
+      " JOIN refresh_commitments rcom USING (melt_serial_id)"
+      " JOIN known_coins okc ON (rcom.old_known_coin_id = okc.known_coin_id)"
+      " WHERE h_coin_ev=$1"
+      " LIMIT 1;",
+      1),
     /* Used in #postgres_lookup_auditor_timestamp() */
-    GNUNET_PQ_make_prepare ("lookup_auditor_timestamp",
-                            "SELECT"
-                            " last_change"
-                            " FROM auditors"
-                            " WHERE auditor_pub=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "lookup_auditor_timestamp",
+      "SELECT"
+      " last_change"
+      " FROM auditors"
+      " WHERE auditor_pub=$1;",
+      1),
     /* Used in #postgres_lookup_auditor_status() */
-    GNUNET_PQ_make_prepare ("lookup_auditor_status",
-                            "SELECT"
-                            " auditor_url"
-                            ",is_active"
-                            " FROM auditors"
-                            " WHERE auditor_pub=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "lookup_auditor_status",
+      "SELECT"
+      " auditor_url"
+      ",is_active"
+      " FROM auditors"
+      " WHERE auditor_pub=$1;",
+      1),
     /* Used in #postgres_lookup_wire_timestamp() */
-    GNUNET_PQ_make_prepare ("lookup_wire_timestamp",
-                            "SELECT"
-                            " last_change"
-                            " FROM wire_accounts"
-                            " WHERE payto_uri=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "lookup_wire_timestamp",
+      "SELECT"
+      " last_change"
+      " FROM wire_accounts"
+      " WHERE payto_uri=$1;",
+      1),
     /* used in #postgres_insert_auditor() */
-    GNUNET_PQ_make_prepare ("insert_auditor",
-                            "INSERT INTO auditors "
-                            "(auditor_pub"
-                            ",auditor_name"
-                            ",auditor_url"
-                            ",is_active"
-                            ",last_change"
-                            ") VALUES "
-                            "($1, $2, $3, true, $4);",
-                            4),
+    GNUNET_PQ_make_prepare (
+      "insert_auditor",
+      "INSERT INTO auditors "
+      "(auditor_pub"
+      ",auditor_name"
+      ",auditor_url"
+      ",is_active"
+      ",last_change"
+      ") VALUES "
+      "($1, $2, $3, true, $4);",
+      4),
     /* used in #postgres_update_auditor() */
-    GNUNET_PQ_make_prepare ("update_auditor",
-                            "UPDATE auditors"
-                            " SET"
-                            "  auditor_url=$2"
-                            " ,auditor_name=$3"
-                            " ,is_active=$4"
-                            " ,last_change=$5"
-                            " WHERE auditor_pub=$1",
-                            5),
+    GNUNET_PQ_make_prepare (
+      "update_auditor",
+      "UPDATE auditors"
+      " SET"
+      "  auditor_url=$2"
+      " ,auditor_name=$3"
+      " ,is_active=$4"
+      " ,last_change=$5"
+      " WHERE auditor_pub=$1",
+      5),
     /* used in #postgres_insert_wire() */
-    GNUNET_PQ_make_prepare ("insert_wire",
-                            "INSERT INTO wire_accounts "
-                            "(payto_uri"
-                            ",master_sig"
-                            ",is_active"
-                            ",last_change"
-                            ") VALUES "
-                            "($1, $2, true, $3);",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "insert_wire",
+      "INSERT INTO wire_accounts "
+      "(payto_uri"
+      ",master_sig"
+      ",is_active"
+      ",last_change"
+      ") VALUES "
+      "($1, $2, true, $3);",
+      3),
     /* used in #postgres_update_wire() */
-    GNUNET_PQ_make_prepare ("update_wire",
-                            "UPDATE wire_accounts"
-                            " SET"
-                            "  is_active=$2"
-                            " ,last_change=$3"
-                            " WHERE payto_uri=$1",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "update_wire",
+      "UPDATE wire_accounts"
+      " SET"
+      "  is_active=$2"
+      " ,last_change=$3"
+      " WHERE payto_uri=$1",
+      3),
     /* used in #postgres_update_wire() */
-    GNUNET_PQ_make_prepare ("get_wire_accounts",
-                            "SELECT"
-                            " payto_uri"
-                            ",master_sig"
-                            " FROM wire_accounts"
-                            " WHERE is_active",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "get_wire_accounts",
+      "SELECT"
+      " payto_uri"
+      ",master_sig"
+      " FROM wire_accounts"
+      " WHERE is_active",
+      0),
     /* used in #postgres_update_wire() */
-    GNUNET_PQ_make_prepare ("get_wire_fees",
-                            "SELECT"
-                            " wire_fee_val"
-                            ",wire_fee_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            ",start_date"
-                            ",end_date"
-                            ",master_sig"
-                            " FROM wire_fee"
-                            " WHERE wire_method=$1",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_wire_fees",
+      "SELECT"
+      " wire_fee_val"
+      ",wire_fee_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      ",start_date"
+      ",end_date"
+      ",master_sig"
+      " FROM wire_fee"
+      " WHERE wire_method=$1",
+      1),
     /* used in #postgres_insert_signkey_revocation() */
-    GNUNET_PQ_make_prepare ("insert_signkey_revocation",
-                            "INSERT INTO signkey_revocations "
-                            "(esk_serial"
-                            ",master_sig"
-                            ") SELECT esk_serial, $2 "
-                            "    FROM exchange_sign_keys"
-                            "   WHERE exchange_pub=$1;",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "insert_signkey_revocation",
+      "INSERT INTO signkey_revocations "
+      "(esk_serial"
+      ",master_sig"
+      ") SELECT esk_serial, $2 "
+      "    FROM exchange_sign_keys"
+      "   WHERE exchange_pub=$1;",
+      2),
     /* used in #postgres_insert_signkey_revocation() */
-    GNUNET_PQ_make_prepare ("lookup_signkey_revocation",
-                            "SELECT "
-                            " master_sig"
-                            " FROM signkey_revocations"
-                            " WHERE esk_serial="
-                            "   (SELECT esk_serial"
-                            "      FROM exchange_sign_keys"
-                            "     WHERE exchange_pub=$1);",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "lookup_signkey_revocation",
+      "SELECT "
+      " master_sig"
+      " FROM signkey_revocations"
+      " WHERE esk_serial="
+      "   (SELECT esk_serial"
+      "      FROM exchange_sign_keys"
+      "     WHERE exchange_pub=$1);",
+      1),
     /* used in #postgres_insert_signkey() */
-    GNUNET_PQ_make_prepare ("insert_signkey",
-                            "INSERT INTO exchange_sign_keys "
-                            "(exchange_pub"
-                            ",valid_from"
-                            ",expire_sign"
-                            ",expire_legal"
-                            ",master_sig"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5);",
-                            5),
+    GNUNET_PQ_make_prepare (
+      "insert_signkey",
+      "INSERT INTO exchange_sign_keys "
+      "(exchange_pub"
+      ",valid_from"
+      ",expire_sign"
+      ",expire_legal"
+      ",master_sig"
+      ") VALUES "
+      "($1, $2, $3, $4, $5);",
+      5),
     /* used in #postgres_lookup_signing_key() */
-    GNUNET_PQ_make_prepare ("lookup_signing_key",
-                            "SELECT"
-                            " valid_from"
-                            ",expire_sign"
-                            ",expire_legal"
-                            " FROM exchange_sign_keys"
-                            " WHERE exchange_pub=$1",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "lookup_signing_key",
+      "SELECT"
+      " valid_from"
+      ",expire_sign"
+      ",expire_legal"
+      " FROM exchange_sign_keys"
+      " WHERE exchange_pub=$1",
+      1),
     /* used in #postgres_lookup_denomination_key() */
-    GNUNET_PQ_make_prepare ("lookup_denomination_key",
-                            "SELECT"
-                            " valid_from"
-                            ",expire_withdraw"
-                            ",expire_deposit"
-                            ",expire_legal"
-                            ",coin_val"
-                            ",coin_frac"
-                            ",fee_withdraw_val"
-                            ",fee_withdraw_frac"
-                            ",fee_deposit_val"
-                            ",fee_deposit_frac"
-                            ",fee_refresh_val"
-                            ",fee_refresh_frac"
-                            ",fee_refund_val"
-                            ",fee_refund_frac"
-                            " FROM denominations"
-                            " WHERE denom_pub_hash=$1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "lookup_denomination_key",
+      "SELECT"
+      " valid_from"
+      ",expire_withdraw"
+      ",expire_deposit"
+      ",expire_legal"
+      ",coin_val"
+      ",coin_frac"
+      ",fee_withdraw_val"
+      ",fee_withdraw_frac"
+      ",fee_deposit_val"
+      ",fee_deposit_frac"
+      ",fee_refresh_val"
+      ",fee_refresh_frac"
+      ",fee_refund_val"
+      ",fee_refund_frac"
+      " FROM denominations"
+      " WHERE denom_pub_hash=$1;",
+      1),
     /* used in #postgres_insert_auditor_denom_sig() */
-    GNUNET_PQ_make_prepare ("insert_auditor_denom_sig",
-                            "WITH ax AS"
-                            " (SELECT auditor_uuid"
-                            "    FROM auditors"
-                            "   WHERE auditor_pub=$1)"
-                            "INSERT INTO auditor_denom_sigs "
-                            "(auditor_uuid"
-                            ",denominations_serial"
-                            ",auditor_sig"
-                            ") SELECT ax.auditor_uuid, denominations_serial, 
$3 "
-                            "    FROM denominations"
-                            "   CROSS JOIN ax"
-                            "   WHERE denom_pub_hash=$2;",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "insert_auditor_denom_sig",
+      "WITH ax AS"
+      " (SELECT auditor_uuid"
+      "    FROM auditors"
+      "   WHERE auditor_pub=$1)"
+      "INSERT INTO auditor_denom_sigs "
+      "(auditor_uuid"
+      ",denominations_serial"
+      ",auditor_sig"
+      ") SELECT ax.auditor_uuid, denominations_serial, $3 "
+      "    FROM denominations"
+      "   CROSS JOIN ax"
+      "   WHERE denom_pub_hash=$2;",
+      3),
     /* used in #postgres_select_auditor_denom_sig() */
-    GNUNET_PQ_make_prepare ("select_auditor_denom_sig",
-                            "SELECT"
-                            " auditor_sig"
-                            " FROM auditor_denom_sigs"
-                            " WHERE auditor_uuid="
-                            "  (SELECT auditor_uuid"
-                            "    FROM auditors"
-                            "    WHERE auditor_pub=$1)"
-                            " AND denominations_serial="
-                            "  (SELECT denominations_serial"
-                            "    FROM denominations"
-                            "    WHERE denom_pub_hash=$2);",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "select_auditor_denom_sig",
+      "SELECT"
+      " auditor_sig"
+      " FROM auditor_denom_sigs"
+      " WHERE auditor_uuid="
+      "  (SELECT auditor_uuid"
+      "    FROM auditors"
+      "    WHERE auditor_pub=$1)"
+      " AND denominations_serial="
+      "  (SELECT denominations_serial"
+      "    FROM denominations"
+      "    WHERE denom_pub_hash=$2);",
+      2),
+    /* used in #postgres_select_withdraw_amounts_by_account() */
+    GNUNET_PQ_make_prepare (
+      "select_above_date_by_reserves_out",
+      "SELECT"
+      " amount_with_fee_val"
+      ",amount_with_fee_frac"
+      " FROM reserves_out"
+      " WHERE reserve_uuid="
+      "   (SELECT reserve_uuid"
+      "      FROM reserves"
+      "     WHERE reserve_pub=$1)"
+      "  AND execution_date > $2;",
+      2),
     /* used in #postgres_lookup_wire_fee_by_time() */
-    GNUNET_PQ_make_prepare ("lookup_wire_fee_by_time",
-                            "SELECT"
-                            " wire_fee_val"
-                            ",wire_fee_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            " FROM wire_fee"
-                            " WHERE wire_method=$1"
-                            " AND end_date > $2"
-                            " AND start_date < $3;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "lookup_wire_fee_by_time",
+      "SELECT"
+      " wire_fee_val"
+      ",wire_fee_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      " FROM wire_fee"
+      " WHERE wire_method=$1"
+      " AND end_date > $2"
+      " AND start_date < $3;",
+      1),
     /* used in #postgres_commit */
-    GNUNET_PQ_make_prepare ("do_commit",
-                            "COMMIT",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "do_commit",
+      "COMMIT",
+      0),
     /* used in #postgres_lookup_serial_by_table() */
-    GNUNET_PQ_make_prepare ("select_serial_by_table_denominations",
-                            "SELECT"
-                            " denominations_serial AS serial"
-                            " FROM denominations"
-                            " ORDER BY denominations_serial DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_denomination_revocations",
-                            "SELECT"
-                            " denom_revocations_serial_id AS serial"
-                            " FROM denomination_revocations"
-                            " ORDER BY denom_revocations_serial_id DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_reserves",
-                            "SELECT"
-                            " reserve_uuid AS serial"
-                            " FROM reserves"
-                            " ORDER BY reserve_uuid DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_reserves_in",
-                            "SELECT"
-                            " reserve_in_serial_id AS serial"
-                            " FROM reserves_in"
-                            " ORDER BY reserve_in_serial_id DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_reserves_close",
-                            "SELECT"
-                            " close_uuid AS serial"
-                            " FROM reserves_close"
-                            " ORDER BY close_uuid DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_reserves_out",
-                            "SELECT"
-                            " reserve_out_serial_id AS serial"
-                            " FROM reserves_out"
-                            " ORDER BY reserve_out_serial_id DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_auditors",
-                            "SELECT"
-                            " auditor_uuid AS serial"
-                            " FROM auditors"
-                            " ORDER BY auditor_uuid DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_auditor_denom_sigs",
-                            "SELECT"
-                            " auditor_denom_serial AS serial"
-                            " FROM auditor_denom_sigs"
-                            " ORDER BY auditor_denom_serial DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_exchange_sign_keys",
-                            "SELECT"
-                            " esk_serial AS serial"
-                            " FROM exchange_sign_keys"
-                            " ORDER BY esk_serial DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_signkey_revocations",
-                            "SELECT"
-                            " signkey_revocations_serial_id AS serial"
-                            " FROM signkey_revocations"
-                            " ORDER BY signkey_revocations_serial_id DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_known_coins",
-                            "SELECT"
-                            " known_coin_id AS serial"
-                            " FROM known_coins"
-                            " ORDER BY known_coin_id DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_refresh_commitments",
-                            "SELECT"
-                            " melt_serial_id AS serial"
-                            " FROM refresh_commitments"
-                            " ORDER BY melt_serial_id DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_refresh_revealed_coins",
-                            "SELECT"
-                            " rrc_serial AS serial"
-                            " FROM refresh_revealed_coins"
-                            " ORDER BY rrc_serial DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_refresh_transfer_keys",
-                            "SELECT"
-                            " rtc_serial AS serial"
-                            " FROM refresh_transfer_keys"
-                            " ORDER BY rtc_serial DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_deposits",
-                            "SELECT"
-                            " deposit_serial_id AS serial"
-                            " FROM deposits"
-                            " ORDER BY deposit_serial_id DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_refunds",
-                            "SELECT"
-                            " refund_serial_id AS serial"
-                            " FROM refunds"
-                            " ORDER BY refund_serial_id DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_wire_out",
-                            "SELECT"
-                            " wireout_uuid AS serial"
-                            " FROM wire_out"
-                            " ORDER BY wireout_uuid DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_aggregation_tracking",
-                            "SELECT"
-                            " aggregation_serial_id AS serial"
-                            " FROM aggregation_tracking"
-                            " ORDER BY aggregation_serial_id DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_wire_fee",
-                            "SELECT"
-                            " wire_fee_serial AS serial"
-                            " FROM wire_fee"
-                            " ORDER BY wire_fee_serial DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_recoup",
-                            "SELECT"
-                            " recoup_uuid AS serial"
-                            " FROM recoup"
-                            " ORDER BY recoup_uuid DESC"
-                            " LIMIT 1;",
-                            0),
-    GNUNET_PQ_make_prepare ("select_serial_by_table_recoup_refresh",
-                            "SELECT"
-                            " recoup_refresh_uuid AS serial"
-                            " FROM recoup_refresh"
-                            " ORDER BY recoup_refresh_uuid DESC"
-                            " LIMIT 1;",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_denominations",
+      "SELECT"
+      " denominations_serial AS serial"
+      " FROM denominations"
+      " ORDER BY denominations_serial DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_denomination_revocations",
+      "SELECT"
+      " denom_revocations_serial_id AS serial"
+      " FROM denomination_revocations"
+      " ORDER BY denom_revocations_serial_id DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_reserves",
+      "SELECT"
+      " reserve_uuid AS serial"
+      " FROM reserves"
+      " ORDER BY reserve_uuid DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_reserves_in",
+      "SELECT"
+      " reserve_in_serial_id AS serial"
+      " FROM reserves_in"
+      " ORDER BY reserve_in_serial_id DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_reserves_close",
+      "SELECT"
+      " close_uuid AS serial"
+      " FROM reserves_close"
+      " ORDER BY close_uuid DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_reserves_out",
+      "SELECT"
+      " reserve_out_serial_id AS serial"
+      " FROM reserves_out"
+      " ORDER BY reserve_out_serial_id DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_auditors",
+      "SELECT"
+      " auditor_uuid AS serial"
+      " FROM auditors"
+      " ORDER BY auditor_uuid DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_auditor_denom_sigs",
+      "SELECT"
+      " auditor_denom_serial AS serial"
+      " FROM auditor_denom_sigs"
+      " ORDER BY auditor_denom_serial DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_exchange_sign_keys",
+      "SELECT"
+      " esk_serial AS serial"
+      " FROM exchange_sign_keys"
+      " ORDER BY esk_serial DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_signkey_revocations",
+      "SELECT"
+      " signkey_revocations_serial_id AS serial"
+      " FROM signkey_revocations"
+      " ORDER BY signkey_revocations_serial_id DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_known_coins",
+      "SELECT"
+      " known_coin_id AS serial"
+      " FROM known_coins"
+      " ORDER BY known_coin_id DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_refresh_commitments",
+      "SELECT"
+      " melt_serial_id AS serial"
+      " FROM refresh_commitments"
+      " ORDER BY melt_serial_id DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_refresh_revealed_coins",
+      "SELECT"
+      " rrc_serial AS serial"
+      " FROM refresh_revealed_coins"
+      " ORDER BY rrc_serial DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_refresh_transfer_keys",
+      "SELECT"
+      " rtc_serial AS serial"
+      " FROM refresh_transfer_keys"
+      " ORDER BY rtc_serial DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_deposits",
+      "SELECT"
+      " deposit_serial_id AS serial"
+      " FROM deposits"
+      " ORDER BY deposit_serial_id DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_refunds",
+      "SELECT"
+      " refund_serial_id AS serial"
+      " FROM refunds"
+      " ORDER BY refund_serial_id DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_wire_out",
+      "SELECT"
+      " wireout_uuid AS serial"
+      " FROM wire_out"
+      " ORDER BY wireout_uuid DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_aggregation_tracking",
+      "SELECT"
+      " aggregation_serial_id AS serial"
+      " FROM aggregation_tracking"
+      " ORDER BY aggregation_serial_id DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_wire_fee",
+      "SELECT"
+      " wire_fee_serial AS serial"
+      " FROM wire_fee"
+      " ORDER BY wire_fee_serial DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_recoup",
+      "SELECT"
+      " recoup_uuid AS serial"
+      " FROM recoup"
+      " ORDER BY recoup_uuid DESC"
+      " LIMIT 1;",
+      0),
+    GNUNET_PQ_make_prepare (
+      "select_serial_by_table_recoup_refresh",
+      "SELECT"
+      " recoup_refresh_uuid AS serial"
+      " FROM recoup_refresh"
+      " ORDER BY recoup_refresh_uuid DESC"
+      " LIMIT 1;",
+      0),
     /* For postgres_lookup_records_by_table */
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_denominations",
-                            "SELECT"
-                            " denominations_serial AS serial"
-                            ",denom_pub"
-                            ",master_sig"
-                            ",valid_from"
-                            ",expire_withdraw"
-                            ",expire_deposit"
-                            ",expire_legal"
-                            ",coin_val"
-                            ",coin_frac"
-                            ",fee_withdraw_val"
-                            ",fee_withdraw_frac"
-                            ",fee_deposit_val"
-                            ",fee_deposit_frac"
-                            ",fee_refresh_val"
-                            ",fee_refresh_frac"
-                            ",fee_refund_val"
-                            ",fee_refund_frac"
-                            " FROM denominations"
-                            " WHERE denominations_serial > $1"
-                            " ORDER BY denominations_serial ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_denominations",
+      "SELECT"
+      " denominations_serial AS serial"
+      ",denom_type"
+      ",age_restrictions"
+      ",denom_pub"
+      ",master_sig"
+      ",valid_from"
+      ",expire_withdraw"
+      ",expire_deposit"
+      ",expire_legal"
+      ",coin_val"
+      ",coin_frac"
+      ",fee_withdraw_val"
+      ",fee_withdraw_frac"
+      ",fee_deposit_val"
+      ",fee_deposit_frac"
+      ",fee_refresh_val"
+      ",fee_refresh_frac"
+      ",fee_refund_val"
+      ",fee_refund_frac"
+      " FROM denominations"
+      " WHERE denominations_serial > $1"
+      " ORDER BY denominations_serial ASC;",
+      1),
     GNUNET_PQ_make_prepare (
       "select_above_serial_by_table_denomination_revocations",
       "SELECT"
@@ -1935,97 +2133,103 @@ prepare_statements (struct PostgresClosure *pg)
       " WHERE denom_revocations_serial_id > $1"
       " ORDER BY denom_revocations_serial_id ASC;",
       1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_reserves",
-                            "SELECT"
-                            " reserve_uuid AS serial"
-                            ",reserve_pub"
-                            ",account_details"
-                            ",current_balance_val"
-                            ",current_balance_frac"
-                            ",expiration_date"
-                            ",gc_date"
-                            " FROM reserves"
-                            " WHERE reserve_uuid > $1"
-                            " ORDER BY reserve_uuid ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_reserves_in",
-                            "SELECT"
-                            " reserve_in_serial_id AS serial"
-                            ",wire_reference"
-                            ",credit_val"
-                            ",credit_frac"
-                            ",sender_account_details"
-                            ",exchange_account_section"
-                            ",execution_date"
-                            ",reserve_uuid"
-                            " FROM reserves_in"
-                            " WHERE reserve_in_serial_id > $1"
-                            " ORDER BY reserve_in_serial_id ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_reserves_close",
-                            "SELECT"
-                            " close_uuid AS serial"
-                            ",execution_date"
-                            ",wtid"
-                            ",receiver_account"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            ",reserve_uuid"
-                            " FROM reserves_close"
-                            " WHERE close_uuid > $1"
-                            " ORDER BY close_uuid ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_reserves_out",
-                            "SELECT"
-                            " reserve_out_serial_id AS serial"
-                            ",h_blind_ev"
-                            ",denom_sig"
-                            ",reserve_sig"
-                            ",execution_date"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",reserve_uuid"
-                            ",denominations_serial"
-                            " FROM reserves_out"
-                            " WHERE reserve_out_serial_id > $1"
-                            " ORDER BY reserve_out_serial_id ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_auditors",
-                            "SELECT"
-                            " auditor_uuid AS serial"
-                            ",auditor_pub"
-                            ",auditor_name"
-                            ",auditor_url"
-                            ",is_active"
-                            ",last_change"
-                            " FROM auditors"
-                            " WHERE auditor_uuid > $1"
-                            " ORDER BY auditor_uuid ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_auditor_denom_sigs",
-                            "SELECT"
-                            " auditor_denom_serial AS serial"
-                            ",auditor_uuid"
-                            ",denominations_serial"
-                            ",auditor_sig"
-                            " FROM auditor_denom_sigs"
-                            " WHERE auditor_denom_serial > $1"
-                            " ORDER BY auditor_denom_serial ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_exchange_sign_keys",
-                            "SELECT"
-                            " esk_serial AS serial"
-                            ",exchange_pub"
-                            ",master_sig"
-                            ",valid_from"
-                            ",expire_sign"
-                            ",expire_legal"
-                            " FROM exchange_sign_keys"
-                            " WHERE esk_serial > $1"
-                            " ORDER BY esk_serial ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_reserves",
+      "SELECT"
+      " reserve_uuid AS serial"
+      ",reserve_pub"
+      ",current_balance_val"
+      ",current_balance_frac"
+      ",expiration_date"
+      ",gc_date"
+      " FROM reserves"
+      " WHERE reserve_uuid > $1"
+      " ORDER BY reserve_uuid ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_reserves_in",
+      "SELECT"
+      " reserve_in_serial_id AS serial"
+      ",reserve_uuid"
+      ",wire_reference"
+      ",credit_val"
+      ",credit_frac"
+      ",wire_source_serial_id"
+      ",exchange_account_section"
+      ",execution_date"
+      " FROM reserves_in"
+      " WHERE reserve_in_serial_id > $1"
+      " ORDER BY reserve_in_serial_id ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_reserves_close",
+      "SELECT"
+      " close_uuid AS serial"
+      ",reserve_uuid"
+      ",execution_date"
+      ",wtid"
+      ",wire_target_serial_id"
+      ",amount_val"
+      ",amount_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      " FROM reserves_close"
+      " WHERE close_uuid > $1"
+      " ORDER BY close_uuid ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_reserves_out",
+      "SELECT"
+      " reserve_out_serial_id AS serial"
+      ",h_blind_ev"
+      ",denominations_serial"
+      ",denom_sig"
+      ",reserve_uuid"
+      ",reserve_sig"
+      ",execution_date"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      " FROM reserves_out"
+      " WHERE reserve_out_serial_id > $1"
+      " ORDER BY reserve_out_serial_id ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_auditors",
+      "SELECT"
+      " auditor_uuid AS serial"
+      ",auditor_pub"
+      ",auditor_name"
+      ",auditor_url"
+      ",is_active"
+      ",last_change"
+      " FROM auditors"
+      " WHERE auditor_uuid > $1"
+      " ORDER BY auditor_uuid ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_auditor_denom_sigs",
+      "SELECT"
+      " auditor_denom_serial AS serial"
+      ",auditor_uuid"
+      ",denominations_serial"
+      ",auditor_sig"
+      " FROM auditor_denom_sigs"
+      " WHERE auditor_denom_serial > $1"
+      " ORDER BY auditor_denom_serial ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_exchange_sign_keys",
+      "SELECT"
+      " esk_serial AS serial"
+      ",exchange_pub"
+      ",master_sig"
+      ",valid_from"
+      ",expire_sign"
+      ",expire_legal"
+      " FROM exchange_sign_keys"
+      " WHERE esk_serial > $1"
+      " ORDER BY esk_serial ASC;",
+      1),
     GNUNET_PQ_make_prepare (
       "select_above_serial_by_table_signkey_revocations",
       "SELECT"
@@ -2036,26 +2240,27 @@ prepare_statements (struct PostgresClosure *pg)
       " WHERE signkey_revocations_serial_id > $1"
       " ORDER BY signkey_revocations_serial_id ASC;",
       1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_known_coins",
-                            "SELECT"
-                            " known_coin_id AS serial"
-                            ",coin_pub"
-                            ",denom_sig"
-                            ",denominations_serial"
-                            " FROM known_coins"
-                            " WHERE known_coin_id > $1"
-                            " ORDER BY known_coin_id ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_known_coins",
+      "SELECT"
+      " known_coin_id AS serial"
+      ",coin_pub"
+      ",denom_sig"
+      ",denominations_serial"
+      " FROM known_coins"
+      " WHERE known_coin_id > $1"
+      " ORDER BY known_coin_id ASC;",
+      1),
     GNUNET_PQ_make_prepare (
       "select_above_serial_by_table_refresh_commitments",
       "SELECT"
       " melt_serial_id AS serial"
       ",rc"
-      ",old_known_coin_id"
       ",old_coin_sig"
       ",amount_with_fee_val"
       ",amount_with_fee_frac"
       ",noreveal_index"
+      ",old_known_coin_id"
       " FROM refresh_commitments"
       " WHERE melt_serial_id > $1"
       " ORDER BY melt_serial_id ASC;",
@@ -2067,10 +2272,9 @@ prepare_statements (struct PostgresClosure *pg)
       ",freshcoin_index"
       ",link_sig"
       ",coin_ev"
-      ",h_coin_ev"
       ",ev_sig"
-      ",melt_serial_id"
       ",denominations_serial"
+      ",melt_serial_id"
       " FROM refresh_revealed_coins"
       " WHERE rrc_serial > $1"
       " ORDER BY rrc_serial ASC;",
@@ -2086,52 +2290,58 @@ prepare_statements (struct PostgresClosure *pg)
       " WHERE rtc_serial > $1"
       " ORDER BY rtc_serial ASC;",
       1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_deposits",
-                            "SELECT"
-                            " deposit_serial_id AS serial"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",wallet_timestamp"
-                            ",exchange_timestamp"
-                            ",refund_deadline"
-                            ",wire_deadline"
-                            ",merchant_pub"
-                            ",h_contract_terms"
-                            ",h_wire"
-                            ",coin_sig"
-                            ",wire"
-                            ",tiny"
-                            ",done"
-                            ",known_coin_id"
-                            " FROM deposits"
-                            " WHERE deposit_serial_id > $1"
-                            " ORDER BY deposit_serial_id ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_refunds",
-                            "SELECT"
-                            " refund_serial_id AS serial"
-                            ",merchant_sig"
-                            ",rtransaction_id"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",deposit_serial_id"
-                            " FROM refunds"
-                            " WHERE refund_serial_id > $1"
-                            " ORDER BY refund_serial_id ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_wire_out",
-                            "SELECT"
-                            " wireout_uuid AS serial"
-                            ",execution_date"
-                            ",wtid_raw"
-                            ",wire_target"
-                            ",exchange_account_section"
-                            ",amount_val"
-                            ",amount_frac"
-                            " FROM wire_out"
-                            " WHERE wireout_uuid > $1"
-                            " ORDER BY wireout_uuid ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_deposits",
+      "SELECT"
+      " deposit_serial_id AS serial"
+      ",shard"
+      ",known_coin_id"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",wallet_timestamp"
+      ",exchange_timestamp"
+      ",refund_deadline"
+      ",wire_deadline"
+      ",merchant_pub"
+      ",h_contract_terms"
+      ",coin_sig"
+      ",wire_salt"
+      ",wire_target_serial_id"
+      ",tiny"
+      ",done"
+      ",extension_blocked"
+      ",extension_details_serial_id"
+      " FROM deposits"
+      " WHERE deposit_serial_id > $1"
+      " ORDER BY deposit_serial_id ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_refunds",
+      "SELECT"
+      " refund_serial_id AS serial"
+      ",merchant_sig"
+      ",rtransaction_id"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",deposit_serial_id"
+      " FROM refunds"
+      " WHERE refund_serial_id > $1"
+      " ORDER BY refund_serial_id ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_wire_out",
+      "SELECT"
+      " wireout_uuid AS serial"
+      ",execution_date"
+      ",wtid_raw"
+      ",wire_target_serial_id"
+      ",exchange_account_section"
+      ",amount_val"
+      ",amount_frac"
+      " FROM wire_out"
+      " WHERE wireout_uuid > $1"
+      " ORDER BY wireout_uuid ASC;",
+      1),
     GNUNET_PQ_make_prepare (
       "select_above_serial_by_table_aggregation_tracking",
       "SELECT"
@@ -2142,409 +2352,433 @@ prepare_statements (struct PostgresClosure *pg)
       " WHERE aggregation_serial_id > $1"
       " ORDER BY aggregation_serial_id ASC;",
       1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_wire_fee",
-                            "SELECT"
-                            " wire_fee_serial AS serial"
-                            ",wire_method"
-                            ",start_date"
-                            ",end_date"
-                            ",wire_fee_val"
-                            ",wire_fee_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            ",master_sig"
-                            " FROM wire_fee"
-                            " WHERE wire_fee_serial > $1"
-                            " ORDER BY wire_fee_serial ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_recoup",
-                            "SELECT"
-                            " recoup_uuid AS serial"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",known_coin_id"
-                            ",reserve_out_serial_id"
-                            " FROM recoup"
-                            " WHERE recoup_uuid > $1"
-                            " ORDER BY recoup_uuid ASC;",
-                            1),
-    GNUNET_PQ_make_prepare ("select_above_serial_by_table_recoup_refresh",
-                            "SELECT"
-                            " recoup_refresh_uuid AS serial"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",known_coin_id"
-                            ",rrc_serial"
-                            " FROM recoup_refresh"
-                            " WHERE recoup_refresh_uuid > $1"
-                            " ORDER BY recoup_refresh_uuid ASC;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_wire_fee",
+      "SELECT"
+      " wire_fee_serial AS serial"
+      ",wire_method"
+      ",start_date"
+      ",end_date"
+      ",wire_fee_val"
+      ",wire_fee_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      ",master_sig"
+      " FROM wire_fee"
+      " WHERE wire_fee_serial > $1"
+      " ORDER BY wire_fee_serial ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_recoup",
+      "SELECT"
+      " recoup_uuid AS serial"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",known_coin_id"
+      ",reserve_out_serial_id"
+      " FROM recoup"
+      " WHERE recoup_uuid > $1"
+      " ORDER BY recoup_uuid ASC;",
+      1),
+    GNUNET_PQ_make_prepare (
+      "select_above_serial_by_table_recoup_refresh",
+      "SELECT"
+      " recoup_refresh_uuid AS serial"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",known_coin_id"
+      ",rrc_serial"
+      " FROM recoup_refresh"
+      " WHERE recoup_refresh_uuid > $1"
+      " ORDER BY recoup_refresh_uuid ASC;",
+      1),
     /* For postgres_insert_records_by_table */
-    GNUNET_PQ_make_prepare ("insert_into_table_denominations",
-                            "INSERT INTO denominations"
-                            "(denominations_serial"
-                            ",denom_pub_hash"
-                            ",denom_pub"
-                            ",master_sig"
-                            ",valid_from"
-                            ",expire_withdraw"
-                            ",expire_deposit"
-                            ",expire_legal"
-                            ",coin_val"
-                            ",coin_frac"
-                            ",fee_withdraw_val"
-                            ",fee_withdraw_frac"
-                            ",fee_deposit_val"
-                            ",fee_deposit_frac"
-                            ",fee_refresh_val"
-                            ",fee_refresh_frac"
-                            ",fee_refund_val"
-                            ",fee_refund_frac"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
-                            " $11, $12, $13, $14, $15, $16, $17, $18);",
-                            18),
-    GNUNET_PQ_make_prepare ("insert_into_table_denomination_revocations",
-                            "INSERT INTO denomination_revocations"
-                            "(denom_revocations_serial_id"
-                            ",master_sig"
-                            ",denominations_serial"
-                            ") VALUES "
-                            "($1, $2, $3);",
-                            3),
-    GNUNET_PQ_make_prepare ("insert_into_table_reserves",
-                            "INSERT INTO reserves"
-                            "(reserve_uuid"
-                            ",reserve_pub"
-                            ",account_details"
-                            ",current_balance_val"
-                            ",current_balance_frac"
-                            ",expiration_date"
-                            ",gc_date"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7);",
-                            7),
-    GNUNET_PQ_make_prepare ("insert_into_table_reserves_in",
-                            "INSERT INTO reserves_in"
-                            "(reserve_in_serial_id"
-                            ",wire_reference"
-                            ",credit_val"
-                            ",credit_frac"
-                            ",sender_account_details"
-                            ",exchange_account_section"
-                            ",execution_date"
-                            ",reserve_uuid"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8);",
-                            8),
-    GNUNET_PQ_make_prepare ("insert_into_table_reserves_close",
-                            "INSERT INTO reserves_close"
-                            "(close_uuid"
-                            ",execution_date"
-                            ",wtid"
-                            ",receiver_account"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            ",reserve_uuid"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8, $9);",
-                            9),
-    GNUNET_PQ_make_prepare ("insert_into_table_reserves_out",
-                            "INSERT INTO reserves_out"
-                            "(reserve_out_serial_id"
-                            ",h_blind_ev"
-                            ",denom_sig"
-                            ",reserve_sig"
-                            ",execution_date"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",reserve_uuid"
-                            ",denominations_serial"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8, $9);",
-                            9),
-    GNUNET_PQ_make_prepare ("insert_into_table_auditors",
-                            "INSERT INTO auditors"
-                            "(auditor_uuid"
-                            ",auditor_pub"
-                            ",auditor_name"
-                            ",auditor_url"
-                            ",is_active"
-                            ",last_change"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6);",
-                            6),
-    GNUNET_PQ_make_prepare ("insert_into_table_auditor_denom_sigs",
-                            "INSERT INTO auditor_denom_sigs"
-                            "(auditor_denom_serial"
-                            ",auditor_uuid"
-                            ",denominations_serial"
-                            ",auditor_sig"
-                            ") VALUES "
-                            "($1, $2, $3, $4);",
-                            4),
-    GNUNET_PQ_make_prepare ("insert_into_table_exchange_sign_keys",
-                            "INSERT INTO exchange_sign_keys"
-                            "(esk_serial"
-                            ",exchange_pub"
-                            ",master_sig"
-                            ",valid_from"
-                            ",expire_sign"
-                            ",expire_legal"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6);",
-                            6),
-    GNUNET_PQ_make_prepare ("insert_into_table_signkey_revocations",
-                            "INSERT INTO signkey_revocations"
-                            "(signkey_revocations_serial_id"
-                            ",esk_serial"
-                            ",master_sig"
-                            ") VALUES "
-                            "($1, $2, $3);",
-                            3),
-    GNUNET_PQ_make_prepare ("insert_into_table_known_coins",
-                            "INSERT INTO known_coins"
-                            "(known_coin_id"
-                            ",coin_pub"
-                            ",denom_sig"
-                            ",denominations_serial"
-                            ") VALUES "
-                            "($1, $2, $3, $4);",
-                            4),
-    GNUNET_PQ_make_prepare ("insert_into_table_refresh_commitments",
-                            "INSERT INTO refresh_commitments"
-                            "(melt_serial_id"
-                            ",rc"
-                            ",old_coin_sig"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",noreveal_index"
-                            ",old_known_coin_id"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7);",
-                            7),
-    GNUNET_PQ_make_prepare ("insert_into_table_refresh_revealed_coins",
-                            "INSERT INTO refresh_revealed_coins"
-                            "(rrc_serial"
-                            ",freshcoin_index"
-                            ",link_sig"
-                            ",coin_ev"
-                            ",h_coin_ev"
-                            ",ev_sig"
-                            ",denominations_serial"
-                            ",melt_serial_id"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8);",
-                            8),
-    GNUNET_PQ_make_prepare ("insert_into_table_refresh_transfer_keys",
-                            "INSERT INTO refresh_transfer_keys"
-                            "(rtc_serial"
-                            ",transfer_pub"
-                            ",transfer_privs"
-                            ",melt_serial_id"
-                            ") VALUES "
-                            "($1, $2, $3, $4);",
-                            4),
-    GNUNET_PQ_make_prepare ("insert_into_table_deposits",
-                            "INSERT INTO deposits"
-                            "(deposit_serial_id"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",wallet_timestamp"
-                            ",exchange_timestamp"
-                            ",refund_deadline"
-                            ",wire_deadline"
-                            ",merchant_pub"
-                            ",h_contract_terms"
-                            ",h_wire"
-                            ",coin_sig"
-                            ",wire"
-                            ",tiny"
-                            ",done"
-                            ",known_coin_id"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
-                            " $11, $12, $13, $14, $15);",
-                            15),
-    GNUNET_PQ_make_prepare ("insert_into_table_refunds",
-                            "INSERT INTO refunds"
-                            "(refund_serial_id"
-                            ",merchant_sig"
-                            ",rtransaction_id"
-                            ",amount_with_fee_val"
-                            ",amount_with_fee_frac"
-                            ",deposit_serial_id"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6);",
-                            6),
-    GNUNET_PQ_make_prepare ("insert_into_table_wire_out",
-                            "INSERT INTO wire_out"
-                            "(wireout_uuid"
-                            ",execution_date"
-                            ",wtid_raw"
-                            ",wire_target"
-                            ",exchange_account_section"
-                            ",amount_val"
-                            ",amount_frac"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7);",
-                            7),
-    GNUNET_PQ_make_prepare ("insert_into_table_aggregation_tracking",
-                            "INSERT INTO aggregation_tracking"
-                            "(aggregation_serial_id"
-                            ",deposit_serial_id"
-                            ",wtid_raw"
-                            ") VALUES "
-                            "($1, $2, $3);",
-                            3),
-    GNUNET_PQ_make_prepare ("insert_into_table_wire_fee",
-                            "INSERT INTO wire_fee"
-                            "(wire_fee_serial"
-                            ",wire_method"
-                            ",start_date"
-                            ",end_date"
-                            ",wire_fee_val"
-                            ",wire_fee_frac"
-                            ",closing_fee_val"
-                            ",closing_fee_frac"
-                            ",master_sig"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8, $9);",
-                            9),
-    GNUNET_PQ_make_prepare ("insert_into_table_recoup",
-                            "INSERT INTO recoup"
-                            "(recoup_uuid"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",known_coin_id"
-                            ",reserve_out_serial_id"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8);",
-                            8),
-    GNUNET_PQ_make_prepare ("insert_into_table_recoup_refresh",
-                            "INSERT INTO recoup_refresh"
-                            "(recoup_refresh_uuid"
-                            ",coin_sig"
-                            ",coin_blind"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",timestamp"
-                            ",known_coin_id"
-                            ",rrc_serial"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7, $8);",
-                            8),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_denominations",
+      "INSERT INTO denominations"
+      "(denominations_serial"
+      ",denom_pub_hash"
+      ",denom_pub"
+      ",master_sig"
+      ",valid_from"
+      ",expire_withdraw"
+      ",expire_deposit"
+      ",expire_legal"
+      ",coin_val"
+      ",coin_frac"
+      ",fee_withdraw_val"
+      ",fee_withdraw_frac"
+      ",fee_deposit_val"
+      ",fee_deposit_frac"
+      ",fee_refresh_val"
+      ",fee_refresh_frac"
+      ",fee_refund_val"
+      ",fee_refund_frac"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
+      " $11, $12, $13, $14, $15, $16, $17, $18);",
+      18),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_denomination_revocations",
+      "INSERT INTO denomination_revocations"
+      "(denom_revocations_serial_id"
+      ",master_sig"
+      ",denominations_serial"
+      ") VALUES "
+      "($1, $2, $3);",
+      3),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_reserves",
+      "INSERT INTO reserves"
+      "(reserve_uuid"
+      ",reserve_pub"
+      ",current_balance_val"
+      ",current_balance_frac"
+      ",expiration_date"
+      ",gc_date"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6);",
+      6),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_reserves_in",
+      "INSERT INTO reserves_in"
+      "(reserve_in_serial_id"
+      ",wire_reference"
+      ",credit_val"
+      ",credit_frac"
+      ",wire_source_serial_id"
+      ",exchange_account_section"
+      ",execution_date"
+      ",reserve_uuid"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8);",
+      8),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_reserves_close",
+      "INSERT INTO reserves_close"
+      "(close_uuid"
+      ",execution_date"
+      ",wtid"
+      ",wire_target_serial_id"
+      ",amount_val"
+      ",amount_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      ",reserve_uuid"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8, $9);",
+      9),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_reserves_out",
+      "INSERT INTO reserves_out"
+      "(reserve_out_serial_id"
+      ",h_blind_ev"
+      ",denominations_serial"
+      ",denom_sig"
+      ",reserve_uuid"
+      ",reserve_sig"
+      ",execution_date"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8, $9);",
+      9),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_auditors",
+      "INSERT INTO auditors"
+      "(auditor_uuid"
+      ",auditor_pub"
+      ",auditor_name"
+      ",auditor_url"
+      ",is_active"
+      ",last_change"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6);",
+      6),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_auditor_denom_sigs",
+      "INSERT INTO auditor_denom_sigs"
+      "(auditor_denom_serial"
+      ",auditor_uuid"
+      ",denominations_serial"
+      ",auditor_sig"
+      ") VALUES "
+      "($1, $2, $3, $4);",
+      4),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_exchange_sign_keys",
+      "INSERT INTO exchange_sign_keys"
+      "(esk_serial"
+      ",exchange_pub"
+      ",master_sig"
+      ",valid_from"
+      ",expire_sign"
+      ",expire_legal"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6);",
+      6),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_signkey_revocations",
+      "INSERT INTO signkey_revocations"
+      "(signkey_revocations_serial_id"
+      ",esk_serial"
+      ",master_sig"
+      ") VALUES "
+      "($1, $2, $3);",
+      3),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_known_coins",
+      "INSERT INTO known_coins"
+      "(known_coin_id"
+      ",coin_pub"
+      ",denom_sig"
+      ",denominations_serial"
+      ") VALUES "
+      "($1, $2, $3, $4);",
+      4),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_refresh_commitments",
+      "INSERT INTO refresh_commitments"
+      "(melt_serial_id"
+      ",rc"
+      ",old_coin_sig"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",noreveal_index"
+      ",old_known_coin_id"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7);",
+      7),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_refresh_revealed_coins",
+      "INSERT INTO refresh_revealed_coins"
+      "(rrc_serial"
+      ",freshcoin_index"
+      ",link_sig"
+      ",coin_ev"
+      ",h_coin_ev"
+      ",ev_sig"
+      ",denominations_serial"
+      ",melt_serial_id"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8);",
+      8),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_refresh_transfer_keys",
+      "INSERT INTO refresh_transfer_keys"
+      "(rtc_serial"
+      ",transfer_pub"
+      ",transfer_privs"
+      ",melt_serial_id"
+      ") VALUES "
+      "($1, $2, $3, $4);",
+      4),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_deposits",
+      "INSERT INTO deposits"
+      "(deposit_serial_id"
+      ",shard"
+      ",known_coin_id"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",wallet_timestamp"
+      ",exchange_timestamp"
+      ",refund_deadline"
+      ",wire_deadline"
+      ",merchant_pub"
+      ",h_contract_terms"
+      ",coin_sig"
+      ",wire_salt"
+      ",wire_target_serial_id"
+      ",tiny"
+      ",done"
+      ",extension_blocked"
+      ",extension_details_serial_id"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
+      " $11, $12, $13, $14, $15, $16, $17, $18);",
+      18),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_refunds",
+      "INSERT INTO refunds"
+      "(refund_serial_id"
+      ",merchant_sig"
+      ",rtransaction_id"
+      ",amount_with_fee_val"
+      ",amount_with_fee_frac"
+      ",deposit_serial_id"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6);",
+      6),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_aggregation_tracking",
+      "INSERT INTO aggregation_tracking"
+      "(aggregation_serial_id"
+      ",deposit_serial_id"
+      ",wtid_raw"
+      ") VALUES "
+      "($1, $2, $3);",
+      3),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_wire_fee",
+      "INSERT INTO wire_fee"
+      "(wire_fee_serial"
+      ",wire_method"
+      ",start_date"
+      ",end_date"
+      ",wire_fee_val"
+      ",wire_fee_frac"
+      ",closing_fee_val"
+      ",closing_fee_frac"
+      ",master_sig"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8, $9);",
+      9),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_recoup",
+      "INSERT INTO recoup"
+      "(recoup_uuid"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",known_coin_id"
+      ",reserve_out_serial_id"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8);",
+      8),
+    GNUNET_PQ_make_prepare (
+      "insert_into_table_recoup_refresh",
+      "INSERT INTO recoup_refresh"
+      "(recoup_refresh_uuid"
+      ",coin_sig"
+      ",coin_blind"
+      ",amount_val"
+      ",amount_frac"
+      ",timestamp"
+      ",known_coin_id"
+      ",rrc_serial"
+      ") VALUES "
+      "($1, $2, $3, $4, $5, $6, $7, $8);",
+      8),
 
     /* Used in #postgres_begin_shard() */
-    GNUNET_PQ_make_prepare ("get_open_shard",
-                            "SELECT"
-                            " start_row"
-                            ",end_row"
-                            " FROM work_shards"
-                            " WHERE job_name=$1"
-                            "   AND last_attempt<$2"
-                            "   AND completed=FALSE"
-                            " ORDER BY last_attempt ASC"
-                            " LIMIT 1;",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "get_open_shard",
+      "SELECT"
+      " start_row"
+      ",end_row"
+      " FROM work_shards"
+      " WHERE job_name=$1"
+      "   AND last_attempt<$2"
+      "   AND completed=FALSE"
+      " ORDER BY last_attempt ASC"
+      " LIMIT 1;",
+      2),
     /* Used in #postgres_begin_revolving_shard() */
-    GNUNET_PQ_make_prepare ("get_open_revolving_shard",
-                            "SELECT"
-                            " start_row"
-                            ",end_row"
-                            " FROM revolving_work_shards"
-                            " WHERE job_name=$1"
-                            "   AND active=FALSE"
-                            " ORDER BY last_attempt ASC"
-                            " LIMIT 1;",
-                            2),
+    GNUNET_PQ_make_prepare (
+      "get_open_revolving_shard",
+      "SELECT"
+      " start_row"
+      ",end_row"
+      " FROM revolving_work_shards"
+      " WHERE job_name=$1"
+      "   AND active=FALSE"
+      " ORDER BY last_attempt ASC"
+      " LIMIT 1;",
+      2),
     /* Used in #postgres_begin_shard() */
-    GNUNET_PQ_make_prepare ("reclaim_shard",
-                            "UPDATE work_shards"
-                            " SET last_attempt=$2"
-                            " WHERE job_name=$1"
-                            "   AND start_row=$3"
-                            "   AND end_row=$4",
-                            4),
+    GNUNET_PQ_make_prepare (
+      "reclaim_shard",
+      "UPDATE work_shards"
+      " SET last_attempt=$2"
+      " WHERE job_name=$1"
+      "   AND start_row=$3"
+      "   AND end_row=$4",
+      4),
     /* Used in #postgres_begin_revolving_shard() */
-    GNUNET_PQ_make_prepare ("reclaim_revolving_shard",
-                            "UPDATE revolving_work_shards"
-                            " SET last_attempt=$2"
-                            "    ,active=TRUE"
-                            " WHERE job_name=$1"
-                            "   AND start_row=$3"
-                            "   AND end_row=$4",
-                            4),
+    GNUNET_PQ_make_prepare (
+      "reclaim_revolving_shard",
+      "UPDATE revolving_work_shards"
+      " SET last_attempt=$2"
+      "    ,active=TRUE"
+      " WHERE job_name=$1"
+      "   AND start_row=$3"
+      "   AND end_row=$4",
+      4),
     /* Used in #postgres_begin_shard() */
-    GNUNET_PQ_make_prepare ("get_last_shard",
-                            "SELECT"
-                            " end_row"
-                            " FROM work_shards"
-                            " WHERE job_name=$1"
-                            " ORDER BY end_row DESC"
-                            " LIMIT 1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_last_shard",
+      "SELECT"
+      " end_row"
+      " FROM work_shards"
+      " WHERE job_name=$1"
+      " ORDER BY end_row DESC"
+      " LIMIT 1;",
+      1),
     /* Used in #postgres_begin_revolving_shard() */
-    GNUNET_PQ_make_prepare ("get_last_revolving_shard",
-                            "SELECT"
-                            " end_row"
-                            " FROM revolving_work_shards"
-                            " WHERE job_name=$1"
-                            " ORDER BY end_row DESC"
-                            " LIMIT 1;",
-                            1),
+    GNUNET_PQ_make_prepare (
+      "get_last_revolving_shard",
+      "SELECT"
+      " end_row"
+      " FROM revolving_work_shards"
+      " WHERE job_name=$1"
+      " ORDER BY end_row DESC"
+      " LIMIT 1;",
+      1),
     /* Used in #postgres_begin_shard() */
-    GNUNET_PQ_make_prepare ("claim_next_shard",
-                            "INSERT INTO work_shards"
-                            "(job_name"
-                            ",last_attempt"
-                            ",start_row"
-                            ",end_row"
-                            ") VALUES "
-                            "($1, $2, $3, $4);",
-                            4),
+    GNUNET_PQ_make_prepare (
+      "claim_next_shard",
+      "INSERT INTO work_shards"
+      "(job_name"
+      ",last_attempt"
+      ",start_row"
+      ",end_row"
+      ") VALUES "
+      "($1, $2, $3, $4);",
+      4),
     /* Used in #postgres_claim_revolving_shard() */
-    GNUNET_PQ_make_prepare ("create_revolving_shard",
-                            "INSERT INTO revolving_work_shards"
-                            "(job_name"
-                            ",last_attempt"
-                            ",start_row"
-                            ",end_row"
-                            ",active"
-                            ") VALUES "
-                            "($1, $2, $3, $4, TRUE);",
-                            4),
+    GNUNET_PQ_make_prepare (
+      "create_revolving_shard",
+      "INSERT INTO revolving_work_shards"
+      "(job_name"
+      ",last_attempt"
+      ",start_row"
+      ",end_row"
+      ",active"
+      ") VALUES "
+      "($1, $2, $3, $4, TRUE);",
+      4),
     /* Used in #postgres_complete_shard() */
-    GNUNET_PQ_make_prepare ("complete_shard",
-                            "UPDATE work_shards"
-                            " SET completed=TRUE"
-                            " WHERE job_name=$1"
-                            "   AND start_row=$2"
-                            "   AND end_row=$3",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "complete_shard",
+      "UPDATE work_shards"
+      " SET completed=TRUE"
+      " WHERE job_name=$1"
+      "   AND start_row=$2"
+      "   AND end_row=$3",
+      3),
     /* Used in #postgres_complete_shard() */
-    GNUNET_PQ_make_prepare ("release_revolving_shard",
-                            "UPDATE revolving_work_shards"
-                            " SET active=FALSE"
-                            " WHERE job_name=$1"
-                            "   AND start_row=$2"
-                            "   AND end_row=$3",
-                            3),
+    GNUNET_PQ_make_prepare (
+      "release_revolving_shard",
+      "UPDATE revolving_work_shards"
+      " SET active=FALSE"
+      " WHERE job_name=$1"
+      "   AND start_row=$2"
+      "   AND end_row=$3",
+      3),
     /* Used in #postgres_delete_revolving_shards() */
-    GNUNET_PQ_make_prepare ("delete_revolving_shards",
-                            "DELETE FROM revolving_work_shards",
-                            0),
+    GNUNET_PQ_make_prepare (
+      "delete_revolving_shards",
+      "DELETE FROM revolving_work_shards",
+      0),
     GNUNET_PQ_PREPARED_STATEMENT_END
   };
 
@@ -2864,7 +3098,7 @@ postgres_insert_denomination_info (
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (&issue->properties.denom_hash),
-    GNUNET_PQ_query_param_rsa_public_key (denom_pub->rsa_public_key),
+    TALER_PQ_query_param_denom_pub (denom_pub),
     GNUNET_PQ_query_param_auto_from_type (&issue->signature),
     TALER_PQ_query_param_absolute_time_nbo (&issue->properties.start),
     TALER_PQ_query_param_absolute_time_nbo 
(&issue->properties.expire_withdraw),
@@ -2917,7 +3151,7 @@ postgres_insert_denomination_info (
 static enum GNUNET_DB_QueryStatus
 postgres_get_denomination_info (
   void *cls,
-  const struct GNUNET_HashCode *denom_pub_hash,
+  const struct TALER_DenominationHash *denom_pub_hash,
   struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue)
 {
   struct PostgresClosure *pg = cls;
@@ -3031,8 +3265,8 @@ domination_cb_helper (void *cls,
                                        &issue.properties.fee_refresh),
       TALER_PQ_RESULT_SPEC_AMOUNT_NBO ("fee_refund",
                                        &issue.properties.fee_refund),
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &denom_pub.rsa_public_key),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
       GNUNET_PQ_result_spec_end
     };
 
@@ -3051,12 +3285,12 @@ domination_cb_helper (void *cls,
       = htonl (sizeof (struct TALER_DenominationKeyValidityPS));
     issue.properties.purpose.purpose
       = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY);
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
-                                       &issue.properties.denom_hash);
+    TALER_denom_pub_hash (&denom_pub,
+                          &issue.properties.denom_hash);
     dic->cb (dic->cb_cls,
              &denom_pub,
              &issue);
-    GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key);
+    TALER_denom_pub_free (&denom_pub);
   }
 }
 
@@ -3135,7 +3369,7 @@ dominations_cb_helper (void *cls,
     struct TALER_EXCHANGEDB_DenominationKeyMetaData meta;
     struct TALER_DenominationPublicKey denom_pub;
     struct TALER_MasterSignatureP master_sig;
-    struct GNUNET_HashCode h_denom_pub;
+    struct TALER_DenominationHash h_denom_pub;
     uint8_t revoked;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("master_sig",
@@ -3160,8 +3394,8 @@ dominations_cb_helper (void *cls,
                                    &meta.fee_refresh),
       TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refund",
                                    &meta.fee_refund),
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &denom_pub.rsa_public_key),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
       GNUNET_PQ_result_spec_end
     };
 
@@ -3173,8 +3407,8 @@ dominations_cb_helper (void *cls,
       GNUNET_break (0);
       return;
     }
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
-                                       &h_denom_pub);
+    TALER_denom_pub_hash (&denom_pub,
+                          &h_denom_pub);
     dic->cb (dic->cb_cls,
              &denom_pub,
              &h_denom_pub,
@@ -3454,7 +3688,7 @@ auditor_denoms_cb_helper (void *cls,
   for (unsigned int i = 0; i<num_results; i++)
   {
     struct TALER_AuditorPublicKeyP auditor_pub;
-    struct GNUNET_HashCode h_denom_pub;
+    struct TALER_DenominationHash h_denom_pub;
     struct TALER_AuditorSignatureP auditor_sig;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
@@ -3566,23 +3800,51 @@ postgres_reserves_get (void *cls,
  *
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param payment_target_uuid which account has been checked
- * @param ... possibly additional data to persist (TODO)
+ * @param id external ID to persist
  * @return transaction status
  */
 static enum GNUNET_DB_QueryStatus
 postgres_set_kyc_ok (void *cls,
                      uint64_t payment_target_uuid,
-                     ...)
+                     const char *id)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_uint64 (&payment_target_uuid),
     GNUNET_PQ_query_param_end
   };
+  struct GNUNET_PQ_QueryParam params2[] = {
+    GNUNET_PQ_query_param_uint64 (&payment_target_uuid),
+    GNUNET_PQ_query_param_string (id),
+    GNUNET_PQ_query_param_end
+  };
+  struct TALER_KycCompletedEventP rep = {
+    .header.size = htons (sizeof (rep)),
+    .header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED)
+  };
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    GNUNET_PQ_result_spec_auto_from_type ("h_payto",
+                                          &rep.h_payto),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "set_kyc_ok",
-                                             params);
+  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                           "set_kyc_ok",
+                                           params2);
+  if (qs <= 0)
+    return qs;
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "get_kyc_h_payto",
+                                                 params,
+                                                 rs);
+  if (qs <= 0)
+    return qs;
+  postgres_event_notify (pg,
+                         &rep.header,
+                         NULL,
+                         0);
+  return qs;
 }
 
 
@@ -3599,15 +3861,12 @@ postgres_get_kyc_status (void *cls,
                          const char *payto_uri,
                          struct TALER_EXCHANGEDB_KycStatus *kyc)
 {
-#if FIXME_DD23
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_string (payto_uri),
     GNUNET_PQ_query_param_end
   };
-#endif
   uint8_t ok8;
-#if FIXME_DD23
   struct GNUNET_PQ_ResultSpec rs[] = {
     GNUNET_PQ_result_spec_uint64 ("payment_target_uuid",
                                   &kyc->payment_target_uuid),
@@ -3615,19 +3874,12 @@ postgres_get_kyc_status (void *cls,
                                           &ok8),
     GNUNET_PQ_result_spec_end
   };
-#endif
   enum GNUNET_DB_QueryStatus qs;
 
-#if FIXME_DD23
   qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
                                                  "get_kyc_status",
                                                  params,
                                                  rs);
-#else
-  qs = 1;
-  ok8 = 0;
-  kyc->payment_target_uuid = 0;
-#endif
   kyc->type = TALER_EXCHANGEDB_KYC_DEPOSIT;
   kyc->ok = (0 != ok8);
   return qs;
@@ -3646,18 +3898,15 @@ postgres_get_kyc_status (void *cls,
 static enum GNUNET_DB_QueryStatus
 postgres_select_kyc_status (void *cls,
                             uint64_t payment_target_uuid,
-                            struct GNUNET_HashCode *h_payto,
+                            struct TALER_PaytoHash *h_payto,
                             struct TALER_EXCHANGEDB_KycStatus *kyc)
 {
-#if FIXME_DD23
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (payment_target_uuid),
+    GNUNET_PQ_query_param_uint64 (&payment_target_uuid),
     GNUNET_PQ_query_param_end
   };
-#endif
   uint8_t ok8;
-#if FIXME_DD23
   struct GNUNET_PQ_ResultSpec rs[] = {
     GNUNET_PQ_result_spec_auto_from_type ("h_payto",
                                           h_payto),
@@ -3665,21 +3914,88 @@ postgres_select_kyc_status (void *cls,
                                           &ok8),
     GNUNET_PQ_result_spec_end
   };
-#endif
   enum GNUNET_DB_QueryStatus qs;
 
-#if FIXME_DD23
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "select_kyc_status",
-                                                 params,
-                                                 rs);
-#else
-  qs = 1;
-  ok8 = 0;
-#endif
-  kyc->type = TALER_EXCHANGEDB_KYC_UNKNOWN;
-  kyc->ok = (0 != ok8);
-  kyc->payment_target_uuid = payment_target_uuid;
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "select_kyc_status",
+                                                 params,
+                                                 rs);
+  kyc->type = TALER_EXCHANGEDB_KYC_UNKNOWN;
+  kyc->ok = (0 != ok8);
+  kyc->payment_target_uuid = payment_target_uuid;
+  return qs;
+}
+
+
+/**
+ * Get the KYC status for a wallet. If the status is unknown,
+ * inserts a new status record (hence INsertSELECT).
+ *
+ * @param cls the @e cls of this struct with the plugin-specific state
+ * @param payto_uri the payto URI to check
+ * @param oauth_username user ID to store
+ * @param[out] kyc set to the KYC status of the wallet
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+inselect_account_kyc_status (
+  struct PostgresClosure *pg,
+  const char *payto_uri,
+  struct TALER_EXCHANGEDB_KycStatus *kyc)
+{
+
+  struct TALER_PaytoHash h_payto;
+  enum GNUNET_DB_QueryStatus qs;
+
+  TALER_payto_hash (payto_uri,
+                    &h_payto);
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&h_payto),
+      GNUNET_PQ_query_param_end
+    };
+    uint8_t ok8 = 0;
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_uint64 ("wire_target_serial_id",
+                                    &kyc->payment_target_uuid),
+      GNUNET_PQ_result_spec_auto_from_type ("kyc_ok",
+                                            &ok8),
+      GNUNET_PQ_result_spec_end
+    };
+
+    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"select_kyc_status_by_payto",
+                                                   params,
+                                                   rs);
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+    {
+      struct GNUNET_PQ_QueryParam iparams[] = {
+        GNUNET_PQ_query_param_auto_from_type (&h_payto),
+        GNUNET_PQ_query_param_string (payto_uri),
+        GNUNET_PQ_query_param_end
+      };
+      struct GNUNET_PQ_ResultSpec irs[] = {
+        GNUNET_PQ_result_spec_uint64 ("wire_target_serial_id",
+                                      &kyc->payment_target_uuid),
+        GNUNET_PQ_result_spec_end
+      };
+
+      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     "insert_kyc_status",
+                                                     iparams,
+                                                     irs);
+      if (qs < 0)
+        return qs;
+      if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+        return GNUNET_DB_STATUS_SOFT_ERROR;
+      kyc->ok = false;
+    }
+    else
+    {
+      kyc->ok = (0 != ok8);
+    }
+  }
+  kyc->type = TALER_EXCHANGEDB_KYC_BALANCE;
   return qs;
 }
 
@@ -3699,41 +4015,20 @@ postgres_inselect_wallet_kyc_status (
   const struct TALER_ReservePublicKeyP *reserve_pub,
   struct TALER_EXCHANGEDB_KycStatus *kyc)
 {
-#if FIXME_DD23
   struct PostgresClosure *pg = cls;
-  /* FIXME: maybe prepared statement will take
-     a payto:// URI instead of the reserve public key?
-     => figure out once DB schema is stable! */
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
-                                          reserve_pub),
-    GNUNET_PQ_query_param_end
-  };
-#endif
-  uint8_t ok8;
-#if FIXME_DD23
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_uint64 ("payment_target_uuid",
-                                  &kyc->payment_target_uuid),
-    GNUNET_PQ_result_spec_auto_from_type ("kyc_ok",
-                                          &ok8),
-    GNUNET_PQ_result_spec_end
-  };
-#endif
+  char *payto_uri;
   enum GNUNET_DB_QueryStatus qs;
 
-#if FIXME_DD23
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "inselect_wallet_kyc_status",
-                                                 params,
-                                                 rs);
-#else
-  qs = 1;
-  ok8 = 0;
-  kyc->payment_target_uuid = 0;
-#endif
-  kyc->type = TALER_EXCHANGEDB_KYC_BALANCE;
-  kyc->ok = (0 != ok8);
+  payto_uri = TALER_payto_from_reserve (pg->exchange_url,
+                                        reserve_pub);
+  qs = inselect_account_kyc_status (pg,
+                                    payto_uri,
+                                    kyc);
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Wire account for `%s' is %llu\n",
+              payto_uri,
+              (unsigned long long) kyc->payment_target_uuid);
+  GNUNET_free (payto_uri);
   return qs;
 }
 
@@ -3879,7 +4174,6 @@ postgres_reserves_in_insert (void *cls,
   {
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-      GNUNET_PQ_query_param_string (sender_account_details),
       TALER_PQ_query_param_amount (balance),
       TALER_PQ_query_param_absolute_time (&expiry),
       TALER_PQ_query_param_absolute_time (&gc),
@@ -3906,7 +4200,21 @@ postgres_reserves_in_insert (void *cls,
      is again used to guard against duplicates. */
   {
     enum GNUNET_DB_QueryStatus qs2;
+    struct TALER_EXCHANGEDB_KycStatus kyc;
+    enum GNUNET_DB_QueryStatus qs3;
 
+    memset (&kyc,
+            0,
+            sizeof (kyc));
+    qs3 = inselect_account_kyc_status (pg,
+                                       sender_account_details,
+                                       &kyc);
+    if (qs3 <= 0)
+    {
+      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs3);
+      return qs3;
+    }
+    GNUNET_assert (0 != kyc.payment_target_uuid);
     if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs1)
     {
       struct GNUNET_PQ_QueryParam params[] = {
@@ -3914,7 +4222,7 @@ postgres_reserves_in_insert (void *cls,
         GNUNET_PQ_query_param_uint64 (&wire_ref),
         TALER_PQ_query_param_amount (balance),
         GNUNET_PQ_query_param_string (exchange_account_section),
-        GNUNET_PQ_query_param_string (sender_account_details),
+        GNUNET_PQ_query_param_uint64 (&kyc.payment_target_uuid),
         TALER_PQ_query_param_absolute_time (&execution_time),
         GNUNET_PQ_query_param_end
       };
@@ -3930,7 +4238,7 @@ postgres_reserves_in_insert (void *cls,
         GNUNET_PQ_query_param_uint64 (&wire_ref),
         TALER_PQ_query_param_amount (balance),
         GNUNET_PQ_query_param_string (exchange_account_section),
-        GNUNET_PQ_query_param_string (sender_account_details),
+        GNUNET_PQ_query_param_uint64 (&kyc.payment_target_uuid),
         TALER_PQ_query_param_absolute_time (&execution_time),
         GNUNET_PQ_query_param_end
       };
@@ -4114,7 +4422,7 @@ postgres_get_latest_reserve_in_reference (
 static enum GNUNET_DB_QueryStatus
 postgres_get_withdraw_info (
   void *cls,
-  const struct GNUNET_HashCode *h_blind,
+  const struct TALER_BlindedCoinHash *h_blind,
   struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable)
 {
   struct PostgresClosure *pg = cls;
@@ -4125,8 +4433,8 @@ postgres_get_withdraw_info (
   struct GNUNET_PQ_ResultSpec rs[] = {
     GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
                                           &collectable->denom_pub_hash),
-    GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                         &collectable->sig.rsa_signature),
+    TALER_PQ_result_spec_blinded_denom_sig ("denom_sig",
+                                            &collectable->sig),
     GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
                                           &collectable->reserve_sig),
     GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
@@ -4177,7 +4485,7 @@ postgres_insert_withdraw_info (
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (&collectable->h_coin_envelope),
     GNUNET_PQ_query_param_auto_from_type (&collectable->denom_pub_hash),
-    GNUNET_PQ_query_param_rsa_signature (collectable->sig.rsa_signature),
+    TALER_PQ_query_param_blinded_denom_sig (&collectable->sig),
     GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_pub),
     GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_sig),
     TALER_PQ_query_param_absolute_time (&now),
@@ -4381,8 +4689,8 @@ add_withdraw_coin (void *cls,
                                               &cbc->h_coin_envelope),
         GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
                                               &cbc->denom_pub_hash),
-        GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                             &cbc->sig.rsa_signature),
+        TALER_PQ_result_spec_blinded_denom_sig ("denom_sig",
+                                                &cbc->sig),
         GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
                                               &cbc->reserve_sig),
         TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
@@ -4446,9 +4754,9 @@ add_recoup (void *cls,
                                             &recoup->timestamp),
         GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
                                               &recoup->coin.denom_pub_hash),
-        GNUNET_PQ_result_spec_rsa_signature (
+        TALER_PQ_result_spec_denom_sig (
           "denom_sig",
-          &recoup->coin.denom_sig.rsa_signature),
+          &recoup->coin.denom_sig),
         GNUNET_PQ_result_spec_end
       };
 
@@ -4654,11 +4962,11 @@ withdraw_amount_by_account_cb (void *cls,
   struct WithdrawAmountByAccountContext *wac = cls;
   struct PostgresClosure *pg = wac->pg;
 
-  for (unsigned int i = 0; num_results; i++)
+  for (unsigned int i = 0; i < num_results; i++)
   {
     struct TALER_Amount val;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      TALER_PQ_RESULT_SPEC_AMOUNT ("val",
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
                                    &val),
       GNUNET_PQ_result_spec_end
     };
@@ -4716,7 +5024,7 @@ postgres_select_withdraw_amounts_by_account (
 
   qs = GNUNET_PQ_eval_prepared_multi_select (
     pg->conn,
-    "select_XXX",
+    "select_above_date_by_reserves_out",
     params,
     &withdraw_amount_by_account_cb,
     &wac);
@@ -4735,7 +5043,6 @@ postgres_select_withdraw_amounts_by_account (
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
  * @param deposit deposit to search for
- * @param check_extras whether to check extra fields match or not
  * @param[out] deposit_fee set to the deposit fee the exchange charged
  * @param[out] exchange_timestamp set to the time when the exchange received 
the deposit
  * @return 1 if we know this operation,
@@ -4745,7 +5052,6 @@ postgres_select_withdraw_amounts_by_account (
 static enum GNUNET_DB_QueryStatus
 postgres_have_deposit (void *cls,
                        const struct TALER_EXCHANGEDB_Deposit *deposit,
-                       int check_extras,
                        struct TALER_Amount *deposit_fee,
                        struct GNUNET_TIME_Absolute *exchange_timestamp)
 {
@@ -4770,8 +5076,10 @@ postgres_have_deposit (void *cls,
                                         &deposit2.wire_deadline),
     TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
                                  deposit_fee),
-    GNUNET_PQ_result_spec_auto_from_type ("h_wire",
-                                          &deposit2.h_wire),
+    GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                          &deposit2.wire_salt),
+    GNUNET_PQ_result_spec_string ("receiver_wire_account",
+                                  &deposit2.receiver_wire_account),
     GNUNET_PQ_result_spec_end
   };
   enum GNUNET_DB_QueryStatus qs;
@@ -4796,98 +5104,146 @@ postgres_have_deposit (void *cls,
     return qs;
   /* Now we check that the other information in @a deposit
      also matches, and if not report inconsistencies. */
-  if ( ( (check_extras) &&
-         ( (0 != TALER_amount_cmp (&deposit->amount_with_fee,
-                                   &deposit2.amount_with_fee)) ||
-           (deposit->timestamp.abs_value_us !=
-            deposit2.timestamp.abs_value_us) ) ) ||
+  if ( (0 != TALER_amount_cmp (&deposit->amount_with_fee,
+                               &deposit2.amount_with_fee)) ||
+       (deposit->timestamp.abs_value_us !=
+        deposit2.timestamp.abs_value_us) ||
        (deposit->refund_deadline.abs_value_us !=
         deposit2.refund_deadline.abs_value_us) ||
-       (0 != GNUNET_memcmp (&deposit->h_wire,
-                            &deposit2.h_wire) ) )
+       (0 != strcmp (deposit->receiver_wire_account,
+                     deposit2.receiver_wire_account)) ||
+       (0 != GNUNET_memcmp (&deposit->wire_salt,
+                            &deposit2.wire_salt) ) )
   {
+    GNUNET_free (deposit2.receiver_wire_account);
     /* Inconsistencies detected! Does not match!  (We might want to
        expand the API with a 'get_deposit' function to return the
        original transaction details to be used for an error message
-       in the future!) #3838 */
-    return 0;   /* Counts as if the transaction was not there */
+       in the future!) FIXME #3838 */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   }
-  return 1;
+  GNUNET_free (deposit2.receiver_wire_account);
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
 /**
- * Mark a deposit as tiny, thereby declaring that it cannot be
- * executed by itself and should no longer be returned by
- * @e iterate_ready_deposits()
+ * Check if we have the specified deposit already in the database.
  *
- * @param cls the @e cls of this struct with the plugin-specific state
- * @param rowid identifies the deposit row to modify
- * @return query result status
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param h_contract_terms contract to check for
+ * @param h_wire wire hash to check for
+ * @param coin_pub public key of the coin to check for
+ * @param merchant merchant public key to check for
+ * @param refund_deadline expected refund deadline
+ * @param[out] deposit_fee set to the deposit fee the exchange charged
+ * @param[out] exchange_timestamp set to the time when the exchange received 
the deposit
+ * @return 1 if we know this operation,
+ *         0 if this exact deposit is unknown to us,
+ *         otherwise transaction error status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_mark_deposit_tiny (void *cls,
-                            uint64_t rowid)
+postgres_have_deposit2 (
+  void *cls,
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant,
+  struct GNUNET_TIME_Absolute refund_deadline,
+  struct TALER_Amount *deposit_fee,
+  struct GNUNET_TIME_Absolute *exchange_timestamp)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_uint64 (&rowid),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (merchant),
+    GNUNET_PQ_query_param_end
+  };
+  struct TALER_EXCHANGEDB_Deposit deposit2;
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                 &deposit2.amount_with_fee),
+    TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
+                                        &deposit2.timestamp),
+    TALER_PQ_result_spec_absolute_time ("exchange_timestamp",
+                                        exchange_timestamp),
+    TALER_PQ_result_spec_absolute_time ("refund_deadline",
+                                        &deposit2.refund_deadline),
+    TALER_PQ_result_spec_absolute_time ("wire_deadline",
+                                        &deposit2.wire_deadline),
+    TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                 deposit_fee),
+    GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                          &deposit2.wire_salt),
+    GNUNET_PQ_result_spec_string ("receiver_wire_account",
+                                  &deposit2.receiver_wire_account),
+    GNUNET_PQ_result_spec_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+  struct TALER_MerchantWireHash h_wire2;
+#if EXPLICIT_LOCKS
+  struct GNUNET_PQ_QueryParam no_params[] = {
     GNUNET_PQ_query_param_end
   };
 
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "mark_deposit_tiny",
-                                             params);
+  if (0 > (qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                                    "lock_deposit",
+                                                    no_params)))
+    return qs;
+#endif
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Getting deposits for coin %s\n",
+              TALER_B2S (coin_pub));
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "get_deposit",
+                                                 params,
+                                                 rs);
+  if (0 >= qs)
+    return qs;
+  TALER_merchant_wire_signature_hash (deposit2.receiver_wire_account,
+                                      &deposit2.wire_salt,
+                                      &h_wire2);
+  GNUNET_free (deposit2.receiver_wire_account);
+  /* Now we check that the other information in @a deposit
+     also matches, and if not report inconsistencies. */
+  if ( (refund_deadline.abs_value_us !=
+        deposit2.refund_deadline.abs_value_us) ||
+       (0 != GNUNET_memcmp (h_wire,
+                            &h_wire2) ) )
+  {
+    /* Inconsistencies detected! Does not match!  (We might want to
+       expand the API with a 'get_deposit' function to return the
+       original transaction details to be used for an error message
+       in the future!) FIXME #3838 */
+    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+  }
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
 /**
- * Test if a deposit was marked as done, thereby declaring that it cannot be
- * refunded anymore.
+ * Mark a deposit as tiny, thereby declaring that it cannot be
+ * executed by itself and should no longer be returned by
+ * @e iterate_ready_deposits()
  *
  * @param cls the @e cls of this struct with the plugin-specific state
- * @param coin_pub the coin to check for deposit
- * @param merchant_pub merchant to receive the deposit
- * @param h_contract_terms contract terms of the deposit
- * @param h_wire hash of the merchant's wire details
- * @return #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if is is marked done,
- *         #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if not,
- *         otherwise transaction error status (incl. deposit unknown)
+ * @param rowid identifies the deposit row to modify
+ * @return query result status
  */
 static enum GNUNET_DB_QueryStatus
-postgres_test_deposit_done (void *cls,
-                            const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                            const struct TALER_MerchantPublicKeyP 
*merchant_pub,
-                            const struct GNUNET_HashCode *h_contract_terms,
-                            const struct GNUNET_HashCode *h_wire)
+postgres_mark_deposit_tiny (void *cls,
+                            uint64_t rowid)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (h_wire),
+    GNUNET_PQ_query_param_uint64 (&rowid),
     GNUNET_PQ_query_param_end
   };
-  uint8_t done = 0;
-  struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_auto_from_type ("done",
-                                          &done),
-    GNUNET_PQ_result_spec_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
 
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "test_deposit_done",
-                                                 params,
-                                                 rs);
-  if (qs < 0)
-    return qs;
-  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
-    return GNUNET_DB_STATUS_HARD_ERROR; /* deposit MUST exist */
-  return (done
-          ? GNUNET_DB_STATUS_SUCCESS_ONE_RESULT
-          : GNUNET_DB_STATUS_SUCCESS_NO_RESULTS);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "mark_deposit_tiny",
+                                             params);
 }
 
 
@@ -4917,42 +5273,50 @@ postgres_mark_deposit_done (void *cls,
 
 
 /**
- * Obtain information about deposits that are ready to be executed.
- * Such deposits must not be marked as "tiny" or "done", and the
- * execution time must be in the past.
+ * Obtain information about deposits that are ready to be executed.  Such
+ * deposits must not be marked as "tiny" or "done", the execution time must be
+ * in the past, and the KYC status must be 'ok'.
  *
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param start_shard_row minimum shard row to select
  * @param end_shard_row maximum shard row to select (inclusive)
+ * @param kyc_off true if we should not check the KYC status because
+ *                this exchange does not need/support KYC checks.
  * @param deposit_cb function to call for ONE such deposit
  * @param deposit_cb_cls closure for @a deposit_cb
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
 postgres_get_ready_deposit (void *cls,
-                            uint32_t start_shard_row,
-                            uint32_t end_shard_row,
+                            uint64_t start_shard_row,
+                            uint64_t end_shard_row,
+                            bool kyc_off,
                             TALER_EXCHANGEDB_DepositIterator deposit_cb,
                             void *deposit_cb_cls)
 {
   struct PostgresClosure *pg = cls;
+  uint8_t kyc_override = (kyc_off) ? 1 : 0;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   struct GNUNET_PQ_QueryParam params[] = {
     TALER_PQ_query_param_absolute_time (&now),
-    GNUNET_PQ_query_param_uint32 (&start_shard_row),
-    GNUNET_PQ_query_param_uint32 (&end_shard_row),
+    GNUNET_PQ_query_param_uint64 (&start_shard_row),
+    GNUNET_PQ_query_param_uint64 (&end_shard_row),
+    GNUNET_PQ_query_param_auto_from_type (&kyc_override),
     GNUNET_PQ_query_param_end
   };
   struct TALER_Amount amount_with_fee;
   struct TALER_Amount deposit_fee;
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
   struct TALER_MerchantPublicKeyP merchant_pub;
   struct TALER_CoinSpendPublicKeyP coin_pub;
   uint64_t serial_id;
-  json_t *wire;
+  uint64_t wire_target;
+  char *payto_uri;
   struct GNUNET_PQ_ResultSpec rs[] = {
     GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
                                   &serial_id),
+    GNUNET_PQ_result_spec_uint64 ("wire_target_serial_id",
+                                  &wire_target),
     TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
                                  &amount_with_fee),
     TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
@@ -4963,8 +5327,8 @@ postgres_get_ready_deposit (void *cls,
                                           &merchant_pub),
     GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                           &coin_pub),
-    TALER_PQ_result_spec_json ("wire",
-                               &wire),
+    GNUNET_PQ_result_spec_string ("payto_uri",
+                                  &payto_uri),
     GNUNET_PQ_result_spec_end
   };
   enum GNUNET_DB_QueryStatus qs;
@@ -4991,7 +5355,8 @@ postgres_get_ready_deposit (void *cls,
                    &amount_with_fee,
                    &deposit_fee,
                    &h_contract_terms,
-                   wire);
+                   wire_target,
+                   payto_uri);
   GNUNET_PQ_cleanup_result (rs);
   return qs;
 }
@@ -5066,7 +5431,7 @@ match_deposit_cb (void *cls,
   {
     struct TALER_Amount amount_with_fee;
     struct TALER_Amount deposit_fee;
-    struct GNUNET_HashCode h_contract_terms;
+    struct TALER_PrivateContractHash h_contract_terms;
     struct TALER_CoinSpendPublicKeyP coin_pub;
     uint64_t serial_id;
     enum GNUNET_DB_QueryStatus qs;
@@ -5111,7 +5476,7 @@ match_deposit_cb (void *cls,
  * destination.  Those deposits must not already be "done".
  *
  * @param cls the @e cls of this struct with the plugin-specific state
- * @param h_wire destination of the wire transfer
+ * @param wire_target destination of the wire transfer
  * @param merchant_pub public key of the merchant
  * @param deposit_cb function to call for each deposit
  * @param deposit_cb_cls closure for @a deposit_cb
@@ -5122,7 +5487,7 @@ match_deposit_cb (void *cls,
 static enum GNUNET_DB_QueryStatus
 postgres_iterate_matching_deposits (
   void *cls,
-  const struct GNUNET_HashCode *h_wire,
+  uint64_t wire_target,
   const struct TALER_MerchantPublicKeyP *merchant_pub,
   TALER_EXCHANGEDB_MatchingDepositIterator deposit_cb,
   void *deposit_cb_cls,
@@ -5131,7 +5496,7 @@ postgres_iterate_matching_deposits (
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (h_wire),
+    GNUNET_PQ_query_param_uint64 (&wire_target),
     GNUNET_PQ_query_param_end
   };
   struct MatchingDepositContext mdc = {
@@ -5181,8 +5546,8 @@ postgres_get_known_coin (void *cls,
   struct GNUNET_PQ_ResultSpec rs[] = {
     GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
                                           &coin_info->denom_pub_hash),
-    GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                         &coin_info->denom_sig.rsa_signature),
+    TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                    &coin_info->denom_sig),
     GNUNET_PQ_result_spec_end
   };
 
@@ -5209,7 +5574,7 @@ static enum GNUNET_DB_QueryStatus
 postgres_get_coin_denomination (
   void *cls,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  struct GNUNET_HashCode *denom_hash)
+  struct TALER_DenominationHash *denom_hash)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
@@ -5249,7 +5614,7 @@ insert_known_coin (void *cls,
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (&coin_info->coin_pub),
     GNUNET_PQ_query_param_auto_from_type (&coin_info->denom_pub_hash),
-    GNUNET_PQ_query_param_rsa_signature (coin_info->denom_sig.rsa_signature),
+    TALER_PQ_query_param_denom_sig (&coin_info->denom_sig),
     GNUNET_PQ_query_param_end
   };
 
@@ -5271,7 +5636,7 @@ insert_known_coin (void *cls,
  */
 static long long
 postgres_count_known_coins (void *cls,
-                            const struct GNUNET_HashCode *denom_pub_hash)
+                            const struct TALER_DenominationHash 
*denom_pub_hash)
 {
   struct PostgresClosure *pg = cls;
   uint64_t count;
@@ -5309,7 +5674,7 @@ postgres_ensure_coin_known (void *cls,
 {
   struct PostgresClosure *pg = cls;
   enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_HashCode denom_pub_hash;
+  struct TALER_DenominationHash denom_pub_hash;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (&coin->coin_pub),
     GNUNET_PQ_query_param_end
@@ -5356,9 +5721,10 @@ postgres_ensure_coin_known (void *cls,
   switch (qs)
   {
   case GNUNET_DB_STATUS_HARD_ERROR:
-    return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
+    GNUNET_break (0);
     return TALER_EXCHANGEDB_CKS_HARD_FAIL;
+  case GNUNET_DB_STATUS_SOFT_ERROR:
+    return TALER_EXCHANGEDB_CKS_SOFT_FAIL;
   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     GNUNET_break (0);
     return TALER_EXCHANGEDB_CKS_HARD_FAIL;
@@ -5375,7 +5741,7 @@ postgres_ensure_coin_known (void *cls,
  * @param deposit deposit to compute shard for
  * @return shard number
  */
-static uint32_t
+static uint64_t
 compute_shard (const struct TALER_EXCHANGEDB_Deposit *deposit)
 {
   uint32_t res;
@@ -5383,10 +5749,10 @@ compute_shard (const struct TALER_EXCHANGEDB_Deposit 
*deposit)
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CRYPTO_kdf (&res,
                                     sizeof (res),
-                                    &deposit->h_wire,
-                                    sizeof (deposit->h_wire),
                                     &deposit->merchant_pub,
                                     sizeof (deposit->merchant_pub),
+                                    deposit->receiver_wire_account,
+                                    strlen (deposit->receiver_wire_account),
                                     NULL, 0));
   /* interpret hash result as NBO for platform independence,
      convert to HBO and map to [0..2^31-1] range */
@@ -5394,7 +5760,7 @@ compute_shard (const struct TALER_EXCHANGEDB_Deposit 
*deposit)
   if (res > INT32_MAX)
     res += INT32_MIN;
   GNUNET_assert (res <= INT32_MAX);
-  return res;
+  return (uint64_t) res;
 }
 
 
@@ -5412,32 +5778,46 @@ postgres_insert_deposit (void *cls,
                          const struct TALER_EXCHANGEDB_Deposit *deposit)
 {
   struct PostgresClosure *pg = cls;
-  uint32_t shard = compute_shard (deposit);
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
-    TALER_PQ_query_param_amount (&deposit->amount_with_fee),
-    TALER_PQ_query_param_absolute_time (&deposit->timestamp),
-    TALER_PQ_query_param_absolute_time (&deposit->refund_deadline),
-    TALER_PQ_query_param_absolute_time (&deposit->wire_deadline),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->h_wire),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
-    TALER_PQ_query_param_json (deposit->receiver_wire_account),
-    TALER_PQ_query_param_absolute_time (&exchange_timestamp),
-    GNUNET_PQ_query_param_uint32 (&shard),
-    GNUNET_PQ_query_param_end
-  };
+  struct TALER_EXCHANGEDB_KycStatus kyc;
+  enum GNUNET_DB_QueryStatus qs;
 
-  GNUNET_assert (shard <= INT32_MAX);
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Inserting deposit to be executed at %s (%llu/%llu)\n",
-              GNUNET_STRINGS_absolute_time_to_string (deposit->wire_deadline),
-              (unsigned long long) deposit->wire_deadline.abs_value_us,
-              (unsigned long long) deposit->refund_deadline.abs_value_us);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "insert_deposit",
-                                             params);
+  qs = inselect_account_kyc_status (pg,
+                                    deposit->receiver_wire_account,
+                                    &kyc);
+  if (qs <= 0)
+  {
+    GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
+  }
+  {
+    uint64_t shard = compute_shard (deposit);
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
+      TALER_PQ_query_param_amount (&deposit->amount_with_fee),
+      TALER_PQ_query_param_absolute_time (&deposit->timestamp),
+      TALER_PQ_query_param_absolute_time (&deposit->refund_deadline),
+      TALER_PQ_query_param_absolute_time (&deposit->wire_deadline),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->wire_salt),
+      GNUNET_PQ_query_param_uint64 (&kyc.payment_target_uuid),
+      GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
+      TALER_PQ_query_param_absolute_time (&exchange_timestamp),
+      GNUNET_PQ_query_param_uint64 (&shard),
+      GNUNET_PQ_query_param_end
+    };
+
+    GNUNET_assert (shard <= INT32_MAX);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Inserting deposit to be executed at %s (%llu/%llu)\n",
+                GNUNET_STRINGS_absolute_time_to_string 
(deposit->wire_deadline),
+                (unsigned long long) deposit->wire_deadline.abs_value_us,
+                (unsigned long long) deposit->refund_deadline.abs_value_us);
+    return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "insert_deposit",
+                                               params);
+  }
 }
 
 
@@ -5557,7 +5937,7 @@ postgres_select_refunds_by_coin (
   void *cls,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_MerchantPublicKeyP *merchant_pub,
-  const struct GNUNET_HashCode *h_contract,
+  const struct TALER_PrivateContractHash *h_contract,
   TALER_EXCHANGEDB_RefundCoinCallback cb,
   void *cb_cls)
 {
@@ -5625,7 +6005,9 @@ postgres_get_melt (void *cls,
   };
   enum GNUNET_DB_QueryStatus qs;
 
-  melt->session.coin.denom_sig.rsa_signature = NULL;
+  memset (&melt->session.coin.denom_sig,
+          0,
+          sizeof (melt->session.coin.denom_sig));
   qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
                                                  "get_melt",
                                                  params,
@@ -5731,8 +6113,8 @@ postgres_insert_refresh_reveal (
   for (uint32_t i = 0; i<num_rrcs; i++)
   {
     const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
-    struct GNUNET_HashCode denom_pub_hash;
-    struct GNUNET_HashCode h_coin_ev;
+    struct TALER_DenominationHash denom_pub_hash;
+    struct TALER_BlindedCoinHash h_coin_ev;
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_auto_from_type (rc),
       GNUNET_PQ_query_param_uint32 (&i),
@@ -5741,16 +6123,16 @@ postgres_insert_refresh_reveal (
       GNUNET_PQ_query_param_fixed_size (rrc->coin_ev,
                                         rrc->coin_ev_size),
       GNUNET_PQ_query_param_auto_from_type (&h_coin_ev),
-      GNUNET_PQ_query_param_rsa_signature (rrc->coin_sig.rsa_signature),
+      TALER_PQ_query_param_blinded_denom_sig (&rrc->coin_sig),
       GNUNET_PQ_query_param_end
     };
     enum GNUNET_DB_QueryStatus qs;
 
-    GNUNET_CRYPTO_rsa_public_key_hash (rrc->denom_pub.rsa_public_key,
-                                       &denom_pub_hash);
+    TALER_denom_pub_hash (&rrc->denom_pub,
+                          &denom_pub_hash);
     GNUNET_CRYPTO_hash (rrc->coin_ev,
                         rrc->coin_ev_size,
-                        &h_coin_ev);
+                        &h_coin_ev.hash);
     qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                              "insert_refresh_revealed_coin",
                                              params);
@@ -5826,15 +6208,15 @@ add_revealed_coins (void *cls,
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint32 ("freshcoin_index",
                                     &off),
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &rrc->denom_pub.rsa_public_key),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &rrc->denom_pub),
       GNUNET_PQ_result_spec_auto_from_type ("link_sig",
                                             &rrc->orig_coin_link_sig),
       GNUNET_PQ_result_spec_variable_size ("coin_ev",
                                            (void **) &rrc->coin_ev,
                                            &rrc->coin_ev_size),
-      GNUNET_PQ_result_spec_rsa_signature ("ev_sig",
-                                           &rrc->coin_sig.rsa_signature),
+      TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
+                                              &rrc->coin_sig),
       GNUNET_PQ_result_spec_end
     };
 
@@ -5961,10 +6343,8 @@ cleanup:
   {
     struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &grctx.rrcs[i];
 
-    if (NULL != rrc->denom_pub.rsa_public_key)
-      GNUNET_CRYPTO_rsa_public_key_free (rrc->denom_pub.rsa_public_key);
-    if (NULL != rrc->coin_sig.rsa_signature)
-      GNUNET_CRYPTO_rsa_signature_free (rrc->coin_sig.rsa_signature);
+    TALER_denom_pub_free (&rrc->denom_pub);
+    TALER_blinded_denom_sig_free (&rrc->coin_sig);
     GNUNET_free (rrc->coin_ev);
   }
   GNUNET_free (grctx.rrcs);
@@ -6021,10 +6401,8 @@ free_link_data_list (void *cls,
   while (NULL != ldl)
   {
     next = ldl->next;
-    if (NULL != ldl->denom_pub.rsa_public_key)
-      GNUNET_CRYPTO_rsa_public_key_free (ldl->denom_pub.rsa_public_key);
-    if (NULL != ldl->ev_sig.rsa_signature)
-      GNUNET_CRYPTO_rsa_signature_free (ldl->ev_sig.rsa_signature);
+    TALER_denom_pub_free (&ldl->denom_pub);
+    TALER_blinded_denom_sig_free (&ldl->ev_sig);
     GNUNET_free (ldl);
     ldl = next;
   }
@@ -6058,10 +6436,10 @@ add_ldl (void *cls,
                                               &transfer_pub),
         GNUNET_PQ_result_spec_auto_from_type ("link_sig",
                                               &pos->orig_coin_link_sig),
-        GNUNET_PQ_result_spec_rsa_signature ("ev_sig",
-                                             &pos->ev_sig.rsa_signature),
-        GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                              &pos->denom_pub.rsa_public_key),
+        TALER_PQ_result_spec_blinded_denom_sig ("ev_sig",
+                                                &pos->ev_sig),
+        TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                        &pos->denom_pub),
         GNUNET_PQ_result_spec_end
       };
 
@@ -6231,10 +6609,10 @@ add_coin_deposit (void *cls,
                                               &deposit->merchant_pub),
         GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
                                               &deposit->h_contract_terms),
-        GNUNET_PQ_result_spec_auto_from_type ("h_wire",
-                                              &deposit->h_wire),
-        TALER_PQ_result_spec_json ("wire",
-                                   &deposit->receiver_wire_account),
+        GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                              &deposit->wire_salt),
+        GNUNET_PQ_result_spec_string ("payto_uri",
+                                      &deposit->receiver_wire_account),
         GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
                                               &deposit->csig),
         GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
@@ -6429,9 +6807,8 @@ add_old_coin_recoup (void *cls,
                                             &recoup->timestamp),
         GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
                                               &recoup->coin.denom_pub_hash),
-        GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                             &recoup->coin.denom_sig.
-                                             rsa_signature),
+        TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                        &recoup->coin.denom_sig),
         GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
                                       &serial_id),
         GNUNET_PQ_result_spec_end
@@ -6559,9 +6936,8 @@ add_coin_recoup_refresh (void *cls,
                                             &recoup->timestamp),
         GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
                                               &recoup->coin.denom_pub_hash),
-        GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                             &recoup->coin.denom_sig.
-                                             rsa_signature),
+        TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                        &recoup->coin.denom_sig),
         GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
                                       &serial_id),
         GNUNET_PQ_result_spec_end
@@ -6752,28 +7128,32 @@ handle_wt_result (void *cls,
   for (unsigned int i = 0; i<num_results; i++)
   {
     uint64_t rowid;
-    struct GNUNET_HashCode h_contract_terms;
-    struct GNUNET_HashCode h_wire;
+    struct TALER_PrivateContractHash h_contract_terms;
     struct TALER_CoinSpendPublicKeyP coin_pub;
     struct TALER_MerchantPublicKeyP merchant_pub;
     struct GNUNET_TIME_Absolute exec_time;
     struct TALER_Amount amount_with_fee;
     struct TALER_Amount deposit_fee;
     struct TALER_DenominationPublicKey denom_pub;
-    json_t *wire;
+    char *payto_uri;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", &rowid),
       GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
                                             &h_contract_terms),
-      TALER_PQ_result_spec_json ("wire", &wire),
-      GNUNET_PQ_result_spec_auto_from_type ("h_wire", &h_wire),
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &denom_pub.rsa_public_key),
-      GNUNET_PQ_result_spec_auto_from_type ("coin_pub", &coin_pub),
-      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub", &merchant_pub),
-      TALER_PQ_result_spec_absolute_time ("execution_date", &exec_time),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", &amount_with_fee),
-      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", &deposit_fee),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
+                                            &coin_pub),
+      GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
+                                            &merchant_pub),
+      TALER_PQ_result_spec_absolute_time ("execution_date",
+                                          &exec_time),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
+                                   &amount_with_fee),
+      TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+                                   &deposit_fee),
       GNUNET_PQ_result_spec_end
     };
 
@@ -6789,8 +7169,7 @@ handle_wt_result (void *cls,
     ctx->cb (ctx->cb_cls,
              rowid,
              &merchant_pub,
-             &h_wire,
-             wire,
+             payto_uri,
              exec_time,
              &h_contract_terms,
              &denom_pub,
@@ -6866,8 +7245,8 @@ postgres_lookup_wire_transfer (
 static enum GNUNET_DB_QueryStatus
 postgres_lookup_transfer_by_deposit (
   void *cls,
-  const struct GNUNET_HashCode *h_contract_terms,
-  const struct GNUNET_HashCode *h_wire,
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const struct TALER_MerchantWireHash *h_wire,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_MerchantPublicKeyP *merchant_pub,
   bool *pending,
@@ -6882,13 +7261,18 @@ postgres_lookup_transfer_by_deposit (
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
     GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (h_wire),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
+  char *payto_uri;
+  struct TALER_WireSalt wire_salt;
   struct GNUNET_PQ_ResultSpec rs[] = {
     GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
                                           wtid),
+    GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                          &wire_salt),
+    GNUNET_PQ_result_spec_string ("payto_uri",
+                                  &payto_uri),
     TALER_PQ_result_spec_absolute_time ("execution_date",
                                         exec_time),
     TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
@@ -6905,13 +7289,25 @@ postgres_lookup_transfer_by_deposit (
                                                  rs);
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
   {
-    *pending = false;
-    memset (kyc,
-            0,
-            sizeof (*kyc));
-    kyc->type = TALER_EXCHANGEDB_KYC_DEPOSIT;
-    kyc->ok = true;
-    return qs;
+    struct TALER_MerchantWireHash wh;
+
+    TALER_merchant_wire_signature_hash (payto_uri,
+                                        &wire_salt,
+                                        &wh);
+    GNUNET_PQ_cleanup_result (rs);
+    if (0 ==
+        GNUNET_memcmp (&wh,
+                       h_wire))
+    {
+      *pending = false;
+      memset (kyc,
+              0,
+              sizeof (*kyc));
+      kyc->type = TALER_EXCHANGEDB_KYC_DEPOSIT;
+      kyc->ok = true;
+      return qs;
+    }
+    qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   }
   if (0 > qs)
     return qs;
@@ -6924,10 +7320,14 @@ postgres_lookup_transfer_by_deposit (
               "lookup_deposit_wtid returned 0 matching rows\n");
   {
     /* Check if transaction exists in deposits, so that we just
-       do not have a WTID yet, if so, do call the CB with a NULL wtid
-       and return #GNUNET_YES! */
+       do not have a WTID yet. In that case, return without wtid
+       (by setting 'pending' true). */
     uint8_t ok8 = 0;
     struct GNUNET_PQ_ResultSpec rs2[] = {
+      GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                            &wire_salt),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
       GNUNET_PQ_result_spec_uint64 ("payment_target_uuid",
                                     &kyc->payment_target_uuid),
       GNUNET_PQ_result_spec_auto_from_type ("kyc_ok",
@@ -6942,9 +7342,22 @@ postgres_lookup_transfer_by_deposit (
     };
 
     qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "get_deposit_for_wtid",
+                                                   "get_deposit_without_wtid",
                                                    params,
                                                    rs2);
+    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+    {
+      struct TALER_MerchantWireHash wh;
+
+      TALER_merchant_wire_signature_hash (payto_uri,
+                                          &wire_salt,
+                                          &wh);
+      GNUNET_PQ_cleanup_result (rs);
+      if (0 !=
+          GNUNET_memcmp (&wh,
+                         h_wire))
+        return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+    }
     kyc->type = TALER_EXCHANGEDB_KYC_DEPOSIT;
     kyc->ok = (0 != ok8);
     return qs;
@@ -7257,21 +7670,33 @@ postgres_insert_reserve_closed (
 {
   struct PostgresClosure *pg = cls;
   struct TALER_EXCHANGEDB_Reserve reserve;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (reserve_pub),
-    TALER_PQ_query_param_absolute_time (&execution_date),
-    GNUNET_PQ_query_param_auto_from_type (wtid),
-    GNUNET_PQ_query_param_string (receiver_account),
-    TALER_PQ_query_param_amount (amount_with_fee),
-    TALER_PQ_query_param_amount (closing_fee),
-    GNUNET_PQ_query_param_end
-  };
-  enum TALER_AmountArithmeticResult ret;
+  struct TALER_EXCHANGEDB_KycStatus kyc;
   enum GNUNET_DB_QueryStatus qs;
 
-  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                           "reserves_close_insert",
-                                           params);
+  qs = inselect_account_kyc_status (pg,
+                                    receiver_account,
+                                    &kyc);
+  if (qs <= 0)
+  {
+    GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    return qs;
+  }
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (reserve_pub),
+      TALER_PQ_query_param_absolute_time (&execution_date),
+      GNUNET_PQ_query_param_auto_from_type (wtid),
+      GNUNET_PQ_query_param_uint64 (&kyc.payment_target_uuid),
+      TALER_PQ_query_param_amount (amount_with_fee),
+      TALER_PQ_query_param_amount (closing_fee),
+      GNUNET_PQ_query_param_end
+    };
+
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "reserves_close_insert",
+                                             params);
+  }
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
     return qs;
 
@@ -7287,20 +7712,24 @@ postgres_insert_reserve_closed (
       qs = GNUNET_DB_STATUS_HARD_ERROR;
     return qs;
   }
-  ret = TALER_amount_subtract (&reserve.balance,
-                               &reserve.balance,
-                               amount_with_fee);
-  if (ret < 0)
   {
-    /* The reserve history was checked to make sure there is enough of a 
balance
-       left before we tried this; however, concurrent operations may have 
changed
-       the situation by now.  We should re-try the transaction.  */
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Closing of reserve `%s' refused due to balance mismatch. 
Retrying.\n",
-                TALER_B2S (reserve_pub));
-    return GNUNET_DB_STATUS_HARD_ERROR;
+    enum TALER_AmountArithmeticResult ret;
+
+    ret = TALER_amount_subtract (&reserve.balance,
+                                 &reserve.balance,
+                                 amount_with_fee);
+    if (ret < 0)
+    {
+      /* The reserve history was checked to make sure there is enough of a 
balance
+         left before we tried this; however, concurrent operations may have 
changed
+         the situation by now.  We should re-try the transaction.  */
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Closing of reserve `%s' refused due to balance mismatch. 
Retrying.\n",
+                  TALER_B2S (reserve_pub));
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
   }
-  GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
   return reserves_update (cls,
                           &reserve);
 }
@@ -7538,7 +7967,7 @@ postgres_start_deferred_wire_out (void *cls)
  * @param cls closure
  * @param date time of the wire transfer
  * @param wtid subject of the wire transfer
- * @param wire_account details about the receiver account of the wire transfer
+ * @param wire_target identifies the receiver account of the wire transfer
  * @param exchange_account_section configuration section of the exchange 
specifying the
  *        exchange's bank account being used
  * @param amount amount that was transmitted
@@ -7549,7 +7978,7 @@ postgres_store_wire_transfer_out (
   void *cls,
   struct GNUNET_TIME_Absolute date,
   const struct TALER_WireTransferIdentifierRawP *wtid,
-  const json_t *wire_account,
+  uint64_t wire_target,
   const char *exchange_account_section,
   const struct TALER_Amount *amount)
 {
@@ -7557,12 +7986,14 @@ postgres_store_wire_transfer_out (
   struct GNUNET_PQ_QueryParam params[] = {
     TALER_PQ_query_param_absolute_time (&date),
     GNUNET_PQ_query_param_auto_from_type (wtid),
-    TALER_PQ_query_param_json (wire_account),
+    GNUNET_PQ_query_param_uint64 (&wire_target),
     GNUNET_PQ_query_param_string (exchange_account_section),
     TALER_PQ_query_param_amount (amount),
     GNUNET_PQ_query_param_end
   };
 
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_TIME_round_abs (&date));
   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                              "insert_wire_out",
                                              params);
@@ -7577,7 +8008,7 @@ postgres_store_wire_transfer_out (
  * @return #GNUNET_OK on success,
  *         #GNUNET_SYSERR on DB errors
  */
-static int
+static enum GNUNET_GenericReturnValue
 postgres_gc (void *cls)
 {
   struct PostgresClosure *pg = cls;
@@ -7726,8 +8157,8 @@ deposit_serial_helper_cb (void *cls,
                                           &exchange_timestamp),
       GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
                                             &deposit.merchant_pub),
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &denom_pub.rsa_public_key),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                             &deposit.coin.coin_pub),
       GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
@@ -7738,8 +8169,10 @@ deposit_serial_helper_cb (void *cls,
                                           &deposit.wire_deadline),
       GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
                                             &deposit.h_contract_terms),
-      TALER_PQ_result_spec_json ("wire",
-                                 &deposit.receiver_wire_account),
+      GNUNET_PQ_result_spec_auto_from_type ("wire_salt",
+                                            &deposit.wire_salt),
+      GNUNET_PQ_result_spec_string ("receiver_wire_account",
+                                    &deposit.receiver_wire_account),
       GNUNET_PQ_result_spec_auto_from_type ("done",
                                             &done),
       GNUNET_PQ_result_spec_uint64 ("deposit_serial_id",
@@ -7760,17 +8193,9 @@ deposit_serial_helper_cb (void *cls,
     ret = dsc->cb (dsc->cb_cls,
                    rowid,
                    exchange_timestamp,
-                   deposit.timestamp,
-                   &deposit.merchant_pub,
+                   &deposit,
                    &denom_pub,
-                   &deposit.coin.coin_pub,
-                   &deposit.csig,
-                   &deposit.amount_with_fee,
-                   &deposit.h_contract_terms,
-                   deposit.refund_deadline,
-                   deposit.wire_deadline,
-                   deposit.receiver_wire_account,
-                   done);
+                   (0 != done) ? true : false);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
@@ -7873,8 +8298,8 @@ refreshs_serial_helper_cb (void *cls,
     uint64_t rowid;
     struct TALER_RefreshCommitmentP rc;
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &denom_pub.rsa_public_key),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
       GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
                                             &coin_pub),
       GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
@@ -8014,8 +8439,8 @@ refunds_serial_helper_cb (void *cls,
                                             &refund.details.h_contract_terms),
       GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
                                     &refund.details.rtransaction_id),
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &denom_pub.rsa_public_key),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                             &refund.coin.coin_pub),
       TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
@@ -8315,7 +8740,7 @@ reserves_out_serial_helper_cb (void *cls,
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    struct GNUNET_HashCode h_blind_ev;
+    struct TALER_BlindedCoinHash h_blind_ev;
     struct TALER_DenominationPublicKey denom_pub;
     struct TALER_ReservePublicKeyP reserve_pub;
     struct TALER_ReserveSignatureP reserve_sig;
@@ -8325,8 +8750,8 @@ reserves_out_serial_helper_cb (void *cls,
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
                                             &h_blind_ev),
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &denom_pub.rsa_public_key),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
       GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
                                             &reserve_pub),
       GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
@@ -8455,7 +8880,7 @@ wire_out_serial_helper_cb (void *cls,
     uint64_t rowid;
     struct GNUNET_TIME_Absolute date;
     struct TALER_WireTransferIdentifierRawP wtid;
-    json_t *wire;
+    char *payto_uri;
     struct TALER_Amount amount;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint64 ("wireout_uuid",
@@ -8464,8 +8889,8 @@ wire_out_serial_helper_cb (void *cls,
                                           &date),
       GNUNET_PQ_result_spec_auto_from_type ("wtid_raw",
                                             &wtid),
-      TALER_PQ_result_spec_json ("wire_target",
-                                 &wire),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
       TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
                                    &amount),
       GNUNET_PQ_result_spec_end
@@ -8485,7 +8910,7 @@ wire_out_serial_helper_cb (void *cls,
                     rowid,
                     date,
                     &wtid,
-                    wire,
+                    payto_uri,
                     &amount);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
@@ -8629,10 +9054,10 @@ recoup_serial_helper_cb (void *cls,
     struct TALER_ReservePublicKeyP reserve_pub;
     struct TALER_CoinPublicInfo coin;
     struct TALER_CoinSpendSignatureP coin_sig;
-    struct TALER_DenominationBlindingKeyP coin_blind;
+    union TALER_DenominationBlindingKeyP coin_blind;
     struct TALER_Amount amount;
     struct TALER_DenominationPublicKey denom_pub;
-    struct GNUNET_HashCode h_blind_ev;
+    struct TALER_BlindedCoinHash h_blind_ev;
     struct GNUNET_TIME_Absolute timestamp;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint64 ("recoup_uuid",
@@ -8643,8 +9068,8 @@ recoup_serial_helper_cb (void *cls,
                                             &reserve_pub),
       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                             &coin.coin_pub),
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &denom_pub.rsa_public_key),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
       GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
                                             &coin_sig),
       GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
@@ -8653,8 +9078,8 @@ recoup_serial_helper_cb (void *cls,
                                             &h_blind_ev),
       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
                                             &coin.denom_pub_hash),
-      GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                           &coin.denom_sig.rsa_signature),
+      TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                      &coin.denom_sig),
       TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
                                    &amount),
       GNUNET_PQ_result_spec_end
@@ -8777,11 +9202,11 @@ recoup_refresh_serial_helper_cb (void *cls,
     struct TALER_CoinSpendPublicKeyP old_coin_pub;
     struct TALER_CoinPublicInfo coin;
     struct TALER_CoinSpendSignatureP coin_sig;
-    struct TALER_DenominationBlindingKeyP coin_blind;
+    union TALER_DenominationBlindingKeyP coin_blind;
     struct TALER_DenominationPublicKey denom_pub;
-    struct GNUNET_HashCode old_denom_pub_hash;
+    struct TALER_DenominationHash old_denom_pub_hash;
     struct TALER_Amount amount;
-    struct GNUNET_HashCode h_blind_ev;
+    struct TALER_BlindedCoinHash h_blind_ev;
     struct GNUNET_TIME_Absolute timestamp;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_uint64 ("recoup_refresh_uuid",
@@ -8798,14 +9223,14 @@ recoup_refresh_serial_helper_cb (void *cls,
                                             &coin_sig),
       GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
                                             &coin_blind),
-      GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &denom_pub.rsa_public_key),
+      TALER_PQ_result_spec_denom_pub ("denom_pub",
+                                      &denom_pub),
       GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
                                             &h_blind_ev),
       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
                                             &coin.denom_pub_hash),
-      GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                           &coin.denom_sig.rsa_signature),
+      TALER_PQ_result_spec_denom_sig ("denom_sig",
+                                      &coin.denom_sig),
       TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
                                    &amount),
       GNUNET_PQ_result_spec_end
@@ -9038,9 +9463,9 @@ postgres_insert_recoup_request (
   const struct TALER_ReservePublicKeyP *reserve_pub,
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const struct TALER_DenominationBlindingKeyP *coin_blind,
+  const union TALER_DenominationBlindingKeyP *coin_blind,
   const struct TALER_Amount *amount,
-  const struct GNUNET_HashCode *h_blind_ev,
+  const struct TALER_BlindedCoinHash *h_blind_ev,
   struct GNUNET_TIME_Absolute timestamp)
 {
   struct PostgresClosure *pg = cls;
@@ -9130,9 +9555,9 @@ postgres_insert_recoup_refresh_request (
   void *cls,
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const struct TALER_DenominationBlindingKeyP *coin_blind,
+  const union TALER_DenominationBlindingKeyP *coin_blind,
   const struct TALER_Amount *amount,
-  const struct GNUNET_HashCode *h_blind_ev,
+  const struct TALER_BlindedCoinHash *h_blind_ev,
   struct GNUNET_TIME_Absolute timestamp)
 {
   struct PostgresClosure *pg = cls;
@@ -9174,7 +9599,7 @@ postgres_insert_recoup_refresh_request (
  */
 static enum GNUNET_DB_QueryStatus
 postgres_get_reserve_by_h_blind (void *cls,
-                                 const struct GNUNET_HashCode *h_blind_ev,
+                                 const struct TALER_BlindedCoinHash 
*h_blind_ev,
                                  struct TALER_ReservePublicKeyP *reserve_pub)
 {
   struct PostgresClosure *pg = cls;
@@ -9206,7 +9631,8 @@ postgres_get_reserve_by_h_blind (void *cls,
  */
 static enum GNUNET_DB_QueryStatus
 postgres_get_old_coin_by_h_blind (void *cls,
-                                  const struct GNUNET_HashCode *h_blind_ev,
+                                  const struct
+                                  TALER_BlindedCoinHash *h_blind_ev,
                                   struct TALER_CoinSpendPublicKeyP 
*old_coin_pub)
 {
   struct PostgresClosure *pg = cls;
@@ -9239,7 +9665,7 @@ postgres_get_old_coin_by_h_blind (void *cls,
 static enum GNUNET_DB_QueryStatus
 postgres_insert_denomination_revocation (
   void *cls,
-  const struct GNUNET_HashCode *denom_pub_hash,
+  const struct TALER_DenominationHash *denom_pub_hash,
   const struct TALER_MasterSignatureP *master_sig)
 {
   struct PostgresClosure *pg = cls;
@@ -9268,7 +9694,7 @@ postgres_insert_denomination_revocation (
 static enum GNUNET_DB_QueryStatus
 postgres_get_denomination_revocation (
   void *cls,
-  const struct GNUNET_HashCode *denom_pub_hash,
+  const struct TALER_DenominationHash *denom_pub_hash,
   struct TALER_MasterSignatureP *master_sig,
   uint64_t *rowid)
 {
@@ -9337,7 +9763,7 @@ missing_wire_cb (void *cls,
     uint64_t rowid;
     struct TALER_CoinSpendPublicKeyP coin_pub;
     struct TALER_Amount amount;
-    json_t *wire;
+    char *payto_uri;
     struct GNUNET_TIME_Absolute deadline;
     uint8_t tiny;
     uint8_t done;
@@ -9348,8 +9774,8 @@ missing_wire_cb (void *cls,
                                             &coin_pub),
       TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
                                    &amount),
-      TALER_PQ_result_spec_json ("wire",
-                                 &wire),
+      GNUNET_PQ_result_spec_string ("payto_uri",
+                                    &payto_uri),
       TALER_PQ_result_spec_absolute_time ("wire_deadline",
                                           &deadline),
       GNUNET_PQ_result_spec_auto_from_type ("tiny",
@@ -9372,7 +9798,7 @@ missing_wire_cb (void *cls,
              rowid,
              &coin_pub,
              &amount,
-             wire,
+             payto_uri,
              deadline,
              tiny,
              done);
@@ -9957,7 +10383,7 @@ postgres_lookup_signkey_revocation (
 static enum GNUNET_DB_QueryStatus
 postgres_lookup_denomination_key (
   void *cls,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
 {
   struct PostgresClosure *pg = cls;
@@ -10008,7 +10434,7 @@ postgres_lookup_denomination_key (
 static enum GNUNET_DB_QueryStatus
 postgres_add_denomination_key (
   void *cls,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
   const struct TALER_MasterSignatureP *master_sig)
@@ -10016,7 +10442,7 @@ postgres_add_denomination_key (
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam iparams[] = {
     GNUNET_PQ_query_param_auto_from_type (h_denom_pub),
-    GNUNET_PQ_query_param_rsa_public_key (denom_pub->rsa_public_key),
+    TALER_PQ_query_param_denom_pub (denom_pub),
     GNUNET_PQ_query_param_auto_from_type (master_sig),
     TALER_PQ_query_param_absolute_time (&meta->start),
     TALER_PQ_query_param_absolute_time (&meta->expire_withdraw),
@@ -10129,7 +10555,7 @@ postgres_lookup_signing_key (
 static enum GNUNET_DB_QueryStatus
 postgres_insert_auditor_denom_sig (
   void *cls,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
   const struct TALER_AuditorSignatureP *auditor_sig)
 {
@@ -10159,7 +10585,7 @@ postgres_insert_auditor_denom_sig (
 static enum GNUNET_DB_QueryStatus
 postgres_select_auditor_denom_sig (
   void *cls,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
   struct TALER_AuditorSignatureP *auditor_sig)
 {
@@ -10507,6 +10933,10 @@ postgres_lookup_records_by_table (void *cls,
     statement = "select_above_serial_by_table_denomination_revocations";
     rh = &lrbt_cb_table_denomination_revocations;
     break;
+  case TALER_EXCHANGEDB_RT_WIRE_TARGETS:
+    statement = "select_above_serial_by_table_wire_targets";
+    rh = &lrbt_cb_table_wire_targets;
+    break;
   case TALER_EXCHANGEDB_RT_RESERVES:
     statement = "select_above_serial_by_table_reserves";
     rh = &lrbt_cb_table_reserves;
@@ -10640,6 +11070,9 @@ postgres_insert_records_by_table (void *cls,
   case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS:
     rh = &irbt_cb_table_denomination_revocations;
     break;
+  case TALER_EXCHANGEDB_RT_WIRE_TARGETS:
+    rh = &irbt_cb_table_wire_targets;
+    break;
   case TALER_EXCHANGEDB_RT_RESERVES:
     rh = &irbt_cb_table_reserves;
     break;
@@ -10964,7 +11397,7 @@ postgres_begin_revolving_shard (void *cls,
 {
   struct PostgresClosure *pg = cls;
 
-  GNUNET_assert (shard_limit <= 1U + (uint32_t) INT32_MAX);
+  GNUNET_assert (shard_limit <= 1U + (uint32_t) INT_MAX);
   GNUNET_assert (shard_limit > 0);
   GNUNET_assert (shard_size > 0);
   for (unsigned int retries = 0; retries<3; retries++)
@@ -11234,6 +11667,19 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     GNUNET_free (pg);
     return NULL;
   }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "exchange",
+                                             "BASE_URL",
+                                             &pg->exchange_url))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "exchange",
+                               "BASE_URL");
+    GNUNET_free (pg->sql_dir);
+    GNUNET_free (pg);
+    return NULL;
+  }
   if ( (GNUNET_OK !=
         GNUNET_CONFIGURATION_get_value_time (cfg,
                                              "exchangedb",
@@ -11249,6 +11695,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
                                "exchangedb",
                                "LEGAL/IDLE_RESERVE_EXPIRATION_TIME");
+    GNUNET_free (pg->exchange_url);
     GNUNET_free (pg->sql_dir);
     GNUNET_free (pg);
     return NULL;
@@ -11257,6 +11704,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
       TALER_config_get_currency (cfg,
                                  &pg->currency))
   {
+    GNUNET_free (pg->exchange_url);
     GNUNET_free (pg->sql_dir);
     GNUNET_free (pg);
     return NULL;
@@ -11265,6 +11713,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
       internal_setup (pg,
                       true))
   {
+    GNUNET_free (pg->exchange_url);
     GNUNET_free (pg->currency);
     GNUNET_free (pg->sql_dir);
     GNUNET_free (pg);
@@ -11310,8 +11759,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
   plugin->get_known_coin = &postgres_get_known_coin;
   plugin->get_coin_denomination = &postgres_get_coin_denomination;
   plugin->have_deposit = &postgres_have_deposit;
+  plugin->have_deposit2 = &postgres_have_deposit2;
   plugin->mark_deposit_tiny = &postgres_mark_deposit_tiny;
-  plugin->test_deposit_done = &postgres_test_deposit_done;
   plugin->mark_deposit_done = &postgres_mark_deposit_done;
   plugin->get_ready_deposit = &postgres_get_ready_deposit;
   plugin->iterate_matching_deposits = &postgres_iterate_matching_deposits;
@@ -11448,6 +11897,7 @@ libtaler_plugin_exchangedb_postgres_done (void *cls)
 
   if (NULL != pg->conn)
     GNUNET_PQ_disconnect (pg->conn);
+  GNUNET_free (pg->exchange_url);
   GNUNET_free (pg->sql_dir);
   GNUNET_free (pg->currency);
   GNUNET_free (pg);
diff --git a/src/exchangedb/test-exchange-db-postgres.conf 
b/src/exchangedb/test-exchange-db-postgres.conf
index f6db7694..e582025b 100644
--- a/src/exchangedb/test-exchange-db-postgres.conf
+++ b/src/exchangedb/test-exchange-db-postgres.conf
@@ -2,6 +2,8 @@
 #The DB plugin to use
 DB = postgres
 
+BASE_URL = http://localhost/
+
 [exchangedb-postgres]
 
 #The connection string the plugin has to use for connecting to the database
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index c68cba81..3c3f9fd0 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -194,8 +194,8 @@ struct DenomKeyPair
 static void
 destroy_denom_key_pair (struct DenomKeyPair *dkp)
 {
-  GNUNET_CRYPTO_rsa_public_key_free (dkp->pub.rsa_public_key);
-  GNUNET_CRYPTO_rsa_private_key_free (dkp->priv.rsa_private_key);
+  TALER_denom_pub_free (&dkp->pub);
+  TALER_denom_priv_free (&dkp->priv);
   GNUNET_free (dkp);
 }
 
@@ -225,11 +225,11 @@ create_denom_key_pair (unsigned int size,
   struct TALER_EXCHANGEDB_DenominationKeyInformationP issue2;
 
   dkp = GNUNET_new (struct DenomKeyPair);
-  dkp->priv.rsa_private_key = GNUNET_CRYPTO_rsa_private_key_create (size);
-  GNUNET_assert (NULL != dkp->priv.rsa_private_key);
-  dkp->pub.rsa_public_key
-    = GNUNET_CRYPTO_rsa_private_key_get_public (dkp->priv.rsa_private_key);
-
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_denom_priv_create (&dkp->priv,
+                                          &dkp->pub,
+                                          TALER_DENOMINATION_RSA,
+                                          size));
   /* Using memset() as fields like master key and signature
      are not properly initialized for this test. */
   memset (&dki,
@@ -256,11 +256,11 @@ create_denom_key_pair (unsigned int size,
   TALER_amount_hton (&dki.issue.properties.fee_deposit, fee_deposit);
   TALER_amount_hton (&dki.issue.properties.fee_refresh, fee_refresh);
   TALER_amount_hton (&dki.issue.properties.fee_refund, fee_refund);
-  GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
-                                     &dki.issue.properties.denom_hash);
+  TALER_denom_pub_hash (&dkp->pub,
+                        &dki.issue.properties.denom_hash);
 
-  dki.issue.properties.purpose.size = htonl (sizeof (struct
-                                                     
TALER_DenominationKeyValidityPS));
+  dki.issue.properties.purpose.size
+    = htonl (sizeof (struct TALER_DenominationKeyValidityPS));
   dki.issue.properties.purpose.purpose = htonl (
     TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY);
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
@@ -312,9 +312,9 @@ static struct TALER_Amount amount_with_fee;
 #define MELT_NOREVEAL_INDEX 1
 
 /**
- * How big do we make the coin envelopes?
+ * How big do we make the RSA keys?
  */
-#define COIN_ENC_MAX_SIZE 512
+#define RSA_KEY_SIZE 1024
 
 static struct TALER_EXCHANGEDB_RefreshRevealedCoin *revealed_coins;
 
@@ -387,10 +387,8 @@ check_refresh_reveal_cb (
                    GNUNET_memcmp (acoin->coin_ev,
                                   bcoin->coin_ev));
     GNUNET_assert (0 ==
-                   GNUNET_CRYPTO_rsa_public_key_cmp (
-                     acoin->denom_pub.rsa_public_key,
-                     bcoin->denom_pub.
-                     rsa_public_key));
+                   TALER_denom_pub_cmp (&acoin->denom_pub,
+                                        &bcoin->denom_pub));
   }
   GNUNET_assert (0 == GNUNET_memcmp (&tpub, tpr));
   GNUNET_assert (0 == memcmp (tprivs, tprivsr,
@@ -474,15 +472,12 @@ handle_link_data_cb (void *cls,
     found = GNUNET_NO;
     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
     {
-      GNUNET_assert (NULL != ldlp->ev_sig.rsa_signature);
       if ( (0 ==
-            GNUNET_CRYPTO_rsa_public_key_cmp (ldlp->denom_pub.rsa_public_key,
-                                              
new_dkp[cnt]->pub.rsa_public_key))
-           &&
+            TALER_denom_pub_cmp (&ldlp->denom_pub,
+                                 &new_dkp[cnt]->pub)) &&
            (0 ==
-            GNUNET_CRYPTO_rsa_signature_cmp (ldlp->ev_sig.rsa_signature,
-                                             revealed_coins[cnt].coin_sig.
-                                             rsa_signature)) )
+            TALER_blinded_denom_sig_cmp (&ldlp->ev_sig,
+                                         &revealed_coins[cnt].coin_sig)) )
       {
         found = GNUNET_YES;
         break;
@@ -498,14 +493,14 @@ handle_link_data_cb (void *cls,
  *
  * @return #GNUNET_OK if everything went well; #GNUNET_SYSERR if not
  */
-static int
+static enum GNUNET_GenericReturnValue
 test_melting (void)
 {
   struct TALER_EXCHANGEDB_Refresh refresh_session;
   struct TALER_EXCHANGEDB_Melt ret_refresh_session;
   struct DenomKeyPair *dkp;
   struct TALER_DenominationPublicKey *new_denom_pubs;
-  int ret;
+  enum GNUNET_GenericReturnValue ret;
   enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_TIME_Absolute now;
 
@@ -529,18 +524,35 @@ test_melting (void)
   GNUNET_assert (NULL != dkp);
   /* initialize refresh session melt data */
   {
-    struct GNUNET_HashCode hc;
+    struct TALER_CoinPubHash c_hash;
+    struct TALER_PlanchetDetail pd;
+    struct TALER_BlindedDenominationSignature bds;
+    union TALER_DenominationBlindingKeyP bks;
 
     RND_BLK (&refresh_session.coin.coin_pub);
-    GNUNET_CRYPTO_hash (&refresh_session.coin.coin_pub,
-                        sizeof (refresh_session.coin.coin_pub),
-                        &hc);
-    refresh_session.coin.denom_sig.rsa_signature =
-      GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key,
-                                  &hc);
-    GNUNET_assert (NULL != refresh_session.coin.denom_sig.rsa_signature);
-    GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
-                                       &refresh_session.coin.denom_pub_hash);
+    TALER_blinding_secret_create (&bks);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_blind (&dkp->pub,
+                                      &bks,
+                                      NULL, /* FIXME-Oec */
+                                      &refresh_session.coin.coin_pub,
+                                      &c_hash,
+                                      &pd.coin_ev,
+                                      &pd.coin_ev_size));
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sign_blinded (&bds,
+                                             &dkp->priv,
+                                             pd.coin_ev,
+                                             pd.coin_ev_size));
+    GNUNET_free (pd.coin_ev);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sig_unblind (&refresh_session.coin.denom_sig,
+                                            &bds,
+                                            &bks,
+                                            &dkp->pub));
+    TALER_blinded_denom_sig_free (&bds);
+    TALER_denom_pub_hash (&dkp->pub,
+                          &refresh_session.coin.denom_pub_hash);
     refresh_session.amount_with_fee = amount_with_fee;
   }
 
@@ -568,11 +580,10 @@ test_melting (void)
           TALER_amount_cmp (&fee_refresh,
                             &ret_refresh_session.melt_fee));
   FAILIF (0 !=
-          GNUNET_memcmp (&refresh_session.rc, 
&ret_refresh_session.session.rc));
+          GNUNET_memcmp (&refresh_session.rc,
+                         &ret_refresh_session.session.rc));
   FAILIF (0 != GNUNET_memcmp (&refresh_session.coin_sig,
                               &ret_refresh_session.session.coin_sig));
-  FAILIF (NULL !=
-          ret_refresh_session.session.coin.denom_sig.rsa_signature);
   FAILIF (0 != memcmp (&refresh_session.coin.coin_pub,
                        &ret_refresh_session.session.coin.coin_pub,
                        sizeof (refresh_session.coin.coin_pub)));
@@ -599,12 +610,11 @@ test_melting (void)
   for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
   {
     struct TALER_EXCHANGEDB_RefreshRevealedCoin *ccoin;
-    struct GNUNET_HashCode hc;
     struct GNUNET_TIME_Absolute now;
 
     now = GNUNET_TIME_absolute_get ();
     GNUNET_TIME_round_abs (&now);
-    new_dkp[cnt] = create_denom_key_pair (1024,
+    new_dkp[cnt] = create_denom_key_pair (RSA_KEY_SIZE,
                                           now,
                                           &value,
                                           &fee_withdraw,
@@ -616,16 +626,17 @@ test_melting (void)
     ccoin = &revealed_coins[cnt];
     ccoin->coin_ev_size = (size_t) GNUNET_CRYPTO_random_u64 (
       GNUNET_CRYPTO_QUALITY_WEAK,
-      COIN_ENC_MAX_SIZE);
+      (RSA_KEY_SIZE / 8) - 1);
     ccoin->coin_ev = GNUNET_malloc (ccoin->coin_ev_size);
     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                                 ccoin->coin_ev,
                                 ccoin->coin_ev_size);
-    RND_BLK (&hc);
     ccoin->denom_pub = new_dkp[cnt]->pub;
-    ccoin->coin_sig.rsa_signature
-      = GNUNET_CRYPTO_rsa_sign_fdh (new_dkp[cnt]->priv.rsa_private_key,
-                                    &hc);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sign_blinded (&ccoin->coin_sig,
+                                             &new_dkp[cnt]->priv,
+                                             ccoin->coin_ev,
+                                             ccoin->coin_ev_size));
   }
   RND_BLK (&tprivs);
   RND_BLK (&tpub);
@@ -647,8 +658,6 @@ test_melting (void)
                                       &refresh_session.rc,
                                       &check_refresh_reveal_cb,
                                       NULL));
-
-
   qs = plugin->get_link_data (plugin->cls,
                               &refresh_session.coin.coin_pub,
                               &handle_link_data_cb,
@@ -675,17 +684,14 @@ drop:
   {
     for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++)
     {
-      if (NULL != revealed_coins[cnt].coin_sig.rsa_signature)
-        GNUNET_CRYPTO_rsa_signature_free (
-          revealed_coins[cnt].coin_sig.rsa_signature);
+      TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig);
       GNUNET_free (revealed_coins[cnt].coin_ev);
     }
     GNUNET_free (revealed_coins);
     revealed_coins = NULL;
   }
   destroy_denom_key_pair (dkp);
-  GNUNET_CRYPTO_rsa_signature_free (
-    refresh_session.coin.denom_sig.rsa_signature);
+  TALER_denom_sig_free (&refresh_session.coin.denom_sig);
   GNUNET_free (new_denom_pubs);
   for (unsigned int cnt = 0;
        (NULL != new_dkp) && (cnt < MELT_NEW_COINS) && (NULL != new_dkp[cnt]);
@@ -703,10 +709,9 @@ static void
 cb_wt_never (void *cls,
              uint64_t serial_id,
              const struct TALER_MerchantPublicKeyP *merchant_pub,
-             const struct GNUNET_HashCode *h_wire,
-             const json_t *wire,
+             const char *account_payto_uri,
              struct GNUNET_TIME_Absolute exec_time,
-             const struct GNUNET_HashCode *h_contract_terms,
+             const struct TALER_PrivateContractHash *h_contract_terms,
              const struct TALER_DenominationPublicKey *denom_pub,
              const struct TALER_CoinSpendPublicKeyP *coin_pub,
              const struct TALER_Amount *coin_value,
@@ -717,8 +722,8 @@ cb_wt_never (void *cls,
 
 
 static struct TALER_MerchantPublicKeyP merchant_pub_wt;
-static struct GNUNET_HashCode h_wire_wt;
-static struct GNUNET_HashCode h_contract_terms_wt;
+static struct TALER_MerchantWireHash h_wire_wt;
+static struct TALER_PrivateContractHash h_contract_terms_wt;
 static struct TALER_CoinSpendPublicKeyP coin_pub_wt;
 static struct TALER_Amount coin_value_wt;
 static struct TALER_Amount coin_fee_wt;
@@ -734,10 +739,9 @@ static void
 cb_wt_check (void *cls,
              uint64_t rowid,
              const struct TALER_MerchantPublicKeyP *merchant_pub,
-             const struct GNUNET_HashCode *h_wire,
-             const json_t *wire,
+             const char *account_payto_uri,
              struct GNUNET_TIME_Absolute exec_time,
-             const struct GNUNET_HashCode *h_contract_terms,
+             const struct TALER_PrivateContractHash *h_contract_terms,
              const struct TALER_DenominationPublicKey *denom_pub,
              const struct TALER_CoinSpendPublicKeyP *coin_pub,
              const struct TALER_Amount *coin_value,
@@ -746,11 +750,8 @@ cb_wt_check (void *cls,
   GNUNET_assert (cls == &cb_wt_never);
   GNUNET_assert (0 == GNUNET_memcmp (merchant_pub,
                                      &merchant_pub_wt));
-  GNUNET_assert (0 == strcmp (json_string_value (json_object_get (wire,
-                                                                  
"payto_uri")),
+  GNUNET_assert (0 == strcmp (account_payto_uri,
                               
"payto://iban/DE67830654080004822650?receiver-name=Test"));
-  GNUNET_assert (0 == GNUNET_memcmp (h_wire,
-                                     &h_wire_wt));
   GNUNET_assert (exec_time.abs_value_us == wire_out_date.abs_value_us);
   GNUNET_assert (0 == GNUNET_memcmp (h_contract_terms,
                                      &h_contract_terms_wt));
@@ -768,6 +769,11 @@ cb_wt_check (void *cls,
  */
 static uint64_t deposit_rowid;
 
+/**
+ * Here #deposit_cb() will store the row ID of the account.
+ */
+static uint64_t wire_target_row;
+
 
 /**
  * Function called with details about deposits that
@@ -782,7 +788,8 @@ static uint64_t deposit_rowid;
  * @param amount_with_fee amount that was deposited including fee
  * @param deposit_fee amount the exchange gets to keep as transaction fees
  * @param h_contract_terms hash of the proposal data known to merchant and 
customer
- * @param wire wire details for the merchant
+ * @param wire_target unique ID of the receiver account
+ * @param payto_uri how to pay the merchant, URI in payto://-format;
  * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to 
continue to iterate
  */
 static enum GNUNET_DB_QueryStatus
@@ -792,16 +799,14 @@ deposit_cb (void *cls,
             const struct TALER_CoinSpendPublicKeyP *coin_pub,
             const struct TALER_Amount *amount_with_fee,
             const struct TALER_Amount *deposit_fee,
-            const struct GNUNET_HashCode *h_contract_terms,
-            const json_t *wire)
+            const struct TALER_PrivateContractHash *h_contract_terms,
+            uint64_t wire_target,
+            const char *payto_uri)
 {
   struct TALER_EXCHANGEDB_Deposit *deposit = cls;
-  struct GNUNET_HashCode h_wire;
 
   deposit_rowid = rowid;
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_JSON_merchant_wire_signature_hash (wire,
-                                                          &h_wire));
+  wire_target_row = wire_target;
   if ( (0 != GNUNET_memcmp (merchant_pub,
                             &deposit->merchant_pub)) ||
        (0 != TALER_amount_cmp (amount_with_fee,
@@ -813,8 +818,8 @@ deposit_cb (void *cls,
        (0 != memcmp (coin_pub,
                      &deposit->coin.coin_pub,
                      sizeof (struct TALER_CoinSpendPublicKeyP))) ||
-       (0 != GNUNET_memcmp (&h_wire,
-                            &deposit->h_wire)) )
+       (0 != strcmp (payto_uri,
+                     deposit->receiver_wire_account)) )
   {
     GNUNET_break (0);
     return GNUNET_DB_STATUS_HARD_ERROR;
@@ -844,7 +849,7 @@ matching_deposit_cb (void *cls,
                      const struct TALER_CoinSpendPublicKeyP *coin_pub,
                      const struct TALER_Amount *amount_with_fee,
                      const struct TALER_Amount *deposit_fee,
-                     const struct GNUNET_HashCode *h_contract_terms)
+                     const struct TALER_PrivateContractHash *h_contract_terms)
 {
   struct TALER_EXCHANGEDB_Deposit *deposit = cls;
 
@@ -855,9 +860,8 @@ matching_deposit_cb (void *cls,
                                &deposit->deposit_fee)) ||
        (0 != GNUNET_memcmp (h_contract_terms,
                             &deposit->h_contract_terms)) ||
-       (0 != memcmp (coin_pub,
-                     &deposit->coin.coin_pub,
-                     sizeof (struct TALER_CoinSpendPublicKeyP))) )
+       (0 != GNUNET_memcmp (coin_pub,
+                            &deposit->coin.coin_pub)) )
   {
     GNUNET_break (0);
     return GNUNET_DB_STATUS_HARD_ERROR;
@@ -873,36 +877,18 @@ matching_deposit_cb (void *cls,
  * @param cls closure
  * @param rowid unique serial ID for the deposit in our DB
  * @param exchange_timestamp when did the deposit happen
- * @param wallet_timestamp when did the wallet sign the contract
- * @param merchant_pub public key of the merchant
+ * @param deposit deposit details
  * @param denom_pub denomination of the @a coin_pub
- * @param coin_pub public key of the coin
- * @param coin_sig signature from the coin
- * @param amount_with_fee amount that was deposited including fee
- * @param h_contract_terms hash of the proposal data known to merchant and 
customer
- * @param refund_deadline by which the merchant advised that he might want
- *        to get a refund
- * @param wire_deadline by which the merchant advised that he would like the
- *        wire transfer to be executed
- * @param receiver_wire_account wire details for the merchant, NULL from 
iterate_matching_deposits()
  * @param done flag set if the deposit was already executed (or not)
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
-static int
+static enum GNUNET_GenericReturnValue
 audit_deposit_cb (void *cls,
                   uint64_t rowid,
                   struct GNUNET_TIME_Absolute exchange_timestamp,
-                  struct GNUNET_TIME_Absolute wallet_timestamp,
-                  const struct TALER_MerchantPublicKeyP *merchant_pub,
+                  const struct TALER_EXCHANGEDB_Deposit *deposit,
                   const struct TALER_DenominationPublicKey *denom_pub,
-                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                  const struct TALER_CoinSpendSignatureP *coin_sig,
-                  const struct TALER_Amount *amount_with_fee,
-                  const struct GNUNET_HashCode *h_contract_terms,
-                  struct GNUNET_TIME_Absolute refund_deadline,
-                  struct GNUNET_TIME_Absolute wire_deadline,
-                  const json_t *receiver_wire_account,
-                  int done)
+                  bool done)
 {
   auditor_row_cnt++;
   return GNUNET_OK;
@@ -932,7 +918,7 @@ audit_refund_cb (void *cls,
                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
                  const struct TALER_MerchantPublicKeyP *merchant_pub,
                  const struct TALER_MerchantSignatureP *merchant_sig,
-                 const struct GNUNET_HashCode *h_contract_terms,
+                 const struct TALER_PrivateContractHash *h_contract_terms,
                  uint64_t rtransaction_id,
                  const struct TALER_Amount *amount_with_fee)
 {
@@ -999,7 +985,7 @@ audit_reserve_in_cb (void *cls,
 static int
 audit_reserve_out_cb (void *cls,
                       uint64_t rowid,
-                      const struct GNUNET_HashCode *h_blind_ev,
+                      const struct TALER_BlindedCoinHash *h_blind_ev,
                       const struct TALER_DenominationPublicKey *denom_pub,
                       const struct TALER_ReservePublicKeyP *reserve_pub,
                       const struct TALER_ReserveSignatureP *reserve_sig,
@@ -1031,7 +1017,7 @@ test_gc (void)
   struct GNUNET_TIME_Absolute now;
   struct GNUNET_TIME_Absolute past;
   struct TALER_EXCHANGEDB_DenominationKeyInformationP issue2;
-  struct GNUNET_HashCode denom_hash;
+  struct TALER_DenominationHash denom_hash;
 
   now = GNUNET_TIME_absolute_get ();
   GNUNET_TIME_round_abs (&now);
@@ -1039,7 +1025,7 @@ test_gc (void)
                                         GNUNET_TIME_relative_multiply (
                                           GNUNET_TIME_UNIT_HOURS,
                                           4));
-  dkp = create_denom_key_pair (1024,
+  dkp = create_denom_key_pair (RSA_KEY_SIZE,
                                past,
                                &value,
                                &fee_withdraw,
@@ -1054,8 +1040,8 @@ test_gc (void)
     destroy_denom_key_pair (dkp);
     return GNUNET_SYSERR;
   }
-  GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
-                                     &denom_hash);
+  TALER_denom_pub_hash (&dkp->pub,
+                        &denom_hash);
 
   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
       plugin->get_denomination_info (plugin->cls,
@@ -1190,7 +1176,7 @@ audit_wire_cb (void *cls,
                uint64_t rowid,
                struct GNUNET_TIME_Absolute date,
                const struct TALER_WireTransferIdentifierRawP *wtid,
-               const json_t *wire,
+               const char *payto_uri,
                const struct TALER_Amount *amount)
 {
   auditor_row_cnt++;
@@ -1231,7 +1217,6 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit 
*deposit)
 
   /* setup values for wire transfer aggregation data */
   merchant_pub_wt = deposit->merchant_pub;
-  h_wire_wt = deposit->h_wire;
   h_contract_terms_wt = deposit->h_contract_terms;
   coin_pub_wt = deposit->coin.coin_pub;
 
@@ -1248,7 +1233,7 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit 
*deposit)
                                         NULL));
 
   {
-    struct GNUNET_HashCode h_contract_terms_wt2 = h_contract_terms_wt;
+    struct TALER_PrivateContractHash h_contract_terms_wt2 = 
h_contract_terms_wt;
     bool pending;
     struct TALER_WireTransferIdentifierRawP wtid2;
     struct TALER_Amount coin_contribution2;
@@ -1256,7 +1241,7 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit 
*deposit)
     struct GNUNET_TIME_Absolute execution_time2;
     struct TALER_EXCHANGEDB_KycStatus kyc;
 
-    h_contract_terms_wt2.bits[0]++;
+    h_contract_terms_wt2.hash.bits[0]++;
     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
             plugin->lookup_transfer_by_deposit (plugin->cls,
                                                 &h_contract_terms_wt2,
@@ -1279,29 +1264,23 @@ test_wire_out (const struct TALER_EXCHANGEDB_Deposit 
*deposit)
   /* Now let's fix the transient constraint violation by
      putting in the WTID into the wire_out table */
   {
-    json_t *wire_out_account;
-    struct TALER_WireSalt salt;
+    struct TALER_ReservePublicKeyP rpub;
+    struct TALER_EXCHANGEDB_KycStatus kyc;
 
-    memset (&salt,
+    memset (&rpub,
             44,
-            sizeof (salt));
-    wire_out_account = GNUNET_JSON_PACK (
-      GNUNET_JSON_pack_string ("payto_uri",
-                               "payto://x-taler-bank/localhost:8080/1"),
-      GNUNET_JSON_pack_data_auto ("salt",
-                                  &salt));
-    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-        plugin->store_wire_transfer_out (plugin->cls,
-                                         wire_out_date,
-                                         &wire_out_wtid,
-                                         wire_out_account,
-                                         "my-config-section",
-                                         &wire_out_amount))
-    {
-      json_decref (wire_out_account);
-      FAILIF (1);
-    }
-    json_decref (wire_out_account);
+            sizeof (rpub));
+    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+            plugin->inselect_wallet_kyc_status (plugin->cls,
+                                                &rpub,
+                                                &kyc));
+    FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+            plugin->store_wire_transfer_out (plugin->cls,
+                                             wire_out_date,
+                                             &wire_out_wtid,
+                                             kyc.payment_target_uuid,
+                                             "my-config-section",
+                                             &wire_out_amount));
   }
   /* And now the commit should still succeed! */
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
@@ -1377,9 +1356,9 @@ recoup_cb (void *cls,
            const struct TALER_CoinPublicInfo *coin,
            const struct TALER_DenominationPublicKey *denom_pub,
            const struct TALER_CoinSpendSignatureP *coin_sig,
-           const struct TALER_DenominationBlindingKeyP *coin_blind)
+           const union TALER_DenominationBlindingKeyP *coin_blind)
 {
-  const struct TALER_DenominationBlindingKeyP *cb = cls;
+  const union TALER_DenominationBlindingKeyP *cb = cls;
 
   FAILIF (NULL == cb);
   FAILIF (0 != GNUNET_memcmp (cb,
@@ -1398,7 +1377,7 @@ drop:
  * @param rowid deposit table row of the coin's deposit
  * @param coin_pub public key of the coin
  * @param amount value of the deposit, including fee
- * @param wire where should the funds be wired
+ * @param payto_uri where should the funds be wired
  * @param deadline what was the requested wire transfer deadline
  * @param tiny did the exchange defer this transfer because it is too small?
  * @param done did the exchange claim that it made a transfer?
@@ -1408,29 +1387,22 @@ wire_missing_cb (void *cls,
                  uint64_t rowid,
                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
                  const struct TALER_Amount *amount,
-                 const json_t *wire,
+                 const char *payto_uri,
                  struct GNUNET_TIME_Absolute deadline,
-                 /* bool? */ int tiny,
-                 /* bool? */ int done)
+                 bool tiny,
+                 bool done)
 {
   const struct TALER_EXCHANGEDB_Deposit *deposit = cls;
-  struct GNUNET_HashCode h_wire;
 
-  (void) done;
-  if (NULL != wire)
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_JSON_merchant_wire_signature_hash (wire,
-                                                            &h_wire));
-  else
-    memset (&h_wire,
-            0,
-            sizeof (h_wire));
-  if (GNUNET_NO != tiny)
+  (void) payto_uri;
+  (void) deadline;
+  (void) rowid;
+  if (tiny)
   {
     GNUNET_break (0);
     result = 66;
   }
-  if (GNUNET_NO != done)
+  if (done)
   {
     GNUNET_break (0);
     result = 66;
@@ -1447,12 +1419,6 @@ wire_missing_cb (void *cls,
     GNUNET_break (0);
     result = 66;
   }
-  if (0 != GNUNET_memcmp (&h_wire,
-                          &deposit->h_wire))
-  {
-    GNUNET_break (0);
-    result = 66;
-  }
 }
 
 
@@ -1464,7 +1430,7 @@ wire_missing_cb (void *cls,
  * @param amount_with_fee amount being refunded
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
-static int
+static enum GNUNET_GenericReturnValue
 check_refund_cb (void *cls,
                  const struct TALER_Amount *amount_with_fee)
 {
@@ -1491,11 +1457,10 @@ run (void *cls)
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   struct TALER_CoinSpendSignatureP coin_sig;
   struct GNUNET_TIME_Absolute deadline;
-  struct TALER_DenominationBlindingKeyP coin_blind;
+  union TALER_DenominationBlindingKeyP coin_blind;
   struct TALER_ReservePublicKeyP reserve_pub;
   struct TALER_ReservePublicKeyP reserve_pub2;
   struct DenomKeyPair *dkp;
-  struct GNUNET_HashCode dkp_pub_hash;
   struct TALER_MasterSignatureP master_sig;
   struct TALER_EXCHANGEDB_CollectableBlindcoin cbc;
   struct TALER_EXCHANGEDB_CollectableBlindcoin cbc2;
@@ -1508,7 +1473,6 @@ run (void *cls)
   struct TALER_EXCHANGEDB_Refund refund;
   struct TALER_EXCHANGEDB_TransactionList *tl;
   struct TALER_EXCHANGEDB_TransactionList *tlp;
-  json_t *wire;
   const char *sndr = "payto://x-taler-bank/localhost:8080/1";
   unsigned int matched;
   unsigned int cnt;
@@ -1516,18 +1480,17 @@ run (void *cls)
   enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_TIME_Absolute now;
   struct TALER_WireSalt salt;
+  union TALER_DenominationBlindingKeyP bks;
+  struct TALER_CoinPubHash c_hash;
 
   dkp = NULL;
   rh = NULL;
-  deposit.coin.denom_sig.rsa_signature = NULL;
+  memset (&deposit.coin.denom_sig,
+          0,
+          sizeof (deposit.coin.denom_sig));
   memset (&salt,
           45,
           sizeof (salt));
-  wire = GNUNET_JSON_PACK (
-    GNUNET_JSON_pack_string ("payto_uri",
-                             
"payto://iban/DE67830654080004822650?receiver-name=Test"),
-    GNUNET_JSON_pack_data_auto ("salt",
-                                &salt));
   ZR_BLK (&cbc);
   ZR_BLK (&cbc2);
   if (NULL ==
@@ -1626,7 +1589,7 @@ run (void *cls)
   result = 5;
   now = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&now);
-  dkp = create_denom_key_pair (1024,
+  dkp = create_denom_key_pair (RSA_KEY_SIZE,
                                now,
                                &value,
                                &fee_withdraw,
@@ -1634,14 +1597,33 @@ run (void *cls)
                                &fee_refresh,
                                &fee_refund);
   GNUNET_assert (NULL != dkp);
-  GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
-                                     &dkp_pub_hash);
-  RND_BLK (&cbc.h_coin_envelope);
+  TALER_denom_pub_hash (&dkp->pub,
+                        &cbc.denom_pub_hash);
   RND_BLK (&cbc.reserve_sig);
-  cbc.denom_pub_hash = dkp_pub_hash;
-  cbc.sig.rsa_signature
-    = GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key,
-                                  &cbc.h_coin_envelope);
+  {
+    struct TALER_PlanchetDetail pd;
+    struct TALER_CoinSpendPublicKeyP coin_pub;
+
+    RND_BLK (&coin_pub);
+    TALER_blinding_secret_create (&bks);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_blind (&dkp->pub,
+                                      &bks,
+                                      NULL, /* FIXME-Oec */
+                                      &coin_pub,
+                                      &c_hash,
+                                      &pd.coin_ev,
+                                      &pd.coin_ev_size));
+    TALER_coin_ev_hash (pd.coin_ev,
+                        pd.coin_ev_size,
+                        &cbc.h_coin_envelope);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sign_blinded (&cbc.sig,
+                                             &dkp->priv,
+                                             pd.coin_ev,
+                                             pd.coin_ev_size));
+    GNUNET_free (pd.coin_ev);
+  }
   cbc.reserve_pub = reserve_pub;
   cbc.amount_with_fee = value;
   GNUNET_assert (GNUNET_OK ==
@@ -1666,21 +1648,37 @@ run (void *cls)
           plugin->get_withdraw_info (plugin->cls,
                                      &cbc.h_coin_envelope,
                                      &cbc2));
-  FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_sig, &cbc.reserve_sig));
-  FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_pub, &cbc.reserve_pub));
+  FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_sig,
+                              &cbc.reserve_sig));
+  FAILIF (0 != GNUNET_memcmp (&cbc2.reserve_pub,
+                              &cbc.reserve_pub));
   result = 6;
-  FAILIF (GNUNET_OK !=
-          GNUNET_CRYPTO_rsa_verify (&cbc.h_coin_envelope,
-                                    cbc2.sig.rsa_signature,
-                                    dkp->pub.rsa_public_key));
 
+  {
+    struct TALER_DenominationSignature ds;
+
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sig_unblind (&ds,
+                                            &cbc2.sig,
+                                            &bks,
+                                            &dkp->pub));
+    FAILIF (GNUNET_OK !=
+            TALER_denom_pub_verify (&dkp->pub,
+                                    &ds,
+                                    &c_hash));
+  }
 
   RND_BLK (&coin_sig);
   RND_BLK (&coin_blind);
   RND_BLK (&deposit.coin.coin_pub);
-  GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
-                                     &deposit.coin.denom_pub_hash);
-  deposit.coin.denom_sig = cbc.sig;
+  TALER_denom_pub_hash (&dkp->pub,
+                        &deposit.coin.denom_pub_hash);
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_denom_sig_unblind (&deposit.coin.denom_sig,
+                                          &cbc.sig,
+                                          &bks,
+                                          &dkp->pub));
+
   deadline = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&deadline);
   FAILIF (TALER_EXCHANGEDB_CKS_ADDED !=
@@ -1761,9 +1759,9 @@ run (void *cls)
     {
     case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
       bt = rh_head->details.bank;
-      FAILIF (0 != memcmp (&bt->reserve_pub,
-                           &reserve_pub,
-                           sizeof (reserve_pub)));
+      FAILIF (0 !=
+              GNUNET_memcmp (&bt->reserve_pub,
+                             &reserve_pub));
       /* this is the amount we transferred twice*/
       FAILIF (1 != bt->amount.value);
       FAILIF (1000 != bt->amount.fraction);
@@ -1772,31 +1770,32 @@ run (void *cls)
       break;
     case TALER_EXCHANGEDB_RO_WITHDRAW_COIN:
       withdraw = rh_head->details.withdraw;
-      FAILIF (0 != memcmp (&withdraw->reserve_pub,
-                           &reserve_pub,
-                           sizeof (reserve_pub)));
-      FAILIF (0 != memcmp (&withdraw->h_coin_envelope,
-                           &cbc.h_coin_envelope,
-                           sizeof (cbc.h_coin_envelope)));
+      FAILIF (0 !=
+              GNUNET_memcmp (&withdraw->reserve_pub,
+                             &reserve_pub));
+      FAILIF (0 !=
+              GNUNET_memcmp (&withdraw->h_coin_envelope,
+                             &cbc.h_coin_envelope));
       break;
     case TALER_EXCHANGEDB_RO_RECOUP_COIN:
       {
         struct TALER_EXCHANGEDB_Recoup *recoup = rh_head->details.recoup;
 
-        FAILIF (0 != memcmp (&recoup->coin_sig,
-                             &coin_sig,
-                             sizeof (coin_sig)));
-        FAILIF (0 != memcmp (&recoup->coin_blind,
-                             &coin_blind,
-                             sizeof (coin_blind)));
-        FAILIF (0 != memcmp (&recoup->reserve_pub,
-                             &reserve_pub,
-                             sizeof (reserve_pub)));
-        FAILIF (0 != memcmp (&recoup->coin.coin_pub,
-                             &deposit.coin.coin_pub,
-                             sizeof (deposit.coin.coin_pub)));
-        FAILIF (0 != TALER_amount_cmp (&recoup->value,
-                                       &value));
+        FAILIF (0 !=
+                GNUNET_memcmp (&recoup->coin_sig,
+                               &coin_sig));
+        FAILIF (0 !=
+                GNUNET_memcmp (&recoup->coin_blind,
+                               &coin_blind));
+        FAILIF (0 !=
+                GNUNET_memcmp (&recoup->reserve_pub,
+                               &reserve_pub));
+        FAILIF (0 !=
+                GNUNET_memcmp (&recoup->coin.coin_pub,
+                               &deposit.coin.coin_pub));
+        FAILIF (0 !=
+                TALER_amount_cmp (&recoup->value,
+                                  &value));
       }
       break;
     case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK:
@@ -1804,9 +1803,9 @@ run (void *cls)
         struct TALER_EXCHANGEDB_ClosingTransfer *closing
           = rh_head->details.closing;
 
-        FAILIF (0 != memcmp (&closing->reserve_pub,
-                             &reserve_pub,
-                             sizeof (reserve_pub)));
+        FAILIF (0 !=
+                GNUNET_memcmp (&closing->reserve_pub,
+                               &reserve_pub));
         FAILIF (0 != TALER_amount_cmp (&closing->amount,
                                        &amount_with_fee));
         FAILIF (0 != TALER_amount_cmp (&closing->closing_fee,
@@ -1830,21 +1829,30 @@ run (void *cls)
                                                       NULL));
   FAILIF (3 != auditor_row_cnt);
 
+
   /* Tests for deposits */
+  TALER_denom_sig_free (&deposit.coin.denom_sig);
   memset (&deposit,
           0,
           sizeof (deposit));
   RND_BLK (&deposit.coin.coin_pub);
-  GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
-                                     &deposit.coin.denom_pub_hash);
-  deposit.coin.denom_sig = cbc.sig;
+  TALER_denom_pub_hash (&dkp->pub,
+                        &deposit.coin.denom_pub_hash);
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_denom_sig_unblind (&deposit.coin.denom_sig,
+                                          &cbc.sig,
+                                          &bks,
+                                          &dkp->pub));
   RND_BLK (&deposit.csig);
   RND_BLK (&deposit.merchant_pub);
   RND_BLK (&deposit.h_contract_terms);
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_JSON_merchant_wire_signature_hash (wire,
-                                                          &deposit.h_wire));
-  deposit.receiver_wire_account = wire;
+  RND_BLK (&deposit.wire_salt);
+  deposit.receiver_wire_account =
+    "payto://iban/DE67830654080004822650?receiver-name=Test";
+  TALER_merchant_wire_signature_hash (
+    "payto://iban/DE67830654080004822650?receiver-name=Test",
+    &deposit.wire_salt,
+    &h_wire_wt);
   deposit.amount_with_fee = value;
   deposit.deposit_fee = fee_deposit;
 
@@ -1868,7 +1876,6 @@ run (void *cls)
     FAILIF (1 !=
             plugin->have_deposit (plugin->cls,
                                   &deposit,
-                                  GNUNET_YES,
                                   &deposit_fee,
                                   &r));
     FAILIF (now.abs_value_us != r.abs_value_us);
@@ -1897,20 +1904,21 @@ run (void *cls)
                                                    NULL));
   FAILIF (1 != auditor_row_cnt);
   result = 9;
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->iterate_matching_deposits (plugin->cls,
-                                             &deposit.h_wire,
-                                             &deposit.merchant_pub,
-                                             &matching_deposit_cb,
-                                             &deposit,
-                                             2));
   sleep (2); /* give deposit time to be ready */
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_ready_deposit (plugin->cls,
                                      0,
                                      INT32_MAX,
+                                     true,
                                      &deposit_cb,
                                      &deposit));
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+          plugin->iterate_matching_deposits (plugin->cls,
+                                             wire_target_row,
+                                             &deposit.merchant_pub,
+                                             &matching_deposit_cb,
+                                             &deposit,
+                                             2));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->commit (plugin->cls));
   FAILIF (GNUNET_OK !=
@@ -1923,6 +1931,7 @@ run (void *cls)
           plugin->get_ready_deposit (plugin->cls,
                                      0,
                                      INT32_MAX,
+                                     true,
                                      &deposit_cb,
                                      &deposit));
   plugin->rollback (plugin->cls);
@@ -1930,28 +1939,17 @@ run (void *cls)
           plugin->get_ready_deposit (plugin->cls,
                                      0,
                                      INT32_MAX,
+                                     true,
                                      &deposit_cb,
                                      &deposit));
   FAILIF (GNUNET_OK !=
           plugin->start (plugin->cls,
                          "test-3"));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
-          plugin->test_deposit_done (plugin->cls,
-                                     &deposit.coin.coin_pub,
-                                     &deposit.merchant_pub,
-                                     &deposit.h_contract_terms,
-                                     &deposit.h_wire));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->mark_deposit_done (plugin->cls,
                                      deposit_rowid));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->commit (plugin->cls));
-  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
-          plugin->test_deposit_done (plugin->cls,
-                                     &deposit.coin.coin_pub,
-                                     &deposit.merchant_pub,
-                                     &deposit.h_contract_terms,
-                                     &deposit.h_wire));
 
   result = 10;
   deposit2 = deposit;
@@ -1966,7 +1964,6 @@ run (void *cls)
     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
             plugin->have_deposit (plugin->cls,
                                   &deposit2,
-                                  GNUNET_YES,
                                   &deposit_fee,
                                   &r));
     deposit2.merchant_pub = deposit.merchant_pub;
@@ -1974,7 +1971,6 @@ run (void *cls)
     FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
             plugin->have_deposit (plugin->cls,
                                   &deposit2,
-                                  GNUNET_YES,
                                   &deposit_fee,
                                   &r));
   }
@@ -2009,7 +2005,7 @@ run (void *cls)
   RND_BLK (&master_sig);
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_denomination_revocation (plugin->cls,
-                                                  &dkp_pub_hash,
+                                                  &cbc.denom_pub_hash,
                                                   &master_sig));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->commit (plugin->cls));
@@ -2019,7 +2015,7 @@ run (void *cls)
                          "test-4"));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->insert_denomination_revocation (plugin->cls,
-                                                  &dkp_pub_hash,
+                                                  &cbc.denom_pub_hash,
                                                   &master_sig));
   plugin->rollback (plugin->cls);
   plugin->preflight (plugin->cls);
@@ -2032,7 +2028,7 @@ run (void *cls)
 
     FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
             plugin->get_denomination_revocation (plugin->cls,
-                                                 &dkp_pub_hash,
+                                                 &cbc.denom_pub_hash,
                                                  &msig,
                                                  &rev_rowid));
     FAILIF (0 != GNUNET_memcmp (&msig,
@@ -2078,19 +2074,18 @@ run (void *cls)
         /* Note: we're not comparing the denomination keys, as there is
            still the question of whether we should even bother exporting
            them here. */
-        FAILIF (0 != memcmp (&have->csig,
-                             &deposit.csig,
-                             sizeof (struct TALER_CoinSpendSignatureP)));
-        FAILIF (0 != memcmp (&have->merchant_pub,
-                             &deposit.merchant_pub,
-                             sizeof (struct TALER_MerchantPublicKeyP)));
-        FAILIF (0 != memcmp (&have->h_contract_terms,
-                             &deposit.h_contract_terms,
-                             sizeof (struct GNUNET_HashCode)));
-        FAILIF (0 != memcmp (&have->h_wire,
-                             &deposit.h_wire,
-                             sizeof (struct GNUNET_HashCode)));
-        /* Note: not comparing 'wire', seems truly redundant and would be 
tricky */
+        FAILIF (0 !=
+                GNUNET_memcmp (&have->csig,
+                               &deposit.csig));
+        FAILIF (0 !=
+                GNUNET_memcmp (&have->merchant_pub,
+                               &deposit.merchant_pub));
+        FAILIF (0 !=
+                GNUNET_memcmp (&have->h_contract_terms,
+                               &deposit.h_contract_terms));
+        FAILIF (0 !=
+                GNUNET_memcmp (&have->wire_salt,
+                               &deposit.wire_salt));
         FAILIF (have->timestamp.abs_value_us != 
deposit.timestamp.abs_value_us);
         FAILIF (have->refund_deadline.abs_value_us !=
                 deposit.refund_deadline.abs_value_us);
@@ -2106,9 +2101,9 @@ run (void *cls)
 #if 0
     /* this coin pub was actually never melted... */
     case TALER_EXCHANGEDB_TT_MELT:
-      FAILIF (0 != memcmp (&melt,
-                           &tlp->details.melt,
-                           sizeof (struct TALER_EXCHANGEDB_Melt)));
+      FAILIF (0 !=
+              GNUNET_memcmp (&melt,
+                             &tlp->details.melt));
       matched |= 2;
       break;
 #endif
@@ -2184,12 +2179,10 @@ drop:
                 plugin->drop_tables (plugin->cls));
   if (NULL != dkp)
     destroy_denom_key_pair (dkp);
-  if (NULL != cbc.sig.rsa_signature)
-    GNUNET_CRYPTO_rsa_signature_free (cbc.sig.rsa_signature);
-  if (NULL != cbc2.sig.rsa_signature)
-    GNUNET_CRYPTO_rsa_signature_free (cbc2.sig.rsa_signature);
+  TALER_denom_sig_free (&deposit.coin.denom_sig);
+  TALER_blinded_denom_sig_free (&cbc.sig);
+  TALER_blinded_denom_sig_free (&cbc2.sig);
   dkp = NULL;
-  json_decref (wire);
   TALER_EXCHANGEDB_plugin_unload (plugin);
   plugin = NULL;
 }
diff --git a/src/include/taler_amount_lib.h b/src/include/taler_amount_lib.h
index c1f42e47..c6d2f474 100644
--- a/src/include/taler_amount_lib.h
+++ b/src/include/taler_amount_lib.h
@@ -21,6 +21,9 @@
 #ifndef TALER_AMOUNT_LIB_H
 #define TALER_AMOUNT_LIB_H
 
+#include <stdint.h>
+#include "gnunet/gnunet_common.h"
+
 #ifdef __cplusplus
 extern "C"
 {
diff --git a/src/include/taler_auditor_service.h 
b/src/include/taler_auditor_service.h
index d84ecd5e..bc990a14 100644
--- a/src/include/taler_auditor_service.h
+++ b/src/include/taler_auditor_service.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2020 Taler Systems SA
+  Copyright (C) 2014-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -233,8 +233,10 @@ typedef void
  *
  * @param auditor the auditor handle; the auditor must be ready to operate
  * @param h_wire hash of merchant wire details
+ * @param h_extensions hash over the extensions, if any
  * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the auditor)
  * @param exchange_timestamp timestamp when the contract was finalized, must 
not be too far in the future
+ * @param wire_deadline date until which the exchange should wire the funds
  * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the auditor (can be zero if refunds are not allowed); must not 
be after the @a wire_deadline
  * @param amount_without_fee the amount confirmed to be wired by the exchange 
to the merchant
  * @param coin_pub coin’s public key
@@ -254,9 +256,11 @@ typedef void
 struct TALER_AUDITOR_DepositConfirmationHandle *
 TALER_AUDITOR_deposit_confirmation (
   struct TALER_AUDITOR_Handle *auditor,
-  const struct GNUNET_HashCode *h_wire,
-  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_ExtensionContractHash *h_extensions,
+  const struct TALER_PrivateContractHash *h_contract_terms,
   struct GNUNET_TIME_Absolute timestamp,
+  struct GNUNET_TIME_Absolute wire_deadline,
   struct GNUNET_TIME_Absolute refund_deadline,
   const struct TALER_Amount *amount_without_fee,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
diff --git a/src/include/taler_auditordb_plugin.h 
b/src/include/taler_auditordb_plugin.h
index 7733009b..7756db2b 100644
--- a/src/include/taler_auditordb_plugin.h
+++ b/src/include/taler_auditordb_plugin.h
@@ -59,10 +59,10 @@ typedef void
  *         #GNUNET_NO to stop processing further rows
  *         #GNUNET_SYSERR or other values on error.
  */
-typedef int
+typedef enum GNUNET_GenericReturnValue
 (*TALER_AUDITORDB_HistoricDenominationRevenueDataCallback)(
   void *cls,
-  const struct GNUNET_HashCode *denom_pub_hash,
+  const struct TALER_DenominationHash *denom_pub_hash,
   struct GNUNET_TIME_Absolute revenue_timestamp,
   const struct TALER_Amount *revenue_balance,
   const struct TALER_Amount *loss_balance);
@@ -81,7 +81,7 @@ typedef int
  *         #GNUNET_NO to stop processing further rows
  *         #GNUNET_SYSERR or other values on error.
  */
-typedef int
+typedef enum GNUNET_GenericReturnValue
 (*TALER_AUDITORDB_HistoricReserveRevenueDataCallback)(
   void *cls,
   struct GNUNET_TIME_Absolute start_time,
@@ -171,7 +171,6 @@ struct TALER_AUDITORDB_ProgressPointDepositConfirmation
    */
   uint64_t last_deposit_confirmation_serial_id;
 
-
 };
 
 
@@ -275,12 +274,17 @@ struct TALER_AUDITORDB_DepositConfirmation
   /**
    * Hash over the contract for which this deposit is made.
    */
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
+
+  /**
+   * Hash over the extensions for the deposit.
+   */
+  struct TALER_ExtensionContractHash h_extensions;
 
   /**
    * Hash over the wiring information of the merchant.
    */
-  struct GNUNET_HashCode h_wire;
+  struct TALER_MerchantWireHash h_wire;
 
   /**
    * Time when this deposit confirmation was generated by the exchange.
@@ -296,6 +300,11 @@ struct TALER_AUDITORDB_DepositConfirmation
    */
   struct GNUNET_TIME_Absolute refund_deadline;
 
+  /**
+   * How much time does the @e exchange have to wire the funds?
+   */
+  struct GNUNET_TIME_Absolute wire_deadline;
+
   /**
    * Amount to be deposited, excluding fee.  Calculated from the
    * amount with fee and the fee from the deposit request.
@@ -349,7 +358,7 @@ struct TALER_AUDITORDB_DepositConfirmation
  * @param dc the deposit confirmation itself
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating
  */
-typedef int
+typedef enum GNUNET_GenericReturnValue
 (*TALER_AUDITORDB_DepositConfirmationCallback)(
   void *cls,
   uint64_t serial_id,
@@ -453,8 +462,8 @@ struct TALER_AUDITORDB_Plugin
    * @return #GNUNET_OK on success,
    *         #GNUNET_SYSERR on DB errors
    */
-  int
-  (*gc) (void *cls);
+  enum GNUNET_GenericReturnValue
+  (*gc)(void *cls);
 
 
   /**
@@ -1040,7 +1049,8 @@ struct TALER_AUDITORDB_Plugin
    */
   enum GNUNET_DB_QueryStatus
   (*insert_denomination_balance)(void *cls,
-                                 const struct GNUNET_HashCode *denom_pub_hash,
+                                 const struct
+                                 TALER_DenominationHash *denom_pub_hash,
                                  const struct TALER_Amount *denom_balance,
                                  const struct TALER_Amount *denom_loss,
                                  const struct TALER_Amount *denom_risk,
@@ -1063,7 +1073,8 @@ struct TALER_AUDITORDB_Plugin
    */
   enum GNUNET_DB_QueryStatus
   (*update_denomination_balance)(void *cls,
-                                 const struct GNUNET_HashCode *denom_pub_hash,
+                                 const struct
+                                 TALER_DenominationHash *denom_pub_hash,
                                  const struct TALER_Amount *denom_balance,
                                  const struct TALER_Amount *denom_loss,
                                  const struct TALER_Amount *denom_risk,
@@ -1085,7 +1096,8 @@ struct TALER_AUDITORDB_Plugin
    */
   enum GNUNET_DB_QueryStatus
   (*get_denomination_balance)(void *cls,
-                              const struct GNUNET_HashCode *denom_pub_hash,
+                              const struct
+                              TALER_DenominationHash *denom_pub_hash,
                               struct TALER_Amount *denom_balance,
                               struct TALER_Amount *denom_loss,
                               struct TALER_Amount *denom_risk,
@@ -1102,7 +1114,8 @@ struct TALER_AUDITORDB_Plugin
    */
   enum GNUNET_DB_QueryStatus
   (*del_denomination_balance)(void *cls,
-                              const struct GNUNET_HashCode *denom_pub_hash);
+                              const struct
+                              TALER_DenominationHash *denom_pub_hash);
 
 
   /**
@@ -1206,7 +1219,7 @@ struct TALER_AUDITORDB_Plugin
   (*insert_historic_denom_revenue)(
     void *cls,
     const struct TALER_MasterPublicKeyP *master_pub,
-    const struct GNUNET_HashCode *denom_pub_hash,
+    const struct TALER_DenominationHash *denom_pub_hash,
     struct GNUNET_TIME_Absolute revenue_timestamp,
     const struct TALER_Amount *revenue_balance,
     const struct TALER_Amount *recoup_loss_balance);
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index 0284fc55..0a40282e 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2020 Taler Systems SA
+  Copyright (C) 2014-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -23,7 +23,6 @@
 #define TALER_CRYPTO_LIB_H
 
 #include <gnunet/gnunet_util_lib.h>
-#include "taler_util.h"
 #include "taler_error_codes.h"
 #include <gcrypt.h>
 
@@ -281,6 +280,37 @@ struct TALER_MasterSignatureP
   struct GNUNET_CRYPTO_EddsaSignature eddsa_signature;
 };
 
+/*
+ * @brief Type of a list of age groups, represented as bit mask.
+ *
+ * The bits set in the mask mark the edges at the beginning of a next age
+ * group.  F.e. for the age groups
+ *     0-7, 8-9, 10-11, 12-14, 14-15, 16-17, 18-21, 21-*
+ * the following bits are set:
+ *
+ *   31     24        16        8         0
+ *   |      |         |         |         |
+ *   oooooooo  oo1oo1o1  o1o1o1o1  ooooooo1
+ *
+ * A value of 0 means that the exchange does not support the extension for
+ * age-restriction.
+ */
+struct TALER_AgeMask
+{
+  uint32_t mask;
+};
+
+/**
+ * @brief Age restriction commitment of a coin.
+ */
+struct TALER_AgeHash
+{
+  /**
+   * The commitment is a SHA-256 hash code.
+   */
+  struct GNUNET_ShortHashCode shash;
+};
+
 
 /**
  * @brief Type of public keys for Taler coins.  The same key material is used
@@ -324,12 +354,12 @@ struct TALER_CoinSpendSignatureP
 /**
  * @brief Type of blinding keys for Taler.
  */
-struct TALER_DenominationBlindingKeyP
+union TALER_DenominationBlindingKeyP
 {
   /**
    * Taler uses RSA for blind signatures.
    */
-  struct GNUNET_CRYPTO_RsaBlindingKeySecret bks;
+  struct GNUNET_CRYPTO_RsaBlindingKeySecret rsa_bks;
 };
 
 
@@ -366,25 +396,181 @@ struct TALER_ClaimTokenP
 struct TALER_WireSalt
 {
   /**
-   * Actual salt value.
-   * FIXME: #7032: change to 16 byte value!
+   * Actual 128-bit salt value.
+   */
+  uint32_t salt[4];
+};
+
+
+/**
+ * Hash used to represent a denomination public key
+ * and associated age restrictions (if any).
+ */
+struct TALER_DenominationHash
+{
+  /**
+   * Actual hash value.
+   */
+  struct GNUNET_HashCode hash;
+};
+
+
+/**
+ * Hash used to represent the private part
+ * of a contract between merchant and consumer.
+ */
+struct TALER_PrivateContractHash
+{
+  /**
+   * Actual hash value.
+   */
+  struct GNUNET_HashCode hash;
+};
+
+
+/**
+ * Hash used to represent the "public" extensions to
+ * a contract that is shared with the exchange.
+ */
+struct TALER_ExtensionContractHash
+{
+  /**
+   * Actual hash value.
    */
-  struct GNUNET_HashCode data;
+  struct GNUNET_HashCode hash;
+};
+
+
+/**
+ * Hash used to represent the salted hash of a
+ * merchant's bank account.
+ */
+struct TALER_MerchantWireHash
+{
+  /**
+   * Actual hash value.
+   */
+  struct GNUNET_HashCode hash;
+};
+
+
+/**
+ * Hash used to represent the unsalted hash of a
+ * payto:// URI representing a bank account.
+ */
+struct TALER_PaytoHash
+{
+  /**
+   * Actual hash value.
+   */
+  struct GNUNET_HashCode hash;
+};
+
+
+/**
+ * Hash used to represent a commitment to a blinded
+ * coin, i.e. the hash of the envelope.
+ */
+struct TALER_BlindedCoinHash
+{
+  /**
+   * Actual hash value.
+   */
+  struct GNUNET_HashCode hash;
+};
+
+
+/**
+ * Hash used to represent the hash of the public
+ * key of a coin (without blinding).
+ */
+struct TALER_CoinPubHash
+{
+  /**
+   * Actual hash value.
+   */
+  struct GNUNET_HashCode hash;
 };
 
 
 GNUNET_NETWORK_STRUCT_END
 
 
+/**
+ * Types of public keys used for denominations in Taler.
+ */
+enum TALER_DenominationCipher
+{
+
+  /**
+   * Invalid type of signature.
+   */
+  TALER_DENOMINATION_INVALID = 0,
+
+  /**
+   * RSA blind signature.
+   */
+  TALER_DENOMINATION_RSA = 1,
+
+  /**
+   * Clause-Schnorr blind signature.
+   */
+  // TALER_DENOMINATION_CS = 2
+};
+
+
 /**
  * @brief Type of (unblinded) coin signatures for Taler.
  */
 struct TALER_DenominationSignature
 {
+
   /**
-   * Taler uses RSA for blinding.
+   * Type of the signature.
    */
-  struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
+  enum TALER_DenominationCipher cipher;
+
+  /**
+   * Details, depending on @e cipher.
+   */
+  union
+  {
+
+    /**
+     * If we use #TALER_DENOMINATION_RSA in @a cipher.
+     */
+    struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
+
+  } details;
+
+};
+
+
+/**
+ * @brief Type for *blinded* denomination signatures for Taler.
+ * Must be unblinded before it becomes valid.
+ */
+struct TALER_BlindedDenominationSignature
+{
+
+  /**
+   * Type of the signature.
+   */
+  enum TALER_DenominationCipher cipher;
+
+  /**
+   * Details, depending on @e cipher.
+   */
+  union
+  {
+
+    /**
+     * If we use #TALER_DENOMINATION_RSA in @a cipher.
+     */
+    struct GNUNET_CRYPTO_RsaSignature *blinded_rsa_signature;
+
+  } details;
+
 };
 
 
@@ -393,10 +579,29 @@ struct TALER_DenominationSignature
  */
 struct TALER_DenominationPublicKey
 {
+
+  /**
+   * Type of the public key.
+   */
+  enum TALER_DenominationCipher cipher;
+
   /**
-   * Taler uses RSA for signing coins.
+   * Age restriction mask used for the key.
    */
-  struct GNUNET_CRYPTO_RsaPublicKey *rsa_public_key;
+  struct TALER_AgeMask age_mask;
+
+  /**
+   * Details, depending on @e cipher.
+   */
+  union
+  {
+
+    /**
+     * If we use #TALER_DENOMINATION_RSA in @a cipher.
+     */
+    struct GNUNET_CRYPTO_RsaPublicKey *rsa_public_key;
+
+  } details;
 };
 
 
@@ -405,10 +610,24 @@ struct TALER_DenominationPublicKey
  */
 struct TALER_DenominationPrivateKey
 {
+
+  /**
+   * Type of the public key.
+   */
+  enum TALER_DenominationCipher cipher;
+
   /**
-   * Taler uses RSA for signing coins.
+   * Details, depending on @e cipher.
    */
-  struct GNUNET_CRYPTO_RsaPrivateKey *rsa_private_key;
+  union
+  {
+
+    /**
+     * If we use #TALER_DENOMINATION_RSA in @a cipher.
+     */
+    struct GNUNET_CRYPTO_RsaPrivateKey *rsa_private_key;
+
+  } details;
 };
 
 
@@ -428,7 +647,12 @@ struct TALER_CoinPublicInfo
    * Hash of the public key representing the denomination of the coin that is
    * being deposited.
    */
-  struct GNUNET_HashCode denom_pub_hash;
+  struct TALER_DenominationHash denom_pub_hash;
+
+  /**
+   * Hash of the age commitment.
+   */
+  struct TALER_AgeHash age_commitment_hash;
 
   /**
    * (Unblinded) signature over @e coin_pub with @e denom_pub,
@@ -447,7 +671,7 @@ struct TALER_TrackTransferDetails
   /**
    * Hash of the proposal data.
    */
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
 
   /**
    * Which coin was deposited?
@@ -467,6 +691,240 @@ struct TALER_TrackTransferDetails
 };
 
 
+/**
+ * Free internals of @a denom_pub, but not @a denom_pub itself.
+ *
+ * @param[in] denom_pub key to free
+ */
+void
+TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub);
+
+
+/**
+ * Create a blinding secret @a bs for @a cipher.
+ *
+ * @param[out] bs blinding secret to initialize
+ */
+void
+TALER_blinding_secret_create (union TALER_DenominationBlindingKeyP *bs);
+
+
+/**
+ * Initialize denomination public-private key pair.
+ *
+ * For #TALER_DENOMINATION_RSA, an additional "unsigned int"
+ * argument with the number of bits for 'n' (e.g. 2048) must
+ * be passed.
+ *
+ * @param[out] denom_priv where to write the private key
+ * @param[out] deonm_pub where to write the public key
+ * @param cipher which type of cipher to use
+ * @param ... cipher-specific parameters
+ * @return #GNUNET_OK on success, #GNUNET_NO if parameters were invalid
+ */
+enum GNUNET_GenericReturnValue
+TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv,
+                         struct TALER_DenominationPublicKey *denom_pub,
+                         enum TALER_DenominationCipher cipher,
+                         ...);
+
+
+/**
+ * Free internals of @a denom_priv, but not @a denom_priv itself.
+ *
+ * @param[in] denom_priv key to free
+ */
+void
+TALER_denom_priv_free (struct TALER_DenominationPrivateKey *denom_priv);
+
+
+/**
+ * Free internals of @a denom_sig, but not @a denom_sig itself.
+ *
+ * @param[in] denom_sig signature to free
+ */
+void
+TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig);
+
+
+/**
+ * Blind coin for blind signing with @a dk using blinding secret @a coin_bks.
+ *
+ * @param dk denomination public key to blind for
+ * @param coin_bks blinding secret to use
+ * @param age_commitment_hash hash of the age commitment to be used for the 
coin. NULL if no commitment is made.
+ * @param coin_pub public key of the coin to blind
+ * @param[out] c_hash resulting hashed coin
+ * @param[out] coin_ev blinded coin to submit
+ * @param[out] coin_ev_size number of bytes in @a coin_ev
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+TALER_denom_blind (const struct TALER_DenominationPublicKey *dk,
+                   const union TALER_DenominationBlindingKeyP *coin_bks,
+                   const struct TALER_AgeHash *age_commitment_hash,
+                   const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                   struct TALER_CoinPubHash *c_hash,
+                   void **coin_ev,
+                   size_t *coin_ev_size);
+
+
+/**
+ * Create blinded signature.
+ *
+ * @param[out] denom_sig where to write the signature
+ * @param denom_priv private key to use for signing
+ * @param blinded_msg message to sign
+ * @param blinded_msg_size number of bytes in @a blinded_msg
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig,
+                          const struct TALER_DenominationPrivateKey 
*denom_priv,
+                          void *blinded_msg,
+                          size_t blinded_msg_size);
+
+
+/**
+ * Unblind blinded signature.
+ *
+ * @param[out] denom_sig where to write the unblinded signature
+ * @param bdenom_sig the blinded signature
+ * @param bks blinding secret to use
+ * @param denom_pub public key used for signing
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+TALER_denom_sig_unblind (
+  struct TALER_DenominationSignature *denom_sig,
+  const struct TALER_BlindedDenominationSignature *bdenom_sig,
+  const union TALER_DenominationBlindingKeyP *bks,
+  const struct TALER_DenominationPublicKey *denom_pub);
+
+
+/**
+ * Free internals of @a denom_sig, but not @a denom_sig itself.
+ *
+ * @param[in] denom_sig signature to free
+ */
+void
+TALER_blinded_denom_sig_free (
+  struct TALER_BlindedDenominationSignature *denom_sig);
+
+
+/**
+ * Compute the hash of the given @a denom_pub.
+ *
+ * @param denom_pub public key to hash
+ * @param[out] denom_hash resulting hash value
+ */
+void
+TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub,
+                      struct TALER_DenominationHash *denom_hash);
+
+
+/**
+ * Make a (deep) copy of the given @a denom_src to
+ * @a denom_dst.
+ *
+ * @param[out] denom_dst target to copy to
+ * @param denom_str public key to copy
+ */
+void
+TALER_denom_pub_deep_copy (struct TALER_DenominationPublicKey *denom_dst,
+                           const struct TALER_DenominationPublicKey 
*denom_src);
+
+
+/**
+ * Make a (deep) copy of the given @a denom_src to
+ * @a denom_dst.
+ *
+ * @param[out] denom_dst target to copy to
+ * @param denom_str public key to copy
+ */
+void
+TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst,
+                           const struct TALER_DenominationSignature 
*denom_src);
+
+
+/**
+ * Make a (deep) copy of the given @a denom_src to
+ * @a denom_dst.
+ *
+ * @param[out] denom_dst target to copy to
+ * @param denom_str public key to copy
+ */
+void
+TALER_blinded_denom_sig_deep_copy (
+  struct TALER_BlindedDenominationSignature *denom_dst,
+  const struct TALER_BlindedDenominationSignature *denom_src);
+
+
+/**
+ * Compare two denomination public keys.
+ *
+ * @param denom1 first key
+ * @param denom2 second key
+ * @return 0 if the keys are equal, otherwise -1 or 1
+ */
+int
+TALER_denom_pub_cmp (const struct TALER_DenominationPublicKey *denom1,
+                     const struct TALER_DenominationPublicKey *denom2);
+
+
+/**
+ * Compare two denomination signatures.
+ *
+ * @param sig1 first signature
+ * @param sig2 second signature
+ * @return 0 if the keys are equal, otherwise -1 or 1
+ */
+int
+TALER_denom_sig_cmp (const struct TALER_DenominationSignature *sig1,
+                     const struct TALER_DenominationSignature *sig2);
+
+
+/**
+ * Compare two blinded denomination signatures.
+ *
+ * @param sig1 first signature
+ * @param sig2 second signature
+ * @return 0 if the keys are equal, otherwise -1 or 1
+ */
+int
+TALER_blinded_denom_sig_cmp (
+  const struct TALER_BlindedDenominationSignature *sig1,
+  const struct TALER_BlindedDenominationSignature *sig2);
+
+
+/**
+ * Obtain denomination public key from a denomination private key.
+ *
+ * @param denom_priv private key to convert
+ * @param age_mask age mask to be applied
+ * @param[out] denom_pub where to return the public key
+ */
+void
+TALER_denom_priv_to_pub (const struct TALER_DenominationPrivateKey *denom_priv,
+                         const struct TALER_AgeMask age_mask,
+                         struct TALER_DenominationPublicKey *denom_pub);
+
+
+/**
+ * Verify signature made with a denomination public key
+ * over a coin.
+ *
+ * @param denom_pub public denomination key
+ * @param denom_sig signature made with the private key
+ * @param c_hash hash over the coin
+ * @return #GNUNET_OK if the signature is valid
+ */
+enum GNUNET_GenericReturnValue
+TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub,
+                        const struct TALER_DenominationSignature *denom_sig,
+                        const struct TALER_CoinPubHash *c_hash);
+
+
 /**
  * Check if a coin is valid; that is, whether the denomination key exists,
  * is not expired, and the signature is correct.
@@ -482,6 +940,43 @@ TALER_test_coin_valid (const struct TALER_CoinPublicInfo 
*coin_public_info,
                        const struct TALER_DenominationPublicKey *denom_pub);
 
 
+/**
+ * Compute the hash of a blinded coin.
+ *
+ * @param coin_ev blinded coin
+ * @param coin_ev_size number of bytes in @a coin_ev
+ * @param[out] bch where to write the hash
+ */
+void
+TALER_coin_ev_hash (const void *coin_ev,
+                    size_t coin_ev_size,
+                    struct TALER_BlindedCoinHash *bch);
+
+
+/**
+ * Compute the hash of a coin.
+ *
+ * @param coin_pub public key of the coin
+ * @param age_commitment_hash hash of the age commitment vector. NULL, if no 
age commitment was set
+ * @param[out] coin_h where to write the hash
+ */
+void
+TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                     const struct TALER_AgeHash *age_commitment_hash,
+                     struct TALER_CoinPubHash *coin_h);
+
+
+/**
+ * Compute the hash of a payto URI.
+ *
+ * @param payto URI to hash
+ * @param[out] h_payto where to write the hash
+ */
+void
+TALER_payto_hash (const char *payto,
+                  struct TALER_PaytoHash *h_payto);
+
+
 GNUNET_NETWORK_STRUCT_BEGIN
 
 /**
@@ -501,7 +996,7 @@ struct TALER_PlanchetSecretsP
   /**
    * The blinding key.
    */
-  struct TALER_DenominationBlindingKeyP blinding_key;
+  union TALER_DenominationBlindingKeyP blinding_key;
 
 };
 
@@ -520,7 +1015,7 @@ struct TALER_PlanchetDetail
   /**
    * Hash of the denomination public key.
    */
-  struct GNUNET_HashCode denom_pub_hash;
+  struct TALER_DenominationHash denom_pub_hash;
 
   /**
    * Blinded coin (see GNUNET_CRYPTO_rsa_blind()).  Note: is malloc()'ed!
@@ -552,6 +1047,9 @@ struct TALER_FreshCoin
    */
   struct TALER_CoinSpendPrivateKeyP coin_priv;
 
+  /**
+   * FIXME-Oec: Age-verification vector, as pointer: Dyn alloc!
+   */
 };
 
 
@@ -680,7 +1178,7 @@ TALER_planchet_setup_random (struct TALER_PlanchetSecretsP 
*ps);
 enum GNUNET_GenericReturnValue
 TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
                         const struct TALER_PlanchetSecretsP *ps,
-                        struct GNUNET_HashCode *c_hash,
+                        struct TALER_CoinPubHash *c_hash,
                         struct TALER_PlanchetDetail *pd);
 
 
@@ -696,11 +1194,12 @@ TALER_planchet_prepare (const struct 
TALER_DenominationPublicKey *dk,
  * @return #GNUNET_OK on success
  */
 enum GNUNET_GenericReturnValue
-TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk,
-                        const struct GNUNET_CRYPTO_RsaSignature *blind_sig,
-                        const struct TALER_PlanchetSecretsP *ps,
-                        const struct GNUNET_HashCode *c_hash,
-                        struct TALER_FreshCoin *coin);
+TALER_planchet_to_coin (
+  const struct TALER_DenominationPublicKey *dk,
+  const struct TALER_BlindedDenominationSignature *blind_sig,
+  const struct TALER_PlanchetSecretsP *ps,
+  const struct TALER_CoinPubHash *c_hash,
+  struct TALER_FreshCoin *coin);
 
 
 /* ****************** Refresh crypto primitives ************* */
@@ -845,7 +1344,7 @@ typedef void
   const char *section_name,
   struct GNUNET_TIME_Absolute start_time,
   struct GNUNET_TIME_Relative validity_duration,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_SecurityModulePublicKeyP *sm_pub,
   const struct TALER_SecurityModuleSignatureP *sm_sig);
@@ -897,10 +1396,10 @@ TALER_CRYPTO_helper_denom_poll (struct 
TALER_CRYPTO_DenominationHelper *dh);
  * @return signature, the value inside the structure will be NULL on failure,
  *         see @a ec for details about the failure
  */
-struct TALER_DenominationSignature
+struct TALER_BlindedDenominationSignature
 TALER_CRYPTO_helper_denom_sign (
   struct TALER_CRYPTO_DenominationHelper *dh,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const void *msg,
   size_t msg_size,
   enum TALER_ErrorCode *ec);
@@ -924,7 +1423,7 @@ TALER_CRYPTO_helper_denom_sign (
 void
 TALER_CRYPTO_helper_denom_revoke (
   struct TALER_CRYPTO_DenominationHelper *dh,
-  const struct GNUNET_HashCode *h_denom_pub);
+  const struct TALER_DenominationHash *h_denom_pub);
 
 
 /**
@@ -1077,8 +1576,104 @@ TALER_CRYPTO_helper_esign_disconnect (
   struct TALER_CRYPTO_ExchangeSignHelper *esh);
 
 
+/* ********************* exchange signing ************************** */
+
+
+/**
+ * Verify a deposit confirmation.
+ *
+ * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the exchange)
+ * @param h_wire hash of the merchant’s account details
+ * @param h_extensions hash over the extensions, can be NULL
+ * @param exchange_timestamp timestamp when the contract was finalized, must 
not be too far off
+ * @param wire_deadline date until which the exchange should wire the funds
+ * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the exchange (can be zero if refunds are not allowed); must 
not be after the @a wire_deadline
+ * @param amount_without_fee the amount to be deposited after fees
+ * @param coin_pub public key of the deposited coin
+ * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
+ * @param exchange_pub exchange's online signing public key
+ * @param exchange_sig the signature made with purpose 
#TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT
+ * @return #GNUNET_OK if the signature is valid
+ */
+enum GNUNET_GenericReturnValue
+TALER_exchange_deposit_confirm_verify (
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_ExtensionContractHash *h_extensions,
+  struct GNUNET_TIME_Absolute exchange_timestamp,
+  struct GNUNET_TIME_Absolute wire_deadline,
+  struct GNUNET_TIME_Absolute refund_deadline,
+  const struct TALER_Amount *amount_without_fee,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_ExchangePublicKeyP *exchange_pub,
+  const struct TALER_ExchangeSignatureP *exchange_sig);
+
+
 /* ********************* wallet signing ************************** */
 
+
+/**
+ * Sign a deposit permission.  Function for wallets.
+ *
+ * @param amount the amount to be deposited
+ * @param deposit_fee the deposit fee we expect to pay
+ * @param h_wire hash of the merchant’s account details
+ * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the exchange)
+ * @param h_extensions hash over the extensions
+ * @param h_denom_pub hash of the coin denomination's public key
+ * @param coin_priv coin’s private key
+ * @param wallet_timestamp timestamp when the contract was finalized, must not 
be too far in the future
+ * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
+ * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the exchange (can be zero if refunds are not allowed); must 
not be after the @a wire_deadline
+ * @param[out] coin_sig set to the signature made with purpose 
#TALER_SIGNATURE_WALLET_COIN_DEPOSIT
+ */
+void
+TALER_wallet_deposit_sign (
+  const struct TALER_Amount *amount,
+  const struct TALER_Amount *deposit_fee,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const struct TALER_ExtensionContractHash *h_extensions,
+  const struct TALER_DenominationHash *h_denom_pub,
+  struct GNUNET_TIME_Absolute wallet_timestamp,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  struct GNUNET_TIME_Absolute refund_deadline,
+  const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+  struct TALER_CoinSpendSignatureP *coin_sig);
+
+
+/**
+ * Verify a deposit permission.
+ *
+ * @param amount the amount to be deposited
+ * @param deposit_fee the deposit fee we expect to pay
+ * @param h_wire hash of the merchant’s account details
+ * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the exchange)
+ * @param h_extensions hash over the extensions
+ * @param h_denom_pub hash of the coin denomination's public key
+ * @param wallet_timestamp timestamp when the contract was finalized, must not 
be too far in the future
+ * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
+ * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the exchange (can be zero if refunds are not allowed); must 
not be after the @a wire_deadline
+ * @param coin_pub coin’s public key
+ * @param coin_sig the signature made with purpose 
#TALER_SIGNATURE_WALLET_COIN_DEPOSIT
+ * @return #GNUNET_OK if the signature is valid
+ */
+enum GNUNET_GenericReturnValue
+TALER_wallet_deposit_verify (
+  const struct TALER_Amount *amount,
+  const struct TALER_Amount *deposit_fee,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const struct TALER_ExtensionContractHash *h_extensions,
+  const struct TALER_DenominationHash *h_denom_pub,
+  struct GNUNET_TIME_Absolute wallet_timestamp,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  struct GNUNET_TIME_Absolute refund_deadline,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_CoinSpendSignatureP *coin_sig);
+
+
 /**
  * Sign link data.
  *
@@ -1090,7 +1685,7 @@ TALER_CRYPTO_helper_esign_disconnect (
  * @param[out] coin_sig resulting signature
  */
 void
-TALER_wallet_link_sign (const struct GNUNET_HashCode *h_denom_pub,
+TALER_wallet_link_sign (const struct TALER_DenominationHash *h_denom_pub,
                         const struct TALER_TransferPublicKeyP *transfer_pub,
                         const void *coin_ev,
                         size_t coin_ev_size,
@@ -1111,7 +1706,7 @@ TALER_wallet_link_sign (const struct GNUNET_HashCode 
*h_denom_pub,
  */
 enum GNUNET_GenericReturnValue
 TALER_wallet_link_verify (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_TransferPublicKeyP *transfer_pub,
   const void *coin_ev,
   size_t coin_ev_size,
@@ -1200,7 +1795,7 @@ TALER_exchange_offline_auditor_del_verify (
  */
 void
 TALER_exchange_offline_denomination_revoke_sign (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterPrivateKeyP *master_priv,
   struct TALER_MasterSignatureP *master_sig);
 
@@ -1215,7 +1810,7 @@ TALER_exchange_offline_denomination_revoke_sign (
  */
 enum GNUNET_GenericReturnValue
 TALER_exchange_offline_denomination_revoke_verify (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterPublicKeyP *master_pub,
   const struct TALER_MasterSignatureP *master_sig);
 
@@ -1308,7 +1903,7 @@ TALER_exchange_offline_signkey_validity_verify (
  */
 void
 TALER_exchange_offline_denom_validity_sign (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   struct GNUNET_TIME_Absolute stamp_start,
   struct GNUNET_TIME_Absolute stamp_expire_withdraw,
   struct GNUNET_TIME_Absolute stamp_expire_deposit,
@@ -1341,7 +1936,7 @@ TALER_exchange_offline_denom_validity_sign (
  */
 enum GNUNET_GenericReturnValue
 TALER_exchange_offline_denom_validity_verify (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   struct GNUNET_TIME_Absolute stamp_start,
   struct GNUNET_TIME_Absolute stamp_expire_withdraw,
   struct GNUNET_TIME_Absolute stamp_expire_deposit,
@@ -1393,9 +1988,9 @@ TALER_exchange_secmod_eddsa_verify (
 
 
 /**
- * Create security module RSA signature.
+ * Create security module denomination signature.
  *
- * @param h_denom_pub hash of the public key to validate
+ * @param h_denom_pub hash of the public key to sign
  * @param section_name name of the section in the configuration
  * @param start_sign starting point of validity for signing
  * @param duration how long will the key be in use
@@ -1403,8 +1998,8 @@ TALER_exchange_secmod_eddsa_verify (
  * @param[out] secm_sig where to write the signature
  */
 void
-TALER_exchange_secmod_rsa_sign (
-  const struct GNUNET_HashCode *h_denom_pub,
+TALER_exchange_secmod_denom_sign (
+  const struct TALER_DenominationHash *h_denom_pub,
   const char *section_name,
   struct GNUNET_TIME_Absolute start_sign,
   struct GNUNET_TIME_Relative duration,
@@ -1413,7 +2008,7 @@ TALER_exchange_secmod_rsa_sign (
 
 
 /**
- * Verify security module RSA signature.
+ * Verify security module denomination signature.
  *
  * @param h_denom_pub hash of the public key to validate
  * @param section_name name of the section in the configuration
@@ -1424,8 +2019,8 @@ TALER_exchange_secmod_rsa_sign (
  * @return #GNUNET_OK if the signature is valid
  */
 enum GNUNET_GenericReturnValue
-TALER_exchange_secmod_rsa_verify (
-  const struct GNUNET_HashCode *h_denom_pub,
+TALER_exchange_secmod_denom_verify (
+  const struct TALER_DenominationHash *h_denom_pub,
   const char *section_name,
   struct GNUNET_TIME_Absolute start_sign,
   struct GNUNET_TIME_Relative duration,
@@ -1454,7 +2049,7 @@ TALER_exchange_secmod_rsa_verify (
 void
 TALER_auditor_denom_validity_sign (
   const char *auditor_url,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterPublicKeyP *master_pub,
   struct GNUNET_TIME_Absolute stamp_start,
   struct GNUNET_TIME_Absolute stamp_expire_withdraw,
@@ -1491,7 +2086,7 @@ TALER_auditor_denom_validity_sign (
 enum GNUNET_GenericReturnValue
 TALER_auditor_denom_validity_verify (
   const char *auditor_url,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterPublicKeyP *master_pub,
   struct GNUNET_TIME_Absolute stamp_start,
   struct GNUNET_TIME_Absolute stamp_expire_withdraw,
@@ -1620,18 +2215,6 @@ TALER_exchange_offline_wire_del_verify (
   const struct TALER_MasterSignatureP *master_sig);
 
 
-/**
- * Compute the hash of the given wire details.   The resulting
- * hash is what is signed by the master key.
- *
- * @param payto_uri bank account
- * @param[out] hc set to the hash
- */
-void
-TALER_exchange_wire_signature_hash (const char *payto_uri,
-                                    struct GNUNET_HashCode *hc);
-
-
 /**
  * Check the signature in @a master_sig.
  *
@@ -1673,7 +2256,7 @@ TALER_exchange_wire_signature_make (
 void
 TALER_merchant_wire_signature_hash (const char *payto_uri,
                                     const struct TALER_WireSalt *salt,
-                                    struct GNUNET_HashCode *hc);
+                                    struct TALER_MerchantWireHash *hc);
 
 
 /**
@@ -1709,37 +2292,4 @@ TALER_merchant_wire_signature_make (
   struct TALER_MerchantSignatureP *merch_sig);
 
 
-/**
- * Blinds the given message with the given blinding key
- *
- * @param hash hash of the message to sign
- * @param bks the blinding key
- * @param pkey the public key of the signer
- * @param[out] buf set to a buffer with the blinded message to be signed
- * @param[out] buf_size number of bytes stored in @a buf
- * @return #GNUNET_YES if successful, #GNUNET_NO if RSA key is malicious
- */
-enum GNUNET_GenericReturnValue
-TALER_rsa_blind (const struct GNUNET_HashCode *hash,
-                 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
-                 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
-                 void **buf,
-                 size_t *buf_size);
-
-
-/**
- * Unblind a blind-signed signature.  The signature should have been generated
- * with GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
- * GNUNET_CRYPTO_rsa_blind().
- *
- * @param sig the signature made on the blinded signature purpose
- * @param bks the blinding key secret used to blind the signature purpose
- * @param pkey the public key of the signer
- * @return unblinded signature on success, NULL if RSA key is bad or malicious.
- */
-struct GNUNET_CRYPTO_RsaSignature *
-TALER_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig,
-                   const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
-                   struct GNUNET_CRYPTO_RsaPublicKey *pkey);
-
 #endif
diff --git a/src/include/taler_exchange_service.h 
b/src/include/taler_exchange_service.h
index 0b624391..09c50b17 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -97,7 +97,7 @@ struct TALER_EXCHANGE_DenomPublicKey
   /**
    * The hash of the public key.
    */
-  struct GNUNET_HashCode h_key;
+  struct TALER_DenominationHash h_key;
 
   /**
    * Exchange's master signature over this denomination record.
@@ -558,7 +558,7 @@ TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle 
*exchange);
  * @param pub claimed current online signing key for the exchange
  * @return #GNUNET_OK if @a pub is (according to /keys) a current signing key
  */
-int
+enum GNUNET_GenericReturnValue
 TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys,
                                  const struct TALER_ExchangePublicKeyP *pub);
 
@@ -619,7 +619,7 @@ TALER_EXCHANGE_destroy_denomination_key (
 const struct TALER_EXCHANGE_DenomPublicKey *
 TALER_EXCHANGE_get_denomination_key_by_hash (
   const struct TALER_EXCHANGE_Keys *keys,
-  const struct GNUNET_HashCode *hc);
+  const struct TALER_DenominationHash *hc);
 
 
 /**
@@ -772,6 +772,7 @@ TALER_EXCHANGE_wire_cancel (struct 
TALER_EXCHANGE_WireHandle *wh);
  * @param deposit_fee the deposit fee we expect to pay
  * @param h_wire hash of the merchant’s account details
  * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the exchange)
+ * @param h_extensions hash over the extensions
  * @param h_denom_pub hash of the coin denomination's public key
  * @param coin_priv coin’s private key
  * @param wallet_timestamp timestamp when the contract was finalized, must not 
be too far in the future
@@ -783,9 +784,10 @@ void
 TALER_EXCHANGE_deposit_permission_sign (
   const struct TALER_Amount *amount,
   const struct TALER_Amount *deposit_fee,
-  const struct GNUNET_HashCode *h_wire,
-  const struct GNUNET_HashCode *h_contract_terms,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const struct TALER_ExtensionContractHash *h_extensions,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   struct GNUNET_TIME_Absolute wallet_timestamp,
   const struct TALER_MerchantPublicKeyP *merchant_pub,
@@ -887,8 +889,10 @@ typedef void
  * @param amount the amount to be deposited
  * @param wire_deadline execution date, until which the merchant would like 
the exchange to settle the balance (advisory, the exchange cannot be
  *        forced to settle in the past or upon very short notice, but of 
course a well-behaved exchange will limit aggregation based on the advice 
received)
- * @param wire_details the merchant’s account details, in a format supported 
by the exchange
+ * @param merchant_payto_uri the merchant’s account details, in the 
payto://-format supported by the exchange
+ * @param wire_salt salt used to hash the @a merchant_payto_uri
  * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the exchange)
+ * @param extension_details extension-specific details about the deposit 
relevant to the exchange
  * @param coin_pub coin’s public key
  * @param denom_pub denomination key with which the coin is signed
  * @param denom_sig exchange’s unblinded signature of the coin
@@ -903,21 +907,24 @@ typedef void
  *         signatures fail to verify).  In this case, the callback is not 
called.
  */
 struct TALER_EXCHANGE_DepositHandle *
-TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange,
-                        const struct TALER_Amount *amount,
-                        struct GNUNET_TIME_Absolute wire_deadline,
-                        json_t *wire_details,
-                        const struct GNUNET_HashCode *h_contract_terms,
-                        const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                        const struct TALER_DenominationSignature *denom_sig,
-                        const struct TALER_DenominationPublicKey *denom_pub,
-                        struct GNUNET_TIME_Absolute timestamp,
-                        const struct TALER_MerchantPublicKeyP *merchant_pub,
-                        struct GNUNET_TIME_Absolute refund_deadline,
-                        const struct TALER_CoinSpendSignatureP *coin_sig,
-                        TALER_EXCHANGE_DepositResultCallback cb,
-                        void *cb_cls,
-                        enum TALER_ErrorCode *ec);
+TALER_EXCHANGE_deposit (
+  struct TALER_EXCHANGE_Handle *exchange,
+  const struct TALER_Amount *amount,
+  struct GNUNET_TIME_Absolute wire_deadline,
+  const char *merchant_payto_uri,
+  const struct TALER_WireSalt *wire_salt,
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const json_t *extension_details,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_DenominationSignature *denom_sig,
+  const struct TALER_DenominationPublicKey *denom_pub,
+  struct GNUNET_TIME_Absolute timestamp,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  struct GNUNET_TIME_Absolute refund_deadline,
+  const struct TALER_CoinSpendSignatureP *coin_sig,
+  TALER_EXCHANGE_DepositResultCallback cb,
+  void *cb_cls,
+  enum TALER_ErrorCode *ec);
 
 
 /**
@@ -996,7 +1003,7 @@ typedef void
 struct TALER_EXCHANGE_RefundHandle *
 TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange,
                        const struct TALER_Amount *amount,
-                       const struct GNUNET_HashCode *h_contract_terms,
+                       const struct TALER_PrivateContractHash 
*h_contract_terms,
                        const struct TALER_CoinSpendPublicKeyP *coin_pub,
                        uint64_t rtransaction_id,
                        const struct TALER_MerchantPrivateKeyP *merchant_priv,
@@ -1380,7 +1387,7 @@ typedef void
 (*TALER_EXCHANGE_Withdraw2Callback) (
   void *cls,
   const struct TALER_EXCHANGE_HttpResponse *hr,
-  const struct GNUNET_CRYPTO_RsaSignature *blind_sig);
+  const struct TALER_BlindedDenominationSignature *blind_sig);
 
 
 /**
@@ -1464,22 +1471,20 @@ TALER_EXCHANGE_withdraw2_cancel (struct 
TALER_EXCHANGE_Withdraw2Handle *wh);
  *                   validity of the keys
  * @param fresh_pks_len length of the @a pks array
  * @param fresh_pks array of @a pks_len denominations of fresh coins to create
- * @param[out] res_size set to the size of the return value, or 0 on error
  * @return NULL
  *         if the inputs are invalid (i.e. denomination key not with this 
exchange).
- *         Otherwise, pointer to a buffer of @a res_size to store persistently
+ *         Otherwise, JSON data structure to store persistently
  *         before proceeding to #TALER_EXCHANGE_melt().
  *         Non-null results should be freed using GNUNET_free().
  */
-char *
+json_t *
 TALER_EXCHANGE_refresh_prepare (
   const struct TALER_CoinSpendPrivateKeyP *melt_priv,
   const struct TALER_Amount *melt_amount,
   const struct TALER_DenominationSignature *melt_sig,
   const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
   unsigned int fresh_pks_len,
-  const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks,
-  size_t *res_size);
+  const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks);
 
 
 /* ********************* /coins/$COIN_PUB/melt ***************************** */
@@ -1521,8 +1526,6 @@ typedef void
  * prior to calling this function.
  *
  * @param exchange the exchange handle; the exchange must be ready to operate
- * @param refresh_data_length size of the @a refresh_data (returned
- *        in the `res_size` argument from #TALER_EXCHANGE_refresh_prepare())
  * @param refresh_data the refresh data as returned from
           #TALER_EXCHANGE_refresh_prepare())
  * @param melt_cb the callback to call with the result
@@ -1532,8 +1535,7 @@ typedef void
  */
 struct TALER_EXCHANGE_MeltHandle *
 TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
-                     size_t refresh_data_length,
-                     const char *refresh_data,
+                     const json_t *refresh_data,
                      TALER_EXCHANGE_MeltCallback melt_cb,
                      void *melt_cb_cls);
 
@@ -1590,8 +1592,6 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
  * prior to calling this function.
  *
  * @param exchange the exchange handle; the exchange must be ready to operate
- * @param refresh_data_length size of the @a refresh_data (returned
- *        in the `res_size` argument from #TALER_EXCHANGE_refresh_prepare())
  * @param refresh_data the refresh data as returned from
           #TALER_EXCHANGE_refresh_prepare())
  * @param noreveal_index response from the exchange to the
@@ -1605,8 +1605,7 @@ struct TALER_EXCHANGE_RefreshesRevealHandle;
 struct TALER_EXCHANGE_RefreshesRevealHandle *
 TALER_EXCHANGE_refreshes_reveal (
   struct TALER_EXCHANGE_Handle *exchange,
-  size_t refresh_data_length,
-  const char *refresh_data,
+  const json_t *refresh_data,
   uint32_t noreveal_index,
   TALER_EXCHANGE_RefreshesRevealCallback reveal_cb,
   void *reveal_cb_cls);
@@ -1710,9 +1709,9 @@ struct TALER_EXCHANGE_TransferData
   struct TALER_ExchangeSignatureP exchange_sig;
 
   /**
-   * hash of the wire transfer address the transfer went to
+   * hash of the payto:// URI the transfer went to
    */
-  struct GNUNET_HashCode h_wire;
+  struct TALER_PaytoHash h_payto;
 
   /**
    * time when the exchange claims to have performed the wire transfer
@@ -1912,8 +1911,8 @@ struct TALER_EXCHANGE_DepositGetHandle *
 TALER_EXCHANGE_deposits_get (
   struct TALER_EXCHANGE_Handle *exchange,
   const struct TALER_MerchantPrivateKeyP *merchant_priv,
-  const struct GNUNET_HashCode *h_wire,
-  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_PrivateContractHash *h_contract_terms,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   TALER_EXCHANGE_DepositGetCallback cb,
   void *cb_cls);
@@ -1948,7 +1947,7 @@ TALER_EXCHANGE_verify_coin_history (
   const char *currency,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   json_t *history,
-  struct GNUNET_HashCode *h_denom_pub,
+  struct TALER_DenominationHash *h_denom_pub,
   struct TALER_Amount *total);
 
 
@@ -2146,7 +2145,7 @@ typedef void
 struct TALER_EXCHANGE_KycCheckHandle *
 TALER_EXCHANGE_kyc_check (struct TALER_EXCHANGE_Handle *eh,
                           uint64_t payment_target,
-                          const struct GNUNET_HashCode *h_payto,
+                          const struct TALER_PaytoHash *h_payto,
                           struct GNUNET_TIME_Relative timeout,
                           TALER_EXCHANGE_KycStatusCallback cb,
                           void *cb_cls);
@@ -2161,6 +2160,83 @@ void
 TALER_EXCHANGE_kyc_check_cancel (struct TALER_EXCHANGE_KycCheckHandle *kyc);
 
 
+/**
+ * KYC proof response details.
+ */
+struct TALER_EXCHANGE_KycProofResponse
+{
+  /**
+   * HTTP status code returned by the exchange.
+   */
+  unsigned int http_status;
+
+  union
+  {
+
+    /**
+     * KYC is OK, affirmation returned by the exchange.
+     */
+    struct
+    {
+
+      /**
+       * Where to redirect the client next.
+       */
+      const char *redirect_url;
+
+    } found;
+
+  } details;
+
+};
+
+/**
+ * Function called with the result of a KYC check.
+ *
+ * @param cls closure
+ * @param ks the account's KYC status details
+ */
+typedef void
+(*TALER_EXCHANGE_KycProofCallback)(
+  void *cls,
+  const struct TALER_EXCHANGE_KycProofResponse *kpr);
+
+
+/**
+ * Handle for a /kyc-proof operation.
+ */
+struct TALER_EXCHANGE_KycProofHandle;
+
+
+/**
+ * Run interaction with exchange to provide proof of KYC status.
+ *
+ * @param eh exchange handle to use
+ * @param payment_target number identifying the target
+ * @param code OAuth 2.0 code argument
+ * @param state OAuth 2.0 state argument
+ * @param cb function to call with the result
+ * @param cb_cls closure for @a cb
+ * @return NULL on error
+ */
+struct TALER_EXCHANGE_KycProofHandle *
+TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *eh,
+                          uint64_t payment_target,
+                          const char *code,
+                          const char *state,
+                          TALER_EXCHANGE_KycProofCallback cb,
+                          void *cb_cls);
+
+
+/**
+ * Cancel KYC proof operation.
+ *
+ * @param kph handle for operation to cancel
+ */
+void
+TALER_EXCHANGE_kyc_proof_cancel (struct TALER_EXCHANGE_KycProofHandle *kph);
+
+
 /**
  * Handle for a ``/kyc-wallet`` operation.
  */
@@ -2452,7 +2528,7 @@ struct TALER_EXCHANGE_DenominationKeySignature
   /**
    * The hash of the denomination's public key
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Signature over this denomination key by the exchange's master signature.
@@ -2570,7 +2646,7 @@ struct 
TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle *
 TALER_EXCHANGE_management_revoke_denomination_key (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterSignatureP *master_sig,
   TALER_EXCHANGE_ManagementRevokeDenominationKeyCallback cb,
   void *cb_cls);
@@ -2942,7 +3018,7 @@ struct TALER_EXCHANGE_AuditorAddDenominationHandle *
 TALER_EXCHANGE_add_auditor_denomination (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
   const struct TALER_AuditorSignatureP *auditor_sig,
   TALER_EXCHANGE_AuditorAddDenominationCallback cb,
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 5a3313ca..7b3c3baf 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -74,7 +74,7 @@ struct TALER_EXCHANGEDB_DenominationKeyInformationP
 
 
 /**
- * Signature of events signalling a reseve got funding.
+ * Signature of events signalling a reserve got funding.
  */
 struct TALER_ReserveEventP
 {
@@ -90,6 +90,23 @@ struct TALER_ReserveEventP
 };
 
 
+/**
+ * Signature of events signalling a KYC process was completed.
+ */
+struct TALER_KycCompletedEventP
+{
+  /**
+   * Of type #TALER_DBEVENT_EXCHANGE_KYC_COMPLETED.
+   */
+  struct GNUNET_DB_EventHeaderP header;
+
+  /**
+   * Public key of the reserve the event is about.
+   */
+  struct TALER_PaytoHash h_payto;
+};
+
+
 GNUNET_NETWORK_STRUCT_END
 
 /**
@@ -127,6 +144,7 @@ enum TALER_EXCHANGEDB_ReplicatedTable
 {
   TALER_EXCHANGEDB_RT_DENOMINATIONS,
   TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS,
+  TALER_EXCHANGEDB_RT_WIRE_TARGETS,
   TALER_EXCHANGEDB_RT_RESERVES,
   TALER_EXCHANGEDB_RT_RESERVES_IN,
   TALER_EXCHANGEDB_RT_RESERVES_CLOSE,
@@ -175,6 +193,8 @@ struct TALER_EXCHANGEDB_TableData
      */
     struct
     {
+      uint32_t denom_type;
+      uint32_t age_restrictions;
       struct TALER_DenominationPublicKey denom_pub;
       struct TALER_MasterSignatureP master_sig;
       struct GNUNET_TIME_Absolute valid_from;
@@ -194,10 +214,16 @@ struct TALER_EXCHANGEDB_TableData
       uint64_t denominations_serial;
     } denomination_revocations;
 
+    struct
+    {
+      char *payto_uri;
+      bool kyc_ok;
+      char *external_id;
+    } wire_targets;
+
     struct
     {
       struct TALER_ReservePublicKeyP reserve_pub;
-      char *account_details;
       /**
        * Note: not useful for auditor, because not UPDATEd!
        */
@@ -210,7 +236,7 @@ struct TALER_EXCHANGEDB_TableData
     {
       uint64_t wire_reference;
       struct TALER_Amount credit;
-      char *sender_account_details;
+      uint64_t sender_account;
       char *exchange_account_section;
       struct GNUNET_TIME_Absolute execution_date;
       uint64_t reserve_uuid;
@@ -218,23 +244,23 @@ struct TALER_EXCHANGEDB_TableData
 
     struct
     {
+      uint64_t reserve_uuid;
       struct GNUNET_TIME_Absolute execution_date;
       struct TALER_WireTransferIdentifierRawP wtid;
-      char *receiver_account;
+      uint64_t wire_target_serial_id;
       struct TALER_Amount amount;
       struct TALER_Amount closing_fee;
-      uint64_t reserve_uuid;
     } reserves_close;
 
     struct
     {
-      struct GNUNET_HashCode h_blind_ev;
-      struct TALER_DenominationSignature denom_sig;
+      struct TALER_BlindedCoinHash h_blind_ev;
+      uint64_t denominations_serial;
+      struct TALER_BlindedDenominationSignature denom_sig;
+      uint64_t reserve_uuid;
       struct TALER_ReserveSignatureP reserve_sig;
       struct GNUNET_TIME_Absolute execution_date;
       struct TALER_Amount amount_with_fee;
-      uint64_t reserve_uuid;
-      uint64_t denominations_serial;
     } reserves_out;
 
     struct
@@ -269,68 +295,72 @@ struct TALER_EXCHANGEDB_TableData
     struct
     {
       struct TALER_CoinSpendPublicKeyP coin_pub;
-      struct TALER_DenominationSignature denom_sig;
+      struct TALER_AgeHash age_hash;
       uint64_t denominations_serial;
+      struct TALER_DenominationSignature denom_sig;
     } known_coins;
 
     struct
     {
       struct TALER_RefreshCommitmentP rc;
+      uint64_t old_known_coin_id;
       struct TALER_CoinSpendSignatureP old_coin_sig;
       struct TALER_Amount amount_with_fee;
       uint32_t noreveal_index;
-      uint64_t old_known_coin_id;
     } refresh_commitments;
 
     struct
     {
+      uint64_t melt_serial_id;
       uint32_t freshcoin_index;
       struct TALER_CoinSpendSignatureP link_sig;
+      uint64_t denominations_serial;
       void *coin_ev;
       size_t coin_ev_size;
       // h_coin_ev omitted, to be recomputed!
-      struct TALER_DenominationSignature ev_sig;
-      uint64_t denominations_serial;
-      uint64_t melt_serial_id;
+      struct TALER_BlindedDenominationSignature ev_sig;
     } refresh_revealed_coins;
 
     struct
     {
+      uint64_t melt_serial_id;
       struct TALER_TransferPublicKeyP tp;
       struct TALER_TransferPrivateKeyP tprivs[TALER_CNC_KAPPA - 1];
-      uint64_t melt_serial_id;
     } refresh_transfer_keys;
 
     struct
     {
+      uint64_t shard;
+      uint64_t known_coin_id;
       struct TALER_Amount amount_with_fee;
       struct GNUNET_TIME_Absolute wallet_timestamp;
       struct GNUNET_TIME_Absolute exchange_timestamp;
       struct GNUNET_TIME_Absolute refund_deadline;
       struct GNUNET_TIME_Absolute wire_deadline;
       struct TALER_MerchantPublicKeyP merchant_pub;
-      struct GNUNET_HashCode h_contract_terms;
-      // h_wire omitted, to be recomputed!
+      struct TALER_PrivateContractHash h_contract_terms;
       struct TALER_CoinSpendSignatureP coin_sig;
-      json_t *wire;
+      struct TALER_WireSalt wire_salt;
+      uint64_t wire_target_serial_id;
       bool tiny;
       bool done;
-      uint64_t known_coin_id;
+      bool extension_blocked;
+      uint64_t extension_details_serial_id;
     } deposits;
 
     struct
     {
+      uint64_t deposit_serial_id;
       struct TALER_MerchantSignatureP merchant_sig;
       uint64_t rtransaction_id;
       struct TALER_Amount amount_with_fee;
-      uint64_t deposit_serial_id;
     } refunds;
 
     struct
     {
       struct GNUNET_TIME_Absolute execution_date;
       struct TALER_WireTransferIdentifierRawP wtid_raw;
-      json_t *wire_target;
+      uint64_t wire_target_serial_id;
       char *exchange_account_section;
       struct TALER_Amount amount;
     } wire_out;
@@ -353,21 +383,21 @@ struct TALER_EXCHANGEDB_TableData
 
     struct
     {
+      uint64_t known_coin_id;
       struct TALER_CoinSpendSignatureP coin_sig;
-      struct TALER_DenominationBlindingKeyP coin_blind;
+      union TALER_DenominationBlindingKeyP coin_blind;
       struct TALER_Amount amount;
       struct GNUNET_TIME_Absolute timestamp;
-      uint64_t known_coin_id;
       uint64_t reserve_out_serial_id;
     } recoup;
 
     struct
     {
+      uint64_t known_coin_id;
       struct TALER_CoinSpendSignatureP coin_sig;
-      struct TALER_DenominationBlindingKeyP coin_blind;
+      union TALER_DenominationBlindingKeyP coin_blind;
       struct TALER_Amount amount;
       struct GNUNET_TIME_Absolute timestamp;
-      uint64_t known_coin_id;
       uint64_t rrc_serial;
     } recoup_refresh;
 
@@ -618,7 +648,7 @@ typedef void
 (*TALER_EXCHANGEDB_DenominationsCallback)(
   void *cls,
   const struct TALER_DenominationPublicKey *denom_pub,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
   const struct TALER_MasterSignatureP *master_sig,
   bool recoup_possible);
@@ -670,7 +700,7 @@ typedef void
 (*TALER_EXCHANGEDB_AuditorDenominationsCallback)(
   void *cls,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_AuditorSignatureP *auditor_sig);
 
 
@@ -683,14 +713,14 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin
 {
 
   /**
-   * Our signature over the (blinded) coin.
+   * Our (blinded) signature over the (blinded) coin.
    */
-  struct TALER_DenominationSignature sig;
+  struct TALER_BlindedDenominationSignature sig;
 
   /**
    * Hash of the denomination key (which coin was generated).
    */
-  struct GNUNET_HashCode denom_pub_hash;
+  struct TALER_DenominationHash denom_pub_hash;
 
   /**
    * Value of the coin being exchangeed (matching the denomination key)
@@ -723,7 +753,7 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin
    * Hash over the blinded message, needed to verify
    * the @e reserve_sig.
    */
-  struct GNUNET_HashCode h_coin_envelope;
+  struct TALER_BlindedCoinHash h_coin_envelope;
 
   /**
    * Signature confirming the withdrawal, matching @e reserve_pub,
@@ -749,7 +779,7 @@ struct TALER_EXCHANGEDB_Recoup
    * Blinding factor supplied to prove to the exchange that
    * the coin came from this reserve.
    */
-  struct TALER_DenominationBlindingKeyP coin_blind;
+  union TALER_DenominationBlindingKeyP coin_blind;
 
   /**
    * Signature of the coin of type
@@ -786,7 +816,7 @@ struct TALER_EXCHANGEDB_RecoupListEntry
    * Blinding factor supplied to prove to the exchange that
    * the coin came from this reserve.
    */
-  struct TALER_DenominationBlindingKeyP coin_blind;
+  union TALER_DenominationBlindingKeyP coin_blind;
 
   /**
    * Signature of the coin of type
@@ -797,7 +827,7 @@ struct TALER_EXCHANGEDB_RecoupListEntry
   /**
    * Hash of the public denomination key used to sign the coin.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Public key of the reserve the coin was paid back into.
@@ -834,7 +864,7 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry
    * Blinding factor supplied to prove to the exchange that
    * the coin came from this @e old_coin_pub.
    */
-  struct TALER_DenominationBlindingKeyP coin_blind;
+  union TALER_DenominationBlindingKeyP coin_blind;
 
   /**
    * Signature of the coin of type
@@ -977,21 +1007,24 @@ struct TALER_EXCHANGEDB_Deposit
    * Hash over the proposal data between merchant and customer
    * (remains unknown to the Exchange).
    */
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
 
   /**
-   * Hash of the (canonical) representation of @e wire, used
-   * to check the signature on the request.  Generated by
-   * the exchange from the detailed wire data provided by the
-   * merchant.
+   * Salt used by the merchant to compute "h_wire".
    */
-  struct GNUNET_HashCode h_wire;
+  struct TALER_WireSalt wire_salt;
 
   /**
-   * Detailed information about the receiver for executing the transaction.
-   * Includes URL in payto://-format and salt.
+   * Information about the receiver for executing the transaction.  URI in
+   * payto://-format.
    */
-  json_t *receiver_wire_account;
+  char *receiver_wire_account;
+
+  /**
+   * Additional details for extensions relevant for this
+   * deposit operation.
+   */
+  json_t *extension_details;
 
   /**
    * Time when this request was generated.  Used, for example, to
@@ -1062,26 +1095,23 @@ struct TALER_EXCHANGEDB_DepositListEntry
    * Hash over the proposa data between merchant and customer
    * (remains unknown to the Exchange).
    */
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
 
   /**
-   * Hash of the (canonical) representation of @e wire, used
-   * to check the signature on the request.  Generated by
-   * the exchange from the detailed wire data provided by the
-   * merchant.
+   * Hash of the public denomination key used to sign the coin.
    */
-  struct GNUNET_HashCode h_wire;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
-   * Hash of the public denomination key used to sign the coin.
+   * Detailed information about the receiver for executing the transaction.
+   * URL in payto://-format.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  char *receiver_wire_account;
 
   /**
-   * Detailed information about the receiver for executing the transaction.
-   * Includes URL in payto://-format and salt.
+   * Salt used to compute h_wire from the @e receiver_wire_account.
    */
-  json_t *receiver_wire_account;
+  struct TALER_WireSalt wire_salt;
 
   /**
    * Time when this request was generated.  Used, for example, to
@@ -1152,7 +1182,7 @@ struct TALER_EXCHANGEDB_RefundListEntry
    * Hash over the proposal data between merchant and customer
    * (remains unknown to the Exchange).
    */
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
 
   /**
    * Merchant-generated REFUND transaction ID to detect duplicate
@@ -1258,7 +1288,7 @@ struct TALER_EXCHANGEDB_MeltListEntry
   /**
    * Hash of the public denomination key used to sign the coin.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * How much value is being melted?  This amount includes the fees,
@@ -1321,7 +1351,7 @@ struct TALER_EXCHANGEDB_LinkList
   /**
    * Signature over the blinded envelope.
    */
-  struct TALER_DenominationSignature ev_sig;
+  struct TALER_BlindedDenominationSignature ev_sig;
 
   /**
    * Signature of the original coin being refreshed over the
@@ -1462,7 +1492,7 @@ typedef enum GNUNET_DB_QueryStatus
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_Amount *amount_with_fee,
   const struct TALER_Amount *deposit_fee,
-  const struct GNUNET_HashCode *h_contract_terms);
+  const struct TALER_PrivateContractHash *h_contract_terms);
 
 
 /**
@@ -1477,8 +1507,8 @@ typedef enum GNUNET_DB_QueryStatus
  * @param amount_with_fee amount that was deposited including fee
  * @param deposit_fee amount the exchange gets to keep as transaction fees
  * @param h_contract_terms hash of the proposal data known to merchant and 
customer
- * @param receiver_wire_account wire details for the merchant, includes
- *        'url' in payto://-format;
+ * @param wire_target unique ID of the receiver account
+ * @param payto_uri how to pay the merchant, URI in payto://-format;
  * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to 
continue to iterate
  */
 typedef enum GNUNET_DB_QueryStatus
@@ -1489,8 +1519,9 @@ typedef enum GNUNET_DB_QueryStatus
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_Amount *amount_with_fee,
   const struct TALER_Amount *deposit_fee,
-  const struct GNUNET_HashCode *h_contract_terms,
-  const json_t *receiver_wire_account);
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  uint64_t wire_target,
+  const char *payto_uri);
 
 
 /**
@@ -1517,19 +1548,8 @@ typedef void
  * @param cls closure
  * @param rowid unique serial ID for the deposit in our DB
  * @param exchange_timestamp when did the deposit happen
- * @param wallet_timestamp when did the contract happen
- * @param merchant_pub public key of the merchant
+ * @param deposit deposit details
  * @param denom_pub denomination public key of @a coin_pub
- * @param coin_pub public key of the coin
- * @param coin_sig signature from the coin
- * @param amount_with_fee amount that was deposited including fee
- * @param h_contract_terms hash of the proposal data known to merchant and 
customer
- * @param refund_deadline by which the merchant advised that he might want
- *        to get a refund
- * @param wire_deadline by which the merchant advised that he would like the
- *        wire transfer to be executed
- * @param receiver_wire_account wire details for the merchant including 'url' 
in payto://-format;
- *        NULL from iterate_matching_deposits()
  * @param done flag set if the deposit was already executed (or not)
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
@@ -1538,17 +1558,9 @@ typedef enum GNUNET_GenericReturnValue
   void *cls,
   uint64_t rowid,
   struct GNUNET_TIME_Absolute exchange_timestamp,
-  struct GNUNET_TIME_Absolute wallet_timestamp,
-  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_EXCHANGEDB_Deposit *deposit,
   const struct TALER_DenominationPublicKey *denom_pub,
-  const struct TALER_CoinSpendPublicKeyP *coin_pub,
-  const struct TALER_CoinSpendSignatureP *coin_sig,
-  const struct TALER_Amount *amount_with_fee,
-  const struct GNUNET_HashCode *h_contract_terms,
-  struct GNUNET_TIME_Absolute refund_deadline,
-  struct GNUNET_TIME_Absolute wire_deadline,
-  const json_t *receiver_wire_account,
-  int done);
+  bool done);
 
 
 /**
@@ -1621,7 +1633,7 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin
   /**
    * Signature generated by the exchange over the coin (in blinded format).
    */
-  struct TALER_DenominationSignature coin_sig;
+  struct TALER_BlindedDenominationSignature coin_sig;
 };
 
 
@@ -1735,7 +1747,7 @@ typedef enum GNUNET_GenericReturnValue
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_MerchantPublicKeyP *merchant_pub,
   const struct TALER_MerchantSignatureP *merchant_sig,
-  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_PrivateContractHash *h_contract_terms,
   uint64_t rtransaction_id,
   const struct TALER_Amount *amount_with_fee);
 
@@ -1816,7 +1828,7 @@ typedef enum GNUNET_GenericReturnValue
 (*TALER_EXCHANGEDB_WithdrawCallback)(
   void *cls,
   uint64_t rowid,
-  const struct GNUNET_HashCode *h_blind_ev,
+  const struct TALER_BlindedCoinHash *h_blind_ev,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_ReservePublicKeyP *reserve_pub,
   const struct TALER_ReserveSignatureP *reserve_sig,
@@ -1847,7 +1859,7 @@ typedef void
  * @param rowid which row in the table is the information from (for 
diagnostics)
  * @param merchant_pub public key of the merchant (should be same for all 
callbacks with the same @e cls)
  * @param h_wire hash of wire transfer details of the merchant (should be same 
for all callbacks with the same @e cls)
- * @param account_details which account did the transfer go to?
+ * @param account_payto_uri which account did the transfer go to?
  * @param exec_time execution time of the wire transfer (should be same for 
all callbacks with the same @e cls)
  * @param h_contract_terms which proposal was this payment about
  * @param denom_pub denomination of @a coin_pub
@@ -1860,10 +1872,9 @@ typedef void
   void *cls,
   uint64_t rowid,
   const struct TALER_MerchantPublicKeyP *merchant_pub,
-  const struct GNUNET_HashCode *h_wire,
-  const json_t *account_details,
+  const char *account_payto_uri,
   struct GNUNET_TIME_Absolute exec_time,
-  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_PrivateContractHash *h_contract_terms,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_Amount *coin_value,
@@ -1878,7 +1889,7 @@ typedef void
  * @param rowid identifier of the respective row in the database
  * @param date timestamp of the wire transfer (roughly)
  * @param wtid wire transfer subject
- * @param wire wire transfer details of the receiver, including "url" in 
payto://-format
+ * @param payto_uri details of the receiver, URI in payto://-format
  * @param amount amount that was wired
  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration
  */
@@ -1888,7 +1899,7 @@ typedef enum GNUNET_GenericReturnValue
   uint64_t rowid,
   struct GNUNET_TIME_Absolute date,
   const struct TALER_WireTransferIdentifierRawP *wtid,
-  const json_t *wire,
+  const char *payto_uri,
   const struct TALER_Amount *amount);
 
 
@@ -1936,7 +1947,7 @@ typedef enum GNUNET_GenericReturnValue
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const struct TALER_DenominationBlindingKeyP *coin_blind);
+  const union TALER_DenominationBlindingKeyP *coin_blind);
 
 
 /**
@@ -1962,11 +1973,11 @@ typedef enum GNUNET_GenericReturnValue
   struct GNUNET_TIME_Absolute timestamp,
   const struct TALER_Amount *amount,
   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
-  const struct GNUNET_HashCode *old_denom_pub_hash,
+  const struct TALER_DenominationHash *old_denom_pub_hash,
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_DenominationPublicKey *denom_pub,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const struct TALER_DenominationBlindingKeyP *coin_blind);
+  const union TALER_DenominationBlindingKeyP *coin_blind);
 
 
 /**
@@ -2044,8 +2055,8 @@ typedef void
   uint64_t rowid,
   const struct TALER_CoinPublicInfo *coin,
   const struct TALER_CoinSpendSignatureP *coin_sig,
-  const struct TALER_DenominationBlindingKeyP *coin_blind,
-  const struct GNUNET_HashCode *h_blinded_ev,
+  const union TALER_DenominationBlindingKeyP *coin_blind,
+  const struct TALER_BlindedCoinHash *h_blinded_ev,
   const struct TALER_Amount *amount);
 
 
@@ -2057,7 +2068,7 @@ typedef void
  * @param rowid deposit table row of the coin's deposit
  * @param coin_pub public key of the coin
  * @param amount value of the deposit, including fee
- * @param wire where should the funds be wired, including 'url' in 
payto://-format
+ * @param payto_uri where should the funds be wired; URI in payto://-format
  * @param deadline what was the requested wire transfer deadline
  * @param tiny did the exchange defer this transfer because it is too small?
  * @param done did the exchange claim that it made a transfer?
@@ -2068,10 +2079,10 @@ typedef void
   uint64_t rowid,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   const struct TALER_Amount *amount,
-  const json_t *wire,
+  const char *payto_uri,
   struct GNUNET_TIME_Absolute deadline,
-  /* bool? */ int tiny,
-  /* bool? */ int done);
+  bool tiny,
+  bool done);
 
 
 /**
@@ -2260,7 +2271,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*get_denomination_info)(
     void *cls,
-    const struct GNUNET_HashCode *denom_pub_hash,
+    const struct TALER_DenominationHash *denom_pub_hash,
     struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue);
 
 
@@ -2365,13 +2376,13 @@ struct TALER_EXCHANGEDB_Plugin
    *
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param payment_target_uuid which account has been checked
-   * @param ... possibly additional data to persist (TODO)
+   * @param id ID data to persist
    * @return transaction status
    */
   enum GNUNET_DB_QueryStatus
   (*set_kyc_ok)(void *cls,
                 uint64_t payment_target_uuid,
-                ...);
+                const char *id);
 
 
   /**
@@ -2400,7 +2411,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*select_kyc_status)(void *cls,
                        uint64_t payment_target_uuid,
-                       struct GNUNET_HashCode *h_payto,
+                       struct TALER_PaytoHash *h_payto,
                        struct TALER_EXCHANGEDB_KycStatus *kyc);
 
 
@@ -2472,7 +2483,7 @@ struct TALER_EXCHANGEDB_Plugin
    */
   enum GNUNET_DB_QueryStatus
   (*get_withdraw_info)(void *cls,
-                       const struct GNUNET_HashCode *h_blind,
+                       const struct TALER_BlindedCoinHash *h_blind,
                        struct TALER_EXCHANGEDB_CollectableBlindcoin 
*collectable);
 
 
@@ -2547,7 +2558,7 @@ struct TALER_EXCHANGEDB_Plugin
    */
   long long
   (*count_known_coins) (void *cls,
-                        const struct GNUNET_HashCode *denom_pub_hash);
+                        const struct TALER_DenominationHash *denom_pub_hash);
 
 
   /**
@@ -2612,7 +2623,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*get_coin_denomination)(void *cls,
                            const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                           struct GNUNET_HashCode *denom_hash);
+                           struct TALER_DenominationHash *denom_hash);
 
 
   /**
@@ -2620,7 +2631,6 @@ struct TALER_EXCHANGEDB_Plugin
    *
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param deposit deposit to search for
-   * @param check_extras whether to check extra fields or not
    * @param[out] deposit_fee set to the deposit fee the exchange charged
    * @param[out] exchange_timestamp set to the time when the exchange received 
the deposit
    * @return 1 if we know this operation,
@@ -2630,11 +2640,37 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*have_deposit)(void *cls,
                   const struct TALER_EXCHANGEDB_Deposit *deposit,
-                  int check_extras,
                   struct TALER_Amount *deposit_fee,
                   struct GNUNET_TIME_Absolute *exchange_timestamp);
 
 
+  /**
+   * Check if we have the specified deposit already in the database.
+   *
+   * @param cls the `struct PostgresClosure` with the plugin-specific state
+   * @param h_contract_terms contract to check for
+   * @param h_wire wire hash to check for
+   * @param coin_pub public key of the coin to check for
+   * @param merchant merchant public key to check for
+   * @param refund_deadline expected refund deadline
+   * @param[out] deposit_fee set to the deposit fee the exchange charged
+   * @param[out] exchange_timestamp set to the time when the exchange received 
the deposit
+   * @return 1 if we know this operation,
+   *         0 if this exact deposit is unknown to us,
+   *         otherwise transaction error status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*have_deposit2)(
+    void *cls,
+    const struct TALER_PrivateContractHash *h_contract_terms,
+    const struct TALER_MerchantWireHash *h_wire,
+    const struct TALER_CoinSpendPublicKeyP *coin_pub,
+    const struct TALER_MerchantPublicKeyP *merchant,
+    struct GNUNET_TIME_Absolute refund_deadline,
+    struct TALER_Amount *deposit_fee,
+    struct GNUNET_TIME_Absolute *exchange_timestamp);
+
+
   /**
    * Insert information about deposited coin into the database.
    *
@@ -2676,7 +2712,7 @@ struct TALER_EXCHANGEDB_Plugin
   (*select_refunds_by_coin)(void *cls,
                             const struct TALER_CoinSpendPublicKeyP *coin_pub,
                             const struct TALER_MerchantPublicKeyP 
*merchant_pub,
-                            const struct GNUNET_HashCode *h_contract,
+                            const struct TALER_PrivateContractHash *h_contract,
                             TALER_EXCHANGEDB_RefundCoinCallback cb,
                             void *cb_cls);
 
@@ -2695,27 +2731,6 @@ struct TALER_EXCHANGEDB_Plugin
                        uint64_t rowid);
 
 
-  /**
-   * Test if a deposit was marked as done, thereby declaring that it
-   * cannot be refunded anymore.
-   *
-   * @param cls the @e cls of this struct with the plugin-specific state
-   * @param coin_pub the coin to check for deposit
-   * @param merchant_pub merchant to receive the deposit
-   * @param h_contract_terms contract terms of the deposit
-   * @param h_wire hash of the merchant's wire details
-   * @return #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if is is marked done,
-   *         #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if not,
-   *         otherwise transaction error status (incl. deposit unknown)
-   */
-  enum GNUNET_DB_QueryStatus
-  (*test_deposit_done)(void *cls,
-                       const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                       const struct TALER_MerchantPublicKeyP *merchant_pub,
-                       const struct GNUNET_HashCode *h_contract_terms,
-                       const struct GNUNET_HashCode *h_wire);
-
-
   /**
    * Mark a deposit as done, thereby declaring that it cannot be
    * executed at all anymore, and should no longer be returned by
@@ -2733,19 +2748,23 @@ struct TALER_EXCHANGEDB_Plugin
   /**
    * Obtain information about deposits that are ready to be executed.
    * Such deposits must not be marked as "tiny" or "done", and the
-   * execution time and refund deadlines must both be in the past.
+   * execution time, the refund deadlines must both be in the past and
+   * the KYC status must be 'ok'.
    *
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param start_shard_row minimum shard row to select
    * @param end_shard_row maximum shard row to select (inclusive)
+   * @param kyc_off true if we should not check the KYC status because
+   *                this exchange does not need/support KYC checks.
    * @param deposit_cb function to call for ONE such deposit
    * @param deposit_cb_cls closure for @a deposit_cb
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
   (*get_ready_deposit)(void *cls,
-                       uint32_t start_shard_row,
-                       uint32_t end_shard_row,
+                       uint64_t start_shard_row,
+                       uint64_t end_shard_row,
+                       bool kyc_off,
                        TALER_EXCHANGEDB_DepositIterator deposit_cb,
                        void *deposit_cb_cls);
 
@@ -2778,7 +2797,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*iterate_matching_deposits)(
     void *cls,
-    const struct GNUNET_HashCode *h_wire,
+    uint64_t wire_target,
     const struct TALER_MerchantPublicKeyP *merchant_pub,
     TALER_EXCHANGEDB_MatchingDepositIterator deposit_cb,
     void *deposit_cb_cls,
@@ -2959,8 +2978,8 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*lookup_transfer_by_deposit)(
     void *cls,
-    const struct GNUNET_HashCode *h_contract_terms,
-    const struct GNUNET_HashCode *h_wire,
+    const struct TALER_PrivateContractHash *h_contract_terms,
+    const struct TALER_MerchantWireHash *h_wire,
     const struct TALER_CoinSpendPublicKeyP *coin_pub,
     const struct TALER_MerchantPublicKeyP *merchant_pub,
     bool *pending,
@@ -3160,7 +3179,7 @@ struct TALER_EXCHANGEDB_Plugin
     void *cls,
     struct GNUNET_TIME_Absolute date,
     const struct TALER_WireTransferIdentifierRawP *wtid,
-    const json_t *wire_account,
+    uint64_t wire_target,
     const char *exchange_account_section,
     const struct TALER_Amount *amount);
 
@@ -3173,8 +3192,8 @@ struct TALER_EXCHANGEDB_Plugin
    * @return #GNUNET_OK on success,
    *         #GNUNET_SYSERR on DB errors
    */
-  int
-  (*gc) (void *cls);
+  enum GNUNET_GenericReturnValue
+  (*gc)(void *cls);
 
 
   /**
@@ -3393,9 +3412,9 @@ struct TALER_EXCHANGEDB_Plugin
     const struct TALER_ReservePublicKeyP *reserve_pub,
     const struct TALER_CoinPublicInfo *coin,
     const struct TALER_CoinSpendSignatureP *coin_sig,
-    const struct TALER_DenominationBlindingKeyP *coin_blind,
+    const union TALER_DenominationBlindingKeyP *coin_blind,
     const struct TALER_Amount *amount,
-    const struct GNUNET_HashCode *h_blind_ev,
+    const struct TALER_BlindedCoinHash *h_blind_ev,
     struct GNUNET_TIME_Absolute timestamp);
 
 
@@ -3418,9 +3437,9 @@ struct TALER_EXCHANGEDB_Plugin
     void *cls,
     const struct TALER_CoinPublicInfo *coin,
     const struct TALER_CoinSpendSignatureP *coin_sig,
-    const struct TALER_DenominationBlindingKeyP *coin_blind,
+    const union TALER_DenominationBlindingKeyP *coin_blind,
     const struct TALER_Amount *amount,
-    const struct GNUNET_HashCode *h_blind_ev,
+    const struct TALER_BlindedCoinHash *h_blind_ev,
     struct GNUNET_TIME_Absolute timestamp);
 
 
@@ -3435,7 +3454,7 @@ struct TALER_EXCHANGEDB_Plugin
    */
   enum GNUNET_DB_QueryStatus
   (*get_reserve_by_h_blind)(void *cls,
-                            const struct GNUNET_HashCode *h_blind_ev,
+                            const struct TALER_BlindedCoinHash *h_blind_ev,
                             struct TALER_ReservePublicKeyP *reserve_pub);
 
 
@@ -3450,7 +3469,7 @@ struct TALER_EXCHANGEDB_Plugin
    */
   enum GNUNET_DB_QueryStatus
   (*get_old_coin_by_h_blind)(void *cls,
-                             const struct GNUNET_HashCode *h_blind_ev,
+                             const struct TALER_BlindedCoinHash *h_blind_ev,
                              struct TALER_CoinSpendPublicKeyP *old_coin_pub);
 
 
@@ -3466,7 +3485,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*insert_denomination_revocation)(
     void *cls,
-    const struct GNUNET_HashCode *denom_pub_hash,
+    const struct TALER_DenominationHash *denom_pub_hash,
     const struct TALER_MasterSignatureP *master_sig);
 
 
@@ -3482,7 +3501,8 @@ struct TALER_EXCHANGEDB_Plugin
    */
   enum GNUNET_DB_QueryStatus
   (*get_denomination_revocation)(void *cls,
-                                 const struct GNUNET_HashCode *denom_pub_hash,
+                                 const struct
+                                 TALER_DenominationHash *denom_pub_hash,
                                  struct TALER_MasterSignatureP *master_sig,
                                  uint64_t *rowid);
 
@@ -3699,7 +3719,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*lookup_denomination_key)(
     void *cls,
-    const struct GNUNET_HashCode *h_denom_pub,
+    const struct TALER_DenominationHash *h_denom_pub,
     struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta);
 
 
@@ -3716,7 +3736,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*add_denomination_key)(
     void *cls,
-    const struct GNUNET_HashCode *h_denom_pub,
+    const struct TALER_DenominationHash *h_denom_pub,
     const struct TALER_DenominationPublicKey *denom_pub,
     const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta,
     const struct TALER_MasterSignatureP *master_sig);
@@ -3767,7 +3787,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*insert_auditor_denom_sig)(
     void *cls,
-    const struct GNUNET_HashCode *h_denom_pub,
+    const struct TALER_DenominationHash *h_denom_pub,
     const struct TALER_AuditorPublicKeyP *auditor_pub,
     const struct TALER_AuditorSignatureP *auditor_sig);
 
@@ -3784,7 +3804,7 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*select_auditor_denom_sig)(
     void *cls,
-    const struct GNUNET_HashCode *h_denom_pub,
+    const struct TALER_DenominationHash *h_denom_pub,
     const struct TALER_AuditorPublicKeyP *auditor_pub,
     struct TALER_AuditorSignatureP *auditor_sig);
 
diff --git a/src/include/taler_auditordb_lib.h b/src/include/taler_extensions.h
similarity index 50%
copy from src/include/taler_auditordb_lib.h
copy to src/include/taler_extensions.h
index 3ba3bb37..0ef69a78 100644
--- a/src/include/taler_auditordb_lib.h
+++ b/src/include/taler_extensions.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2016 Taler Systems SA
+  Copyright (C) 2014-2021 Taler Systems SA
 
   TALER is free 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,34 +14,22 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file include/taler_auditordb_lib.h
- * @brief high-level interface for the auditor's database
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
+ * @file include/taler_extensions.h
+ * @brief Interface for extensions
+ * @author Özgür Kesim
  */
-#ifndef TALER_AUDITORDB_LIB_H
-#define TALER_AUDITORDB_LIB_H
-
-#include "taler_auditordb_plugin.h"
+#ifndef TALER_EXTENSIONS_H
+#define TALER_EXTENSIONS_H
 
 /**
- * Initialize the plugin.
  *
- * @param cfg configuration to use
- * @return NULL on failure
+ * @param cfg
+ * @param[out] mask for age restriction
+ * @return Error if extension for age restriction was set but age groups were
+ *         invalid, OK otherwise.
  */
-struct TALER_AUDITORDB_Plugin *
-TALER_AUDITORDB_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg);
-
-
-/**
- * Shutdown the plugin.
- *
- * @param plugin plugin to unload
- */
-void
-TALER_AUDITORDB_plugin_unload (struct TALER_AUDITORDB_Plugin *plugin);
-
+enum GNUNET_GenericReturnValue
+TALER_get_age_mask (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                    struct TALER_AgeMask *mask);
 
 #endif
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
index 068dea7d..26df1f11 100644
--- a/src/include/taler_json_lib.h
+++ b/src/include/taler_json_lib.h
@@ -139,7 +139,7 @@ TALER_JSON_pack_time_rel_nbo (const char *name,
  * @return json pack specification
  */
 struct GNUNET_JSON_PackSpec
-TALER_JSON_pack_denomination_public_key (
+TALER_JSON_pack_denom_pub (
   const char *name,
   const struct TALER_DenominationPublicKey *pk);
 
@@ -153,11 +153,26 @@ TALER_JSON_pack_denomination_public_key (
  * @return json pack specification
  */
 struct GNUNET_JSON_PackSpec
-TALER_JSON_pack_denomination_signature (
+TALER_JSON_pack_denom_sig (
   const char *name,
   const struct TALER_DenominationSignature *sig);
 
 
+/**
+ * Generate packer instruction for a JSON field of type
+ * blinded denomination signature (that needs to be
+ * unblinded before it becomes valid).
+ *
+ * @param name name of the field to add to the object
+ * @param sig signature
+ * @return json pack specification
+ */
+struct GNUNET_JSON_PackSpec
+TALER_JSON_pack_blinded_denom_sig (
+  const char *name,
+  const struct TALER_BlindedDenominationSignature *sig);
+
+
 /**
  * Generate packer instruction for a JSON field of type
  * amount.
@@ -311,8 +326,8 @@ TALER_JSON_spec_relative_time (const char *name,
  * @return corresponding field spec
  */
 struct GNUNET_JSON_Specification
-TALER_JSON_spec_denomination_public_key (const char *field,
-                                         struct TALER_DenominationPublicKey 
*pk);
+TALER_JSON_spec_denom_pub (const char *field,
+                           struct TALER_DenominationPublicKey *pk);
 
 
 /**
@@ -323,8 +338,22 @@ TALER_JSON_spec_denomination_public_key (const char *field,
  * @return corresponding field spec
  */
 struct GNUNET_JSON_Specification
-TALER_JSON_spec_denomination_signature (const char *field,
-                                        struct TALER_DenominationSignature 
*sig);
+TALER_JSON_spec_denom_sig (const char *field,
+                           struct TALER_DenominationSignature *sig);
+
+
+/**
+ * Generate line in parser specification for a
+ * blinded denomination signature.
+ *
+ * @param field name of the field
+ * @param sig the blinded signature to initialize
+ * @return corresponding field spec
+ */
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_blinded_denom_sig (
+  const char *field,
+  struct TALER_BlindedDenominationSignature *sig);
 
 
 /**
@@ -383,7 +412,7 @@ TALER_JSON_spec_i18n_str (const char *name,
  */
 enum GNUNET_GenericReturnValue
 TALER_JSON_contract_hash (const json_t *json,
-                          struct GNUNET_HashCode *hc);
+                          struct TALER_PrivateContractHash *hc);
 
 
 /**
@@ -505,7 +534,7 @@ TALER_JSON_get_error_code2 (const void *data,
  */
 enum GNUNET_GenericReturnValue
 TALER_JSON_merchant_wire_signature_hash (const json_t *wire_s,
-                                         struct GNUNET_HashCode *hc);
+                                         struct TALER_MerchantWireHash *hc);
 
 
 /**
diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h
index 4545b6d5..6e69cdf6 100644
--- a/src/include/taler_pq_lib.h
+++ b/src/include/taler_pq_lib.h
@@ -41,10 +41,10 @@ TALER_PQ_query_param_amount_nbo (const struct 
TALER_AmountNBO *x);
 
 
 /**
- * Generate query parameter for a currency, consisting of the three
- * components "value", "fraction" and "currency" in this order. The
- * types must be a 64-bit integer, 32-bit integer and a
- * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively.
+ * Generate query parameter for an amount, consisting of the two
+ * components "value" and "fraction" in this order. The
+ * types must be a 64-bit integer and a 32-bit integer
+ * respectively. The currency is dropped.
  *
  * @param x pointer to the query parameter to pass
  */
@@ -52,6 +52,43 @@ struct GNUNET_PQ_QueryParam
 TALER_PQ_query_param_amount (const struct TALER_Amount *x);
 
 
+/**
+ * Generate query parameter for a denomination public
+ * key. Internally, the various attributes of the
+ * public key will be serialized into on variable-size
+ * BLOB.
+ *
+ * @param x pointer to the query parameter to pass
+ */
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_denom_pub (
+  const struct TALER_DenominationPublicKey *denom_pub);
+
+
+/**
+ * Generate query parameter for a denomination signature.  Internally, the
+ * various attributes of the signature will be serialized into on
+ * variable-size BLOB.
+ *
+ * @param x pointer to the query parameter to pass
+ */
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_denom_sig (
+  const struct TALER_DenominationSignature *denom_sig);
+
+
+/**
+ * Generate query parameter for a blinded denomination signature.  Internally,
+ * the various attributes of the signature will be serialized into on
+ * variable-size BLOB.
+ *
+ * @param x pointer to the query parameter to pass
+ */
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_blinded_denom_sig (
+  const struct TALER_BlindedDenominationSignature *denom_sig);
+
+
 /**
  * Generate query parameter for a JSON object (stored as a string
  * in the DB).  Note that @a x must really be a JSON object or array,
@@ -119,6 +156,43 @@ TALER_PQ_result_spec_amount (const char *name,
                              struct TALER_Amount *amount);
 
 
+/**
+ * Denomination public key expected.
+ *
+ * @param name name of the field in the table
+ * @param[out] denom_pub where to store the public key
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_denom_pub (const char *name,
+                                struct TALER_DenominationPublicKey *denom_pub);
+
+
+/**
+ * Denomination signature expected.
+ *
+ * @param name name of the field in the table
+ * @param[out] denom_sig where to store the denomination signature
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_denom_sig (const char *name,
+                                struct TALER_DenominationSignature *denom_sig);
+
+
+/**
+ * Blinded denomination signature expected.
+ *
+ * @param name name of the field in the table
+ * @param[out] denom_sig where to store the denomination signature
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_blinded_denom_sig (
+  const char *name,
+  struct TALER_BlindedDenominationSignature *denom_sig);
+
+
 /**
  * json_t expected.
  *
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index 38c2dc25..40755348 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -332,7 +332,7 @@ struct TALER_DenominationKeyAnnouncementPS
   /**
    * Hash of the denomination public key.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Hash of the section name in the configuration of this denomination.
@@ -398,7 +398,7 @@ struct TALER_LinkDataPS
   /**
    * Hash of the denomination public key of the new coin.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Transfer public key (for which the private key was not revealed)
@@ -408,7 +408,7 @@ struct TALER_LinkDataPS
   /**
    * Hash of the blinded new coin.
    */
-  struct GNUNET_HashCode coin_envelope_hash;
+  struct TALER_BlindedCoinHash coin_envelope_hash;
 };
 
 
@@ -443,12 +443,12 @@ struct TALER_WithdrawRequestPS
   /**
    * Hash of the denomination public key for the coin that is withdrawn.
    */
-  struct GNUNET_HashCode h_denomination_pub GNUNET_PACKED;
+  struct TALER_DenominationHash h_denomination_pub GNUNET_PACKED;
 
   /**
    * Hash of the (blinded) message to be signed by the Exchange.
    */
-  struct GNUNET_HashCode h_coin_envelope GNUNET_PACKED;
+  struct TALER_BlindedCoinHash h_coin_envelope GNUNET_PACKED;
 };
 
 
@@ -467,17 +467,22 @@ struct TALER_DepositRequestPS
   /**
    * Hash over the contract for which this deposit is made.
    */
-  struct GNUNET_HashCode h_contract_terms GNUNET_PACKED;
+  struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED;
+
+  /**
+   * Hash over extension attributes shared with the exchange.
+   */
+  struct TALER_ExtensionContractHash h_extensions GNUNET_PACKED;
 
   /**
    * Hash over the wiring information of the merchant.
    */
-  struct GNUNET_HashCode h_wire GNUNET_PACKED;
+  struct TALER_MerchantWireHash h_wire GNUNET_PACKED;
 
   /**
    * Hash over the denomination public key used to sign the coin.
    */
-  struct GNUNET_HashCode h_denom_pub GNUNET_PACKED;
+  struct TALER_DenominationHash h_denom_pub GNUNET_PACKED;
 
   /**
    * Time when this request was generated.  Used, for example, to
@@ -525,13 +530,6 @@ struct TALER_DepositRequestPS
    */
   struct TALER_MerchantPublicKeyP merchant;
 
-  /**
-   * The coin's public key.  This is the value that must have been
-   * signed (blindly) by the Exchange.  The deposit request is to be
-   * signed by the corresponding private key (using EdDSA).
-   */
-  struct TALER_CoinSpendPublicKeyP coin_pub;
-
 };
 
 
@@ -550,12 +548,18 @@ struct TALER_DepositConfirmationPS
   /**
    * Hash over the contract for which this deposit is made.
    */
-  struct GNUNET_HashCode h_contract_terms GNUNET_PACKED;
+  struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED;
 
   /**
    * Hash over the wiring information of the merchant.
    */
-  struct GNUNET_HashCode h_wire GNUNET_PACKED;
+  struct TALER_MerchantWireHash h_wire GNUNET_PACKED;
+
+  /**
+   * Hash over the extension options of the deposit, 0 if there
+   * were not extension options.
+   */
+  struct TALER_ExtensionContractHash h_extensions GNUNET_PACKED;
 
   /**
    * Time when this confirmation was generated / when the exchange received
@@ -563,6 +567,12 @@ struct TALER_DepositConfirmationPS
    */
   struct GNUNET_TIME_AbsoluteNBO exchange_timestamp;
 
+  /**
+   * By when does the exchange expect to pay the merchant
+   * (as per the merchant's request).
+   */
+  struct GNUNET_TIME_AbsoluteNBO wire_deadline;
+
   /**
    * How much time does the @e merchant have to issue a refund
    * request?  Zero if refunds are not allowed.  After this time, the
@@ -579,9 +589,7 @@ struct TALER_DepositConfirmationPS
   struct TALER_AmountNBO amount_without_fee;
 
   /**
-   * The coin's public key.  This is the value that must have been
-   * signed (blindly) by the Exchange.  The deposit request is to be
-   * signed by the corresponding private key (using EdDSA).
+   * The public key of the coin that was deposited.
    */
   struct TALER_CoinSpendPublicKeyP coin_pub;
 
@@ -589,7 +597,7 @@ struct TALER_DepositConfirmationPS
    * The Merchant's public key.  Allows the merchant to later refund
    * the transaction or to inquire about the wire transfer identifier.
    */
-  struct TALER_MerchantPublicKeyP merchant;
+  struct TALER_MerchantPublicKeyP merchant_pub;
 
 };
 
@@ -609,7 +617,7 @@ struct TALER_RefundRequestPS
    * Hash over the proposal data to identify the contract
    * which is being refunded.
    */
-  struct GNUNET_HashCode h_contract_terms GNUNET_PACKED;
+  struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED;
 
   /**
    * The coin's public key.  This is the value that must have been
@@ -651,7 +659,7 @@ struct TALER_RefundConfirmationPS
    * Hash over the proposal data to identify the contract
    * which is being refunded.
    */
-  struct GNUNET_HashCode h_contract_terms GNUNET_PACKED;
+  struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED;
 
   /**
    * The coin's public key.  This is the value that must have been
@@ -698,7 +706,7 @@ struct TALER_RefreshMeltCoinAffirmationPS
   /**
    * Hash over the denomination public key used to sign the coin.
    */
-  struct GNUNET_HashCode h_denom_pub GNUNET_PACKED;
+  struct TALER_DenominationHash h_denom_pub GNUNET_PACKED;
 
   /**
    * How much of the value of the coin should be melted?  This amount
@@ -845,7 +853,7 @@ struct TALER_ExchangeAccountSetupSuccessPS
    * Hash over the payto for which the signature was
    * made.
    */
-  struct GNUNET_HashCode h_payto;
+  struct TALER_PaytoHash h_payto;
 
   /**
    * When was the signature made.
@@ -931,7 +939,7 @@ struct TALER_MasterAddWirePS
   /**
    * Hash over the exchange's payto URI.
    */
-  struct GNUNET_HashCode h_wire GNUNET_PACKED;
+  struct TALER_PaytoHash h_payto GNUNET_PACKED;
 };
 
 
@@ -956,7 +964,7 @@ struct TALER_MasterDelWirePS
   /**
    * Hash over the exchange's payto URI.
    */
-  struct GNUNET_HashCode h_wire GNUNET_PACKED;
+  struct TALER_PaytoHash h_payto GNUNET_PACKED;
 
 };
 
@@ -1053,7 +1061,7 @@ struct TALER_DenominationKeyValidityPS
    * Hash code of the denomination public key. (Used to avoid having
    * the variable-size RSA key in this struct.)
    */
-  struct GNUNET_HashCode denom_hash GNUNET_PACKED;
+  struct TALER_DenominationHash denom_hash GNUNET_PACKED;
 
 };
 
@@ -1155,7 +1163,7 @@ struct TALER_ExchangeKeyValidityPS
    * Hash code of the denomination public key. (Used to avoid having
    * the variable-size RSA key in this struct.)
    */
-  struct GNUNET_HashCode denom_hash GNUNET_PACKED;
+  struct TALER_DenominationHash denom_hash GNUNET_PACKED;
 
 };
 
@@ -1173,10 +1181,30 @@ struct TALER_MasterWireDetailsPS
   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
 
   /**
-   * Hash over the account holder's payto:// URL and
+   * Hash over the account holder's payto:// URL.
+   */
+  struct TALER_PaytoHash h_wire_details GNUNET_PACKED;
+
+};
+
+
+/**
+ * @brief Information signed by the exchange's master
+ * key affirming the IBAN details for the exchange.
+ */
+struct TALER_MerchantWireDetailsPS
+{
+
+  /**
+   * Purpose is #TALER_SIGNATURE_MERCHANT_WIRE_DETAILS.
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Salted hash over the account holder's payto:// URL and
    * the salt, as done by #TALER_exchange_wire_signature_hash().
    */
-  struct GNUNET_HashCode h_wire_details GNUNET_PACKED;
+  struct TALER_MerchantWireHash h_wire_details GNUNET_PACKED;
 
 };
 
@@ -1236,7 +1264,7 @@ struct TALER_MasterDenominationKeyRevocationPS
   /**
    * Hash of the denomination key.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
 };
 
@@ -1273,12 +1301,12 @@ struct TALER_DepositTrackPS
   /**
    * Hash over the proposal data of the contract for which this deposit is 
made.
    */
-  struct GNUNET_HashCode h_contract_terms GNUNET_PACKED;
+  struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED;
 
   /**
    * Hash over the wiring information of the merchant.
    */
-  struct GNUNET_HashCode h_wire GNUNET_PACKED;
+  struct TALER_MerchantWireHash h_wire GNUNET_PACKED;
 
   /**
    * The Merchant's public key.  The deposit inquiry request is to be
@@ -1305,7 +1333,7 @@ struct TALER_WireDepositDetailP
   /**
    * Hash of the contract
    */
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
 
   /**
    * Time when the wire transfer was performed by the exchange.
@@ -1358,9 +1386,9 @@ struct TALER_WireDepositDataPS
   struct TALER_MerchantPublicKeyP merchant_pub;
 
   /**
-   * Hash of wire details of the merchant.
+   * Hash of bank account of the merchant.
    */
-  struct GNUNET_HashCode h_wire;
+  struct TALER_PaytoHash h_payto;
 
   /**
    * Hash of the individual deposits that were aggregated,
@@ -1385,7 +1413,7 @@ struct TALER_ProposalDataPS
    * Hash of the JSON contract in UTF-8 including 0-termination,
    * using JSON_COMPACT | JSON_SORT_KEYS
    */
-  struct GNUNET_HashCode hash;
+  struct TALER_PrivateContractHash hash;
 };
 
 /**
@@ -1403,7 +1431,7 @@ struct TALER_PaymentResponsePS
   /**
    * Hash of the proposal data associated with this confirmation
    */
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
 };
 
 
@@ -1422,12 +1450,12 @@ struct TALER_ConfirmWirePS
   /**
    * Hash over the wiring information of the merchant.
    */
-  struct GNUNET_HashCode h_wire GNUNET_PACKED;
+  struct TALER_MerchantWireHash h_wire GNUNET_PACKED;
 
   /**
    * Hash over the contract for which this deposit is made.
    */
-  struct GNUNET_HashCode h_contract_terms GNUNET_PACKED;
+  struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED;
 
   /**
    * Raw value (binary encoding) of the wire transfer subject.
@@ -1476,12 +1504,12 @@ struct TALER_RecoupRequestPS
   /**
    * Hash of the (revoked) denomination public key of the coin.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Blinding factor that was used to withdraw the coin.
    */
-  struct TALER_DenominationBlindingKeyP coin_blind;
+  union TALER_DenominationBlindingKeyP coin_blind;
 };
 
 
@@ -1582,7 +1610,7 @@ struct TALER_DenominationUnknownAffirmationPS
   /**
    * Hash of the public denomination key we do not know.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 };
 
 
@@ -1612,7 +1640,7 @@ struct TALER_DenominationExpiredAffirmationPS
   /**
    * Hash of the public denomination key we do not know.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
 };
 
@@ -1652,7 +1680,7 @@ struct TALER_ReserveCloseConfirmationPS
   /**
    * Hash of the receiver's bank account.
    */
-  struct GNUNET_HashCode h_wire;
+  struct TALER_PaytoHash h_payto;
 
   /**
    * Wire transfer subject.
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index 7768a7f6..1f678b43 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -574,6 +574,7 @@ const struct TALER_TESTING_Command *
 TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is,
                                           const char *label);
 
+
 /**
  * Obtain main execution context for the main loop.
  *
@@ -1193,6 +1194,7 @@ struct TALER_TESTING_Command
 TALER_TESTING_cmd_exec_wirewatch (const char *label,
                                   const char *config_filename);
 
+
 /**
  * Make a "aggregator" CMD.
  *
@@ -1206,6 +1208,19 @@ TALER_TESTING_cmd_exec_aggregator (const char *label,
                                    const char *config_filename);
 
 
+/**
+ * Make a "aggregator" CMD and do not disable KYC checks.
+ *
+ * @param label command label.
+ * @param config_filename configuration file for the
+ *                        aggregator to use.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_exec_aggregator_with_kyc (const char *label,
+                                            const char *config_filename);
+
+
 /**
  * Make a "closer" CMD.  Note that it is right now not supported to run the
  * closer to close multiple reserves in combination with a subsequent reserve
@@ -1554,7 +1569,6 @@ TALER_TESTING_cmd_refresh_link_with_retry (struct 
TALER_TESTING_Command cmd);
  * @param bank_transfer_reference reference to a command that
  *        can offer a WTID so as to check that against what WTID
  *        the tracked operation has.  Set as NULL if not needed.
- *
  * @return the command.
  */
 struct TALER_TESTING_Command
@@ -1575,15 +1589,12 @@ TALER_TESTING_cmd_track_transaction (const char *label,
  *        a wtid.  If NULL is given, then a all zeroed WTID is
  *        used that will at 99.9999% probability NOT match any
  *        existing WTID known to the exchange.
- * @param index index number of the WTID to track, in case there
- *        are multiple on offer.
  * @param expected_response_code expected HTTP response code.
  * @return the command.
  */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_track_transfer_empty (const char *label,
                                         const char *wtid_reference,
-                                        unsigned int index,
                                         unsigned int expected_response_code);
 
 
@@ -1594,8 +1605,6 @@ TALER_TESTING_cmd_track_transfer_empty (const char *label,
  * @param label the command label.
  * @param wtid_reference reference to any command which can provide
  *        a wtid.  Will be the one tracked.
- * @param index in case there are multiple WTID offered, this
- *        parameter selects a particular one.
  * @param expected_response_code expected HTTP response code.
  * @param expected_total_amount how much money we expect being moved
  *        with this wire-transfer.
@@ -1605,11 +1614,11 @@ TALER_TESTING_cmd_track_transfer_empty (const char 
*label,
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_track_transfer (const char *label,
                                   const char *wtid_reference,
-                                  unsigned int index,
                                   unsigned int expected_response_code,
                                   const char *expected_total_amount,
                                   const char *expected_wire_fee);
 
+
 /**
  * Make a "bank check" CMD.  It checks whether a particular wire transfer from
  * the exchange (debit) has been made or not.
@@ -1870,7 +1879,7 @@ TALER_TESTING_cmd_batch (const char *label,
  *
  * @return false if not, true if it is a batch command
  */
-int
+bool
 TALER_TESTING_cmd_is_batch (const struct TALER_TESTING_Command *cmd);
 
 /**
@@ -2188,463 +2197,65 @@ TALER_TESTING_cmd_auditor_add_denom_sig (const char 
*label,
                                          bool bad_sig);
 
 
-/* *** Generic trait logic for implementing traits ********* */
-
-/**
- * A trait.
- */
-struct TALER_TESTING_Trait
-{
-  /**
-   * Index number associated with the trait.  This gives the
-   * possibility to have _multiple_ traits on offer under the
-   * same name.
-   */
-  unsigned int index;
-
-  /**
-   * Trait type, for example "reserve-pub" or "coin-priv".
-   */
-  const char *trait_name;
-
-  /**
-   * Pointer to the piece of data to offer.
-   */
-  const void *ptr;
-};
-
-
 /**
- * "end" trait.  Because traits are offered into arrays,
- * this type of trait is used to mark the end of such arrays;
- * useful when iterating over those.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_trait_end (void);
-
-
-/**
- * Extract a trait.
+ * Create a request for a wallet's KYC UUID.
  *
- * @param traits the array of all the traits.
- * @param[out] ret where to store the result.
- * @param trait type of the trait to extract.
- * @param index index number of the trait to extract.
- * @return #GNUNET_OK when the trait is found.
- */
-int
-TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
-                         const void **ret,
-                         const char *trait,
-                         unsigned int index);
-
-
-/* ****** Specific traits supported by this component ******* */
-
-
-/**
- * Obtain a bank transaction row value from @a cmd.
- *
- * @param cmd command to extract the number from.
- * @param[out] row set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_bank_row (const struct TALER_TESTING_Command *cmd,
-                                  const uint64_t **row);
-
-
-/**
- * Offer bank transaction row trait.
- *
- * @param row number to offer.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_bank_row (const uint64_t *row);
-
-
-/**
- * Offer a reserve private key.
- *
- * @param index reserve priv's index number.
- * @param reserve_priv reserve private key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_reserve_priv (
-  unsigned int index,
-  const struct TALER_ReservePrivateKeyP *reserve_priv);
-
-
-/**
- * Obtain a reserve private key from a @a cmd.
- *
- * @param cmd command to extract the reserve priv from.
- * @param index reserve priv's index number.
- * @param[out] reserve_priv set to the reserve priv.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_reserve_priv (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_ReservePrivateKeyP **reserve_priv);
-
-
-/**
- * Offer a reserve public key.
- *
- * @param index reserve pubs's index number.
- * @param reserve_pub reserve public key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_reserve_pub (
-  unsigned int index,
-  const struct TALER_ReservePublicKeyP *reserve_pub);
-
-
-/**
- * Obtain a reserve public key from a @a cmd.
- *
- * @param cmd command to extract the reserve pub from.
- * @param index reserve pub's index number.
- * @param[out] reserve_pub set to the reserve pub.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_reserve_pub (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_ReservePublicKeyP **reserve_pub);
-
-
-/**
- * Offer a reserve history entry.
- *
- * @param index reserve pubs's index number.
- * @param rh reserve history entry to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_reserve_history (
-  unsigned int index,
-  const struct TALER_EXCHANGE_ReserveHistory *rh);
-
-
-/**
- * Obtain a reserve history entry from a @a cmd.
- *
- * @param cmd command to extract the reserve history from.
- * @param index reserve history's index number.
- * @param[out] rhp set to the reserve history.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_reserve_history (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_EXCHANGE_ReserveHistory **rhp);
-
-
-/**
- * Make a trait for a exchange signature.
- *
- * @param index index number to associate to the offered exchange pub.
- * @param exchange_sig exchange signature to offer with this trait.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_exchange_sig (
-  unsigned int index,
-  const struct TALER_ExchangeSignatureP *exchange_sig);
-
-
-/**
- * Obtain a exchange signature (online sig) from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index index number of the exchange to obtain.
- * @param[out] exchange_sig set to the offered exchange signature.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_exchange_sig (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_ExchangeSignatureP **exchange_sig);
-
-
-/**
- * Make a trait for a exchange public key.
- *
- * @param index index number to associate to the offered exchange pub.
- * @param exchange_pub exchange pub to offer with this trait.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_exchange_pub (
-  unsigned int index,
-  const struct TALER_ExchangePublicKeyP *exchange_pub);
-
-
-/**
- * Obtain a exchange public key from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index index number of the exchange to obtain.
- * @param[out] exchange_pub set to the offered exchange pub.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_exchange_pub (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_ExchangePublicKeyP **exchange_pub);
-
-
-/**
- * Obtain location where a command stores a pointer to a process.
- *
- * @param cmd command to extract trait from.
- * @param index which process to pick if @a cmd
- *        has multiple on offer.
- * @param[out] processp set to the address of the pointer to the
- *        process.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_process (const struct TALER_TESTING_Command *cmd,
-                                 unsigned int index,
-                                 struct GNUNET_OS_Process ***processp);
-
-
-/**
- * Offer location where a command stores a pointer to a process.
- *
- * @param index offered location index number, in case there are
- *        multiple on offer.
- * @param processp process location to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_process (unsigned int index,
-                                  struct GNUNET_OS_Process **processp);
-
-
-/**
- * Offer coin private key.
- *
- * @param index index number to associate with offered coin priv.
- * @param coin_priv coin private key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_coin_priv (
-  unsigned int index,
-  const struct TALER_CoinSpendPrivateKeyP *coin_priv);
-
-/**
- * Obtain a coin private key from a @a cmd.
- *
- * @param cmd command to extract trait from.
- * @param index index of the coin priv to obtain.
- * @param[out] coin_priv set to the private key of the coin.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_coin_priv (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_CoinSpendPrivateKeyP **coin_priv);
-
-
-/**
- * Offer blinding key.
- *
- * @param index index number to associate to the offered key.
- * @param blinding_key blinding key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_blinding_key (
-  unsigned int index,
-  const struct TALER_DenominationBlindingKeyP *blinding_key);
-
-
-/**
- * Obtain a blinding key from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which coin to pick if @a cmd has multiple on offer.
- * @param[out] blinding_key set to the offered blinding key.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_blinding_key (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_DenominationBlindingKeyP **blinding_key);
-
-
-/**
- * Make a trait for a denomination public key.
- *
- * @param index index number to associate to the offered denom pub.
- * @param denom_pub denom pub to offer with this trait.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_denom_pub (
-  unsigned int index,
-  const struct TALER_EXCHANGE_DenomPublicKey *dpk);
-
-
-/**
- * Obtain a denomination public key from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index index number of the denom to obtain.
- * @param[out] denom_pub set to the offered denom pub.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_denom_pub (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_EXCHANGE_DenomPublicKey **dpk);
-
-
-/**
- * Obtain a denomination signature from a @a cmd.
- *
- * @param cmd command to extract the denom sig from.
- * @param index index number associated with the denom sig.
- * @param[out] denom_sig set to the offered signature.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_denom_sig (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_DenominationSignature **dpk);
-
-
-/**
- * Offer denom sig.
- *
- * @param index index number to associate to the signature on
- *        offer.
- * @param denom_sig the denom sig on offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_denom_sig (
-  unsigned int index,
-  const struct TALER_DenominationSignature *sig);
-
-
-/**
- * Offer number trait, 32-bit version.
- *
- * @param index the number's index number.
- * @param n number to offer.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uint32 (unsigned int index,
-                                 const uint32_t *n);
-
-
-/**
- * Obtain a "number" value from @a cmd, 32-bit version.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_uint32 (const struct TALER_TESTING_Command *cmd,
-                                unsigned int index,
-                                const uint32_t **n);
-
-
-/**
- * Offer number trait, 64-bit version.
- *
- * @param index the number's index number.
- * @param n number to offer.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uint64 (unsigned int index,
-                                 const uint64_t *n);
-
-
-/**
- * Obtain a "number" value from @a cmd, 64-bit version.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
+ * @param label command label.
+ * @param reserve_reference command with reserve private key to use (or NULL 
to create a fresh reserve key).
+ * @param expected_response_code expected HTTP status
+ * @return the command
  */
-int
-TALER_TESTING_get_trait_uint64 (const struct TALER_TESTING_Command *cmd,
-                                unsigned int index,
-                                const uint64_t **n);
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_wallet_kyc_get (const char *label,
+                                  const char *reserve_reference,
+                                  unsigned int expected_response_code);
 
 
 /**
- * Offer number trait, 64-bit signed version.
+ * Create a request for an account's KYC status.
  *
- * @param index the number's index number.
- * @param n number to offer.
+ * @param label command label.
+ * @param payment_target_reference command with a payment target to query
+ * @param expected_response_code expected HTTP status
+ * @return the command
  */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_int64 (unsigned int index,
-                                const int64_t *n);
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_check_kyc_get (const char *label,
+                                 const char *payment_target_reference,
+                                 unsigned int expected_response_code);
 
 
 /**
- * Obtain a "number" value from @a cmd, 64-bit signed version.
+ * Create a KYC proof request.
  *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
+ * @param label command label.
+ * @param payment_target_reference command with a payment target to query
+ * @param code OAuth 2.0 code to use
+ * @param state OAuth 2.0 state to use
+ * @param expected_response_code expected HTTP status
+ * @return the command
  */
-int
-TALER_TESTING_get_trait_int64 (const struct TALER_TESTING_Command *cmd,
-                               unsigned int index,
-                               const int64_t **n);
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_proof_kyc (const char *label,
+                             const char *payment_target_reference,
+                             const char *code,
+                             const char *state,
+                             unsigned int expected_response_code);
 
 
 /**
- * Offer a number.
+ * Starts a fake OAuth 2.0 service on @a port for testing
+ * KYC processes.
  *
- * @param index the number's index number.
- * @param n the number to offer.
- * @return #GNUNET_OK on success.
+ * @param label command label
+ * @param port the TCP port to listen on
  */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uint (unsigned int index,
-                               const unsigned int *i);
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_oauth (const char *label,
+                         uint16_t port);
 
 
-/**
- * Obtain a number from @a cmd.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_uint (const struct TALER_TESTING_Command *cmd,
-                              unsigned int index,
-                              const unsigned int **n);
+/* *** Generic trait logic for implementing traits ********* */
 
 
 /**
@@ -2655,579 +2266,204 @@ struct TALER_TESTING_FreshCoinData;
 
 
 /**
- * Offer a _array_ of fresh coins.
- *
- * @param index which array of fresh coins to offer,
- *        if there are multiple on offer.  Typically passed as
- *        zero.
- * @param fresh_coins the array of fresh coins to offer
- * @return the trait,
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_fresh_coins (
-  unsigned int index,
-  const struct TALER_TESTING_FreshCoinData *fresh_coins);
-
-
-/**
- * Get a array of fresh coins.
- *
- * @param cmd command to extract the fresh coin from.
- * @param index which array to pick if @a cmd has multiple
- *        on offer.
- * @param[out] fresh_coins will point to the offered array.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_fresh_coins (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_TESTING_FreshCoinData **fresh_coins);
-
-
-/**
- * Obtain contract terms from @a cmd.
- *
- * @param cmd command to extract the contract terms from.
- * @param index contract terms index number.
- * @param[out] contract_terms where to write the contract
- *        terms.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_contract_terms (const struct TALER_TESTING_Command 
*cmd,
-                                        unsigned int index,
-                                        const json_t **contract_terms);
-
-
-/**
- * Offer contract terms.
- *
- * @param index contract terms index number.
- * @param contract_terms contract terms to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_contract_terms (unsigned int index,
-                                         const json_t *contract_terms);
-
-
-/**
- * Obtain wire details from @a cmd.
- *
- * @param cmd command to extract the wire details from.
- * @param index index number associate with the wire details
- *        on offer; usually zero, as one command sticks to
- *        one bank account.
- * @param[out] wire_details where to write the wire details.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_wire_details (const struct TALER_TESTING_Command *cmd,
-                                      unsigned int index,
-                                      const json_t **wire_details);
-
-
-/**
- * Offer wire details in a trait.
- *
- * @param index index number associate with the wire details
- *        on offer; usually zero, as one command sticks to
- *        one bank account.
- * @param wire_details wire details to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_wire_details (unsigned int index,
-                                       const json_t *wire_details);
-
-
-/**
- * Obtain serialized exchange keys from @a cmd.
- *
- * @param cmd command to extract the keys from.
- * @param index index number associate with the keys on offer.
- * @param[out] keys where to write the serialized keys.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_exchange_keys (const struct TALER_TESTING_Command *cmd,
-                                       unsigned int index,
-                                       const json_t **keys);
-
-
-/**
- * Offer serialized keys in a trait.
- *
- * @param index index number associate with the serial keys
- *        on offer.
- * @param keys serialized keys to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_exchange_keys (unsigned int index,
-                                        const json_t *keys);
-
-
-/**
- * Obtain json from @a cmd.
- *
- * @param cmd command to extract the json from.
- * @param index index number associate with the json on offer.
- * @param[out] json where to write the json.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_json (const struct TALER_TESTING_Command *cmd,
-                              unsigned int index,
-                              const json_t **json);
-
-
-/**
- * Offer json in a trait.
- *
- * @param index index number associate with the json
- *        on offer.
- * @param json json to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_json (unsigned int index,
-                               const json_t *json);
-
-
-/**
- * Obtain a private key from a "merchant".  Used e.g. to obtain
- * a merchant's priv to sign a /track request.
- *
- * @param cmd command that is offering the key.
- * @param index (typically zero) which key to return if there
- *        are multiple on offer.
- * @param[out] priv set to the key coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_merchant_priv (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_MerchantPrivateKeyP **priv);
-
-
-/**
- * Offer private key of a merchant, typically done when CMD_1 needs it to
- * sign a request.
- *
- * @param index (typically zero) which key to return if there are
- *        multiple on offer.
- * @param priv which object should be offered.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_merchant_priv (
-  unsigned int index,
-  const struct TALER_MerchantPrivateKeyP *priv);
-
-
-/**
- * Obtain a public key from a "merchant".  Used e.g. to obtain
- * a merchant's public key to use backend's API.
- *
- * @param cmd command offering the key.
- * @param index (typically zero) which key to return if there
- *        are multiple on offer.
- * @param[out] pub set to the key coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_merchant_pub (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_MerchantPublicKeyP **pub);
-
-
-/**
- * Offer public key.
- *
- * @param index (typically zero) which key to return if there
- *        are multiple on offer.  NOTE: if one key is offered, it
- *        is mandatory to set this as zero.
- * @param pub which object should be returned.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_merchant_pub (
-  unsigned int index,
-  const struct TALER_MerchantPublicKeyP *pub);
-
-
-/**
- * Obtain a string from @a cmd.
- *
- * @param cmd command to extract the subject from.
- * @param index index number associated with the transfer
- *        subject to offer.
- * @param[out] s where to write the offered
- *        string.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_string (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const char **s);
-
-
-/**
- * Offer string subject.
- *
- * @param index index number associated with the transfer
- *        subject being offered.
- * @param s string to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_string (unsigned int index,
-                                 const char *s);
-
-
-/**
- * Obtain a WTID value from @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which WTID to pick if @a cmd has multiple on
- *        offer
- * @param[out] wtid set to the wanted WTID.
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_wtid (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_WireTransferIdentifierRawP **wtid);
-
-
-/**
- * Offer a WTID.
- *
- * @param index associate the WTID with this index.
- * @param wtid pointer to the WTID to offer.
- * @return the trait.
+ * A trait.
  */
 struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_wtid (
-  unsigned int index,
-  const struct TALER_WireTransferIdentifierRawP *wtid);
-
-
-/**
- * Different types of URLs that appear in traits.
- */
-enum TALER_TESTING_URL_Type
 {
   /**
-   * Category of last resort. Should not be used.
-   */
-  TALER_TESTING_UT_UNDEFINED = 0,
-
-  /**
-   * HTTP base URL of an exchange (API), as for example
-   * given in wire transfers subjects made by the aggregator.
-   */
-  TALER_TESTING_UT_EXCHANGE_BASE_URL = 1,
-
-  /**
-   * HTTP URL of the exchange's bank account at the bank.
+   * Index number associated with the trait.  This gives the
+   * possibility to have _multiple_ traits on offer under the
+   * same name.
    */
-  TALER_TESTING_UT_EXCHANGE_BANK_ACCOUNT_URL = 2,
+  unsigned int index;
 
   /**
-   * A taler://-URL.
+   * Trait type, for example "reserve-pub" or "coin-priv".
    */
-  TALER_TESTING_UT_TALER_URL = 3
-};
-
-
-/**
- * Offer HTTP url in a trait.
- *
- * @param index which url is to be picked,
- *        in case multiple are offered.
- * @param url the url to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_url (enum TALER_TESTING_URL_Type index,
-                              const char *url);
-
-
-/**
- * Obtain a HTTP url from @a cmd.
- *
- * @param cmd command to extract the url from.
- * @param index which url is to be picked, in case
- *        multiple are offered.
- * @param[out] url where to write the url.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_url (const struct TALER_TESTING_Command *cmd,
-                             enum TALER_TESTING_URL_Type index,
-                             const char **url);
-
+  const char *trait_name;
 
-/**
- * Used as the "index" in payto traits, to identify what kind of
- * payto URL we are returning.
- */
-enum TALER_TESTING_PaytoType
-{
-  /**
-   * We don't know / not credit or debit.
-   */
-  TALER_TESTING_PT_NEUTRAL,
   /**
-   * Credit side of a transaction.
-   */
-  TALER_TESTING_PT_CREDIT,
-  /**
-   * Debit side of a transaction.
+   * Pointer to the piece of data to offer.
    */
-  TALER_TESTING_PT_DEBIT
+  const void *ptr;
 };
 
 
 /**
- * Offer a payto uri in a trait.
- *
- * @param pt which url is to be picked,
- *        in case multiple are offered.
- * @param payto_uri the uri to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_payto (enum TALER_TESTING_PaytoType pt,
-                                const char *payto_uri);
-
-
-/**
- * Obtain a PAYTO url from @a cmd.
- *
- * @param cmd command to extract the url from.
- * @param pt which url is to be picked, in case
- *        multiple are offered.
- * @param[out] url where to write the url.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_payto (const struct TALER_TESTING_Command *cmd,
-                               enum TALER_TESTING_PaytoType pt,
-                               const char **url);
-
-
-/**
- * Obtain a order id from @a cmd.
- *
- * @param cmd command to extract the order id from.
- * @param index which order id is to be picked, in case
- *        multiple are offered.
- * @param[out] order_id where to write the order id.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_order_id (const struct TALER_TESTING_Command *cmd,
-                                  unsigned int index,
-                                  const char **order_id);
-
-
-/**
- * Offer order id in a trait.
- *
- * @param index which order id is to be offered,
- *        in case multiple are offered.
- * @param order_id the order id to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_order_id (unsigned int index,
-                                   const char *order_id);
-
-
-/**
- * Obtain an amount from a @a cmd.
- *
- * @param cmd command to extract the amount from.
- * @param index which amount to pick if @a cmd has multiple
- *        on offer
- * @param[out] amount set to the amount.
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_amount_obj (const struct TALER_TESTING_Command *cmd,
-                                    unsigned int index,
-                                    const struct TALER_Amount **amount);
-
-
-/**
- * Offer amount.
- *
- * @param index which amount to offer, in case there are
- *        multiple available.
- * @param amount the amount to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_amount_obj (unsigned int index,
-                                     const struct TALER_Amount *amount);
-
-
-/**
- * Offer a command in a trait.
- *
- * @param index always zero.  Commands offering this
- *        kind of traits do not need this index.  For
- *        example, a "meta" CMD returns always the
- *        CMD currently being executed.
- * @param cmd wire details to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_cmd (unsigned int index,
-                              const struct TALER_TESTING_Command *cmd);
-
-
-/**
- * Obtain a command from @a cmd.
- *
- * @param cmd command to extract the command from.
- * @param index always zero.  Commands offering this
- *        kind of traits do not need this index.  For
- *        example, a "meta" CMD returns always the
- *        CMD currently being executed.
- * @param[out] _cmd where to write the wire details.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_cmd (const struct TALER_TESTING_Command *cmd,
-                             unsigned int index,
-                             struct TALER_TESTING_Command **_cmd);
-
-
-/**
- * Obtain a uuid from @a cmd.
- *
- * @param cmd command to extract the uuid from.
- * @param index which amount to pick if @a cmd has multiple
- *        on offer
- * @param[out] uuid where to write the uuid.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_uuid (const struct TALER_TESTING_Command *cmd,
-                              unsigned int index,
-                              struct GNUNET_Uuid **uuid);
-
-
-/**
- * Offer a uuid in a trait.
- *
- * @param index which uuid to offer, in case there are
- *        multiple available.
- * @param uuid the uuid to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uuid (unsigned int index,
-                               const struct GNUNET_Uuid *uuid);
-
-
-/**
- * Obtain a claim token from @a cmd.
- *
- * @param cmd command to extract the token from.
- * @param index which amount to pick if @a cmd has multiple
- *        on offer
- * @param[out] ct where to write the token.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_claim_token (const struct TALER_TESTING_Command *cmd,
-                                     unsigned int index,
-                                     const struct TALER_ClaimTokenP **ct);
-
-
-/**
- * Offer a claim token in a trait.
- *
- * @param index which token to offer, in case there are
- *        multiple available.
- * @param ct the token to offer.
- *
- * @return the trait.
+ * "end" trait.  Because traits are offered into arrays,
+ * this type of trait is used to mark the end of such arrays;
+ * useful when iterating over those.
  */
 struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_claim_token (unsigned int index,
-                                      const struct TALER_ClaimTokenP *ct);
+TALER_TESTING_trait_end (void);
 
 
 /**
- * Obtain a absolute time from @a cmd.
+ * Extract a trait.
  *
- * @param cmd command to extract trait from
- * @param index which time stamp to pick if
- *        @a cmd has multiple on offer.
- * @param[out] time set to the wanted WTID.
- * @return #GNUNET_OK on success
+ * @param traits the array of all the traits.
+ * @param[out] ret where to store the result.
+ * @param trait type of the trait to extract.
+ * @param index index number of the trait to extract.
+ * @return #GNUNET_OK when the trait is found.
  */
-int
-TALER_TESTING_get_trait_absolute_time (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct GNUNET_TIME_Absolute **time);
+enum GNUNET_GenericReturnValue
+TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
+                         const void **ret,
+                         const char *trait,
+                         unsigned int index);
 
 
-/**
- * Offer a absolute time.
- *
- * @param index associate the object with this index
- * @param time which object should be returned
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_absolute_time (
-  unsigned int index,
-  const struct GNUNET_TIME_Absolute *time);
+/* ****** Specific traits supported by this component ******* */
 
 
 /**
- * Obtain a relative time from @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which time to pick if
- *        @a cmd has multiple on offer.
- * @param[out] time set to the wanted WTID.
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_relative_time (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct GNUNET_TIME_Relative **time);
+ * Create headers for a trait with name @a name for
+ * statically allocated data of type @a type.
+ */
+#define TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT(name,type)   \
+  enum GNUNET_GenericReturnValue                          \
+    TALER_TESTING_get_trait_ ## name (                    \
+    const struct TALER_TESTING_Command *cmd,              \
+    type **ret);                                          \
+  struct TALER_TESTING_Trait                              \
+    TALER_TESTING_make_trait_ ## name (                   \
+    type * value);
+
+
+/**
+ * Create C implementation for a trait with name @a name for statically
+ * allocated data of type @a type.
+ */
+#define TALER_TESTING_MAKE_IMPL_SIMPLE_TRAIT(name,type)  \
+  enum GNUNET_GenericReturnValue                         \
+    TALER_TESTING_get_trait_ ## name (                   \
+    const struct TALER_TESTING_Command *cmd,             \
+    type **ret)                                          \
+  {                                                      \
+    if (NULL == cmd->traits) return GNUNET_SYSERR;       \
+    return cmd->traits (cmd->cls,                        \
+                        (const void **) ret,             \
+                        TALER_S (name),                  \
+                        0);                              \
+  }                                                      \
+  struct TALER_TESTING_Trait                             \
+    TALER_TESTING_make_trait_ ## name (                  \
+    type * value)                                        \
+  {                                                      \
+    struct TALER_TESTING_Trait ret = {                   \
+      .trait_name = TALER_S (name),                      \
+      .ptr = (const void *) value                        \
+    };                                                   \
+    return ret;                                          \
+  }
+
+
+/**
+ * Create headers for a trait with name @a name for
+ * statically allocated data of type @a type.
+ */
+#define TALER_TESTING_MAKE_DECL_INDEXED_TRAIT(name,type)  \
+  enum GNUNET_GenericReturnValue                          \
+    TALER_TESTING_get_trait_ ## name (                    \
+    const struct TALER_TESTING_Command *cmd,              \
+    unsigned int index,                                   \
+    type **ret);                                          \
+  struct TALER_TESTING_Trait                              \
+    TALER_TESTING_make_trait_ ## name (                   \
+    unsigned int index,                                   \
+    type * value);
+
+
+/**
+ * Create C implementation for a trait with name @a name for statically
+ * allocated data of type @a type.
+ */
+#define TALER_TESTING_MAKE_IMPL_INDEXED_TRAIT(name,type) \
+  enum GNUNET_GenericReturnValue                         \
+    TALER_TESTING_get_trait_ ## name (                   \
+    const struct TALER_TESTING_Command *cmd,             \
+    unsigned int index,                                  \
+    type **ret)                                          \
+  {                                                      \
+    if (NULL == cmd->traits) return GNUNET_SYSERR;       \
+    return cmd->traits (cmd->cls,                        \
+                        (const void **) ret,             \
+                        TALER_S (name),                  \
+                        index);                          \
+  }                                                      \
+  struct TALER_TESTING_Trait                             \
+    TALER_TESTING_make_trait_ ## name (                  \
+    unsigned int index,                                  \
+    type * value)                                        \
+  {                                                      \
+    struct TALER_TESTING_Trait ret = {                   \
+      .index = index,                                    \
+      .trait_name = TALER_S (name),                      \
+      .ptr = (const void *) value                        \
+    };                                                   \
+    return ret;                                          \
+  }
+
+
+/**
+ * Call #op on all simple traits.
+ */
+#define TALER_TESTING_SIMPLE_TRAITS(op) \
+  op (bank_row, const uint64_t)                                    \
+  op (reserve_priv, const struct TALER_ReservePrivateKeyP) \
+  op (reserve_pub, const struct TALER_ReservePublicKeyP)   \
+  op (merchant_priv, const struct TALER_MerchantPrivateKeyP)       \
+  op (merchant_pub, const struct TALER_MerchantPublicKeyP)         \
+  op (merchant_sig, const struct TALER_MerchantSignatureP)         \
+  op (wtid, const struct TALER_WireTransferIdentifierRawP)         \
+  op (contract_terms, const json_t)                                \
+  op (wire_details, const json_t)                                  \
+  op (exchange_keys, const json_t)                                 \
+  op (reserve_history, const struct TALER_EXCHANGE_ReserveHistory) \
+  op (exchange_url, const char *)                                  \
+  op (exchange_bank_account_url, const char *)                     \
+  op (taler_uri, const char *)                                     \
+  op (payto_uri, const char *)                                     \
+  op (kyc_url, const char *)                                     \
+  op (web_url, const char *)                                     \
+  op (row, const uint64_t)                                         \
+  op (payment_target_uuid, const uint64_t)                         \
+  op (array_length, const unsigned int)                            \
+  op (credit_payto_uri, const char *)                              \
+  op (debit_payto_uri, const char *)                               \
+  op (order_id, const char *)                                      \
+  op (amount, const struct TALER_Amount)                           \
+  op (amount_with_fee, const struct TALER_Amount)                        \
+  op (deposit_amount, const struct TALER_Amount)                           \
+  op (deposit_fee_amount, const struct TALER_Amount)                           
\
+  op (batch_cmds, struct TALER_TESTING_Command *)                  \
+  op (uuid, const struct GNUNET_Uuid)                              \
+  op (fresh_coins, const struct TALER_TESTING_FreshCoinData *)            \
+  op (claim_token, const struct TALER_ClaimTokenP)                 \
+  op (relative_time, const struct GNUNET_TIME_Relative)            \
+  op (process, struct GNUNET_OS_Process *)
+
+
+/**
+ * Call #op on all indexed traits.
+ */
+#define TALER_TESTING_INDEXED_TRAITS(op)                         \
+  op (denom_pub, const struct TALER_EXCHANGE_DenomPublicKey)           \
+  op (denom_sig, const struct TALER_DenominationSignature) \
+  op (coin_priv, const struct TALER_CoinSpendPrivateKeyP)              \
+  op (coin_pub, const struct TALER_CoinSpendPublicKeyP)                \
+  op (absolute_time, const struct GNUNET_TIME_Absolute)                \
+  op (wire_deadline, const struct GNUNET_TIME_Absolute)                \
+  op (refund_deadline, const struct GNUNET_TIME_Absolute)                \
+  op (exchange_pub, const struct TALER_ExchangePublicKeyP)             \
+  op (exchange_sig, const struct TALER_ExchangeSignatureP)             \
+  op (blinding_key, const union TALER_DenominationBlindingKeyP)
+
+
+TALER_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT)
+
+TALER_TESTING_INDEXED_TRAITS (TALER_TESTING_MAKE_DECL_INDEXED_TRAIT)
 
 
-/**
- * Offer a relative time.
- *
- * @param index associate the object with this index
- * @param time which object should be returned
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_relative_time (
-  unsigned int index,
-  const struct GNUNET_TIME_Relative *time);
-
 #endif
diff --git a/src/include/taler_util.h b/src/include/taler_util.h
index 2c556be2..8d7f5f75 100644
--- a/src/include/taler_util.h
+++ b/src/include/taler_util.h
@@ -233,7 +233,7 @@ TALER_language_matches (const char *language_pattern,
  *          #GNUNET_NO if the MHD connection is using http,
  *          #GNUNET_SYSERR if the connection type couldn't be determined
  */
-int
+enum GNUNET_GenericReturnValue
 TALER_mhd_is_https (struct MHD_Connection *connection);
 
 
@@ -327,6 +327,19 @@ char *
 TALER_payto_get_method (const char *payto_uri);
 
 
+/**
+ * Construct a payto://-URI from a Taler @a reserve_pub at
+ * a @exchange_base_url
+ *
+ * @param exchange_base_url the URL of the exchange
+ * @param reserve_pub public key of the reserve
+ * @return payto:// URI encoding the reserve's address
+ */
+char *
+TALER_payto_from_reserve (const char *exchange_base_url,
+                          const struct TALER_ReservePublicKeyP *reserve_pub);
+
+
 /**
  * Obtain the account name from a payto URL.
  *
diff --git a/src/json/json.c b/src/json/json.c
index 4c2b82cc..2dfabbf9 100644
--- a/src/json/json.c
+++ b/src/json/json.c
@@ -325,7 +325,7 @@ forget (const json_t *in,
 
 enum GNUNET_GenericReturnValue
 TALER_JSON_contract_hash (const json_t *json,
-                          struct GNUNET_HashCode *hc)
+                          struct TALER_PrivateContractHash *hc)
 {
   enum GNUNET_GenericReturnValue ret;
   json_t *cjson;
@@ -339,7 +339,7 @@ TALER_JSON_contract_hash (const json_t *json,
     return ret;
   ret = dump_and_hash (cjson,
                        NULL,
-                       hc);
+                       &hc->hash);
   json_decref (cjson);
   return ret;
 }
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 1f8d320b..e82fb294 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -60,7 +60,7 @@ TALER_JSON_from_amount_nbo (const struct TALER_AmountNBO 
*amount)
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_amount (void *cls,
               json_t *root,
               struct GNUNET_JSON_Specification *spec)
@@ -139,7 +139,7 @@ TALER_JSON_spec_amount_any (const char *name,
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_amount_nbo (void *cls,
                   json_t *root,
                   struct GNUNET_JSON_Specification *spec)
@@ -223,7 +223,7 @@ TALER_JSON_spec_amount_any_nbo (const char *name,
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_abs_time (void *cls,
                 json_t *root,
                 struct GNUNET_JSON_Specification *spec)
@@ -304,7 +304,7 @@ TALER_JSON_spec_absolute_time (const char *name,
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_abs_time_nbo (void *cls,
                     json_t *root,
                     struct GNUNET_JSON_Specification *spec)
@@ -355,7 +355,7 @@ TALER_JSON_spec_absolute_time_nbo (const char *name,
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_rel_time (void *cls,
                 json_t *root,
                 struct GNUNET_JSON_Specification *spec)
@@ -425,21 +425,285 @@ TALER_JSON_spec_relative_time (const char *name,
 }
 
 
+/**
+ * Parse given JSON object to denomination public key.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_denom_pub (void *cls,
+                 json_t *root,
+                 struct GNUNET_JSON_Specification *spec)
+{
+  struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
+  uint32_t cipher;
+  struct GNUNET_JSON_Specification dspec[] = {
+    GNUNET_JSON_spec_uint32 ("cipher",
+                             &cipher),
+    GNUNET_JSON_spec_uint32 ("age_mask",
+                             &denom_pub->age_mask.mask),
+    GNUNET_JSON_spec_end ()
+  };
+  const char *emsg;
+  unsigned int eline;
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root,
+                         dspec,
+                         &emsg,
+                         &eline))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  denom_pub->cipher = (enum TALER_DenominationCipher) cipher;
+  switch (denom_pub->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    {
+      struct GNUNET_JSON_Specification ispec[] = {
+        GNUNET_JSON_spec_rsa_public_key (
+          "rsa_public_key",
+          &denom_pub->details.rsa_public_key),
+        GNUNET_JSON_spec_end ()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (root,
+                             ispec,
+                             &emsg,
+                             &eline))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      return GNUNET_OK;
+    }
+  default:
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Cleanup data left from parsing denomination public key.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_denom_pub (void *cls,
+                 struct GNUNET_JSON_Specification *spec)
+{
+  struct TALER_DenominationPublicKey *denom_pub = spec->ptr;
+
+  TALER_denom_pub_free (denom_pub);
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_denom_pub (const char *field,
+                           struct TALER_DenominationPublicKey *pk)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_denom_pub,
+    .cleaner = &clean_denom_pub,
+    .field = field,
+    .ptr = pk
+  };
+
+  return ret;
+}
+
+
+/**
+ * Parse given JSON object to denomination signature.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_denom_sig (void *cls,
+                 json_t *root,
+                 struct GNUNET_JSON_Specification *spec)
+{
+  struct TALER_DenominationSignature *denom_sig = spec->ptr;
+  uint32_t cipher;
+  struct GNUNET_JSON_Specification dspec[] = {
+    GNUNET_JSON_spec_uint32 ("cipher",
+                             &cipher),
+    GNUNET_JSON_spec_end ()
+  };
+  const char *emsg;
+  unsigned int eline;
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root,
+                         dspec,
+                         &emsg,
+                         &eline))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  denom_sig->cipher = (enum TALER_DenominationCipher) cipher;
+  switch (denom_sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    {
+      struct GNUNET_JSON_Specification ispec[] = {
+        GNUNET_JSON_spec_rsa_signature (
+          "rsa_signature",
+          &denom_sig->details.rsa_signature),
+        GNUNET_JSON_spec_end ()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (root,
+                             ispec,
+                             &emsg,
+                             &eline))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      return GNUNET_OK;
+    }
+  default:
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Cleanup data left from parsing denomination public key.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_denom_sig (void *cls,
+                 struct GNUNET_JSON_Specification *spec)
+{
+  struct TALER_DenominationSignature *denom_sig = spec->ptr;
+
+  TALER_denom_sig_free (denom_sig);
+}
+
+
 struct GNUNET_JSON_Specification
-TALER_JSON_spec_denomination_public_key (const char *field,
-                                         struct TALER_DenominationPublicKey 
*pk)
+TALER_JSON_spec_denom_sig (const char *field,
+                           struct TALER_DenominationSignature *sig)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_denom_sig,
+    .cleaner = &clean_denom_sig,
+    .field = field,
+    .ptr = sig
+  };
+
+  return ret;
+}
+
+
+/**
+ * Parse given JSON object to blinded denomination signature.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_blinded_denom_sig (void *cls,
+                         json_t *root,
+                         struct GNUNET_JSON_Specification *spec)
+{
+  struct TALER_BlindedDenominationSignature *denom_sig = spec->ptr;
+  uint32_t cipher;
+  struct GNUNET_JSON_Specification dspec[] = {
+    GNUNET_JSON_spec_uint32 ("cipher",
+                             &cipher),
+    GNUNET_JSON_spec_end ()
+  };
+  const char *emsg;
+  unsigned int eline;
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (root,
+                         dspec,
+                         &emsg,
+                         &eline))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  denom_sig->cipher = (enum TALER_DenominationCipher) cipher;
+  switch (denom_sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    {
+      struct GNUNET_JSON_Specification ispec[] = {
+        GNUNET_JSON_spec_rsa_signature (
+          "blinded_rsa_signature",
+          &denom_sig->details.blinded_rsa_signature),
+        GNUNET_JSON_spec_end ()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (root,
+                             ispec,
+                             &emsg,
+                             &eline))
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+      return GNUNET_OK;
+    }
+  default:
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Cleanup data left from parsing denomination public key.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_blinded_denom_sig (void *cls,
+                         struct GNUNET_JSON_Specification *spec)
 {
-  return GNUNET_JSON_spec_rsa_public_key (field,
-                                          &pk->rsa_public_key);
+  struct TALER_BlindedDenominationSignature *denom_sig = spec->ptr;
+
+  TALER_blinded_denom_sig_free (denom_sig);
 }
 
 
 struct GNUNET_JSON_Specification
-TALER_JSON_spec_denomination_signature (const char *field,
-                                        struct TALER_DenominationSignature 
*sig)
+TALER_JSON_spec_blinded_denom_sig (
+  const char *field,
+  struct TALER_BlindedDenominationSignature *sig)
 {
-  return GNUNET_JSON_spec_rsa_signature (field,
-                                         &sig->rsa_signature);
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_blinded_denom_sig,
+    .cleaner = &clean_blinded_denom_sig,
+    .field = field,
+    .ptr = sig
+  };
+
+  return ret;
 }
 
 
@@ -468,7 +732,7 @@ struct I18nContext
  * @param[out] spec where to write the data
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_i18n_string (void *cls,
                    json_t *root,
                    struct GNUNET_JSON_Specification *spec)
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
index a03b09e2..f41ba523 100644
--- a/src/json/json_pack.c
+++ b/src/json/json_pack.c
@@ -88,22 +88,82 @@ TALER_JSON_pack_time_rel_nbo (const char *name,
 
 
 struct GNUNET_JSON_PackSpec
-TALER_JSON_pack_denomination_public_key (const char *name,
-                                         const struct
-                                         TALER_DenominationPublicKey *pk)
+TALER_JSON_pack_denom_pub (
+  const char *name,
+  const struct TALER_DenominationPublicKey *pk)
 {
-  return GNUNET_JSON_pack_rsa_public_key (name,
-                                          pk->rsa_public_key);
+  struct GNUNET_JSON_PackSpec ps = {
+    .field_name = name,
+  };
+
+  switch (pk->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    ps.object
+      = GNUNET_JSON_PACK (
+          GNUNET_JSON_pack_uint64 ("cipher",
+                                   TALER_DENOMINATION_RSA),
+          GNUNET_JSON_pack_uint64 ("age_mask",
+                                   pk->age_mask.mask),
+          GNUNET_JSON_pack_rsa_public_key ("rsa_public_key",
+                                           pk->details.rsa_public_key));
+    break;
+  default:
+    GNUNET_assert (0);
+  }
+  return ps;
+}
+
+
+struct GNUNET_JSON_PackSpec
+TALER_JSON_pack_denom_sig (
+  const char *name,
+  const struct TALER_DenominationSignature *sig)
+{
+  struct GNUNET_JSON_PackSpec ps = {
+    .field_name = name,
+  };
+
+  switch (sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    ps.object
+      = GNUNET_JSON_PACK (
+          GNUNET_JSON_pack_uint64 ("cipher",
+                                   TALER_DENOMINATION_RSA),
+          GNUNET_JSON_pack_rsa_signature ("rsa_signature",
+                                          sig->details.rsa_signature));
+    break;
+  default:
+    GNUNET_assert (0);
+  }
+  return ps;
 }
 
 
 struct GNUNET_JSON_PackSpec
-TALER_JSON_pack_denomination_signature (const char *name,
-                                        const struct
-                                        TALER_DenominationSignature *sig)
+TALER_JSON_pack_blinded_denom_sig (
+  const char *name,
+  const struct TALER_BlindedDenominationSignature *sig)
 {
-  return GNUNET_JSON_pack_rsa_signature (name,
-                                         sig->rsa_signature);
+  struct GNUNET_JSON_PackSpec ps = {
+    .field_name = name,
+  };
+
+  switch (sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    ps.object
+      = GNUNET_JSON_PACK (
+          GNUNET_JSON_pack_uint64 ("cipher",
+                                   TALER_DENOMINATION_RSA),
+          GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature",
+                                          sig->details.blinded_rsa_signature));
+    break;
+  default:
+    GNUNET_assert (0);
+  }
+  return ps;
 }
 
 
@@ -114,8 +174,8 @@ TALER_JSON_pack_amount (const char *name,
   struct GNUNET_JSON_PackSpec ps = {
     .field_name = name,
     .object = (NULL != amount)
-    ? TALER_JSON_from_amount (amount)
-    : NULL
+              ? TALER_JSON_from_amount (amount)
+              : NULL
   };
 
   return ps;
@@ -129,8 +189,8 @@ TALER_JSON_pack_amount_nbo (const char *name,
   struct GNUNET_JSON_PackSpec ps = {
     .field_name = name,
     .object = (NULL != amount)
-    ? TALER_JSON_from_amount_nbo (amount)
-    : NULL
+              ? TALER_JSON_from_amount_nbo (amount)
+              : NULL
   };
 
   return ps;
diff --git a/src/json/json_wire.c b/src/json/json_wire.c
index f88daefc..8f7fd6bb 100644
--- a/src/json/json_wire.c
+++ b/src/json/json_wire.c
@@ -26,7 +26,7 @@
 
 enum GNUNET_GenericReturnValue
 TALER_JSON_merchant_wire_signature_hash (const json_t *wire_s,
-                                         struct GNUNET_HashCode *hc)
+                                         struct TALER_MerchantWireHash *hc)
 {
   const char *payto_uri;
   struct TALER_WireSalt salt;
diff --git a/src/json/test_json.c b/src/json/test_json.c
index e312a4ed..ffc5b33c 100644
--- a/src/json/test_json.c
+++ b/src/json/test_json.c
@@ -91,8 +91,8 @@ path_cb (void *cls,
 static int
 test_contract (void)
 {
-  struct GNUNET_HashCode h1;
-  struct GNUNET_HashCode h2;
+  struct TALER_PrivateContractHash h1;
+  struct TALER_PrivateContractHash h2;
   json_t *c1;
   json_t *c2;
   json_t *c3;
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 518b725a..2862799d 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -28,6 +28,7 @@ libtalerexchange_la_SOURCES = \
   exchange_api_deposit.c \
   exchange_api_deposits_get.c \
   exchange_api_kyc_check.c \
+  exchange_api_kyc_proof.c \
   exchange_api_kyc_wallet.c \
   exchange_api_link.c \
   exchange_api_management_auditor_disable.c \
diff --git a/src/lib/auditor_api_deposit_confirmation.c 
b/src/lib/auditor_api_deposit_confirmation.c
index 9c13c3f0..5b207a18 100644
--- a/src/lib/auditor_api_deposit_confirmation.c
+++ b/src/lib/auditor_api_deposit_confirmation.c
@@ -153,6 +153,7 @@ handle_deposit_confirmation_finished (void *cls,
  * Verify signature information about the deposit-confirmation.
  *
  * @param h_wire hash of merchant wire details
+ * @param h_extensions hash over the extensions, if any
  * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the auditor)
  * @param exchange_timestamp timestamp when the deposit was received by the 
wallet
  * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the auditor (can be zero if refunds are not allowed); must not 
be after the @a wire_deadline
@@ -168,10 +169,12 @@ handle_deposit_confirmation_finished (void *cls,
  * @param master_sig master signature affirming validity of @a exchange_pub
  * @return #GNUNET_OK if signatures are OK, #GNUNET_SYSERR if not
  */
-static int
-verify_signatures (const struct GNUNET_HashCode *h_wire,
-                   const struct GNUNET_HashCode *h_contract_terms,
+static enum GNUNET_GenericReturnValue
+verify_signatures (const struct TALER_MerchantWireHash *h_wire,
+                   const struct TALER_ExtensionContractHash *h_extensions,
+                   const struct TALER_PrivateContractHash *h_contract_terms,
                    struct GNUNET_TIME_Absolute exchange_timestamp,
+                   struct GNUNET_TIME_Absolute wire_deadline,
                    struct GNUNET_TIME_Absolute refund_deadline,
                    const struct TALER_Amount *amount_without_fee,
                    const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -184,36 +187,29 @@ verify_signatures (const struct GNUNET_HashCode *h_wire,
                    struct GNUNET_TIME_Absolute ep_end,
                    const struct TALER_MasterSignatureP *master_sig)
 {
+  if (GNUNET_OK !=
+      TALER_exchange_deposit_confirm_verify (h_contract_terms,
+                                             h_wire,
+                                             h_extensions,
+                                             exchange_timestamp,
+                                             wire_deadline,
+                                             refund_deadline,
+                                             amount_without_fee,
+                                             coin_pub,
+                                             merchant_pub,
+                                             exchange_pub,
+                                             exchange_sig))
   {
-    struct TALER_DepositConfirmationPS dc = {
-      .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
-      .purpose.size = htonl (sizeof (dc)),
-      .h_contract_terms = *h_contract_terms,
-      .h_wire = *h_wire,
-      .exchange_timestamp = GNUNET_TIME_absolute_hton (exchange_timestamp),
-      .refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
-      .coin_pub = *coin_pub,
-      .merchant = *merchant_pub
-    };
-
-    TALER_amount_hton (&dc.amount_without_fee,
-                       amount_without_fee);
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
-                                    &dc,
-                                    &exchange_sig->eddsa_signature,
-                                    &exchange_pub->eddsa_pub))
+    GNUNET_break_op (0);
+    TALER_LOG_WARNING (
+      "Invalid signature on /deposit-confirmation request!\n");
     {
-      GNUNET_break_op (0);
-      TALER_LOG_WARNING (
-        "Invalid signature on /deposit-confirmation request!\n");
-      {
-        TALER_LOG_DEBUG ("... amount_without_fee was %s\n",
-                         TALER_amount2s (amount_without_fee));
-      }
-      return GNUNET_SYSERR;
+      TALER_LOG_DEBUG ("... amount_without_fee was %s\n",
+                       TALER_amount2s (amount_without_fee));
     }
+    return GNUNET_SYSERR;
   }
+
   if (GNUNET_OK !=
       TALER_exchange_offline_signkey_validity_verify (
         exchange_pub,
@@ -237,45 +233,14 @@ verify_signatures (const struct GNUNET_HashCode *h_wire,
 }
 
 
-/**
- * Submit a deposit-confirmation permission to the auditor and get the
- * auditor's response.  Note that while we return the response
- * verbatim to the caller for further processing, we do already verify
- * that the response is well-formed.  If the auditor's reply is not
- * well-formed, we return an HTTP status code of zero to @a cb.
- *
- * We also verify that the @a exchange_sig is valid for this 
deposit-confirmation
- * request, and that the @a master_sig is a valid signature for @a
- * exchange_pub.  Also, the @a auditor must be ready to operate (i.e.  have
- * finished processing the /version reply).  If either check fails, we do
- * NOT initiate the transaction with the auditor and instead return NULL.
- *
- * @param auditor the auditor handle; the auditor must be ready to operate
- * @param h_wire hash of merchant wire details
- * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the auditor)
- * @param exchange_timestamp timestamp when deposit was received by the 
exchange
- * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the auditor (can be zero if refunds are not allowed); must not 
be after the @a wire_deadline
- * @param amount_without_fee the amount confirmed to be wired by the exchange 
to the merchant
- * @param coin_pub coin’s public key
- * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
- * @param exchange_sig the signature made with purpose 
#TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT
- * @param exchange_pub the public key of the exchange that matches @a 
exchange_sig
- * @param master_pub master public key of the exchange
- * @param ep_start when does @a exchange_pub validity start
- * @param ep_expire when does @a exchange_pub usage end
- * @param ep_end when does @a exchange_pub legal validity end
- * @param master_sig master signature affirming validity of @a exchange_pub
- * @param cb the callback to call when a reply for this request is available
- * @param cb_cls closure for the above callback
- * @return a handle for this request; NULL if the inputs are invalid (i.e.
- *         signatures fail to verify).  In this case, the callback is not 
called.
- */
 struct TALER_AUDITOR_DepositConfirmationHandle *
 TALER_AUDITOR_deposit_confirmation (
   struct TALER_AUDITOR_Handle *auditor,
-  const struct GNUNET_HashCode *h_wire,
-  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_ExtensionContractHash *h_extensions,
+  const struct TALER_PrivateContractHash *h_contract_terms,
   struct GNUNET_TIME_Absolute exchange_timestamp,
+  struct GNUNET_TIME_Absolute wire_deadline,
   struct GNUNET_TIME_Absolute refund_deadline,
   const struct TALER_Amount *amount_without_fee,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -304,8 +269,10 @@ TALER_AUDITOR_deposit_confirmation (
                  TALER_AUDITOR_handle_is_ready_ (auditor));
   if (GNUNET_OK !=
       verify_signatures (h_wire,
+                         h_extensions,
                          h_contract_terms,
                          exchange_timestamp,
+                         wire_deadline,
                          refund_deadline,
                          amount_without_fee,
                          coin_pub,
@@ -326,12 +293,16 @@ TALER_AUDITOR_deposit_confirmation (
     = GNUNET_JSON_PACK (
         GNUNET_JSON_pack_data_auto ("h_wire",
                                     h_wire),
+        GNUNET_JSON_pack_data_auto ("h_extensions",
+                                    h_extensions),
         GNUNET_JSON_pack_data_auto ("h_contract_terms",
                                     h_contract_terms),
         GNUNET_JSON_pack_time_abs ("exchange_timestamp",
                                    exchange_timestamp),
         GNUNET_JSON_pack_time_abs ("refund_deadline",
                                    refund_deadline),
+        GNUNET_JSON_pack_time_abs ("wire_deadline",
+                                   wire_deadline),
         TALER_JSON_pack_amount ("amount_without_fee",
                                 amount_without_fee),
         GNUNET_JSON_pack_data_auto ("coin_pub",
@@ -397,12 +368,6 @@ TALER_AUDITOR_deposit_confirmation (
 }
 
 
-/**
- * Cancel a deposit-confirmation permission request.  This function cannot be 
used
- * on a request handle if a response is already served for it.
- *
- * @param deposit_confirmation the deposit-confirmation permission request 
handle
- */
 void
 TALER_AUDITOR_deposit_confirmation_cancel (
   struct TALER_AUDITOR_DepositConfirmationHandle *deposit_confirmation)
diff --git a/src/lib/auditor_api_exchanges.c b/src/lib/auditor_api_exchanges.c
index 0fe4ce28..13621225 100644
--- a/src/lib/auditor_api_exchanges.c
+++ b/src/lib/auditor_api_exchanges.c
@@ -122,9 +122,9 @@ handle_exchanges_finished (void *cls,
     }
     {
       struct TALER_AUDITOR_ExchangeInfo ei[ja_len];
-      int ok;
+      bool ok;
 
-      ok = GNUNET_YES;
+      ok = true;
       for (unsigned int i = 0; i<ja_len; i++)
       {
         struct GNUNET_JSON_Specification spec[] = {
@@ -140,13 +140,13 @@ handle_exchanges_finished (void *cls,
                                NULL, NULL))
         {
           GNUNET_break_op (0);
-          ok = GNUNET_NO;
+          ok = false;
           hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
           hr.http_status = 0;
           break;
         }
       }
-      if (GNUNET_YES != ok)
+      if (! ok)
         break;
       leh->cb (leh->cb_cls,
                &hr,
@@ -220,7 +220,8 @@ TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle 
*auditor,
   leh->auditor = auditor;
   leh->cb = cb;
   leh->cb_cls = cb_cls;
-  leh->url = TALER_AUDITOR_path_to_url_ (auditor, "/exchanges");
+  leh->url = TALER_AUDITOR_path_to_url_ (auditor,
+                                         "/exchanges");
   if (NULL == leh->url)
   {
     GNUNET_free (leh);
@@ -253,8 +254,8 @@ TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle 
*auditor,
  * @param leh the list exchanges request handle
  */
 void
-TALER_AUDITOR_list_exchanges_cancel (struct
-                                     TALER_AUDITOR_ListExchangesHandle *leh)
+TALER_AUDITOR_list_exchanges_cancel (
+  struct TALER_AUDITOR_ListExchangesHandle *leh)
 {
   if (NULL != leh->job)
   {
diff --git a/src/lib/exchange_api_auditor_add_denomination.c 
b/src/lib/exchange_api_auditor_add_denomination.c
index 8952cd2f..fbe46e51 100644
--- a/src/lib/exchange_api_auditor_add_denomination.c
+++ b/src/lib/exchange_api_auditor_add_denomination.c
@@ -141,7 +141,7 @@ struct TALER_EXCHANGE_AuditorAddDenominationHandle *
 TALER_EXCHANGE_add_auditor_denomination (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_AuditorPublicKeyP *auditor_pub,
   const struct TALER_AuditorSignatureP *auditor_sig,
   TALER_EXCHANGE_AuditorAddDenominationCallback cb,
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index 9c4a95ad..900c871d 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2015-2020 Taler Systems SA
+  Copyright (C) 2015-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -26,22 +26,6 @@
 #include "taler_signatures.h"
 
 
-/**
- * Parse history given in JSON format and return it in binary
- * format.
- *
- * @param exchange connection to the exchange we can use
- * @param history JSON array with the history
- * @param reserve_pub public key of the reserve to inspect
- * @param currency currency we expect the balance to be in
- * @param[out] balance final balance
- * @param history_length number of entries in @a history
- * @param[out] rhistory array of length @a history_length, set to the
- *             parsed history entries
- * @return #GNUNET_OK if history was valid and @a rhistory and @a balance
- *         were set,
- *         #GNUNET_SYSERR if there was a protocol violation in @a history
- */
 enum GNUNET_GenericReturnValue
 TALER_EXCHANGE_parse_reserve_history (
   struct TALER_EXCHANGE_Handle *exchange,
@@ -340,10 +324,8 @@ TALER_EXCHANGE_parse_reserve_history (
       }
       TALER_amount_hton (&rcc.closing_amount,
                          &amount);
-      GNUNET_CRYPTO_hash (
-        rh->details.close_details.receiver_account_details,
-        strlen (rh->details.close_details.receiver_account_details) + 1,
-        &rcc.h_wire);
+      TALER_payto_hash (rh->details.close_details.receiver_account_details,
+                        &rcc.h_payto);
       rcc.wtid = rh->details.close_details.wtid;
       rcc.purpose.size = htonl (sizeof (rcc));
       rcc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED);
@@ -451,7 +433,7 @@ TALER_EXCHANGE_verify_coin_history (
   const char *currency,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   json_t *history,
-  struct GNUNET_HashCode *h_denom_pub,
+  struct TALER_DenominationHash *h_denom_pub,
   struct TALER_Amount *total)
 {
   size_t len;
@@ -510,30 +492,31 @@ TALER_EXCHANGE_verify_coin_history (
     if (0 == strcasecmp (type,
                          "DEPOSIT"))
     {
-      struct TALER_DepositRequestPS dr = {
-        .purpose.size = htonl (sizeof (dr)),
-        .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
-        .coin_pub = *coin_pub
-      };
+      struct TALER_MerchantWireHash h_wire;
+      struct TALER_PrivateContractHash h_contract_terms;
+      // struct TALER_ExtensionContractHash h_extensions; // FIXME!
+      struct GNUNET_TIME_Absolute wallet_timestamp;
+      struct TALER_MerchantPublicKeyP merchant_pub;
+      struct GNUNET_TIME_Absolute refund_deadline = {0};
       struct TALER_CoinSpendSignatureP sig;
       struct GNUNET_JSON_Specification spec[] = {
         GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                      &sig),
         GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
-                                     &dr.h_contract_terms),
+                                     &h_contract_terms),
         GNUNET_JSON_spec_fixed_auto ("h_wire",
-                                     &dr.h_wire),
+                                     &h_wire),
         GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
-                                     &dr.h_denom_pub),
-        TALER_JSON_spec_absolute_time_nbo ("timestamp",
-                                           &dr.wallet_timestamp),
+                                     h_denom_pub),
+        TALER_JSON_spec_absolute_time ("timestamp",
+                                       &wallet_timestamp),
         GNUNET_JSON_spec_mark_optional (
-          TALER_JSON_spec_absolute_time_nbo ("refund_deadline",
-                                             &dr.refund_deadline)),
-        TALER_JSON_spec_amount_any_nbo ("deposit_fee",
-                                        &dr.deposit_fee),
+          TALER_JSON_spec_absolute_time ("refund_deadline",
+                                         &refund_deadline)),
+        TALER_JSON_spec_amount_any ("deposit_fee",
+                                    &fee),
         GNUNET_JSON_spec_fixed_auto ("merchant_pub",
-                                     &dr.merchant),
+                                     &merchant_pub),
         GNUNET_JSON_spec_end ()
       };
 
@@ -545,23 +528,25 @@ TALER_EXCHANGE_verify_coin_history (
         GNUNET_break_op (0);
         return GNUNET_SYSERR;
       }
-      TALER_amount_hton (&dr.amount_with_fee,
-                         &amount);
       if (GNUNET_OK !=
-          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
-                                      &dr,
-                                      &sig.eddsa_signature,
-                                      &coin_pub->eddsa_pub))
+          TALER_wallet_deposit_verify (&amount,
+                                       &fee,
+                                       &h_wire,
+                                       &h_contract_terms,
+                                       NULL /* h_extensions! */,
+                                       h_denom_pub,
+                                       wallet_timestamp,
+                                       &merchant_pub,
+                                       refund_deadline,
+                                       coin_pub,
+                                       &sig))
       {
         GNUNET_break_op (0);
         return GNUNET_SYSERR;
       }
-      *h_denom_pub = dr.h_denom_pub;
       if (NULL != dk)
       {
         /* check that deposit fee matches our expectations from /keys! */
-        TALER_amount_ntoh (&fee,
-                           &dr.deposit_fee);
         if ( (GNUNET_YES !=
               TALER_amount_cmp_currency (&fee,
                                          &dk->fee_deposit)) ||
@@ -956,14 +941,6 @@ TALER_EXCHANGE_verify_coin_history (
 }
 
 
-/**
- * Obtain meta data about an exchange (online) signing
- * key.
- *
- * @param keys from where to obtain the meta data
- * @param exchange_pub public key to lookup
- * @return NULL on error (@a exchange_pub not known)
- */
 const struct TALER_EXCHANGE_SigningPublicKey *
 TALER_EXCHANGE_get_signing_key_info (
   const struct TALER_EXCHANGE_Keys *keys,
diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c
index 35e09bd0..408601c6 100644
--- a/src/lib/exchange_api_deposit.c
+++ b/src/lib/exchange_api_deposit.c
@@ -81,9 +81,58 @@ struct TALER_EXCHANGE_DepositHandle
   void *cb_cls;
 
   /**
-   * Information the exchange should sign in response.
+   * Hash over the contract for which this deposit is made.
    */
-  struct TALER_DepositConfirmationPS depconf;
+  struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED;
+
+  /**
+   * Hash over the wiring information of the merchant.
+   */
+  struct TALER_MerchantWireHash h_wire GNUNET_PACKED;
+
+  /**
+   * Hash over the extension options of the deposit, 0 if there
+   * were not extension options.
+   */
+  struct TALER_ExtensionContractHash h_extensions GNUNET_PACKED;
+
+  /**
+   * Time when this confirmation was generated / when the exchange received
+   * the deposit request.
+   */
+  struct GNUNET_TIME_Absolute exchange_timestamp;
+
+  /**
+   * By when does the exchange expect to pay the merchant
+   * (as per the merchant's request).
+   */
+  struct GNUNET_TIME_Absolute wire_deadline;
+
+  /**
+   * How much time does the @e merchant have to issue a refund
+   * request?  Zero if refunds are not allowed.  After this time, the
+   * coin cannot be refunded.  Note that the wire transfer will not be
+   * performed by the exchange until the refund deadline.  This value
+   * is taken from the original deposit request.
+   */
+  struct GNUNET_TIME_Absolute refund_deadline;
+
+  /**
+   * Amount to be deposited, excluding fee.  Calculated from the
+   * amount with fee and the fee from the deposit request.
+   */
+  struct TALER_Amount amount_without_fee;
+
+  /**
+   * The public key of the coin that was deposited.
+   */
+  struct TALER_CoinSpendPublicKeyP coin_pub;
+
+  /**
+   * The Merchant's public key.  Allows the merchant to later refund
+   * the transaction or to inquire about the wire transfer identifier.
+   */
+  struct TALER_MerchantPublicKeyP merchant_pub;
 
   /**
    * Exchange signature, set for #auditor_cb.
@@ -132,7 +181,6 @@ auditor_cb (void *cls,
   struct TALER_EXCHANGE_DepositHandle *dh = cls;
   const struct TALER_EXCHANGE_Keys *key_state;
   const struct TALER_EXCHANGE_SigningPublicKey *spk;
-  struct TALER_Amount amount_without_fee;
   struct TEAH_AuditorInteractionEntry *aie;
 
   if (0 != GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
@@ -153,18 +201,18 @@ auditor_cb (void *cls,
     GNUNET_break_op (0);
     return NULL;
   }
-  TALER_amount_ntoh (&amount_without_fee,
-                     &dh->depconf.amount_without_fee);
   aie = GNUNET_new (struct TEAH_AuditorInteractionEntry);
   aie->dch = TALER_AUDITOR_deposit_confirmation (
     ah,
-    &dh->depconf.h_wire,
-    &dh->depconf.h_contract_terms,
-    GNUNET_TIME_absolute_ntoh (dh->depconf.exchange_timestamp),
-    GNUNET_TIME_absolute_ntoh (dh->depconf.refund_deadline),
-    &amount_without_fee,
-    &dh->depconf.coin_pub,
-    &dh->depconf.merchant,
+    &dh->h_wire,
+    &dh->h_extensions,
+    &dh->h_contract_terms,
+    dh->exchange_timestamp,
+    dh->wire_deadline,
+    dh->refund_deadline,
+    &dh->amount_without_fee,
+    &dh->coin_pub,
+    &dh->merchant_pub,
     &dh->exchange_pub,
     &dh->exchange_sig,
     &key_state->master_pub,
@@ -194,7 +242,7 @@ verify_deposit_signature_conflict (
   json_t *history;
   struct TALER_Amount total;
   enum TALER_ErrorCode ec;
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   memset (&h_denom_pub,
           0,
@@ -204,7 +252,7 @@ verify_deposit_signature_conflict (
   if (GNUNET_OK !=
       TALER_EXCHANGE_verify_coin_history (&dh->dki,
                                           dh->dki.value.currency,
-                                          &dh->depconf.coin_pub,
+                                          &dh->coin_pub,
                                           history,
                                           &h_denom_pub,
                                           &total))
@@ -286,8 +334,8 @@ handle_deposit_finished (void *cls,
         GNUNET_JSON_spec_mark_optional (
           GNUNET_JSON_spec_string ("transaction_base_url",
                                    &dr.details.success.transaction_base_url)),
-        TALER_JSON_spec_absolute_time_nbo ("exchange_timestamp",
-                                           &dh->depconf.exchange_timestamp),
+        TALER_JSON_spec_absolute_time ("exchange_timestamp",
+                                       &dh->exchange_timestamp),
         GNUNET_JSON_spec_end ()
       };
 
@@ -313,10 +361,17 @@ handle_deposit_finished (void *cls,
       }
 
       if (GNUNET_OK !=
-          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
-                                      &dh->depconf,
-                                      &dh->exchange_sig.eddsa_signature,
-                                      &dh->exchange_pub.eddsa_pub))
+          TALER_exchange_deposit_confirm_verify (&dh->h_contract_terms,
+                                                 &dh->h_wire,
+                                                 &dh->h_extensions,
+                                                 dh->exchange_timestamp,
+                                                 dh->wire_deadline,
+                                                 dh->refund_deadline,
+                                                 &dh->amount_without_fee,
+                                                 &dh->coin_pub,
+                                                 &dh->merchant_pub,
+                                                 &dh->exchange_pub,
+                                                 &dh->exchange_sig))
       {
         GNUNET_break_op (0);
         dr.hr.http_status = 0;
@@ -331,8 +386,7 @@ handle_deposit_finished (void *cls,
     }
     dr.details.success.exchange_sig = &dh->exchange_sig;
     dr.details.success.exchange_pub = &dh->exchange_pub;
-    dr.details.success.deposit_timestamp
-      = GNUNET_TIME_absolute_ntoh (dh->depconf.exchange_timestamp);
+    dr.details.success.deposit_timestamp = dh->exchange_timestamp;
     break;
   case MHD_HTTP_BAD_REQUEST:
     /* This should never happen, either us or the exchange is buggy
@@ -408,9 +462,9 @@ handle_deposit_finished (void *cls,
  * @param h_wire hash of the merchant’s account details
  * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the exchange)
  * @param coin_pub coin’s public key
+ * @param denom_sig exchange’s unblinded signature of the coin
  * @param denom_pub denomination key with which the coin is signed
  * @param denom_pub_hash hash of @a denom_pub
- * @param denom_sig exchange’s unblinded signature of the coin
  * @param timestamp timestamp when the deposit was finalized
  * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
  * @param refund_deadline date until which the merchant can issue a refund to 
the customer via the exchange (can be zero if refunds are not allowed)
@@ -420,50 +474,37 @@ handle_deposit_finished (void *cls,
 static enum GNUNET_GenericReturnValue
 verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
                    const struct TALER_Amount *amount,
-                   const struct GNUNET_HashCode *h_wire,
-                   const struct GNUNET_HashCode *h_contract_terms,
+                   const struct TALER_MerchantWireHash *h_wire,
+                   const struct TALER_PrivateContractHash *h_contract_terms,
                    const struct TALER_CoinSpendPublicKeyP *coin_pub,
                    const struct TALER_DenominationSignature *denom_sig,
                    const struct TALER_DenominationPublicKey *denom_pub,
-                   const struct GNUNET_HashCode *denom_pub_hash,
+                   const struct TALER_DenominationHash *denom_pub_hash,
                    struct GNUNET_TIME_Absolute timestamp,
                    const struct TALER_MerchantPublicKeyP *merchant_pub,
                    struct GNUNET_TIME_Absolute refund_deadline,
                    const struct TALER_CoinSpendSignatureP *coin_sig)
 {
+  if (GNUNET_OK !=
+      TALER_wallet_deposit_verify (amount,
+                                   &dki->fee_deposit,
+                                   h_wire,
+                                   h_contract_terms,
+                                   NULL /* FIXME: h_extensions! */,
+                                   denom_pub_hash,
+                                   timestamp,
+                                   merchant_pub,
+                                   refund_deadline,
+                                   coin_pub,
+                                   coin_sig))
   {
-    struct TALER_DepositRequestPS dr = {
-      .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
-      .purpose.size = htonl (sizeof (dr)),
-      .h_contract_terms = *h_contract_terms,
-      .h_wire = *h_wire,
-      .h_denom_pub = *denom_pub_hash,
-      .wallet_timestamp = GNUNET_TIME_absolute_hton (timestamp),
-      .refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
-      .merchant = *merchant_pub,
-      .coin_pub = *coin_pub
-    };
-
-    TALER_amount_hton (&dr.amount_with_fee,
-                       amount);
-    TALER_amount_hton (&dr.deposit_fee,
-                       &dki->fee_deposit);
-    if (GNUNET_OK !=
-        GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
-                                    &dr,
-                                    &coin_sig->eddsa_signature,
-                                    &coin_pub->eddsa_pub))
-    {
-      GNUNET_break_op (0);
-      TALER_LOG_WARNING ("Invalid coin signature on /deposit request!\n");
-      {
-        TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
-                         TALER_amount2s (amount));
-        TALER_LOG_DEBUG ("... deposit_fee was %s\n",
-                         TALER_amount2s (&dki->fee_deposit));
-      }
-      return GNUNET_SYSERR;
-    }
+    GNUNET_break_op (0);
+    TALER_LOG_WARNING ("Invalid coin signature on /deposit request!\n");
+    TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
+                     TALER_amount2s (amount));
+    TALER_LOG_DEBUG ("... deposit_fee was %s\n",
+                     TALER_amount2s (&dki->fee_deposit));
+    return GNUNET_SYSERR;
   }
 
   /* check coin signature */
@@ -471,7 +512,8 @@ verify_signatures (const struct 
TALER_EXCHANGE_DenomPublicKey *dki,
     struct TALER_CoinPublicInfo coin_info = {
       .coin_pub = *coin_pub,
       .denom_pub_hash = *denom_pub_hash,
-      .denom_sig = *denom_sig
+      .denom_sig = *denom_sig,
+      .age_commitment_hash = NULL /* FIXME-Oec */
     };
 
     if (GNUNET_YES !=
@@ -496,64 +538,25 @@ verify_signatures (const struct 
TALER_EXCHANGE_DenomPublicKey *dki,
 }
 
 
-void
-TALER_EXCHANGE_deposit_permission_sign (
+struct TALER_EXCHANGE_DepositHandle *
+TALER_EXCHANGE_deposit (
+  struct TALER_EXCHANGE_Handle *exchange,
   const struct TALER_Amount *amount,
-  const struct TALER_Amount *deposit_fee,
-  const struct GNUNET_HashCode *h_wire,
-  const struct GNUNET_HashCode *h_contract_terms,
-  const struct GNUNET_HashCode *h_denom_pub,
-  const struct TALER_CoinSpendPrivateKeyP *coin_priv,
-  struct GNUNET_TIME_Absolute wallet_timestamp,
+  struct GNUNET_TIME_Absolute wire_deadline,
+  const char *merchant_payto_uri,
+  const struct TALER_WireSalt *wire_salt,
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const json_t *extension_details,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_DenominationSignature *denom_sig,
+  const struct TALER_DenominationPublicKey *denom_pub,
+  struct GNUNET_TIME_Absolute timestamp,
   const struct TALER_MerchantPublicKeyP *merchant_pub,
   struct GNUNET_TIME_Absolute refund_deadline,
-  struct TALER_CoinSpendSignatureP *coin_sig)
-{
-  struct TALER_DepositRequestPS dr = {
-    .purpose.size = htonl
-                      (sizeof (dr)),
-    .purpose.purpose = htonl
-                         (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
-    .h_contract_terms = *h_contract_terms,
-    .h_wire = *h_wire,
-    .h_denom_pub = *h_denom_pub,
-    .wallet_timestamp = GNUNET_TIME_absolute_hton (wallet_timestamp),
-    .refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
-    .merchant = *merchant_pub
-  };
-
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_TIME_round_abs (&wallet_timestamp));
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_TIME_round_abs (&refund_deadline));
-  GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
-                                      &dr.coin_pub.eddsa_pub);
-  TALER_amount_hton (&dr.amount_with_fee,
-                     amount);
-  TALER_amount_hton (&dr.deposit_fee,
-                     deposit_fee);
-  GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
-                            &dr,
-                            &coin_sig->eddsa_signature);
-}
-
-
-struct TALER_EXCHANGE_DepositHandle *
-TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange,
-                        const struct TALER_Amount *amount,
-                        struct GNUNET_TIME_Absolute wire_deadline,
-                        json_t *wire_details,
-                        const struct GNUNET_HashCode *h_contract_terms,
-                        const struct TALER_CoinSpendPublicKeyP *coin_pub,
-                        const struct TALER_DenominationSignature *denom_sig,
-                        const struct TALER_DenominationPublicKey *denom_pub,
-                        struct GNUNET_TIME_Absolute timestamp,
-                        const struct TALER_MerchantPublicKeyP *merchant_pub,
-                        struct GNUNET_TIME_Absolute refund_deadline,
-                        const struct TALER_CoinSpendSignatureP *coin_sig,
-                        TALER_EXCHANGE_DepositResultCallback cb,
-                        void *cb_cls,
-                        enum TALER_ErrorCode *ec)
+  const struct TALER_CoinSpendSignatureP *coin_sig,
+  TALER_EXCHANGE_DepositResultCallback cb,
+  void *cb_cls,
+  enum TALER_ErrorCode *ec)
 {
   const struct TALER_EXCHANGE_Keys *key_state;
   const struct TALER_EXCHANGE_DenomPublicKey *dki;
@@ -561,8 +564,8 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
   struct GNUNET_CURL_Context *ctx;
   json_t *deposit_obj;
   CURL *eh;
-  struct GNUNET_HashCode h_wire;
-  struct GNUNET_HashCode denom_pub_hash;
+  struct TALER_MerchantWireHash h_wire;
+  struct TALER_DenominationHash denom_pub_hash;
   struct TALER_Amount amount_without_fee;
   char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
 
@@ -592,14 +595,9 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
   GNUNET_assert (GNUNET_YES ==
                  TEAH_handle_is_ready (exchange));
   /* initialize h_wire */
-  if (GNUNET_OK !=
-      TALER_JSON_merchant_wire_signature_hash (wire_details,
-                                               &h_wire))
-  {
-    GNUNET_break (0);
-    *ec = TALER_EC_GENERIC_FAILED_COMPUTE_JSON_HASH;
-    return NULL;
-  }
+  TALER_merchant_wire_signature_hash (merchant_payto_uri,
+                                      wire_salt,
+                                      &h_wire);
   key_state = TALER_EXCHANGE_get_keys (exchange);
   dki = TALER_EXCHANGE_get_denomination_key (key_state,
                                              denom_pub);
@@ -618,8 +616,8 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
     GNUNET_break_op (0);
     return NULL;
   }
-  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
-                                     &denom_pub_hash);
+  TALER_denom_pub_hash (denom_pub,
+                        &denom_pub_hash);
   if (GNUNET_OK !=
       verify_signatures (dki,
                          amount,
@@ -642,16 +640,16 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
   deposit_obj = GNUNET_JSON_PACK (
     TALER_JSON_pack_amount ("contribution",
                             amount),
-    GNUNET_JSON_pack_object_incref ("wire",
-                                    wire_details),
-    GNUNET_JSON_pack_data_auto ("h_wire",
-                                &h_wire),
+    GNUNET_JSON_pack_string ("merchant_payto_uri",
+                             merchant_payto_uri),
+    GNUNET_JSON_pack_data_auto ("wire_salt",
+                                wire_salt),
     GNUNET_JSON_pack_data_auto ("h_contract_terms",
                                 h_contract_terms),
     GNUNET_JSON_pack_data_auto ("denom_pub_hash",
                                 &denom_pub_hash),
-    TALER_JSON_pack_denomination_signature ("ub_sig",
-                                            denom_sig),
+    TALER_JSON_pack_denom_sig ("ub_sig",
+                               denom_sig),
     GNUNET_JSON_pack_time_abs ("timestamp",
                                timestamp),
     GNUNET_JSON_pack_data_auto ("merchant_pub",
@@ -678,22 +676,20 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
     json_decref (deposit_obj);
     return NULL;
   }
-  dh->depconf.purpose.size = htonl (sizeof (struct
-                                            TALER_DepositConfirmationPS));
-  dh->depconf.purpose.purpose = htonl (
-    TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT);
-  dh->depconf.h_contract_terms = *h_contract_terms;
-  dh->depconf.h_wire = h_wire;
-  /* dh->depconf.exchange_timestamp; -- initialized later from exchange reply! 
*/
-  dh->depconf.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
-  TALER_amount_hton (&dh->depconf.amount_without_fee,
-                     &amount_without_fee);
-  dh->depconf.coin_pub = *coin_pub;
-  dh->depconf.merchant = *merchant_pub;
+  dh->h_contract_terms = *h_contract_terms;
+  dh->h_wire = h_wire;
+  /* dh->h_extensions = ... */
+  dh->refund_deadline = refund_deadline;
+  dh->wire_deadline = wire_deadline;
+  dh->amount_without_fee = amount_without_fee;
+  dh->coin_pub = *coin_pub;
+  dh->merchant_pub = *merchant_pub;
   dh->amount_with_fee = *amount;
   dh->dki = *dki;
-  dh->dki.key.rsa_public_key = NULL; /* lifetime not warranted, so better
-                                        not copy the pointer */
+  memset (&dh->dki.key,
+          0,
+          sizeof (dh->dki.key)); /* lifetime not warranted, so better
+                                    not copy the contents! */
 
   eh = TALER_EXCHANGE_curl_easy_get_ (dh->url);
   if ( (NULL == eh) ||
diff --git a/src/lib/exchange_api_deposits_get.c 
b/src/lib/exchange_api_deposits_get.c
index e449aefb..843b00ff 100644
--- a/src/lib/exchange_api_deposits_get.c
+++ b/src/lib/exchange_api_deposits_get.c
@@ -278,8 +278,8 @@ struct TALER_EXCHANGE_DepositGetHandle *
 TALER_EXCHANGE_deposits_get (
   struct TALER_EXCHANGE_Handle *exchange,
   const struct TALER_MerchantPrivateKeyP *merchant_priv,
-  const struct GNUNET_HashCode *h_wire,
-  const struct GNUNET_HashCode *h_contract_terms,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_PrivateContractHash *h_contract_terms,
   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   TALER_EXCHANGE_DepositGetCallback cb,
   void *cb_cls)
@@ -290,9 +290,9 @@ TALER_EXCHANGE_deposits_get (
   struct GNUNET_CURL_Context *ctx;
   CURL *eh;
   char arg_str[(sizeof (struct TALER_CoinSpendPublicKeyP)
-                + sizeof (struct GNUNET_HashCode)
+                + sizeof (struct TALER_MerchantWireHash)
                 + sizeof (struct TALER_MerchantPublicKeyP)
-                + sizeof (struct GNUNET_HashCode)
+                + sizeof (struct TALER_PrivateContractHash)
                 + sizeof (struct TALER_MerchantSignatureP)) * 2 + 48];
 
   if (GNUNET_YES !=
@@ -316,37 +316,32 @@ TALER_EXCHANGE_deposits_get (
     char cpub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2];
     char mpub_str[sizeof (struct TALER_MerchantPublicKeyP) * 2];
     char msig_str[sizeof (struct TALER_MerchantSignatureP) * 2];
-    char chash_str[sizeof (struct GNUNET_HashCode) * 2];
-    char whash_str[sizeof (struct GNUNET_HashCode) * 2];
+    char chash_str[sizeof (struct TALER_PrivateContractHash) * 2];
+    char whash_str[sizeof (struct TALER_MerchantWireHash) * 2];
     char *end;
 
     end = GNUNET_STRINGS_data_to_string (h_wire,
-                                         sizeof (struct
-                                                 GNUNET_HashCode),
+                                         sizeof (*h_wire),
                                          whash_str,
                                          sizeof (whash_str));
     *end = '\0';
     end = GNUNET_STRINGS_data_to_string (&dtp.merchant,
-                                         sizeof (struct
-                                                 TALER_MerchantPublicKeyP),
+                                         sizeof (dtp.merchant),
                                          mpub_str,
                                          sizeof (mpub_str));
     *end = '\0';
     end = GNUNET_STRINGS_data_to_string (h_contract_terms,
-                                         sizeof (struct
-                                                 GNUNET_HashCode),
+                                         sizeof (*h_contract_terms),
                                          chash_str,
                                          sizeof (chash_str));
     *end = '\0';
     end = GNUNET_STRINGS_data_to_string (coin_pub,
-                                         sizeof (struct
-                                                 TALER_CoinSpendPublicKeyP),
+                                         sizeof (*coin_pub),
                                          cpub_str,
                                          sizeof (cpub_str));
     *end = '\0';
     end = GNUNET_STRINGS_data_to_string (&merchant_sig,
-                                         sizeof (struct
-                                                 TALER_MerchantSignatureP),
+                                         sizeof (merchant_sig),
                                          msig_str,
                                          sizeof (msig_str));
     *end = '\0';
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index 215f122b..f2f8b594 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -345,8 +345,8 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey 
*denom_key,
                                 &denom_key->fee_refresh),
     TALER_JSON_spec_amount_any ("fee_refund",
                                 &denom_key->fee_refund),
-    GNUNET_JSON_spec_rsa_public_key ("denom_pub",
-                                     &denom_key->key.rsa_public_key),
+    TALER_JSON_spec_denom_pub ("denom_pub",
+                               &denom_key->key),
     GNUNET_JSON_spec_end ()
   };
 
@@ -359,8 +359,8 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey 
*denom_key,
     return GNUNET_SYSERR;
   }
 
-  GNUNET_CRYPTO_rsa_public_key_hash (denom_key->key.rsa_public_key,
-                                     &denom_key->h_key);
+  TALER_denom_pub_hash (&denom_key->key,
+                        &denom_key->h_key);
   if (NULL != hash_context)
     GNUNET_CRYPTO_hash_context_read (hash_context,
                                      &denom_key->h_key,
@@ -445,7 +445,7 @@ parse_json_auditor (struct 
TALER_EXCHANGE_AuditorInformation *auditor,
   off = 0;
   json_array_foreach (keys, i, key) {
     struct TALER_AuditorSignatureP auditor_sig;
-    struct GNUNET_HashCode denom_h;
+    struct TALER_DenominationHash denom_h;
     const struct TALER_EXCHANGE_DenomPublicKey *dk;
     unsigned int dk_off;
     struct GNUNET_JSON_Specification kspec[] = {
@@ -480,7 +480,7 @@ parse_json_auditor (struct 
TALER_EXCHANGE_AuditorInformation *auditor,
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                   "Auditor signed denomination %s, which we do not know. 
Ignoring signature.\n",
-                  GNUNET_h2s (&denom_h));
+                  GNUNET_h2s (&denom_h.hash));
       continue;
     }
     if (check_sigs)
@@ -626,36 +626,28 @@ update_auditors (struct TALER_EXCHANGE_Handle *exchange)
  *  the same object), 1 otherwise.
  */
 static unsigned int
-denoms_cmp (struct TALER_EXCHANGE_DenomPublicKey *denom1,
-            struct TALER_EXCHANGE_DenomPublicKey *denom2)
+denoms_cmp (const struct TALER_EXCHANGE_DenomPublicKey *denom1,
+            const struct TALER_EXCHANGE_DenomPublicKey *denom2)
 {
-  struct GNUNET_CRYPTO_RsaPublicKey *tmp1;
-  struct GNUNET_CRYPTO_RsaPublicKey *tmp2;
-  int r1;
-  int r2;
-  int ret;
-
-  /* First check if pub is the same.  */
-  if (0 != GNUNET_CRYPTO_rsa_public_key_cmp
-        (denom1->key.rsa_public_key,
-        denom2->key.rsa_public_key))
-    return 1;
+  struct TALER_EXCHANGE_DenomPublicKey tmp1;
+  struct TALER_EXCHANGE_DenomPublicKey tmp2;
 
-  tmp1 = denom1->key.rsa_public_key;
-  tmp2 = denom2->key.rsa_public_key;
-  r1 = denom1->revoked;
-  r2 = denom2->revoked;
-
-  denom1->key.rsa_public_key = NULL;
-  denom2->key.rsa_public_key = NULL;
-  /* Then proceed with the rest of the object.  */
-  ret = GNUNET_memcmp (denom1,
-                       denom2);
-  denom1->revoked = r1;
-  denom2->revoked = r2;
-  denom1->key.rsa_public_key = tmp1;
-  denom2->key.rsa_public_key = tmp2;
-  return ret;
+  if (0 !=
+      TALER_denom_pub_cmp (&denom1->key,
+                           &denom2->key))
+    return 1;
+  tmp1 = *denom1;
+  tmp2 = *denom2;
+  tmp1.revoked = false;
+  tmp2.revoked = false;
+  memset (&tmp1.key,
+          0,
+          sizeof (tmp1.key));
+  memset (&tmp2.key,
+          0,
+          sizeof (tmp2.key));
+  return GNUNET_memcmp (&tmp1,
+                        &tmp2);
 }
 
 
@@ -844,7 +836,7 @@ decode_keys_json (const json_t *resp_obj,
       {
         /* 0:0:0 did not support /keys cherry picking */
         TALER_LOG_DEBUG ("Skipping denomination key: already know it\n");
-        GNUNET_CRYPTO_rsa_public_key_free (dk.key.rsa_public_key);
+        TALER_denom_pub_free (&dk.key);
         continue;
       }
       if (key_data->denom_keys_size == key_data->num_denom_keys)
@@ -951,7 +943,7 @@ decode_keys_json (const json_t *resp_obj,
       EXITIF (JSON_ARRAY != json_typeof (recoup_array));
 
       json_array_foreach (recoup_array, index, recoup_info) {
-        struct GNUNET_HashCode h_denom_pub;
+        struct TALER_DenominationHash h_denom_pub;
         struct GNUNET_JSON_Specification spec[] = {
           GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
                                        &h_denom_pub),
@@ -1019,8 +1011,7 @@ free_key_data (struct TALER_EXCHANGE_Keys *key_data)
                      key_data->num_sign_keys,
                      0);
   for (unsigned int i = 0; i<key_data->num_denom_keys; i++)
-    GNUNET_CRYPTO_rsa_public_key_free (
-      key_data->denom_keys[i].key.rsa_public_key);
+    TALER_denom_pub_free (&key_data->denom_keys[i].key);
 
   GNUNET_array_grow (key_data->denom_keys,
                      key_data->denom_keys_size,
@@ -1167,9 +1158,8 @@ keys_completed_cb (void *cls,
                                             TALER_EXCHANGE_DenomPublicKey));
 
     for (unsigned int i = 0; i<kd_old.num_denom_keys; i++)
-      kd.denom_keys[i].key.rsa_public_key
-        = GNUNET_CRYPTO_rsa_public_key_dup (
-            kd_old.denom_keys[i].key.rsa_public_key);
+      TALER_denom_pub_deep_copy (&kd.denom_keys[i].key,
+                                 &kd_old.denom_keys[i].key);
 
     kd.num_auditors = kd_old.num_auditors;
     kd.auditors = GNUNET_new_array (kd.num_auditors,
@@ -1216,7 +1206,7 @@ keys_completed_cb (void *cls,
       kd.auditors = NULL;
       kd.num_auditors = 0;
       for (unsigned int i = 0; i<kd_old.num_denom_keys; i++)
-        GNUNET_CRYPTO_rsa_public_key_free 
(kd.denom_keys[i].key.rsa_public_key);
+        TALER_denom_pub_free (&kd.denom_keys[i].key);
       GNUNET_array_grow (kd.denom_keys,
                          kd.denom_keys_size,
                          0);
@@ -1683,8 +1673,8 @@ TALER_EXCHANGE_serialize_data (struct 
TALER_EXCHANGE_Handle *exchange)
                               &dk->fee_refund),
       GNUNET_JSON_pack_data_auto ("master_sig",
                                   &dk->master_sig),
-      TALER_JSON_pack_denomination_public_key ("denom_pub",
-                                               &dk->key));
+      TALER_JSON_pack_denom_pub ("denom_pub",
+                                 &dk->key));
     GNUNET_assert (0 ==
                    json_array_append_new (denoms,
                                           denom));
@@ -2010,7 +2000,7 @@ TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle 
*exchange)
  * @param pub claimed current online signing key for the exchange
  * @return #GNUNET_OK if @a pub is (according to /keys) a current signing key
  */
-int
+enum GNUNET_GenericReturnValue
 TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys,
                                  const struct TALER_ExchangePublicKeyP *pub)
 {
@@ -2060,9 +2050,9 @@ TALER_EXCHANGE_get_denomination_key (
   const struct TALER_DenominationPublicKey *pk)
 {
   for (unsigned int i = 0; i<keys->num_denom_keys; i++)
-    if (0 == GNUNET_CRYPTO_rsa_public_key_cmp (pk->rsa_public_key,
-                                               keys->denom_keys[i].key.
-                                               rsa_public_key))
+    if (0 ==
+        TALER_denom_pub_cmp (pk,
+                             &keys->denom_keys[i].key))
       return &keys->denom_keys[i];
   return NULL;
 }
@@ -2082,9 +2072,8 @@ TALER_EXCHANGE_copy_denomination_key (
 
   copy = GNUNET_new (struct TALER_EXCHANGE_DenomPublicKey);
   *copy = *key;
-  copy->key.rsa_public_key = GNUNET_CRYPTO_rsa_public_key_dup (
-    key->key.rsa_public_key);
-
+  TALER_denom_pub_deep_copy (&copy->key,
+                             &key->key);
   return copy;
 }
 
@@ -2099,7 +2088,7 @@ void
 TALER_EXCHANGE_destroy_denomination_key (
   struct TALER_EXCHANGE_DenomPublicKey *key)
 {
-  GNUNET_CRYPTO_rsa_public_key_free (key->key.rsa_public_key);;
+  TALER_denom_pub_free (&key->key);
   GNUNET_free (key);
 }
 
@@ -2114,7 +2103,7 @@ TALER_EXCHANGE_destroy_denomination_key (
 const struct TALER_EXCHANGE_DenomPublicKey *
 TALER_EXCHANGE_get_denomination_key_by_hash (
   const struct TALER_EXCHANGE_Keys *keys,
-  const struct GNUNET_HashCode *hc)
+  const struct TALER_DenominationHash *hc)
 {
   for (unsigned int i = 0; i<keys->num_denom_keys; i++)
     if (0 == GNUNET_memcmp (hc,
diff --git a/src/lib/exchange_api_kyc_check.c b/src/lib/exchange_api_kyc_check.c
index 82fddd45..f64dfe4e 100644
--- a/src/lib/exchange_api_kyc_check.c
+++ b/src/lib/exchange_api_kyc_check.c
@@ -64,7 +64,7 @@ struct TALER_EXCHANGE_KycCheckHandle
   /**
    * Hash of the payto:// URL that is being KYC'ed.
    */
-  struct GNUNET_HashCode h_payto;
+  struct TALER_PaytoHash h_payto;
 };
 
 
@@ -216,7 +216,7 @@ handle_kyc_check_finished (void *cls,
 struct TALER_EXCHANGE_KycCheckHandle *
 TALER_EXCHANGE_kyc_check (struct TALER_EXCHANGE_Handle *exchange,
                           uint64_t payment_target,
-                          const struct GNUNET_HashCode *h_payto,
+                          const struct TALER_PaytoHash *h_payto,
                           struct GNUNET_TIME_Relative timeout,
                           TALER_EXCHANGE_KycStatusCallback cb,
                           void *cb_cls)
diff --git a/src/lib/exchange_api_kyc_proof.c b/src/lib/exchange_api_kyc_proof.c
new file mode 100644
index 00000000..f8e84d7c
--- /dev/null
+++ b/src/lib/exchange_api_kyc_proof.c
@@ -0,0 +1,213 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2021 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/exchange_api_kyc_proof.c
+ * @brief Implementation of the /kyc-proof request
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <microhttpd.h> /* just for HTTP proof codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_exchange_service.h"
+#include "taler_json_lib.h"
+#include "exchange_api_handle.h"
+#include "taler_signatures.h"
+#include "exchange_api_curl_defaults.h"
+
+
+/**
+ * @brief A ``/kyc-proof`` handle
+ */
+struct TALER_EXCHANGE_KycProofHandle
+{
+
+  /**
+   * The connection to exchange this request handle will use
+   */
+  struct TALER_EXCHANGE_Handle *exchange;
+
+  /**
+   * The url for this request.
+   */
+  char *url;
+
+  /**
+   * Handle to our CURL request.
+   */
+  CURL *eh;
+
+  /**
+   * Handle for the request.
+   */
+  struct GNUNET_CURL_Job *job;
+
+  /**
+   * Function to call with the result.
+   */
+  TALER_EXCHANGE_KycProofCallback cb;
+
+  /**
+   * Closure for @e cb.
+   */
+  void *cb_cls;
+
+};
+
+
+/**
+ * Function called when we're done processing the
+ * HTTP /kyc-proof request.
+ *
+ * @param cls the `struct TALER_EXCHANGE_KycProofHandle`
+ * @param response_code HTTP response code, 0 on error
+ * @param body response body
+ * @param body_size number of bytes in @a body
+ */
+static void
+handle_kyc_proof_finished (void *cls,
+                           long response_code,
+                           const void *body,
+                           size_t body_size)
+{
+  struct TALER_EXCHANGE_KycProofHandle *kph = cls;
+  struct TALER_EXCHANGE_KycProofResponse kpr = {
+    .http_status = (unsigned int) response_code
+  };
+
+  kph->job = NULL;
+  switch (response_code)
+  {
+  case 0:
+    break;
+  case MHD_HTTP_SEE_OTHER:
+    {
+      char *redirect_url;
+
+      GNUNET_assert (CURLE_OK ==
+                     curl_easy_getinfo (kph->eh,
+                                        CURLINFO_REDIRECT_URL,
+                                        &redirect_url));
+      kpr.details.found.redirect_url = redirect_url;
+      break;
+    }
+  case MHD_HTTP_BAD_REQUEST:
+    /* This should never happen, either us or the exchange is buggy
+       (or API version conflict); just pass JSON reply to the application */
+    break;
+  case MHD_HTTP_UNAUTHORIZED:
+    break;
+  case MHD_HTTP_FORBIDDEN:
+    break;
+  case MHD_HTTP_NOT_FOUND:
+    break;
+  case MHD_HTTP_BAD_GATEWAY:
+    /* Server had an internal issue; we should retry, but this API
+       leaves this to the application */
+    break;
+  case MHD_HTTP_GATEWAY_TIMEOUT:
+    /* Server had an internal issue; we should retry, but this API
+       leaves this to the application */
+    break;
+  default:
+    /* unexpected response code */
+    GNUNET_break_op (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u for exchange kyc_proof\n",
+                (unsigned int) response_code);
+    break;
+  }
+  kph->cb (kph->cb_cls,
+           &kpr);
+  TALER_EXCHANGE_kyc_proof_cancel (kph);
+}
+
+
+struct TALER_EXCHANGE_KycProofHandle *
+TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *exchange,
+                          uint64_t payment_target,
+                          const char *code,
+                          const char *state,
+                          TALER_EXCHANGE_KycProofCallback cb,
+                          void *cb_cls)
+{
+  struct TALER_EXCHANGE_KycProofHandle *kph;
+  struct GNUNET_CURL_Context *ctx;
+  char *arg_str;
+
+  if (GNUNET_YES !=
+      TEAH_handle_is_ready (exchange))
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  /* TODO: any escaping of code/state needed??? */
+  GNUNET_asprintf (&arg_str,
+                   "/kyc-proof/%llu?code=%s&state=%s",
+                   (unsigned long long) payment_target,
+                   code,
+                   state);
+  kph = GNUNET_new (struct TALER_EXCHANGE_KycProofHandle);
+  kph->exchange = exchange;
+  kph->cb = cb;
+  kph->cb_cls = cb_cls;
+  kph->url = TEAH_path_to_url (exchange,
+                               arg_str);
+  GNUNET_free (arg_str);
+  if (NULL == kph->url)
+  {
+    GNUNET_free (kph);
+    return NULL;
+  }
+  kph->eh = TALER_EXCHANGE_curl_easy_get_ (kph->url);
+  if (NULL == kph->eh)
+  {
+    GNUNET_break (0);
+    GNUNET_free (kph->url);
+    GNUNET_free (kph);
+    return NULL;
+  }
+  /* disable location following, we want to learn the
+     result of a 303 redirect! */
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (kph->eh,
+                                   CURLOPT_FOLLOWLOCATION,
+                                   0L));
+  ctx = TEAH_handle_to_context (exchange);
+  kph->job = GNUNET_CURL_job_add_raw (ctx,
+                                      kph->eh,
+                                      NULL,
+                                      &handle_kyc_proof_finished,
+                                      kph);
+  return kph;
+}
+
+
+void
+TALER_EXCHANGE_kyc_proof_cancel (struct TALER_EXCHANGE_KycProofHandle *kph)
+{
+  if (NULL != kph->job)
+  {
+    GNUNET_CURL_job_cancel (kph->job);
+    kph->job = NULL;
+  }
+  GNUNET_free (kph->url);
+  GNUNET_free (kph);
+}
+
+
+/* end of exchange_api_kyc_proof.c */
diff --git a/src/lib/exchange_api_kyc_wallet.c 
b/src/lib/exchange_api_kyc_wallet.c
index 16d4253e..4a41fd59 100644
--- a/src/lib/exchange_api_kyc_wallet.c
+++ b/src/lib/exchange_api_kyc_wallet.c
@@ -166,6 +166,7 @@ TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle 
*exchange,
     .purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP)
   };
 
+  /* FIXME: move to util/wallet-signatures.c! */
   GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
                                       &reserve_pub.eddsa_pub);
 
@@ -187,6 +188,7 @@ TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle 
*exchange,
                                "/kyc-wallet");
   if (NULL == kwh->url)
   {
+    json_decref (req);
     GNUNET_free (kwh);
     return NULL;
   }
@@ -207,10 +209,11 @@ TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle 
*exchange,
     return NULL;
   }
   json_decref (req);
-  kwh->job = GNUNET_CURL_job_add (ctx,
-                                  eh,
-                                  &handle_kyc_wallet_finished,
-                                  kwh);
+  kwh->job = GNUNET_CURL_job_add2 (ctx,
+                                   eh,
+                                   kwh->ctx.headers,
+                                   &handle_kyc_wallet_finished,
+                                   kwh);
   return kwh;
 }
 
diff --git a/src/lib/exchange_api_link.c b/src/lib/exchange_api_link.c
index ceb31884..a9dc8852 100644
--- a/src/lib/exchange_api_link.c
+++ b/src/lib/exchange_api_link.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2015-2020 Taler Systems SA
+  Copyright (C) 2015-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -91,13 +91,16 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
                  struct TALER_DenominationSignature *sig,
                  struct TALER_DenominationPublicKey *pub)
 {
-  struct GNUNET_CRYPTO_RsaSignature *bsig;
-  struct GNUNET_CRYPTO_RsaPublicKey *rpub;
+  struct TALER_BlindedDenominationSignature bsig;
+  struct TALER_DenominationPublicKey rpub;
   struct TALER_CoinSpendSignatureP link_sig;
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_rsa_public_key ("denom_pub", &rpub),
-    GNUNET_JSON_spec_rsa_signature ("ev_sig", &bsig),
-    GNUNET_JSON_spec_fixed_auto ("link_sig", &link_sig),
+    TALER_JSON_spec_denom_pub ("denom_pub",
+                               &rpub),
+    TALER_JSON_spec_blinded_denom_sig ("ev_sig",
+                                       &bsig),
+    GNUNET_JSON_spec_fixed_auto ("link_sig",
+                                 &link_sig),
     GNUNET_JSON_spec_end ()
   };
   struct TALER_TransferSecretP secret;
@@ -120,22 +123,26 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle 
*lh,
                                 &fc);
 
   /* extract coin and signature */
+  if (GNUNET_OK !=
+      TALER_denom_sig_unblind (sig,
+                               &bsig,
+                               &fc.blinding_key,
+                               &rpub))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
   *coin_priv = fc.coin_priv;
-  sig->rsa_signature
-    = TALER_rsa_unblind (bsig,
-                         &fc.blinding_key.bks,
-                         rpub);
   /* verify link_sig */
   {
     struct TALER_PlanchetDetail pd;
-    struct GNUNET_HashCode c_hash;
+    struct TALER_CoinPubHash c_hash;
     struct TALER_CoinSpendPublicKeyP old_coin_pub;
 
     GNUNET_CRYPTO_eddsa_key_get_public (&lh->coin_priv.eddsa_priv,
                                         &old_coin_pub.eddsa_pub);
-    pub->rsa_public_key = rpub;
     if (GNUNET_OK !=
-        TALER_planchet_prepare (pub,
+        TALER_planchet_prepare (&rpub,
                                 &fc,
                                 &c_hash,
                                 &pd))
@@ -161,7 +168,8 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
   }
 
   /* clean up */
-  pub->rsa_public_key = GNUNET_CRYPTO_rsa_public_key_dup (rpub);
+  TALER_denom_pub_deep_copy (pub,
+                             &rpub);
   GNUNET_JSON_parse_free (spec);
   return GNUNET_OK;
 }
@@ -323,10 +331,8 @@ parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
     GNUNET_assert (off_coin <= num_coins);
     for (i = 0; i<off_coin; i++)
     {
-      if (NULL != sigs[i].rsa_signature)
-        GNUNET_CRYPTO_rsa_signature_free (sigs[i].rsa_signature);
-      if (NULL != pubs[i].rsa_public_key)
-        GNUNET_CRYPTO_rsa_public_key_free (pubs[i].rsa_public_key);
+      TALER_denom_sig_free (&sigs[i]);
+      TALER_denom_pub_free (&pubs[i]);
     }
   }
   return ret;
diff --git a/src/lib/exchange_api_management_get_keys.c 
b/src/lib/exchange_api_management_get_keys.c
index e9cab581..98083679 100644
--- a/src/lib/exchange_api_management_get_keys.c
+++ b/src/lib/exchange_api_management_get_keys.c
@@ -179,8 +179,8 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle 
*gh,
                                      &denom_key->expire_deposit),
       TALER_JSON_spec_absolute_time ("stamp_expire_legal",
                                      &denom_key->expire_legal),
-      GNUNET_JSON_spec_rsa_public_key ("denom_pub",
-                                       &denom_key->key.rsa_public_key),
+      TALER_JSON_spec_denom_pub ("denom_pub",
+                                 &denom_key->key),
       TALER_JSON_spec_amount_any ("fee_withdraw",
                                   &denom_key->fee_withdraw),
       TALER_JSON_spec_amount_any ("fee_deposit",
@@ -212,20 +212,20 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle 
*gh,
     }
 
     {
+      struct TALER_DenominationHash h_denom_pub;
       struct GNUNET_TIME_Relative duration
         = GNUNET_TIME_absolute_get_difference (denom_key->valid_from,
                                                
denom_key->withdraw_valid_until);
-      struct GNUNET_HashCode h_denom_pub;
 
-      GNUNET_CRYPTO_rsa_public_key_hash (denom_key->key.rsa_public_key,
-                                         &h_denom_pub);
+      TALER_denom_pub_hash (&denom_key->key,
+                            &h_denom_pub);
       if (GNUNET_OK !=
-          TALER_exchange_secmod_rsa_verify (&h_denom_pub,
-                                            section_name,
-                                            denom_key->valid_from,
-                                            duration,
-                                            &fk.denom_secmod_public_key,
-                                            &denom_key->denom_secmod_sig))
+          TALER_exchange_secmod_denom_verify (&h_denom_pub,
+                                              section_name,
+                                              denom_key->valid_from,
+                                              duration,
+                                              &fk.denom_secmod_public_key,
+                                              &denom_key->denom_secmod_sig))
       {
         GNUNET_break_op (0);
         ok = false;
@@ -246,14 +246,7 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle 
*gh,
             &fk);
   }
   for (unsigned int i = 0; i<fk.num_denom_keys; i++)
-  {
-    if (NULL != fk.denom_keys[i].key.rsa_public_key)
-    {
-      GNUNET_CRYPTO_rsa_public_key_free (
-        fk.denom_keys[i].key.rsa_public_key);
-      fk.denom_keys[i].key.rsa_public_key = NULL;
-    }
-  }
+    TALER_denom_pub_free (&fk.denom_keys[i].key);
   GNUNET_free (fk.sign_keys);
   GNUNET_free (fk.denom_keys);
   GNUNET_JSON_parse_free (spec);
diff --git a/src/lib/exchange_api_management_revoke_denomination_key.c 
b/src/lib/exchange_api_management_revoke_denomination_key.c
index b9e2a556..4a1a79d0 100644
--- a/src/lib/exchange_api_management_revoke_denomination_key.c
+++ b/src/lib/exchange_api_management_revoke_denomination_key.c
@@ -125,7 +125,7 @@ struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle 
*
 TALER_EXCHANGE_management_revoke_denomination_key (
   struct GNUNET_CURL_Context *ctx,
   const char *url,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterSignatureP *master_sig,
   TALER_EXCHANGE_ManagementRevokeDenominationKeyCallback cb,
   void *cb_cls)
diff --git a/src/lib/exchange_api_melt.c b/src/lib/exchange_api_melt.c
index dcee66a8..f3032e8b 100644
--- a/src/lib/exchange_api_melt.c
+++ b/src/lib/exchange_api_melt.c
@@ -141,8 +141,8 @@ verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle 
*mh,
 
   /* verify signature by exchange */
   confirm.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT);
-  confirm.purpose.size = htonl (sizeof (struct
-                                        TALER_RefreshMeltConfirmationPS));
+  confirm.purpose.size
+    = htonl (sizeof (struct TALER_RefreshMeltConfirmationPS));
   confirm.rc = mh->md->rc;
   confirm.noreveal_index = htonl (*noreveal_index);
   if (GNUNET_OK !=
@@ -167,14 +167,14 @@ verify_melt_signature_ok (struct 
TALER_EXCHANGE_MeltHandle *mh,
  * @param json json reply with the signature(s) and transaction history
  * @return #GNUNET_OK if the signature(s) is valid, #GNUNET_SYSERR if not
  */
-static int
+static enum GNUNET_GenericReturnValue
 verify_melt_signature_denom_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
                                       const json_t *json)
 
 {
   json_t *history;
   struct TALER_Amount total;
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   memset (&h_denom_pub,
           0,
@@ -226,7 +226,7 @@ verify_melt_signature_spend_conflict (struct 
TALER_EXCHANGE_MeltHandle *mh,
   };
   const struct MeltedCoin *mc;
   enum TALER_ErrorCode ec;
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /* parse JSON reply */
   if (GNUNET_OK !=
@@ -451,8 +451,7 @@ handle_melt_finished (void *cls,
 
 struct TALER_EXCHANGE_MeltHandle *
 TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
-                     size_t refresh_data_length,
-                     const char *refresh_data,
+                     const json_t *refresh_data,
                      TALER_EXCHANGE_MeltCallback melt_cb,
                      void *melt_cb_cls)
 {
@@ -473,7 +472,7 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
   GNUNET_assert (GNUNET_YES ==
                  TEAH_handle_is_ready (exchange));
   md = TALER_EXCHANGE_deserialize_melt_data_ (refresh_data,
-                                              refresh_data_length);
+                                              exchange->key_data.currency);
   if (NULL == md)
   {
     GNUNET_break (0);
@@ -486,8 +485,8 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
                      &md->melted_coin.fee_melt);
   GNUNET_CRYPTO_eddsa_key_get_public (&md->melted_coin.coin_priv.eddsa_priv,
                                       &melt.coin_pub.eddsa_pub);
-  GNUNET_CRYPTO_rsa_public_key_hash (md->melted_coin.pub_key.rsa_public_key,
-                                     &melt.h_denom_pub);
+  TALER_denom_pub_hash (&md->melted_coin.pub_key,
+                        &melt.h_denom_pub);
   GNUNET_CRYPTO_eddsa_sign (&md->melted_coin.coin_priv.eddsa_priv,
                             &melt,
                             &confirm_sig.eddsa_signature);
@@ -496,8 +495,8 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange,
                                 &melt.coin_pub),
     GNUNET_JSON_pack_data_auto ("denom_pub_hash",
                                 &melt.h_denom_pub),
-    TALER_JSON_pack_denomination_signature ("denom_sig",
-                                            &md->melted_coin.sig),
+    TALER_JSON_pack_denom_sig ("denom_sig",
+                               &md->melted_coin.sig),
     GNUNET_JSON_pack_data_auto ("confirm_sig",
                                 &confirm_sig),
     TALER_JSON_pack_amount ("value_with_fee",
@@ -529,8 +528,10 @@ TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle 
*exchange,
   mh->exchange = exchange;
   mh->coin_pub = melt.coin_pub;
   mh->dki = *dki;
-  mh->dki.key.rsa_public_key = NULL; /* lifetime not warranted, so better
-                                         not copy the pointer */
+  memset (&mh->dki.key,
+          0,
+          sizeof (mh->dki.key)); /* lifetime not warranted, so better
+                                    not copy the pointers */
   mh->melt_cb = melt_cb;
   mh->melt_cb_cls = melt_cb_cls;
   mh->md = md;
diff --git a/src/lib/exchange_api_recoup.c b/src/lib/exchange_api_recoup.c
index 09d99b23..d61e7eff 100644
--- a/src/lib/exchange_api_recoup.c
+++ b/src/lib/exchange_api_recoup.c
@@ -187,7 +187,7 @@ handle_recoup_finished (void *cls,
       /* Insufficient funds, proof attached */
       json_t *history;
       struct TALER_Amount total;
-      struct GNUNET_HashCode h_denom_pub;
+      struct TALER_DenominationHash h_denom_pub;
       const struct TALER_EXCHANGE_DenomPublicKey *dki;
       enum TALER_ErrorCode ec;
 
@@ -313,7 +313,7 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle 
*exchange,
   struct GNUNET_CURL_Context *ctx;
   struct TALER_RecoupRequestPS pr;
   struct TALER_CoinSpendSignatureP coin_sig;
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
   json_t *recoup_obj;
   CURL *eh;
   char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32];
@@ -324,8 +324,8 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle 
*exchange,
   pr.purpose.size = htonl (sizeof (struct TALER_RecoupRequestPS));
   GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
                                       &pr.coin_pub.eddsa_pub);
-  GNUNET_CRYPTO_rsa_public_key_hash (pk->key.rsa_public_key,
-                                     &h_denom_pub);
+  TALER_denom_pub_hash (&pk->key,
+                        &h_denom_pub);
   pr.h_denom_pub = pk->h_key;
   pr.coin_blind = ps->blinding_key;
   GNUNET_CRYPTO_eddsa_sign (&ps->coin_priv.eddsa_priv,
@@ -334,8 +334,8 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle 
*exchange,
   recoup_obj = GNUNET_JSON_PACK (
     GNUNET_JSON_pack_data_auto ("denom_pub_hash",
                                 &h_denom_pub),
-    TALER_JSON_pack_denomination_signature ("denom_sig",
-                                            denom_sig),
+    TALER_JSON_pack_denom_sig ("denom_sig",
+                               denom_sig),
     GNUNET_JSON_pack_data_auto ("coin_sig",
                                 &coin_sig),
     GNUNET_JSON_pack_data_auto ("coin_blind_key_secret",
@@ -362,7 +362,9 @@ TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle 
*exchange,
   ph->coin_pub = pr.coin_pub;
   ph->exchange = exchange;
   ph->pk = *pk;
-  ph->pk.key.rsa_public_key = NULL; /* zero out, as lifetime cannot be 
warranted */
+  memset (&ph->pk.key,
+          0,
+          sizeof (ph->pk.key)); /* zero out, as lifetime cannot be warranted */
   ph->cb = recoup_cb;
   ph->cb_cls = recoup_cb_cls;
   ph->url = TEAH_path_to_url (exchange,
diff --git a/src/lib/exchange_api_refresh_common.c 
b/src/lib/exchange_api_refresh_common.c
index 00d01e4e..520c80fd 100644
--- a/src/lib/exchange_api_refresh_common.c
+++ b/src/lib/exchange_api_refresh_common.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2015-2020 Taler Systems SA
+  Copyright (C) 2015-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -32,22 +32,11 @@
 static void
 free_melted_coin (struct MeltedCoin *mc)
 {
-  if (NULL != mc->pub_key.rsa_public_key)
-    GNUNET_CRYPTO_rsa_public_key_free (mc->pub_key.rsa_public_key);
-  if (NULL != mc->sig.rsa_signature)
-    GNUNET_CRYPTO_rsa_signature_free (mc->sig.rsa_signature);
+  TALER_denom_pub_free (&mc->pub_key);
+  TALER_denom_sig_free (&mc->sig);
 }
 
 
-/**
- * Free all information associated with a melting session.  Note
- * that we allow the melting session to be only partially initialized,
- * as we use this function also when freeing melt data that was not
- * fully initialized (i.e. due to failures in 
#TALER_EXCHANGE_deserialize_melt_data_()).
- *
- * @param md melting data to release, the pointer itself is NOT
- *           freed (as it is typically not allocated by itself)
- */
 void
 TALER_EXCHANGE_free_melt_data_ (struct MeltData *md)
 {
@@ -55,11 +44,9 @@ TALER_EXCHANGE_free_melt_data_ (struct MeltData *md)
   if (NULL != md->fresh_pks)
   {
     for (unsigned int i = 0; i<md->num_fresh_coins; i++)
-      if (NULL != md->fresh_pks[i].rsa_public_key)
-        GNUNET_CRYPTO_rsa_public_key_free (md->fresh_pks[i].rsa_public_key);
+      TALER_denom_pub_free (&md->fresh_pks[i]);
     GNUNET_free (md->fresh_pks);
   }
-
   for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
     GNUNET_free (md->fresh_coins[i]);
   /* Finally, clean up a bit... */
@@ -72,63 +59,40 @@ TALER_EXCHANGE_free_melt_data_ (struct MeltData *md)
  * Serialize information about a coin we are melting.
  *
  * @param mc information to serialize
- * @param buf buffer to write data in, NULL to just compute
- *            required size
- * @param off offeset at @a buf to use
- * @return number of bytes written to @a buf at @a off, or if
- *        @a buf is NULL, number of bytes required; 0 on error
+ * @return NULL on error
  */
-static size_t
-serialize_melted_coin (const struct MeltedCoin *mc,
-                       char *buf,
-                       size_t off)
+static json_t *
+serialize_melted_coin (const struct MeltedCoin *mc)
 {
-  struct MeltedCoinP mcp;
-  void *pbuf;
-  size_t pbuf_size;
-  void *sbuf;
-  size_t sbuf_size;
+  json_t *tprivs;
 
-  sbuf_size = GNUNET_CRYPTO_rsa_signature_encode (mc->sig.rsa_signature,
-                                                  &sbuf);
-  pbuf_size = GNUNET_CRYPTO_rsa_public_key_encode (mc->pub_key.rsa_public_key,
-                                                   &pbuf);
-  if (NULL == buf)
-  {
-    GNUNET_free (sbuf);
-    GNUNET_free (pbuf);
-    return sizeof (struct MeltedCoinP) + sbuf_size + pbuf_size;
-  }
-  if ( (sbuf_size > UINT16_MAX) ||
-       (pbuf_size > UINT16_MAX) )
-  {
-    GNUNET_break (0);
-    return 0;
-  }
-  mcp.coin_priv = mc->coin_priv;
-  TALER_amount_hton (&mcp.melt_amount_with_fee,
-                     &mc->melt_amount_with_fee);
-  TALER_amount_hton (&mcp.fee_melt,
-                     &mc->fee_melt);
-  TALER_amount_hton (&mcp.original_value,
-                     &mc->original_value);
+  tprivs = json_array ();
+  GNUNET_assert (NULL != tprivs);
   for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
-    mcp.transfer_priv[i] = mc->transfer_priv[i];
-  mcp.expire_deposit = GNUNET_TIME_absolute_hton (mc->expire_deposit);
-  mcp.pbuf_size = htons ((uint16_t) pbuf_size);
-  mcp.sbuf_size = htons ((uint16_t) sbuf_size);
-  memcpy (&buf[off],
-          &mcp,
-          sizeof (struct MeltedCoinP));
-  memcpy (&buf[off + sizeof (struct MeltedCoinP)],
-          pbuf,
-          pbuf_size);
-  memcpy (&buf[off + sizeof (struct MeltedCoinP) + pbuf_size],
-          sbuf,
-          sbuf_size);
-  GNUNET_free (sbuf);
-  GNUNET_free (pbuf);
-  return sizeof (struct MeltedCoinP) + sbuf_size + pbuf_size;
+    GNUNET_assert (0 ==
+                   json_array_append_new (
+                     tprivs,
+                     GNUNET_JSON_PACK (
+                       GNUNET_JSON_pack_data_auto (
+                         "transfer_priv",
+                         &mc->transfer_priv[i]))));
+  return GNUNET_JSON_PACK (
+    GNUNET_JSON_pack_data_auto ("coin_priv",
+                                &mc->coin_priv),
+    TALER_JSON_pack_denom_sig ("denom_sig",
+                               &mc->sig),
+    TALER_JSON_pack_denom_pub ("denom_pub",
+                               &mc->pub_key),
+    TALER_JSON_pack_amount ("melt_amount_with_fee",
+                            &mc->melt_amount_with_fee),
+    TALER_JSON_pack_amount ("original_value",
+                            &mc->original_value),
+    TALER_JSON_pack_amount ("melt_fee",
+                            &mc->fee_melt),
+    GNUNET_JSON_pack_time_abs ("expire_deposit",
+                               mc->expire_deposit),
+    GNUNET_JSON_pack_array_steal ("transfer_privs",
+                                  tprivs));
 }
 
 
@@ -136,315 +100,231 @@ serialize_melted_coin (const struct MeltedCoin *mc,
  * Deserialize information about a coin we are melting.
  *
  * @param[out] mc information to deserialize
- * @param buf buffer to read data from
- * @param size number of bytes available at @a buf to use
- * @param[out] ok set to #GNUNET_NO to report errors
- * @return number of bytes read from @a buf, 0 on error
+ * @param currency expected currency
+ * @param in JSON object to read data from
+ * @return #GNUNET_NO to report errors
  */
-static size_t
+static enum GNUNET_GenericReturnValue
 deserialize_melted_coin (struct MeltedCoin *mc,
-                         const char *buf,
-                         size_t size,
-                         int *ok)
+                         const char *currency,
+                         const json_t *in)
 {
-  struct MeltedCoinP mcp;
-  size_t pbuf_size;
-  size_t sbuf_size;
-  size_t off;
-
-  if (size < sizeof (struct MeltedCoinP))
+  json_t *trans_privs;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_fixed_auto ("coin_priv",
+                                 &mc->coin_priv),
+    TALER_JSON_spec_denom_sig ("denom_sig",
+                               &mc->sig),
+    TALER_JSON_spec_denom_pub ("denom_pub",
+                               &mc->pub_key),
+    TALER_JSON_spec_amount ("melt_amount_with_fee",
+                            currency,
+                            &mc->melt_amount_with_fee),
+    TALER_JSON_spec_amount ("original_value",
+                            currency,
+                            &mc->original_value),
+    TALER_JSON_spec_amount ("melt_fee",
+                            currency,
+                            &mc->fee_melt),
+    TALER_JSON_spec_absolute_time ("expire_deposit",
+                                   &mc->expire_deposit),
+    GNUNET_JSON_spec_json ("transfer_privs",
+                           &trans_privs),
+    GNUNET_JSON_spec_end ()
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (in,
+                         spec,
+                         NULL, NULL))
   {
-    GNUNET_break (0);
-    *ok = GNUNET_NO;
-    return 0;
+    GNUNET_break_op (0);
+    return GNUNET_NO;
   }
-  memcpy (&mcp,
-          buf,
-          sizeof (struct MeltedCoinP));
-  pbuf_size = ntohs (mcp.pbuf_size);
-  sbuf_size = ntohs (mcp.sbuf_size);
-  if (size < sizeof (struct MeltedCoinP) + pbuf_size + sbuf_size)
+  if (TALER_CNC_KAPPA != json_array_size (trans_privs))
   {
-    GNUNET_break (0);
-    *ok = GNUNET_NO;
-    return 0;
+    GNUNET_JSON_parse_free (spec);
+    GNUNET_break_op (0);
+    return GNUNET_NO;
   }
-  off = sizeof (struct MeltedCoinP);
-  mc->pub_key.rsa_public_key
-    = GNUNET_CRYPTO_rsa_public_key_decode (&buf[off],
-                                           pbuf_size);
-  off += pbuf_size;
-  mc->sig.rsa_signature
-    = GNUNET_CRYPTO_rsa_signature_decode (&buf[off],
-                                          sbuf_size);
-  off += sbuf_size;
-  if ( (NULL == mc->pub_key.rsa_public_key) ||
-       (NULL == mc->sig.rsa_signature) )
+  for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
   {
-    GNUNET_break (0);
-    *ok = GNUNET_NO;
-    return 0;
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_fixed_auto ("transfer_priv",
+                                   &mc->transfer_priv[i]),
+      GNUNET_JSON_spec_end ()
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (json_array_get (trans_privs,
+                                           i),
+                           spec,
+                           NULL, NULL))
+    {
+      GNUNET_break_op (0);
+      GNUNET_JSON_parse_free (spec);
+      return GNUNET_NO;
+    }
   }
-
-  mc->coin_priv = mcp.coin_priv;
-  TALER_amount_ntoh (&mc->melt_amount_with_fee,
-                     &mcp.melt_amount_with_fee);
-  TALER_amount_ntoh (&mc->fee_melt,
-                     &mcp.fee_melt);
-  TALER_amount_ntoh (&mc->original_value,
-                     &mcp.original_value);
-  for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
-    mc->transfer_priv[i] = mcp.transfer_priv[i];
-  mc->expire_deposit = GNUNET_TIME_absolute_ntoh (mcp.expire_deposit);
-  return off;
+  json_decref (trans_privs);
+  return GNUNET_OK;
 }
 
 
 /**
- * Serialize information about a denomination key.
+ * Serialize melt data.
  *
- * @param dk information to serialize
- * @param buf buffer to write data in, NULL to just compute
- *            required size
- * @param off offset at @a buf to use
- * @return number of bytes written to @a buf at @a off (in addition to @a off 
itself), or if
- *        @a buf is NULL, number of bytes required, excluding @a off
+ * @param md data to serialize
+ * @return serialized melt data
  */
-static size_t
-serialize_denomination_key (const struct TALER_DenominationPublicKey *dk,
-                            char *buf,
-                            size_t off)
+static json_t *
+serialize_melt_data (const struct MeltData *md)
 {
-  void *pbuf;
-  size_t pbuf_size;
-  uint32_t be;
+  json_t *fresh_coins;
 
-  pbuf_size = GNUNET_CRYPTO_rsa_public_key_encode (dk->rsa_public_key,
-                                                   &pbuf);
-  if (NULL == buf)
+  fresh_coins = json_array ();
+  GNUNET_assert (NULL != fresh_coins);
+  for (int i = 0; i<md->num_fresh_coins; i++)
   {
-    GNUNET_free (pbuf);
-    return pbuf_size + sizeof (uint32_t);
+    json_t *planchet_secrets;
+
+    planchet_secrets = json_array ();
+    GNUNET_assert (NULL != planchet_secrets);
+    for (unsigned int j = 0; j<TALER_CNC_KAPPA; j++)
+    {
+      json_t *ps;
+
+      ps = GNUNET_JSON_PACK (
+        GNUNET_JSON_pack_data_auto ("ps",
+                                    &md->fresh_coins[j][i]));
+      GNUNET_assert (0 ==
+                     json_array_append (planchet_secrets,
+                                        ps));
+    }
+    GNUNET_assert (0 ==
+                   json_array_append (
+                     fresh_coins,
+                     GNUNET_JSON_PACK (
+                       TALER_JSON_pack_denom_pub ("denom_pub",
+                                                  &md->fresh_pks[i]),
+                       GNUNET_JSON_pack_array_steal ("planchet_secrets",
+                                                     planchet_secrets)))
+                   );
   }
-  be = htonl ((uint32_t) pbuf_size);
-  memcpy (&buf[off],
-          &be,
-          sizeof (uint32_t));
-  memcpy (&buf[off + sizeof (uint32_t)],
-          pbuf,
-          pbuf_size);
-  GNUNET_free (pbuf);
-  return pbuf_size + sizeof (uint32_t);
+  return GNUNET_JSON_PACK (
+    GNUNET_JSON_pack_array_steal ("fresh_coins",
+                                  fresh_coins),
+    GNUNET_JSON_pack_object_steal ("melted_coin",
+                                   serialize_melted_coin (&md->melted_coin)),
+    GNUNET_JSON_pack_data_auto ("rc",
+                                &md->rc));
 }
 
 
-/**
- * Deserialize information about a denomination key.
- *
- * @param[out] dk information to deserialize
- * @param buf buffer to read data from
- * @param size number of bytes available at @a buf to use
- * @param[out] ok set to #GNUNET_NO to report errors
- * @return number of bytes read from @a buf, 0 on error
- */
-static size_t
-deserialize_denomination_key (struct TALER_DenominationPublicKey *dk,
-                              const char *buf,
-                              size_t size,
-                              int *ok)
+struct MeltData *
+TALER_EXCHANGE_deserialize_melt_data_ (const json_t *melt_data,
+                                       const char *currency)
 {
-  size_t pbuf_size;
-  uint32_t be;
-
-  if (size < sizeof (uint32_t))
+  struct MeltData *md = GNUNET_new (struct MeltData);
+  json_t *fresh_coins;
+  json_t *melted_coin;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_fixed_auto ("rc",
+                                 &md->rc),
+    GNUNET_JSON_spec_json ("melted_coin",
+                           &melted_coin),
+    GNUNET_JSON_spec_json ("fresh_coins",
+                           &fresh_coins),
+    GNUNET_JSON_spec_end ()
+  };
+  bool ok;
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (melt_data,
+                         spec,
+                         NULL, NULL))
   {
     GNUNET_break (0);
-    *ok = GNUNET_NO;
-    return 0;
-  }
-  memcpy (&be,
-          buf,
-          sizeof (uint32_t));
-  pbuf_size = ntohl (be);
-  if ( (size < sizeof (uint32_t) + pbuf_size) ||
-       (sizeof (uint32_t) + pbuf_size < pbuf_size) )
-  {
-    GNUNET_break (0);
-    *ok = GNUNET_NO;
-    return 0;
+    GNUNET_JSON_parse_free (spec);
+    GNUNET_free (md);
+    return NULL;
   }
-  dk->rsa_public_key
-    = GNUNET_CRYPTO_rsa_public_key_decode (&buf[sizeof (uint32_t)],
-                                           pbuf_size);
-  if (NULL == dk->rsa_public_key)
+  if (! (json_is_array (fresh_coins) &&
+         json_is_object (melted_coin)) )
   {
     GNUNET_break (0);
-    *ok = GNUNET_NO;
-    return 0;
+    GNUNET_JSON_parse_free (spec);
+    return NULL;
   }
-  return sizeof (uint32_t) + pbuf_size;
-}
-
-
-/**
- * Serialize information about a fresh coin we are generating.
- *
- * @param fc information to serialize
- * @param buf buffer to write data in, NULL to just compute
- *            required size
- * @param off offeset at @a buf to use
- * @return number of bytes written to @a buf at @a off, or if
- *        @a buf is NULL, number of bytes required
- */
-static size_t
-serialize_fresh_coin (const struct TALER_PlanchetSecretsP *fc,
-                      char *buf,
-                      size_t off)
-{
-  if (NULL != buf)
-    memcpy (&buf[off],
-            fc,
-            sizeof (struct TALER_PlanchetSecretsP));
-  return sizeof (struct TALER_PlanchetSecretsP);
-}
-
-
-/**
- * Deserialize information about a fresh coin we are generating.
- *
- * @param[out] fc information to deserialize
- * @param buf buffer to read data from
- * @param size number of bytes available at @a buf to use
- * @param[out] ok set to #GNUNET_NO to report errors
- * @return number of bytes read from @a buf, 0 on error
- */
-static size_t
-deserialize_fresh_coin (struct TALER_PlanchetSecretsP *fc,
-                        const char *buf,
-                        size_t size,
-                        int *ok)
-{
-  if (size < sizeof (struct TALER_PlanchetSecretsP))
+  if (GNUNET_OK !=
+      deserialize_melted_coin (&md->melted_coin,
+                               currency,
+                               melted_coin))
   {
     GNUNET_break (0);
-    *ok = GNUNET_NO;
-    return 0;
-  }
-  memcpy (fc,
-          buf,
-          sizeof (struct TALER_PlanchetSecretsP));
-  return sizeof (struct TALER_PlanchetSecretsP);
-}
-
-
-/**
- * Serialize melt data.
- *
- * @param md data to serialize
- * @param[out] res_size size of buffer returned
- * @return serialized melt data
- */
-static char *
-serialize_melt_data (const struct MeltData *md,
-                     size_t *res_size)
-{
-  size_t size;
-  size_t asize;
-  char *buf;
-
-  size = 0;
-  asize = (size_t) -1; /* make the compiler happy */
-  buf = NULL;
-  /* we do 2 iterations, #1 to determine total size, #2 to
-     actually construct the buffer */
-  do {
-    if (0 == size)
-    {
-      size = sizeof (struct MeltDataP);
-    }
-    else
-    {
-      struct MeltDataP *mdp;
-
-      buf = GNUNET_malloc (size);
-      asize = size; /* just for invariant check later */
-      size = sizeof (struct MeltDataP);
-      mdp = (struct MeltDataP *) buf;
-      mdp->rc = md->rc;
-      mdp->num_fresh_coins = htons (md->num_fresh_coins);
-    }
-    size += serialize_melted_coin (&md->melted_coin,
-                                   buf,
-                                   size);
-    for (unsigned int i = 0; i<md->num_fresh_coins; i++)
-      size += serialize_denomination_key (&md->fresh_pks[i],
-                                          buf,
-                                          size);
-    for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
-      for (unsigned int j = 0; j<md->num_fresh_coins; j++)
-        size += serialize_fresh_coin (&md->fresh_coins[i][j],
-                                      buf,
-                                      size);
-  } while (NULL == buf);
-  GNUNET_assert (size == asize);
-  *res_size = size;
-  return buf;
-}
-
-
-/**
- * Deserialize melt data.
- *
- * @param buf serialized data
- * @param buf_size size of @a buf
- * @return deserialized melt data, NULL on error
- */
-struct MeltData *
-TALER_EXCHANGE_deserialize_melt_data_ (const char *buf,
-                                       size_t buf_size)
-{
-  struct MeltData *md;
-  struct MeltDataP mdp;
-  size_t off;
-  int ok;
-
-  if (buf_size < sizeof (struct MeltDataP))
+    GNUNET_JSON_parse_free (spec);
     return NULL;
-  memcpy (&mdp,
-          buf,
-          sizeof (struct MeltDataP));
-  md = GNUNET_new (struct MeltData);
-  md->rc = mdp.rc;
-  md->num_fresh_coins = ntohs (mdp.num_fresh_coins);
+  }
+  md->num_fresh_coins = json_array_size (fresh_coins);
   md->fresh_pks = GNUNET_new_array (md->num_fresh_coins,
                                     struct TALER_DenominationPublicKey);
   for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
     md->fresh_coins[i] = GNUNET_new_array (md->num_fresh_coins,
                                            struct TALER_PlanchetSecretsP);
-  off = sizeof (struct MeltDataP);
-  ok = GNUNET_YES;
-  off += deserialize_melted_coin (&md->melted_coin,
-                                  &buf[off],
-                                  buf_size - off,
-                                  &ok);
-  for (unsigned int i = 0; (i<md->num_fresh_coins) && (GNUNET_YES == ok); i++)
-    off += deserialize_denomination_key (&md->fresh_pks[i],
-                                         &buf[off],
-                                         buf_size - off,
-                                         &ok);
-
-  for (unsigned int i = 0; i<TALER_CNC_KAPPA; i++)
-    for (unsigned int j = 0; (j<md->num_fresh_coins) && (GNUNET_YES == ok); 
j++)
-      off += deserialize_fresh_coin (&md->fresh_coins[i][j],
-                                     &buf[off],
-                                     buf_size - off,
-                                     &ok);
-  if (off != buf_size)
+  ok = true;
+  for (unsigned int i = 0; i<md->num_fresh_coins; i++)
   {
-    GNUNET_break (0);
-    ok = GNUNET_NO;
+    const json_t *ji = json_array_get (fresh_coins,
+                                       i);
+    json_t *planchet_secrets;
+    struct GNUNET_JSON_Specification ispec[] = {
+      GNUNET_JSON_spec_json ("planchet_secrets",
+                             &planchet_secrets),
+      TALER_JSON_spec_denom_pub ("denom_pub",
+                                 &md->fresh_pks[i]),
+      GNUNET_JSON_spec_end ()
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (ji,
+                           ispec,
+                           NULL, NULL))
+    {
+      GNUNET_break (0);
+      ok = false;
+      break;
+    }
+    if ( (! json_is_array (planchet_secrets)) ||
+         (TALER_CNC_KAPPA != json_array_size (planchet_secrets)) )
+    {
+      GNUNET_break (0);
+      ok = false;
+      break;
+    }
+    for (unsigned int j = 0; j<TALER_CNC_KAPPA; j++)
+    {
+      struct GNUNET_JSON_Specification jspec[] = {
+        GNUNET_JSON_spec_fixed_auto ("ps",
+                                     &md->fresh_coins[j][i]),
+        GNUNET_JSON_spec_end ()
+      };
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (json_array_get (planchet_secrets,
+                                             j),
+                             jspec,
+                             NULL, NULL))
+      {
+        GNUNET_break (0);
+        ok = false;
+        break;
+      }
+    }
+    if (! ok)
+      break;
   }
-  if (GNUNET_YES != ok)
+
+  if (! ok)
   {
     TALER_EXCHANGE_free_melt_data_ (md);
     GNUNET_free (md);
@@ -454,56 +334,17 @@ TALER_EXCHANGE_deserialize_melt_data_ (const char *buf,
 }
 
 
-/**
- * Melt (partially spent) coins to obtain fresh coins that are
- * unlinkable to the original coin(s).  Note that melting more
- * than one coin in a single request will make those coins linkable,
- * so the safest operation only melts one coin at a time.
- *
- * This API is typically used by a wallet.  Note that to ensure that
- * no money is lost in case of hardware failures, this operation does
- * not actually initiate the request. Instead, it generates a buffer
- * which the caller must store before proceeding with the actual call
- * to #TALER_EXCHANGE_melt() that will generate the request.
- *
- * This function does verify that the given request data is internally
- * consistent.  However, the @a melts_sigs are NOT verified.
- *
- * Aside from some non-trivial cryptographic operations that might
- * take a bit of CPU time to complete, this function returns
- * its result immediately and does not start any asynchronous
- * processing.  This function is also thread-safe.
- *
- * @param melt_priv private key of the coin to melt
- * @param melt_amount amount specifying how much
- *                     the coin will contribute to the melt (including fee)
- * @param melt_sig signature affirming the
- *                   validity of the public keys corresponding to the
- *                   @a melt_priv private key
- * @param melt_pk denomination key information
- *                   record corresponding to the @a melt_sig
- *                   validity of the keys
- * @param fresh_pks_len length of the @a pks array
- * @param fresh_pks array of @a pks_len denominations of fresh coins to create
- * @param[out] res_size set to the size of the return value, or 0 on error
- * @return NULL
- *         if the inputs are invalid (i.e. denomination key not with this 
exchange).
- *         Otherwise, pointer to a buffer of @a res_size to store persistently
- *         before proceeding to #TALER_EXCHANGE_melt().
- *         Non-null results should be freed using GNUNET_free().
- */
-char *
+json_t *
 TALER_EXCHANGE_refresh_prepare (
   const struct TALER_CoinSpendPrivateKeyP *melt_priv,
   const struct TALER_Amount *melt_amount,
   const struct TALER_DenominationSignature *melt_sig,
   const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
   unsigned int fresh_pks_len,
-  const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks,
-  size_t *res_size)
+  const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks)
 {
   struct MeltData md;
-  char *buf;
+  json_t *ret;
   struct TALER_Amount total;
   struct TALER_CoinSpendPublicKeyP coin_pub;
   struct TALER_TransferSecretP trans_sec[TALER_CNC_KAPPA];
@@ -512,7 +353,9 @@ TALER_EXCHANGE_refresh_prepare (
   GNUNET_CRYPTO_eddsa_key_get_public (&melt_priv->eddsa_priv,
                                       &coin_pub.eddsa_pub);
   /* build up melt data structure */
-  memset (&md, 0, sizeof (md));
+  memset (&md,
+          0,
+          sizeof (md));
   md.num_fresh_coins = fresh_pks_len;
   md.melted_coin.coin_priv = *melt_priv;
   md.melted_coin.melt_amount_with_fee = *melt_amount;
@@ -523,16 +366,16 @@ TALER_EXCHANGE_refresh_prepare (
   GNUNET_assert (GNUNET_OK ==
                  TALER_amount_set_zero (melt_amount->currency,
                                         &total));
-  md.melted_coin.pub_key.rsa_public_key
-    = GNUNET_CRYPTO_rsa_public_key_dup (melt_pk->key.rsa_public_key);
-  md.melted_coin.sig.rsa_signature
-    = GNUNET_CRYPTO_rsa_signature_dup (melt_sig->rsa_signature);
+  TALER_denom_pub_deep_copy (&md.melted_coin.pub_key,
+                             &melt_pk->key);
+  TALER_denom_sig_deep_copy (&md.melted_coin.sig,
+                             melt_sig);
   md.fresh_pks = GNUNET_new_array (fresh_pks_len,
                                    struct TALER_DenominationPublicKey);
   for (unsigned int i = 0; i<fresh_pks_len; i++)
   {
-    md.fresh_pks[i].rsa_public_key
-      = GNUNET_CRYPTO_rsa_public_key_dup (fresh_pks[i].key.rsa_public_key);
+    TALER_denom_pub_deep_copy (&md.fresh_pks[i],
+                               &fresh_pks[i].key);
     if ( (0 >
           TALER_amount_add (&total,
                             &total,
@@ -579,7 +422,7 @@ TALER_EXCHANGE_refresh_prepare (
       struct TALER_PlanchetSecretsP *fc = &md.fresh_coins[i][j];
       struct TALER_RefreshCoinData *rcd = &rce[i].new_coins[j];
       struct TALER_PlanchetDetail pd;
-      struct GNUNET_HashCode c_hash;
+      struct TALER_CoinPubHash c_hash;
 
       TALER_planchet_setup_refresh (&trans_sec[i],
                                     j,
@@ -608,8 +451,7 @@ TALER_EXCHANGE_refresh_prepare (
                                 &coin_pub,
                                 melt_amount);
   /* finally, serialize everything */
-  buf = serialize_melt_data (&md,
-                             res_size);
+  ret = serialize_melt_data (&md);
   for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
   {
     for (unsigned int j = 0; j < fresh_pks_len; j++)
@@ -617,5 +459,5 @@ TALER_EXCHANGE_refresh_prepare (
     GNUNET_free (rce[i].new_coins);
   }
   TALER_EXCHANGE_free_melt_data_ (&md);
-  return buf;
+  return ret;
 }
diff --git a/src/lib/exchange_api_refresh_common.h 
b/src/lib/exchange_api_refresh_common.h
index 9f2715a1..7b531e70 100644
--- a/src/lib/exchange_api_refresh_common.h
+++ b/src/lib/exchange_api_refresh_common.h
@@ -27,97 +27,6 @@
 #include "taler_signatures.h"
 
 
-/* structures for committing refresh data to disk before doing the
-   network interaction(s) */
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Header of serialized information about a coin we are melting.
- */
-struct MeltedCoinP
-{
-  /**
-   * Private key of the coin.
-   */
-  struct TALER_CoinSpendPrivateKeyP coin_priv;
-
-  /**
-   * Amount this coin contributes to the melt, including fee.
-   */
-  struct TALER_AmountNBO melt_amount_with_fee;
-
-  /**
-   * The applicable fee for withdrawing a coin of this denomination
-   */
-  struct TALER_AmountNBO fee_melt;
-
-  /**
-   * The original value of the coin.
-   */
-  struct TALER_AmountNBO original_value;
-
-  /**
-   * Transfer private keys for each cut-and-choose dimension.
-   */
-  struct TALER_TransferPrivateKeyP transfer_priv[TALER_CNC_KAPPA];
-
-  /**
-   * Timestamp indicating when coins of this denomination become invalid.
-   */
-  struct GNUNET_TIME_AbsoluteNBO expire_deposit;
-
-  /**
-   * Size of the encoded public key that follows.
-   */
-  uint16_t pbuf_size;
-
-  /**
-   * Size of the encoded signature that follows.
-   */
-  uint16_t sbuf_size;
-
-  /* Followed by serializations of:
-     1) struct TALER_DenominationPublicKey pub_key;
-     2) struct TALER_DenominationSignature sig;
-  */
-};
-
-
-/**
- * Header of serialized data about a melt operation, suitable for
- * persisting it on disk.
- */
-struct MeltDataP
-{
-
-  /**
-   * Hash over the melting session.
-   */
-  struct TALER_RefreshCommitmentP rc;
-
-  /**
-   * Number of coins we are melting, in NBO
-   */
-  uint16_t num_melted_coins GNUNET_PACKED;
-
-  /**
-   * Number of coins we are creating, in NBO
-   */
-  uint16_t num_fresh_coins GNUNET_PACKED;
-
-  /* Followed by serializations of:
-     1) struct MeltedCoinP melted_coins[num_melted_coins];
-     2) struct TALER_EXCHANGE_DenomPublicKey fresh_pks[num_fresh_coins];
-     3) TALER_CNC_KAPPA times:
-        3a) struct TALER_PlanchetSecretsP fresh_coins[num_fresh_coins];
-  */
-};
-
-
-GNUNET_NETWORK_STRUCT_END
-
-
 /**
  * Information about a coin we are melting.
  */
@@ -204,13 +113,13 @@ struct MeltData
 /**
  * Deserialize melt data.
  *
- * @param buf serialized data
- * @param buf_size size of @a buf
+ * @param data json data to deserialize
+ * @param currency expected currency for the coins
  * @return deserialized melt data, NULL on error
  */
 struct MeltData *
-TALER_EXCHANGE_deserialize_melt_data_ (const char *buf,
-                                       size_t buf_size);
+TALER_EXCHANGE_deserialize_melt_data_ (const json_t *data,
+                                       const char *currency);
 
 
 /**
@@ -219,7 +128,7 @@ TALER_EXCHANGE_deserialize_melt_data_ (const char *buf,
  * as we use this function also when freeing melt data that was not
  * fully initialized (i.e. due to failures in 
#TALER_EXCHANGE_deserialize_melt_data_()).
  *
- * @param md melting data to release, the pointer itself is NOT
+ * @param[in] md melting data to release, the pointer itself is NOT
  *           freed (as it is typically not allocated by itself)
  */
 void
diff --git a/src/lib/exchange_api_refreshes_reveal.c 
b/src/lib/exchange_api_refreshes_reveal.c
index f54487ae..2b7fcf8c 100644
--- a/src/lib/exchange_api_refreshes_reveal.c
+++ b/src/lib/exchange_api_refreshes_reveal.c
@@ -98,14 +98,15 @@ struct TALER_EXCHANGE_RefreshesRevealHandle
  * @param[out] sigs array of length `num_fresh_coins`, initialized to contain 
RSA signatures
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
  */
-static int
+static enum GNUNET_GenericReturnValue
 refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh,
                    const json_t *json,
                    struct TALER_DenominationSignature *sigs)
 {
   json_t *jsona;
   struct GNUNET_JSON_Specification outer_spec[] = {
-    GNUNET_JSON_spec_json ("ev_sigs", &jsona),
+    GNUNET_JSON_spec_json ("ev_sigs",
+                           &jsona),
     GNUNET_JSON_spec_end ()
   };
 
@@ -136,11 +137,12 @@ refresh_reveal_ok (struct 
TALER_EXCHANGE_RefreshesRevealHandle *rrh,
     const struct TALER_PlanchetSecretsP *fc;
     struct TALER_DenominationPublicKey *pk;
     json_t *jsonai;
-    struct GNUNET_CRYPTO_RsaSignature *blind_sig;
+    struct TALER_BlindedDenominationSignature blind_sig;
     struct TALER_CoinSpendPublicKeyP coin_pub;
-    struct GNUNET_HashCode coin_hash;
+    struct TALER_CoinPubHash coin_hash;
     struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_rsa_signature ("ev_sig", &blind_sig),
+      TALER_JSON_spec_blinded_denom_sig ("ev_sig",
+                                         &blind_sig),
       GNUNET_JSON_spec_end ()
     };
     struct TALER_FreshCoin coin;
@@ -164,22 +166,23 @@ refresh_reveal_ok (struct 
TALER_EXCHANGE_RefreshesRevealHandle *rrh,
        hence recomputing it here... */
     GNUNET_CRYPTO_eddsa_key_get_public (&fc->coin_priv.eddsa_priv,
                                         &coin_pub.eddsa_pub);
-    GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub,
-                        sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
-                        &coin_hash);
+    /* FIXME-Oec: Age commitment hash. */
+    TALER_coin_pub_hash (&coin_pub,
+                         NULL, /* FIXME-Oec */
+                         &coin_hash);
     if (GNUNET_OK !=
         TALER_planchet_to_coin (pk,
-                                blind_sig,
+                                &blind_sig,
                                 fc,
                                 &coin_hash,
                                 &coin))
     {
       GNUNET_break_op (0);
-      GNUNET_CRYPTO_rsa_signature_free (blind_sig);
+      GNUNET_JSON_parse_free (spec);
       GNUNET_JSON_parse_free (outer_spec);
       return GNUNET_SYSERR;
     }
-    GNUNET_CRYPTO_rsa_signature_free (blind_sig);
+    GNUNET_JSON_parse_free (spec);
     sigs[i] = coin.sig;
   }
   GNUNET_JSON_parse_free (outer_spec);
@@ -218,7 +221,9 @@ handle_refresh_reveal_finished (void *cls,
       struct TALER_DenominationSignature sigs[rrh->md->num_fresh_coins];
       int ret;
 
-      memset (sigs, 0, sizeof (sigs));
+      memset (sigs,
+              0,
+              sizeof (sigs));
       ret = refresh_reveal_ok (rrh,
                                j,
                                sigs);
@@ -237,8 +242,7 @@ handle_refresh_reveal_finished (void *cls,
         rrh->reveal_cb = NULL;
       }
       for (unsigned int i = 0; i<rrh->md->num_fresh_coins; i++)
-        if (NULL != sigs[i].rsa_signature)
-          GNUNET_CRYPTO_rsa_signature_free (sigs[i].rsa_signature);
+        TALER_denom_sig_free (&sigs[i]);
       TALER_EXCHANGE_refreshes_reveal_cancel (rrh);
       return;
     }
@@ -290,8 +294,7 @@ handle_refresh_reveal_finished (void *cls,
 struct TALER_EXCHANGE_RefreshesRevealHandle *
 TALER_EXCHANGE_refreshes_reveal (
   struct TALER_EXCHANGE_Handle *exchange,
-  size_t refresh_data_length,
-  const char *refresh_data,
+  const json_t *refresh_data,
   uint32_t noreveal_index,
   TALER_EXCHANGE_RefreshesRevealCallback reveal_cb,
   void *reveal_cb_cls)
@@ -324,7 +327,7 @@ TALER_EXCHANGE_refreshes_reveal (
     return NULL;
   }
   md = TALER_EXCHANGE_deserialize_melt_data_ (refresh_data,
-                                              refresh_data_length);
+                                              exchange->key_data.currency);
   if (NULL == md)
   {
     GNUNET_break (0);
@@ -342,12 +345,12 @@ TALER_EXCHANGE_refreshes_reveal (
   GNUNET_assert (NULL != (link_sigs = json_array ()));
   for (unsigned int i = 0; i<md->num_fresh_coins; i++)
   {
-    struct GNUNET_HashCode denom_hash;
+    struct TALER_DenominationHash denom_hash;
     struct TALER_PlanchetDetail pd;
-    struct GNUNET_HashCode c_hash;
+    struct TALER_CoinPubHash c_hash;
 
-    GNUNET_CRYPTO_rsa_public_key_hash (md->fresh_pks[i].rsa_public_key,
-                                       &denom_hash);
+    TALER_denom_pub_hash (&md->fresh_pks[i],
+                          &denom_hash);
     GNUNET_assert (0 ==
                    json_array_append_new (new_denoms_h,
                                           GNUNET_JSON_from_data_auto (
diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c
index f83a2985..1362a9c2 100644
--- a/src/lib/exchange_api_refund.c
+++ b/src/lib/exchange_api_refund.c
@@ -87,7 +87,7 @@ struct TALER_EXCHANGE_RefundHandle
  * @param[out] exchange_sig set to the exchange's signature
  * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
  */
-static int
+static enum GNUNET_GenericReturnValue
 verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh,
                             const json_t *json,
                             struct TALER_ExchangePublicKeyP *exchange_pub,
@@ -138,7 +138,7 @@ verify_refund_signature_ok (struct 
TALER_EXCHANGE_RefundHandle *rh,
  * @param json json reply with the coin transaction history
  * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
  */
-static int
+static enum GNUNET_GenericReturnValue
 verify_conflict_history_ok (struct TALER_EXCHANGE_RefundHandle *rh,
                             const json_t *json)
 {
@@ -196,29 +196,32 @@ verify_conflict_history_ok (struct 
TALER_EXCHANGE_RefundHandle *rh,
     if (0 == strcasecmp (type,
                          "DEPOSIT"))
     {
-      struct TALER_DepositRequestPS dr = {
-        .purpose.size = htonl (sizeof (dr)),
-        .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
-        .coin_pub = rh->depconf.coin_pub
-      };
+      struct TALER_Amount deposit_fee;
+      struct TALER_MerchantWireHash h_wire;
+      struct TALER_PrivateContractHash h_contract_terms;
+      // struct TALER_ExtensionContractHash h_extensions; // FIXME!
+      struct TALER_DenominationHash h_denom_pub;
+      struct GNUNET_TIME_Absolute wallet_timestamp;
+      struct TALER_MerchantPublicKeyP merchant_pub;
+      struct GNUNET_TIME_Absolute refund_deadline;
       struct TALER_CoinSpendSignatureP sig;
       struct GNUNET_JSON_Specification spec[] = {
         GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                      &sig),
         GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
-                                     &dr.h_contract_terms),
+                                     &h_contract_terms),
         GNUNET_JSON_spec_fixed_auto ("h_wire",
-                                     &dr.h_wire),
+                                     &h_wire),
         GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
-                                     &dr.h_denom_pub),
-        TALER_JSON_spec_absolute_time_nbo ("timestamp",
-                                           &dr.wallet_timestamp),
-        TALER_JSON_spec_absolute_time_nbo ("refund_deadline",
-                                           &dr.refund_deadline),
-        TALER_JSON_spec_amount_any_nbo ("deposit_fee",
-                                        &dr.deposit_fee),
+                                     &h_denom_pub),
+        TALER_JSON_spec_absolute_time ("timestamp",
+                                       &wallet_timestamp),
+        TALER_JSON_spec_absolute_time ("refund_deadline",
+                                       &refund_deadline),
+        TALER_JSON_spec_amount_any ("deposit_fee",
+                                    &deposit_fee),
         GNUNET_JSON_spec_fixed_auto ("merchant_pub",
-                                     &dr.merchant),
+                                     &merchant_pub),
         GNUNET_JSON_spec_end ()
       };
 
@@ -230,21 +233,26 @@ verify_conflict_history_ok (struct 
TALER_EXCHANGE_RefundHandle *rh,
         GNUNET_break_op (0);
         return GNUNET_SYSERR;
       }
-      TALER_amount_hton (&dr.amount_with_fee,
-                         &amount);
       if (GNUNET_OK !=
-          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
-                                      &dr,
-                                      &sig.eddsa_signature,
-                                      &rh->depconf.coin_pub.eddsa_pub))
+          TALER_wallet_deposit_verify (&amount,
+                                       &deposit_fee,
+                                       &h_wire,
+                                       &h_contract_terms,
+                                       NULL /* h_extensions! */,
+                                       &h_denom_pub,
+                                       wallet_timestamp,
+                                       &merchant_pub,
+                                       refund_deadline,
+                                       &rh->depconf.coin_pub,
+                                       &sig))
       {
         GNUNET_break_op (0);
         return GNUNET_SYSERR;
       }
       if ( (0 != GNUNET_memcmp (&rh->depconf.h_contract_terms,
-                                &dr.h_contract_terms)) ||
+                                &h_contract_terms)) ||
            (0 != GNUNET_memcmp (&rh->depconf.merchant,
-                                &dr.merchant)) )
+                                &merchant_pub)) )
       {
         /* deposit information is about a different merchant/contract */
         GNUNET_break_op (0);
@@ -638,7 +646,7 @@ handle_refund_finished (void *cls,
 struct TALER_EXCHANGE_RefundHandle *
 TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange,
                        const struct TALER_Amount *amount,
-                       const struct GNUNET_HashCode *h_contract_terms,
+                       const struct TALER_PrivateContractHash 
*h_contract_terms,
                        const struct TALER_CoinSpendPublicKeyP *coin_pub,
                        uint64_t rtransaction_id,
                        const struct TALER_MerchantPrivateKeyP *merchant_priv,
diff --git a/src/lib/exchange_api_transfers_get.c 
b/src/lib/exchange_api_transfers_get.c
index 1f6e419c..87d654c0 100644
--- a/src/lib/exchange_api_transfers_get.c
+++ b/src/lib/exchange_api_transfers_get.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2020 Taler Systems SA
+  Copyright (C) 2014-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -79,7 +79,7 @@ struct TALER_EXCHANGE_TransfersGetHandle
  * @return #GNUNET_OK if we are done and all is well,
  *         #GNUNET_SYSERR if the response was bogus
  */
-static int
+static enum GNUNET_GenericReturnValue
 check_transfers_get_response_ok (
   struct TALER_EXCHANGE_TransfersGetHandle *wdh,
   const json_t *json)
@@ -92,7 +92,7 @@ check_transfers_get_response_ok (
     TALER_JSON_spec_amount_any ("total", &td.total_amount),
     TALER_JSON_spec_amount_any ("wire_fee", &td.wire_fee),
     GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
-    GNUNET_JSON_spec_fixed_auto ("h_wire", &td.h_wire),
+    GNUNET_JSON_spec_fixed_auto ("h_payto", &td.h_payto),
     TALER_JSON_spec_absolute_time ("execution_time", &td.execution_time),
     GNUNET_JSON_spec_json ("deposits", &details_j),
     GNUNET_JSON_spec_fixed_auto ("exchange_sig", &td.exchange_sig),
@@ -199,7 +199,7 @@ check_transfers_get_response_ok (
           TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
         .purpose.size = htonl (sizeof (wdp)),
         .merchant_pub = merchant_pub,
-        .h_wire = td.h_wire
+        .h_payto = td.h_payto
       };
 
       TALER_amount_hton (&wdp.total,
diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c
index 85b7e7db..5e823ee6 100644
--- a/src/lib/exchange_api_withdraw.c
+++ b/src/lib/exchange_api_withdraw.c
@@ -71,7 +71,7 @@ struct TALER_EXCHANGE_WithdrawHandle
   /**
    * Hash of the public key of the coin we are signing.
    */
-  struct GNUNET_HashCode c_hash;
+  struct TALER_CoinPubHash c_hash;
 
 };
 
@@ -88,7 +88,7 @@ static void
 handle_reserve_withdraw_finished (
   void *cls,
   const struct TALER_EXCHANGE_HttpResponse *hr,
-  const struct GNUNET_CRYPTO_RsaSignature *blind_sig)
+  const struct TALER_BlindedDenominationSignature *blind_sig)
 {
   struct TALER_EXCHANGE_WithdrawHandle *wh = cls;
   struct TALER_EXCHANGE_WithdrawResponse wr = {
@@ -142,7 +142,7 @@ handle_reserve_withdraw_finished (
   wh->cb (wh->cb_cls,
           &wr);
   if (MHD_HTTP_OK == hr->http_status)
-    GNUNET_CRYPTO_rsa_signature_free (wr.details.success.sig.rsa_signature);
+    TALER_denom_sig_free (&wr.details.success.sig);
   TALER_EXCHANGE_withdraw_cancel (wh);
 }
 
@@ -193,8 +193,8 @@ TALER_EXCHANGE_withdraw (
     GNUNET_free (wh);
     return NULL;
   }
-  wh->pk.key.rsa_public_key
-    = GNUNET_CRYPTO_rsa_public_key_dup (pk->key.rsa_public_key);
+  TALER_denom_pub_deep_copy (&wh->pk.key,
+                             &pk->key);
   wh->wh2 = TALER_EXCHANGE_withdraw2 (exchange,
                                       &pd,
                                       reserve_priv,
@@ -205,12 +205,6 @@ TALER_EXCHANGE_withdraw (
 }
 
 
-/**
- * Cancel a withdraw status request.  This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param wh the withdraw sign request handle
- */
 void
 TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh)
 {
@@ -219,6 +213,6 @@ TALER_EXCHANGE_withdraw_cancel (struct 
TALER_EXCHANGE_WithdrawHandle *wh)
     TALER_EXCHANGE_withdraw2_cancel (wh->wh2);
     wh->wh2 = NULL;
   }
-  GNUNET_CRYPTO_rsa_public_key_free (wh->pk.key.rsa_public_key);
+  TALER_denom_pub_free (&wh->pk.key);
   GNUNET_free (wh);
 }
diff --git a/src/lib/exchange_api_withdraw2.c b/src/lib/exchange_api_withdraw2.c
index 330f93d7..d50892e5 100644
--- a/src/lib/exchange_api_withdraw2.c
+++ b/src/lib/exchange_api_withdraw2.c
@@ -99,10 +99,10 @@ static enum GNUNET_GenericReturnValue
 reserve_withdraw_ok (struct TALER_EXCHANGE_Withdraw2Handle *wh,
                      const json_t *json)
 {
-  struct GNUNET_CRYPTO_RsaSignature *blind_sig;
+  struct TALER_BlindedDenominationSignature blind_sig;
   struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_rsa_signature ("ev_sig",
-                                    &blind_sig),
+    TALER_JSON_spec_blinded_denom_sig ("ev_sig",
+                                       &blind_sig),
     GNUNET_JSON_spec_end ()
   };
   struct TALER_EXCHANGE_HttpResponse hr = {
@@ -122,7 +122,7 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_Withdraw2Handle 
*wh,
   /* signature is valid, return it to the application */
   wh->cb (wh->cb_cls,
           &hr,
-          blind_sig);
+          &blind_sig);
   /* make sure callback isn't called again after return */
   wh->cb = NULL;
   GNUNET_JSON_parse_free (spec);
@@ -437,7 +437,7 @@ TALER_EXCHANGE_withdraw2 (
 
     TALER_amount_hton (&req.amount_with_fee,
                        &wh->requested_amount);
-    GNUNET_CRYPTO_hash (pd->coin_ev,
+    TALER_coin_ev_hash (pd->coin_ev,
                         pd->coin_ev_size,
                         &req.h_coin_envelope);
     GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
diff --git a/src/mhd/mhd_responses.c b/src/mhd/mhd_responses.c
index 1e0fd690..5b99dd12 100644
--- a/src/mhd/mhd_responses.c
+++ b/src/mhd/mhd_responses.c
@@ -58,7 +58,6 @@ TALER_MHD_add_global_headers (struct MHD_Response *response)
                                          /* Not available as MHD constant yet 
*/
                                          "Access-Control-Expose-Headers",
                                          "*"));
-
 }
 
 
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
index f558cbcc..43b8374a 100644
--- a/src/pq/pq_query_helper.c
+++ b/src/pq/pq_query_helper.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014, 2015, 2016 Taler Systems SA
+  Copyright (C) 2014, 2015, 2016, 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -70,20 +70,16 @@ qconv_amount_nbo (void *cls,
 }
 
 
-/**
- * Generate query parameter for a currency, consisting of the three
- * components "value", "fraction" and "currency" in this order. The
- * types must be a 64-bit integer, 32-bit integer and a
- * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively.
- *
- * @param x pointer to the query parameter to pass
- * @return array entry for the query parameters to use
- */
 struct GNUNET_PQ_QueryParam
 TALER_PQ_query_param_amount_nbo (const struct TALER_AmountNBO *x)
 {
-  struct GNUNET_PQ_QueryParam res =
-  { &qconv_amount_nbo, NULL, x, sizeof (*x), 2 };
+  struct GNUNET_PQ_QueryParam res = {
+    .conv = &qconv_amount_nbo,
+    .data = x,
+    .size = sizeof (*x),
+    .num_params = 2
+  };
+
   return res;
 }
 
@@ -138,20 +134,283 @@ qconv_amount (void *cls,
 }
 
 
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_amount (const struct TALER_Amount *x)
+{
+  struct GNUNET_PQ_QueryParam res = {
+    .conv = &qconv_amount,
+    .data = x,
+    .size = sizeof (*x),
+    .num_params = 2
+  };
+
+  return res;
+}
+
+
 /**
- * Generate query parameter for a currency, consisting of the three
- * components "value", "fraction" and "currency" in this order. The
- * types must be a 64-bit integer, 32-bit integer and a
- * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively.
+ * Function called to convert input argument into SQL parameters.
  *
- * @param x pointer to the query parameter to pass
- * @return array entry for the query parameters to use
+ * @param cls closure
+ * @param data pointer to input argument
+ * @param data_len number of bytes in @a data (if applicable)
+ * @param[out] param_values SQL data to set
+ * @param[out] param_lengths SQL length data to set
+ * @param[out] param_formats SQL format data to set
+ * @param param_length number of entries available in the @a param_values, @a 
param_lengths and @a param_formats arrays
+ * @param[out] scratch buffer for dynamic allocations (to be done via 
#GNUNET_malloc()
+ * @param scratch_length number of entries left in @a scratch
+ * @return -1 on error, number of offsets used in @a scratch otherwise
  */
+static int
+qconv_denom_pub (void *cls,
+                 const void *data,
+                 size_t data_len,
+                 void *param_values[],
+                 int param_lengths[],
+                 int param_formats[],
+                 unsigned int param_length,
+                 void *scratch[],
+                 unsigned int scratch_length)
+{
+  const struct TALER_DenominationPublicKey *denom_pub = data;
+  size_t tlen;
+  size_t len;
+  uint32_t be[2];
+  char *buf;
+  void *tbuf;
+
+  (void) cls;
+  GNUNET_assert (1 == param_length);
+  GNUNET_assert (scratch_length > 0);
+  GNUNET_break (NULL == cls);
+  be[0] = htonl ((uint32_t) denom_pub->cipher);
+  be[1] = htonl (denom_pub->age_mask.mask);
+  switch (denom_pub->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    tlen = GNUNET_CRYPTO_rsa_public_key_encode (
+      denom_pub->details.rsa_public_key,
+      &tbuf);
+    break;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+  len = tlen + sizeof (be);
+  buf = GNUNET_malloc (len);
+  memcpy (buf,
+          be,
+          sizeof (be));
+  switch (denom_pub->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    memcpy (&buf[sizeof (be)],
+            tbuf,
+            tlen);
+    GNUNET_free (tbuf);
+    break;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+
+  scratch[0] = buf;
+  param_values[0] = (void *) buf;
+  param_lengths[0] = len;
+  param_formats[0] = 1;
+  return 1;
+}
+
+
 struct GNUNET_PQ_QueryParam
-TALER_PQ_query_param_amount (const struct TALER_Amount *x)
+TALER_PQ_query_param_denom_pub (
+  const struct TALER_DenominationPublicKey *denom_pub)
+{
+  struct GNUNET_PQ_QueryParam res = {
+    .conv = &qconv_denom_pub,
+    .data = denom_pub,
+    .num_params = 1
+  };
+
+  return res;
+}
+
+
+/**
+ * Function called to convert input argument into SQL parameters.
+ *
+ * @param cls closure
+ * @param data pointer to input argument
+ * @param data_len number of bytes in @a data (if applicable)
+ * @param[out] param_values SQL data to set
+ * @param[out] param_lengths SQL length data to set
+ * @param[out] param_formats SQL format data to set
+ * @param param_length number of entries available in the @a param_values, @a 
param_lengths and @a param_formats arrays
+ * @param[out] scratch buffer for dynamic allocations (to be done via 
#GNUNET_malloc()
+ * @param scratch_length number of entries left in @a scratch
+ * @return -1 on error, number of offsets used in @a scratch otherwise
+ */
+static int
+qconv_denom_sig (void *cls,
+                 const void *data,
+                 size_t data_len,
+                 void *param_values[],
+                 int param_lengths[],
+                 int param_formats[],
+                 unsigned int param_length,
+                 void *scratch[],
+                 unsigned int scratch_length)
+{
+  const struct TALER_DenominationSignature *denom_sig = data;
+  size_t tlen;
+  size_t len;
+  uint32_t be[2];
+  char *buf;
+  void *tbuf;
+
+  (void) cls;
+  GNUNET_assert (1 == param_length);
+  GNUNET_assert (scratch_length > 0);
+  GNUNET_break (NULL == cls);
+  be[0] = htonl ((uint32_t) denom_sig->cipher);
+  be[1] = htonl (0x00); /* magic marker: unblinded */
+  switch (denom_sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    tlen = GNUNET_CRYPTO_rsa_signature_encode (
+      denom_sig->details.rsa_signature,
+      &tbuf);
+    break;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+  len = tlen + sizeof (be);
+  buf = GNUNET_malloc (len);
+  memcpy (buf,
+          &be,
+          sizeof (be));
+  switch (denom_sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    memcpy (&buf[sizeof (be)],
+            tbuf,
+            tlen);
+    GNUNET_free (tbuf);
+    break;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+
+  scratch[0] = buf;
+  param_values[0] = (void *) buf;
+  param_lengths[0] = len;
+  param_formats[0] = 1;
+  return 1;
+}
+
+
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_denom_sig (
+  const struct TALER_DenominationSignature *denom_sig)
+{
+  struct GNUNET_PQ_QueryParam res = {
+    .conv = &qconv_denom_sig,
+    .data = denom_sig,
+    .num_params = 1
+  };
+
+  return res;
+}
+
+
+/**
+ * Function called to convert input argument into SQL parameters.
+ *
+ * @param cls closure
+ * @param data pointer to input argument
+ * @param data_len number of bytes in @a data (if applicable)
+ * @param[out] param_values SQL data to set
+ * @param[out] param_lengths SQL length data to set
+ * @param[out] param_formats SQL format data to set
+ * @param param_length number of entries available in the @a param_values, @a 
param_lengths and @a param_formats arrays
+ * @param[out] scratch buffer for dynamic allocations (to be done via 
#GNUNET_malloc()
+ * @param scratch_length number of entries left in @a scratch
+ * @return -1 on error, number of offsets used in @a scratch otherwise
+ */
+static int
+qconv_blinded_denom_sig (void *cls,
+                         const void *data,
+                         size_t data_len,
+                         void *param_values[],
+                         int param_lengths[],
+                         int param_formats[],
+                         unsigned int param_length,
+                         void *scratch[],
+                         unsigned int scratch_length)
 {
-  struct GNUNET_PQ_QueryParam res =
-  { &qconv_amount, NULL, x, sizeof (*x), 2 };
+  const struct TALER_BlindedDenominationSignature *denom_sig = data;
+  size_t tlen;
+  size_t len;
+  uint32_t be[2];
+  char *buf;
+  void *tbuf;
+
+  (void) cls;
+  GNUNET_assert (1 == param_length);
+  GNUNET_assert (scratch_length > 0);
+  GNUNET_break (NULL == cls);
+  be[0] = htonl ((uint32_t) denom_sig->cipher);
+  be[1] = htonl (0x01); /* magic marker: blinded */
+  switch (denom_sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    tlen = GNUNET_CRYPTO_rsa_signature_encode (
+      denom_sig->details.blinded_rsa_signature,
+      &tbuf);
+    break;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+  len = tlen + sizeof (be);
+  buf = GNUNET_malloc (len);
+  memcpy (buf,
+          &be,
+          sizeof (be));
+  switch (denom_sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    memcpy (&buf[sizeof (be)],
+            tbuf,
+            tlen);
+    GNUNET_free (tbuf);
+    break;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+
+  scratch[0] = buf;
+  param_values[0] = (void *) buf;
+  param_lengths[0] = len;
+  param_formats[0] = 1;
+  return 1;
+}
+
+
+struct GNUNET_PQ_QueryParam
+TALER_PQ_query_param_blinded_denom_sig (
+  const struct TALER_BlindedDenominationSignature *denom_sig)
+{
+  struct GNUNET_PQ_QueryParam res = {
+    .conv = &qconv_blinded_denom_sig,
+    .data = denom_sig,
+    .num_params = 1
+  };
+
   return res;
 }
 
@@ -199,17 +458,15 @@ qconv_json (void *cls,
 }
 
 
-/**
- * Generate query parameter for a JSON object (stored as a string
- * in the DB).
- *
- * @param x pointer to the json object to pass
- */
 struct GNUNET_PQ_QueryParam
 TALER_PQ_query_param_json (const json_t *x)
 {
-  struct GNUNET_PQ_QueryParam res =
-  { &qconv_json, NULL, x, 0, 1 };
+  struct GNUNET_PQ_QueryParam res = {
+    .conv = &qconv_json,
+    .data = x,
+    .num_params = 1
+  };
+
   return res;
 }
 
@@ -261,21 +518,16 @@ qconv_round_time (void *cls,
 }
 
 
-/**
- * Generate query parameter for an absolute time value.
- * In contrast to
- * #GNUNET_PQ_query_param_absolute_time(), this function
- * will abort (!) if the time given is not rounded!
- * The database must store a 64-bit integer.
- *
- * @param x pointer to the query parameter to pass
- * @return array entry for the query parameters to use
- */
 struct GNUNET_PQ_QueryParam
 TALER_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x)
 {
-  struct GNUNET_PQ_QueryParam res =
-  { &qconv_round_time, NULL, x, sizeof (*x), 1 };
+  struct GNUNET_PQ_QueryParam res = {
+    .conv = &qconv_round_time,
+    .data = x,
+    .size = sizeof (*x),
+    .num_params = 1
+  };
+
   return res;
 }
 
@@ -324,20 +576,16 @@ qconv_round_time_abs (void *cls,
 }
 
 
-/**
- * Generate query parameter for an absolute time value.
- * In contrast to
- * #GNUNET_PQ_query_param_absolute_time(), this function
- * will abort (!) if the time given is not rounded!
- * The database must store a 64-bit integer.
- *
- * @param x pointer to the query parameter to pass
- */
 struct GNUNET_PQ_QueryParam
 TALER_PQ_query_param_absolute_time_nbo (const struct GNUNET_TIME_AbsoluteNBO 
*x)
 {
-  struct GNUNET_PQ_QueryParam res =
-  { &qconv_round_time_abs, NULL, x, sizeof (*x), 1 };
+  struct GNUNET_PQ_QueryParam res = {
+    .conv = &qconv_round_time_abs,
+    .data = x,
+    .size = sizeof (*x),
+    .num_params = 1
+  };
+
   return res;
 }
 
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
index 3d252890..ea815a9c 100644
--- a/src/pq/pq_result_helper.c
+++ b/src/pq/pq_result_helper.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014, 2015, 2016 Taler Systems SA
+  Copyright (C) 2014, 2015, 2016, 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -156,14 +156,6 @@ extract_amount_nbo (void *cls,
 }
 
 
-/**
- * Currency amount expected.
- *
- * @param name name of the field in the table
- * @param currency the currency to use for @a amount
- * @param[out] amount where to store the result
- * @return array entry for the result specification to use
- */
 struct GNUNET_PQ_ResultSpec
 TALER_PQ_result_spec_amount_nbo (const char *name,
                                  const char *currency,
@@ -240,14 +232,6 @@ extract_amount (void *cls,
 }
 
 
-/**
- * Currency amount expected.
- *
- * @param name name of the field in the table
- * @param currency the currency to use for @a amount
- * @param[out] amount where to store the result
- * @return array entry for the result specification to use
- */
 struct GNUNET_PQ_ResultSpec
 TALER_PQ_result_spec_amount (const char *name,
                              const char *currency,
@@ -353,13 +337,6 @@ clean_json (void *cls,
 }
 
 
-/**
- * json_t expected.
- *
- * @param name name of the field in the table
- * @param[out] jp where to store the result
- * @return array entry for the result specification to use
- */
 struct GNUNET_PQ_ResultSpec
 TALER_PQ_result_spec_json (const char *name,
                            json_t **jp)
@@ -430,16 +407,6 @@ extract_round_time (void *cls,
 }
 
 
-/**
- * Rounded absolute time expected.
- * In contrast to #GNUNET_PQ_query_param_absolute_time_nbo(),
- * this function ensures that the result is rounded and can
- * be converted to JSON.
- *
- * @param name name of the field in the table
- * @param[out] at where to store the result
- * @return array entry for the result specification to use
- */
 struct GNUNET_PQ_ResultSpec
 TALER_PQ_result_spec_absolute_time (const char *name,
                                     struct GNUNET_TIME_Absolute *at)
@@ -510,16 +477,6 @@ extract_round_time_nbo (void *cls,
 }
 
 
-/**
- * Rounded absolute time in network byte order expected.
- * In contrast to #GNUNET_PQ_query_param_absolute_time_nbo(),
- * this function ensures that the result is rounded and can
- * be converted to JSON.
- *
- * @param name name of the field in the table
- * @param[out] at where to store the result
- * @return array entry for the result specification to use
- */
 struct GNUNET_PQ_ResultSpec
 TALER_PQ_result_spec_absolute_time_nbo (const char *name,
                                         struct GNUNET_TIME_AbsoluteNBO *at)
@@ -535,4 +492,352 @@ TALER_PQ_result_spec_absolute_time_nbo (const char *name,
 }
 
 
+/**
+ * Extract data from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param int row to extract data from
+ * @param fname name (or prefix) of the fields to extract from
+ * @param[in,out] dst_size where to store size of result, may be NULL
+ * @param[out] dst where to store the result
+ * @return
+ *   #GNUNET_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static enum GNUNET_GenericReturnValue
+extract_denom_pub (void *cls,
+                   PGresult *result,
+                   int row,
+                   const char *fname,
+                   size_t *dst_size,
+                   void *dst)
+{
+  struct TALER_DenominationPublicKey *pk = dst;
+  size_t len;
+  const char *res;
+  int fnum;
+  uint32_t be[2];
+
+  (void) cls;
+  fnum = PQfnumber (result,
+                    fname);
+  if (fnum < 0)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (PQgetisnull (result,
+                   row,
+                   fnum))
+    return GNUNET_NO;
+
+  /* if a field is null, continue but
+   * remember that we now return a different result */
+  len = PQgetlength (result,
+                     row,
+                     fnum);
+  res = PQgetvalue (result,
+                    row,
+                    fnum);
+  if (len < sizeof (be))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  memcpy (be,
+          res,
+          sizeof (be));
+  res += sizeof (be);
+  len -= sizeof (be);
+  pk->cipher = ntohl (be[0]);
+  pk->age_mask.mask = ntohl (be[1]);
+  switch (pk->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    pk->details.rsa_public_key
+      = GNUNET_CRYPTO_rsa_public_key_decode (res,
+                                             len);
+    if (NULL == pk->details.rsa_public_key)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_OK;
+  // FIXME: add CS case!
+  default:
+    GNUNET_break (0);
+  }
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Function called to clean up memory allocated
+ * by a #GNUNET_PQ_ResultConverter.
+ *
+ * @param cls closure
+ * @param rd result data to clean up
+ */
+static void
+clean_denom_pub (void *cls,
+                 void *rd)
+{
+  struct TALER_DenominationPublicKey *denom_pub = rd;
+
+  (void) cls;
+  TALER_denom_pub_free (denom_pub);
+}
+
+
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_denom_pub (const char *name,
+                                struct TALER_DenominationPublicKey *denom_pub)
+{
+  struct GNUNET_PQ_ResultSpec res = {
+    .conv = &extract_denom_pub,
+    .cleaner = &clean_denom_pub,
+    .dst = (void *) denom_pub,
+    .fname = name
+  };
+
+  return res;
+}
+
+
+/**
+ * Extract data from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param int row to extract data from
+ * @param fname name (or prefix) of the fields to extract from
+ * @param[in,out] dst_size where to store size of result, may be NULL
+ * @param[out] dst where to store the result
+ * @return
+ *   #GNUNET_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static enum GNUNET_GenericReturnValue
+extract_denom_sig (void *cls,
+                   PGresult *result,
+                   int row,
+                   const char *fname,
+                   size_t *dst_size,
+                   void *dst)
+{
+  struct TALER_DenominationSignature *sig = dst;
+  size_t len;
+  const char *res;
+  int fnum;
+  uint32_t be[2];
+
+  (void) cls;
+  fnum = PQfnumber (result,
+                    fname);
+  if (fnum < 0)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (PQgetisnull (result,
+                   row,
+                   fnum))
+    return GNUNET_NO;
+
+  /* if a field is null, continue but
+   * remember that we now return a different result */
+  len = PQgetlength (result,
+                     row,
+                     fnum);
+  res = PQgetvalue (result,
+                    row,
+                    fnum);
+  if (len < sizeof (be))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  memcpy (&be,
+          res,
+          sizeof (be));
+  if (0x00 != ntohl (be[1]))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  res += sizeof (be);
+  len -= sizeof (be);
+  sig->cipher = ntohl (be[0]);
+  switch (sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    sig->details.rsa_signature
+      = GNUNET_CRYPTO_rsa_signature_decode (res,
+                                            len);
+    if (NULL == sig->details.rsa_signature)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_OK;
+  // FIXME: add CS case!
+  default:
+    GNUNET_break (0);
+  }
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Function called to clean up memory allocated
+ * by a #GNUNET_PQ_ResultConverter.
+ *
+ * @param cls closure
+ * @param rd result data to clean up
+ */
+static void
+clean_denom_sig (void *cls,
+                 void *rd)
+{
+  struct TALER_DenominationSignature *denom_sig = rd;
+
+  (void) cls;
+  TALER_denom_sig_free (denom_sig);
+}
+
+
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_denom_sig (const char *name,
+                                struct TALER_DenominationSignature *denom_sig)
+{
+  struct GNUNET_PQ_ResultSpec res = {
+    .conv = &extract_denom_sig,
+    .cleaner = &clean_denom_sig,
+    .dst = (void *) denom_sig,
+    .fname = name
+  };
+
+  return res;
+}
+
+
+/**
+ * Extract data from a Postgres database @a result at row @a row.
+ *
+ * @param cls closure
+ * @param result where to extract data from
+ * @param int row to extract data from
+ * @param fname name (or prefix) of the fields to extract from
+ * @param[in,out] dst_size where to store size of result, may be NULL
+ * @param[out] dst where to store the result
+ * @return
+ *   #GNUNET_YES if all results could be extracted
+ *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
+ */
+static enum GNUNET_GenericReturnValue
+extract_blinded_denom_sig (void *cls,
+                           PGresult *result,
+                           int row,
+                           const char *fname,
+                           size_t *dst_size,
+                           void *dst)
+{
+  struct TALER_BlindedDenominationSignature *sig = dst;
+  size_t len;
+  const char *res;
+  int fnum;
+  uint32_t be[2];
+
+  (void) cls;
+  fnum = PQfnumber (result,
+                    fname);
+  if (fnum < 0)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (PQgetisnull (result,
+                   row,
+                   fnum))
+    return GNUNET_NO;
+
+  /* if a field is null, continue but
+   * remember that we now return a different result */
+  len = PQgetlength (result,
+                     row,
+                     fnum);
+  res = PQgetvalue (result,
+                    row,
+                    fnum);
+  if (len < sizeof (be))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  memcpy (&be,
+          res,
+          sizeof (be));
+  if (0x01 != ntohl (be[1])) /* magic marker: blinded */
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  res += sizeof (be);
+  len -= sizeof (be);
+  sig->cipher = ntohl (be[0]);
+  switch (sig->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    sig->details.blinded_rsa_signature
+      = GNUNET_CRYPTO_rsa_signature_decode (res,
+                                            len);
+    if (NULL == sig->details.blinded_rsa_signature)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_OK;
+  // FIXME: add CS case!
+  default:
+    GNUNET_break (0);
+  }
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * Function called to clean up memory allocated
+ * by a #GNUNET_PQ_ResultConverter.
+ *
+ * @param cls closure
+ * @param rd result data to clean up
+ */
+static void
+clean_blinded_denom_sig (void *cls,
+                         void *rd)
+{
+  struct TALER_BlindedDenominationSignature *denom_sig = rd;
+
+  (void) cls;
+  TALER_blinded_denom_sig_free (denom_sig);
+}
+
+
+struct GNUNET_PQ_ResultSpec
+TALER_PQ_result_spec_blinded_denom_sig (
+  const char *name,
+  struct TALER_BlindedDenominationSignature *denom_sig)
+{
+  struct GNUNET_PQ_ResultSpec res = {
+    .conv = &extract_blinded_denom_sig,
+    .cleaner = &clean_blinded_denom_sig,
+    .dst = (void *) denom_sig,
+    .fname = name
+  };
+
+  return res;
+}
+
+
 /* end of pq_result_helper.c */
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 7fa7ef3d..d02e6377 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -61,6 +61,10 @@ libtalertesting_la_SOURCES = \
   testing_api_cmd_exec_transfer.c \
   testing_api_cmd_exec_wirewatch.c \
   testing_api_cmd_insert_deposit.c \
+  testing_api_cmd_kyc_check_get.c \
+  testing_api_cmd_kyc_proof.c \
+  testing_api_cmd_kyc_wallet_get.c \
+  testing_api_cmd_oauth.c \
   testing_api_cmd_offline_sign_fees.c \
   testing_api_cmd_offline_sign_keys.c \
   testing_api_cmd_set_wire_fee.c \
@@ -86,32 +90,12 @@ libtalertesting_la_SOURCES = \
   testing_api_helpers_bank.c \
   testing_api_helpers_exchange.c \
   testing_api_loop.c \
-  testing_api_traits.c \
-  testing_api_trait_amount.c \
-  testing_api_trait_blinding_key.c \
-  testing_api_trait_cmd.c \
-  testing_api_trait_coin_priv.c \
-  testing_api_trait_contract.c \
-  testing_api_trait_denom_pub.c \
-  testing_api_trait_denom_sig.c \
-  testing_api_trait_exchange_pub.c \
-  testing_api_trait_exchange_sig.c \
-  testing_api_trait_fresh_coin.c \
-  testing_api_trait_json.c \
-  testing_api_trait_merchant_key.c \
-  testing_api_trait_number.c \
-  testing_api_trait_process.c \
-  testing_api_trait_reserve_history.c \
-  testing_api_trait_reserve_pub.c \
-  testing_api_trait_reserve_priv.c \
-  testing_api_trait_string.c \
-  testing_api_trait_time.c \
-  testing_api_trait_uuid.c \
-  testing_api_trait_wtid.c
+  testing_api_traits.c
 libtalertesting_la_LIBADD = \
   $(top_builddir)/src/lib/libtalerauditor.la \
   $(top_builddir)/src/lib/libtalerexchange.la \
   $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/mhd/libtalermhd.la \
   $(top_builddir)/src/util/libtalerutil.la \
   $(top_builddir)/src/bank-lib/libtalerbank.la \
   $(top_builddir)/src/bank-lib/libtalerfakebank.la \
@@ -138,6 +122,7 @@ check_PROGRAMS = \
   test_exchange_api_revocation \
   test_exchange_api_overlapping_keys_bug \
   test_exchange_management_api \
+  test_kyc_api \
   test_taler_exchange_aggregator-postgres \
   test_taler_exchange_wirewatch-postgres
 if HAVE_TWISTER
@@ -168,6 +153,7 @@ test_auditor_api_LDADD = \
   -ljansson \
   $(XLIB)
 
+
 test_auditor_api_version_SOURCES = \
   test_auditor_api_version.c
 test_auditor_api_version_LDADD = \
@@ -355,6 +341,22 @@ test_bank_api_with_pybank_twisted_LDADD = \
   $(XLIB)
 
 
+test_kyc_api_SOURCES = \
+  test_kyc_api.c
+test_kyc_api_LDADD = \
+  libtalertesting.la \
+  $(top_builddir)/src/lib/libtalerauditor.la \
+  $(top_builddir)/src/lib/libtalerexchange.la \
+  $(LIBGCRYPT_LIBS) \
+  $(top_builddir)/src/bank-lib/libtalerfakebank.la \
+  $(top_builddir)/src/bank-lib/libtalerbank.la \
+  $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/util/libtalerutil.la \
+  -lgnunetcurl \
+  -lgnunetutil \
+  -ljansson \
+  $(XLIB)
+
 # Distribution
 
 EXTRA_DIST = \
@@ -381,4 +383,5 @@ EXTRA_DIST = \
   
test_taler_exchange_httpd_home/.local/share/taler/exchange/offline-keys/master.priv
 \
   
test_taler_exchange_httpd_home/.local/share/taler/exchange/wirefees/x-taler-bank.fee
 \
   test-taler-exchange-aggregator-postgres.conf \
-  test-taler-exchange-wirewatch-postgres.conf
+  test-taler-exchange-wirewatch-postgres.conf \
+  test_kyc_api.conf
diff --git a/src/testing/test_auditor_api.c b/src/testing/test_auditor_api.c
index 2ea17356..d85ece1f 100644
--- a/src/testing/test_auditor_api.c
+++ b/src/testing/test_auditor_api.c
@@ -70,6 +70,7 @@ static struct TALER_TESTING_BankConfiguration bc;
  * @param label label to use for the command.
  */
 #define CMD_EXEC_AGGREGATOR(label) \
+  TALER_TESTING_cmd_sleep (label "-sleep", 1), \
   TALER_TESTING_cmd_exec_aggregator (label, CONFIG_FILE), \
   TALER_TESTING_cmd_exec_transfer (label, CONFIG_FILE)
 
@@ -213,26 +214,35 @@ run (void *cls,
      * happen here, as each deposit operation is run with a
      * fresh merchant public key! NOTE: this comment comes
      * "verbatim" from the old test-suite, and IMO does not explain
-     * a lot!*///
+     * a lot! */
     CMD_EXEC_AGGREGATOR ("run-aggregator"),
 
     /**
      * Check all the transfers took place.
      */
-    TALER_TESTING_cmd_check_bank_transfer
-      ("check_bank_transfer-499c", ec.exchange_url,
-      "EUR:4.98", bc.exchange_payto, bc.user42_payto),
-    TALER_TESTING_cmd_check_bank_transfer
-      ("check_bank_transfer-99c1", ec.exchange_url,
-      "EUR:0.98", bc.exchange_payto, bc.user42_payto),
-    TALER_TESTING_cmd_check_bank_transfer
-      ("check_bank_transfer-99c", ec.exchange_url,
-      "EUR:0.08", bc.exchange_payto, bc.user43_payto),
+    TALER_TESTING_cmd_check_bank_transfer (
+      "check_bank_transfer-499c",
+      ec.exchange_url,
+      "EUR:4.98",
+      bc.exchange_payto,
+      bc.user42_payto),
+    TALER_TESTING_cmd_check_bank_transfer (
+      "check_bank_transfer-99c1",
+      ec.exchange_url,
+      "EUR:0.98",
+      bc.exchange_payto,
+      bc.user42_payto),
+    TALER_TESTING_cmd_check_bank_transfer (
+      "check_bank_transfer-99c",
+      ec.exchange_url,
+      "EUR:0.08",
+      bc.exchange_payto,
+      bc.user43_payto),
 
     /* The following transactions got originated within
      * the "massive deposit confirms" batch.  */
-    TALER_TESTING_cmd_check_bank_transfer
-      ("check-massive-transfer-1",
+    TALER_TESTING_cmd_check_bank_transfer (
+      "check-massive-transfer-1",
       ec.exchange_url,
       "EUR:0.98",
       bc.exchange_payto, bc.user43_payto),
@@ -412,7 +422,8 @@ run (void *cls,
      * These commands should close the reserve because the aggregator
      * is given a config file that overrides the reserve expiration
      * time (making it now-ish)
-     */CMD_TRANSFER_TO_EXCHANGE ("short-lived-reserve",
+     */
+    CMD_TRANSFER_TO_EXCHANGE ("short-lived-reserve",
                               "EUR:5.01"),
     TALER_TESTING_cmd_exec_wirewatch ("short-lived-aggregation",
                                       CONFIG_FILE_EXPIRE_RESERVE_NOW),
@@ -472,8 +483,8 @@ run (void *cls,
      */
     CMD_TRANSFER_TO_EXCHANGE ("massive-reserve",
                               "EUR:10.10"),
-    TALER_TESTING_cmd_check_bank_admin_transfer
-      ("check-massive-transfer",
+    TALER_TESTING_cmd_check_bank_admin_transfer (
+      "check-massive-transfer",
       "EUR:10.10",
       bc.user42_payto, bc.exchange_payto,
       "massive-reserve"),
@@ -518,8 +529,8 @@ run (void *cls,
                                        "massive-reserve",
                                        "EUR:1",
                                        MHD_HTTP_OK),
-    TALER_TESTING_cmd_deposit
-      ("massive-deposit-1",
+    TALER_TESTING_cmd_deposit (
+      "massive-deposit-1",
       "massive-withdraw-1",
       0,
       bc.user43_payto,
@@ -599,8 +610,8 @@ run (void *cls,
       GNUNET_TIME_UNIT_ZERO,
       "EUR:1",
       MHD_HTTP_OK),
-    TALER_TESTING_cmd_deposit
-      ("massive-deposit-10",
+    TALER_TESTING_cmd_deposit (
+      "massive-deposit-10",
       "massive-withdraw-10",
       0,
       bc.user43_payto,
diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c
index 008eefb2..72968c25 100644
--- a/src/testing/test_exchange_api.c
+++ b/src/testing/test_exchange_api.c
@@ -343,7 +343,7 @@ run (void *cls,
     /* Try resolving a deposit's WTID for a failed deposit.
      * As the deposit failed, the answer should be that the
      * exchange does NOT know about the deposit.
-     *///
+     */
     TALER_TESTING_cmd_track_transaction ("deposit-wtid-failing",
                                          "deposit-double-2",
                                          0,
@@ -352,10 +352,9 @@ run (void *cls,
     /* Try resolving an undefined (all zeros) WTID; this
      * should fail as obviously the exchange didn't use that
      * WTID value for any transaction.
-     *///
+     */
     TALER_TESTING_cmd_track_transfer_empty ("wire-deposit-failing",
                                             NULL,
-                                            0,
                                             MHD_HTTP_NOT_FOUND),
     TALER_TESTING_cmd_sleep ("sleep-before-aggregator",
                              1),
@@ -396,13 +395,11 @@ run (void *cls,
                                          "check_bank_transfer-499c"),
     TALER_TESTING_cmd_track_transfer ("wire-deposit-success-bank",
                                       "check_bank_transfer-99c1",
-                                      0,
                                       MHD_HTTP_OK,
                                       "EUR:0.98",
                                       "EUR:0.01"),
     TALER_TESTING_cmd_track_transfer ("wire-deposits-success-wtid",
                                       "deposit-wtid-ok",
-                                      0,
                                       MHD_HTTP_OK,
                                       "EUR:4.98",
                                       "EUR:0.01"),
diff --git a/src/testing/test_exchange_api_revocation.c 
b/src/testing/test_exchange_api_revocation.c
index 62be6a0e..d4595abe 100644
--- a/src/testing/test_exchange_api_revocation.c
+++ b/src/testing/test_exchange_api_revocation.c
@@ -122,7 +122,8 @@ run (void *cls,
                                MHD_HTTP_OK),
     /**
      * Melt SOME of the rest of the coin's value
-     * (EUR:3.17 = 3x EUR:1.03 + 7x EUR:0.13) */
+     * (EUR:3.17 = 3x EUR:1.03 + 7x EUR:0.13)
+     */
     TALER_TESTING_cmd_melt ("refresh-melt-1",
                             "withdraw-revocation-coin-1",
                             MHD_HTTP_OK,
diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c
new file mode 100644
index 00000000..f90932b0
--- /dev/null
+++ b/src/testing/test_kyc_api.c
@@ -0,0 +1,288 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014-2021 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 3, or
+  (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file testing/test_kyc_api.c
+ * @brief testcase to test the KYC processes
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_signatures.h"
+#include "taler_exchange_service.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <microhttpd.h>
+#include "taler_bank_service.h"
+#include "taler_fakebank_lib.h"
+#include "taler_testing_lib.h"
+
+
+/**
+ * Configuration file we use.  One (big) configuration is used
+ * for the various components for this test.
+ */
+#define CONFIG_FILE "test_kyc_api.conf"
+
+/**
+ * Exchange configuration data.
+ */
+static struct TALER_TESTING_ExchangeConfiguration ec;
+
+/**
+ * Bank configuration data.
+ */
+static struct TALER_TESTING_BankConfiguration bc;
+
+/**
+ * Execute the taler-exchange-wirewatch command with
+ * our configuration file.
+ *
+ * @param label label to use for the command.
+ */
+#define CMD_EXEC_WIREWATCH(label) \
+  TALER_TESTING_cmd_exec_wirewatch (label, CONFIG_FILE)
+
+/**
+ * Execute the taler-exchange-aggregator, closer and transfer commands with
+ * our configuration file.
+ *
+ * @param label label to use for the command.
+ */
+#define CMD_EXEC_AGGREGATOR(label)                        \
+  TALER_TESTING_cmd_sleep (label "-sleep", 1), \
+  TALER_TESTING_cmd_exec_aggregator_with_kyc (label, CONFIG_FILE), \
+  TALER_TESTING_cmd_exec_transfer (label, CONFIG_FILE)
+
+/**
+ * Run wire transfer of funds from some user's account to the
+ * exchange.
+ *
+ * @param label label to use for the command.
+ * @param amount amount to transfer, i.e. "EUR:1"
+ */
+#define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
+  TALER_TESTING_cmd_admin_add_incoming (label, amount,           \
+                                        &bc.exchange_auth,       \
+                                        bc.user42_payto)
+
+/**
+ * Main function that will tell the interpreter what commands to
+ * run.
+ *
+ * @param cls closure
+ */
+static void
+run (void *cls,
+     struct TALER_TESTING_Interpreter *is)
+{
+  /**
+   * Test withdraw.
+   */
+  struct TALER_TESTING_Command withdraw[] = {
+    CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1",
+                              "EUR:15.02"),
+    TALER_TESTING_cmd_check_bank_admin_transfer (
+      "check-create-reserve-1",
+      "EUR:15.02", bc.user42_payto, bc.exchange_payto,
+      "create-reserve-1"),
+    CMD_EXEC_WIREWATCH ("wirewatch-1"),
+    TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1-no-kyc",
+                                       "create-reserve-1",
+                                       "EUR:10",
+                                       MHD_HTTP_ACCEPTED),
+    TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1",
+                                       "create-reserve-1",
+                                       "EUR:5",
+                                       MHD_HTTP_OK),
+    TALER_TESTING_cmd_end ()
+  };
+  /**
+   * Test withdraw with KYC.
+   */
+  struct TALER_TESTING_Command withdraw_kyc[] = {
+    CMD_EXEC_WIREWATCH ("wirewatch-1"),
+    TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1-lacking-kyc",
+                                       "create-reserve-1",
+                                       "EUR:5",
+                                       MHD_HTTP_ACCEPTED),
+    TALER_TESTING_cmd_proof_kyc ("proof-kyc",
+                                 "withdraw-coin-1-lacking-kyc",
+                                 "pass",
+                                 "state",
+                                 MHD_HTTP_SEE_OTHER),
+    TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1-with-kyc",
+                                       "create-reserve-1",
+                                       "EUR:5",
+                                       MHD_HTTP_OK),
+    TALER_TESTING_cmd_end ()
+  };
+  struct TALER_TESTING_Command spend[] = {
+    TALER_TESTING_cmd_deposit (
+      "deposit-simple",
+      "withdraw-coin-1",
+      0,
+      bc.user43_payto,
+      "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
+      GNUNET_TIME_UNIT_ZERO,
+      "EUR:5",
+      MHD_HTTP_OK),
+    TALER_TESTING_cmd_track_transaction (
+      "track-deposit",
+      "deposit-simple",
+      0,
+      MHD_HTTP_ACCEPTED,
+      NULL),
+    TALER_TESTING_cmd_end ()
+  };
+
+  struct TALER_TESTING_Command track[] = {
+    CMD_EXEC_AGGREGATOR ("run-aggregator-before-kyc"),
+    TALER_TESTING_cmd_check_bank_empty ("check_bank_empty-no-kyc"),
+    TALER_TESTING_cmd_check_kyc_get ("check-kyc-deposit",
+                                     "track-deposit",
+                                     MHD_HTTP_ACCEPTED),
+    TALER_TESTING_cmd_proof_kyc ("proof-kyc-no-service",
+                                 "track-deposit",
+                                 "bad",
+                                 "state",
+                                 MHD_HTTP_BAD_GATEWAY),
+    TALER_TESTING_cmd_oauth ("start-oauth-service",
+                             6666),
+    TALER_TESTING_cmd_proof_kyc ("proof-kyc-fail",
+                                 "track-deposit",
+                                 "bad",
+                                 "state",
+                                 MHD_HTTP_FORBIDDEN),
+    TALER_TESTING_cmd_proof_kyc ("proof-kyc-fail",
+                                 "track-deposit",
+                                 "pass",
+                                 "state",
+                                 MHD_HTTP_SEE_OTHER),
+    CMD_EXEC_AGGREGATOR ("run-aggregator-after-kyc"),
+    TALER_TESTING_cmd_check_bank_transfer (
+      "check_bank_transfer-499c",
+      ec.exchange_url,
+      "EUR:4.98",
+      bc.exchange_payto,
+      bc.user43_payto),
+    TALER_TESTING_cmd_check_bank_empty ("check_bank_empty"),
+    TALER_TESTING_cmd_end ()
+  };
+
+  struct TALER_TESTING_Command wallet_kyc[] = {
+    TALER_TESTING_cmd_wallet_kyc_get (
+      "wallet-kyc-fail",
+      NULL,
+      MHD_HTTP_OK),
+    TALER_TESTING_cmd_proof_kyc ("proof-wallet-kyc",
+                                 "wallet-kyc-fail",
+                                 "pass",
+                                 "state",
+                                 MHD_HTTP_SEE_OTHER),
+    TALER_TESTING_cmd_check_kyc_get (
+      "wallet-kyc-check",
+      "wallet-kyc-fail",
+      MHD_HTTP_OK),
+    TALER_TESTING_cmd_end ()
+  };
+
+  struct TALER_TESTING_Command commands[] = {
+    TALER_TESTING_cmd_exec_offline_sign_fees ("offline-sign-fees",
+                                              CONFIG_FILE,
+                                              "EUR:0.01",
+                                              "EUR:0.01"),
+    TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
+                                   MHD_HTTP_NO_CONTENT,
+                                   false),
+    TALER_TESTING_cmd_wire_add ("add-wire-account",
+                                "payto://x-taler-bank/localhost/2",
+                                MHD_HTTP_NO_CONTENT,
+                                false),
+    TALER_TESTING_cmd_exec_offline_sign_keys ("offline-sign-future-keys",
+                                              CONFIG_FILE),
+    TALER_TESTING_cmd_check_keys_pull_all_keys ("refetch /keys",
+                                                2),
+    TALER_TESTING_cmd_batch ("withdraw",
+                             withdraw),
+    TALER_TESTING_cmd_batch ("spend",
+                             spend),
+    TALER_TESTING_cmd_batch ("track",
+                             track),
+    TALER_TESTING_cmd_batch ("withdraw-kyc",
+                             withdraw_kyc),
+    TALER_TESTING_cmd_batch ("wallet-kyc",
+                             wallet_kyc),
+    TALER_TESTING_cmd_end ()
+  };
+
+  TALER_TESTING_run_with_fakebank (is,
+                                   commands,
+                                   bc.exchange_auth.wire_gateway_url);
+}
+
+
+int
+main (int argc,
+      char *const *argv)
+{
+  /* These environment variables get in the way... */
+  unsetenv ("XDG_DATA_HOME");
+  unsetenv ("XDG_CONFIG_HOME");
+  GNUNET_log_setup ("test-kyc-api",
+                    "INFO",
+                    NULL);
+  /* Check fakebank port is available and get configuration data. */
+  if (GNUNET_OK !=
+      TALER_TESTING_prepare_fakebank (CONFIG_FILE,
+                                      "exchange-account-2",
+                                      &bc))
+    return 77;
+  TALER_TESTING_cleanup_files (CONFIG_FILE);
+  /* @helpers.  Run keyup, create tables, ... Note: it
+   * fetches the port number from config in order to see
+   * if it's available. */
+  switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
+                                          GNUNET_YES,
+                                          &ec))
+  {
+  case GNUNET_SYSERR:
+    GNUNET_break (0);
+    return 1;
+  case GNUNET_NO:
+    return 77;
+  case GNUNET_OK:
+    if (GNUNET_OK !=
+        /* Set up event loop and reschedule context, plus
+         * start/stop the exchange.  It calls TALER_TESTING_setup
+         * which creates the 'is' object.
+         */
+        TALER_TESTING_setup_with_exchange (&run,
+                                           NULL,
+                                           CONFIG_FILE))
+      return 1;
+    break;
+  default:
+    GNUNET_break (0);
+    return 1;
+  }
+  return 0;
+}
+
+
+/* end of test_kyc_api.c */
diff --git a/src/testing/test_auditor_api.conf b/src/testing/test_kyc_api.conf
similarity index 89%
copy from src/testing/test_auditor_api.conf
copy to src/testing/test_kyc_api.conf
index 03a5e245..8ca6b74b 100644
--- a/src/testing/test_auditor_api.conf
+++ b/src/testing/test_kyc_api.conf
@@ -45,6 +45,23 @@ DB = postgres
 # exchange (or the twister) is actually listening.
 BASE_URL = "http://localhost:8081/";
 
+
+KYC_MODE = OAUTH2
+
+KYC_WALLET_BALANCE_LIMIT = EUR:1
+
+KYC_WITHDRAW_PERIOD = "31 days"
+
+KYC_WITHDRAW_LIMIT = EUR:8
+
+[exchange-kyc-oauth2]
+
+KYC_OAUTH2_URL = http://localhost:6666/oauth/v2/login
+KYC_INFO_URL = http://localhost:6666/api/user/me
+KYC_OAUTH2_CLIENT_ID = taler-exchange
+KYC_OAUTH2_CLIENT_SECRET = exchange-secret
+KYC_OAUTH2_POST_URL = http://example.com/
+
 [exchangedb-postgres]
 CONFIG = "postgres:///talercheck"
 
diff --git a/src/testing/testing_api_cmd_auditor_add_denom_sig.c 
b/src/testing/testing_api_cmd_auditor_add_denom_sig.c
index efa4a9d7..33cd9575 100644
--- a/src/testing/testing_api_cmd_auditor_add_denom_sig.c
+++ b/src/testing/testing_api_cmd_auditor_add_denom_sig.c
@@ -108,7 +108,7 @@ auditor_add_run (void *cls,
 {
   struct AuditorAddDenomSigState *ds = cls;
   struct TALER_AuditorSignatureP auditor_sig;
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
   const struct TALER_EXCHANGE_DenomPublicKey *dk;
 
   (void) cmd;
@@ -202,26 +202,6 @@ auditor_add_cleanup (void *cls,
 }
 
 
-/**
- * Offer internal data from a "auditor_add" CMD, to other commands.
- *
- * @param cls closure.
- * @param[out] ret result.
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- *
- * @return #GNUNET_OK on success.
- */
-static int
-auditor_add_traits (void *cls,
-                    const void **ret,
-                    const char *trait,
-                    unsigned int index)
-{
-  return GNUNET_NO;
-}
-
-
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_auditor_add_denom_sig (const char *label,
                                          unsigned int expected_http_status,
@@ -239,8 +219,7 @@ TALER_TESTING_cmd_auditor_add_denom_sig (const char *label,
       .cls = ds,
       .label = label,
       .run = &auditor_add_run,
-      .cleanup = &auditor_add_cleanup,
-      .traits = &auditor_add_traits
+      .cleanup = &auditor_add_cleanup
     };
 
     return cmd;
diff --git a/src/testing/testing_api_cmd_auditor_deposit_confirmation.c 
b/src/testing/testing_api_cmd_auditor_deposit_confirmation.c
index f40d78c8..54b5dd6c 100644
--- a/src/testing/testing_api_cmd_auditor_deposit_confirmation.c
+++ b/src/testing/testing_api_cmd_auditor_deposit_confirmation.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
+  Copyright (C) 2018, 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
@@ -199,12 +199,14 @@ deposit_confirmation_run (void *cls,
                           const struct TALER_TESTING_Command *cmd,
                           struct TALER_TESTING_Interpreter *is)
 {
+  static struct TALER_ExtensionContractHash no_h_extensions;
   struct DepositConfirmationState *dcs = cls;
   const struct TALER_TESTING_Command *deposit_cmd;
-  struct GNUNET_HashCode h_wire;
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_MerchantWireHash h_wire;
+  struct TALER_PrivateContractHash h_contract_terms;
   const struct GNUNET_TIME_Absolute *exchange_timestamp = NULL;
   struct GNUNET_TIME_Absolute timestamp;
+  const struct GNUNET_TIME_Absolute *wire_deadline;
   struct GNUNET_TIME_Absolute refund_deadline;
   struct TALER_Amount amount_without_fee;
   struct TALER_CoinSpendPublicKeyP coin_pub;
@@ -243,6 +245,10 @@ deposit_confirmation_run (void *cls,
                  TALER_TESTING_get_trait_absolute_time (deposit_cmd,
                                                         dcs->coin_index,
                                                         &exchange_timestamp));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_TESTING_get_trait_wire_deadline (deposit_cmd,
+                                                        dcs->coin_index,
+                                                        &wire_deadline));
   GNUNET_assert (NULL != exchange_timestamp);
   keys = TALER_EXCHANGE_get_keys (dcs->is->exchange);
   GNUNET_assert (NULL != keys);
@@ -251,7 +257,6 @@ deposit_confirmation_run (void *cls,
 
   GNUNET_assert (GNUNET_OK ==
                  TALER_TESTING_get_trait_contract_terms (deposit_cmd,
-                                                         dcs->coin_index,
                                                          &contract_terms));
   /* Very unlikely to fail */
   GNUNET_assert (NULL != contract_terms);
@@ -260,7 +265,6 @@ deposit_confirmation_run (void *cls,
                                            &h_contract_terms));
   GNUNET_assert (GNUNET_OK ==
                  TALER_TESTING_get_trait_wire_details (deposit_cmd,
-                                                       dcs->coin_index,
                                                        &wire_details));
   GNUNET_assert (GNUNET_OK ==
                  TALER_JSON_merchant_wire_signature_hash (wire_details,
@@ -273,7 +277,6 @@ deposit_confirmation_run (void *cls,
                                       &coin_pub.eddsa_pub);
   GNUNET_assert (GNUNET_OK ==
                  TALER_TESTING_get_trait_merchant_priv (deposit_cmd,
-                                                        dcs->coin_index,
                                                         &merchant_priv));
   GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv,
                                       &merchant_pub.eddsa_pub);
@@ -300,7 +303,8 @@ deposit_confirmation_run (void *cls,
   /* refund deadline is optional, defaults to zero */
   {
     struct GNUNET_JSON_Specification spec[] = {
-      TALER_JSON_spec_absolute_time ("refund_deadline", &refund_deadline),
+      TALER_JSON_spec_absolute_time ("refund_deadline",
+                                     &refund_deadline),
       GNUNET_JSON_spec_end ()
     };
 
@@ -314,8 +318,10 @@ deposit_confirmation_run (void *cls,
   }
   dcs->dc = TALER_AUDITOR_deposit_confirmation (dcs->auditor,
                                                 &h_wire,
+                                                &no_h_extensions,
                                                 &h_contract_terms,
                                                 *exchange_timestamp,
+                                                *wire_deadline,
                                                 refund_deadline,
                                                 &amount_without_fee,
                                                 &coin_pub,
@@ -371,47 +377,6 @@ deposit_confirmation_cleanup (void *cls,
 }
 
 
-/**
- * Offer internal data to other commands.
- *
- * @param cls closure.
- * @param[out] ret set to the wanted data.
- * @param trait name of the trait.
- * @param index index number of the traits to be returned.
- *
- * @return #GNUNET_OK on success
- */
-static int
-deposit_confirmation_traits (void *cls,
-                             const void **ret,
-                             const char *trait,
-                             unsigned int index)
-{
-  (void) cls;
-  (void) ret;
-  (void) trait;
-  (void) index;
-  /* Must define this function because some callbacks
-   * look for certain traits on _all_ the commands. */
-  return GNUNET_SYSERR;
-}
-
-
-/**
- * Create a "deposit-confirmation" command.
- *
- * @param label command label.
- * @param auditor auditor connection.
- * @param deposit_reference reference to any operation that can
- *        provide a coin.
- * @param coin_index if @a deposit_reference offers an array of
- *        coins, this parameter selects which one in that array.
- *        This value is currently ignored, as only one-coin
- *        deposits are implemented.
- * @param amount_without_fee deposited amount without the fee
- * @param expected_response_code expected HTTP response code.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_deposit_confirmation (const char *label,
                                         struct TALER_AUDITOR_Handle *auditor,
@@ -434,8 +399,7 @@ TALER_TESTING_cmd_deposit_confirmation (const char *label,
       .cls = dcs,
       .label = label,
       .run = &deposit_confirmation_run,
-      .cleanup = &deposit_confirmation_cleanup,
-      .traits = &deposit_confirmation_traits
+      .cleanup = &deposit_confirmation_cleanup
     };
 
     return cmd;
@@ -443,13 +407,6 @@ TALER_TESTING_cmd_deposit_confirmation (const char *label,
 }
 
 
-/**
- * Modify a deposit confirmation command to enable retries when we get
- * transient errors from the auditor.
- *
- * @param cmd a deposit confirmation command
- * @return the command with retries enabled
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_deposit_confirmation_with_retry (
   struct TALER_TESTING_Command cmd)
diff --git a/src/testing/testing_api_cmd_auditor_exec_auditor.c 
b/src/testing/testing_api_cmd_auditor_exec_auditor.c
index 06dfe91b..8ec128c0 100644
--- a/src/testing/testing_api_cmd_auditor_exec_auditor.c
+++ b/src/testing/testing_api_cmd_auditor_exec_auditor.c
@@ -115,7 +115,7 @@ auditor_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 auditor_traits (void *cls,
                 const void **ret,
                 const char *trait,
@@ -123,7 +123,7 @@ auditor_traits (void *cls,
 {
   struct AuditorState *ks = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &ks->auditor_proc),
+    TALER_TESTING_make_trait_process (&ks->auditor_proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -134,13 +134,6 @@ auditor_traits (void *cls,
 }
 
 
-/**
- * Make the "exec-auditor" CMD.
- *
- * @param label command label.
- * @param config_filename configuration filename.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_exec_auditor (const char *label,
                                 const char *config_filename)
diff --git a/src/testing/testing_api_cmd_auditor_exec_auditor_dbinit.c 
b/src/testing/testing_api_cmd_auditor_exec_auditor_dbinit.c
index c09ec291..2ab5bda8 100644
--- a/src/testing/testing_api_cmd_auditor_exec_auditor_dbinit.c
+++ b/src/testing/testing_api_cmd_auditor_exec_auditor_dbinit.c
@@ -124,7 +124,7 @@ auditor_dbinit_traits (void *cls,
 {
   struct AuditorDbinitState *ks = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &ks->auditor_dbinit_proc),
+    TALER_TESTING_make_trait_process (&ks->auditor_dbinit_proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -135,13 +135,6 @@ auditor_dbinit_traits (void *cls,
 }
 
 
-/**
- * Make the "exec-auditor-dbinit" CMD.
- *
- * @param label command label.
- * @param config_filename configuration filename.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_exec_auditor_dbinit (const char *label,
                                        const char *config_filename)
diff --git a/src/testing/testing_api_cmd_bank_admin_add_incoming.c 
b/src/testing/testing_api_cmd_bank_admin_add_incoming.c
index 28f907fd..58089f42 100644
--- a/src/testing/testing_api_cmd_bank_admin_add_incoming.c
+++ b/src/testing/testing_api_cmd_bank_admin_add_incoming.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018-2020 Taler Systems SA
+  Copyright (C) 2018-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
@@ -217,16 +217,15 @@ confirmation_cb (void *cls,
   fts->reserve_history.details.in_details.timestamp = timestamp;
   fts->reserve_history.details.in_details.wire_reference = serial_id;
   fts->aih = NULL;
+  if (http_status != fts->expected_http_status)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
   switch (http_status)
   {
   case MHD_HTTP_OK:
-    if (fts->expected_http_status !=
-        MHD_HTTP_OK)
-    {
-      GNUNET_break (0);
-      TALER_TESTING_interpreter_fail (is);
-      return;
-    }
     fts->serial_id = serial_id;
     fts->timestamp = timestamp;
     TALER_TESTING_interpreter_next (is);
@@ -246,13 +245,6 @@ confirmation_cb (void *cls,
     }
     break;
   case MHD_HTTP_CONFLICT:
-    if (fts->expected_http_status !=
-        MHD_HTTP_CONFLICT)
-    {
-      GNUNET_break (0);
-      TALER_TESTING_interpreter_fail (is);
-      return;
-    }
     TALER_TESTING_interpreter_next (is);
     return;
   default:
@@ -326,11 +318,9 @@ admin_add_incoming_run (void *cls,
     }
     if (GNUNET_OK !=
         TALER_TESTING_get_trait_reserve_priv (ref,
-                                              0,
                                               &reserve_priv))
     {
       if (GNUNET_OK != TALER_TESTING_get_trait_reserve_pub (ref,
-                                                            0,
                                                             &reserve_pub))
       {
         GNUNET_break (0);
@@ -420,13 +410,14 @@ admin_add_incoming_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 admin_add_incoming_traits (void *cls,
                            const void **ret,
                            const char *trait,
                            unsigned int index)
 {
   struct AdminAddIncomingState *fts = cls;
+  static const char *void_uri = "payto://void/the-exchange";
 
   if (MHD_HTTP_OK !=
       fts->expected_http_status)
@@ -435,21 +426,16 @@ admin_add_incoming_traits (void *cls,
   {
     struct TALER_TESTING_Trait traits[] = {
       TALER_TESTING_make_trait_bank_row (&fts->serial_id),
-      TALER_TESTING_make_trait_payto (TALER_TESTING_PT_DEBIT,
-                                      fts->payto_debit_account),
+      TALER_TESTING_make_trait_debit_payto_uri (&fts->payto_debit_account),
       /* Used as a marker, content does not matter */
-      TALER_TESTING_make_trait_payto (TALER_TESTING_PT_CREDIT,
-                                      "payto://void/the-exchange"),
-      TALER_TESTING_make_trait_url (TALER_TESTING_UT_EXCHANGE_BANK_ACCOUNT_URL,
-                                    fts->exchange_credit_url),
-      TALER_TESTING_make_trait_amount_obj (0, &fts->amount),
+      TALER_TESTING_make_trait_credit_payto_uri (&void_uri),
+      TALER_TESTING_make_trait_exchange_bank_account_url (
+        &fts->exchange_credit_url),
+      TALER_TESTING_make_trait_amount (&fts->amount),
       TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp),
-      TALER_TESTING_make_trait_reserve_priv (0,
-                                             &fts->reserve_priv),
-      TALER_TESTING_make_trait_reserve_pub (0,
-                                            &fts->reserve_pub),
-      TALER_TESTING_make_trait_reserve_history (0,
-                                                &fts->reserve_history),
+      TALER_TESTING_make_trait_reserve_priv (&fts->reserve_priv),
+      TALER_TESTING_make_trait_reserve_pub (&fts->reserve_pub),
+      TALER_TESTING_make_trait_reserve_history (&fts->reserve_history),
       TALER_TESTING_trait_end ()
     };
 
@@ -462,19 +448,15 @@ admin_add_incoming_traits (void *cls,
   {
     struct TALER_TESTING_Trait traits[] = {
       TALER_TESTING_make_trait_bank_row (&fts->serial_id),
-      TALER_TESTING_make_trait_payto (TALER_TESTING_PT_DEBIT,
-                                      fts->payto_debit_account),
+      TALER_TESTING_make_trait_debit_payto_uri (&fts->payto_debit_account),
       /* Used as a marker, content does not matter */
-      TALER_TESTING_make_trait_payto (TALER_TESTING_PT_CREDIT,
-                                      "payto://void/the-exchange"),
-      TALER_TESTING_make_trait_url (TALER_TESTING_UT_EXCHANGE_BANK_ACCOUNT_URL,
-                                    fts->exchange_credit_url),
-      TALER_TESTING_make_trait_amount_obj (0, &fts->amount),
+      TALER_TESTING_make_trait_credit_payto_uri (&void_uri),
+      TALER_TESTING_make_trait_exchange_bank_account_url (
+        &fts->exchange_credit_url),
+      TALER_TESTING_make_trait_amount (&fts->amount),
       TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp),
-      TALER_TESTING_make_trait_reserve_pub (0,
-                                            &fts->reserve_pub),
-      TALER_TESTING_make_trait_reserve_history (0,
-                                                &fts->reserve_history),
+      TALER_TESTING_make_trait_reserve_pub (&fts->reserve_pub),
+      TALER_TESTING_make_trait_reserve_history (&fts->reserve_history),
       TALER_TESTING_trait_end ()
     };
 
@@ -543,11 +525,11 @@ make_command (const char *label,
 
 
 struct TALER_TESTING_Command
-TALER_TESTING_cmd_admin_add_incoming (const char *label,
-                                      const char *amount,
-                                      const struct
-                                      TALER_BANK_AuthenticationData *auth,
-                                      const char *payto_debit_account)
+TALER_TESTING_cmd_admin_add_incoming (
+  const char *label,
+  const char *amount,
+  const struct TALER_BANK_AuthenticationData *auth,
+  const char *payto_debit_account)
 {
   return make_command (label,
                        make_fts (amount,
diff --git a/src/testing/testing_api_cmd_bank_admin_check.c 
b/src/testing/testing_api_cmd_bank_admin_check.c
index 473f3f3f..21a23083 100644
--- a/src/testing/testing_api_cmd_bank_admin_check.c
+++ b/src/testing/testing_api_cmd_bank_admin_check.c
@@ -95,7 +95,6 @@ check_bank_admin_transfer_run (void *cls,
   }
   if (GNUNET_OK !=
       TALER_TESTING_get_trait_reserve_pub (cmd_ref,
-                                           0,
                                            &reserve_pub))
   {
     GNUNET_break (0);
@@ -159,33 +158,6 @@ check_bank_admin_transfer_cleanup (void *cls,
 }
 
 
-/**
- * Offer internal data from a "bank admin check" CMD state.
- *
- * @param cls closure.
- * @param[out] ret result.
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success.
- */
-static int
-check_bank_admin_transfer_traits (void *cls,
-                                  const void **ret,
-                                  const char *trait,
-                                  unsigned int index)
-{
-  struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_trait_end ()
-  };
-
-  (void) cls;
-  return TALER_TESTING_get_trait (traits,
-                                  ret,
-                                  trait,
-                                  index);
-}
-
-
 /**
  * Make a "bank check" CMD.  It checks whether a particular wire transfer to
  * the exchange (credit) has been made or not.
@@ -217,8 +189,7 @@ TALER_TESTING_cmd_check_bank_admin_transfer
       .label = label,
       .cls = bcs,
       .run = &check_bank_admin_transfer_run,
-      .cleanup = &check_bank_admin_transfer_cleanup,
-      .traits = &check_bank_admin_transfer_traits
+      .cleanup = &check_bank_admin_transfer_cleanup
     };
 
     return cmd;
diff --git a/src/testing/testing_api_cmd_bank_check.c 
b/src/testing/testing_api_cmd_bank_check.c
index c01bc709..ed4cde46 100644
--- a/src/testing/testing_api_cmd_bank_check.c
+++ b/src/testing/testing_api_cmd_bank_check.c
@@ -74,6 +74,7 @@ struct BankCheckState
   const char *deposit_reference;
 };
 
+
 /**
  * Run the command.
  *
@@ -90,17 +91,17 @@ check_bank_transfer_run (void *cls,
   struct TALER_Amount amount;
   char *debit_account;
   char *credit_account;
-  const char *exchange_base_url;
-  const char *debit_payto;
-  const char *credit_payto;
+  const char **exchange_base_url;
+  const char **debit_payto;
+  const char **credit_payto;
 
   (void) cmd;
   if (NULL == bcs->deposit_reference)
   {
     TALER_LOG_INFO ("Deposit reference NOT given\n");
-    debit_payto = bcs->debit_payto;
-    credit_payto = bcs->credit_payto;
-    exchange_base_url = bcs->exchange_base_url;
+    debit_payto = &bcs->debit_payto;
+    credit_payto = &bcs->credit_payto;
+    exchange_base_url = &bcs->exchange_base_url;
 
     if (GNUNET_OK !=
         TALER_string_to_amount (bcs->amount,
@@ -130,37 +131,33 @@ check_bank_transfer_run (void *cls,
     if (NULL == deposit_cmd)
       TALER_TESTING_FAIL (is);
     if ( (GNUNET_OK !=
-          TALER_TESTING_get_trait_amount_obj (deposit_cmd,
-                                              0,
-                                              &amount_ptr)) ||
+          TALER_TESTING_get_trait_amount (deposit_cmd,
+                                          &amount_ptr)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_payto (deposit_cmd,
-                                         TALER_TESTING_PT_DEBIT,
-                                         &debit_payto)) ||
+          TALER_TESTING_get_trait_debit_payto_uri (deposit_cmd,
+                                                   &debit_payto)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_payto (deposit_cmd,
-                                         TALER_TESTING_PT_CREDIT,
-                                         &credit_payto)) ||
+          TALER_TESTING_get_trait_credit_payto_uri (deposit_cmd,
+                                                    &credit_payto)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_url (deposit_cmd,
-                                       TALER_TESTING_UT_EXCHANGE_BASE_URL,
-                                       &exchange_base_url)) )
+          TALER_TESTING_get_trait_exchange_url (deposit_cmd,
+                                                &exchange_base_url)) )
       TALER_TESTING_FAIL (is);
     amount = *amount_ptr;
   }
 
 
-  debit_account = TALER_xtalerbank_account_from_payto (debit_payto);
-  credit_account = TALER_xtalerbank_account_from_payto (credit_payto);
+  debit_account = TALER_xtalerbank_account_from_payto (*debit_payto);
+  credit_account = TALER_xtalerbank_account_from_payto (*credit_payto);
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "converted debit_payto (%s) to debit_account (%s)\n",
-              debit_payto,
+              *debit_payto,
               debit_account);
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "converted credit_payto (%s) to credit_account (%s)\n",
-              credit_payto,
+              *credit_payto,
               credit_account);
 
   if (GNUNET_OK !=
@@ -168,7 +165,7 @@ check_bank_transfer_run (void *cls,
                                   &amount,
                                   debit_account,
                                   credit_account,
-                                  exchange_base_url,
+                                  *exchange_base_url,
                                   &bcs->wtid))
   {
     GNUNET_break (0);
@@ -209,7 +206,7 @@ check_bank_transfer_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 check_bank_transfer_traits (void *cls,
                             const void **ret,
                             const char *trait,
@@ -218,10 +215,9 @@ check_bank_transfer_traits (void *cls,
   struct BankCheckState *bcs = cls;
   struct TALER_WireTransferIdentifierRawP *wtid_ptr = &bcs->wtid;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_wtid (0,
-                                   wtid_ptr),
-    TALER_TESTING_make_trait_url (TALER_TESTING_UT_EXCHANGE_BASE_URL,
-                                  bcs->exchange_base_url),
+    TALER_TESTING_make_trait_wtid (wtid_ptr),
+    TALER_TESTING_make_trait_exchange_url (
+      &bcs->exchange_base_url),
     TALER_TESTING_trait_end ()
   };
 
diff --git a/src/testing/testing_api_cmd_bank_history_credit.c 
b/src/testing/testing_api_cmd_bank_history_credit.c
index c052b55f..a7ad40a4 100644
--- a/src/testing/testing_api_cmd_bank_history_credit.c
+++ b/src/testing/testing_api_cmd_bank_history_credit.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018-2020 Taler Systems SA
+  Copyright (C) 2018-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as
@@ -93,10 +93,10 @@ struct HistoryState
   uint64_t results_obtained;
 
   /**
-   * Set to GNUNET_YES if the callback detects something
+   * Set to true if the callback detects something
    * unexpected.
    */
-  int failed;
+  bool failed;
 
   /**
    * Expected history.
@@ -111,32 +111,6 @@ struct HistoryState
 };
 
 
-/**
- * Offer internal data to other commands.
- *
- * @param cls closure.
- * @param[out] ret set to the wanted data.
- * @param trait name of the trait.
- * @param index index number of the traits to be returned.
- *
- * @return #GNUNET_OK on success
- */
-static int
-history_traits (void *cls,
-                const void **ret,
-                const char *trait,
-                unsigned int index)
-{
-  (void) cls;
-  (void) ret;
-  (void) trait;
-  (void) index;
-  /* Must define this function because some callbacks
-   * look for certain traits on _all_ the commands. */
-  return GNUNET_SYSERR;
-}
-
-
 /**
  * Log which history we expected.  Called when an error occurs.
  *
@@ -210,9 +184,8 @@ build_history (struct TALER_TESTING_Interpreter *is,
                                                   hs->start_row_reference);
     GNUNET_assert (NULL != add_incoming_cmd);
     GNUNET_assert (GNUNET_OK ==
-                   TALER_TESTING_get_trait_uint64 (add_incoming_cmd,
-                                                   0,
-                                                   &row_id_start));
+                   TALER_TESTING_get_trait_row (add_incoming_cmd,
+                                                &row_id_start));
   }
 
   GNUNET_assert (0 != hs->num_results);
@@ -249,11 +222,11 @@ build_history (struct TALER_TESTING_Interpreter *is,
   {
     const struct TALER_TESTING_Command *cmd = &is->commands[off];
     const uint64_t *row_id;
-    const char *credit_account;
-    const char *debit_account;
+    const char **credit_account;
+    const char **debit_account;
     const struct TALER_Amount *amount;
     const struct TALER_ReservePublicKeyP *reserve_pub;
-    const char *exchange_credit_url;
+    const char **exchange_credit_url;
 
     /* The following command allows us to skip over those CMDs
      * that do not offer a "row_id" trait.  Such skipped CMDs are
@@ -262,25 +235,21 @@ build_history (struct TALER_TESTING_Interpreter *is,
           TALER_TESTING_get_trait_bank_row (cmd,
                                             &row_id)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_payto (cmd,
-                                         TALER_TESTING_PT_CREDIT,
-                                         &credit_account)) ||
+          TALER_TESTING_get_trait_credit_payto_uri (cmd,
+                                                    &credit_account)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_payto (cmd,
-                                         TALER_TESTING_PT_DEBIT,
-                                         &debit_account)) ||
+          TALER_TESTING_get_trait_debit_payto_uri (cmd,
+                                                   &debit_account)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_amount_obj (cmd,
-                                              0,
-                                              &amount)) ||
+          TALER_TESTING_get_trait_amount (cmd,
+                                          &amount)) ||
          (GNUNET_OK !=
           TALER_TESTING_get_trait_reserve_pub (cmd,
-                                               0,
                                                &reserve_pub)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_url (cmd,
-                                       
TALER_TESTING_UT_EXCHANGE_BANK_ACCOUNT_URL,
-                                       &exchange_credit_url)) )
+          TALER_TESTING_get_trait_exchange_bank_account_url (
+            cmd,
+            &exchange_credit_url)) )
       continue; /* not an interesting event */
     /* Seek "/history/incoming" starting row.  */
     if ( (NULL != row_id_start) &&
@@ -295,7 +264,7 @@ build_history (struct TALER_TESTING_Interpreter *is,
     if (GNUNET_NO == ok)
       continue; /* skip until we find the marker */
     if (0 != strcasecmp (hs->account_url,
-                         exchange_credit_url))
+                         *exchange_credit_url))
       continue; /* account mismatch */
     if (total >= GNUNET_MAX (hs->num_results,
                              -hs->num_results) )
@@ -304,20 +273,20 @@ build_history (struct TALER_TESTING_Interpreter *is,
       break;
     }
     TALER_LOG_INFO ("Found history: %s->%s for account %s\n",
-                    debit_account,
-                    credit_account,
+                    *debit_account,
+                    *credit_account,
                     hs->account_url);
     /* found matching record, make sure we have room */
     if (pos == total)
       GNUNET_array_grow (h,
                          total,
                          pos * 2);
-    h[pos].url = GNUNET_strdup (debit_account);
+    h[pos].url = GNUNET_strdup (*debit_account);
     h[pos].details.debit_account_uri = h[pos].url;
     h[pos].details.amount = *amount;
     h[pos].row_id = *row_id;
     h[pos].details.reserve_pub = *reserve_pub;
-    h[pos].details.credit_account_uri = exchange_credit_url;
+    h[pos].details.credit_account_uri = *exchange_credit_url;
     pos++;
   }
   GNUNET_assert (GNUNET_YES == ok);
@@ -405,7 +374,7 @@ check_result (struct History *h,
  *        reply was not in JSON.
  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
-static int
+static enum GNUNET_GenericReturnValue
 history_cb (void *cls,
             unsigned int http_status,
             enum TALER_ErrorCode ec,
@@ -421,7 +390,7 @@ history_cb (void *cls,
   {
     hs->hh = NULL;
     if ( (hs->results_obtained != hs->total) ||
-         (GNUNET_YES == hs->failed) ||
+         (hs->failed) ||
          (MHD_HTTP_NO_CONTENT != http_status) )
     {
       GNUNET_break (0);
@@ -432,7 +401,7 @@ history_cb (void *cls,
                   (unsigned long long) hs->results_obtained,
                   http_status,
                   (int) ec,
-                  hs->failed);
+                  hs->failed ? 1 : 0);
       print_expected (hs->h,
                       hs->total,
                       UINT_MAX);
@@ -469,7 +438,7 @@ history_cb (void *cls,
                 acc);
     if (NULL != acc)
       free (acc);
-    hs->failed = GNUNET_YES;
+    hs->failed = true;
     return GNUNET_SYSERR;
   }
   hs->results_obtained++;
@@ -499,16 +468,15 @@ history_run (void *cls,
   {
     const struct TALER_TESTING_Command *history_cmd;
 
-    history_cmd = TALER_TESTING_interpreter_lookup_command
-                    (is, hs->start_row_reference);
-
+    history_cmd = TALER_TESTING_interpreter_lookup_command (
+      is,
+      hs->start_row_reference);
     if (NULL == history_cmd)
       TALER_TESTING_FAIL (is);
 
     if (GNUNET_OK !=
-        TALER_TESTING_get_trait_uint64 (history_cmd,
-                                        0,
-                                        &row_ptr))
+        TALER_TESTING_get_trait_row (history_cmd,
+                                     &row_ptr))
       TALER_TESTING_FAIL (is);
     else
       row_id = *row_ptr;
@@ -574,8 +542,7 @@ TALER_TESTING_cmd_bank_credits (
       .label = label,
       .cls = hs,
       .run = &history_run,
-      .cleanup = &history_cleanup,
-      .traits = &history_traits
+      .cleanup = &history_cleanup
     };
 
     return cmd;
diff --git a/src/testing/testing_api_cmd_bank_history_debit.c 
b/src/testing/testing_api_cmd_bank_history_debit.c
index 779facee..a1dee81e 100644
--- a/src/testing/testing_api_cmd_bank_history_debit.c
+++ b/src/testing/testing_api_cmd_bank_history_debit.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018-2020 Taler Systems SA
+  Copyright (C) 2018-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as
@@ -115,32 +115,6 @@ struct HistoryState
 };
 
 
-/**
- * Offer internal data to other commands.
- *
- * @param cls closure.
- * @param[out] ret set to the wanted data.
- * @param trait name of the trait.
- * @param index index number of the traits to be returned.
- *
- * @return #GNUNET_OK on success
- */
-static int
-history_traits (void *cls,
-                const void **ret,
-                const char *trait,
-                unsigned int index)
-{
-  (void) cls;
-  (void) ret;
-  (void) trait;
-  (void) index;
-  /* Must define this function because some callbacks
-   * look for certain traits on _all_ the commands. */
-  return GNUNET_SYSERR;
-}
-
-
 /**
  * Log which history we expected.  Called when an error occurs.
  *
@@ -207,13 +181,13 @@ build_history (struct TALER_TESTING_Interpreter *is,
       ("`%s': start row given via reference `%s'\n",
       TALER_TESTING_interpreter_get_current_label  (is),
       hs->start_row_reference);
-    add_incoming_cmd = TALER_TESTING_interpreter_lookup_command
-                         (is, hs->start_row_reference);
+    add_incoming_cmd = TALER_TESTING_interpreter_lookup_command (
+      is,
+      hs->start_row_reference);
     GNUNET_assert (NULL != add_incoming_cmd);
     GNUNET_assert (GNUNET_OK ==
-                   TALER_TESTING_get_trait_uint64 (add_incoming_cmd,
-                                                   0,
-                                                   &row_id_start));
+                   TALER_TESTING_get_trait_row (add_incoming_cmd,
+                                                &row_id_start));
   }
 
   GNUNET_assert (0 != hs->num_results);
@@ -255,11 +229,11 @@ build_history (struct TALER_TESTING_Interpreter *is,
   {
     const struct TALER_TESTING_Command *cmd = &is->commands[off];
     const uint64_t *row_id;
-    const char *debit_account;
-    const char *credit_account;
+    const char **debit_account;
+    const char **credit_account;
     const struct TALER_Amount *amount;
     const struct TALER_WireTransferIdentifierRawP *wtid;
-    const char *exchange_base_url;
+    const char **exchange_base_url;
 
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Checking if command %s is relevant for debit history\n",
@@ -268,25 +242,20 @@ build_history (struct TALER_TESTING_Interpreter *is,
           TALER_TESTING_get_trait_bank_row (cmd,
                                             &row_id)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_payto (cmd,
-                                         TALER_TESTING_PT_DEBIT,
-                                         &debit_account)) ||
+          TALER_TESTING_get_trait_debit_payto_uri (cmd,
+                                                   &debit_account)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_payto (cmd,
-                                         TALER_TESTING_PT_CREDIT,
-                                         &credit_account)) ||
+          TALER_TESTING_get_trait_credit_payto_uri (cmd,
+                                                    &credit_account)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_amount_obj (cmd,
-                                              0,
-                                              &amount)) ||
+          TALER_TESTING_get_trait_amount (cmd,
+                                          &amount)) ||
          (GNUNET_OK !=
           TALER_TESTING_get_trait_wtid (cmd,
-                                        0,
                                         &wtid)) ||
          (GNUNET_OK !=
-          TALER_TESTING_get_trait_url (cmd,
-                                       TALER_TESTING_UT_EXCHANGE_BASE_URL,
-                                       &exchange_base_url)) )
+          TALER_TESTING_get_trait_exchange_url (cmd,
+                                                &exchange_base_url)) )
       continue; /* not an event we care about */
     /* Seek "/history/outgoing" starting row.  */
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -310,22 +279,22 @@ build_history (struct TALER_TESTING_Interpreter *is,
       break;
     }
     TALER_LOG_INFO ("Found history: %s->%s for account %s\n",
-                    debit_account,
-                    credit_account,
+                    *debit_account,
+                    *credit_account,
                     hs->account_url);
     /* found matching record, make sure we have room */
     if (pos == total)
       GNUNET_array_grow (h,
                          total,
                          pos * 2);
-    h[pos].c_url = GNUNET_strdup (credit_account);
-    h[pos].d_url = GNUNET_strdup (debit_account);
+    h[pos].c_url = GNUNET_strdup (*credit_account);
+    h[pos].d_url = GNUNET_strdup (*debit_account);
     h[pos].details.credit_account_uri = h[pos].c_url;
     h[pos].details.debit_account_uri = h[pos].d_url;
     h[pos].details.amount = *amount;
     h[pos].row_id = *row_id;
     h[pos].details.wtid = *wtid;
-    h[pos].details.exchange_base_url = exchange_base_url;
+    h[pos].details.exchange_base_url = *exchange_base_url;
     pos++;
   }
   GNUNET_assert (GNUNET_YES == ok);
@@ -350,7 +319,7 @@ build_history (struct TALER_TESTING_Interpreter *is,
  * @param details the expected transaction details.
  * @return #GNUNET_OK if the transaction is what we expect.
  */
-static int
+static enum GNUNET_GenericReturnValue
 check_result (struct History *h,
               uint64_t total,
               unsigned int off,
@@ -407,7 +376,7 @@ check_result (struct History *h,
  *        reply was not in JSON.
  * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
  */
-static int
+static enum GNUNET_GenericReturnValue
 history_cb (void *cls,
             unsigned int http_status,
             enum TALER_ErrorCode ec,
@@ -508,9 +477,8 @@ history_run (void *cls,
     if (NULL == history_cmd)
       TALER_TESTING_FAIL (is);
     if (GNUNET_OK !=
-        TALER_TESTING_get_trait_uint64 (history_cmd,
-                                        0,
-                                        &row_ptr))
+        TALER_TESTING_get_trait_row (history_cmd,
+                                     &row_ptr))
       TALER_TESTING_FAIL (is);
     else
       row_id = *row_ptr;
@@ -558,17 +526,6 @@ history_cleanup (void *cls,
 }
 
 
-/**
- * Make a "history" CMD.
- *
- * @param label command label.
- * @param auth login data to use
- * @param start_row_reference reference to a command that can
- *        offer a row identifier, to be used as the starting row
- *        to accept in the result.
- * @param num_results how many rows we want in the result.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_bank_debits (const char *label,
                                const struct TALER_BANK_AuthenticationData 
*auth,
@@ -588,8 +545,7 @@ TALER_TESTING_cmd_bank_debits (const char *label,
       .label = label,
       .cls = hs,
       .run = &history_run,
-      .cleanup = &history_cleanup,
-      .traits = &history_traits
+      .cleanup = &history_cleanup
     };
 
     return cmd;
diff --git a/src/testing/testing_api_cmd_bank_transfer.c 
b/src/testing/testing_api_cmd_bank_transfer.c
index 565d6e46..0755a71d 100644
--- a/src/testing/testing_api_cmd_bank_transfer.c
+++ b/src/testing/testing_api_cmd_bank_transfer.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018-2020 Taler Systems SA
+  Copyright (C) 2018-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
@@ -310,7 +310,7 @@ transfer_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 transfer_traits (void *cls,
                  const void **ret,
                  const char *trait,
@@ -318,17 +318,16 @@ transfer_traits (void *cls,
 {
   struct TransferState *fts = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_url (TALER_TESTING_UT_EXCHANGE_BASE_URL,
-                                  fts->exchange_base_url),
+    TALER_TESTING_make_trait_exchange_url (
+      (const char **) &fts->exchange_base_url),
     TALER_TESTING_make_trait_bank_row (&fts->serial_id),
-    TALER_TESTING_make_trait_payto (TALER_TESTING_PT_CREDIT,
-                                    fts->payto_credit_account),
-    TALER_TESTING_make_trait_payto (TALER_TESTING_PT_DEBIT,
-                                    fts->payto_debit_account),
-    TALER_TESTING_make_trait_amount_obj (0, &fts->amount),
+    TALER_TESTING_make_trait_credit_payto_uri (
+      (const char **) &fts->payto_credit_account),
+    TALER_TESTING_make_trait_debit_payto_uri (
+      (const char **) &fts->payto_debit_account),
+    TALER_TESTING_make_trait_amount (&fts->amount),
     TALER_TESTING_make_trait_absolute_time (0, &fts->timestamp),
-    TALER_TESTING_make_trait_wtid (0,
-                                   &fts->wtid),
+    TALER_TESTING_make_trait_wtid (&fts->wtid),
     TALER_TESTING_trait_end ()
   };
 
@@ -339,18 +338,6 @@ transfer_traits (void *cls,
 }
 
 
-/**
- * Create transfer command.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @param auth authentication data to use
- * @param payto_debit_account which account sends money.
- * @param payto_credit_account which account receives money.
- * @param wtid wire transfer identifier to use
- * @param exchange_base_url exchange URL to use
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_transfer (const char *label,
                             const char *amount,
@@ -394,13 +381,6 @@ TALER_TESTING_cmd_transfer (const char *label,
 }
 
 
-/**
- * Modify a transfer command to enable retries when the reserve is not yet
- * full or we get other transient errors from the bank.
- *
- * @param cmd a fakebank transfer command
- * @return the command with retries enabled
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_transfer_retry (struct TALER_TESTING_Command cmd)
 {
diff --git a/src/testing/testing_api_cmd_batch.c 
b/src/testing/testing_api_cmd_batch.c
index ca23d7fd..e8f76ca3 100644
--- a/src/testing/testing_api_cmd_batch.c
+++ b/src/testing/testing_api_cmd_batch.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2018 Taler Systems SA
+  Copyright (C) 2014-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as
@@ -113,22 +113,15 @@ batch_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 batch_traits (void *cls,
               const void **ret,
               const char *trait,
               unsigned int index)
 {
-#define CURRENT_CMD_INDEX 0
-#define BATCH_INDEX 1
-
   struct BatchState *bs = cls;
-
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_cmd
-      (CURRENT_CMD_INDEX, &bs->batch[bs->batch_ip]),
-    TALER_TESTING_make_trait_cmd
-      (BATCH_INDEX, bs->batch),
+    TALER_TESTING_make_trait_batch_cmds (&bs->batch),
     TALER_TESTING_trait_end ()
   };
 
@@ -140,18 +133,6 @@ batch_traits (void *cls,
 }
 
 
-/**
- * Create a "batch" command.  Such command takes a
- * end_CMD-terminated array of CMDs and executed them.
- * Once it hits the end CMD, it passes the control
- * to the next top-level CMD, regardless of it being
- * another batch or ordinary CMD.
- *
- * @param label the command label.
- * @param batch array of CMDs to execute.
- *
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_batch (const char *label,
                          struct TALER_TESTING_Command *batch)
@@ -185,11 +166,6 @@ TALER_TESTING_cmd_batch (const char *label,
 }
 
 
-/**
- * Advance internal pointer to next command.
- *
- * @param is interpreter state.
- */
 void
 TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is)
 {
@@ -206,23 +182,13 @@ TALER_TESTING_cmd_batch_next (struct 
TALER_TESTING_Interpreter *is)
 }
 
 
-/**
- * Test if this command is a batch command.
- *
- * @return false if not, true if it is a batch command
- */
-int
+bool
 TALER_TESTING_cmd_is_batch (const struct TALER_TESTING_Command *cmd)
 {
   return cmd->run == &batch_run;
 }
 
 
-/**
- * Obtain what command the batch is at.
- *
- * @return cmd current batch command
- */
 struct TALER_TESTING_Command *
 TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd)
 {
@@ -233,12 +199,6 @@ TALER_TESTING_cmd_batch_get_current (const struct 
TALER_TESTING_Command *cmd)
 }
 
 
-/**
- * Set what command the batch should be at.
- *
- * @param cmd current batch command
- * @param new_ip where to move the IP
- */
 void
 TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd,
                                      unsigned int new_ip)
diff --git a/src/testing/testing_api_cmd_deposit.c 
b/src/testing/testing_api_cmd_deposit.c
index 58322b1d..29b2ce64 100644
--- a/src/testing/testing_api_cmd_deposit.c
+++ b/src/testing/testing_api_cmd_deposit.c
@@ -84,6 +84,11 @@ struct DepositState
    */
   struct GNUNET_TIME_Absolute refund_deadline;
 
+  /**
+   * Wire deadline.
+   */
+  struct GNUNET_TIME_Absolute wire_deadline;
+
   /**
    * Set (by the interpreter) to a fresh private key.  This
    * key will be used to sign the deposit request.
@@ -285,10 +290,18 @@ deposit_run (void *cls,
   const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
   const struct TALER_DenominationSignature *denom_pub_sig;
   struct TALER_CoinSpendSignatureP coin_sig;
-  struct GNUNET_TIME_Absolute wire_deadline;
   struct TALER_MerchantPublicKeyP merchant_pub;
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
   enum TALER_ErrorCode ec;
+  struct TALER_WireSalt wire_salt;
+  const char *payto_uri;
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_string ("payto_uri",
+                             &payto_uri),
+    GNUNET_JSON_spec_fixed_auto ("salt",
+                                 &wire_salt),
+    GNUNET_JSON_spec_end ()
+  };
 
   (void) cmd;
   ds->is = is;
@@ -310,6 +323,7 @@ deposit_run (void *cls,
     ds->coin_reference = ods->coin_reference;
     ds->coin_index = ods->coin_index;
     ds->wire_details = json_incref (ods->wire_details);
+    GNUNET_assert (NULL != ds->wire_details);
     ds->contract_terms = json_incref (ods->contract_terms);
     ds->wallet_timestamp = ods->wallet_timestamp;
     ds->refund_deadline = ods->refund_deadline;
@@ -333,7 +347,6 @@ deposit_run (void *cls,
     }
     if ( (GNUNET_OK !=
           TALER_TESTING_get_trait_merchant_priv (cmd,
-                                                 0,
                                                  &merchant_priv)) )
     {
       GNUNET_break (0);
@@ -342,6 +355,19 @@ deposit_run (void *cls,
     }
     ds->merchant_priv = *merchant_priv;
   }
+  GNUNET_assert (NULL != ds->wire_details);
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (ds->wire_details,
+                         spec,
+                         NULL, NULL))
+  {
+    json_dumpf (ds->wire_details,
+                stderr,
+                JSON_INDENT (2));
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
   GNUNET_assert (ds->coin_reference);
   coin_cmd = TALER_TESTING_interpreter_lookup_command (is,
                                                        ds->coin_reference);
@@ -380,40 +406,48 @@ deposit_run (void *cls,
   {
     struct GNUNET_TIME_Relative refund_deadline;
 
-    refund_deadline = GNUNET_TIME_absolute_get_remaining (ds->refund_deadline);
-    wire_deadline = GNUNET_TIME_relative_to_absolute
-                      (GNUNET_TIME_relative_multiply (refund_deadline, 2));
+    refund_deadline
+      = GNUNET_TIME_absolute_get_remaining (ds->refund_deadline);
+    ds->wire_deadline
+      = GNUNET_TIME_relative_to_absolute (
+          GNUNET_TIME_relative_multiply (refund_deadline,
+                                         2));
   }
   else
   {
     ds->refund_deadline = ds->wallet_timestamp;
-    wire_deadline = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_ZERO);
+    ds->wire_deadline
+      = GNUNET_TIME_relative_to_absolute (
+          GNUNET_TIME_UNIT_ZERO);
   }
   GNUNET_CRYPTO_eddsa_key_get_public (&ds->merchant_priv.eddsa_priv,
                                       &merchant_pub.eddsa_pub);
-  (void) GNUNET_TIME_round_abs (&wire_deadline);
+  (void) GNUNET_TIME_round_abs (&ds->wire_deadline);
   {
-    struct GNUNET_HashCode h_wire;
+    struct TALER_MerchantWireHash h_wire;
 
     GNUNET_assert (GNUNET_OK ==
                    TALER_JSON_merchant_wire_signature_hash (ds->wire_details,
                                                             &h_wire));
-    TALER_EXCHANGE_deposit_permission_sign (&ds->amount,
-                                            &denom_pub->fee_deposit,
-                                            &h_wire,
-                                            &h_contract_terms,
-                                            &denom_pub->h_key,
-                                            coin_priv,
-                                            ds->wallet_timestamp,
-                                            &merchant_pub,
-                                            ds->refund_deadline,
-                                            &coin_sig);
+    TALER_wallet_deposit_sign (&ds->amount,
+                               &denom_pub->fee_deposit,
+                               &h_wire,
+                               &h_contract_terms,
+                               NULL, /* FIXME: extension hash! */
+                               &denom_pub->h_key,
+                               ds->wallet_timestamp,
+                               &merchant_pub,
+                               ds->refund_deadline,
+                               coin_priv,
+                               &coin_sig);
   }
   ds->dh = TALER_EXCHANGE_deposit (is->exchange,
                                    &ds->amount,
-                                   wire_deadline,
-                                   ds->wire_details,
+                                   ds->wire_deadline,
+                                   payto_uri,
+                                   &wire_salt,
                                    &h_contract_terms,
+                                   NULL, /* FIXME: extension object */
                                    &coin_pub,
                                    denom_pub_sig,
                                    &denom_pub->key,
@@ -476,10 +510,9 @@ deposit_cleanup (void *cls,
  * @param[out] ret result.
  * @param trait name of the trait.
  * @param index index number of the object to offer.
- *
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 deposit_traits (void *cls,
                 const void **ret,
                 const char *trait,
@@ -519,27 +552,22 @@ deposit_traits (void *cls,
     struct TALER_TESTING_Trait traits[] = {
       /* First two traits are only available if
          ds->traits is #GNUNET_YES */
-      TALER_TESTING_make_trait_exchange_pub (0,
-                                             &ds->exchange_pub),
-      TALER_TESTING_make_trait_exchange_sig (0,
-                                             &ds->exchange_sig),
+      TALER_TESTING_make_trait_exchange_pub (0, &ds->exchange_pub),
+      TALER_TESTING_make_trait_exchange_sig (0, &ds->exchange_sig),
       /* These traits are always available */
       TALER_TESTING_make_trait_coin_priv (0,
                                           coin_spent_priv),
-      TALER_TESTING_make_trait_wire_details (0,
-                                             ds->wire_details),
-      TALER_TESTING_make_trait_contract_terms (0,
-                                               ds->contract_terms),
-      TALER_TESTING_make_trait_merchant_priv (0,
-                                              &ds->merchant_priv),
-      TALER_TESTING_make_trait_amount_obj (
-        TALER_TESTING_CMD_DEPOSIT_TRAIT_IDX_DEPOSIT_VALUE,
-        &ds->amount),
-      TALER_TESTING_make_trait_amount_obj (
-        TALER_TESTING_CMD_DEPOSIT_TRAIT_IDX_DEPOSIT_FEE,
-        &ds->deposit_fee),
+      TALER_TESTING_make_trait_wire_details (ds->wire_details),
+      TALER_TESTING_make_trait_contract_terms (ds->contract_terms),
+      TALER_TESTING_make_trait_merchant_priv (&ds->merchant_priv),
+      TALER_TESTING_make_trait_deposit_amount (&ds->amount),
+      TALER_TESTING_make_trait_deposit_fee_amount (&ds->deposit_fee),
       TALER_TESTING_make_trait_absolute_time (0,
                                               &ds->exchange_timestamp),
+      TALER_TESTING_make_trait_wire_deadline (0,
+                                              &ds->wire_deadline),
+      TALER_TESTING_make_trait_refund_deadline (0,
+                                                &ds->refund_deadline),
       TALER_TESTING_trait_end ()
     };
 
@@ -553,28 +581,6 @@ deposit_traits (void *cls,
 }
 
 
-/**
- * Create a "deposit" command.
- *
- * @param label command label.
- * @param coin_reference reference to any operation that can
- *        provide a coin.
- * @param coin_index if @a withdraw_reference offers an array of
- *        coins, this parameter selects which one in that array.
- *        This value is currently ignored, as only one-coin
- *        withdrawals are implemented.
- * @param target_account_payto target account for the "deposit"
- *        request.
- * @param contract_terms contract terms to be signed over by the
- *        coin.
- * @param refund_deadline refund deadline, zero means 'no refunds'.
- *        Note, if time were absolute, then it would have come
- *        one day and disrupt tests meaning.
- * @param amount how much is going to be deposited.
- * @param expected_response_code expected HTTP response code.
- *
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_deposit (const char *label,
                            const char *coin_reference,
@@ -586,13 +592,12 @@ TALER_TESTING_cmd_deposit (const char *label,
                            unsigned int expected_response_code)
 {
   struct DepositState *ds;
-  json_t *wire_details;
 
-  wire_details = TALER_TESTING_make_wire_details (target_account_payto);
   ds = GNUNET_new (struct DepositState);
   ds->coin_reference = coin_reference;
   ds->coin_index = coin_index;
-  ds->wire_details = wire_details;
+  ds->wire_details = TALER_TESTING_make_wire_details (target_account_payto);
+  GNUNET_assert (NULL != ds->wire_details);
   ds->contract_terms = json_loads (contract_terms,
                                    JSON_REJECT_DUPLICATES,
                                    NULL);
@@ -638,30 +643,6 @@ TALER_TESTING_cmd_deposit (const char *label,
 }
 
 
-/**
- * Create a "deposit" command that references an existing merchant key.
- *
- * @param label command label.
- * @param coin_reference reference to any operation that can
- *        provide a coin.
- * @param coin_index if @a withdraw_reference offers an array of
- *        coins, this parameter selects which one in that array.
- *        This value is currently ignored, as only one-coin
- *        withdrawals are implemented.
- * @param target_account_payto target account for the "deposit"
- *        request.
- * @param contract_terms contract terms to be signed over by the
- *        coin.
- * @param refund_deadline refund deadline, zero means 'no refunds'.
- *        Note, if time were absolute, then it would have come
- *        one day and disrupt tests meaning.
- * @param amount how much is going to be deposited.
- * @param expected_response_code expected HTTP response code.
- * @param merchant_priv_reference reference to another operation
- *        that has a merchant private key trait
- *
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_deposit_with_ref (const char *label,
                                     const char *coin_reference,
@@ -674,14 +655,13 @@ TALER_TESTING_cmd_deposit_with_ref (const char *label,
                                     const char *merchant_priv_reference)
 {
   struct DepositState *ds;
-  json_t *wire_details;
 
-  wire_details = TALER_TESTING_make_wire_details (target_account_payto);
   ds = GNUNET_new (struct DepositState);
   ds->merchant_priv_reference = merchant_priv_reference;
   ds->coin_reference = coin_reference;
   ds->coin_index = coin_index;
-  ds->wire_details = wire_details;
+  ds->wire_details = TALER_TESTING_make_wire_details (target_account_payto);
+  GNUNET_assert (NULL != ds->wire_details);
   ds->contract_terms = json_loads (contract_terms,
                                    JSON_REJECT_DUPLICATES,
                                    NULL);
@@ -726,15 +706,6 @@ TALER_TESTING_cmd_deposit_with_ref (const char *label,
 }
 
 
-/**
- * Create a "deposit" command that repeats an existing
- * deposit command.
- *
- * @param label command label.
- * @param deposit_reference which deposit command should we repeat
- * @param expected_response_code expected HTTP response code.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_deposit_replay (const char *label,
                                   const char *deposit_reference,
@@ -759,13 +730,6 @@ TALER_TESTING_cmd_deposit_replay (const char *label,
 }
 
 
-/**
- * Modify a deposit command to enable retries when we get transient
- * errors from the exchange.
- *
- * @param cmd a deposit command
- * @return the command with retries enabled
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_deposit_with_retry (struct TALER_TESTING_Command cmd)
 {
diff --git a/src/testing/testing_api_cmd_deposits_get.c 
b/src/testing/testing_api_cmd_deposits_get.c
index 61358291..baddb2d0 100644
--- a/src/testing/testing_api_cmd_deposits_get.c
+++ b/src/testing/testing_api_cmd_deposits_get.c
@@ -49,12 +49,23 @@ struct TrackTransactionState
    */
   unsigned int expected_response_code;
 
+  /**
+   * Set to the KYC UUID *if* the exchange replied with
+   * a request for KYC (#MHD_HTTP_ACCEPTED).
+   */
+  uint64_t kyc_uuid;
+
   /**
    * Reference to any operation that can provide a transaction.
    * Will be the transaction to track.
    */
   const char *transaction_reference;
 
+  /**
+   * Payto URI of the merchant receiving the deposit.
+   */
+  char *merchant_payto_uri;
+
   /**
    * Index of the coin involved in the transaction.  Recall:
    * at the exchange, the tracking is done _per coin_.
@@ -128,7 +139,6 @@ deposit_wtid_cb (void *cls,
 
       if (GNUNET_OK !=
           TALER_TESTING_get_trait_wtid (bank_transfer_cmd,
-                                        0,
                                         &wtid_want))
       {
         GNUNET_break (0);
@@ -148,6 +158,7 @@ deposit_wtid_cb (void *cls,
     break;
   case MHD_HTTP_ACCEPTED:
     /* allowed, nothing to check here */
+    tts->kyc_uuid = dr->details.accepted.payment_target_uuid;
     break;
   case MHD_HTTP_NOT_FOUND:
     /* allowed, nothing to check here */
@@ -178,8 +189,8 @@ track_transaction_run (void *cls,
   struct TALER_CoinSpendPublicKeyP coin_pub;
   const json_t *contract_terms;
   const json_t *wire_details;
-  struct GNUNET_HashCode h_wire_details;
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_MerchantWireHash h_wire_details;
+  struct TALER_PrivateContractHash h_contract_terms;
   const struct TALER_MerchantPrivateKeyP *merchant_priv;
 
   (void) cmd;
@@ -210,17 +221,17 @@ track_transaction_run (void *cls,
   /* Get the strings.. */
   if (GNUNET_OK !=
       TALER_TESTING_get_trait_wire_details (transaction_cmd,
-                                            0,
                                             &wire_details))
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (tts->is);
     return;
   }
-
+  tts->merchant_payto_uri
+    = GNUNET_strdup (json_string_value (json_object_get (wire_details,
+                                                         "payto_uri")));
   if (GNUNET_OK !=
       TALER_TESTING_get_trait_contract_terms (transaction_cmd,
-                                              0,
                                               &contract_terms))
   {
     GNUNET_break (0);
@@ -247,7 +258,6 @@ track_transaction_run (void *cls,
 
   if (GNUNET_OK !=
       TALER_TESTING_get_trait_merchant_priv (transaction_cmd,
-                                             0,
                                              &merchant_priv))
   {
     GNUNET_break (0);
@@ -288,6 +298,7 @@ track_transaction_cleanup (void *cls,
     TALER_EXCHANGE_deposits_get_cancel (tts->tth);
     tts->tth = NULL;
   }
+  GNUNET_free (tts->merchant_payto_uri);
   GNUNET_free (tts);
 }
 
@@ -301,7 +312,7 @@ track_transaction_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 track_transaction_traits (void *cls,
                           const void **ret,
                           const char *trait,
@@ -309,7 +320,10 @@ track_transaction_traits (void *cls,
 {
   struct TrackTransactionState *tts = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_wtid (0, &tts->wtid),
+    TALER_TESTING_make_trait_wtid (&tts->wtid),
+    TALER_TESTING_make_trait_payment_target_uuid (&tts->kyc_uuid),
+    TALER_TESTING_make_trait_payto_uri (
+      (const char **) &tts->merchant_payto_uri),
     TALER_TESTING_trait_end ()
   };
 
@@ -320,19 +334,6 @@ track_transaction_traits (void *cls,
 }
 
 
-/**
- * Create a "track transaction" command.
- *
- * @param label the command label.
- * @param transaction_reference reference to a deposit operation,
- *        will be used to get the input data for the track.
- * @param coin_index index of the coin involved in the transaction.
- * @param expected_response_code expected HTTP response code.
- * @param bank_transfer_reference reference to a command that
- *        can offer a WTID so as to check that against what WTID
- *        the tracked operation has.  Set as NULL if not needed.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_track_transaction (const char *label,
                                      const char *transaction_reference,
diff --git a/src/testing/testing_api_cmd_exec_aggregator.c 
b/src/testing/testing_api_cmd_exec_aggregator.c
index 6ec56c17..0f3cc1e1 100644
--- a/src/testing/testing_api_cmd_exec_aggregator.c
+++ b/src/testing/testing_api_cmd_exec_aggregator.c
@@ -43,6 +43,11 @@ struct AggregatorState
    * Configuration file used by the aggregator.
    */
   const char *config_filename;
+
+  /**
+   * Run with KYC restrictions on.
+   */
+  bool kyc_on;
 };
 
 
@@ -67,7 +72,11 @@ aggregator_run (void *cls,
                                "taler-exchange-aggregator",
                                "taler-exchange-aggregator",
                                "-c", as->config_filename,
+                               "-L", "INFO",
                                "-t", /* exit when done */
+                               (as->kyc_on)
+                               ? NULL
+                               : "-y", /* skip KYC */
                                NULL);
   if (NULL == as->aggregator_proc)
   {
@@ -115,7 +124,7 @@ aggregator_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 aggregator_traits (void *cls,
                    const void **ret,
                    const char *trait,
@@ -123,7 +132,7 @@ aggregator_traits (void *cls,
 {
   struct AggregatorState *as = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &as->aggregator_proc),
+    TALER_TESTING_make_trait_process (&as->aggregator_proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -134,14 +143,6 @@ aggregator_traits (void *cls,
 }
 
 
-/**
- * Make a "aggregator" CMD.
- *
- * @param label command label.
- * @param config_filename configuration file for the
- *                        aggregator to use.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_exec_aggregator (const char *label,
                                    const char *config_filename)
@@ -164,4 +165,27 @@ TALER_TESTING_cmd_exec_aggregator (const char *label,
 }
 
 
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_exec_aggregator_with_kyc (const char *label,
+                                            const char *config_filename)
+{
+  struct AggregatorState *as;
+
+  as = GNUNET_new (struct AggregatorState);
+  as->config_filename = config_filename;
+  as->kyc_on = true;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = as,
+      .label = label,
+      .run = &aggregator_run,
+      .cleanup = &aggregator_cleanup,
+      .traits = &aggregator_traits
+    };
+
+    return cmd;
+  }
+}
+
+
 /* end of testing_api_cmd_exec_aggregator.c */
diff --git a/src/testing/testing_api_cmd_exec_closer.c 
b/src/testing/testing_api_cmd_exec_closer.c
index c1153bab..442fb4ce 100644
--- a/src/testing/testing_api_cmd_exec_closer.c
+++ b/src/testing/testing_api_cmd_exec_closer.c
@@ -65,7 +65,7 @@ struct CloserState
   /**
    * Do we expect the command to actually close a reserve?
    */
-  int expect_close;
+  bool expect_close;
 };
 
 
@@ -93,7 +93,6 @@ closer_run (void *cls,
                                                      as->reserve_ref);
     if (GNUNET_OK !=
         TALER_TESTING_get_trait_reserve_pub (rcmd,
-                                             0,
                                              &reserve_pubp))
     {
       GNUNET_break (0);
@@ -156,7 +155,7 @@ closer_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 closer_traits (void *cls,
                const void **ret,
                const char *trait,
@@ -164,15 +163,13 @@ closer_traits (void *cls,
 {
   struct CloserState *as = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &as->closer_proc),
+    TALER_TESTING_make_trait_process (&as->closer_proc),
     TALER_TESTING_trait_end ()
   };
   struct TALER_TESTING_Trait xtraits[] = {
-    TALER_TESTING_make_trait_process (0, &as->closer_proc),
-    TALER_TESTING_make_trait_reserve_pub (0,
-                                          &as->reserve_pub),
-    TALER_TESTING_make_trait_reserve_history (0,
-                                              &as->reserve_history),
+    TALER_TESTING_make_trait_process (&as->closer_proc),
+    TALER_TESTING_make_trait_reserve_pub (&as->reserve_pub),
+    TALER_TESTING_make_trait_reserve_history (&as->reserve_history),
     TALER_TESTING_trait_end ()
   };
 
@@ -185,22 +182,6 @@ closer_traits (void *cls,
 }
 
 
-/**
- * Make a "closer" CMD.  Note that it is right now not supported to run the
- * closer to close multiple reserves in combination with a subsequent reserve
- * status call, as we cannot generate the traits necessary for multiple closed
- * reserves.  You can work around this by using multiple closer commands, one
- * per reserve that is being closed.
- *
- * @param label command label.
- * @param config_filename configuration file for the
- *                        closer to use.
- * @param expected_amount amount we expect to see wired from a @a 
expected_reserve_ref
- * @param expected_fee closing fee we expect to see
- * @param expected_reserve_ref reference to a reserve we expect the closer to 
drain;
- *          NULL if we do not expect the closer to do anything
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_exec_closer (const char *label,
                                const char *config_filename,
@@ -214,7 +195,7 @@ TALER_TESTING_cmd_exec_closer (const char *label,
   as->config_filename = config_filename;
   if (NULL != expected_reserve_ref)
   {
-    as->expect_close = GNUNET_YES;
+    as->expect_close = true;
     as->reserve_ref = expected_reserve_ref;
     if (GNUNET_OK !=
         TALER_string_to_amount (expected_amount,
diff --git a/src/testing/testing_api_cmd_exec_transfer.c 
b/src/testing/testing_api_cmd_exec_transfer.c
index 796f32d0..beceec57 100644
--- a/src/testing/testing_api_cmd_exec_transfer.c
+++ b/src/testing/testing_api_cmd_exec_transfer.c
@@ -116,7 +116,7 @@ transfer_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 transfer_traits (void *cls,
                  const void **ret,
                  const char *trait,
@@ -124,7 +124,7 @@ transfer_traits (void *cls,
 {
   struct TransferState *as = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &as->transfer_proc),
+    TALER_TESTING_make_trait_process (&as->transfer_proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -135,14 +135,6 @@ transfer_traits (void *cls,
 }
 
 
-/**
- * Make a "transfer" CMD.
- *
- * @param label command label.
- * @param config_filename configuration file for the
- *                        transfer to use.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_exec_transfer (const char *label,
                                  const char *config_filename)
diff --git a/src/testing/testing_api_cmd_exec_wirewatch.c 
b/src/testing/testing_api_cmd_exec_wirewatch.c
index 2c50b4f4..e4188ac8 100644
--- a/src/testing/testing_api_cmd_exec_wirewatch.c
+++ b/src/testing/testing_api_cmd_exec_wirewatch.c
@@ -46,6 +46,7 @@ struct WirewatchState
   const char *config_filename;
 };
 
+
 /**
  * Run the command; use the `taler-exchange-wirewatch' program.
  *
@@ -115,7 +116,7 @@ wirewatch_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 wirewatch_traits (void *cls,
                   const void **ret,
                   const char *trait,
@@ -123,8 +124,7 @@ wirewatch_traits (void *cls,
 {
   struct WirewatchState *ws = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0,
-                                      &ws->wirewatch_proc),
+    TALER_TESTING_make_trait_process (&ws->wirewatch_proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -135,13 +135,6 @@ wirewatch_traits (void *cls,
 }
 
 
-/**
- * Make a "wirewatch" CMD.
- *
- * @param label command label.
- * @param config_filename configuration filename.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_exec_wirewatch (const char *label,
                                   const char *config_filename)
diff --git a/src/testing/testing_api_cmd_insert_deposit.c 
b/src/testing/testing_api_cmd_insert_deposit.c
index 0a0d5db2..6b5d9d74 100644
--- a/src/testing/testing_api_cmd_insert_deposit.c
+++ b/src/testing/testing_api_cmd_insert_deposit.c
@@ -137,15 +137,17 @@ insert_deposit_run (void *cls,
   struct TALER_MerchantPrivateKeyP merchant_priv;
   struct TALER_EXCHANGEDB_DenominationKeyInformationP issue;
   struct TALER_DenominationPublicKey dpk;
-  struct GNUNET_CRYPTO_RsaPrivateKey *denom_priv;
-  struct GNUNET_HashCode hc;
+  struct TALER_DenominationPrivateKey denom_priv;
 
   // prepare and store issue first.
   fake_issue (&issue);
-  denom_priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
-  dpk.rsa_public_key = GNUNET_CRYPTO_rsa_private_key_get_public (denom_priv);
-  GNUNET_CRYPTO_rsa_public_key_hash (dpk.rsa_public_key,
-                                     &issue.properties.denom_hash);
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_denom_priv_create (&denom_priv,
+                                          &dpk,
+                                          TALER_DENOMINATION_RSA,
+                                          1024));
+  TALER_denom_pub_hash (&dpk,
+                        &issue.properties.denom_hash);
 
   if ( (GNUNET_OK !=
         ids->dbc->plugin->start (ids->dbc->plugin->cls,
@@ -158,6 +160,8 @@ insert_deposit_run (void *cls,
         ids->dbc->plugin->commit (ids->dbc->plugin->cls)) )
   {
     TALER_TESTING_interpreter_fail (is);
+    TALER_denom_pub_free (&dpk);
+    TALER_denom_priv_free (&denom_priv);
     return;
   }
 
@@ -177,7 +181,7 @@ insert_deposit_run (void *cls,
   GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv.eddsa_priv,
                                       &deposit.merchant_pub.eddsa_pub);
   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
-                                    &deposit.h_contract_terms);
+                                    &deposit.h_contract_terms.hash);
   if ( (GNUNET_OK !=
         TALER_string_to_amount (ids->amount_with_fee,
                                 &deposit.amount_with_fee)) ||
@@ -186,41 +190,50 @@ insert_deposit_run (void *cls,
                                 &deposit.deposit_fee)) )
   {
     TALER_TESTING_interpreter_fail (is);
+    TALER_denom_pub_free (&dpk);
+    TALER_denom_priv_free (&denom_priv);
     return;
   }
 
-  GNUNET_CRYPTO_rsa_public_key_hash (dpk.rsa_public_key,
-                                     &deposit.coin.denom_pub_hash);
+  TALER_denom_pub_hash (&dpk,
+                        &deposit.coin.denom_pub_hash);
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                               &deposit.coin.coin_pub,
                               sizeof (deposit.coin.coin_pub));
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
-                                    &hc);
-  deposit.coin.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_sign_fdh 
(denom_priv,
-                                                                     &hc);
   {
-    char *str;
-    struct TALER_WireSalt salt;
-
-    GNUNET_asprintf (&str,
-                     "payto://x-taler-bank/localhost/%s",
-                     ids->merchant_account);
-    memset (&salt,
-            46,
-            sizeof (salt));
-    deposit.receiver_wire_account
-      = GNUNET_JSON_PACK (
-          GNUNET_JSON_pack_data_auto ("salt",
-                                      &salt),
-          GNUNET_JSON_pack_string ("payto_uri",
-                                   str));
-    GNUNET_free (str);
+    struct TALER_CoinPubHash c_hash;
+    struct TALER_PlanchetDetail pd;
+    struct TALER_BlindedDenominationSignature bds;
+    union TALER_DenominationBlindingKeyP bks;
+
+    TALER_blinding_secret_create (&bks);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_blind (&dpk,
+                                      &bks,
+                                      NULL, /* FIXME-Oec */
+                                      &deposit.coin.coin_pub,
+                                      &c_hash,
+                                      &pd.coin_ev,
+                                      &pd.coin_ev_size));
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sign_blinded (&bds,
+                                             &denom_priv,
+                                             pd.coin_ev,
+                                             pd.coin_ev_size));
+    GNUNET_free (pd.coin_ev);
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_denom_sig_unblind (&deposit.coin.denom_sig,
+                                            &bds,
+                                            &bks,
+                                            &dpk));
+    TALER_blinded_denom_sig_free (&bds);
   }
-
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_JSON_merchant_wire_signature_hash (
-                   deposit.receiver_wire_account,
-                   &deposit.h_wire));
+  GNUNET_asprintf (&deposit.receiver_wire_account,
+                   "payto://x-taler-bank/localhost/%s",
+                   ids->merchant_account);
+  memset (&deposit.wire_salt,
+          46,
+          sizeof (deposit.wire_salt));
   deposit.timestamp = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&deposit.timestamp);
   deposit.wire_deadline = GNUNET_TIME_relative_to_absolute 
(ids->wire_deadline);
@@ -242,14 +255,17 @@ insert_deposit_run (void *cls,
   {
     GNUNET_break (0);
     ids->dbc->plugin->rollback (ids->dbc->plugin->cls);
+    GNUNET_free (deposit.receiver_wire_account);
+    TALER_denom_pub_free (&dpk);
+    TALER_denom_priv_free (&denom_priv);
     TALER_TESTING_interpreter_fail (is);
+    return;
   }
 
-  GNUNET_CRYPTO_rsa_signature_free (deposit.coin.denom_sig.rsa_signature);
-  GNUNET_CRYPTO_rsa_public_key_free (dpk.rsa_public_key);
-  GNUNET_CRYPTO_rsa_private_key_free (denom_priv);
-  json_decref (deposit.receiver_wire_account);
-
+  TALER_denom_sig_free (&deposit.coin.denom_sig);
+  TALER_denom_pub_free (&dpk);
+  TALER_denom_priv_free (&denom_priv);
+  GNUNET_free (deposit.receiver_wire_account);
   TALER_TESTING_interpreter_next (is);
 }
 
@@ -271,43 +287,6 @@ insert_deposit_cleanup (void *cls,
 }
 
 
-/**
- * Offer "insert-deposit" CMD internal data to other commands.
- *
- * @param cls closure.
- * @param[out] ret result
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success.
- */
-static int
-insert_deposit_traits (void *cls,
-                       const void **ret,
-                       const char *trait,
-                       unsigned int index)
-{
-  (void) cls;
-  (void) ret;
-  (void) trait;
-  (void) index;
-  return GNUNET_NO;
-}
-
-
-/**
- * Make the "insert-deposit" CMD.
- *
- * @param label command label.
- * @param dbc collects database plugin
- * @param merchant_name Human-readable name of the merchant.
- * @param merchant_account merchant's account name (NOT a payto:// URI)
- * @param exchange_timestamp when did the exchange receive the deposit
- * @param wire_deadline point in time where the aggregator should have
- *        wired money to the merchant.
- * @param amount_with_fee amount to deposit (inclusive of deposit fee)
- * @param deposit_fee deposit fee
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_insert_deposit (
   const char *label,
@@ -336,8 +315,7 @@ TALER_TESTING_cmd_insert_deposit (
       .cls = ids,
       .label = label,
       .run = &insert_deposit_run,
-      .cleanup = &insert_deposit_cleanup,
-      .traits = &insert_deposit_traits
+      .cleanup = &insert_deposit_cleanup
     };
 
     return cmd;
diff --git a/src/testing/testing_api_cmd_kyc_check_get.c 
b/src/testing/testing_api_cmd_kyc_check_get.c
new file mode 100644
index 00000000..3d35752b
--- /dev/null
+++ b/src/testing/testing_api_cmd_kyc_check_get.c
@@ -0,0 +1,252 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2021 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 3, or
+  (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file testing/testing_api_cmd_kyc_check_get.c
+ * @brief Implement the testing CMDs for the /kyc_check/ GET operations.
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_testing_lib.h"
+
+/**
+ * State for a "track transaction" CMD.
+ */
+struct KycCheckGetState
+{
+
+  /**
+   * Command to get a reserve private key from.
+   */
+  const char *payment_target_reference;
+
+  /**
+   * Expected HTTP response code.
+   */
+  unsigned int expected_response_code;
+
+  /**
+   * Set to the KYC URL *if* the exchange replied with
+   * a request for KYC (#MHD_HTTP_ACCEPTED).
+   */
+  char *kyc_url;
+
+  /**
+   * Handle to the "track transaction" pending operation.
+   */
+  struct TALER_EXCHANGE_KycCheckHandle *kwh;
+
+  /**
+   * Interpreter state.
+   */
+  struct TALER_TESTING_Interpreter *is;
+};
+
+
+/**
+ * Handle response to the command.
+ *
+ * @param cls closure.
+ * @param ks GET KYC status response details
+ */
+static void
+check_kyc_cb (void *cls,
+              const struct TALER_EXCHANGE_KycStatus *ks)
+{
+  struct KycCheckGetState *kcg = cls;
+  struct TALER_TESTING_Interpreter *is = kcg->is;
+  struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
+
+  kcg->kwh = NULL;
+  if (kcg->expected_response_code != ks->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u/%d to command %s in %s:%u\n",
+                ks->http_status,
+                (int) ks->ec,
+                cmd->label,
+                __FILE__,
+                __LINE__);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+  switch (ks->http_status)
+  {
+  case MHD_HTTP_OK:
+    break;
+  case MHD_HTTP_ACCEPTED:
+    kcg->kyc_url = GNUNET_strdup (ks->details.kyc_url);
+    break;
+  case MHD_HTTP_NO_CONTENT:
+    break;
+  default:
+    GNUNET_break (0);
+    break;
+  }
+  TALER_TESTING_interpreter_next (kcg->is);
+}
+
+
+/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+check_kyc_run (void *cls,
+               const struct TALER_TESTING_Command *cmd,
+               struct TALER_TESTING_Interpreter *is)
+{
+  struct KycCheckGetState *kcg = cls;
+  const struct TALER_TESTING_Command *res_cmd;
+  const char **payto_uri;
+  const uint64_t *payment_target;
+  struct TALER_PaytoHash h_payto;
+
+  (void) cmd;
+  kcg->is = is;
+  res_cmd = TALER_TESTING_interpreter_lookup_command (kcg->is,
+                                                      kcg->
+                                                      
payment_target_reference);
+  if (NULL == res_cmd)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (kcg->is);
+    return;
+  }
+  if (GNUNET_OK !=
+      TALER_TESTING_get_trait_payto_uri (res_cmd,
+                                         &payto_uri))
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (kcg->is);
+    return;
+  }
+  if (GNUNET_OK !=
+      TALER_TESTING_get_trait_payment_target_uuid (res_cmd,
+                                                   &payment_target))
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (kcg->is);
+    return;
+  }
+  if ( (NULL == *payto_uri) ||
+       (0 == *payment_target) )
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (kcg->is);
+    return;
+  }
+  TALER_payto_hash (*payto_uri,
+                    &h_payto);
+  kcg->kwh = TALER_EXCHANGE_kyc_check (is->exchange,
+                                       *payment_target,
+                                       &h_payto,
+                                       GNUNET_TIME_UNIT_SECONDS,
+                                       &check_kyc_cb,
+                                       kcg);
+  GNUNET_assert (NULL != kcg->kwh);
+}
+
+
+/**
+ * Cleanup the state from a "track transaction" CMD, and possibly
+ * cancel a operation thereof.
+ *
+ * @param cls closure.
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+check_kyc_cleanup (void *cls,
+                   const struct TALER_TESTING_Command *cmd)
+{
+  struct KycCheckGetState *kcg = cls;
+
+  if (NULL != kcg->kwh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Command %u (%s) did not complete\n",
+                kcg->is->ip,
+                cmd->label);
+    TALER_EXCHANGE_kyc_check_cancel (kcg->kwh);
+    kcg->kwh = NULL;
+  }
+  GNUNET_free (kcg->kyc_url);
+  GNUNET_free (kcg);
+}
+
+
+/**
+ * Offer internal data from a "check KYC" CMD.
+ *
+ * @param cls closure.
+ * @param[out] ret result (could be anything).
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ * @return #GNUNET_OK on success.
+ */
+static enum GNUNET_GenericReturnValue
+check_kyc_traits (void *cls,
+                  const void **ret,
+                  const char *trait,
+                  unsigned int index)
+{
+  struct KycCheckGetState *kcg = cls;
+  struct TALER_TESTING_Trait traits[] = {
+    TALER_TESTING_make_trait_kyc_url (
+      (const char **) &kcg->kyc_url),
+    TALER_TESTING_trait_end ()
+  };
+
+  return TALER_TESTING_get_trait (traits,
+                                  ret,
+                                  trait,
+                                  index);
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_check_kyc_get (const char *label,
+                                 const char *payment_target_reference,
+                                 unsigned int expected_response_code)
+{
+  struct KycCheckGetState *kcg;
+
+  kcg = GNUNET_new (struct KycCheckGetState);
+  kcg->payment_target_reference = payment_target_reference;
+  kcg->expected_response_code = expected_response_code;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = kcg,
+      .label = label,
+      .run = &check_kyc_run,
+      .cleanup = &check_kyc_cleanup,
+      .traits = &check_kyc_traits
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_kyc_check_get.c */
diff --git a/src/testing/testing_api_cmd_kyc_proof.c 
b/src/testing/testing_api_cmd_kyc_proof.c
new file mode 100644
index 00000000..fdd3affd
--- /dev/null
+++ b/src/testing/testing_api_cmd_kyc_proof.c
@@ -0,0 +1,249 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2021 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 3, or
+  (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file testing/testing_api_cmd_kyc_proof.c
+ * @brief Implement the testing CMDs for the /kyc-proof/ operation.
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_testing_lib.h"
+
+/**
+ * State for a "track transaction" CMD.
+ */
+struct KycProofGetState
+{
+
+  /**
+   * Command to get a reserve private key from.
+   */
+  const char *payment_target_reference;
+
+  /**
+   * Code to pass.
+   */
+  const char *code;
+
+  /**
+   * State to pass.
+   */
+  const char *state;
+
+  /**
+   * Expected HTTP response code.
+   */
+  unsigned int expected_response_code;
+
+  /**
+   * Set to the KYC REDIRECT *if* the exchange replied with
+   * success (#MHD_HTTP_OK).
+   */
+  char *redirect_url;
+
+  /**
+   * Handle to the "track transaction" pending operation.
+   */
+  struct TALER_EXCHANGE_KycProofHandle *kph;
+
+  /**
+   * Interpreter state.
+   */
+  struct TALER_TESTING_Interpreter *is;
+};
+
+
+/**
+ * Handle response to the command.
+ *
+ * @param cls closure.
+ * @param kpr KYC proof response details
+ */
+static void
+proof_kyc_cb (void *cls,
+              const struct TALER_EXCHANGE_KycProofResponse *kpr)
+{
+  struct KycProofGetState *kcg = cls;
+  struct TALER_TESTING_Interpreter *is = kcg->is;
+  struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
+
+  kcg->kph = NULL;
+  if (kcg->expected_response_code != kpr->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to command %s in %s:%u\n",
+                kpr->http_status,
+                cmd->label,
+                __FILE__,
+                __LINE__);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+  switch (kpr->http_status)
+  {
+  case MHD_HTTP_SEE_OTHER:
+    kcg->redirect_url = GNUNET_strdup (kpr->details.found.redirect_url);
+    break;
+  case MHD_HTTP_FORBIDDEN:
+    break;
+  case MHD_HTTP_BAD_GATEWAY:
+    break;
+  default:
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to /kyc-proof\n",
+                kpr->http_status);
+    break;
+  }
+  TALER_TESTING_interpreter_next (kcg->is);
+}
+
+
+/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+proof_kyc_run (void *cls,
+               const struct TALER_TESTING_Command *cmd,
+               struct TALER_TESTING_Interpreter *is)
+{
+  struct KycProofGetState *kps = cls;
+  const struct TALER_TESTING_Command *res_cmd;
+  const uint64_t *payment_target;
+
+  (void) cmd;
+  kps->is = is;
+  res_cmd = TALER_TESTING_interpreter_lookup_command (kps->is,
+                                                      kps->
+                                                      
payment_target_reference);
+  if (NULL == res_cmd)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (kps->is);
+    return;
+  }
+  if (GNUNET_OK !=
+      TALER_TESTING_get_trait_payment_target_uuid (res_cmd,
+                                                   &payment_target))
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (kps->is);
+    return;
+  }
+  kps->kph = TALER_EXCHANGE_kyc_proof (is->exchange,
+                                       *payment_target,
+                                       kps->code,
+                                       kps->state,
+                                       &proof_kyc_cb,
+                                       kps);
+  GNUNET_assert (NULL != kps->kph);
+}
+
+
+/**
+ * Cleanup the state from a "track transaction" CMD, and possibly
+ * cancel a operation thereof.
+ *
+ * @param cls closure.
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+proof_kyc_cleanup (void *cls,
+                   const struct TALER_TESTING_Command *cmd)
+{
+  struct KycProofGetState *kps = cls;
+
+  if (NULL != kps->kph)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Command %u (%s) did not complete\n",
+                kps->is->ip,
+                cmd->label);
+    TALER_EXCHANGE_kyc_proof_cancel (kps->kph);
+    kps->kph = NULL;
+  }
+  GNUNET_free (kps->redirect_url);
+  GNUNET_free (kps);
+}
+
+
+/**
+ * Offer internal data from a "proof KYC" CMD.
+ *
+ * @param cls closure.
+ * @param[out] ret result (could be anything).
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ * @return #GNUNET_OK on success.
+ */
+static enum GNUNET_GenericReturnValue
+proof_kyc_traits (void *cls,
+                  const void **ret,
+                  const char *trait,
+                  unsigned int index)
+{
+  struct KycProofGetState *kps = cls;
+  struct TALER_TESTING_Trait traits[] = {
+    TALER_TESTING_make_trait_web_url (
+      (const char **) &kps->redirect_url),
+    TALER_TESTING_trait_end ()
+  };
+
+  return TALER_TESTING_get_trait (traits,
+                                  ret,
+                                  trait,
+                                  index);
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_proof_kyc (const char *label,
+                             const char *payment_target_reference,
+                             const char *code,
+                             const char *state,
+                             unsigned int expected_response_code)
+{
+  struct KycProofGetState *kps;
+
+  kps = GNUNET_new (struct KycProofGetState);
+  kps->code = code;
+  kps->state = state;
+  kps->payment_target_reference = payment_target_reference;
+  kps->expected_response_code = expected_response_code;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = kps,
+      .label = label,
+      .run = &proof_kyc_run,
+      .cleanup = &proof_kyc_cleanup,
+      .traits = &proof_kyc_traits
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_kyc_proof.c */
diff --git a/src/testing/testing_api_cmd_kyc_wallet_get.c 
b/src/testing/testing_api_cmd_kyc_wallet_get.c
new file mode 100644
index 00000000..91ad09ff
--- /dev/null
+++ b/src/testing/testing_api_cmd_kyc_wallet_get.c
@@ -0,0 +1,266 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2021 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 3, or
+  (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file testing/testing_api_cmd_kyc_wallet_get.c
+ * @brief Implement the testing CMDs for the /kyc_wallet/ GET operations.
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_testing_lib.h"
+
+/**
+ * State for a "/kyc-wallet" GET CMD.
+ */
+struct KycWalletGetState
+{
+
+  /**
+   * Private key of the reserve (account).
+   */
+  struct TALER_ReservePrivateKeyP reserve_priv;
+
+  /**
+   * Public key of the reserve (account).
+   */
+  struct TALER_ReservePublicKeyP reserve_pub;
+
+  /**
+   * Payto URI of the reserve of the wallet.
+   */
+  char *reserve_payto_uri;
+
+  /**
+   * Command to get a reserve private key from.
+   */
+  const char *reserve_reference;
+
+  /**
+   * Expected HTTP response code.
+   */
+  unsigned int expected_response_code;
+
+  /**
+   * Set to the KYC UUID *if* the exchange replied with
+   * a request for KYC (#MHD_HTTP_ACCEPTED).
+   */
+  uint64_t kyc_uuid;
+
+  /**
+   * Handle to the "track transaction" pending operation.
+   */
+  struct TALER_EXCHANGE_KycWalletHandle *kwh;
+
+  /**
+   * Interpreter state.
+   */
+  struct TALER_TESTING_Interpreter *is;
+};
+
+
+/**
+ * Handle response to the command.
+ *
+ * @param cls closure.
+ * @param wkr GET deposit response details
+ */
+static void
+wallet_kyc_cb (void *cls,
+               const struct TALER_EXCHANGE_WalletKycResponse *wkr)
+{
+  struct KycWalletGetState *kwg = cls;
+  struct TALER_TESTING_Interpreter *is = kwg->is;
+  struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
+
+  kwg->kwh = NULL;
+  if (kwg->expected_response_code != wkr->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u/%d (wanted %u) to command %s in 
%s:%u\n",
+                wkr->http_status,
+                (int) wkr->ec,
+                kwg->expected_response_code,
+                cmd->label,
+                __FILE__,
+                __LINE__);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+  switch (wkr->http_status)
+  {
+  case MHD_HTTP_OK:
+    kwg->kyc_uuid = wkr->payment_target_uuid;
+    break;
+  case MHD_HTTP_NO_CONTENT:
+    break;
+  case MHD_HTTP_FORBIDDEN:
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  default:
+    GNUNET_break (0);
+    break;
+  }
+  TALER_TESTING_interpreter_next (kwg->is);
+}
+
+
+/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+wallet_kyc_run (void *cls,
+                const struct TALER_TESTING_Command *cmd,
+                struct TALER_TESTING_Interpreter *is)
+{
+  struct KycWalletGetState *kwg = cls;
+
+  (void) cmd;
+  kwg->is = is;
+  if (NULL != kwg->reserve_reference)
+  {
+    const struct TALER_TESTING_Command *res_cmd;
+    const struct TALER_ReservePrivateKeyP *reserve_priv;
+
+    res_cmd = TALER_TESTING_interpreter_lookup_command (kwg->is,
+                                                        
kwg->reserve_reference);
+    if (NULL == res_cmd)
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (kwg->is);
+      return;
+    }
+
+    if (GNUNET_OK !=
+        TALER_TESTING_get_trait_reserve_priv (res_cmd,
+                                              &reserve_priv))
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (kwg->is);
+      return;
+    }
+    kwg->reserve_priv = *reserve_priv;
+  }
+  else
+  {
+    GNUNET_CRYPTO_eddsa_key_create (&kwg->reserve_priv.eddsa_priv);
+  }
+  GNUNET_CRYPTO_eddsa_key_get_public (&kwg->reserve_priv.eddsa_priv,
+                                      &kwg->reserve_pub.eddsa_pub);
+  kwg->reserve_payto_uri
+    = TALER_payto_from_reserve (TALER_EXCHANGE_get_base_url (is->exchange),
+                                &kwg->reserve_pub);
+  kwg->kwh = TALER_EXCHANGE_kyc_wallet (is->exchange,
+                                        &kwg->reserve_priv,
+                                        &wallet_kyc_cb,
+                                        kwg);
+  GNUNET_assert (NULL != kwg->kwh);
+}
+
+
+/**
+ * Cleanup the state from a "track transaction" CMD, and possibly
+ * cancel a operation thereof.
+ *
+ * @param cls closure with our `struct KycWalletGetState`
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+wallet_kyc_cleanup (void *cls,
+                    const struct TALER_TESTING_Command *cmd)
+{
+  struct KycWalletGetState *kwg = cls;
+
+  if (NULL != kwg->kwh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Command %u (%s) did not complete\n",
+                kwg->is->ip,
+                cmd->label);
+    TALER_EXCHANGE_kyc_wallet_cancel (kwg->kwh);
+    kwg->kwh = NULL;
+  }
+  GNUNET_free (kwg->reserve_payto_uri);
+  GNUNET_free (kwg);
+}
+
+
+/**
+ * Offer internal data from a "wallet KYC" CMD.
+ *
+ * @param cls closure.
+ * @param[out] ret result (could be anything).
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ * @return #GNUNET_OK on success.
+ */
+static enum GNUNET_GenericReturnValue
+wallet_kyc_traits (void *cls,
+                   const void **ret,
+                   const char *trait,
+                   unsigned int index)
+{
+  struct KycWalletGetState *kwg = cls;
+  struct TALER_TESTING_Trait traits[] = {
+    TALER_TESTING_make_trait_reserve_priv (&kwg->reserve_priv),
+    TALER_TESTING_make_trait_reserve_pub (&kwg->reserve_pub),
+    TALER_TESTING_make_trait_payment_target_uuid (&kwg->kyc_uuid),
+    TALER_TESTING_make_trait_payto_uri (
+      (const char **) &kwg->reserve_payto_uri),
+    TALER_TESTING_trait_end ()
+  };
+
+  return TALER_TESTING_get_trait (traits,
+                                  ret,
+                                  trait,
+                                  index);
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_wallet_kyc_get (const char *label,
+                                  const char *reserve_reference,
+                                  unsigned int expected_response_code)
+{
+  struct KycWalletGetState *kwg;
+
+  kwg = GNUNET_new (struct KycWalletGetState);
+  kwg->reserve_reference = reserve_reference;
+  kwg->expected_response_code = expected_response_code;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = kwg,
+      .label = label,
+      .run = &wallet_kyc_run,
+      .cleanup = &wallet_kyc_cleanup,
+      .traits = &wallet_kyc_traits
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_kyc_wallet_get.c */
diff --git a/src/testing/testing_api_cmd_oauth.c 
b/src/testing/testing_api_cmd_oauth.c
new file mode 100644
index 00000000..64cb6c03
--- /dev/null
+++ b/src/testing/testing_api_cmd_oauth.c
@@ -0,0 +1,373 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2021 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 3, or
+  (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file testing/testing_api_cmd_oauth.c
+ * @brief Implement a CMD to run an OAuth service for faking the legitimation 
service
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_testing_lib.h"
+#include "taler_mhd_lib.h"
+
+/**
+ * State for the oauth CMD.
+ */
+struct OAuthState
+{
+
+  /**
+   * Handle to the "oauth" service.
+   */
+  struct MHD_Daemon *mhd;
+
+  /**
+   * Port to listen on.
+   */
+  uint16_t port;
+};
+
+
+struct RequestCtx
+{
+  struct MHD_PostProcessor *pp;
+  char *code;
+  char *client_id;
+  char *redirect_uri;
+  char *client_secret;
+};
+
+
+static void
+append (char **target,
+        const char *data,
+        size_t size)
+{
+  char *tmp;
+
+  if (NULL == *target)
+  {
+    *target = GNUNET_strndup (data,
+                              size);
+    return;
+  }
+  GNUNET_asprintf (&tmp,
+                   "%s%.*s",
+                   *target,
+                   (int) size,
+                   data);
+  GNUNET_free (*target);
+  *target = tmp;
+}
+
+
+static enum MHD_Result
+handle_post (void *cls,
+             enum MHD_ValueKind kind,
+             const char *key,
+             const char *filename,
+             const char *content_type,
+             const char *transfer_encoding,
+             const char *data,
+             uint64_t off,
+             size_t size)
+{
+  struct RequestCtx *rc = cls;
+
+  if (0 == strcmp (key,
+                   "code"))
+    append (&rc->code,
+            data,
+            size);
+  if (0 == strcmp (key,
+                   "client_id"))
+    append (&rc->client_id,
+            data,
+            size);
+  if (0 == strcmp (key,
+                   "redirect_uri"))
+    append (&rc->redirect_uri,
+            data,
+            size);
+  if (0 == strcmp (key,
+                   "client_secret"))
+    append (&rc->client_secret,
+            data,
+            size);
+  return MHD_YES;
+}
+
+
+/**
+ * A client has requested the given url using the given method
+ * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT,
+ * #MHD_HTTP_METHOD_DELETE, #MHD_HTTP_METHOD_POST, etc).  The callback
+ * must call MHD callbacks to provide content to give back to the
+ * client and return an HTTP status code (i.e. #MHD_HTTP_OK,
+ * #MHD_HTTP_NOT_FOUND, etc.).
+ *
+ * @param cls argument given together with the function
+ *        pointer when the handler was registered with MHD
+ * @param url the requested url
+ * @param method the HTTP method used (#MHD_HTTP_METHOD_GET,
+ *        #MHD_HTTP_METHOD_PUT, etc.)
+ * @param version the HTTP version string (i.e.
+ *        #MHD_HTTP_VERSION_1_1)
+ * @param upload_data the data being uploaded (excluding HEADERS,
+ *        for a POST that fits into memory and that is encoded
+ *        with a supported encoding, the POST data will NOT be
+ *        given in upload_data and is instead available as
+ *        part of #MHD_get_connection_values; very large POST
+ *        data *will* be made available incrementally in
+ *        @a upload_data)
+ * @param[in,out] upload_data_size set initially to the size of the
+ *        @a upload_data provided; the method must update this
+ *        value to the number of bytes NOT processed;
+ * @param[in,out] con_cls pointer that the callback can set to some
+ *        address and that will be preserved by MHD for future
+ *        calls for this request; since the access handler may
+ *        be called many times (i.e., for a PUT/POST operation
+ *        with plenty of upload data) this allows the application
+ *        to easily associate some request-specific state.
+ *        If necessary, this state can be cleaned up in the
+ *        global #MHD_RequestCompletedCallback (which
+ *        can be set with the #MHD_OPTION_NOTIFY_COMPLETED).
+ *        Initially, `*con_cls` will be NULL.
+ * @return #MHD_YES if the connection was handled successfully,
+ *         #MHD_NO if the socket must be closed due to a serious
+ *         error while handling the request
+ */
+static enum MHD_Result
+handler_cb (void *cls,
+            struct MHD_Connection *connection,
+            const char *url,
+            const char *method,
+            const char *version,
+            const char *upload_data,
+            size_t *upload_data_size,
+            void **con_cls)
+{
+  struct RequestCtx *rc = *con_cls;
+  unsigned int hc;
+  json_t *body;
+
+  if (0 == strcasecmp (method,
+                       MHD_HTTP_METHOD_GET))
+  {
+    body = GNUNET_JSON_PACK (
+      GNUNET_JSON_pack_string (
+        "status",
+        "success"),
+      GNUNET_JSON_pack_object_steal (
+        "data",
+        GNUNET_JSON_PACK (
+          GNUNET_JSON_pack_string ("id",
+                                   "XXXID12345678"))));
+    return TALER_MHD_reply_json_steal (connection,
+                                       body,
+                                       MHD_HTTP_OK);
+  }
+  if (0 != strcasecmp (method,
+                       MHD_HTTP_METHOD_POST))
+  {
+    GNUNET_break (0);
+    return MHD_NO;
+  }
+  if (NULL == rc)
+  {
+    rc = GNUNET_new (struct RequestCtx);
+    *con_cls = rc;
+    rc->pp = MHD_create_post_processor (connection,
+                                        4092,
+                                        &handle_post,
+                                        rc);
+    return MHD_YES;
+  }
+  if (0 != *upload_data_size)
+  {
+    enum MHD_Result ret;
+
+    ret = MHD_post_process (rc->pp,
+                            upload_data,
+                            *upload_data_size);
+    *upload_data_size = 0;
+    return ret;
+  }
+
+
+  /* NOTE: In the future, we MAY want to distinguish between
+     the different URLs and possibly return more information.
+     For now, just do the minimum: implement the main handler
+     that checks the code. */
+  if ( (NULL == rc->code) ||
+       (NULL == rc->client_id) ||
+       (NULL == rc->redirect_uri) ||
+       (NULL == rc->client_secret) )
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Bad request to Oauth faker: `%s' with %s/%s/%s/%s\n",
+                url,
+                rc->code,
+                rc->client_id,
+                rc->redirect_uri,
+                rc->client_secret);
+    return MHD_NO;
+  }
+  if (0 != strcmp (rc->client_id,
+                   "taler-exchange"))
+  {
+    body = GNUNET_JSON_PACK (
+      GNUNET_JSON_pack_string ("error",
+                               "unknown_client"),
+      GNUNET_JSON_pack_string ("error_description",
+                               "only 'taler-exchange' is allowed"));
+    hc = MHD_HTTP_NOT_FOUND;
+  }
+  else if (0 != strcmp (rc->client_secret,
+                        "exchange-secret"))
+  {
+    body = GNUNET_JSON_PACK (
+      GNUNET_JSON_pack_string ("error",
+                               "invalid_client_secret"),
+      GNUNET_JSON_pack_string ("error_description",
+                               "only 'exchange-secret' is valid"));
+    hc = MHD_HTTP_FORBIDDEN;
+  }
+  else
+  {
+    if (0 != strcmp (rc->code,
+                     "pass"))
+    {
+      body = GNUNET_JSON_PACK (
+        GNUNET_JSON_pack_string ("error",
+                                 "invalid_grant"),
+        GNUNET_JSON_pack_string ("error_description",
+                                 "only 'pass' shall pass"));
+      hc = MHD_HTTP_FORBIDDEN;
+    }
+    else
+    {
+      body = GNUNET_JSON_PACK (
+        GNUNET_JSON_pack_string ("access_token",
+                                 "good"),
+        GNUNET_JSON_pack_string ("token_type",
+                                 "bearer"),
+        GNUNET_JSON_pack_uint64 ("expires_in",
+                                 3600),
+        GNUNET_JSON_pack_string ("refresh_token",
+                                 "better"));
+      hc = MHD_HTTP_OK;
+    }
+  }
+  return TALER_MHD_reply_json_steal (connection,
+                                     body,
+                                     hc);
+}
+
+
+static void
+cleanup (void *cls,
+         struct MHD_Connection *connection,
+         void **con_cls,
+         enum MHD_RequestTerminationCode toe)
+{
+  struct RequestCtx *rc = *con_cls;
+
+  if (NULL == rc)
+    return;
+  GNUNET_free (rc->code);
+  GNUNET_free (rc->client_id);
+  GNUNET_free (rc->redirect_uri);
+  GNUNET_free (rc->client_secret);
+  GNUNET_free (rc);
+}
+
+
+/**
+ * Run the command.
+ *
+ * @param cls closure.
+ * @param cmd the command to execute.
+ * @param is the interpreter state.
+ */
+static void
+oauth_run (void *cls,
+           const struct TALER_TESTING_Command *cmd,
+           struct TALER_TESTING_Interpreter *is)
+{
+  struct OAuthState *oas = cls;
+
+  (void) cmd;
+  oas->mhd = MHD_start_daemon (MHD_USE_AUTO_INTERNAL_THREAD,
+                               oas->port,
+                               NULL, NULL,
+                               &handler_cb, oas,
+                               MHD_OPTION_NOTIFY_COMPLETED, &cleanup, NULL,
+                               NULL);
+  TALER_TESTING_interpreter_next (is);
+}
+
+
+/**
+ * Cleanup the state from a "oauth" CMD, and possibly cancel a operation
+ * thereof.
+ *
+ * @param cls closure.
+ * @param cmd the command which is being cleaned up.
+ */
+static void
+oauth_cleanup (void *cls,
+               const struct TALER_TESTING_Command *cmd)
+{
+  struct OAuthState *oas = cls;
+
+  if (NULL != oas->mhd)
+  {
+    MHD_stop_daemon (oas->mhd);
+    oas->mhd = NULL;
+  }
+  GNUNET_free (oas);
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_oauth (const char *label,
+                         uint16_t port)
+{
+  struct OAuthState *oas;
+
+  oas = GNUNET_new (struct OAuthState);
+  oas->port = port;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = oas,
+      .label = label,
+      .run = &oauth_run,
+      .cleanup = &oauth_cleanup,
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_oauth.c */
diff --git a/src/testing/testing_api_cmd_offline_sign_fees.c 
b/src/testing/testing_api_cmd_offline_sign_fees.c
index 50095320..95f52a00 100644
--- a/src/testing/testing_api_cmd_offline_sign_fees.c
+++ b/src/testing/testing_api_cmd_offline_sign_fees.c
@@ -134,7 +134,7 @@ offlinesign_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 offlinesign_traits (void *cls,
                     const void **ret,
                     const char *trait,
@@ -142,8 +142,7 @@ offlinesign_traits (void *cls,
 {
   struct OfflineSignState *ks = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0,
-                                      &ks->offlinesign_proc),
+    TALER_TESTING_make_trait_process (&ks->offlinesign_proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -154,15 +153,6 @@ offlinesign_traits (void *cls,
 }
 
 
-/**
- * Sign a wire fee.
- *
- * @param label command label.
- * @param config_filename configuration filename.
- * @param wire_fee the wire fee to affirm (for the current year)
- * @param closing_fee the closing fee to affirm (for the current year)
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_exec_offline_sign_fees (const char *label,
                                           const char *config_filename,
diff --git a/src/testing/testing_api_cmd_offline_sign_keys.c 
b/src/testing/testing_api_cmd_offline_sign_keys.c
index dd6170d9..2c99219b 100644
--- a/src/testing/testing_api_cmd_offline_sign_keys.c
+++ b/src/testing/testing_api_cmd_offline_sign_keys.c
@@ -121,7 +121,7 @@ offlinesign_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 offlinesign_traits (void *cls,
                     const void **ret,
                     const char *trait,
@@ -129,8 +129,7 @@ offlinesign_traits (void *cls,
 {
   struct OfflineSignState *ks = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0,
-                                      &ks->offlinesign_proc),
+    TALER_TESTING_make_trait_process (&ks->offlinesign_proc),
     TALER_TESTING_trait_end ()
   };
 
diff --git a/src/testing/testing_api_cmd_recoup.c 
b/src/testing/testing_api_cmd_recoup.c
index 7c4204d9..fe97edb7 100644
--- a/src/testing/testing_api_cmd_recoup.c
+++ b/src/testing/testing_api_cmd_recoup.c
@@ -81,7 +81,7 @@ struct RecoupState
  * @param[out] idx where we set $INDEX
  * @return #GNUNET_SYSERR if $INDEX is present but not numeric
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_coin_reference (const char *coin_reference,
                       char **cref,
                       unsigned int *idx)
@@ -166,6 +166,7 @@ recoup_cb (void *cls,
     TALER_TESTING_interpreter_fail (is);
     return;
   }
+  (void) idx; /* do NOT use! We ignore 'idx', must be 0 for melt! */
 
   reserve_cmd = TALER_TESTING_interpreter_lookup_command (is,
                                                           cref);
@@ -201,6 +202,10 @@ recoup_cb (void *cls,
                                              0,
                                              &dirty_priv))
       {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Coin %u not found in command %s\n",
+                    0,
+                    ps->melt_reference);
         GNUNET_break (0);
         TALER_TESTING_interpreter_fail (is);
         return;
@@ -227,7 +232,6 @@ recoup_cb (void *cls,
       }
       if (GNUNET_OK !=
           TALER_TESTING_get_trait_reserve_priv (reserve_cmd,
-                                                idx,
                                                 &reserve_priv))
       {
         GNUNET_break (0);
@@ -279,7 +283,7 @@ recoup_run (void *cls,
   struct RecoupState *ps = cls;
   const struct TALER_TESTING_Command *coin_cmd;
   const struct TALER_CoinSpendPrivateKeyP *coin_priv;
-  const struct TALER_DenominationBlindingKeyP *blinding_key;
+  const union TALER_DenominationBlindingKeyP *blinding_key;
   const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
   const struct TALER_DenominationSignature *coin_sig;
   struct TALER_PlanchetSecretsP planchet;
@@ -398,7 +402,7 @@ recoup_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 recoup_traits (void *cls,
                const void **ret,
                const char *trait,
@@ -410,10 +414,8 @@ recoup_traits (void *cls,
     return GNUNET_SYSERR; /* no traits */
   {
     struct TALER_TESTING_Trait traits[] = {
-      TALER_TESTING_make_trait_reserve_pub (0,
-                                            &ps->reserve_pub),
-      TALER_TESTING_make_trait_reserve_history (0,
-                                                &ps->reserve_history),
+      TALER_TESTING_make_trait_reserve_pub (&ps->reserve_pub),
+      TALER_TESTING_make_trait_reserve_history (&ps->reserve_history),
       TALER_TESTING_trait_end ()
     };
 
@@ -425,17 +427,6 @@ recoup_traits (void *cls,
 }
 
 
-/**
- * Make a "recoup" command.
- *
- * @param label the command label
- * @param expected_response_code expected HTTP status code
- * @param coin_reference reference to any command which
- *        offers a coin & reserve private key.
- * @param melt_reference NULL if coin was not refreshed
- * @param amount how much do we expect to recoup?
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_recoup (const char *label,
                           unsigned int expected_response_code,
diff --git a/src/testing/testing_api_cmd_refresh.c 
b/src/testing/testing_api_cmd_refresh.c
index fcf8540c..8f6ba0cf 100644
--- a/src/testing/testing_api_cmd_refresh.c
+++ b/src/testing/testing_api_cmd_refresh.c
@@ -73,7 +73,7 @@ struct TALER_TESTING_FreshCoinData
   /**
    * The blinding key (needed for recoup operations).
    */
-  struct TALER_DenominationBlindingKeyP blinding_key;
+  union TALER_DenominationBlindingKeyP blinding_key;
 
 };
 
@@ -93,7 +93,7 @@ struct RefreshMeltState
   /**
    * "Crypto data" used in the refresh operation.
    */
-  char *refresh_data;
+  json_t *refresh_data;
 
   /**
    * Reference to a previous melt command.
@@ -136,11 +136,6 @@ struct RefreshMeltState
    */
   struct GNUNET_TIME_Relative total_backoff;
 
-  /**
-   * Number of bytes in @e refresh_data.
-   */
-  size_t refresh_data_length;
-
   /**
    * Amounts to be generated during melt.
    */
@@ -419,8 +414,8 @@ reveal_cb (void *cls,
       }
       fc->coin_priv = coin_privs[i].coin_priv;
       fc->blinding_key = coin_privs[i].blinding_key;
-      fc->sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup
-                                (sigs[i].rsa_signature);
+      TALER_denom_sig_deep_copy (&fc->sig,
+                                 &sigs[i]);
     }
     if (0 != rrs->total_backoff.rel_value_us)
     {
@@ -468,7 +463,6 @@ refresh_reveal_run (void *cls,
   }
   rms = melt_cmd->cls;
   rrs->rrh = TALER_EXCHANGE_refreshes_reveal (is->exchange,
-                                              rms->refresh_data_length,
                                               rms->refresh_data,
                                               rms->noreveal_index,
                                               &reveal_cb,
@@ -512,7 +506,7 @@ refresh_reveal_cleanup (void *cls,
   }
 
   for (unsigned int j = 0; j < rrs->num_fresh_coins; j++)
-    GNUNET_CRYPTO_rsa_signature_free (rrs->fresh_coins[j].sig.rsa_signature);
+    TALER_denom_sig_free (&rrs->fresh_coins[j].sig);
 
   GNUNET_free (rrs->fresh_coins);
   rrs->fresh_coins = NULL;
@@ -641,9 +635,8 @@ link_cb (void *cls,
   case MHD_HTTP_OK:
     /* check that number of coins returned matches */
     if (GNUNET_OK !=
-        TALER_TESTING_get_trait_uint (reveal_cmd,
-                                      0,
-                                      &num_fresh_coins))
+        TALER_TESTING_get_trait_array_length (reveal_cmd,
+                                              &num_fresh_coins))
     {
       GNUNET_break (0);
       TALER_TESTING_interpreter_fail (rls->is);
@@ -672,11 +665,10 @@ link_cb (void *cls,
 
     /* Will point to the pointer inside the cmd state. */
     {
-      const struct TALER_TESTING_FreshCoinData *fc = NULL;
+      const struct TALER_TESTING_FreshCoinData **fc = NULL;
 
       if (GNUNET_OK !=
           TALER_TESTING_get_trait_fresh_coins (reveal_cmd,
-                                               0,
                                                &fc))
       {
         GNUNET_break (0);
@@ -689,13 +681,13 @@ link_cb (void *cls,
         {
           if ( (0 ==
                 GNUNET_memcmp (&coin_privs[i],
-                               &fc[j].coin_priv)) &&
+                               &(*fc)[j].coin_priv)) &&
                (0 ==
-                GNUNET_CRYPTO_rsa_signature_cmp (fc[i].sig.rsa_signature,
-                                                 sigs[j].rsa_signature)) &&
+                TALER_denom_sig_cmp (&(*fc)[i].sig,
+                                     &sigs[j])) &&
                (0 ==
-                GNUNET_CRYPTO_rsa_public_key_cmp (fc[i].pk->key.rsa_public_key,
-                                                  pubs[j].rsa_public_key)) )
+                TALER_denom_pub_cmp (&(*fc)[i].pk->key,
+                                     &pubs[j])) )
           {
             found++;
             break;
@@ -944,7 +936,6 @@ melt_cb (void *cls,
     TALER_LOG_DEBUG ("Doubling the melt (%s)\n",
                      rms->is->commands[rms->is->ip].label);
     rms->rmh = TALER_EXCHANGE_melt (rms->is->exchange,
-                                    rms->refresh_data_length,
                                     rms->refresh_data,
                                     &melt_cb,
                                     rms);
@@ -1003,8 +994,10 @@ melt_run (void *cls,
       return;
     }
 
-    if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
-          (coin_command, 0, &rms->melt_priv))
+    if (GNUNET_OK !=
+        TALER_TESTING_get_trait_coin_priv (coin_command,
+                                           0,
+                                           &rms->melt_priv))
     {
       GNUNET_break (0);
       TALER_TESTING_interpreter_fail (rms->is);
@@ -1020,8 +1013,10 @@ melt_run (void *cls,
       TALER_TESTING_interpreter_fail (rms->is);
       return;
     }
-    if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub
-          (coin_command, 0, &melt_denom_pub))
+    if (GNUNET_OK !=
+        TALER_TESTING_get_trait_denom_pub (coin_command,
+                                           0,
+                                           &melt_denom_pub))
     {
       GNUNET_break (0);
       TALER_TESTING_interpreter_fail (rms->is);
@@ -1063,8 +1058,8 @@ melt_run (void *cls,
                                        &fresh_pk->fee_withdraw));
       rms->fresh_pks[i] = *fresh_pk;
       /* Make a deep copy of the RSA key */
-      rms->fresh_pks[i].key.rsa_public_key
-        = GNUNET_CRYPTO_rsa_public_key_dup (fresh_pk->key.rsa_public_key);
+      TALER_denom_pub_deep_copy (&rms->fresh_pks[i].key,
+                                 &fresh_pk->key);
     }
     rms->refresh_data
       = TALER_EXCHANGE_refresh_prepare (rms->melt_priv,
@@ -1072,9 +1067,7 @@ melt_run (void *cls,
                                         melt_sig,
                                         melt_denom_pub,
                                         num_fresh_coins,
-                                        rms->fresh_pks,
-                                        &rms->refresh_data_length);
-
+                                        rms->fresh_pks);
     if (NULL == rms->refresh_data)
     {
       GNUNET_break (0);
@@ -1082,7 +1075,6 @@ melt_run (void *cls,
       return;
     }
     rms->rmh = TALER_EXCHANGE_melt (is->exchange,
-                                    rms->refresh_data_length,
                                     rms->refresh_data,
                                     &melt_cb,
                                     rms);
@@ -1126,13 +1118,12 @@ melt_cleanup (void *cls,
   if (NULL != rms->fresh_pks)
   {
     for (unsigned int i = 0; i < rms->num_fresh_coins; i++)
-      GNUNET_CRYPTO_rsa_public_key_free (rms->fresh_pks[i].key.rsa_public_key);
+      TALER_denom_pub_free (&rms->fresh_pks[i].key);
   }
   GNUNET_free (rms->fresh_pks);
   rms->fresh_pks = NULL;
-  GNUNET_free (rms->refresh_data);
+  json_decref (rms->refresh_data);
   rms->refresh_data = NULL;
-  rms->refresh_data_length = 0;
   GNUNET_free (rms->melt_fresh_amounts);
   GNUNET_free (rms);
 }
@@ -1147,7 +1138,7 @@ melt_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 melt_traits (void *cls,
              const void **ret,
              const char *trait,
@@ -1162,8 +1153,10 @@ melt_traits (void *cls,
   }
   {
     struct TALER_TESTING_Trait traits[] = {
-      TALER_TESTING_make_trait_denom_pub (index, &rms->fresh_pks[index]),
-      TALER_TESTING_make_trait_coin_priv (0, rms->melt_priv),
+      TALER_TESTING_make_trait_denom_pub (index,
+                                          &rms->fresh_pks[index]),
+      TALER_TESTING_make_trait_coin_priv (0,
+                                          rms->melt_priv),
       TALER_TESTING_trait_end ()
     };
 
@@ -1182,7 +1175,7 @@ melt_traits (void *cls,
  * @param ap NULL-termianted list of amounts to be melted (one per fresh coin)
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_amounts (struct RefreshMeltState *rms,
                va_list ap)
 {
@@ -1225,16 +1218,6 @@ parse_amounts (struct RefreshMeltState *rms,
 }
 
 
-/**
- * Create a "refresh melt" command.
- *
- * @param label command label.
- * @param coin_reference reference to a command
- *        that will provide a coin to refresh.
- * @param expected_response_code expected HTTP code.
- * @param ... NULL-terminated list of amounts to be melted
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_melt (const char *label,
                         const char *coin_reference,
@@ -1265,18 +1248,6 @@ TALER_TESTING_cmd_melt (const char *label,
 }
 
 
-/**
- * Create a "refresh melt" CMD that does TWO /refresh/melt
- * requests.  This was needed to test the replay of a valid melt
- * request, see #5312.
- *
- * @param label command label
- * @param coin_reference reference to a command that will provide
- *        a coin to refresh
- * @param expected_response_code expected HTTP code
- * @param ... NULL-terminated list of amounts to be melted
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_melt_double (const char *label,
                                const char *coin_reference,
@@ -1308,12 +1279,6 @@ TALER_TESTING_cmd_melt_double (const char *label,
 }
 
 
-/**
- * Modify a "refresh melt" command to enable retries.
- *
- * @param cmd command
- * @return modified command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_melt_with_retry (struct TALER_TESTING_Command cmd)
 {
@@ -1335,65 +1300,45 @@ TALER_TESTING_cmd_melt_with_retry (struct 
TALER_TESTING_Command cmd)
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 refresh_reveal_traits (void *cls,
                        const void **ret,
                        const char *trait,
                        unsigned int index)
 {
   struct RefreshRevealState *rrs = cls;
-  unsigned int num_coins = rrs->num_fresh_coins;
-#define NUM_TRAITS ((num_coins * 4) + 3)
-  struct TALER_TESTING_Trait traits[NUM_TRAITS];
-
-  /* Making coin privs traits */
-  for (unsigned int i = 0; i<num_coins; i++)
-    traits[i] = TALER_TESTING_make_trait_coin_priv
-                  (i, &rrs->fresh_coins[i].coin_priv);
-
-  /* Making denom pubs traits */
-  for (unsigned int i = 0; i<num_coins; i++)
-    traits[num_coins + i]
-      = TALER_TESTING_make_trait_denom_pub
-          (i, rrs->fresh_coins[i].pk);
-
-  /* Making denom sigs traits */
-  for (unsigned int i = 0; i<num_coins; i++)
-    traits[(num_coins * 2) + i]
-      = TALER_TESTING_make_trait_denom_sig
-          (i, &rrs->fresh_coins[i].sig);
-  /* blinding key traits */
-  for (unsigned int i = 0; i<num_coins; i++)
-    traits[(num_coins * 3) + i]
-      = TALER_TESTING_make_trait_blinding_key (i,
-                                               
&rrs->fresh_coins[i].blinding_key),
-
-    /* number of fresh coins */
-    traits[(num_coins * 4)] = TALER_TESTING_make_trait_uint
-                                (0, &rrs->num_fresh_coins);
-
-  /* whole array of fresh coins */
-  traits[(num_coins * 4) + 1]
-    = TALER_TESTING_make_trait_fresh_coins (0, rrs->fresh_coins),
-
-  /* end of traits */
-  traits[(num_coins * 4) + 2] = TALER_TESTING_trait_end ();
-
-  return TALER_TESTING_get_trait (traits,
-                                  ret,
-                                  trait,
-                                  index);
+
+  if (index >= rrs->num_fresh_coins)
+    return GNUNET_SYSERR;
+  {
+    struct TALER_TESTING_Trait traits[] = {
+      TALER_TESTING_make_trait_coin_priv (
+        index,
+        &rrs->fresh_coins[index].coin_priv),
+      TALER_TESTING_make_trait_denom_pub (
+        index,
+        rrs->fresh_coins[index].pk),
+      TALER_TESTING_make_trait_denom_sig (
+        index,
+        &rrs->fresh_coins[index].sig),
+      TALER_TESTING_make_trait_blinding_key (
+        index,
+        &rrs->fresh_coins[index].blinding_key),
+      TALER_TESTING_make_trait_array_length (
+        &rrs->num_fresh_coins),
+      TALER_TESTING_make_trait_fresh_coins (
+        (const struct TALER_TESTING_FreshCoinData **) &rrs->fresh_coins),
+      TALER_TESTING_trait_end ()
+    };
+
+    return TALER_TESTING_get_trait (traits,
+                                    ret,
+                                    trait,
+                                    index);
+  }
 }
 
 
-/**
- * Create a "refresh reveal" command.
- *
- * @param label command label.
- * @param melt_reference reference to a "refresh melt" command.
- * @param expected_response_code expected HTTP response code.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_refresh_reveal (const char *label,
                                   const char *melt_reference,
@@ -1418,12 +1363,6 @@ TALER_TESTING_cmd_refresh_reveal (const char *label,
 }
 
 
-/**
- * Modify a "refresh reveal" command to enable retries.
- *
- * @param cmd command
- * @return modified command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_refresh_reveal_with_retry (struct TALER_TESTING_Command cmd)
 {
@@ -1436,14 +1375,6 @@ TALER_TESTING_cmd_refresh_reveal_with_retry (struct 
TALER_TESTING_Command cmd)
 }
 
 
-/**
- * Create a "refresh link" command.
- *
- * @param label command label.
- * @param reveal_reference reference to a "refresh reveal" CMD.
- * @param expected_response_code expected HTTP response code
- * @return the "refresh link" command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_refresh_link (const char *label,
                                 const char *reveal_reference,
@@ -1467,12 +1398,6 @@ TALER_TESTING_cmd_refresh_link (const char *label,
 }
 
 
-/**
- * Modify a "refresh link" command to enable retries.
- *
- * @param cmd command
- * @return modified command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_refresh_link_with_retry (struct TALER_TESTING_Command cmd)
 {
diff --git a/src/testing/testing_api_cmd_refund.c 
b/src/testing/testing_api_cmd_refund.c
index 30f25769..c288e9e1 100644
--- a/src/testing/testing_api_cmd_refund.c
+++ b/src/testing/testing_api_cmd_refund.c
@@ -127,7 +127,7 @@ refund_run (void *cls,
   const struct TALER_CoinSpendPrivateKeyP *coin_priv;
   struct TALER_CoinSpendPublicKeyP coin;
   const json_t *contract_terms;
-  struct GNUNET_HashCode h_contract_terms;
+  struct TALER_PrivateContractHash h_contract_terms;
   struct TALER_Amount refund_amount;
   const struct TALER_MerchantPrivateKeyP *merchant_priv;
   const struct TALER_TESTING_Command *coin_cmd;
@@ -157,7 +157,6 @@ refund_run (void *cls,
   }
   if (GNUNET_OK !=
       TALER_TESTING_get_trait_contract_terms (coin_cmd,
-                                              0,
                                               &contract_terms))
   {
     GNUNET_break (0);
@@ -183,7 +182,6 @@ refund_run (void *cls,
                                       &coin.eddsa_pub);
   if (GNUNET_OK !=
       TALER_TESTING_get_trait_merchant_priv (coin_cmd,
-                                             0,
                                              &merchant_priv))
   {
     GNUNET_break (0);
@@ -228,17 +226,6 @@ refund_cleanup (void *cls,
 }
 
 
-/**
- * Create a "refund" command.
- *
- * @param label command label.
- * @param expected_response_code expected HTTP status code.
- * @param refund_amount the amount to ask a refund for.
- * @param coin_reference reference to a command that can
- *        provide a coin to be refunded.
- *
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_refund (const char *label,
                           unsigned int expected_response_code,
@@ -265,23 +252,9 @@ TALER_TESTING_cmd_refund (const char *label,
 }
 
 
-/**
- * Create a "refund" command, allow to specify refund transaction
- * id.  Mainly used to create conflicting requests.
- *
- * @param label command label.
- * @param expected_response_code expected HTTP status code.
- * @param refund_amount the amount to ask a refund for.
- * @param coin_reference reference to a command that can
- *        provide a coin to be refunded.
- * @param refund_transaction_id transaction id to use
- *        in the request.
- *
- * @return the command.
- */
 struct TALER_TESTING_Command
-TALER_TESTING_cmd_refund_with_id
-  (const char *label,
+TALER_TESTING_cmd_refund_with_id (
+  const char *label,
   unsigned int expected_response_code,
   const char *refund_amount,
   const char *coin_reference,
diff --git a/src/testing/testing_api_cmd_revoke.c 
b/src/testing/testing_api_cmd_revoke.c
index 9f904454..4522dede 100644
--- a/src/testing/testing_api_cmd_revoke.c
+++ b/src/testing/testing_api_cmd_revoke.c
@@ -100,7 +100,7 @@ revoke_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 revoke_traits (void *cls,
                const void **ret,
                const char *trait,
@@ -110,8 +110,7 @@ revoke_traits (void *cls,
   struct TALER_TESTING_Trait traits[] = {
     /* Needed by the handler which waits the proc'
      * death and calls the next command */
-    TALER_TESTING_make_trait_process (0,
-                                      &rs->revoke_proc),
+    TALER_TESTING_make_trait_process (&rs->revoke_proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -183,16 +182,6 @@ revoke_run (void *cls,
 }
 
 
-/**
- * Make a "revoke" command.
- *
- * @param label the command label.
- * @param expected_response_code expected HTTP status code.
- * @param coin_reference reference to a CMD that will offer the
- *        denomination to revoke.
- * @param config_filename configuration file name.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_revoke (const char *label,
                           unsigned int expected_response_code,
diff --git a/src/testing/testing_api_cmd_rewind.c 
b/src/testing/testing_api_cmd_rewind.c
index 979607cd..dae45624 100644
--- a/src/testing/testing_api_cmd_rewind.c
+++ b/src/testing/testing_api_cmd_rewind.c
@@ -46,18 +46,6 @@ struct RewindIpState
 };
 
 
-/**
- * Only defined to respect the API.
- */
-static void
-rewind_ip_cleanup (void *cls,
-                   const struct TALER_TESTING_Command *cmd)
-{
-  (void) cls;
-  (void) cmd;
-}
-
-
 /**
  * Seek for the @a target command in @a batch (and rewind to it
  * if successful).
@@ -68,26 +56,24 @@ rewind_ip_cleanup (void *cls,
  * @return #GNUNET_OK on success, #GNUNET_NO if target was not found,
  *         #GNUNET_SYSERR if target is in the future and we failed
  */
-static int
+static enum GNUNET_GenericReturnValue
 seek_batch (struct TALER_TESTING_Interpreter *is,
             const struct TALER_TESTING_Command *cmd,
             const struct TALER_TESTING_Command *target)
 {
   unsigned int new_ip;
-#define BATCH_INDEX 1
-  struct TALER_TESTING_Command *batch;
+  struct TALER_TESTING_Command **batch;
   struct TALER_TESTING_Command *current;
   struct TALER_TESTING_Command *icmd;
-  const struct TALER_TESTING_Command *match;
+  struct TALER_TESTING_Command *match;
 
   current = TALER_TESTING_cmd_batch_get_current (cmd);
   GNUNET_assert (GNUNET_OK ==
-                 TALER_TESTING_get_trait_cmd (cmd,
-                                              BATCH_INDEX,
-                                              &batch));
+                 TALER_TESTING_get_trait_batch_cmds (cmd,
+                                                     &batch));
   match = NULL;
   for (new_ip = 0;
-       NULL != (icmd = &batch[new_ip]);
+       NULL != (icmd = &(*batch)[new_ip]);
        new_ip++)
   {
     if (current == target)
@@ -189,15 +175,6 @@ rewind_ip_run (void *cls,
 }
 
 
-/**
- * Make the instruction pointer point to @a new_ip
- * only if @a counter is greater than zero.
- *
- * @param label command label
- * @param target_label label of the new instruction pointer's destination 
after the jump;
- *                     must be before the current instruction
- * @param counter counts how many times the rewinding is to happen.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_rewind_ip (const char *label,
                              const char *target_label,
@@ -212,8 +189,7 @@ TALER_TESTING_cmd_rewind_ip (const char *label,
     struct TALER_TESTING_Command cmd = {
       .cls = ris,
       .label = label,
-      .run = &rewind_ip_run,
-      .cleanup = &rewind_ip_cleanup
+      .run = &rewind_ip_run
     };
 
     return cmd;
diff --git a/src/testing/testing_api_cmd_serialize_keys.c 
b/src/testing/testing_api_cmd_serialize_keys.c
index 82df0f06..d3b34a93 100644
--- a/src/testing/testing_api_cmd_serialize_keys.c
+++ b/src/testing/testing_api_cmd_serialize_keys.c
@@ -131,7 +131,7 @@ serialize_keys_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success.
  */
-static int
+static enum GNUNET_GenericReturnValue
 serialize_keys_traits (void *cls,
                        const void **ret,
                        const char *trait,
@@ -139,9 +139,9 @@ serialize_keys_traits (void *cls,
 {
   struct SerializeKeysState *sks = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_exchange_keys (0, sks->keys),
-    TALER_TESTING_make_trait_url (TALER_TESTING_UT_EXCHANGE_BASE_URL,
-                                  sks->exchange_url),
+    TALER_TESTING_make_trait_exchange_keys (sks->keys),
+    TALER_TESTING_make_trait_exchange_url (
+      (const char **) &sks->exchange_url),
     TALER_TESTING_trait_end ()
   };
 
@@ -167,7 +167,7 @@ connect_with_state_run (void *cls,
   struct ConnectWithStateState *cwss = cls;
   const struct TALER_TESTING_Command *state_cmd;
   const json_t *serialized_keys;
-  const char *exchange_url;
+  const char **exchange_url;
 
   /* This command usually gets rescheduled after serialized
    * reconnection.  */
@@ -178,8 +178,8 @@ connect_with_state_run (void *cls,
   }
 
   cwss->is = is;
-  state_cmd = TALER_TESTING_interpreter_lookup_command
-                (is, cwss->state_reference);
+  state_cmd = TALER_TESTING_interpreter_lookup_command (is,
+                                                        cwss->state_reference);
 
   /* Command providing serialized keys not found.  */
   if (NULL == state_cmd)
@@ -191,7 +191,6 @@ connect_with_state_run (void *cls,
 
   GNUNET_assert (GNUNET_OK ==
                  TALER_TESTING_get_trait_exchange_keys (state_cmd,
-                                                        0,
                                                         &serialized_keys));
   {
     char *dump;
@@ -204,11 +203,10 @@ connect_with_state_run (void *cls,
   }
 
   GNUNET_assert (GNUNET_OK ==
-                 TALER_TESTING_get_trait_url (state_cmd,
-                                              
TALER_TESTING_UT_EXCHANGE_BASE_URL,
-                                              &exchange_url));
+                 TALER_TESTING_get_trait_exchange_url (state_cmd,
+                                                       &exchange_url));
   is->exchange = TALER_EXCHANGE_connect (is->ctx,
-                                         exchange_url,
+                                         *exchange_url,
                                          &TALER_TESTING_cert_cb,
                                          cwss,
                                          TALER_EXCHANGE_OPTION_DATA,
diff --git a/src/testing/testing_api_cmd_stat.c 
b/src/testing/testing_api_cmd_stat.c
index 9461a22c..5d41c05c 100644
--- a/src/testing/testing_api_cmd_stat.c
+++ b/src/testing/testing_api_cmd_stat.c
@@ -27,46 +27,6 @@
 #include "taler_testing_lib.h"
 
 
-/**
- * Cleanup the state from a "stat service" CMD.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-stat_cleanup (void *cls,
-              const struct TALER_TESTING_Command *cmd)
-{
-  (void) cls;
-  (void) cmd;
-  /* nothing to clean.  */
-}
-
-
-/**
- * No traits to offer, just provide a stub to be called when
- * some CMDs iterates through the list of all the commands.
- *
- * @param cls closure.
- * @param[out] ret result.
- * @param trait name of the trait.
- * @param index index number of the trait to return.
- * @return #GNUNET_OK on success.
- */
-static int
-stat_traits (void *cls,
-             const void **ret,
-             const char *trait,
-             unsigned int index)
-{
-  (void) cls;
-  (void) ret;
-  (void) trait;
-  (void) index;
-  return GNUNET_NO;
-}
-
-
 /**
  * Add the time @a cmd took to the respective duration in @a timings.
  *
@@ -123,21 +83,21 @@ do_stat (struct TALER_TESTING_Timer *timings,
 {
   if (TALER_TESTING_cmd_is_batch (cmd))
   {
-#define BATCH_INDEX 1
-    struct TALER_TESTING_Command *bcmd;
+    struct TALER_TESTING_Command **bcmd;
 
     if (GNUNET_OK !=
-        TALER_TESTING_get_trait_cmd (cmd,
-                                     BATCH_INDEX,
-                                     &bcmd))
+        TALER_TESTING_get_trait_batch_cmds (cmd,
+                                            &bcmd))
     {
       GNUNET_break (0);
       return;
     }
 
-    for (unsigned int j = 0; NULL != bcmd[j].label; j++)
+    for (unsigned int j = 0;
+         NULL != (*bcmd)[j].label;
+         j++)
       do_stat (timings,
-               &bcmd[j]);
+               &(*bcmd)[j]);
   }
   else
   {
@@ -172,20 +132,12 @@ stat_run (void *cls,
 }
 
 
-/**
- * Obtain performance data from the interpreter.
- *
- * @param timers what commands (by label) to obtain runtimes for
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_stat (struct TALER_TESTING_Timer *timers)
 {
   struct TALER_TESTING_Command cmd = {
     .label = "stat",
     .run = stat_run,
-    .cleanup = stat_cleanup,
-    .traits = stat_traits,
     .cls = (void *) timers
   };
 
diff --git a/src/testing/testing_api_cmd_status.c 
b/src/testing/testing_api_cmd_status.c
index 6acfcc75..8fdfa461 100644
--- a/src/testing/testing_api_cmd_status.c
+++ b/src/testing/testing_api_cmd_status.c
@@ -146,7 +146,7 @@ history_entry_cmp (const struct 
TALER_EXCHANGE_ReserveHistory *h1,
  * @param[in,out] found array to update
  * @return #GNUNET_OK if @a cmd action on reserve was found in @a history
  */
-static int
+static enum GNUNET_GenericReturnValue
 analyze_command (const struct TALER_ReservePublicKeyP *reserve_pub,
                  const struct TALER_TESTING_Command *cmd,
                  unsigned int history_length,
@@ -155,22 +155,20 @@ analyze_command (const struct TALER_ReservePublicKeyP 
*reserve_pub,
 {
   if (TALER_TESTING_cmd_is_batch (cmd))
   {
-#define BATCH_INDEX 1
     struct TALER_TESTING_Command *cur;
-    struct TALER_TESTING_Command *bcmd;
+    struct TALER_TESTING_Command **bcmd;
 
     cur = TALER_TESTING_cmd_batch_get_current (cmd);
     if (GNUNET_OK !=
-        TALER_TESTING_get_trait_cmd (cmd,
-                                     BATCH_INDEX,
-                                     &bcmd))
+        TALER_TESTING_get_trait_batch_cmds (cmd,
+                                            &bcmd))
     {
       GNUNET_break (0);
       return GNUNET_SYSERR;
     }
-    for (unsigned int i = 0; NULL != bcmd[i].label; i++)
+    for (unsigned int i = 0; NULL != (*bcmd)[i].label; i++)
     {
-      struct TALER_TESTING_Command *step = &bcmd[i];
+      struct TALER_TESTING_Command *step = &(*bcmd)[i];
 
       if (step == cur)
         break; /* if *we* are in a batch, make sure not to analyze commands 
past 'now' */
@@ -191,7 +189,6 @@ analyze_command (const struct TALER_ReservePublicKeyP 
*reserve_pub,
 
     if (GNUNET_OK !=
         TALER_TESTING_get_trait_reserve_pub (cmd,
-                                             0,
                                              &rp))
       return GNUNET_OK; /* command does nothing for reserves */
     if (0 !=
@@ -200,7 +197,6 @@ analyze_command (const struct TALER_ReservePublicKeyP 
*reserve_pub,
       return GNUNET_OK; /* command affects some _other_ reserve */
     if (GNUNET_OK !=
         TALER_TESTING_get_trait_reserve_history (cmd,
-                                                 0,
                                                  &he))
     {
       /* NOTE: only for debugging... */
@@ -346,7 +342,6 @@ status_run (void *cls,
   }
   if (GNUNET_OK !=
       TALER_TESTING_get_trait_reserve_pub (create_reserve,
-                                           0,
                                            &ss->reserve_pubp))
   {
     GNUNET_break (0);
@@ -388,16 +383,6 @@ status_cleanup (void *cls,
 }
 
 
-/**
- * Create a "reserve status" command.
- *
- * @param label the command label.
- * @param reserve_reference reference to the reserve to check.
- * @param expected_balance expected balance for the reserve.
- * @param expected_response_code expected HTTP response code.
- *
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_status (const char *label,
                           const char *reserve_reference,
diff --git a/src/testing/testing_api_cmd_transfer_get.c 
b/src/testing/testing_api_cmd_transfer_get.c
index 3ca319cb..580f6ee8 100644
--- a/src/testing/testing_api_cmd_transfer_get.c
+++ b/src/testing/testing_api_cmd_transfer_get.c
@@ -79,11 +79,6 @@ struct TrackTransferState
    */
   unsigned int expected_response_code;
 
-  /**
-   * Index to the WTID to pick, in case @a wtid_reference has
-   * many on offer.
-   */
-  unsigned int index;
 };
 
 
@@ -219,11 +214,12 @@ track_transfer_cb (void *cls,
      * or any operation that could provide wire-details.  (2)
      * Total amount for this transfer matches the one from any
      * referenced command that could provide one.
-     */if (NULL != tts->wire_details_reference)
+     */
+    if (NULL != tts->wire_details_reference)
     {
       const struct TALER_TESTING_Command *wire_details_cmd;
-      const json_t *wire_details;
-      struct GNUNET_HashCode h_wire_details;
+      const char **payto_uri;
+      struct TALER_PaytoHash h_payto;
 
       wire_details_cmd
         = TALER_TESTING_interpreter_lookup_command (is,
@@ -235,19 +231,17 @@ track_transfer_cb (void *cls,
         return;
       }
       if (GNUNET_OK !=
-          TALER_TESTING_get_trait_wire_details (wire_details_cmd,
-                                                0,
-                                                &wire_details))
+          TALER_TESTING_get_trait_payto_uri (wire_details_cmd,
+                                             &payto_uri))
       {
         GNUNET_break (0);
         TALER_TESTING_interpreter_fail (is);
         return;
       }
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_JSON_merchant_wire_signature_hash (wire_details,
-                                                              
&h_wire_details));
-      if (0 != GNUNET_memcmp (&h_wire_details,
-                              &ta->h_wire))
+      TALER_payto_hash (*payto_uri,
+                        &h_payto);
+      if (0 != GNUNET_memcmp (&h_payto,
+                              &ta->h_payto))
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                     "Wire hash missmath to command %s\n",
@@ -274,9 +268,8 @@ track_transfer_cb (void *cls,
         return;
       }
       if (GNUNET_OK !=
-          TALER_TESTING_get_trait_amount_obj (total_amount_cmd,
-                                              0,
-                                              &total_amount_from_reference))
+          TALER_TESTING_get_trait_amount (total_amount_cmd,
+                                          &total_amount_from_reference))
       {
         GNUNET_break (0);
         TALER_TESTING_interpreter_fail (is);
@@ -319,7 +312,9 @@ track_transfer_run (void *cls,
 
   /* If no reference is given, we'll use a all-zeros
    * WTID */
-  memset (&wtid, 0, sizeof (wtid));
+  memset (&wtid,
+          0,
+          sizeof (wtid));
   wtid_ptr = &wtid;
 
   tts->is = is;
@@ -327,9 +322,8 @@ track_transfer_run (void *cls,
   {
     const struct TALER_TESTING_Command *wtid_cmd;
 
-    wtid_cmd = TALER_TESTING_interpreter_lookup_command
-                 (tts->is, tts->wtid_reference);
-
+    wtid_cmd = TALER_TESTING_interpreter_lookup_command (tts->is,
+                                                         tts->wtid_reference);
     if (NULL == wtid_cmd)
     {
       GNUNET_break (0);
@@ -337,8 +331,9 @@ track_transfer_run (void *cls,
       return;
     }
 
-    if (GNUNET_OK != TALER_TESTING_get_trait_wtid
-          (wtid_cmd, tts->index, &wtid_ptr))
+    if (GNUNET_OK !=
+        TALER_TESTING_get_trait_wtid (wtid_cmd,
+                                      &wtid_ptr))
     {
       GNUNET_break (0);
       TALER_TESTING_interpreter_fail (tts->is);
@@ -354,33 +349,15 @@ track_transfer_run (void *cls,
 }
 
 
-/**
- * Make a "track transfer" CMD where no "expected"-arguments,
- * except the HTTP response code, are given.  The best use case
- * is when what matters to check is the HTTP response code, e.g.
- * when a bogus WTID was passed.
- *
- * @param label the command label
- * @param wtid_reference reference to any command which can provide
- *        a wtid.  If NULL is given, then a all zeroed WTID is
- *        used that will at 99.9999% probability NOT match any
- *        existing WTID known to the exchange.
- * @param index index number of the WTID to track, in case there
- *        are multiple on offer.
- * @param expected_response_code expected HTTP response code.
- * @return the command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_track_transfer_empty (const char *label,
                                         const char *wtid_reference,
-                                        unsigned int index,
                                         unsigned int expected_response_code)
 {
   struct TrackTransferState *tts;
 
   tts = GNUNET_new (struct TrackTransferState);
   tts->wtid_reference = wtid_reference;
-  tts->index = index;
   tts->expected_response_code = expected_response_code;
   {
     struct TALER_TESTING_Command cmd = {
@@ -395,25 +372,9 @@ TALER_TESTING_cmd_track_transfer_empty (const char *label,
 }
 
 
-/**
- * Make a "track transfer" command, specifying which amount and
- * wire fee are expected.
- *
- * @param label the command label.
- * @param wtid_reference reference to any command which can provide
- *        a wtid.  Will be the one tracked.
- * @param index in case there are multiple WTID offered, this
- *        parameter selects a particular one.
- * @param expected_response_code expected HTTP response code.
- * @param expected_total_amount how much money we expect being moved
- *        with this wire-transfer.
- * @param expected_wire_fee expected wire fee.
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_track_transfer (const char *label,
                                   const char *wtid_reference,
-                                  unsigned int index,
                                   unsigned int expected_response_code,
                                   const char *expected_total_amount,
                                   const char *expected_wire_fee)
@@ -422,7 +383,6 @@ TALER_TESTING_cmd_track_transfer (const char *label,
 
   tts = GNUNET_new (struct TrackTransferState);
   tts->wtid_reference = wtid_reference;
-  tts->index = index;
   tts->expected_response_code = expected_response_code;
   tts->expected_total_amount = expected_total_amount;
   tts->expected_wire_fee = expected_wire_fee;
diff --git a/src/testing/testing_api_cmd_twister_exec_client.c 
b/src/testing/testing_api_cmd_twister_exec_client.c
index b3903f29..d1d781f5 100644
--- a/src/testing/testing_api_cmd_twister_exec_client.c
+++ b/src/testing/testing_api_cmd_twister_exec_client.c
@@ -194,7 +194,7 @@ hack_response_code_cleanup
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 hack_response_code_traits (void *cls,
                            const void **ret,
                            const char *trait,
@@ -203,7 +203,7 @@ hack_response_code_traits (void *cls,
 
   struct HackResponseCodeState *hrcs = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &hrcs->proc),
+    TALER_TESTING_make_trait_process (&hrcs->proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -251,16 +251,6 @@ hack_response_code_run (void *cls,
 }
 
 
-/**
- * Define a "hack response code" CMD.  This causes the next
- * response code (from the service proxied by the twister) to
- * be substituted with @a http_status.
- *
- * @param label command label
- * @param config_filename configuration filename.
- * @param http_status new response code to use
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_hack_response_code (const char *label,
                                       const char *config_filename,
@@ -271,16 +261,17 @@ TALER_TESTING_cmd_hack_response_code (const char *label,
   hrcs = GNUNET_new (struct HackResponseCodeState);
   hrcs->http_status = http_status;
   hrcs->config_filename = config_filename;
-
-  struct TALER_TESTING_Command cmd = {
-    .label = label,
-    .run = &hack_response_code_run,
-    .cleanup = &hack_response_code_cleanup,
-    .traits = &hack_response_code_traits,
-    .cls = hrcs
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .label = label,
+      .run = &hack_response_code_run,
+      .cleanup = &hack_response_code_cleanup,
+      .traits = &hack_response_code_traits,
+      .cls = hrcs
+    };
+
+    return cmd;
+  }
 }
 
 
@@ -320,7 +311,7 @@ delete_object_cleanup
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 delete_object_traits (void *cls,
                       const void **ret,
                       const char *trait,
@@ -329,7 +320,7 @@ delete_object_traits (void *cls,
 
   struct DeleteObjectState *dos = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &dos->proc),
+    TALER_TESTING_make_trait_process (&dos->proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -379,9 +370,8 @@ delete_object_run (void *cls,
  * @param cmd the command being cleaned up.
  */
 static void
-modify_object_cleanup
-  (void *cls,
-  const struct TALER_TESTING_Command *cmd)
+modify_object_cleanup (void *cls,
+                       const struct TALER_TESTING_Command *cmd)
 {
   struct ModifyObjectState *mos = cls;
 
@@ -407,7 +397,7 @@ modify_object_cleanup
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 modify_object_traits (void *cls,
                       const void **ret,
                       const char *trait,
@@ -416,7 +406,7 @@ modify_object_traits (void *cls,
 
   struct ModifyObjectState *mos = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &mos->proc),
+    TALER_TESTING_make_trait_process (&mos->proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -523,16 +513,6 @@ modify_header_dl_run (void *cls,
 }
 
 
-/**
- * Create a "delete object" CMD.  This command deletes
- * the JSON object pointed by @a path.
- *
- * @param label command label
- * @param config_filename configuration filename.
- * @param path object-like path notation to point the object
- *        to delete.
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_delete_object (const char *label,
                                  const char *config_filename,
@@ -598,10 +578,9 @@ flip_object_traits (void *cls,
                     const char *trait,
                     unsigned int index)
 {
-
   struct FlipObjectState *fos = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &fos->proc),
+    TALER_TESTING_make_trait_process (&fos->proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -674,15 +653,6 @@ flip_download_run (void *cls,
 }
 
 
-/**
- * Define a "flip object" command, for objects to upload.
- *
- * @param label command label
- * @param config_filename configuration filename.
- * @param path object-like path notation to point the object
- *        to flip.
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_flip_upload (const char *label,
                                const char *config_filename,
@@ -693,28 +663,20 @@ TALER_TESTING_cmd_flip_upload (const char *label,
   dos = GNUNET_new (struct FlipObjectState);
   dos->path = path;
   dos->config_filename = config_filename;
-
-  struct TALER_TESTING_Command cmd = {
-    .label = label,
-    .run = &flip_upload_run,
-    .cleanup = &flip_object_cleanup,
-    .traits = &flip_object_traits,
-    .cls = dos
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .label = label,
+      .run = &flip_upload_run,
+      .cleanup = &flip_object_cleanup,
+      .traits = &flip_object_traits,
+      .cls = dos
+    };
+
+    return cmd;
+  }
 }
 
 
-/**
- * Define a "flip object" command, for objects to download.
- *
- * @param label command label
- * @param config_filename configuration filename.
- * @param path object-like path notation to point the object
- *        to flip.
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_flip_download (const char *label,
                                  const char *config_filename,
@@ -725,16 +687,17 @@ TALER_TESTING_cmd_flip_download (const char *label,
   dos = GNUNET_new (struct FlipObjectState);
   dos->path = path;
   dos->config_filename = config_filename;
-
-  struct TALER_TESTING_Command cmd = {
-    .label = label,
-    .run = &flip_download_run,
-    .cleanup = &flip_object_cleanup,
-    .traits = &flip_object_traits,
-    .cls = dos
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .label = label,
+      .run = &flip_download_run,
+      .cleanup = &flip_object_cleanup,
+      .traits = &flip_object_traits,
+      .cls = dos
+    };
+
+    return cmd;
+  }
 }
 
 
@@ -773,7 +736,7 @@ malform_request_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 malform_request_traits (void *cls,
                         const void **ret,
                         const char *trait,
@@ -781,7 +744,7 @@ malform_request_traits (void *cls,
 {
   struct MalformRequestState *mrs = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &mrs->proc),
+    TALER_TESTING_make_trait_process (&mrs->proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -831,9 +794,8 @@ malform_request_run (void *cls,
  * @param cmd the command being cleaned up.
  */
 static void
-malform_response_cleanup
-  (void *cls,
-  const struct TALER_TESTING_Command *cmd)
+malform_response_cleanup (void *cls,
+                          const struct TALER_TESTING_Command *cmd)
 {
   struct MalformResponseState *mrs = cls;
 
@@ -859,7 +821,7 @@ malform_response_cleanup
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 malform_response_traits (void *cls,
                          const void **ret,
                          const char *trait,
@@ -867,7 +829,7 @@ malform_response_traits (void *cls,
 {
   struct MalformResponseState *mrs = cls;
   struct TALER_TESTING_Trait traits[] = {
-    TALER_TESTING_make_trait_process (0, &mrs->proc),
+    TALER_TESTING_make_trait_process (&mrs->proc),
     TALER_TESTING_trait_end ()
   };
 
@@ -909,14 +871,6 @@ malform_response_run (void *cls,
 }
 
 
-/**
- * Create a "malform request" CMD.  This command makes the
- * next request randomly malformed (by truncating it).
- *
- * @param label command label
- * @param config_filename configuration filename.
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_malform_request (const char *label,
                                    const char *config_filename)
@@ -925,28 +879,20 @@ TALER_TESTING_cmd_malform_request (const char *label,
 
   mrs = GNUNET_new (struct MalformRequestState);
   mrs->config_filename = config_filename;
-
-  struct TALER_TESTING_Command cmd = {
-    .label = label,
-    .run = &malform_request_run,
-    .cleanup = &malform_request_cleanup,
-    .traits = &malform_request_traits,
-    .cls = mrs
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .label = label,
+      .run = &malform_request_run,
+      .cleanup = &malform_request_cleanup,
+      .traits = &malform_request_traits,
+      .cls = mrs
+    };
+
+    return cmd;
+  }
 }
 
 
-/**
- * Create a "malform response" CMD.  This command makes
- * the next response randomly malformed (by truncating it).
- *
- * @param label command label
- * @param config_filename configuration filename.
- *
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_malform_response (const char *label,
                                     const char *config_filename)
@@ -969,19 +915,6 @@ TALER_TESTING_cmd_malform_response (const char *label,
 }
 
 
-/**
- * Create a "modify object" CMD.  This command instructs
- * the twister to modify the next object that is downloaded
- * from the proxied service.
- *
- * @param label command label
- * @param config_filename configuration filename.
- * @param path object-like path notation to point the object
- *        to modify.
- * @param value value to put as the object's.
- *
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_modify_object_dl (const char *label,
                                     const char *config_filename,
@@ -994,31 +927,20 @@ TALER_TESTING_cmd_modify_object_dl (const char *label,
   mos->path = path;
   mos->value = value;
   mos->config_filename = config_filename;
-
-  struct TALER_TESTING_Command cmd = {
-    .label = label,
-    .run = &modify_object_dl_run,
-    .cleanup = &modify_object_cleanup,
-    .traits = &modify_object_traits,
-    .cls = mos
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .label = label,
+      .run = &modify_object_dl_run,
+      .cleanup = &modify_object_cleanup,
+      .traits = &modify_object_traits,
+      .cls = mos
+    };
+
+    return cmd;
+  }
 }
 
 
-/**
- * Create a "modify object" CMD.  This command instructs
- * the twister to modify the next object that will be uploaded
- * to the proxied service.
- *
- * @param label command label
- * @param config_filename configuration filename.
- * @param path object-like path notation pointing the object
- *        to modify.
- * @param value value to put as the object's.
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_modify_object_ul (const char *label,
                                     const char *config_filename,
@@ -1031,29 +953,20 @@ TALER_TESTING_cmd_modify_object_ul (const char *label,
   mos->path = path;
   mos->value = value;
   mos->config_filename = config_filename;
-
-  struct TALER_TESTING_Command cmd = {
-    .label = label,
-    .run = &modify_object_ul_run,
-    .cleanup = &modify_object_cleanup,
-    .traits = &modify_object_traits,
-    .cls = mos
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .label = label,
+      .run = &modify_object_ul_run,
+      .cleanup = &modify_object_cleanup,
+      .traits = &modify_object_traits,
+      .cls = mos
+    };
+
+    return cmd;
+  }
 }
 
 
-/**
- * Create a "modify header" CMD.  This command instructs
- * the twister to modify a header in the next HTTP response.
- *
- * @param label command label
- * @param config_filename configuration filename.
- * @param path identifies the location to modify
- * @param value value to set the header to.
- * @return the command
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_modify_header_dl (const char *label,
                                     const char *config_filename,
@@ -1066,16 +979,17 @@ TALER_TESTING_cmd_modify_header_dl (const char *label,
   mos->path = path;
   mos->value = value;
   mos->config_filename = config_filename;
-
-  struct TALER_TESTING_Command cmd = {
-    .label = label,
-    .run = &modify_header_dl_run,
-    .cleanup = &modify_object_cleanup,
-    .traits = &modify_object_traits,
-    .cls = mos
-  };
-
-  return cmd;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .label = label,
+      .run = &modify_header_dl_run,
+      .cleanup = &modify_object_cleanup,
+      .traits = &modify_object_traits,
+      .cls = mos
+    };
+
+    return cmd;
+  }
 }
 
 
diff --git a/src/testing/testing_api_cmd_withdraw.c 
b/src/testing/testing_api_cmd_withdraw.c
index 23beb606..414e7cea 100644
--- a/src/testing/testing_api_cmd_withdraw.c
+++ b/src/testing/testing_api_cmd_withdraw.c
@@ -84,6 +84,21 @@ struct WithdrawState
    */
   char *exchange_url;
 
+  /**
+   * URI if the reserve we are withdrawing from.
+   */
+  char *reserve_payto_uri;
+
+  /**
+   * Private key of the reserve we are withdrawing from.
+   */
+  struct TALER_ReservePrivateKeyP reserve_priv;
+
+  /**
+   * Public key of the reserve we are withdrawing from.
+   */
+  struct TALER_ReservePublicKeyP reserve_pub;
+
   /**
    * Interpreter state (during command).
    */
@@ -126,6 +141,12 @@ struct WithdrawState
    */
   struct GNUNET_TIME_Relative total_backoff;
 
+  /**
+   * Set to the KYC UUID *if* the exchange replied with
+   * a request for KYC.
+   */
+  uint64_t kyc_uuid;
+
   /**
    * Expected HTTP response code to the request.
    */
@@ -240,8 +261,8 @@ reserve_withdraw_cb (void *cls,
   switch (wr->hr.http_status)
   {
   case MHD_HTTP_OK:
-    ws->sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup (
-      wr->details.success.sig.rsa_signature);
+    TALER_denom_sig_deep_copy (&ws->sig,
+                               &wr->details.success.sig);
     if (0 != ws->total_backoff.rel_value_us)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -253,7 +274,7 @@ reserve_withdraw_cb (void *cls,
     break;
   case MHD_HTTP_ACCEPTED:
     /* nothing to check */
-    /* TODO: trait for returned uuid! */
+    ws->kyc_uuid = wr->details.accepted.payment_target_uuid;
     break;
   case MHD_HTTP_FORBIDDEN:
     /* nothing to check */
@@ -287,7 +308,7 @@ reserve_withdraw_cb (void *cls,
  * @param[out] idx where we set $INDEX
  * @return #GNUNET_SYSERR if $INDEX is present but not numeric
  */
-static int
+static enum GNUNET_GenericReturnValue
 parse_coin_reference (const char *coin_reference,
                       char **cref,
                       unsigned int *idx)
@@ -337,6 +358,7 @@ withdraw_run (void *cls,
   const struct TALER_EXCHANGE_DenomPublicKey *dpk;
 
   (void) cmd;
+  ws->is = is;
   create_reserve
     = TALER_TESTING_interpreter_lookup_command (
         is,
@@ -349,13 +371,21 @@ withdraw_run (void *cls,
   }
   if (GNUNET_OK !=
       TALER_TESTING_get_trait_reserve_priv (create_reserve,
-                                            0,
                                             &rp))
   {
     GNUNET_break (0);
     TALER_TESTING_interpreter_fail (is);
     return;
   }
+  if (NULL == ws->exchange_url)
+    ws->exchange_url
+      = GNUNET_strdup (TALER_EXCHANGE_get_base_url (is->exchange));
+  ws->reserve_priv = *rp;
+  GNUNET_CRYPTO_eddsa_key_get_public (&ws->reserve_priv.eddsa_priv,
+                                      &ws->reserve_pub.eddsa_pub);
+  ws->reserve_payto_uri
+    = TALER_payto_from_reserve (ws->exchange_url,
+                                &ws->reserve_pub);
   if (NULL == ws->reuse_coin_key_ref)
   {
     TALER_planchet_setup_random (&ws->ps);
@@ -382,7 +412,6 @@ withdraw_run (void *cls,
     TALER_planchet_setup_random (&ws->ps);
     ws->ps.coin_priv = *coin_priv;
   }
-  ws->is = is;
   if (NULL == ws->pk)
   {
     dpk = TALER_TESTING_find_pk (TALER_EXCHANGE_get_keys (is->exchange),
@@ -451,17 +480,14 @@ withdraw_cleanup (void *cls,
     GNUNET_SCHEDULER_cancel (ws->retry_task);
     ws->retry_task = NULL;
   }
-  if (NULL != ws->sig.rsa_signature)
-  {
-    GNUNET_CRYPTO_rsa_signature_free (ws->sig.rsa_signature);
-    ws->sig.rsa_signature = NULL;
-  }
+  TALER_denom_sig_free (&ws->sig);
   if (NULL != ws->pk)
   {
     TALER_EXCHANGE_destroy_denomination_key (ws->pk);
     ws->pk = NULL;
   }
   GNUNET_free (ws->exchange_url);
+  GNUNET_free (ws->reserve_payto_uri);
   GNUNET_free (ws);
 }
 
@@ -476,81 +502,41 @@ withdraw_cleanup (void *cls,
  * @param index index number of the object to offer.
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 withdraw_traits (void *cls,
                  const void **ret,
                  const char *trait,
                  unsigned int index)
 {
   struct WithdrawState *ws = cls;
-  const struct TALER_TESTING_Command *reserve_cmd;
-  const struct TALER_ReservePrivateKeyP *reserve_priv;
-  const struct TALER_ReservePublicKeyP *reserve_pub;
-
-  /* We offer the reserve key where these coins were withdrawn
-   * from. */
-  reserve_cmd = TALER_TESTING_interpreter_lookup_command (ws->is,
-                                                          
ws->reserve_reference);
-
-  if (NULL == reserve_cmd)
-  {
-    GNUNET_break (0);
-    TALER_TESTING_interpreter_fail (ws->is);
-    return GNUNET_SYSERR;
-  }
-
-  if (GNUNET_OK !=
-      TALER_TESTING_get_trait_reserve_priv (reserve_cmd,
-                                            0,
-                                            &reserve_priv))
-  {
-    GNUNET_break (0);
-    TALER_TESTING_interpreter_fail (ws->is);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK !=
-      TALER_TESTING_get_trait_reserve_pub (reserve_cmd,
-                                           0,
-                                           &reserve_pub))
-  {
-    GNUNET_break (0);
-    TALER_TESTING_interpreter_fail (ws->is);
-    return GNUNET_SYSERR;
-  }
-  if (NULL == ws->exchange_url)
-    ws->exchange_url
-      = GNUNET_strdup (TALER_EXCHANGE_get_base_url (ws->is->exchange));
-  {
-    struct TALER_TESTING_Trait traits[] = {
-      /* history entry MUST be first due to response code logic below! */
-      TALER_TESTING_make_trait_reserve_history (0,
-                                                &ws->reserve_history),
-      TALER_TESTING_make_trait_coin_priv (0 /* only one coin */,
-                                          &ws->ps.coin_priv),
-      TALER_TESTING_make_trait_blinding_key (0 /* only one coin */,
-                                             &ws->ps.blinding_key),
-      TALER_TESTING_make_trait_denom_pub (0 /* only one coin */,
-                                          ws->pk),
-      TALER_TESTING_make_trait_denom_sig (0 /* only one coin */,
-                                          &ws->sig),
-      TALER_TESTING_make_trait_reserve_priv (0,
-                                             reserve_priv),
-      TALER_TESTING_make_trait_reserve_pub (0,
-                                            reserve_pub),
-      TALER_TESTING_make_trait_amount_obj (0,
-                                           &ws->amount),
-      TALER_TESTING_make_trait_url (TALER_TESTING_UT_EXCHANGE_BASE_URL,
-                                    ws->exchange_url),
-      TALER_TESTING_trait_end ()
-    };
-
-    return TALER_TESTING_get_trait ((ws->expected_response_code == MHD_HTTP_OK)
+  struct TALER_TESTING_Trait traits[] = {
+    /* history entry MUST be first due to response code logic below! */
+    TALER_TESTING_make_trait_reserve_history (&ws->reserve_history),
+    TALER_TESTING_make_trait_coin_priv (0 /* only one coin */,
+                                        &ws->ps.coin_priv),
+    TALER_TESTING_make_trait_blinding_key (0 /* only one coin */,
+                                           &ws->ps.blinding_key),
+    TALER_TESTING_make_trait_denom_pub (0 /* only one coin */,
+                                        ws->pk),
+    TALER_TESTING_make_trait_denom_sig (0 /* only one coin */,
+                                        &ws->sig),
+    TALER_TESTING_make_trait_reserve_priv (&ws->reserve_priv),
+    TALER_TESTING_make_trait_reserve_pub (&ws->reserve_pub),
+    TALER_TESTING_make_trait_amount (&ws->amount),
+    TALER_TESTING_make_trait_payment_target_uuid (&ws->kyc_uuid),
+    TALER_TESTING_make_trait_payto_uri (
+      (const char **) &ws->reserve_payto_uri),
+    TALER_TESTING_make_trait_exchange_url (
+      (const char **) &ws->exchange_url),
+    TALER_TESTING_trait_end ()
+  };
+
+  return TALER_TESTING_get_trait ((ws->expected_response_code == MHD_HTTP_OK)
                                     ? &traits[0] /* we have reserve history */
                                     : &traits[1],/* skip reserve history */
-                                    ret,
-                                    trait,
-                                    index);
-  }
+                                  ret,
+                                  trait,
+                                  index);
 }
 
 
diff --git a/src/testing/testing_api_helpers_bank.c 
b/src/testing/testing_api_helpers_bank.c
index 2876c247..d3c7a2d7 100644
--- a/src/testing/testing_api_helpers_bank.c
+++ b/src/testing/testing_api_helpers_bank.c
@@ -281,7 +281,7 @@ TALER_TESTING_run_bank (const char *config_filename,
 }
 
 
-int
+enum GNUNET_GenericReturnValue
 TALER_TESTING_prepare_nexus (const char *config_filename,
                              int reset_db,
                              const char *config_section,
@@ -401,7 +401,7 @@ TALER_TESTING_prepare_nexus (const char *config_filename,
 }
 
 
-int
+enum GNUNET_GenericReturnValue
 TALER_TESTING_prepare_bank (const char *config_filename,
                             int reset_db,
                             const char *config_section,
@@ -582,7 +582,7 @@ TALER_TESTING_prepare_bank (const char *config_filename,
 }
 
 
-int
+enum GNUNET_GenericReturnValue
 TALER_TESTING_prepare_fakebank (const char *config_filename,
                                 const char *config_section,
                                 struct TALER_TESTING_BankConfiguration *bc)
diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c
index 9e989ca3..f86c7765 100644
--- a/src/testing/testing_api_loop.c
+++ b/src/testing/testing_api_loop.c
@@ -66,21 +66,19 @@ TALER_TESTING_interpreter_lookup_command (struct 
TALER_TESTING_Interpreter *is,
 
     if (TALER_TESTING_cmd_is_batch (cmd))
     {
-#define BATCH_INDEX 1
-      struct TALER_TESTING_Command *batch;
+      struct TALER_TESTING_Command **batch;
       struct TALER_TESTING_Command *current;
       struct TALER_TESTING_Command *icmd;
       const struct TALER_TESTING_Command *match;
 
       current = TALER_TESTING_cmd_batch_get_current (cmd);
       GNUNET_assert (GNUNET_OK ==
-                     TALER_TESTING_get_trait_cmd (cmd,
-                                                  BATCH_INDEX,
-                                                  &batch));
+                     TALER_TESTING_get_trait_batch_cmds (cmd,
+                                                         &batch));
       /* We must do the loop forward, but we can find the last match */
       match = NULL;
       for (unsigned int j = 0;
-           NULL != (icmd = &batch[j])->label;
+           NULL != (icmd = &(*batch)[j])->label;
            j++)
       {
         if (current == icmd)
@@ -120,15 +118,6 @@ TALER_TESTING_interpreter_get_fakebank (struct 
TALER_TESTING_Interpreter *is)
 }
 
 
-/**
- * Run tests starting the "fakebank" first.  The "fakebank"
- * is a C minimalist version of the human-oriented Python bank,
- * which is also part of the Taler project.
- *
- * @param is pointer to the interpreter state
- * @param commands the list of commands to execute
- * @param bank_url the url the fakebank is supposed to run on
- */
 void
 TALER_TESTING_run_with_fakebank (struct TALER_TESTING_Interpreter *is,
                                  struct TALER_TESTING_Command *commands,
@@ -166,9 +155,6 @@ static void
 interpreter_run (void *cls);
 
 
-/**
- * Current command is done, run the next one.
- */
 void
 TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is)
 {
@@ -203,11 +189,6 @@ TALER_TESTING_interpreter_next (struct 
TALER_TESTING_Interpreter *is)
 }
 
 
-/**
- * Current command failed, clean up and fail the test case.
- *
- * @param is interpreter of the test
- */
 void
 TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *is)
 {
@@ -228,11 +209,6 @@ TALER_TESTING_interpreter_fail (struct 
TALER_TESTING_Interpreter *is)
 }
 
 
-/**
- * Create command array terminator.
- *
- * @return a end-command.
- */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_end (void)
 {
@@ -243,9 +219,6 @@ TALER_TESTING_cmd_end (void)
 }
 
 
-/**
- * Obtain current label.
- */
 const char *
 TALER_TESTING_interpreter_get_current_label (struct
                                              TALER_TESTING_Interpreter *is)
@@ -316,8 +289,9 @@ do_shutdown (void *cls)
   for (unsigned int j = 0;
        NULL != (cmd = &is->commands[j])->label;
        j++)
-    cmd->cleanup (cmd->cls,
-                  cmd);
+    if (NULL != cmd->cleanup)
+      cmd->cleanup (cmd->cls,
+                    cmd);
 
   if (NULL != is->exchange)
   {
@@ -393,17 +367,8 @@ maint_child_death (void *cls)
   enum GNUNET_OS_ProcessStatusType type;
   unsigned long code;
 
-  if (TALER_TESTING_cmd_is_batch (cmd))
-  {
-    struct TALER_TESTING_Command *batch_cmd;
-
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_TESTING_get_trait_cmd (cmd,
-                                                0,
-                                                &batch_cmd));
-    cmd = batch_cmd;
-  }
-
+  while (TALER_TESTING_cmd_is_batch (cmd))
+    cmd = TALER_TESTING_cmd_batch_get_current (cmd);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Got SIGCHLD for `%s'.\n",
               cmd->label);
@@ -416,7 +381,6 @@ maint_child_death (void *cls)
                                        sizeof (c)));
   if (GNUNET_OK !=
       TALER_TESTING_get_trait_process (cmd,
-                                       0,
                                        &processp))
   {
     GNUNET_break (0);
@@ -469,12 +433,6 @@ maint_child_death (void *cls)
 }
 
 
-/**
- * Wait until we receive SIGCHLD signal.
- * Then obtain the process trait of the current
- * command, wait on the the zombie and continue
- * with the next command.
- */
 void
 TALER_TESTING_wait_for_sigchld (struct TALER_TESTING_Interpreter *is)
 {
@@ -491,16 +449,6 @@ TALER_TESTING_wait_for_sigchld (struct 
TALER_TESTING_Interpreter *is)
 }
 
 
-/**
- * Run the testsuite.  Note, CMDs are copied into
- * the interpreter state because they are _usually_
- * defined into the "run" method that returns after
- * having scheduled the test interpreter.
- *
- * @param is the interpreter state
- * @param commands the list of command to execute
- * @param timeout how long to wait
- */
 void
 TALER_TESTING_run2 (struct TALER_TESTING_Interpreter *is,
                     struct TALER_TESTING_Command *commands,
@@ -530,15 +478,6 @@ TALER_TESTING_run2 (struct TALER_TESTING_Interpreter *is,
 }
 
 
-/**
- * Run the testsuite.  Note, CMDs are copied into
- * the interpreter state because they are _usually_
- * defined into the "run" method that returns after
- * having scheduled the test interpreter.
- *
- * @param is the interpreter state
- * @param commands the list of command to execute
- */
 void
 TALER_TESTING_run (struct TALER_TESTING_Interpreter *is,
                    struct TALER_TESTING_Command *commands)
@@ -597,16 +536,6 @@ sighandler_child_death (void)
 }
 
 
-/**
- * "Canonical" cert_cb used when we are connecting to the
- * Exchange.
- *
- * @param cls closure, typically, the "run" method containing
- *        all the commands to be run, and a closure for it.
- * @param hr HTTP response details
- * @param keys the exchange's keys.
- * @param compat protocol compatibility information.
- */
 void
 TALER_TESTING_cert_cb (void *cls,
                        const struct TALER_EXCHANGE_HttpResponse *hr,
@@ -875,25 +804,6 @@ load_urls (struct TALER_TESTING_Interpreter *is)
 }
 
 
-/**
- * Install signal handlers plus schedules the main wrapper
- * around the "run" method.
- *
- * @param main_cb the "run" method which contains all the
- *        commands.
- * @param main_cb_cls a closure for "run", typically NULL.
- * @param cfg configuration to use
- * @param exchanged exchange process handle: will be put in the
- *        state as some commands - e.g. revoke - need to send
- *        signal to it, for example to let it know to reload the
- *        key state.. if NULL, the interpreter will run without
- *        trying to connect to the exchange first.
- * @param exchange_connect #GNUNET_YES if the test should connect
- *        to the exchange, #GNUNET_NO otherwise
- * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise.
- *         non-GNUNET_OK codes are #GNUNET_SYSERR most of the
- *         times.
- */
 int
 TALER_TESTING_setup (TALER_TESTING_Main main_cb,
                      void *main_cb_cls,
diff --git a/src/testing/testing_api_trait_amount.c 
b/src/testing/testing_api_trait_amount.c
deleted file mode 100644
index 96698b49..00000000
--- a/src/testing/testing_api_trait_amount.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 3,
-  or (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_amount.c
- * @brief offer amounts as traits.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_AMOUNT "amount"
-
-/**
- * Obtain an amount from a @a cmd.
- *
- * @param cmd command to extract the amount from.
- * @param index which amount to pick if @a cmd has multiple
- *        on offer
- * @param[out] amount set to the amount.
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_amount_obj (const struct TALER_TESTING_Command *cmd,
-                                    unsigned int index,
-                                    const struct TALER_Amount **amount)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) amount,
-                      TALER_TESTING_TRAIT_AMOUNT,
-                      index);
-}
-
-
-/**
- * Offer amount.
- *
- * @param index which amount to offer, in case there are
- *        multiple available.
- * @param amount the amount to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_amount_obj (unsigned int index,
-                                     const struct TALER_Amount *amount)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_AMOUNT,
-    .ptr = (const void *) amount
-  };
-
-  return ret;
-}
-
-
-/* end of testing_api_trait_amount.c */
diff --git a/src/testing/testing_api_trait_blinding_key.c 
b/src/testing/testing_api_trait_blinding_key.c
deleted file mode 100644
index ae1889a1..00000000
--- a/src/testing/testing_api_trait_blinding_key.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_blinding_key.c
- * @brief offer blinding keys as traits.
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_BLINDING_KEY "blinding-key"
-
-
-/**
- * Obtain a blinding key from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which coin to pick if @a cmd has multiple on offer.
- * @param[out] blinding_key set to the offered blinding key.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_blinding_key
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_DenominationBlindingKeyP **blinding_key)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) blinding_key,
-                      TALER_TESTING_TRAIT_BLINDING_KEY,
-                      index);
-}
-
-
-/**
- * Offer blinding key.
- *
- * @param index index number to associate to the offered key.
- * @param blinding_key blinding key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_blinding_key
-  (unsigned int index,
-  const struct TALER_DenominationBlindingKeyP *blinding_key)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_BLINDING_KEY,
-    .ptr = (const void *) blinding_key
-  };
-
-  return ret;
-}
-
-
-/* end of testing_api_trait_blinding_key.c */
diff --git a/src/testing/testing_api_trait_cmd.c 
b/src/testing/testing_api_trait_cmd.c
deleted file mode 100644
index f2405471..00000000
--- a/src/testing/testing_api_trait_cmd.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file testing/testing_api_trait_cmd.c
- * @brief offers CMDs as traits.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_CMD "cmd"
-
-
-/**
- * Obtain a command from @a cmd.
- *
- * @param cmd command to extract the command from.
- * @param index always zero.  Commands offering this
- *        kind of traits do not need this index.  For
- *        example, a "batch" CMD returns always the
- *        CMD currently being executed.
- * @param[out] _cmd where to write the wire details.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_cmd (const struct TALER_TESTING_Command *cmd,
-                             unsigned int index,
-                             struct TALER_TESTING_Command **_cmd)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) _cmd,
-                      TALER_TESTING_TRAIT_CMD,
-                      index);
-}
-
-
-/**
- * Offer a command in a trait.
- *
- * @param index always zero.  Commands offering this
- *        kind of traits do not need this index.  For
- *        example, a "meta" CMD returns always the
- *        CMD currently being executed.
- * @param cmd wire details to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_cmd (unsigned int index,
-                              const struct TALER_TESTING_Command *cmd)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_CMD,
-    .ptr = (const struct TALER_TESTING_Command *) cmd
-  };
-  return ret;
-}
-
-
-/* end of testing_api_trait_cmd.c */
diff --git a/src/testing/testing_api_trait_coin_priv.c 
b/src/testing/testing_api_trait_coin_priv.c
deleted file mode 100644
index 61a770cf..00000000
--- a/src/testing/testing_api_trait_coin_priv.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file testing/testing_api_trait_coin_priv.c
- * @brief coin priv traits.
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_COIN_PRIVATE_KEY "coin-private-key"
-
-
-/**
- * Obtain a coin private key from a @a cmd.
- *
- * @param cmd command to extract trait from.
- * @param index index of the coin priv to obtain.
- * @param[out] coin_priv set to the private key of the coin.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_coin_priv
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_CoinSpendPrivateKeyP **coin_priv)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) coin_priv,
-                      TALER_TESTING_TRAIT_COIN_PRIVATE_KEY,
-                      index);
-}
-
-
-/**
- * Offer coin private key.
- *
- * @param index index number to associate with offered coin priv.
- * @param coin_priv coin private key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_coin_priv
-  (unsigned int index,
-  const struct TALER_CoinSpendPrivateKeyP *coin_priv)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_COIN_PRIVATE_KEY,
-    .ptr = (const void *) coin_priv
-  };
-
-  return ret;
-}
-
-
-/* end of testing_api_trait_coin_priv.c */
diff --git a/src/testing/testing_api_trait_contract.c 
b/src/testing/testing_api_trait_contract.c
deleted file mode 100644
index 1e88cb86..00000000
--- a/src/testing/testing_api_trait_contract.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018-2020 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_contract.c
- * @brief offers contract term trait.
- * @author Marcello Stanisci
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_testing_lib.h"
-
-
-/**
- * Contains a contract terms object as a json_t.
- */
-#define TALER_TESTING_TRAIT_CONTRACT_TERMS "contract-terms"
-
-
-/**
- * Obtain contract terms from @a cmd.
- *
- * @param cmd command to extract the contract terms from.
- * @param index contract terms index number.
- * @param[out] contract_terms where to write the contract terms.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_contract_terms (const struct TALER_TESTING_Command 
*cmd,
-                                        unsigned int index,
-                                        const json_t **contract_terms)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) contract_terms,
-                      TALER_TESTING_TRAIT_CONTRACT_TERMS,
-                      index);
-}
-
-
-/**
- * Offer contract terms.
- *
- * @param index contract terms index number.
- * @param contract_terms contract terms to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_contract_terms (unsigned int index,
-                                         const json_t *contract_terms)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_CONTRACT_TERMS,
-    .ptr = (const void *) contract_terms
-  };
-  return ret;
-}
diff --git a/src/testing/testing_api_trait_denom_pub.c 
b/src/testing/testing_api_trait_denom_pub.c
deleted file mode 100644
index f866588d..00000000
--- a/src/testing/testing_api_trait_denom_pub.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_denom_pub.c
- * @brief denom pub traits.
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_DENOM_PUB "denomination-public-key"
-
-
-/**
- * Obtain a denomination public key from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index index number of the denom to obtain.
- * @param[out] denom_pub set to the offered denom pub.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_denom_pub (const struct TALER_TESTING_Command *cmd,
-                                   unsigned int index,
-                                   const struct
-                                   TALER_EXCHANGE_DenomPublicKey **denom_pub)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) denom_pub,
-                      TALER_TESTING_TRAIT_DENOM_PUB,
-                      index);
-}
-
-
-/**
- * Make a trait for a denomination public key.
- *
- * @param index index number to associate to the offered denom pub.
- * @param denom_pub denom pub to offer with this trait.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_denom_pub (unsigned int index,
-                                    const struct
-                                    TALER_EXCHANGE_DenomPublicKey *denom_pub)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_DENOM_PUB,
-    .ptr = (const void *) denom_pub
-  };
-
-  return ret;
-}
-
-
-/* end of testing_api_trait_denom_pub.c */
diff --git a/src/testing/testing_api_trait_denom_sig.c 
b/src/testing/testing_api_trait_denom_sig.c
deleted file mode 100644
index 07e89440..00000000
--- a/src/testing/testing_api_trait_denom_sig.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 3,
-  or (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file testing/testing_api_trait_denom_sig.c
- * @brief offer denomination signatures as traits
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_DENOM_SIG "denomination-signature"
-
-
-/**
- * Obtain a denomination signature from a @a cmd.
- *
- * @param cmd command to extract the denom sig from.
- * @param index index number associated with the denom sig.
- * @param[out] denom_sig set to the offered signature.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_denom_sig
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_DenominationSignature **denom_sig)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) denom_sig,
-                      TALER_TESTING_TRAIT_DENOM_SIG,
-                      index);
-}
-
-
-/**
- * Offer denom sig.
- *
- * @param index index number to associate to the signature on
- *        offer.
- * @param denom_sig the denom sig on offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_denom_sig
-  (unsigned int index,
-  const struct TALER_DenominationSignature *denom_sig)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_DENOM_SIG,
-    .ptr = (const void *) denom_sig
-  };
-
-  return ret;
-}
-
-
-/* end of testing_api_trait_denom_sig.c */
diff --git a/src/testing/testing_api_trait_exchange_pub.c 
b/src/testing/testing_api_trait_exchange_pub.c
deleted file mode 100644
index 8c702726..00000000
--- a/src/testing/testing_api_trait_exchange_pub.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_exchange_pub.c
- * @brief exchange pub traits.
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_EXCHANGE_PUB "exchange-public-key"
-
-
-/**
- * Obtain a exchange public key from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index index number of the exchange to obtain.
- * @param[out] exchange_pub set to the offered exchange pub.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_exchange_pub
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_ExchangePublicKeyP **exchange_pub)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) exchange_pub,
-                      TALER_TESTING_TRAIT_EXCHANGE_PUB,
-                      index);
-}
-
-
-/**
- * Make a trait for a exchange public key.
- *
- * @param index index number to associate to the offered exchange pub.
- * @param exchange_pub exchange pub to offer with this trait.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_exchange_pub
-  (unsigned int index,
-  const struct TALER_ExchangePublicKeyP *exchange_pub)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_EXCHANGE_PUB,
-    .ptr = (const void *) exchange_pub
-  };
-
-  return ret;
-}
-
-
-/* end of testing_api_trait_exchange_pub.c */
diff --git a/src/testing/testing_api_trait_exchange_sig.c 
b/src/testing/testing_api_trait_exchange_sig.c
deleted file mode 100644
index 349454ae..00000000
--- a/src/testing/testing_api_trait_exchange_sig.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_exchange_sig.c
- * @brief exchange pub traits.
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_EXCHANGE_SIG "exchange-online-signature"
-
-
-/**
- * Obtain a exchange signature (online sig) from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index index number of the exchange to obtain.
- * @param[out] exchange_sig set to the offered exchange signature.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_exchange_sig
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_ExchangeSignatureP **exchange_sig)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) exchange_sig,
-                      TALER_TESTING_TRAIT_EXCHANGE_SIG,
-                      index);
-}
-
-
-/**
- * Make a trait for a exchange signature.
- *
- * @param index index number to associate to the offered exchange pub.
- * @param exchange_sig exchange signature to offer with this trait.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_exchange_sig
-  (unsigned int index,
-  const struct TALER_ExchangeSignatureP *exchange_sig)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_EXCHANGE_SIG,
-    .ptr = (const void *) exchange_sig
-  };
-
-  return ret;
-}
-
-
-/* end of testing_api_trait_exchange_sig.c */
diff --git a/src/testing/testing_api_trait_fresh_coin.c 
b/src/testing/testing_api_trait_fresh_coin.c
deleted file mode 100644
index e5f1c682..00000000
--- a/src/testing/testing_api_trait_fresh_coin.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_fresh_coin.c
- * @brief traits to offer fresh conins (after "melt" operations)
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_FRESH_COINS "fresh-coins"
-
-/**
- * Get a array of fresh coins.
- *
- * @param cmd command to extract the fresh coin from.
- * @param index which array to pick if @a cmd has multiple
- *        on offer.
- * @param[out] fresh_coins will point to the offered array.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_fresh_coins
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_TESTING_FreshCoinData **fresh_coins)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) fresh_coins,
-                      TALER_TESTING_TRAIT_FRESH_COINS,
-                      index);
-}
-
-
-/**
- * Offer a _array_ of fresh coins.
- *
- * @param index which array of fresh coins to offer,
- *        if there are multiple on offer.  Typically passed as
- *        zero.
- * @param fresh_coins the array of fresh coins to offer
- * @return the trait,
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_fresh_coins
-  (unsigned int index,
-  const struct TALER_TESTING_FreshCoinData *fresh_coins)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_FRESH_COINS,
-    .ptr = (const void *) fresh_coins
-  };
-  return ret;
-}
-
-
-/* end of testing_api_trait_fresh_coin.c */
diff --git a/src/testing/testing_api_trait_json.c 
b/src/testing/testing_api_trait_json.c
deleted file mode 100644
index e12f1e9a..00000000
--- a/src/testing/testing_api_trait_json.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file testing/testing_api_trait_json.c
- * @brief offers JSON traits.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_WIRE_DETAILS "wire-details"
-#define TALER_TESTING_TRAIT_EXCHANGE_KEYS "exchange-keys"
-#define TALER_TESTING_TRAIT_JSON "json"
-
-/**
- * Obtain serialized exchange keys from @a cmd.
- *
- * @param cmd command to extract the keys from.
- * @param index index number associate with the keys on offer.
- * @param[out] keys where to write the serialized keys.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_exchange_keys
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const json_t **keys)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) keys,
-                      TALER_TESTING_TRAIT_EXCHANGE_KEYS,
-                      index);
-}
-
-
-/**
- * Offer serialized keys in a trait.
- *
- * @param index index number associate with the serial keys
- *        on offer.
- * @param keys serialized keys to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_exchange_keys
-  (unsigned int index,
-  const json_t *keys)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_EXCHANGE_KEYS,
-    .ptr = (const json_t *) keys
-  };
-  return ret;
-}
-
-
-/**
- * Obtain wire details from @a cmd.
- *
- * @param cmd command to extract the wire details from.
- * @param index index number associate with the wire details
- *        on offer; usually zero, as one command sticks to
- *        one bank account.
- * @param[out] wire_details where to write the wire details.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_wire_details
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const json_t **wire_details)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) wire_details,
-                      TALER_TESTING_TRAIT_WIRE_DETAILS,
-                      index);
-}
-
-
-/**
- * Offer wire details in a trait.
- *
- * @param index index number associate with the wire details
- *        on offer; usually zero, as one command sticks to
- *        one bank account.
- * @param wire_details wire details to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_wire_details
-  (unsigned int index,
-  const json_t *wire_details)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_WIRE_DETAILS,
-    .ptr = (const json_t *) wire_details
-  };
-  return ret;
-}
-
-
-/**
- * Obtain json from @a cmd.
- *
- * @param cmd command to extract the json from.
- * @param index index number associate with the json on offer.
- * @param[out] json where to write the json.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_json (const struct TALER_TESTING_Command *cmd,
-                              unsigned int index,
-                              const json_t **json)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) json,
-                      TALER_TESTING_TRAIT_JSON,
-                      index);
-}
-
-
-/**
- * Offer json in a trait.
- *
- * @param index index number associate with the json
- *        on offer.
- * @param json json to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_json (unsigned int index,
-                               const json_t *json)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_JSON,
-    .ptr = (const json_t *) json
-  };
-  return ret;
-}
-
-
-/* end of testing_api_trait_json.c */
diff --git a/src/testing/testing_api_trait_merchant_key.c 
b/src/testing/testing_api_trait_merchant_key.c
deleted file mode 100644
index 41b6b888..00000000
--- a/src/testing/testing_api_trait_merchant_key.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_merchant_key.c
- * @brief traits to offer peer's (private) keys
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_MERCHANT_PRIV "merchant-priv"
-#define TALER_TESTING_TRAIT_MERCHANT_PUB "merchant-pub-pub"
-
-/**
- * Obtain a private key from a "peer".  Used e.g. to obtain
- * a merchant's priv to sign a /track request.
- *
- * @param cmd command that is offering the key.
- * @param index (typically zero) which key to return if there
- *        are multiple on offer.
- * @param[out] priv set to the key coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_merchant_priv
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_MerchantPrivateKeyP **priv)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) priv,
-                      TALER_TESTING_TRAIT_MERCHANT_PRIV,
-                      index);
-}
-
-
-/**
- * Offer private key, typically done when CMD_1 needs it to
- * sign a request.
- *
- * @param index (typically zero) which key to return if there are
- *        multiple on offer.
- * @param priv which object should be offered.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_merchant_priv (unsigned int index,
-                                        const struct
-                                        TALER_MerchantPrivateKeyP *priv)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_MERCHANT_PRIV,
-    .ptr = (const void *) priv
-  };
-
-  return ret;
-}
-
-
-/**
- * Obtain a public key from a "peer".  Used e.g. to obtain
- * a merchant's public key to use backend's API.
- *
- * @param cmd command offering the key.
- * @param index (typically zero) which key to return if there
- *        are multiple on offer.
- * @param[out] pub set to the key coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_merchant_pub
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_MerchantPublicKeyP **pub)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) pub,
-                      TALER_TESTING_TRAIT_MERCHANT_PUB,
-                      index);
-}
-
-
-/**
- * Offer public key.
- *
- * @param index (typically zero) which key to return if there
- *        are multiple on offer.  NOTE: if one key is offered, it
- *        is mandatory to set this as zero.
- * @param pub which object should be returned.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_merchant_pub (unsigned int index,
-                                       const struct
-                                       TALER_MerchantPublicKeyP *pub)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_MERCHANT_PUB,
-    .ptr = (const void *) pub
-  };
-
-  return ret;
-}
-
-
-/* end of testing_api_trait_merchant_key.c */
diff --git a/src/testing/testing_api_trait_number.c 
b/src/testing/testing_api_trait_number.c
deleted file mode 100644
index ed25593e..00000000
--- a/src/testing/testing_api_trait_number.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018-2020 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_number.c
- * @brief traits to offer numbers
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_UINT "uint"
-#define TALER_TESTING_TRAIT_UINT32 "uint-32"
-#define TALER_TESTING_TRAIT_UINT64 "uint-64"
-#define TALER_TESTING_TRAIT_INT64 "int-64"
-#define TALER_TESTING_TRAIT_BANK_ROW "bank-transaction-row"
-
-
-/**
- * Obtain a number from @a cmd.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_uint (const struct TALER_TESTING_Command *cmd,
-                              unsigned int index,
-                              const unsigned int **n)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) n,
-                      TALER_TESTING_TRAIT_UINT,
-                      index);
-}
-
-
-/**
- * Offer a number.
- *
- * @param index the number's index number.
- * @param n the number to offer.
- * @return #GNUNET_OK on success.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uint (unsigned int index,
-                               const unsigned int *n)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_UINT,
-    .ptr = (const void *) n
-  };
-  return ret;
-}
-
-
-/**
- * Obtain a "number" value from @a cmd, 32-bit version.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_uint32 (const struct TALER_TESTING_Command *cmd,
-                                unsigned int index,
-                                const uint32_t **n)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) n,
-                      TALER_TESTING_TRAIT_UINT32,
-                      index);
-}
-
-
-/**
- * Offer number trait, 32-bit version.
- *
- * @param index the number's index number.
- * @param n number to offer.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uint32 (unsigned int index,
-                                 const uint32_t *n)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_UINT32,
-    .ptr = (const void *) n
-  };
-  return ret;
-}
-
-
-/**
- * Obtain a "number" value from @a cmd, 64-bit version.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_uint64 (const struct TALER_TESTING_Command *cmd,
-                                unsigned int index,
-                                const uint64_t **n)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) n,
-                      TALER_TESTING_TRAIT_UINT64,
-                      index);
-}
-
-
-/**
- * Offer number trait, 64-bit version.
- *
- * @param index the number's index number.
- * @param n number to offer.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uint64 (unsigned int index,
-                                 const uint64_t *n)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_UINT64,
-    .ptr = (const void *) n
-  };
-  return ret;
-}
-
-
-/**
- * Obtain a "number" value from @a cmd, 64-bit signed version.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param[out] n set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_int64 (const struct TALER_TESTING_Command *cmd,
-                               unsigned int index,
-                               const int64_t **n)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) n,
-                      TALER_TESTING_TRAIT_INT64,
-                      index);
-}
-
-
-/**
- * Offer number trait, 64-bit signed version.
- *
- * @param index the number's index number.
- * @param n number to offer.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_int64 (unsigned int index,
-                                const int64_t *n)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_INT64,
-    .ptr = (const void *) n
-  };
-  return ret;
-}
-
-
-/**
- * Obtain a bank transaction row value from @a cmd.
- *
- * @param cmd command to extract the number from.
- * @param[out] row set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_bank_row (const struct TALER_TESTING_Command *cmd,
-                                  const uint64_t **row)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) row,
-                      TALER_TESTING_TRAIT_BANK_ROW,
-                      0);
-}
-
-
-/**
- * Offer bank transaction row trait.
- *
- * @param row number to offer.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_bank_row (const uint64_t *row)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = 0,
-    .trait_name = TALER_TESTING_TRAIT_BANK_ROW,
-    .ptr = (const void *) row
-  };
-  return ret;
-}
-
-
-/* end of testing_api_trait_number.c */
diff --git a/src/testing/testing_api_trait_process.c 
b/src/testing/testing_api_trait_process.c
deleted file mode 100644
index 3d2af31f..00000000
--- a/src/testing/testing_api_trait_process.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 3,
-  or (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty
-  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  See the GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file testing/testing_api_trait_process.c
- * @brief trait offering process handles.
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_PROCESS "process"
-
-
-/**
- * Obtain location where a command stores a pointer to a process.
- *
- * @param cmd command to extract trait from.
- * @param index which process to pick if @a cmd
- *        has multiple on offer.
- * @param[out] processp set to the address of the pointer to the
- *        process.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_process
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  struct GNUNET_OS_Process ***processp)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) processp,
-                      TALER_TESTING_TRAIT_PROCESS,
-                      index);
-}
-
-
-/**
- * Offer location where a command stores a pointer to a process.
- *
- * @param index offered location index number, in case there are
- *        multiple on offer.
- * @param processp process location to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_process
-  (unsigned int index,
-  struct GNUNET_OS_Process **processp)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_PROCESS,
-    .ptr = (const void *) processp
-  };
-
-  return ret;
-}
-
-
-/* end of testing_api_trait_process.c */
diff --git a/src/testing/testing_api_trait_reserve_history.c 
b/src/testing/testing_api_trait_reserve_history.c
deleted file mode 100644
index b458dbd6..00000000
--- a/src/testing/testing_api_trait_reserve_history.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018-2020 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 3, or
-  (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_reserve_history.c
- * @brief implements reserve hostry trait
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_RESERVE_HISTORY \
-  "reserve-history-entry"
-
-
-/**
- * Obtain a reserve history entry from a @a cmd.
- *
- * @param cmd command to extract the reserve history from.
- * @param index reserve history's index number.
- * @param[out] rhp set to the reserve history.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_reserve_history (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_EXCHANGE_ReserveHistory **rhp)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) rhp,
-                      TALER_TESTING_TRAIT_RESERVE_HISTORY,
-                      index);
-}
-
-
-/**
- * Offer a reserve history entry.
- *
- * @param index reserve pubs's index number.
- * @param rh reserve history entry to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_reserve_history (
-  unsigned int index,
-  const struct TALER_EXCHANGE_ReserveHistory *rh)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_RESERVE_HISTORY,
-    .ptr = (const void *) rh
-  };
-  return ret;
-}
-
-
-/* end of testing_api_trait_reserve_history.c */
diff --git a/src/testing/testing_api_trait_reserve_priv.c 
b/src/testing/testing_api_trait_reserve_priv.c
deleted file mode 100644
index f4a4ef50..00000000
--- a/src/testing/testing_api_trait_reserve_priv.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 3, or
-  (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_reserve_priv.c
- * @brief implements reserve private key trait
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_RESERVE_PRIVATE_KEY \
-  "reserve-private-key"
-
-/**
- * Obtain a reserve private key from a @a cmd.
- *
- * @param cmd command to extract the reserve priv from.
- * @param index reserve priv's index number.
- * @param[out] reserve_priv set to the reserve priv.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_reserve_priv
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_ReservePrivateKeyP **reserve_priv)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) reserve_priv,
-                      TALER_TESTING_TRAIT_RESERVE_PRIVATE_KEY,
-                      index);
-}
-
-
-/**
- * Offer a reserve private key.
- *
- * @param index reserve priv's index number.
- * @param reserve_priv reserve private key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_reserve_priv
-  (unsigned int index,
-  const struct TALER_ReservePrivateKeyP *reserve_priv)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_RESERVE_PRIVATE_KEY,
-    .ptr = (const void *) reserve_priv
-  };
-  return ret;
-}
-
-
-/* end of testing_api_trait_reserve_priv.c */
diff --git a/src/testing/testing_api_trait_reserve_pub.c 
b/src/testing/testing_api_trait_reserve_pub.c
deleted file mode 100644
index 743a10e9..00000000
--- a/src/testing/testing_api_trait_reserve_pub.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018-2020 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 3, or
-  (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_reserve_pub.c
- * @brief implements reserve public key trait
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY \
-  "reserve-public-key"
-
-/**
- * Obtain a reserve public key from a @a cmd.
- *
- * @param cmd command to extract the reserve pub from.
- * @param index reserve pub's index number.
- * @param[out] reserve_pub set to the reserve pub.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_reserve_pub
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_ReservePublicKeyP **reserve_pub)
-{
-  if (NULL == cmd->traits)
-    return GNUNET_SYSERR;
-  return cmd->traits (cmd->cls,
-                      (const void **) reserve_pub,
-                      TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY,
-                      index);
-}
-
-
-/**
- * Offer a reserve public key.
- *
- * @param index reserve pub's index number.
- * @param reserve_pub reserve public key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_reserve_pub
-  (unsigned int index,
-  const struct TALER_ReservePublicKeyP *reserve_pub)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_RESERVE_PUBLIC_KEY,
-    .ptr = (const void *) reserve_pub
-  };
-  return ret;
-}
-
-
-/* end of testing_api_trait_reserve_pub.c */
diff --git a/src/testing/testing_api_trait_string.c 
b/src/testing/testing_api_trait_string.c
deleted file mode 100644
index b102265e..00000000
--- a/src/testing/testing_api_trait_string.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018-2020 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_string.c
- * @brief offers strings traits.
- * @author Marcello Stanisci
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-/**
- * Some string. Avoid, use something more precise!
- */
-#define TALER_TESTING_TRAIT_STRING "string"
-
-/**
- * An HTTP-URL.
- */
-#define TALER_TESTING_TRAIT_URL "url"
-
-/**
- * A PAYTO-URL.
- */
-#define TALER_TESTING_TRAIT_PAYTO "payto"
-
-/**
- * String identifying an order.
- */
-#define TALER_TESTING_TRAIT_ORDER_ID "order-id"
-
-
-/**
- * Obtain a string from @a cmd.
- *
- * @param cmd command to extract the subject from.
- * @param index index number associated with the transfer
- *        subject to offer.
- * @param[out] s where to write the offered
- *        string
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_string (const struct TALER_TESTING_Command *cmd,
-                                unsigned int index,
-                                const char **s)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) s,
-                      TALER_TESTING_TRAIT_STRING,
-                      index);
-}
-
-
-/**
- * Offer string.
- *
- * @param index index number associated with the transfer
- *        subject being offered.
- * @param s transfer subject to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_string (unsigned int index,
-                                 const char *s)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_STRING,
-    .ptr = (const void *) s
-  };
-  return ret;
-}
-
-
-/**
- * Obtain a HTTP url from @a cmd.
- *
- * @param cmd command to extract the url from.
- * @param index which url is to be picked, in case
- *        multiple are offered.
- * @param[out] url where to write the url.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_url (const struct TALER_TESTING_Command *cmd,
-                             unsigned int index,
-                             const char **url)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) url,
-                      TALER_TESTING_TRAIT_URL,
-                      index);
-}
-
-
-/**
- * Offer HTTP url in a trait.
- *
- * @param index which url is to be picked,
- *        in case multiple are offered.
- * @param url the url to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_url (unsigned int index,
-                              const char *url)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_URL,
-    .ptr = (const void *) url
-  };
-
-  GNUNET_assert ( (NULL == url) ||
-                  (0 != strncasecmp (url,
-                                     "payto://",
-                                     strlen ("payto://"))) );
-  return ret;
-}
-
-
-/**
- * Obtain a order id from @a cmd.
- *
- * @param cmd command to extract the order id from.
- * @param index which order id is to be picked, in case
- *        multiple are offered.
- * @param[out] order_id where to write the order id.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_order_id (const struct TALER_TESTING_Command *cmd,
-                                  unsigned int index,
-                                  const char **order_id)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) order_id,
-                      TALER_TESTING_TRAIT_ORDER_ID,
-                      index);
-}
-
-
-/**
- * Offer order id in a trait.
- *
- * @param index which order id is to be offered,
- *        in case multiple are offered.
- * @param order_id the order id to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_order_id (unsigned int index,
-                                   const char *order_id)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_ORDER_ID,
-    .ptr = (const void *) order_id
-  };
-  return ret;
-}
-
-
-/**
- * Obtain a PAYTO-url from @a cmd.
- *
- * @param cmd command to extract the url from.
- * @param pt which url is to be picked, in case
- *        multiple are offered.
- * @param[out] url where to write the url.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_payto (const struct TALER_TESTING_Command *cmd,
-                               enum TALER_TESTING_PaytoType pt,
-                               const char **url)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) url,
-                      TALER_TESTING_TRAIT_PAYTO,
-                      (unsigned int) pt);
-}
-
-
-/**
- * Offer a "payto" URL reference.
- *
- * @param pt which reference is to be offered,
- *        in case multiple are offered.
- * @param payto_uri the payto URI
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_payto (enum TALER_TESTING_PaytoType pt,
-                                const char *payto_uri)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = (unsigned int) pt,
-    .trait_name = TALER_TESTING_TRAIT_PAYTO,
-    .ptr = (const void *) payto_uri,
-  };
-
-  GNUNET_assert (0 == strncasecmp (payto_uri,
-                                   "payto://",
-                                   strlen ("payto://")));
-  return ret;
-}
-
-
-/* end of testing_api_trait_string.c */
diff --git a/src/testing/testing_api_trait_time.c 
b/src/testing/testing_api_trait_time.c
deleted file mode 100644
index 207246be..00000000
--- a/src/testing/testing_api_trait_time.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file testing/testing_api_trait_time.c
- * @brief traits to offer time stamps.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_TIME_ABS "time-abs"
-#define TALER_TESTING_TRAIT_TIME_REL "time-rel"
-
-/**
- * Obtain a absolute time from @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which time stamp to pick if
- *        @a cmd has multiple on offer.
- * @param[out] time set to the wanted WTID.
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_absolute_time
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct GNUNET_TIME_Absolute **time)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) time,
-                      TALER_TESTING_TRAIT_TIME_ABS,
-                      index);
-}
-
-
-/**
- * Offer a absolute time.
- *
- * @param index associate the object with this index
- * @param time which object should be returned
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_absolute_time
-  (unsigned int index,
-  const struct GNUNET_TIME_Absolute *time)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_TIME_ABS,
-    .ptr = (const void *) time
-  };
-  return ret;
-}
-
-
-/**
- * Obtain a relative time from @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which time to pick if
- *        @a cmd has multiple on offer.
- * @param[out] time set to the wanted WTID.
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_relative_time (
-  const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct GNUNET_TIME_Relative **time)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) time,
-                      TALER_TESTING_TRAIT_TIME_REL,
-                      index);
-}
-
-
-/**
- * Offer a relative time.
- *
- * @param index associate the object with this index
- * @param time which object should be returned
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_relative_time (
-  unsigned int index,
-  const struct GNUNET_TIME_Relative *time)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_TIME_REL,
-    .ptr = (const void *) time
-  };
-  return ret;
-}
-
-
-/* end of testing_api_trait_time.c */
diff --git a/src/testing/testing_api_trait_uuid.c 
b/src/testing/testing_api_trait_uuid.c
deleted file mode 100644
index 4d5003ec..00000000
--- a/src/testing/testing_api_trait_uuid.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2020 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 3, or
-  (at your option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-/**
- * @file testing/testing_api_trait_uuid.c
- * @brief offer any trait that is passed over as a uuid.
- * @author Jonathan Buchanan
- */
-#include "platform.h"
-#include "taler_signatures.h"
-#include "taler_exchange_service.h"
-#include "taler_testing_lib.h"
-
-
-#define TALER_TESTING_TRAIT_UUID "uuid"
-#define TALER_TESTING_TRAIT_CLAIM_TOKEN "claim_token"
-
-
-/**
- * Obtain a uuid from @a cmd.
- *
- * @param cmd command to extract the uuid from.
- * @param index which amount to pick if @a cmd has multiple
- *        on offer
- * @param[out] uuid where to write the uuid.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_uuid (const struct TALER_TESTING_Command *cmd,
-                              unsigned int index,
-                              struct GNUNET_Uuid **uuid)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) uuid,
-                      TALER_TESTING_TRAIT_UUID,
-                      index);
-}
-
-
-/**
- * Offer a uuid in a trait.
- *
- * @param index which uuid to offer, in case there are
- *        multiple available.
- * @param uuid the uuid to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uuid (unsigned int index,
-                               const struct GNUNET_Uuid *uuid)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_UUID,
-    .ptr = (const void *) uuid
-  };
-  return ret;
-}
-
-
-/**
- * Obtain a claim token from @a cmd.
- *
- * @param cmd command to extract the token from.
- * @param index which amount to pick if @a cmd has multiple
- *        on offer
- * @param[out] ct where to write the token.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_claim_token (const struct TALER_TESTING_Command *cmd,
-                                     unsigned int index,
-                                     const struct TALER_ClaimTokenP **ct)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) ct,
-                      TALER_TESTING_TRAIT_CLAIM_TOKEN,
-                      index);
-}
-
-
-/**
- * Offer a claim token in a trait.
- *
- * @param index which token to offer, in case there are
- *        multiple available.
- * @param ct the token to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_claim_token (unsigned int index,
-                                      const struct TALER_ClaimTokenP *ct)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_CLAIM_TOKEN,
-    .ptr = (const void *) ct
-  };
-  return ret;
-}
diff --git a/src/testing/testing_api_trait_wtid.c 
b/src/testing/testing_api_trait_wtid.c
deleted file mode 100644
index 5c7e7060..00000000
--- a/src/testing/testing_api_trait_wtid.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
-
-  TALER is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 3, or (at your
-  option) any later version.
-
-  TALER is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public
-  License along with TALER; see the file COPYING.  If not, see
-  <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file testing/testing_api_trait_number.c
- * @brief traits to offer numbers
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_WTID "wtid"
-
-/**
- * Obtain a WTID value from @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which WTID to pick if @a cmd has multiple on
- *        offer
- * @param[out] wtid set to the wanted WTID.
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_wtid
-  (const struct TALER_TESTING_Command *cmd,
-  unsigned int index,
-  const struct TALER_WireTransferIdentifierRawP **wtid)
-{
-  return cmd->traits (cmd->cls,
-                      (const void **) wtid,
-                      TALER_TESTING_TRAIT_WTID,
-                      index);
-}
-
-
-/**
- * Offer a WTID.
- *
- * @param index associate the object with this index
- * @param wtid which object should be returned
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_wtid
-  (unsigned int index,
-  const struct TALER_WireTransferIdentifierRawP *wtid)
-{
-  struct TALER_TESTING_Trait ret = {
-    .index = index,
-    .trait_name = TALER_TESTING_TRAIT_WTID,
-    .ptr = (const void *) wtid
-  };
-  return ret;
-}
-
-
-/* end of testing_api_trait_number.c */
diff --git a/src/testing/testing_api_traits.c b/src/testing/testing_api_traits.c
index 6d623af7..db94e81a 100644
--- a/src/testing/testing_api_traits.c
+++ b/src/testing/testing_api_traits.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2018 Taler Systems SA
+  Copyright (C) 2018, 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as
@@ -29,6 +29,11 @@
 #include "taler_testing_lib.h"
 
 
+TALER_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_IMPL_SIMPLE_TRAIT)
+
+TALER_TESTING_INDEXED_TRAITS (TALER_TESTING_MAKE_IMPL_INDEXED_TRAIT)
+
+
 /**
  * End a trait array.  Usually, commands offer several traits,
  * and put them in arrays.
@@ -46,16 +51,7 @@ TALER_TESTING_trait_end ()
 }
 
 
-/**
- * Pick the chosen trait from the traits array.
- *
- * @param traits the traits array.
- * @param ret where to store the result.
- * @param trait type of the trait to extract.
- * @param index index number of the object to extract.
- * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
- */
-int
+enum GNUNET_GenericReturnValue
 TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
                          const void **ret,
                          const char *trait,
@@ -63,7 +59,8 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait 
*traits,
 {
   for (unsigned int i = 0; NULL != traits[i].trait_name; i++)
   {
-    if ( (0 == strcmp (trait, traits[i].trait_name)) &&
+    if ( (0 == strcmp (trait,
+                       traits[i].trait_name)) &&
          (index == traits[i].index) )
     {
       *ret = (void *) traits[i].ptr;
@@ -72,8 +69,8 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait 
*traits,
   }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Trait %s/%u not found.\n",
-              trait, index);
-
+              trait,
+              index);
   return GNUNET_SYSERR;
 }
 
diff --git a/src/util/.gitignore b/src/util/.gitignore
index a3fe3520..946924dc 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -1,8 +1,8 @@
 taler-config
 test_payto
+taler-crypto-worker
 taler-exchange-secmod-rsa
 taler-exchange-secmod-eddsa
-taler-crypto-worker
 test_helper_rsa
 test_helper_rsa_home/
 test_helper_eddsa
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 29f1dc25..c9f2b997 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -22,8 +22,7 @@ EXTRA_DIST = \
 
 bin_PROGRAMS = \
   taler-exchange-secmod-eddsa \
-  taler-exchange-secmod-rsa \
-  taler-crypto-worker
+  taler-exchange-secmod-rsa
 
 bin_SCRIPTS = \
   taler-config
@@ -39,17 +38,6 @@ taler-config: taler-config.in
 CLEANFILES = \
   taler-config
 
-taler_crypto_worker_SOURCES = \
-  taler-crypto-worker.c
-taler_crypto_worker_LDADD = \
-  libtalerutil.la \
-  -lgnunetutil \
-  -lgnunetjson \
-  -ljansson \
-  -lpthread \
-  $(LIBGCRYPT_LIBS) \
-  $(XLIB)
-
 taler_exchange_secmod_rsa_SOURCES = \
   taler-exchange-secmod-rsa.c taler-exchange-secmod-rsa.h \
   secmod_common.c secmod_common.h
@@ -70,6 +58,18 @@ taler_exchange_secmod_eddsa_LDADD = \
   $(LIBGCRYPT_LIBS) \
   $(XLIB)
 
+taler_crypto_worker_SOURCES = \
+  taler-crypto-worker.c
+taler_crypto_worker_LDADD = \
+  libtalerutil.la \
+  -lgnunetutil \
+  -lgnunetjson \
+  -ljansson \
+  -lpthread \
+  $(LIBGCRYPT_LIBS) \
+  $(XLIB)
+
+
 lib_LTLIBRARIES = \
   libtalerutil.la
 
@@ -81,6 +81,9 @@ libtalerutil_la_SOURCES = \
   crypto_helper_denom.c \
   crypto_helper_esign.c \
   crypto_wire.c \
+  denom.c \
+  exchange_signatures.c \
+  extension_age_restriction.c \
   getopt.c \
   lang.c \
   iban.c \
diff --git a/src/util/auditor_signatures.c b/src/util/auditor_signatures.c
index b41ce66a..6ca1b046 100644
--- a/src/util/auditor_signatures.c
+++ b/src/util/auditor_signatures.c
@@ -26,7 +26,7 @@
 void
 TALER_auditor_denom_validity_sign (
   const char *auditor_url,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterPublicKeyP *master_pub,
   struct GNUNET_TIME_Absolute stamp_start,
   struct GNUNET_TIME_Absolute stamp_expire_withdraw,
@@ -73,7 +73,7 @@ TALER_auditor_denom_validity_sign (
 enum GNUNET_GenericReturnValue
 TALER_auditor_denom_validity_verify (
   const char *auditor_url,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterPublicKeyP *master_pub,
   struct GNUNET_TIME_Absolute stamp_start,
   struct GNUNET_TIME_Absolute stamp_expire_withdraw,
diff --git a/src/util/crypto.c b/src/util/crypto.c
index a7ea4f4c..0bd91625 100644
--- a/src/util/crypto.c
+++ b/src/util/crypto.c
@@ -73,23 +73,26 @@ enum GNUNET_GenericReturnValue
 TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info,
                        const struct TALER_DenominationPublicKey *denom_pub)
 {
-  struct GNUNET_HashCode c_hash;
+  struct TALER_CoinPubHash c_hash;
 #if ENABLE_SANITY_CHECKS
-  struct GNUNET_HashCode d_hash;
+  struct TALER_DenominationHash d_hash;
 
-  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
-                                     &d_hash);
+  TALER_denom_pub_hash (denom_pub,
+                        &d_hash);
   GNUNET_assert (0 ==
                  GNUNET_memcmp (&d_hash,
                                 &coin_public_info->denom_pub_hash));
 #endif
+  // FIXME-Oec: replace with function that
+  // also hashes the age vector if we have
+  // one!
   GNUNET_CRYPTO_hash (&coin_public_info->coin_pub,
                       sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
-                      &c_hash);
+                      &c_hash.hash);
   if (GNUNET_OK !=
-      GNUNET_CRYPTO_rsa_verify (&c_hash,
-                                coin_public_info->denom_sig.rsa_signature,
-                                denom_pub->rsa_public_key))
+      TALER_denom_pub_verify (denom_pub,
+                              &coin_public_info->denom_sig,
+                              &c_hash))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "coin signature is invalid\n");
@@ -175,54 +178,60 @@ TALER_planchet_setup_random (struct 
TALER_PlanchetSecretsP *ps)
 enum GNUNET_GenericReturnValue
 TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
                         const struct TALER_PlanchetSecretsP *ps,
-                        struct GNUNET_HashCode *c_hash,
+                        struct TALER_CoinPubHash *c_hash,
                         struct TALER_PlanchetDetail *pd)
 {
   struct TALER_CoinSpendPublicKeyP coin_pub;
 
   GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
                                       &coin_pub.eddsa_pub);
-  GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub,
-                      sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
-                      c_hash);
-  if (GNUNET_YES !=
-      TALER_rsa_blind (c_hash,
-                       &ps->blinding_key.bks,
-                       dk->rsa_public_key,
-                       &pd->coin_ev,
-                       &pd->coin_ev_size))
+  if (GNUNET_OK !=
+      TALER_denom_blind (dk,
+                         &ps->blinding_key,
+                         NULL, /* FIXME-Oec */
+                         &coin_pub,
+                         c_hash,
+                         &pd->coin_ev,
+                         &pd->coin_ev_size))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  GNUNET_CRYPTO_rsa_public_key_hash (dk->rsa_public_key,
-                                     &pd->denom_pub_hash);
+  TALER_denom_pub_hash (dk,
+                        &pd->denom_pub_hash);
   return GNUNET_OK;
 }
 
 
 enum GNUNET_GenericReturnValue
-TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk,
-                        const struct GNUNET_CRYPTO_RsaSignature *blind_sig,
-                        const struct TALER_PlanchetSecretsP *ps,
-                        const struct GNUNET_HashCode *c_hash,
-                        struct TALER_FreshCoin *coin)
+TALER_planchet_to_coin (
+  const struct TALER_DenominationPublicKey *dk,
+  const struct TALER_BlindedDenominationSignature *blind_sig,
+  const struct TALER_PlanchetSecretsP *ps,
+  const struct TALER_CoinPubHash *c_hash,
+  struct TALER_FreshCoin *coin)
 {
-  struct GNUNET_CRYPTO_RsaSignature *sig;
+  struct TALER_DenominationSignature sig;
 
-  sig = TALER_rsa_unblind (blind_sig,
-                           &ps->blinding_key.bks,
-                           dk->rsa_public_key);
   if (GNUNET_OK !=
-      GNUNET_CRYPTO_rsa_verify (c_hash,
-                                sig,
-                                dk->rsa_public_key))
+      TALER_denom_sig_unblind (&sig,
+                               blind_sig,
+                               &ps->blinding_key,
+                               dk))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      TALER_denom_pub_verify (dk,
+                              &sig,
+                              c_hash))
   {
     GNUNET_break_op (0);
-    GNUNET_CRYPTO_rsa_signature_free (sig);
+    TALER_denom_sig_free (&sig);
     return GNUNET_SYSERR;
   }
-  coin->sig.rsa_signature = sig;
+  coin->sig = sig;
   coin->coin_priv = ps->coin_priv;
   return GNUNET_OK;
 }
@@ -250,19 +259,16 @@ TALER_refresh_get_commitment (struct 
TALER_RefreshCommitmentP *rc,
      hash_context */
   for (unsigned int i = 0; i<num_new_coins; i++)
   {
-    void *buf;
-    size_t buf_size;
+    struct TALER_DenominationHash denom_hash;
 
     /* The denomination keys should / must all be identical regardless
        of what offset we use, so we use [0]. */
     GNUNET_assert (kappa > 0); /* sanity check */
-    buf_size = GNUNET_CRYPTO_rsa_public_key_encode (
-      rcs[0].new_coins[i].dk->rsa_public_key,
-      &buf);
+    TALER_denom_pub_hash (rcs[0].new_coins[i].dk,
+                          &denom_hash);
     GNUNET_CRYPTO_hash_context_read (hash_context,
-                                     buf,
-                                     buf_size);
-    GNUNET_free (buf);
+                                     &denom_hash,
+                                     sizeof (denom_hash));
   }
 
   /* next, add public key of coin and amount being refreshed */
@@ -300,29 +306,49 @@ TALER_refresh_get_commitment (struct 
TALER_RefreshCommitmentP *rc,
 }
 
 
-enum GNUNET_GenericReturnValue
-TALER_rsa_blind (const struct GNUNET_HashCode *hash,
-                 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
-                 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
-                 void **buf,
-                 size_t *buf_size)
+void
+TALER_coin_ev_hash (const void *coin_ev,
+                    size_t coin_ev_size,
+                    struct TALER_BlindedCoinHash *bch)
 {
-  return GNUNET_CRYPTO_rsa_blind (hash,
-                                  bks,
-                                  pkey,
-                                  buf,
-                                  buf_size);
+  GNUNET_CRYPTO_hash (coin_ev,
+                      coin_ev_size,
+                      &bch->hash);
 }
 
 
-struct GNUNET_CRYPTO_RsaSignature *
-TALER_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig,
-                   const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
-                   struct GNUNET_CRYPTO_RsaPublicKey *pkey)
+void
+TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                     const struct TALER_AgeHash *age_commitment_hash,
+                     struct TALER_CoinPubHash *coin_h)
 {
-  return GNUNET_CRYPTO_rsa_unblind (sig,
-                                    bks,
-                                    pkey);
+  if (NULL == age_commitment_hash)
+  {
+    /* No age commitment was set */
+    GNUNET_CRYPTO_hash (&coin_pub->eddsa_pub,
+                        sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
+                        &coin_h->hash);
+  }
+  else
+  {
+    /* Coin comes with age commitment.  Take the hash of the age commitment
+     * into account */
+    const size_t key_s = sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey);
+    const size_t age_s = sizeof(struct TALER_AgeHash);
+    char data[key_s + age_s];
+
+    GNUNET_memcpy (&data[0],
+                   &coin_pub->eddsa_pub,
+                   key_s);
+
+    GNUNET_memcpy (&data[key_s],
+                   age_commitment_hash,
+                   age_s);
+
+    GNUNET_CRYPTO_hash (&data,
+                        key_s + age_s,
+                        &coin_h->hash);
+  }
 }
 
 
diff --git a/src/util/crypto_helper_denom.c b/src/util/crypto_helper_denom.c
index a7190c8a..6490184e 100644
--- a/src/util/crypto_helper_denom.c
+++ b/src/util/crypto_helper_denom.c
@@ -20,6 +20,7 @@
  */
 #include "platform.h"
 #include "taler_util.h"
+#include "taler_extensions.h"
 #include "taler_signatures.h"
 #include "taler-exchange-secmod-rsa.h"
 #include <poll.h>
@@ -62,6 +63,11 @@ struct TALER_CRYPTO_DenominationHelper
    * Have we ever been sync'ed?
    */
   bool synced;
+
+  /**
+   * Age Mask that applies to this denomination.
+   */
+  struct TALER_AgeMask age_mask;
 };
 
 
@@ -109,9 +115,6 @@ try_connect (struct TALER_CRYPTO_DenominationHelper *dh)
   tmpdir = GNUNET_DISK_mktemp (dh->template);
   if (NULL == tmpdir)
   {
-    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
-                              "mktemp",
-                              dh->template);
     do_disconnect (dh);
     return;
   }
@@ -277,6 +280,21 @@ TALER_CRYPTO_helper_denom_connect (
       TALER_CRYPTO_helper_denom_disconnect (dh);
       return NULL;
     }
+
+    /* Extract the age groups from the config, if the extension has been set,
+     * and serialize them into the age mask
+     */
+    if (GNUNET_OK !=
+        TALER_get_age_mask (cfg, &dh->age_mask))
+    {
+      /* FIXME: maybe more specific error? */
+      GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                                 "extensions", /* FIXME: right section etc? */
+                                 "age-restriction",
+                                 "invalid age groups");
+      TALER_CRYPTO_helper_denom_disconnect (dh);
+      return NULL;
+    }
   }
   TALER_CRYPTO_helper_denom_poll (dh);
   return dh;
@@ -290,7 +308,7 @@ TALER_CRYPTO_helper_denom_connect (
  * @param hdr message that we received
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 handle_mt_avail (struct TALER_CRYPTO_DenominationHelper *dh,
                  const struct GNUNET_MessageHeader *hdr)
 {
@@ -321,24 +339,26 @@ handle_mt_avail (struct TALER_CRYPTO_DenominationHelper 
*dh,
 
   {
     struct TALER_DenominationPublicKey denom_pub;
-    struct GNUNET_HashCode h_denom_pub;
+    struct TALER_DenominationHash h_denom_pub;
 
-    denom_pub.rsa_public_key
+    denom_pub.cipher = TALER_DENOMINATION_RSA;
+    denom_pub.age_mask = dh->age_mask;
+    denom_pub.details.rsa_public_key
       = GNUNET_CRYPTO_rsa_public_key_decode (buf,
                                              ntohs (kan->pub_size));
-    if (NULL == denom_pub.rsa_public_key)
+    if (NULL == denom_pub.details.rsa_public_key)
     {
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-    GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
-                                       &h_denom_pub);
+    TALER_denom_pub_hash (&denom_pub,
+                          &h_denom_pub);
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Received RSA key %s (%s)\n",
-                GNUNET_h2s (&h_denom_pub),
+                GNUNET_h2s (&h_denom_pub.hash),
                 section_name);
     if (GNUNET_OK !=
-        TALER_exchange_secmod_rsa_verify (
+        TALER_exchange_secmod_denom_verify (
           &h_denom_pub,
           section_name,
           GNUNET_TIME_absolute_ntoh (kan->anchor_time),
@@ -347,7 +367,7 @@ handle_mt_avail (struct TALER_CRYPTO_DenominationHelper *dh,
           &kan->secm_sig))
     {
       GNUNET_break_op (0);
-      GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key);
+      GNUNET_CRYPTO_rsa_public_key_free (denom_pub.details.rsa_public_key);
       return GNUNET_SYSERR;
     }
     dh->dkc (dh->dkc_cls,
@@ -358,7 +378,7 @@ handle_mt_avail (struct TALER_CRYPTO_DenominationHelper *dh,
              &denom_pub,
              &kan->secm_pub,
              &kan->secm_sig);
-    GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key);
+    GNUNET_CRYPTO_rsa_public_key_free (denom_pub.details.rsa_public_key);
   }
   return GNUNET_OK;
 }
@@ -371,7 +391,7 @@ handle_mt_avail (struct TALER_CRYPTO_DenominationHelper *dh,
  * @param hdr message that we received
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 handle_mt_purge (struct TALER_CRYPTO_DenominationHelper *dh,
                  const struct GNUNET_MessageHeader *hdr)
 {
@@ -385,7 +405,7 @@ handle_mt_purge (struct TALER_CRYPTO_DenominationHelper *dh,
   }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Received revocation of denomination key %s\n",
-              GNUNET_h2s (&pn->h_denom_pub));
+              GNUNET_h2s (&pn->h_denom_pub.hash));
   dh->dkc (dh->dkc_cls,
            NULL,
            GNUNET_TIME_UNIT_ZERO_ABS,
@@ -468,7 +488,7 @@ TALER_CRYPTO_helper_denom_poll (struct 
TALER_CRYPTO_DenominationHelper *dh)
         if (! await_read_ready (dh))
         {
           /* timeout AND not synced => full reconnect */
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+          GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                       "Restarting connection to RSA helper, did not come up 
properly\n");
           do_disconnect (dh);
           if (0 == retry_limit)
@@ -543,15 +563,17 @@ TALER_CRYPTO_helper_denom_poll (struct 
TALER_CRYPTO_DenominationHelper *dh)
 }
 
 
-struct TALER_DenominationSignature
+struct TALER_BlindedDenominationSignature
 TALER_CRYPTO_helper_denom_sign (
   struct TALER_CRYPTO_DenominationHelper *dh,
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const void *msg,
   size_t msg_size,
   enum TALER_ErrorCode *ec)
 {
-  struct TALER_DenominationSignature ds = { NULL };
+  struct TALER_BlindedDenominationSignature ds = {
+    .details.blinded_rsa_signature = NULL
+  };
   {
     char buf[sizeof (struct TALER_CRYPTO_SignRequest) + msg_size];
     struct TALER_CRYPTO_SignRequest *sr
@@ -600,10 +622,10 @@ TALER_CRYPTO_helper_denom_sign (
 
     if (! await_read_ready (dh))
     {
+      do_disconnect (dh);
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Timeout waiting for helper\n");
-      do_disconnect (dh);
-      *ec = TALER_EC_EXCHANGE_GENERIC_SECMOD_TIMEOUT;
+      *ec = TALER_EC_GENERIC_TIMEOUT;
       return ds;
     }
     ret = recv (dh->sock,
@@ -651,7 +673,8 @@ TALER_CRYPTO_helper_denom_sign (
           return ds;
         }
         *ec = TALER_EC_NONE;
-        ds.rsa_signature = rsa_signature;
+        ds.cipher = TALER_DENOMINATION_RSA;
+        ds.details.blinded_rsa_signature = rsa_signature;
         return ds;
       }
     case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
@@ -691,16 +714,8 @@ TALER_CRYPTO_helper_denom_sign (
         return ds;
       }
       break; /* while(1) loop ensures we recvfrom() again */
-    case TALER_HELPER_RSA_SYNCED:
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Synchronized add odd time with RSA helper!\n");
-      dh->synced = true;
-      break;
     default:
       GNUNET_break_op (0);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Received unexpected message of type %u\n",
-                  ntohs (hdr->type));
       do_disconnect (dh);
       *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
       return ds;
@@ -712,7 +727,7 @@ TALER_CRYPTO_helper_denom_sign (
 void
 TALER_CRYPTO_helper_denom_revoke (
   struct TALER_CRYPTO_DenominationHelper *dh,
-  const struct GNUNET_HashCode *h_denom_pub)
+  const struct TALER_DenominationHash *h_denom_pub)
 {
   struct TALER_CRYPTO_RevokeRequest rr = {
     .header.size = htons (sizeof (rr)),
@@ -741,7 +756,7 @@ TALER_CRYPTO_helper_denom_revoke (
   GNUNET_break (((size_t) ret) == sizeof (rr));
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Requested revocation of denomination key %s\n",
-              GNUNET_h2s (h_denom_pub));
+              GNUNET_h2s (&h_denom_pub->hash));
 }
 
 
diff --git a/src/util/crypto_helper_esign.c b/src/util/crypto_helper_esign.c
index 2faebd51..6257a1d2 100644
--- a/src/util/crypto_helper_esign.c
+++ b/src/util/crypto_helper_esign.c
@@ -110,9 +110,6 @@ try_connect (struct TALER_CRYPTO_ExchangeSignHelper *esh)
   tmpdir = GNUNET_DISK_mktemp (esh->template);
   if (NULL == tmpdir)
   {
-    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
-                              "mktemp",
-                              esh->template);
     do_disconnect (esh);
     return;
   }
@@ -419,7 +416,7 @@ TALER_CRYPTO_helper_esign_poll (struct 
TALER_CRYPTO_ExchangeSignHelper *esh)
         if (! await_read_ready (esh))
         {
           /* timeout AND not synced => full reconnect */
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+          GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                       "Restarting connection to EdDSA helper, did not come up 
properly\n");
           do_disconnect (esh);
           if (0 == retry_limit)
@@ -541,10 +538,10 @@ TALER_CRYPTO_helper_esign_sign_ (
 
     if (! await_read_ready (esh))
     {
+      do_disconnect (esh);
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Timeout waiting for helper\n");
-      do_disconnect (esh);
-      return TALER_EC_EXCHANGE_GENERIC_SECMOD_TIMEOUT;
+      return TALER_EC_GENERIC_TIMEOUT;
     }
     ret = recv (esh->sock,
                 buf,
@@ -613,16 +610,8 @@ TALER_CRYPTO_helper_esign_sign_ (
         return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
       }
       break; /* while(1) loop ensures we recvfrom() again */
-    case TALER_HELPER_EDDSA_SYNCED:
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Synchronized add odd time with EdDSA helper!\n");
-      esh->synced = true;
-      break;
     default:
       GNUNET_break_op (0);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Received unexpected message of type %u\n",
-                  ntohs (hdr->type));
       do_disconnect (esh);
       return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     }
diff --git a/src/util/crypto_wire.c b/src/util/crypto_wire.c
index ee3215ca..616ae410 100644
--- a/src/util/crypto_wire.c
+++ b/src/util/crypto_wire.c
@@ -19,32 +19,10 @@
  * @author Christian Grothoff <christian@grothoff.org>
  */
 #include "platform.h"
-#include "taler_crypto_lib.h"
+#include "taler_util.h"
 #include "taler_signatures.h"
 
 
-/**
- * Compute the hash of the given wire details. The resulting
- * hash is what is signed by the master key.
- *
- * @param payto_uri bank account
- * @param[out] hc set to the hash
- */
-void
-TALER_exchange_wire_signature_hash (const char *payto_uri,
-                                    struct GNUNET_HashCode *hc)
-{
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CRYPTO_kdf (hc,
-                                    sizeof (*hc),
-                                    payto_uri,
-                                    strlen (payto_uri) + 1,
-                                    "exchange-wire-signature",
-                                    strlen ("exchange-wire-signature"),
-                                    NULL, 0));
-}
-
-
 /**
  * Check the signature in @a master_sig.
  *
@@ -64,8 +42,8 @@ TALER_exchange_wire_signature_check (
     .purpose.size = htonl (sizeof (wd))
   };
 
-  TALER_exchange_wire_signature_hash (payto_uri,
-                                      &wd.h_wire_details);
+  TALER_payto_hash (payto_uri,
+                    &wd.h_wire_details);
   return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_DETAILS,
                                      &wd,
                                      &master_sig->eddsa_signature,
@@ -91,8 +69,8 @@ TALER_exchange_wire_signature_make (
     .purpose.size = htonl (sizeof (wd))
   };
 
-  TALER_exchange_wire_signature_hash (payto_uri,
-                                      &wd.h_wire_details);
+  TALER_payto_hash (payto_uri,
+                    &wd.h_wire_details);
   GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
                             &wd,
                             &master_sig->eddsa_signature);
@@ -111,10 +89,8 @@ TALER_exchange_wire_signature_make (
 void
 TALER_merchant_wire_signature_hash (const char *payto_uri,
                                     const struct TALER_WireSalt *salt,
-                                    struct GNUNET_HashCode *hc)
+                                    struct TALER_MerchantWireHash *hc)
 {
-#if FIXED_7032
-  /* new logic to use once #7032 is being addressed */
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CRYPTO_kdf (hc,
                                     sizeof (*hc),
@@ -125,24 +101,6 @@ TALER_merchant_wire_signature_hash (const char *payto_uri,
                                     "merchant-wire-signature",
                                     strlen ("merchant-wire-signature"),
                                     NULL, 0));
-#else
-  /* compatibility logic to avoid protocol breakage... */
-  char *sstr;
-
-  sstr = GNUNET_STRINGS_data_to_string_alloc (salt,
-                                              sizeof (*salt));
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CRYPTO_kdf (hc,
-                                    sizeof (*hc),
-                                    sstr,
-                                    strlen (sstr) + 1,
-                                    payto_uri,
-                                    strlen (payto_uri) + 1,
-                                    "merchant-wire-signature",
-                                    strlen ("merchant-wire-signature"),
-                                    NULL, 0));
-  GNUNET_free (sstr);
-#endif
 }
 
 
@@ -170,7 +128,7 @@ TALER_merchant_wire_signature_check (
   const struct TALER_MerchantPublicKeyP *merch_pub,
   const struct TALER_MerchantSignatureP *merch_sig)
 {
-  struct TALER_MasterWireDetailsPS wd = {
+  struct TALER_MerchantWireDetailsPS wd = {
     .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS),
     .purpose.size = htonl (sizeof (wd))
   };
@@ -200,7 +158,7 @@ TALER_merchant_wire_signature_make (
   const struct TALER_MerchantPrivateKeyP *merch_priv,
   struct TALER_MerchantSignatureP *merch_sig)
 {
-  struct TALER_MasterWireDetailsPS wd = {
+  struct TALER_MerchantWireDetailsPS wd = {
     .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_WIRE_DETAILS),
     .purpose.size = htonl (sizeof (wd))
   };
diff --git a/src/util/denom.c b/src/util/denom.c
new file mode 100644
index 00000000..bb135140
--- /dev/null
+++ b/src/util/denom.c
@@ -0,0 +1,511 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2021 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file denom.c
+ * @brief denomination utility functions
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_util.h"
+
+
+enum GNUNET_GenericReturnValue
+TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv,
+                         struct TALER_DenominationPublicKey *denom_pub,
+                         enum TALER_DenominationCipher cipher,
+                         ...)
+{
+  memset (denom_priv,
+          0,
+          sizeof (*denom_priv));
+  memset (denom_pub,
+          0,
+          sizeof (*denom_pub));
+  switch (cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  case TALER_DENOMINATION_RSA:
+    {
+      va_list ap;
+      unsigned int bits;
+
+      va_start (ap, cipher);
+      bits = va_arg (ap, unsigned int);
+      va_end (ap);
+      if (bits < 512)
+      {
+        GNUNET_break (0);
+        return GNUNET_SYSERR;
+      }
+      denom_priv->details.rsa_private_key
+        = GNUNET_CRYPTO_rsa_private_key_create (bits);
+    }
+    if (NULL == denom_priv->details.rsa_private_key)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    denom_pub->details.rsa_public_key
+      = GNUNET_CRYPTO_rsa_private_key_get_public (
+          denom_priv->details.rsa_private_key);
+    denom_priv->cipher = cipher;
+    denom_pub->cipher = cipher;
+    return GNUNET_OK;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_break (0);
+  }
+  return GNUNET_SYSERR;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig,
+                          const struct TALER_DenominationPrivateKey 
*denom_priv,
+                          void *blinded_msg,
+                          size_t blinded_msg_size)
+{
+  memset (denom_sig,
+          0,
+          sizeof (*denom_sig));
+  switch (denom_priv->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  case TALER_DENOMINATION_RSA:
+    denom_sig->details.blinded_rsa_signature
+      = GNUNET_CRYPTO_rsa_sign_blinded (
+          denom_priv->details.rsa_private_key,
+          blinded_msg,
+          blinded_msg_size);
+    if (NULL == denom_sig->details.blinded_rsa_signature)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    denom_sig->cipher = TALER_DENOMINATION_RSA;
+    return GNUNET_OK;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_break (0);
+  }
+  return GNUNET_SYSERR;
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_denom_sig_unblind (
+  struct TALER_DenominationSignature *denom_sig,
+  const struct TALER_BlindedDenominationSignature *bdenom_sig,
+  const union TALER_DenominationBlindingKeyP *bks,
+  const struct TALER_DenominationPublicKey *denom_pub)
+{
+  if (bdenom_sig->cipher != denom_pub->cipher)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  switch (denom_pub->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  case TALER_DENOMINATION_RSA:
+    denom_sig->details.rsa_signature
+      = GNUNET_CRYPTO_rsa_unblind (
+          bdenom_sig->details.blinded_rsa_signature,
+          &bks->rsa_bks,
+          denom_pub->details.rsa_public_key);
+    if (NULL == denom_sig->details.rsa_signature)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    denom_sig->cipher = TALER_DENOMINATION_RSA;
+    return GNUNET_OK;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_break (0);
+  }
+  return GNUNET_SYSERR;
+}
+
+
+void
+TALER_blinding_secret_create (union TALER_DenominationBlindingKeyP *bs)
+{
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+                              bs,
+                              sizeof (*bs));
+}
+
+
+void
+TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub,
+                      struct TALER_DenominationHash *denom_hash)
+{
+  uint32_t opt[2] = {
+    htonl (denom_pub->age_mask.mask),
+    htonl ((uint32_t) denom_pub->cipher)
+  };
+
+  struct GNUNET_HashContext *hc;
+  hc = GNUNET_CRYPTO_hash_context_start ();
+  GNUNET_CRYPTO_hash_context_read (hc,
+                                   opt,
+                                   sizeof (opt));
+  switch (denom_pub->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    {
+      void *buf;
+      size_t blen;
+
+      blen = GNUNET_CRYPTO_rsa_public_key_encode (
+        denom_pub->details.rsa_public_key,
+        &buf);
+      GNUNET_CRYPTO_hash_context_read (hc,
+                                       buf,
+                                       blen);
+      GNUNET_free (buf);
+    }
+    break;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+  GNUNET_CRYPTO_hash_context_finish (hc,
+                                     &denom_hash->hash);
+}
+
+
+void
+TALER_denom_priv_to_pub (const struct TALER_DenominationPrivateKey *denom_priv,
+                         const struct TALER_AgeMask age_mask,
+                         struct TALER_DenominationPublicKey *denom_pub)
+{
+  switch (denom_priv->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    denom_pub->cipher = TALER_DENOMINATION_RSA;
+    denom_pub->age_mask = age_mask;
+    denom_pub->details.rsa_public_key
+      = GNUNET_CRYPTO_rsa_private_key_get_public (
+          denom_priv->details.rsa_private_key);
+    return;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_denom_blind (const struct TALER_DenominationPublicKey *dk,
+                   const union TALER_DenominationBlindingKeyP *coin_bks,
+                   const struct TALER_AgeHash *age_commitment_hash,
+                   const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                   struct TALER_CoinPubHash *c_hash,
+                   void **coin_ev,
+                   size_t *coin_ev_size)
+{
+  switch (dk->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    TALER_coin_pub_hash (coin_pub,
+                         age_commitment_hash,
+                         c_hash);
+    if (GNUNET_YES !=
+        GNUNET_CRYPTO_rsa_blind (&c_hash->hash,
+                                 &coin_bks->rsa_bks,
+                                 dk->details.rsa_public_key,
+                                 coin_ev,
+                                 coin_ev_size))
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_OK;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub,
+                        const struct TALER_DenominationSignature *denom_sig,
+                        const struct TALER_CoinPubHash *c_hash)
+{
+  if (denom_pub->cipher != denom_sig->cipher)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  switch (denom_pub->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    GNUNET_break (0);
+    return GNUNET_NO;
+  case TALER_DENOMINATION_RSA:
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_rsa_verify (&c_hash->hash,
+                                  denom_sig->details.rsa_signature,
+                                  denom_pub->details.rsa_public_key))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Coin signature is invalid\n");
+      return GNUNET_NO;
+    }
+    return GNUNET_YES;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+void
+TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub)
+{
+  switch (denom_pub->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    return;
+  case TALER_DENOMINATION_RSA:
+    if (NULL != denom_pub->details.rsa_public_key)
+    {
+      GNUNET_CRYPTO_rsa_public_key_free (denom_pub->details.rsa_public_key);
+      denom_pub->details.rsa_public_key = NULL;
+    }
+    denom_pub->cipher = TALER_DENOMINATION_INVALID;
+    return;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+void
+TALER_denom_priv_free (struct TALER_DenominationPrivateKey *denom_priv)
+{
+  switch (denom_priv->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    return;
+  case TALER_DENOMINATION_RSA:
+    if (NULL != denom_priv->details.rsa_private_key)
+    {
+      GNUNET_CRYPTO_rsa_private_key_free (denom_priv->details.rsa_private_key);
+      denom_priv->details.rsa_private_key = NULL;
+    }
+    denom_priv->cipher = TALER_DENOMINATION_INVALID;
+    return;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+void
+TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig)
+{
+  switch (denom_sig->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    return;
+  case TALER_DENOMINATION_RSA:
+    if (NULL != denom_sig->details.rsa_signature)
+    {
+      GNUNET_CRYPTO_rsa_signature_free (denom_sig->details.rsa_signature);
+      denom_sig->details.rsa_signature = NULL;
+    }
+    denom_sig->cipher = TALER_DENOMINATION_INVALID;
+    return;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+void
+TALER_blinded_denom_sig_free (
+  struct TALER_BlindedDenominationSignature *denom_sig)
+{
+  switch (denom_sig->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    return;
+  case TALER_DENOMINATION_RSA:
+    if (NULL != denom_sig->details.blinded_rsa_signature)
+    {
+      GNUNET_CRYPTO_rsa_signature_free (
+        denom_sig->details.blinded_rsa_signature);
+      denom_sig->details.blinded_rsa_signature = NULL;
+    }
+    denom_sig->cipher = TALER_DENOMINATION_INVALID;
+    return;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+/**
+ * Make a (deep) copy of the given @a denom_src to
+ * @a denom_dst.
+ *
+ * @param[out] denom_dst target to copy to
+ * @param denom_str public key to copy
+ */
+void
+TALER_denom_pub_deep_copy (struct TALER_DenominationPublicKey *denom_dst,
+                           const struct TALER_DenominationPublicKey *denom_src)
+{
+  *denom_dst = *denom_src; /* shallow copy */
+  switch (denom_src->cipher)
+  {
+  case TALER_DENOMINATION_RSA:
+    denom_dst->details.rsa_public_key
+      = GNUNET_CRYPTO_rsa_public_key_dup (
+          denom_src->details.rsa_public_key);
+    return;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+void
+TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst,
+                           const struct TALER_DenominationSignature *denom_src)
+{
+  *denom_dst = *denom_src; /* shallow copy */
+  switch (denom_src->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    return;
+  case TALER_DENOMINATION_RSA:
+    denom_dst->details.rsa_signature
+      = GNUNET_CRYPTO_rsa_signature_dup (
+          denom_src->details.rsa_signature);
+    return;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+void
+TALER_blinded_denom_sig_deep_copy (
+  struct TALER_BlindedDenominationSignature *denom_dst,
+  const struct TALER_BlindedDenominationSignature *denom_src)
+{
+  *denom_dst = *denom_src; /* shallow copy */
+  switch (denom_src->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    return;
+  case TALER_DENOMINATION_RSA:
+    denom_dst->details.blinded_rsa_signature
+      = GNUNET_CRYPTO_rsa_signature_dup (
+          denom_src->details.blinded_rsa_signature);
+    return;
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+}
+
+
+int
+TALER_denom_pub_cmp (const struct TALER_DenominationPublicKey *denom1,
+                     const struct TALER_DenominationPublicKey *denom2)
+{
+  if (denom1->cipher != denom2->cipher)
+    return (denom1->cipher > denom2->cipher) ? 1 : -1;
+  if (denom1->age_mask.mask != denom2->age_mask.mask)
+    return (denom1->age_mask.mask > denom2->age_mask.mask) ? 1 : -1;
+  switch (denom1->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    return 0;
+  case TALER_DENOMINATION_RSA:
+    return GNUNET_CRYPTO_rsa_public_key_cmp (denom1->details.rsa_public_key,
+                                             denom2->details.rsa_public_key);
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+  return -2;
+}
+
+
+int
+TALER_denom_sig_cmp (const struct TALER_DenominationSignature *sig1,
+                     const struct TALER_DenominationSignature *sig2)
+{
+  if (sig1->cipher != sig2->cipher)
+    return (sig1->cipher > sig2->cipher) ? 1 : -1;
+  switch (sig1->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    return 0;
+  case TALER_DENOMINATION_RSA:
+    return GNUNET_CRYPTO_rsa_signature_cmp (sig1->details.rsa_signature,
+                                            sig2->details.rsa_signature);
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+  return -2;
+}
+
+
+int
+TALER_blinded_denom_sig_cmp (
+  const struct TALER_BlindedDenominationSignature *sig1,
+  const struct TALER_BlindedDenominationSignature *sig2)
+{
+  if (sig1->cipher != sig2->cipher)
+    return (sig1->cipher > sig2->cipher) ? 1 : -1;
+  switch (sig1->cipher)
+  {
+  case TALER_DENOMINATION_INVALID:
+    return 0;
+  case TALER_DENOMINATION_RSA:
+    return GNUNET_CRYPTO_rsa_signature_cmp 
(sig1->details.blinded_rsa_signature,
+                                            
sig2->details.blinded_rsa_signature);
+  // TODO: add case for Clause-Schnorr
+  default:
+    GNUNET_assert (0);
+  }
+  return -2;
+}
+
+
+/* end of denom.c */
diff --git a/src/util/exchange_signatures.c b/src/util/exchange_signatures.c
new file mode 100644
index 00000000..2e71a33c
--- /dev/null
+++ b/src/util/exchange_signatures.c
@@ -0,0 +1,69 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2021 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file exchange_signatures.c
+ * @brief Utility functions for Taler security module signatures
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_signatures.h"
+
+
+enum GNUNET_GenericReturnValue
+TALER_exchange_deposit_confirm_verify (
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_ExtensionContractHash *h_extensions,
+  struct GNUNET_TIME_Absolute exchange_timestamp,
+  struct GNUNET_TIME_Absolute wire_deadline,
+  struct GNUNET_TIME_Absolute refund_deadline,
+  const struct TALER_Amount *amount_without_fee,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  const struct TALER_ExchangePublicKeyP *exchange_pub,
+  const struct TALER_ExchangeSignatureP *exchange_sig)
+{
+  struct TALER_DepositConfirmationPS dcs = {
+    .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
+    .purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
+    .h_contract_terms = *h_contract_terms,
+    .h_wire = *h_wire,
+    .exchange_timestamp = GNUNET_TIME_absolute_hton (exchange_timestamp),
+    .wire_deadline = GNUNET_TIME_absolute_hton (wire_deadline),
+    .refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
+    .coin_pub = *coin_pub,
+    .merchant_pub = *merchant_pub
+  };
+
+  if (NULL != h_extensions)
+    dcs.h_extensions = *h_extensions;
+  TALER_amount_hton (&dcs.amount_without_fee,
+                     amount_without_fee);
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
+                                  &dcs,
+                                  &exchange_sig->eddsa_signature,
+                                  &exchange_pub->eddsa_pub))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/* end of exchange_signatures.c */
diff --git a/src/util/extension_age_restriction.c 
b/src/util/extension_age_restriction.c
new file mode 100644
index 00000000..dbb4f3e2
--- /dev/null
+++ b/src/util/extension_age_restriction.c
@@ -0,0 +1,49 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2014-2020 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file extension_age_restriction.c
+ * @brief Utility functions regarding age restriction
+ * @author Özgür Kesim
+ */
+#include "platform.h"
+#include "taler_util.h"
+
+
+/**
+ *
+ * @param cfg
+ * @param[out] mask for age restriction
+ * @return Error if extension for age restriction was set but age groups were
+ *         invalid, OK otherwise.
+ */
+enum GNUNET_GenericReturnValue
+TALER_get_age_mask (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                    struct TALER_AgeMask *mask)
+{
+  /* FIXME-Oec:
+   *
+   * - Detect if age restriction is enabled in config
+   * - if not, return 0 mask
+   * - else, parse age group and serialize into mask
+   * - return Error on
+   *
+   * */
+  mask->mask = 0;
+  return GNUNET_OK;
+}
+
+
+/* end of extension_age_restriction.c */
diff --git a/src/util/mhd.c b/src/util/mhd.c
index 9684f979..2f262340 100644
--- a/src/util/mhd.c
+++ b/src/util/mhd.c
@@ -31,7 +31,7 @@
  *          #GNUNET_NO if the MHD connection is using http,
  *          #GNUNET_SYSERR if the connection type couldn't be determined
  */
-int
+enum GNUNET_GenericReturnValue
 TALER_mhd_is_https (struct MHD_Connection *connection)
 {
   const union MHD_ConnectionInfo *ci;
diff --git a/src/util/offline_signatures.c b/src/util/offline_signatures.c
index bd71af8f..fe502c65 100644
--- a/src/util/offline_signatures.c
+++ b/src/util/offline_signatures.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2020 Taler Systems SA
+  Copyright (C) 2020, 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -117,7 +117,7 @@ TALER_exchange_offline_auditor_del_verify (
 
 void
 TALER_exchange_offline_denomination_revoke_sign (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterPrivateKeyP *master_priv,
   struct TALER_MasterSignatureP *master_sig)
 {
@@ -135,7 +135,7 @@ TALER_exchange_offline_denomination_revoke_sign (
 
 enum GNUNET_GenericReturnValue
 TALER_exchange_offline_denomination_revoke_verify (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_MasterPublicKeyP *master_pub,
   const struct TALER_MasterSignatureP *master_sig)
 {
@@ -249,7 +249,7 @@ TALER_exchange_offline_signkey_validity_verify (
 
 void
 TALER_exchange_offline_denom_validity_sign (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   struct GNUNET_TIME_Absolute stamp_start,
   struct GNUNET_TIME_Absolute stamp_expire_withdraw,
   struct GNUNET_TIME_Absolute stamp_expire_deposit,
@@ -294,7 +294,7 @@ TALER_exchange_offline_denom_validity_sign (
 
 enum GNUNET_GenericReturnValue
 TALER_exchange_offline_denom_validity_verify (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   struct GNUNET_TIME_Absolute stamp_start,
   struct GNUNET_TIME_Absolute stamp_expire_withdraw,
   struct GNUNET_TIME_Absolute stamp_expire_deposit,
@@ -353,8 +353,8 @@ TALER_exchange_offline_wire_add_sign (
 
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_TIME_round_abs (&now));
-  TALER_exchange_wire_signature_hash (payto_uri,
-                                      &kv.h_wire);
+  TALER_payto_hash (payto_uri,
+                    &kv.h_payto);
   GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
                             &kv,
                             &master_sig->eddsa_signature);
@@ -374,8 +374,8 @@ TALER_exchange_offline_wire_add_verify (
     .start_date = GNUNET_TIME_absolute_hton (sign_time),
   };
 
-  TALER_exchange_wire_signature_hash (payto_uri,
-                                      &aw.h_wire);
+  TALER_payto_hash (payto_uri,
+                    &aw.h_payto);
   return
     GNUNET_CRYPTO_eddsa_verify (
     TALER_SIGNATURE_MASTER_ADD_WIRE,
@@ -400,8 +400,8 @@ TALER_exchange_offline_wire_del_sign (
 
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_TIME_round_abs (&now));
-  TALER_exchange_wire_signature_hash (payto_uri,
-                                      &kv.h_wire);
+  TALER_payto_hash (payto_uri,
+                    &kv.h_payto);
   GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv,
                             &kv,
                             &master_sig->eddsa_signature);
@@ -422,8 +422,8 @@ TALER_exchange_offline_wire_del_verify (
     .end_date = GNUNET_TIME_absolute_hton (sign_time),
   };
 
-  TALER_exchange_wire_signature_hash (payto_uri,
-                                      &aw.h_wire);
+  TALER_payto_hash (payto_uri,
+                    &aw.h_payto);
   return GNUNET_CRYPTO_eddsa_verify (
     TALER_SIGNATURE_MASTER_DEL_WIRE,
     &aw,
diff --git a/src/util/payto.c b/src/util/payto.c
index 58f1bf63..746b2624 100644
--- a/src/util/payto.c
+++ b/src/util/payto.c
@@ -70,13 +70,6 @@ payto_get_key (const char *payto_uri,
 }
 
 
-/**
- * Extract the subject value from the URI parameters.
- *
- * @param payto_uri the URL to parse
- * @return NULL if the subject parameter is not found.
- *         The caller should free the returned value.
- */
 char *
 TALER_payto_get_subject (const char *payto_uri)
 {
@@ -85,14 +78,6 @@ TALER_payto_get_subject (const char *payto_uri)
 }
 
 
-/**
- * Obtain the payment method from a @a payto_uri. The
- * format of a payto URI is 'payto://$METHOD/$SOMETHING'.
- * We return $METHOD.
- *
- * @param payto_uri the URL to parse
- * @return NULL on error (malformed @a payto_uri)
- */
 char *
 TALER_payto_get_method (const char *payto_uri)
 {
@@ -113,16 +98,6 @@ TALER_payto_get_method (const char *payto_uri)
 }
 
 
-/**
- * Obtain the account name from a payto URL.  The format
- * of the @a payto URL is 'payto://x-taler-bank/$HOSTNAME/$ACCOUNT[?PARAMS]'.
- * We check the first part matches, skip over the $HOSTNAME
- * and return the $ACCOUNT portion.
- *
- * @param payto an x-taler-bank payto URL
- * @return only the account name from the @a payto URL, NULL if not an 
x-taler-bank
- *   payto URL
- */
 char *
 TALER_xtalerbank_account_from_payto (const char *payto)
 {
@@ -202,13 +177,6 @@ validate_payto_iban (const char *account_url)
 }
 
 
-/**
- * Check that a payto:// URI is well-formed.
- *
- * @param payto_uri the URL to check
- * @return NULL on success, otherwise an error
- *         message to be freed by the caller!
- */
 char *
 TALER_payto_validate (const char *payto_uri)
 {
@@ -254,3 +222,55 @@ TALER_payto_validate (const char *payto_uri)
 
   return NULL;
 }
+
+
+void
+TALER_payto_hash (const char *payto,
+                  struct TALER_PaytoHash *h_payto)
+{
+  GNUNET_CRYPTO_hash (payto,
+                      strlen (payto) + 1,
+                      &h_payto->hash);
+}
+
+
+char *
+TALER_payto_from_reserve (const char *exchange_base_url,
+                          const struct TALER_ReservePublicKeyP *reserve_pub)
+{
+  char *payto_uri;
+  char *rps;
+  unsigned int skip;
+  const char *extra = "";
+  int url_len;
+
+  rps = GNUNET_STRINGS_data_to_string_alloc (reserve_pub,
+                                             sizeof (*reserve_pub));
+  skip = 0;
+  if (0 == strncasecmp (exchange_base_url,
+                        "http://";,
+                        strlen ("http://";)))
+  {
+    skip = strlen ("http://";);
+    extra = "+http";
+  }
+  if (0 == strncasecmp (exchange_base_url,
+                        "https://";,
+                        strlen ("https://";)))
+    skip = strlen ("https://";);
+  url_len = strlen (exchange_base_url);
+  if ('/' == exchange_base_url[url_len - 1])
+    url_len--;
+  url_len -= skip;
+  GNUNET_asprintf (&payto_uri,
+                   "taler%s://reserve/%.*s/%s",
+                   extra,
+                   url_len,
+                   exchange_base_url + skip,
+                   rps);
+  GNUNET_free (rps);
+  return payto_uri;
+}
+
+
+/* end of payto.c */
diff --git a/src/util/secmod_signatures.c b/src/util/secmod_signatures.c
index 3df68861..f49cc20a 100644
--- a/src/util/secmod_signatures.c
+++ b/src/util/secmod_signatures.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2020 Taler Systems SA
+  Copyright (C) 2020, 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -70,8 +70,8 @@ TALER_exchange_secmod_eddsa_verify (
 
 
 void
-TALER_exchange_secmod_rsa_sign (
-  const struct GNUNET_HashCode *h_denom_pub,
+TALER_exchange_secmod_denom_sign (
+  const struct TALER_DenominationHash *h_denom_pub,
   const char *section_name,
   struct GNUNET_TIME_Absolute start_sign,
   struct GNUNET_TIME_Relative duration,
@@ -97,8 +97,8 @@ TALER_exchange_secmod_rsa_sign (
 
 
 enum GNUNET_GenericReturnValue
-TALER_exchange_secmod_rsa_verify (
-  const struct GNUNET_HashCode *h_denom_pub,
+TALER_exchange_secmod_denom_verify (
+  const struct TALER_DenominationHash *h_denom_pub,
   const char *section_name,
   struct GNUNET_TIME_Absolute start_sign,
   struct GNUNET_TIME_Relative duration,
diff --git a/src/util/taler-crypto-worker.c b/src/util/taler-crypto-worker.c
index e4480978..9c49ea37 100644
--- a/src/util/taler-crypto-worker.c
+++ b/src/util/taler-crypto-worker.c
@@ -109,7 +109,7 @@ run (void *cls,
         GNUNET_JSON_spec_fixed_auto ("sig",
                                      &sig),
         GNUNET_JSON_spec_varsize ("msg",
-                                  &msg,
+                                  (void **) &msg,
                                   &msg_size),
         GNUNET_JSON_spec_end ()
       };
@@ -148,29 +148,41 @@ run (void *cls,
       uint32_t coin_index;
       json_t *resp;
       struct GNUNET_JSON_Specification eddsa_verify_spec[] = {
-        GNUNET_JSON_spec_rsa_public_key ("denom_pub",
-                                         &denom_pub.rsa_public_key),
-        TALER_JSON_spec_amount_any ("fee_withdraw", &fee_withdraw),
-        TALER_JSON_spec_amount_any ("value", &value),
-        GNUNET_JSON_spec_fixed_auto ("reserve_pub", &reserve_pub),
-        GNUNET_JSON_spec_fixed_auto ("reserve_priv", &reserve_priv),
-        GNUNET_JSON_spec_uint32 ("coin_index", &coin_index),
+        TALER_JSON_spec_denom_pub ("denom_pub",
+                                   &denom_pub),
+        TALER_JSON_spec_amount_any ("fee_withdraw",
+                                    &fee_withdraw),
+        TALER_JSON_spec_amount_any ("value",
+                                    &value),
+        GNUNET_JSON_spec_fixed_auto ("reserve_pub",
+                                     &reserve_pub),
+        GNUNET_JSON_spec_fixed_auto ("reserve_priv",
+                                     &reserve_priv),
+        GNUNET_JSON_spec_uint32 ("coin_index",
+                                 &coin_index),
         GNUNET_JSON_spec_end ()
       };
-      if (GNUNET_OK != GNUNET_JSON_parse (args,
-                                          eddsa_verify_spec,
-                                          NULL,
-                                          NULL))
+      struct TALER_CoinSpendPublicKeyP coin_pub;
+      struct TALER_PlanchetSecretsP ps;
+
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (args,
+                             eddsa_verify_spec,
+                             NULL,
+                             NULL))
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                     "malformed op args\n");
         global_ret = 1;
         return;
       }
+#if FIXME_FLORIAN
       TALER_planchet_setup_refresh (&transfer_secret,
-                                    coin_num_salt, &ps);
+                                    coin_num_salt,
+                                    &ps);
+#endif
       GNUNET_CRYPTO_eddsa_key_get_public (&ps.coin_priv.eddsa_priv,
-                                          &coin_pub);
+                                          &coin_pub.eddsa_pub);
 
       resp = GNUNET_JSON_PACK (
         GNUNET_JSON_pack_data_auto ("coin_priv", &ps.coin_priv),
@@ -211,7 +223,7 @@ run (void *cls,
       TALER_planchet_setup_refresh (&transfer_secret,
                                     coin_num_salt, &ps);
       GNUNET_CRYPTO_eddsa_key_get_public (&ps.coin_priv.eddsa_priv,
-                                          &coin_pub);
+                                          &coin_pub.eddsa_pub);
 
       resp = GNUNET_JSON_PACK (
         GNUNET_JSON_pack_data_auto ("coin_priv", &ps.coin_priv),
diff --git a/src/util/taler-exchange-secmod-rsa.c 
b/src/util/taler-exchange-secmod-rsa.c
index 2aabaddc..6bca58f8 100644
--- a/src/util/taler-exchange-secmod-rsa.c
+++ b/src/util/taler-exchange-secmod-rsa.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2020 Taler Systems SA
+  Copyright (C) 2014-2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -88,7 +88,7 @@ struct DenominationKey
   /**
    * Hash of this denomination's public key.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Time at which this key is supposed to become valid.
@@ -208,10 +208,10 @@ struct WorkItem
   struct DenominationKey *dk;
 
   /**
-   * RSA signature over @e blinded_msg using @e dk. Result of doing the
-   * work. Initially NULL.
+   * Signature over @e blinded_msg using @e dk. Result of doing the
+   * work. Initially zero.
    */
-  struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
+  struct TALER_BlindedDenominationSignature denom_sig;
 
   /**
    * Coin_ev value to sign.
@@ -424,10 +424,11 @@ sign_worker (void *cls)
                                    wi);
       work_counter--;
       GNUNET_assert (0 == pthread_mutex_unlock (&work_lock));
-      wi->rsa_signature
-        = GNUNET_CRYPTO_rsa_sign_blinded (wi->dk->denom_priv.rsa_private_key,
-                                          wi->blinded_msg,
-                                          wi->blinded_msg_size);
+      GNUNET_break (GNUNET_OK ==
+                    TALER_denom_sign_blinded (&wi->denom_sig,
+                                              &wi->dk->denom_priv,
+                                              wi->blinded_msg,
+                                              wi->blinded_msg_size));
       /* put completed work into done queue */
       GNUNET_assert (0 == pthread_mutex_lock (&done_lock));
       GNUNET_CONTAINER_DLL_insert (done_head,
@@ -494,8 +495,8 @@ static void
 free_dk (struct DenominationKey *dk)
 {
   GNUNET_free (dk->filename);
-  GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv.rsa_private_key);
-  GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub.rsa_public_key);
+  TALER_denom_priv_free (&dk->denom_priv);
+  TALER_denom_pub_free (&dk->denom_pub);
   GNUNET_free (dk);
 }
 
@@ -583,7 +584,7 @@ handle_done (void *cls)
                                  done_tail,
                                  wi);
     GNUNET_assert (0 == pthread_mutex_unlock (&done_lock));
-    if (NULL == wi->rsa_signature)
+    if (TALER_DENOMINATION_INVALID == wi->denom_sig.cipher)
     {
       struct TALER_CRYPTO_SignFailure sf = {
         .header.size = htons (sizeof (sf)),
@@ -604,10 +605,10 @@ handle_done (void *cls)
       size_t buf_size;
       size_t tsize;
 
-      buf_size = GNUNET_CRYPTO_rsa_signature_encode (wi->rsa_signature,
-                                                     &buf);
-      GNUNET_CRYPTO_rsa_signature_free (wi->rsa_signature);
-      wi->rsa_signature = NULL;
+      buf_size = GNUNET_CRYPTO_rsa_signature_encode (
+        wi->denom_sig.details.blinded_rsa_signature,
+        &buf);
+      TALER_blinded_denom_sig_free (&wi->denom_sig);
       tsize = sizeof (*sr) + buf_size;
       GNUNET_assert (tsize < UINT16_MAX);
       sr = GNUNET_malloc (tsize);
@@ -661,7 +662,7 @@ handle_sign_request (const struct sockaddr_un *addr,
   size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr);
 
   dk = GNUNET_CONTAINER_multihashmap_get (keys,
-                                          &sr->h_denom_pub);
+                                          &sr->h_denom_pub.hash);
   if (NULL == dk)
   {
     struct TALER_CRYPTO_SignFailure sf = {
@@ -672,7 +673,7 @@ handle_sign_request (const struct sockaddr_un *addr,
 
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Signing request failed, denomination key %s unknown\n",
-                GNUNET_h2s (&sr->h_denom_pub));
+                GNUNET_h2s (&sr->h_denom_pub.hash));
     (void) transmit (addr,
                      addr_size,
                      &sf.header);
@@ -690,7 +691,7 @@ handle_sign_request (const struct sockaddr_un *addr,
 
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Signing request failed, denomination key %s is not yet 
valid\n",
-                GNUNET_h2s (&sr->h_denom_pub));
+                GNUNET_h2s (&sr->h_denom_pub.hash));
     (void) transmit (addr,
                      addr_size,
                      &sf.header);
@@ -700,7 +701,7 @@ handle_sign_request (const struct sockaddr_un *addr,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Received request to sign over %u bytes with key %s\n",
               (unsigned int) blinded_msg_size,
-              GNUNET_h2s (&sr->h_denom_pub));
+              GNUNET_h2s (&sr->h_denom_pub.hash));
   wi = GNUNET_new (struct WorkItem);
   wi->addr = *addr;
   wi->addr_size = addr_size;
@@ -726,7 +727,7 @@ handle_sign_request (const struct sockaddr_un *addr,
  * @param dk the key to notify @a client about
  * @return #GNUNET_OK on success
  */
-static int
+static enum GNUNET_GenericReturnValue
 notify_client_dk_add (struct Client *client,
                       const struct DenominationKey *dk)
 {
@@ -738,8 +739,9 @@ notify_client_dk_add (struct Client *client,
   void *p;
   size_t tlen;
 
-  buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dk->denom_pub.rsa_public_key,
-                                                 &buf);
+  buf_len = GNUNET_CRYPTO_rsa_public_key_encode (
+    dk->denom_pub.details.rsa_public_key,
+    &buf);
   GNUNET_assert (buf_len < UINT16_MAX);
   GNUNET_assert (nlen < UINT16_MAX);
   tlen = buf_len + nlen + sizeof (*an);
@@ -751,12 +753,12 @@ notify_client_dk_add (struct Client *client,
   an->section_name_len = htons ((uint16_t) nlen);
   an->anchor_time = GNUNET_TIME_absolute_hton (dk->anchor);
   an->duration_withdraw = GNUNET_TIME_relative_hton (denom->duration_withdraw);
-  TALER_exchange_secmod_rsa_sign (&dk->h_denom_pub,
-                                  denom->section,
-                                  dk->anchor,
-                                  denom->duration_withdraw,
-                                  &smpriv,
-                                  &an->secm_sig);
+  TALER_exchange_secmod_denom_sign (&dk->h_denom_pub,
+                                    denom->section,
+                                    dk->anchor,
+                                    denom->duration_withdraw,
+                                    &smpriv,
+                                    &an->secm_sig);
   an->secm_pub = smpub;
   p = (void *) &an[1];
   memcpy (p,
@@ -767,11 +769,11 @@ notify_client_dk_add (struct Client *client,
           denom->section,
           nlen);
   {
-    int ret = GNUNET_OK;
+    enum GNUNET_GenericReturnValue ret = GNUNET_OK;
 
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Sending RSA denomination key %s (%s)\n",
-                GNUNET_h2s (&dk->h_denom_pub),
+                GNUNET_h2s (&dk->h_denom_pub.hash),
                 denom->section);
     if (GNUNET_OK !=
         transmit (&client->addr,
@@ -809,7 +811,7 @@ notify_client_dk_del (struct Client *client,
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Sending RSA denomination expiration %s\n",
-              GNUNET_h2s (&dk->h_denom_pub));
+              GNUNET_h2s (&dk->h_denom_pub.hash));
   if (GNUNET_OK !=
       transmit (&client->addr,
                 client->addr_size,
@@ -837,30 +839,26 @@ setup_key (struct DenominationKey *dk,
            struct DenominationKey *position)
 {
   struct Denomination *denom = dk->denom;
-  struct GNUNET_CRYPTO_RsaPrivateKey *priv;
-  struct GNUNET_CRYPTO_RsaPublicKey *pub;
+  struct TALER_DenominationPrivateKey priv;
+  struct TALER_DenominationPublicKey pub;
   size_t buf_size;
   void *buf;
 
-  priv = GNUNET_CRYPTO_rsa_private_key_create (denom->rsa_keysize);
-  if (NULL == priv)
+  if (GNUNET_OK !=
+      TALER_denom_priv_create (&priv,
+                               &pub,
+                               TALER_DENOMINATION_RSA,
+                               (unsigned int) denom->rsa_keysize))
   {
     GNUNET_break (0);
     GNUNET_SCHEDULER_shutdown ();
     global_ret = 40;
     return GNUNET_SYSERR;
   }
-  pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
-  if (NULL == pub)
-  {
-    GNUNET_break (0);
-    GNUNET_CRYPTO_rsa_private_key_free (priv);
-    return GNUNET_SYSERR;
-  }
-  buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
+  buf_size = GNUNET_CRYPTO_rsa_private_key_encode 
(priv.details.rsa_private_key,
                                                    &buf);
-  GNUNET_CRYPTO_rsa_public_key_hash (pub,
-                                     &dk->h_denom_pub);
+  TALER_denom_pub_hash (&pub,
+                        &dk->h_denom_pub);
   GNUNET_asprintf (&dk->filename,
                    "%s/%s/%llu",
                    keydir,
@@ -877,30 +875,30 @@ setup_key (struct DenominationKey *dk,
                               "write",
                               dk->filename);
     GNUNET_free (buf);
-    GNUNET_CRYPTO_rsa_private_key_free (priv);
-    GNUNET_CRYPTO_rsa_public_key_free (pub);
+    TALER_denom_priv_free (&priv);
+    TALER_denom_pub_free (&pub);
     return GNUNET_SYSERR;
   }
   GNUNET_free (buf);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Setup fresh private key %s at %s in `%s'\n",
-              GNUNET_h2s (&dk->h_denom_pub),
+              GNUNET_h2s (&dk->h_denom_pub.hash),
               GNUNET_STRINGS_absolute_time_to_string (dk->anchor),
               dk->filename);
-  dk->denom_priv.rsa_private_key = priv;
-  dk->denom_pub.rsa_public_key = pub;
+  dk->denom_priv = priv;
+  dk->denom_pub = pub;
 
   if (GNUNET_OK !=
       GNUNET_CONTAINER_multihashmap_put (
         keys,
-        &dk->h_denom_pub,
+        &dk->h_denom_pub.hash,
         dk,
         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Duplicate private key created! Terminating.\n");
-    GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv.rsa_private_key);
-    GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub.rsa_public_key);
+    TALER_denom_priv_free (&dk->denom_priv);
+    TALER_denom_pub_free (&dk->denom_pub);
     GNUNET_free (dk->filename);
     GNUNET_free (dk);
     return GNUNET_SYSERR;
@@ -951,12 +949,12 @@ handle_revoke_request (const struct sockaddr_un *addr,
   struct Denomination *denom;
 
   dk = GNUNET_CONTAINER_multihashmap_get (keys,
-                                          &rr->h_denom_pub);
+                                          &rr->h_denom_pub.hash);
   if (NULL == dk)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Revocation request ignored, denomination key %s unknown\n",
-                GNUNET_h2s (&rr->h_denom_pub));
+                GNUNET_h2s (&rr->h_denom_pub.hash));
     return;
   }
 
@@ -985,14 +983,14 @@ handle_revoke_request (const struct sockaddr_un *addr,
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONTAINER_multihashmap_remove (
                    keys,
-                   &dk->h_denom_pub,
+                   &dk->h_denom_pub.hash,
                    dk));
   GNUNET_CONTAINER_DLL_remove (denom->keys_head,
                                denom->keys_tail,
                                dk);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Revocation of denomination key %s complete\n",
-              GNUNET_h2s (&rr->h_denom_pub));
+              GNUNET_h2s (&rr->h_denom_pub.hash));
 
   /* Tell clients this key is gone */
   {
@@ -1240,7 +1238,7 @@ purge_key (struct DenominationKey *dk)
                                dk);
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONTAINER_multihashmap_remove (keys,
-                                                       &dk->h_denom_pub,
+                                                       &dk->h_denom_pub.hash,
                                                        dk));
   if (0 != unlink (dk->filename))
   {
@@ -1261,7 +1259,7 @@ purge_key (struct DenominationKey *dk)
     dk->purge = true;
     return;
   }
-  GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv.rsa_private_key);
+  TALER_denom_priv_free (&dk->denom_priv);
   GNUNET_free (dk);
 }
 
@@ -1372,7 +1370,7 @@ parse_key (struct Denomination *denom,
            const void *buf,
            size_t buf_size)
 {
-  struct GNUNET_CRYPTO_RsaPrivateKey *priv;
+  struct TALER_DenominationPrivateKey priv;
   char *anchor_s;
   char dummy;
   unsigned long long anchor_ll;
@@ -1407,9 +1405,11 @@ parse_key (struct Denomination *denom,
                 filename);
     return;
   }
-  priv = GNUNET_CRYPTO_rsa_private_key_decode (buf,
-                                               buf_size);
-  if (NULL == priv)
+  priv.cipher = TALER_DENOMINATION_RSA;
+  priv.details.rsa_private_key
+    = GNUNET_CRYPTO_rsa_private_key_decode (buf,
+                                            buf_size);
+  if (NULL == priv.details.rsa_private_key)
   {
     /* Parser failure. */
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1419,38 +1419,34 @@ parse_key (struct Denomination *denom,
   }
 
   {
-    struct GNUNET_CRYPTO_RsaPublicKey *pub;
+    struct TALER_DenominationPublicKey pub;
     struct DenominationKey *dk;
     struct DenominationKey *before;
 
-    pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
-    if (NULL == pub)
-    {
-      GNUNET_break (0);
-      GNUNET_CRYPTO_rsa_private_key_free (priv);
-      return;
-    }
+    TALER_denom_priv_to_pub (&priv,
+                             (struct TALER_AgeMask) { .mask = 0 }, /* 
FIXME-Oec */
+                             &pub);
     dk = GNUNET_new (struct DenominationKey);
-    dk->denom_priv.rsa_private_key = priv;
+    dk->denom_priv = priv;
     dk->denom = denom;
     dk->anchor = anchor;
     dk->filename = GNUNET_strdup (filename);
-    GNUNET_CRYPTO_rsa_public_key_hash (pub,
-                                       &dk->h_denom_pub);
-    dk->denom_pub.rsa_public_key = pub;
+    TALER_denom_pub_hash (&pub,
+                          &dk->h_denom_pub);
+    dk->denom_pub = pub;
     if (GNUNET_OK !=
         GNUNET_CONTAINER_multihashmap_put (
           keys,
-          &dk->h_denom_pub,
+          &dk->h_denom_pub.hash,
           dk,
           GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Duplicate private key %s detected in file `%s'. 
Skipping.\n",
-                  GNUNET_h2s (&dk->h_denom_pub),
+                  GNUNET_h2s (&dk->h_denom_pub.hash),
                   filename);
-      GNUNET_CRYPTO_rsa_private_key_free (priv);
-      GNUNET_CRYPTO_rsa_public_key_free (pub);
+      TALER_denom_priv_free (&priv);
+      TALER_denom_pub_free (&pub);
       GNUNET_free (dk);
       return;
     }
@@ -1469,7 +1465,7 @@ parse_key (struct Denomination *denom,
                                        dk);
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Imported key %s from `%s'\n",
-                GNUNET_h2s (&dk->h_denom_pub),
+                GNUNET_h2s (&dk->h_denom_pub.hash),
                 filename);
   }
 }
diff --git a/src/util/taler-exchange-secmod-rsa.h 
b/src/util/taler-exchange-secmod-rsa.h
index 146b6948..cf439e26 100644
--- a/src/util/taler-exchange-secmod-rsa.h
+++ b/src/util/taler-exchange-secmod-rsa.h
@@ -102,7 +102,7 @@ struct TALER_CRYPTO_RsaKeyPurgeNotification
   /**
    * Hash of the public key of the purged RSA key.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
 };
 
@@ -125,7 +125,7 @@ struct TALER_CRYPTO_SignRequest
   /**
    * Hash of the public key of the RSA key to use for the signature.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /* followed by message to sign */
 };
@@ -149,7 +149,7 @@ struct TALER_CRYPTO_RevokeRequest
   /**
    * Hash of the public key of the revoked RSA key.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
 };
 
diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c
index 27e48b9e..5ee06487 100644
--- a/src/util/test_crypto.c
+++ b/src/util/test_crypto.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2015, 2020 Taler Systems SA
+  (C) 2015, 2020, 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -88,39 +88,42 @@ test_planchets (void)
   struct TALER_DenominationPrivateKey dk_priv;
   struct TALER_DenominationPublicKey dk_pub;
   struct TALER_PlanchetDetail pd;
-  struct GNUNET_CRYPTO_RsaSignature *blind_sig;
+  struct TALER_BlindedDenominationSignature blind_sig;
   struct TALER_FreshCoin coin;
-  struct GNUNET_HashCode c_hash;
+  struct TALER_CoinPubHash c_hash;
 
-  dk_priv.rsa_private_key = GNUNET_CRYPTO_rsa_private_key_create (1024);
-  dk_pub.rsa_public_key = GNUNET_CRYPTO_rsa_private_key_get_public (
-    dk_priv.rsa_private_key);
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_denom_priv_create (&dk_priv,
+                                          &dk_pub,
+                                          TALER_DENOMINATION_RSA,
+                                          1024));
   TALER_planchet_setup_random (&ps);
   GNUNET_assert (GNUNET_OK ==
                  TALER_planchet_prepare (&dk_pub,
                                          &ps,
                                          &c_hash,
                                          &pd));
-  blind_sig = GNUNET_CRYPTO_rsa_sign_blinded (dk_priv.rsa_private_key,
-                                              pd.coin_ev,
-                                              pd.coin_ev_size);
-  GNUNET_assert (NULL != blind_sig);
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_denom_sign_blinded (&blind_sig,
+                                           &dk_priv,
+                                           pd.coin_ev,
+                                           pd.coin_ev_size));
   GNUNET_assert (GNUNET_OK ==
                  TALER_planchet_to_coin (&dk_pub,
-                                         blind_sig,
+                                         &blind_sig,
                                          &ps,
                                          &c_hash,
                                          &coin));
-  GNUNET_CRYPTO_rsa_signature_free (blind_sig);
-  GNUNET_CRYPTO_rsa_signature_free (coin.sig.rsa_signature);
-  GNUNET_CRYPTO_rsa_private_key_free (dk_priv.rsa_private_key);
-  GNUNET_CRYPTO_rsa_public_key_free (dk_pub.rsa_public_key);
+  TALER_blinded_denom_sig_free (&blind_sig);
+  TALER_denom_sig_free (&coin.sig);
+  TALER_denom_priv_free (&dk_priv);
+  TALER_denom_pub_free (&dk_pub);
   return 0;
 }
 
 
 static int
-test_exchange_sigs ()
+test_exchange_sigs (void)
 {
   const char *pt = "payto://x-taler-bank/localhost/Account";
   struct TALER_MasterPrivateKeyP priv;
@@ -155,7 +158,7 @@ test_exchange_sigs ()
 
 
 static int
-test_merchant_sigs ()
+test_merchant_sigs (void)
 {
   const char *pt = "payto://x-taler-bank/localhost/Account";
   struct TALER_WireSalt salt;
diff --git a/src/util/test_helper_eddsa.conf b/src/util/test_helper_eddsa.conf
index 321fa7cc..8fe119c4 100644
--- a/src/util/test_helper_eddsa.conf
+++ b/src/util/test_helper_eddsa.conf
@@ -4,6 +4,7 @@ TALER_TEST_HOME = test_helper_eddsa_home/
 TALER_RUNTIME_DIR = ${TMPDIR:-/tmp}/${USER}/test_helper_eddsa/
 
 [taler-exchange-secmod-eddsa]
+CLIENT_DIR = $TALER_RUNTIME_DIR
 LOOKAHEAD_SIGN = 5 minutes
 OVERLAP_DURATION = 1 s
 DURATION = 1 minute
diff --git a/src/util/test_helper_rsa.c b/src/util/test_helper_rsa.c
index 7011afb2..e4c0bf6f 100644
--- a/src/util/test_helper_rsa.c
+++ b/src/util/test_helper_rsa.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2020 Taler Systems SA
+  (C) 2020, 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -62,7 +62,7 @@ struct KeyData
   /**
    * Hash of the public key.
    */
-  struct GNUNET_HashCode h_denom_pub;
+  struct TALER_DenominationHash h_denom_pub;
 
   /**
    * Full public key.
@@ -110,7 +110,7 @@ key_cb (void *cls,
         const char *section_name,
         struct GNUNET_TIME_Absolute start_time,
         struct GNUNET_TIME_Relative validity_duration,
-        const struct GNUNET_HashCode *h_denom_pub,
+        const struct TALER_DenominationHash *h_denom_pub,
         const struct TALER_DenominationPublicKey *denom_pub,
         const struct TALER_SecurityModulePublicKeyP *sm_pub,
         const struct TALER_SecurityModuleSignatureP *sm_sig)
@@ -119,7 +119,7 @@ key_cb (void *cls,
   (void) sm_sig;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Key notification about key %s in `%s'\n",
-              GNUNET_h2s (h_denom_pub),
+              GNUNET_h2s (&h_denom_pub->hash),
               section_name);
   if (0 == validity_duration.rel_value_us)
   {
@@ -133,8 +133,7 @@ key_cb (void *cls,
       {
         keys[i].valid = false;
         keys[i].revoked = false;
-        GNUNET_CRYPTO_rsa_public_key_free (keys[i].denom_pub.rsa_public_key);
-        keys[i].denom_pub.rsa_public_key = NULL;
+        TALER_denom_pub_free (&keys[i].denom_pub);
         GNUNET_assert (num_keys > 0);
         num_keys--;
         found = true;
@@ -155,8 +154,9 @@ key_cb (void *cls,
       keys[i].h_denom_pub = *h_denom_pub;
       keys[i].start_time = start_time;
       keys[i].validity_duration = validity_duration;
-      keys[i].denom_pub.rsa_public_key
-        = GNUNET_CRYPTO_rsa_public_key_dup (denom_pub->rsa_public_key);
+      keys[i].denom_pub = *denom_pub;
+      TALER_denom_pub_deep_copy (&keys[i].denom_pub,
+                                 denom_pub);
       num_keys++;
       return;
     }
@@ -199,7 +199,7 @@ test_revocation (struct TALER_CRYPTO_DenominationHelper *dh)
       keys[j].revoked = true;
       fprintf (stderr,
                "Revoking key %s ...",
-               GNUNET_h2s (&keys[j].h_denom_pub));
+               GNUNET_h2s (&keys[j].h_denom_pub.hash));
       TALER_CRYPTO_helper_denom_revoke (dh,
                                         &keys[j].h_denom_pub);
       for (unsigned int k = 0; k<1000; k++)
@@ -235,42 +235,35 @@ test_revocation (struct TALER_CRYPTO_DenominationHelper 
*dh)
 static int
 test_signing (struct TALER_CRYPTO_DenominationHelper *dh)
 {
-  struct TALER_DenominationSignature ds;
+  struct TALER_BlindedDenominationSignature ds;
   enum TALER_ErrorCode ec;
   bool success = false;
-  struct GNUNET_HashCode m_hash;
-  struct GNUNET_CRYPTO_RsaBlindingKeySecret bks;
-
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
-                              &bks,
-                              sizeof (bks));
-  GNUNET_CRYPTO_hash ("Hello",
-                      strlen ("Hello"),
-                      &m_hash);
+  struct TALER_PlanchetSecretsP ps;
+  struct TALER_CoinPubHash c_hash;
+
+  TALER_planchet_setup_random (&ps);
   for (unsigned int i = 0; i<MAX_KEYS; i++)
   {
     if (! keys[i].valid)
       continue;
     {
-      void *buf;
-      size_t buf_size;
+      struct TALER_PlanchetDetail pd;
 
       GNUNET_assert (GNUNET_YES ==
-                     TALER_rsa_blind (&m_hash,
-                                      &bks,
-                                      keys[i].denom_pub.rsa_public_key,
-                                      &buf,
-                                      &buf_size));
+                     TALER_planchet_prepare (&keys[i].denom_pub,
+                                             &ps,
+                                             &c_hash,
+                                             &pd));
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                   "Requesting signature over %u bytes with key %s\n",
-                  (unsigned int) buf_size,
-                  GNUNET_h2s (&keys[i].h_denom_pub));
+                  (unsigned int) pd.coin_ev_size,
+                  GNUNET_h2s (&keys[i].h_denom_pub.hash));
       ds = TALER_CRYPTO_helper_denom_sign (dh,
                                            &keys[i].h_denom_pub,
-                                           buf,
-                                           buf_size,
+                                           pd.coin_ev,
+                                           pd.coin_ev_size,
                                            &ec);
-      GNUNET_free (buf);
+      GNUNET_free (pd.coin_ev);
     }
     switch (ec)
     {
@@ -290,32 +283,33 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh)
         return 5;
       }
       {
-        struct GNUNET_CRYPTO_RsaSignature *rs;
+        struct TALER_DenominationSignature rs;
 
-        rs = TALER_rsa_unblind (ds.rsa_signature,
-                                &bks,
-                                keys[i].denom_pub.rsa_public_key);
-        if (NULL == rs)
+        if (GNUNET_OK !=
+            TALER_denom_sig_unblind (&rs,
+                                     &ds,
+                                     &ps.blinding_key,
+                                     &keys[i].denom_pub))
         {
           GNUNET_break (0);
           return 6;
         }
-        GNUNET_CRYPTO_rsa_signature_free (ds.rsa_signature);
+        TALER_blinded_denom_sig_free (&ds);
         if (GNUNET_OK !=
-            GNUNET_CRYPTO_rsa_verify (&m_hash,
-                                      rs,
-                                      keys[i].denom_pub.rsa_public_key))
+            TALER_denom_pub_verify (&keys[i].denom_pub,
+                                    &rs,
+                                    &c_hash))
         {
           /* signature invalid */
           GNUNET_break (0);
-          GNUNET_CRYPTO_rsa_signature_free (rs);
+          TALER_denom_sig_free (&rs);
           return 7;
         }
-        GNUNET_CRYPTO_rsa_signature_free (rs);
+        TALER_denom_sig_free (&rs);
       }
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                   "Received valid signature for key %s\n",
-                  GNUNET_h2s (&keys[i].h_denom_pub));
+                  GNUNET_h2s (&keys[i].h_denom_pub.hash));
       success = true;
       break;
     case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
@@ -350,7 +344,7 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh)
 
   /* check signing does not work if the key is unknown */
   {
-    struct GNUNET_HashCode rnd;
+    struct TALER_DenominationHash rnd;
 
     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                                 &rnd,
@@ -367,7 +361,7 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh)
     }
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Signing with invalid key %s failed as desired\n",
-                GNUNET_h2s (&rnd));
+                GNUNET_h2s (&rnd.hash));
   }
   return 0;
 }
@@ -382,18 +376,12 @@ test_signing (struct TALER_CRYPTO_DenominationHelper *dh)
 static int
 perf_signing (struct TALER_CRYPTO_DenominationHelper *dh)
 {
-  struct TALER_DenominationSignature ds;
+  struct TALER_BlindedDenominationSignature ds;
   enum TALER_ErrorCode ec;
-  struct GNUNET_HashCode m_hash;
-  struct GNUNET_CRYPTO_RsaBlindingKeySecret bks;
   struct GNUNET_TIME_Relative duration;
+  struct TALER_PlanchetSecretsP ps;
 
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
-                              &bks,
-                              sizeof (bks));
-  GNUNET_CRYPTO_hash ("Hello",
-                      strlen ("Hello"),
-                      &m_hash);
+  TALER_planchet_setup_random (&ps);
   duration = GNUNET_TIME_UNIT_ZERO;
   for (unsigned int j = 0; j<NUM_SIGN_TESTS;)
   {
@@ -409,15 +397,14 @@ perf_signing (struct TALER_CRYPTO_DenominationHelper *dh)
           keys[i].validity_duration.rel_value_us)
         continue;
       {
-        void *buf;
-        size_t buf_size;
+        struct TALER_CoinPubHash c_hash;
+        struct TALER_PlanchetDetail pd;
 
         GNUNET_assert (GNUNET_YES ==
-                       TALER_rsa_blind (&m_hash,
-                                        &bks,
-                                        keys[i].denom_pub.rsa_public_key,
-                                        &buf,
-                                        &buf_size));
+                       TALER_planchet_prepare (&keys[i].denom_pub,
+                                               &ps,
+                                               &c_hash,
+                                               &pd));
         /* use this key as long as it works */
         while (1)
         {
@@ -426,20 +413,20 @@ perf_signing (struct TALER_CRYPTO_DenominationHelper *dh)
 
           ds = TALER_CRYPTO_helper_denom_sign (dh,
                                                &keys[i].h_denom_pub,
-                                               buf,
-                                               buf_size,
+                                               pd.coin_ev,
+                                               pd.coin_ev_size,
                                                &ec);
           if (TALER_EC_NONE != ec)
             break;
           delay = GNUNET_TIME_absolute_get_duration (start);
           duration = GNUNET_TIME_relative_add (duration,
                                                delay);
-          GNUNET_CRYPTO_rsa_signature_free (ds.rsa_signature);
+          TALER_blinded_denom_sig_free (&ds);
           j++;
           if (NUM_SIGN_TESTS == j)
             break;
         }
-        GNUNET_free (buf);
+        GNUNET_free (pd.coin_ev);
       }
     } /* for i */
   } /* for j */
@@ -526,8 +513,7 @@ run_test (void)
   for (unsigned int i = 0; i<MAX_KEYS; i++)
     if (keys[i].valid)
     {
-      GNUNET_CRYPTO_rsa_public_key_free (keys[i].denom_pub.rsa_public_key);
-      keys[i].denom_pub.rsa_public_key = NULL;
+      TALER_denom_pub_free (&keys[i].denom_pub);
       GNUNET_assert (num_keys > 0);
       num_keys--;
     }
diff --git a/src/util/wallet_signatures.c b/src/util/wallet_signatures.c
index 1916740c..8700d4a8 100644
--- a/src/util/wallet_signatures.c
+++ b/src/util/wallet_signatures.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2020 Taler Systems SA
+  Copyright (C) 2021 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -14,8 +14,8 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file secmod_signatures.c
- * @brief Utility functions for Taler security module signatures
+ * @file wallet_signatures.c
+ * @brief Utility functions for Taler wallet signatures
  * @author Christian Grothoff
  */
 #include "platform.h"
@@ -24,7 +24,92 @@
 
 
 void
-TALER_wallet_link_sign (const struct GNUNET_HashCode *h_denom_pub,
+TALER_wallet_deposit_sign (
+  const struct TALER_Amount *amount,
+  const struct TALER_Amount *deposit_fee,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const struct TALER_ExtensionContractHash *h_extensions,
+  const struct TALER_DenominationHash *h_denom_pub,
+  struct GNUNET_TIME_Absolute wallet_timestamp,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  struct GNUNET_TIME_Absolute refund_deadline,
+  const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+  struct TALER_CoinSpendSignatureP *coin_sig)
+{
+  struct TALER_DepositRequestPS dr = {
+    .purpose.size = htonl (sizeof (dr)),
+    .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
+    .h_contract_terms = *h_contract_terms,
+    .h_wire = *h_wire,
+    .h_denom_pub = *h_denom_pub,
+    .wallet_timestamp = GNUNET_TIME_absolute_hton (wallet_timestamp),
+    .refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
+    .merchant = *merchant_pub
+  };
+
+  if (NULL != h_extensions)
+    dr.h_extensions = *h_extensions;
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_TIME_round_abs (&wallet_timestamp));
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_TIME_round_abs (&refund_deadline));
+  TALER_amount_hton (&dr.amount_with_fee,
+                     amount);
+  TALER_amount_hton (&dr.deposit_fee,
+                     deposit_fee);
+  GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
+                            &dr,
+                            &coin_sig->eddsa_signature);
+}
+
+
+enum GNUNET_GenericReturnValue
+TALER_wallet_deposit_verify (
+  const struct TALER_Amount *amount,
+  const struct TALER_Amount *deposit_fee,
+  const struct TALER_MerchantWireHash *h_wire,
+  const struct TALER_PrivateContractHash *h_contract_terms,
+  const struct TALER_ExtensionContractHash *h_extensions,
+  const struct TALER_DenominationHash *h_denom_pub,
+  struct GNUNET_TIME_Absolute wallet_timestamp,
+  const struct TALER_MerchantPublicKeyP *merchant_pub,
+  struct GNUNET_TIME_Absolute refund_deadline,
+  const struct TALER_CoinSpendPublicKeyP *coin_pub,
+  const struct TALER_CoinSpendSignatureP *coin_sig)
+{
+  struct TALER_DepositRequestPS dr = {
+    .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
+    .purpose.size = htonl (sizeof (dr)),
+    .h_contract_terms = *h_contract_terms,
+    .h_wire = *h_wire,
+    .h_denom_pub = *h_denom_pub,
+    .wallet_timestamp = GNUNET_TIME_absolute_hton (wallet_timestamp),
+    .refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
+    .merchant = *merchant_pub
+  };
+
+  if (NULL != h_extensions)
+    dr.h_extensions = *h_extensions;
+  TALER_amount_hton (&dr.amount_with_fee,
+                     amount);
+  TALER_amount_hton (&dr.deposit_fee,
+                     deposit_fee);
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
+                                  &dr,
+                                  &coin_sig->eddsa_signature,
+                                  &coin_pub->eddsa_pub))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+void
+TALER_wallet_link_sign (const struct TALER_DenominationHash *h_denom_pub,
                         const struct TALER_TransferPublicKeyP *transfer_pub,
                         const void *coin_ev,
                         size_t coin_ev_size,
@@ -40,7 +125,7 @@ TALER_wallet_link_sign (const struct GNUNET_HashCode 
*h_denom_pub,
 
   GNUNET_CRYPTO_hash (coin_ev,
                       coin_ev_size,
-                      &ldp.coin_envelope_hash);
+                      &ldp.coin_envelope_hash.hash);
   GNUNET_CRYPTO_eddsa_sign (&old_coin_priv->eddsa_priv,
                             &ldp,
                             &coin_sig->eddsa_signature);
@@ -49,7 +134,7 @@ TALER_wallet_link_sign (const struct GNUNET_HashCode 
*h_denom_pub,
 
 enum GNUNET_GenericReturnValue
 TALER_wallet_link_verify (
-  const struct GNUNET_HashCode *h_denom_pub,
+  const struct TALER_DenominationHash *h_denom_pub,
   const struct TALER_TransferPublicKeyP *transfer_pub,
   const void *coin_ev,
   size_t coin_ev_size,
@@ -65,7 +150,7 @@ TALER_wallet_link_verify (
 
   GNUNET_CRYPTO_hash (coin_ev,
                       coin_ev_size,
-                      &ldp.coin_envelope_hash);
+                      &ldp.coin_envelope_hash.hash);
   return
     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_LINK,
                                 &ldp,

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