gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-merchant] branch stable updated (73d9a89 -> 64929e2)


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant] branch stable updated (73d9a89 -> 64929e2)
Date: Wed, 31 May 2017 17:14:16 +0200

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

marcello pushed a change to branch stable
in repository merchant.

    from 73d9a89  Restoring the macro-based way of passing values to payments 
generator.
     add eec82c7  README.
     add d0ffaaf  Calling the function (still a stub) that works out wire 
transfers tracks before returning that to the frontend.
     add 7307067  Rough logic for summing up all tracked wire transfers gotten 
from the exchange, grouping them by proposal's hash.
     add 388a27e  TODO comments.
     add 52eef77  Summing up deposited amounts *and* deposit fees concerning 
tracked transfers, building the response; not tested yet.
     add a093c87  json_copy-ing a 'const json_t *' in order to call 
'json_object_del()' on its copy.
     add 561deba  Fix track transfer's response + adjusting tests to it.
     add 4187846  Elaborating /track/transfer response for cached responses as 
well.
     add a42bfbd  Returining order_id in place of h_proposal_data among tracked 
transfers.
     add 4db9844  \#4593.
     add 5479efa  Porting to new getopt API.
     add c7d8e10  helper db methods for /history. Prepared statements have 
still problems with 'FETCH FIRST'.. To be fixed.
     add 1c7e486  Fix compiler warnings.
     add 325db61  FETCH FIRST arg ROW ONLY -> LIMIT arg, in prepared statement, 
as postgresql doesn't like FETCH FIRST arg when arg is a $-parameter. DB 
testcase does not pass yet, logic is likely to be wrong.
     add bcde0fa  Fix indentation.
     add 3ea60fb  fix limit binding
     add 2e761cd  Fix db testcase against newest plugin.
     add b8f25a0  Fix lib testcase.
     add b6f8454  'start' and 'nrows' not hardcoded anymore in testcase.
     add ab7b69e  Removing unneeded configs and dirs.
     add 5499f44  Passing values to payments generator via config file.
     add 67b6b66  Fix getopt memory issue, actually use values from config file.
     add 2dc9f49  Adding function that concatenates amount strings. Needed as 
payment generator now reads currency dynamically.
     add 0deb49a  Fixing remaining problems due to the passing of values from 
config file, in the payments generator. Namely, the command list was statically 
created, so it was necessary to make it dynamic.
     add 3a8a5ca  Iterating interpreter commands, according to -n option passed 
in CLI.
     add 5f35f8c  Produce random order_id.
     add f4f6c3a  README on payments generator.
     add fef322c  date parameter = now when /history doesn't get one.
     add 4073fec  Fix #4968.
     add 62a1f25  Fix signature of db callback.
     add 8a5af34  Fix #4970.
     add 20a5731  logging, db minor fix
     add f88bad9  fix stale index used by /history
     add dba1103  renaming GNUNET_GETOPT-symbols to match latest changes in 
GNUnet
     add 6970f52  indent
     add 061fcf3  README
     add c6e834b  adding option to use a remote exchange in the payments 
generator.
     add ab7198d  renaming variables
     add 48de114  stubs for #4781
     add e23a4e4  adding chapter about testing the backend
     add d021087  warn the reader on having the instance's bank matching the 
exchange's when testing.
     add a90e2d2  fix command name
     add 3e753ff  fix segfaults due to use of remote exchange in payment 
generator.
     add 19b8436  Still on renaming (#4877)
     add 8808d12  Still on #4877
     add a1ee058  addressing comment 11995 from #4774
     add 21b5a19  fix config file for /lib testcase
     add b783ce9  adding option to lookup history entries in the future.
     add c5cad65  adding db method to query proposal data "in the future"
     add 9cfcd98  fix db testcase due to queries in the future
     add 7c083aa  debug prints
     add 6d354ee  indent
     add 1439a4f  launch run() with GNUNET_PROGRAM_run
     add 002bae7  fix compilation due to code move
     add 70765db  fix segfaults caused by the way the payment generator killed 
merchants and exchanges.
     add c834ea4  add cherry-pick like query used in /history.  This API is 
used when the backoffice user enters the exact order id into the form.
     add 87eef0b  Implement #4995
     add 06b7294  specify exchange with '-e' at payments generator
     add b61e1dc  instructions about generating payments against a non-forked 
merchant backend
     add 0d201c9  add wire_method to proposal terms
     add a489a58  mitm proxies request using the same method used by the client.
     add 02d53e6  renaming mitm script
     add 3f382cb  still renaming scripts
     add d17145e  reverting renamings
     add 8a4eebe  mitm standalone takes cli args
     add 5640684  add mitm wsgi file
     add b6690e0  readme
     add 93a4088  autoconf
     add aa18b6e  installing mitm via makefile
     add 466dcea  add forgotten file
     add c423101  NOT using setuptools' "scripts" keyword as it failed to set 
execution permissions on deployed files
     add b49aadf  missing __init__.py
     add 6fa1d31  remove comment
     add 0217dad  returning all the headers that the mitm got from the 
exchange.  This copies the "server" headers though. Wise?
     add ee0fb92  The mitm do NOT copy header Content-Lenght and Server into 
the response; it used to return ill-formed JSONs.
     add 9b44e57  make_response() called in one place
     add 2607c61  remove useless comment
     add dfc0e82  Addressing #4877
     add e1050dc  payments generator takes exchange's admin uri in config
     add 0b56f7b  skeleton for /keys perturbating mitm function
     add 286d238  pacify 'make check' into the mitm subdir
     add f7aeef2  cosmetics
     add c9caf31  config sections for wire plugins changed, adjusting
     add 60fb29c  caveats to run the payments generator
     add 2af84a1  fix format string issue
     add d3f0593  fix make clean target
     add 6da3f7f  nicely handle error from json_dumps without assert
     add 18aa807  fix 'lib' testcase
     add a16bc8a  undoing last commit
     add 59a2609  fix logic to check auditors of denomination keys
     add 1ccb472  log properly which auditors are loaded, fix log level
     add fc0f287  log properly which auditors are loaded, fix log level -- fix 
FTBFS
     add 46c5449  fix style issues
     add c1ead02  fix style issue
     add 61e31b9  fix style issue
     add b50bb3a  moving all the tools in one place
     add 005d790  nicer logging
     add 6004b80  fix FIXME on properly terminating MHD, resuming suspended 
connections before stopping the HTTPD
     add 0390a22  fix #5008
     add bf9ba97  fix whitespace
     add 777ad72  fix autoconf
     add 2f3564b  use demo instead of test, as test is sometimes down
     add a0536b3  rename proposal_data to contract_terms (see #4879)
     add 1d3c450  configuration subsection in manual
     add 7a62a58  fix doc compilation error
     add 64929e2  fix doc compilartion warning

No new revisions were added by this update.

Summary of changes:
 .gitignore                                         |   1 +
 configure.ac                                       |   6 +-
 doc/Makefile.am                                    |   2 +-
 doc/manual.texi                                    | 181 +++++-
 doc/version.texi                                   |   4 +-
 src/Makefile.am                                    |   2 +-
 src/backend/taler-merchant-httpd.c                 |  19 +-
 src/backend/taler-merchant-httpd_auditors.c        |  37 +-
 src/backend/taler-merchant-httpd_exchanges.c       |  14 +-
 src/backend/taler-merchant-httpd_history.c         | 136 ++--
 src/backend/taler-merchant-httpd_pay.c             | 261 +++++---
 src/backend/taler-merchant-httpd_pay.h             |  11 +-
 src/backend/taler-merchant-httpd_proposal.c        |  16 +-
 .../taler-merchant-httpd_track-transaction.c       |  45 +-
 src/backend/taler-merchant-httpd_track-transfer.c  | 225 ++++++-
 src/backenddb/plugin_merchantdb_postgres.c         | 500 +++++++++++----
 src/backenddb/test_merchantdb.c                    | 120 +++-
 src/include/taler_merchant_service.h               |  42 +-
 src/include/taler_merchantdb_plugin.h              | 176 +++--
 src/lib/merchant_api_history.c                     |   5 +-
 src/lib/merchant_api_pay.c                         |  22 +-
 src/lib/merchant_api_proposal.c                    |  29 +-
 src/lib/merchant_api_track_transaction.c           |  22 +-
 src/lib/merchant_api_track_transfer.c              |  25 +-
 src/lib/test_merchant_api.c                        | 156 ++---
 src/lib/test_merchant_api.conf                     |  13 +-
 src/merchant-tools/Makefile.am                     |  23 +-
 src/merchant-tools/README                          |  51 ++
 src/merchant-tools/mitm/Makefile.in                |  21 +
 src/merchant-tools/mitm/README                     |  25 +
 src/merchant-tools/mitm/merchant-mitm.wsgi.in      |  21 +
 src/merchant-tools/mitm/setup.py                   |  11 +
 src/merchant-tools/mitm/taler-merchant-mitm.in     |  45 ++
 .../mitm/talermerchantmitm/__init__.py             |   0
 src/merchant-tools/mitm/talermerchantmitm/mitm.py  |  78 +++
 src/merchant-tools/taler-merchant-dbinit.c         |  11 +-
 .../taler-merchant-generate-payments.c}            | 713 ++++++++++++++-------
 src/samples/Makefile.am                            |  21 -
 src/samples/README                                 |   3 -
 .../.config/taler/merchant/wire/test.json          |   5 -
 .../generate_payments_home/.config/taler/test.json |   6 -
 .../.config/taler/test.signed.json                 |   8 -
 .../share/taler/exchange/offline-keys/master.priv  |   1 -
 src/samples/merchant_generate_payments.conf        | 132 ----
 src/samples/test_merchant.priv                     |   1 -
 45 files changed, 2191 insertions(+), 1055 deletions(-)
 create mode 100644 src/merchant-tools/README
 create mode 100644 src/merchant-tools/mitm/Makefile.in
 create mode 100644 src/merchant-tools/mitm/README
 create mode 100644 src/merchant-tools/mitm/merchant-mitm.wsgi.in
 create mode 100644 src/merchant-tools/mitm/setup.py
 create mode 100644 src/merchant-tools/mitm/taler-merchant-mitm.in
 copy NEWS => src/merchant-tools/mitm/talermerchantmitm/__init__.py (100%)
 create mode 100644 src/merchant-tools/mitm/talermerchantmitm/mitm.py
 rename src/{samples/generate_payments.c => 
merchant-tools/taler-merchant-generate-payments.c} (69%)
 delete mode 100644 src/samples/Makefile.am
 delete mode 100644 src/samples/README
 delete mode 100644 
src/samples/generate_payments_home/.config/taler/merchant/wire/test.json
 delete mode 100644 src/samples/generate_payments_home/.config/taler/test.json
 delete mode 100644 
src/samples/generate_payments_home/.config/taler/test.signed.json
 delete mode 100644 
src/samples/generate_payments_home/.local/share/taler/exchange/offline-keys/master.priv
 delete mode 100644 src/samples/merchant_generate_payments.conf
 delete mode 100644 src/samples/test_merchant.priv

diff --git a/.gitignore b/.gitignore
index 6982c64..4cab3d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 *~
 *Makefile.in
+!src/mitm/*.in
 *Makefile
 aclocal.m4
 autom4te.cache
diff --git a/configure.ac b/configure.ac
index e728793..b60ae5d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -280,6 +280,8 @@ src/merchant-tools/Makefile
 src/include/Makefile
 src/backenddb/Makefile
 src/backend/Makefile
-src/samples/Makefile
-src/lib/Makefile])
+src/lib/Makefile
+src/merchant-tools/mitm/taler-merchant-mitm
+src/merchant-tools/mitm/merchant-mitm.wsgi
+src/merchant-tools/mitm/Makefile])
 AC_OUTPUT
diff --git a/doc/Makefile.am b/doc/Makefile.am
index b233fa5..86e8e65 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -3,7 +3,7 @@ all: manual.pdf manual.html
 manual.pdf: arch.pdf manual.texi
        texi2pdf manual.texi
 manual.html: arch.jpg manual.texi
-       texi2html manual.texi
+       makeinfo --html --no-split manual.texi
 arch.pdf: arch.dot
        dot -Tpdf arch.dot > arch.pdf
 arch.jpg: arch.dot
diff --git a/doc/manual.texi b/doc/manual.texi
index af2dc37..9da4582 100644
--- a/doc/manual.texi
+++ b/doc/manual.texi
@@ -55,6 +55,7 @@ Texts.  A copy of the license is included in the section 
entitled
 * Introduction::            Whom this manual is addressed to
 * Installation::            Installing the Merchant backend
 * Configuration::           How to set up the Merchant backend
+* Testing::                 How to test the installed Merchant backend
 * Advanced topics::         Detailed solutions to specific issues
 
 
@@ -172,10 +173,10 @@ account information is encapsulated within the Taler 
backend.
 
 @node Installation
 @menu
+* Installing Taler using Docker:: Installing Taler using Docker
 * generic-instructions:: Generic installation guidelines
 * Installing Taler on Debian GNU/Linux:: Installing Taler on Debian GNU/Linux
 @c * Installing Taler with GNU Guix:: Installing Taler with GNU Guix
-* Installing Taler using Docker:: Installing Taler using Docker
 @c * Installing Taler on Arch Linux:: Installing Taler on Arch Linux
 @c * Installing Taler on Windows:: Installing Taler on Windows
 @c * Installing Taler on OS X:: Installing Taler on OS X
@@ -740,23 +741,191 @@ reachable.  Production systems should be configured to 
bind
 to a UNIX domain socket or properly restrict access to the
 port.
 
address@hidden Testing
address@hidden Testing
+
+The tool @code{taler-merchant-generate-payments} can be used to test
+the merchant backend installation.  It implements all the payment's steps
+in a programmatically way, relying on the backend you give it as input.
+Note that this tool gets installed along all the merchant backend's binaries.
+
+This tool gets configured by a config file, that must have the following
+layout:
+
address@hidden
+[payments-generator]
+
+# The exchange used during the test: make sure the merchant backend
+# being tested accpets this exchange.
+# If the sysadmin wants, she can also install a local exchange
+# and test against it.
+exchange = https://exchange.demo.taler.net/
+
+# This value must indicate some URL where the backend
+# to be tested is listening; it doesn't have to be the
+# "official" one, though.
+merchant = http://localbackend/
+
+# This value is used when the tool tries to withdraw coins,
+# and must match the bank used by the exchange. If the test is
+# done against the exchange at https://exchange.demo.taler.net/,
+# then this value can be "https://bank.demo.taler.net/";.
+bank = https://bank.demo.taler.net/
+
+# The merchant instance in charge of serving the payment.
+# Make sure this instance has a bank account at the same bank
+# indicated by the 'bank' option above.
+instance = default
+
+# The currency used during the test. Must match the one used
+# by merchant backend and exchange.
+currency = KUDOS
address@hidden example
+
+Run the test in the following way:
+
address@hidden
+$ taler-merchant-generate-payments [-c config] [-e EURI] [-m MURI]
address@hidden example
+
+the argument @code{config} given to @code{-c} points to the configuration
+file and is optional -- @code{~/.config/taler.conf} will be checked by default.
+By default, the tool forks two processes: one for the merchant backend, and one
+for the exchange.
+The option @code{-e} (@code{-m}) avoids any exchange (merchant backend) fork,
+and just runs the generator against the exchange (merchant backend) running
+at @code{EURI} (@code{MURI}).
+
+Please NOTE that the generator contains @emph{hardcoded} values, as for deposit
+fees of the coins it uses.  In order to work against the used exchange, those 
values
+MUST match the ones used by the exchange.
 
address@hidden Add section describing how to test the backend.
address@hidden For this, we should write some tools that make it
address@hidden EASY to test the backend without going through the
address@hidden full manual frontend setup!
address@hidden NOTE: include explaining wallet installation to sysadmin
+The following example shows how the generator "sets" a deposit fee of EUR:0.01
+for the 5 EURO coin.
 
address@hidden
+// from <merchant_repository>/src/sample/generate_payments.c
address@hidden .oc = OC_PAY,
+  .label = "deposit-simple",
+  .expected_response_code = MHD_HTTP_OK,
+  .details.pay.contract_ref = "create-proposal-1",
+  .details.pay.coin_ref = "withdraw-coin-1",
+  .details.pay.amount_with_fee = concat_amount (currency, "5"),
+  .details.pay.amount_without_fee = concat_amount (currency, "4.99") @},
address@hidden example
+
+The logic calculates the deposit fee according to the subtraction:
address@hidden - amount_without_fee}.
+
+The following example shows a 5 EURO coin configuration - needed by the
+used exchange - which is compatible with the hardcoded example above.
+
address@hidden
+[coin_eur_5]
+value = EUR:5
+duration_overlap = 5 minutes
+duration_withdraw = 7 days
+duration_spend = 2 years
+duration_legal = 3 years
+fee_withdraw = EUR:0.00
+fee_deposit = EUR:0.01 # important bit
+fee_refresh = EUR:0.00
+fee_refund = EUR:0.00
+rsa_keysize = 1024
address@hidden example
+
+If the command terminates with no errors, then the merchant backend is 
correctly
+installed.
+
+After this operation is done, the merchant database will have some dummy
+data in it, so it may be convenient to clean all the tables; to this purpose,
+issue the following command:
+
address@hidden
+$ taler-merchant-dbinit -r
address@hidden example
 
 @node Advanced topics
 @chapter Advanced topics
 
 @menu
+* Configuration in Taler::  Configuration patterns
 * Using taler-config::      Introduction to the taler-config tool
 * Key management::          Managing the merchant's cryptographic keys
 * SEPA configuration::      Configuring a SEPA bank account
 @end menu
 
address@hidden Configuration in Taler
address@hidden Configuration in Taler
address@hidden configuration
+
+In Taler realm, any component obeys to the same pattern to get configuration
+values.  According to this pattern, once the component has been installed, the
+installation deploys default values in 
@address@hidden@}/share/taler/config.d/}, in
address@hidden files.  In order to override these defaults, the user can write 
a custom
address@hidden file and either pass it to the component at execution time, or 
name it
address@hidden and place it under @cite{$HOME/.config/}.
+
+
+A config file is a text file containing @cite{sections}, and each section 
contains
+its @cite{values}. The right format follows:
+
address@hidden
+[section1]
+value1 = string
+value2 = 23
+
+[section2]
+value21 = string
+value22 = /path22
address@hidden example
+
+Throughout any configuration file, it is possible to use @code{$}-prefixed 
variables,
+like @code{$VAR}, especially when they represent filesystem paths.
+It is also possible to provide defaults values for those variables that are 
unset,
+by using the following syntax: @address@hidden:address@hidden
+However, there are two ways a user can set @code{$}-prefixable variables:
+
+by defining them under a @code{[paths]} section, see example below,
+
address@hidden
+[paths]
+TALER_DEPLOYMENT_SHARED = address@hidden@}/shared-data
+..
+[section-x]
+path-x = address@hidden@}/x
address@hidden example
+
+or by setting them in the environment:
+
address@hidden
+$ export VAR=/x
address@hidden example
+
+The configuration loader will give precedence to variables set under 
@code{[path]},
+though.
+
+The utility @code{taler-config}, which gets installed along with the exchange, 
serves
+to get and set configuration values without directly editing the @cite{.conf}.
+The option @code{-f} is particularly useful to resolve pathnames, when they use
+several levels of @code{$}-expanded variables. See @code{taler-config --help}.
+
+Note that, in this stage of development, the file 
@code{$HOME/.config/taler.conf}
+can contain sections for @emph{all} the component. For example, both an 
exchange and
+a bank can read values from it.
+
+The repository @code{git://taler.net/deployment} contains examples of 
configuration
+file used in our demos. See under @code{deployment/config}.
+
address@hidden
address@hidden Note
+Expectably, some components will not work just by using default values, as 
their
+work is often interdependent. For example, a merchant needs to know an exchange
+URL, or a database name.
address@hidden quotation
address@hidden cartouche
+
+
 @node Using taler-config
 @section Using taler-config
 @cindex taler-config
diff --git a/doc/version.texi b/doc/version.texi
index 0b47203..d4370a3 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -1,4 +1,4 @@
address@hidden UPDATED 27 January 2017
address@hidden UPDATED-MONTH January 2017
address@hidden UPDATED 30 May 2017
address@hidden UPDATED-MONTH May 2017
 @set EDITION 0.2.0
 @set VERSION 0.2.0
diff --git a/src/Makefile.am b/src/Makefile.am
index 16521e0..e58cf01 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,3 +1,3 @@
 # This Makefile is in the public domain
 AM_CPPFLAGS = -I$(top_srcdir)/src/include
-SUBDIRS = include backenddb backend lib merchant-tools samples
+SUBDIRS = include backenddb backend lib merchant-tools
diff --git a/src/backend/taler-merchant-httpd.c 
b/src/backend/taler-merchant-httpd.c
index f3faa30..0efa7eb 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -286,10 +286,7 @@ do_shutdown (void *cls)
     GNUNET_SCHEDULER_cancel (mhd_task);
     mhd_task = NULL;
   }
-  /* FIXME: MHD API requires us to resume all suspended
-     connections before we do this, but /pay currently
-     suspends connections without giving us a way to
-     enumerate / resume them... */
+  MH_force_pc_resume ();
   if (NULL != mhd)
   {
     MHD_stop_daemon (mhd);
@@ -1109,7 +1106,8 @@ run (void *cls,
                           MHD_OPTION_END);
   if (NULL == mhd)
   {
-    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to launch HTTP service, exiting.\n");
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
@@ -1128,10 +1126,13 @@ run (void *cls,
 int
 main (int argc, char *const *argv)
 {
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    { 'C', "connection-close", NULL,
-      "force HTTP connections to be closed after each request", 0,
-      &GNUNET_GETOPT_set_one, &TMH_merchant_connection_close},
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+
+    GNUNET_GETOPT_option_flag ('C',
+                               "connection-close",
+                               "force HTTP connections to be closed after each 
request",
+                               &TMH_merchant_connection_close),
+
     GNUNET_GETOPT_OPTION_END
   };
 
diff --git a/src/backend/taler-merchant-httpd_auditors.c 
b/src/backend/taler-merchant-httpd_auditors.c
index 2671e08..81b6422 100644
--- a/src/backend/taler-merchant-httpd_auditors.c
+++ b/src/backend/taler-merchant-httpd_auditors.c
@@ -79,8 +79,6 @@ TMH_AUDITORS_check_dk (struct TALER_EXCHANGE_Handle *mh,
 {
   const struct TALER_EXCHANGE_Keys *keys;
   const struct TALER_EXCHANGE_AuditorInformation *ai;
-  unsigned int i;
-  unsigned int j;
 
   if (0 == GNUNET_TIME_absolute_get_remaining 
(dk->expire_deposit).rel_value_us)
   {
@@ -98,15 +96,28 @@ TMH_AUDITORS_check_dk (struct TALER_EXCHANGE_Handle *mh,
     GNUNET_break (0);
     return GNUNET_SYSERR;
   }
-  for (i=0;i<keys->num_auditors;i++)
+  for (unsigned int i=0;i<keys->num_auditors;i++)
   {
     ai = &keys->auditors[i];
-    for (j=0;j<ai->num_denom_keys;j++)
-      if (ai->denom_keys[j] == dk)
-        return GNUNET_OK;
+    for (unsigned int j=0;j<nauditors;j++)
+    {
+      if (0 == memcmp (&ai->auditor_pub,
+                       &auditors[j].public_key,
+                       sizeof (struct TALER_AuditorPublicKeyP)))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Found supported auditor `%s' (%s)\n",
+                    auditors[j].name,
+                    TALER_B2S (&auditors[j].public_key));
+
+      }
+      for (unsigned int k=0;j<ai->num_denom_keys;k++)
+        if (ai->denom_keys[k] == dk)
+          return GNUNET_OK;
+    }
   }
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Denomination key %s offered by client not audited by accepted 
auditor\n",
+              "Denomination key %s offered by client not audited by any 
accepted auditor\n",
               GNUNET_h2s (&dk->h_key));
   return GNUNET_NO;
 }
@@ -181,6 +192,10 @@ parse_auditors (void *cls,
     GNUNET_free (pks);
     return;
   }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Loaded key data of auditor `%s' (%s)\n",
+              auditor.name,
+              TALER_B2S (&auditor.public_key));
   GNUNET_free (pks);
   GNUNET_array_append (auditors,
                        nauditors,
@@ -198,15 +213,13 @@ parse_auditors (void *cls,
 int
 TMH_AUDITORS_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
-  unsigned int cnt;
-
   GNUNET_CONFIGURATION_iterate_sections (cfg,
                                          &parse_auditors,
                                          (void *) cfg);
 
   /* Generate preferred exchange(s) array. */
   j_auditors = json_array ();
-  for (cnt = 0; cnt < nauditors; cnt++)
+  for (unsigned int cnt = 0; cnt < nauditors; cnt++)
     GNUNET_assert (0 ==
                    json_array_append_new (j_auditors,
                                           json_pack ("{s:s, s:o, s:s}",
@@ -223,11 +236,9 @@ TMH_AUDITORS_init (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
 void
 TMH_AUDITORS_done ()
 {
-  unsigned int i;
-
   json_decref (j_auditors);
   j_auditors = NULL;
-  for (i=0;i<nauditors;i++)
+  for (unsigned int i=0;i<nauditors;i++)
   {
     GNUNET_free (auditors[i].name);
     GNUNET_free (auditors[i].uri);
diff --git a/src/backend/taler-merchant-httpd_exchanges.c 
b/src/backend/taler-merchant-httpd_exchanges.c
index daf5550..aab5b27 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -448,6 +448,11 @@ process_find_operations (struct Exchange *exchange)
             wire_fee,
             exchange->trusted);
     GNUNET_free_non_null (fo->wire_method);
+    if (NULL != fo->at)
+    {
+      GNUNET_SCHEDULER_cancel (fo->at);
+      fo->at = NULL;
+    }
     GNUNET_free (fo);
   }
   return need_wire;
@@ -522,6 +527,11 @@ handle_wire_data (void *cls,
               NULL,
               GNUNET_NO);
       GNUNET_free_non_null (fo->wire_method);
+      if (NULL != fo->at)
+      {
+        GNUNET_SCHEDULER_cancel (fo->at);
+        fo->at = NULL;
+      }
       GNUNET_free (fo);
     }
     return;
@@ -648,6 +658,7 @@ return_result (void *cls)
   struct TMH_EXCHANGES_FindOperation *fo = cls;
   struct Exchange *exchange = fo->my_exchange;
 
+  fo->at = NULL;
   if ( (GNUNET_YES ==
         process_find_operations (exchange)) &&
        (NULL == exchange->wire_request) &&
@@ -743,6 +754,7 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
   {
     /* We are not currently waiting for a reply, immediately
        return result */
+    GNUNET_assert (NULL == fo->at);
     fo->at = GNUNET_SCHEDULER_add_now (&return_result,
                                        fo);
     return fo;
@@ -766,8 +778,6 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
     exchange->wire_task = GNUNET_SCHEDULER_add_now (&wire_task_cb,
                                                     exchange);
   }
-
-
   return fo;
 }
 
diff --git a/src/backend/taler-merchant-httpd_history.c 
b/src/backend/taler-merchant-httpd_history.c
index 2e530e9..a06259c 100644
--- a/src/backend/taler-merchant-httpd_history.c
+++ b/src/backend/taler-merchant-httpd_history.c
@@ -25,38 +25,20 @@
 #include "taler-merchant-httpd.h"
 #include "taler-merchant-httpd_responses.h"
 
-/**
- * Index to the first row to return in response to /history.
- */
-unsigned int start;
-
-/**
- * How many rows we are to return in response to /history.
- */
-unsigned int delta;
-
-/**
- * Index to the current row being processed.
- */
-unsigned int current = 0;
-
 
 /**
  * Function called with information about a transaction.
  *
  * @param cls closure
- * @param merchant_pub merchant's public key
- * @param exchange_uri URI of the exchange
- * @param transaction_id proposal's transaction id
- * @param h_wire hash of our wire details
- * @param timestamp time of the confirmation
- * @param refund refund deadline
- * @param total_amount total amount we receive for the contract after fees
+ * @param order_id transaction's order ID.
+ * @param row_id serial numer of the transaction in the table,
+ * used as index by the frontend to skip previous results.
  */
 static void
 pd_cb (void *cls,
        const char *order_id,
-       const json_t *proposal_data)
+       uint64_t row_id,
+       const json_t *contract_terms)
 {
   json_t *response = cls;
   json_t *entry;
@@ -64,32 +46,25 @@ pd_cb (void *cls,
   json_t *timestamp;
   json_t *instance;
 
-  GNUNET_assert (-1 != json_unpack ((json_t *) proposal_data,
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "/history's row_id: %llu\n",
+              (unsigned long long) row_id);
+
+  GNUNET_assert (-1 != json_unpack ((json_t *) contract_terms,
                                     "{s:o, s:o, s:{s:o}}",
                                     "amount", &amount,
                                     "timestamp", &timestamp,
                                     "merchant", "instance", &instance));
 
-  if ( (current >= start) &&
-       (current < start + delta) )
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Adding history element. Current: %u, start: %u, delta: %u\n",
-                current,
-                start,
-                delta);
-    GNUNET_break (NULL != (entry = json_pack ("{s:s, s:O, s:O, s:O}",
-                                              "order_id", order_id,
-                                              "amount", amount,
-                                              "timestamp", timestamp,
-                                              "instance", instance)));
-
-    GNUNET_break (0 == json_array_append_new (response,
-                                              entry));
-  }
+  GNUNET_break (NULL != (entry = json_pack ("{s:I, s:s, s:O, s:O, s:O}",
+                                            "row_id", row_id,
+                                            "order_id", order_id,
+                                            "amount", amount,
+                                            "timestamp", timestamp,
+                                            "instance", instance)));
 
-  // FIXME to zero after returned.
-  current++;
+  GNUNET_break (0 == json_array_append_new (response,
+                                            entry));
 }
 
 
@@ -118,13 +93,16 @@ MH_handler_history (struct TMH_RequestHandler *rh,
   unsigned int ret;
   unsigned long long seconds;
   struct MerchantInstance *mi;
+  int start = -1;
+  unsigned int delta;
 
   response = json_array (); /*FIXME who decrefs this?*/
   str = MHD_lookup_connection_value (connection,
                                      MHD_GET_ARGUMENT_KIND,
                                      "date");
 
-  seconds = 0;
+  date = GNUNET_TIME_absolute_get ();
+
   if (NULL != str)
   {
     if (1 != sscanf (str, "%llu", &seconds))
@@ -134,9 +112,9 @@ MH_handler_history (struct TMH_RequestHandler *rh,
                                              TALER_EC_PARAMETER_MALFORMED,
                                              "date");
     }
-  }
 
   date.abs_value_us = seconds * 1000LL * 1000LL;
+
   if (date.abs_value_us / 1000LL / 1000LL != seconds)
   {
     json_decref (response);
@@ -146,6 +124,8 @@ MH_handler_history (struct TMH_RequestHandler *rh,
   }
 
 
+  }
+
   mi = TMH_lookup_instance ("default");
   str = MHD_lookup_connection_value (connection,
                                      MHD_GET_ARGUMENT_KIND,
@@ -160,7 +140,35 @@ MH_handler_history (struct TMH_RequestHandler *rh,
                                          TALER_EC_HISTORY_INSTANCE_UNKNOWN,
                                          "instance");
   }
-  start = 0;
+
+  /* Here goes the cherry-picking logic */
+
+  str = MHD_lookup_connection_value (connection,
+                                     MHD_GET_ARGUMENT_KIND,
+                                     "order_id");
+
+  if (NULL != str)
+  {
+
+    ret = db->find_contract_terms_history (db->cls,
+                                          str,
+                                          &mi->pubkey,
+                                          pd_cb,
+                                          response);
+    if (GNUNET_SYSERR == ret)
+    {
+      json_decref (response);
+      return TMH_RESPONSE_reply_internal_error (connection,
+                                                
TALER_EC_HISTORY_DB_FETCH_ERROR,
+                                               "db error to get history");
+    }
+    ret = TMH_RESPONSE_reply_json (connection,
+                                   response,
+                                   MHD_HTTP_OK);
+    json_decref (response);
+    return ret;
+  }
+
   delta = 20;
 
   str = MHD_lookup_connection_value (connection,
@@ -169,7 +177,7 @@ MH_handler_history (struct TMH_RequestHandler *rh,
   if (NULL != str)
   {
     if ((1 != sscanf (str, "%d", &start)) ||
-        start < 0)
+        0 > start)
     {
       json_decref (response);
       return TMH_RESPONSE_reply_arg_invalid (connection,
@@ -191,15 +199,27 @@ MH_handler_history (struct TMH_RequestHandler *rh,
                                              "delta");
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Querying history back to %s\n",
-              GNUNET_STRINGS_absolute_time_to_string (date));
-
-  ret = db->find_proposal_data_by_date (db->cls,
-                                        date,
-                                        &mi->pubkey,
-                                        pd_cb,
-                                        response);
-  current = 0;
+              "Querying history back to %s, start: %d, delta: %d\n",
+              GNUNET_STRINGS_absolute_time_to_string (date),
+              start,
+              delta);
+
+  if (0 > start)
+    ret = db->find_contract_terms_by_date (db->cls,
+                                          date,
+                                          &mi->pubkey,
+                                          delta,
+                                          pd_cb,
+                                          response);
+  else
+    ret = db->find_contract_terms_by_date_and_range (db->cls,
+                                                    date,
+                                                    &mi->pubkey,
+                                                    start,
+                                                    delta,
+                                                    GNUNET_NO,
+                                                    pd_cb,
+                                                    response);
   if (GNUNET_SYSERR == ret)
   {
     json_decref (response);
@@ -207,10 +227,6 @@ MH_handler_history (struct TMH_RequestHandler *rh,
                                              TALER_EC_HISTORY_DB_FETCH_ERROR,
                                              "db error to get history");
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "history data: %s\n",
-              json_dumps (response, JSON_INDENT (1)));
-
   ret = TMH_RESPONSE_reply_json (connection,
                                  response,
                                  MHD_HTTP_OK);
diff --git a/src/backend/taler-merchant-httpd_pay.c 
b/src/backend/taler-merchant-httpd_pay.c
index c3203ef..97b7ac4 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -119,6 +119,16 @@ struct PayContext
   struct TM_HandlerContext hc;
 
   /**
+   * Stored in a DLL.
+   */
+  struct PayContext *next;
+
+  /**
+   * Stored in a DLL.
+   */
+  struct PayContext *prev;
+
+  /**
    * Array with @e coins_cnt coins we are despositing.
    */
   struct DepositConfirmation *dc;
@@ -129,6 +139,29 @@ struct PayContext
   struct MHD_Connection *connection;
 
   /**
+   * Instance of the payment's instance (in JSON format)
+   */
+  struct MerchantInstance *mi;
+
+  /**
+   * Proposal data for the proposal that is being
+   * payed for in this context.
+   */
+  json_t *contract_terms;
+
+  /**
+   * Task called when the (suspended) processing for
+   * the /pay request times out.
+   * Happens when we don't get a response from the exchange.
+   */
+  struct GNUNET_SCHEDULER_Task *timeout_task;
+
+  /**
+   * Response to return, NULL if we don't have one yet.
+   */
+  struct MHD_Response *response;
+
+  /**
    * Handle to the exchange that we are doing the payment with.
    * (initially NULL while @e fo is trying to find a exchange).
    */
@@ -157,6 +190,17 @@ struct PayContext
   const char *order_id;
 
   /**
+   * Hashed proposal.
+   */
+  struct GNUNET_HashCode h_contract_terms;
+
+  /**
+   * "H_wire" from @e contract_terms.  Used to identify the instance's
+   * wire transfer method.
+   */
+  struct GNUNET_HashCode h_wire;
+
+  /**
    * Maximum fee the merchant is willing to pay, from @e root.
    * Note that IF the total fee of the exchange is higher, that is
    * acceptable to the merchant if the customer is willing to
@@ -184,57 +228,41 @@ struct PayContext
   struct TALER_Amount max_wire_fee;
 
   /**
-   * Number of transactions that the wire fees are expected to be
-   * amortized over.  Never zero, defaults (conservateively) to 1.
-   * May be higher if merchants expect many small transactions to
-   * be aggregated and thus wire fees to be reasonably amortized
-   * due to aggregation.
-   */
-  uint32_t wire_fee_amortization;
-
-  /**
    * Amount from @e root.  This is the amount the merchant expects
    * to make, minus @e max_fee.
    */
   struct TALER_Amount amount;
 
   /**
-   * Timestamp from @e proposal_data.
-   */
-  struct GNUNET_TIME_Absolute timestamp;
-
-  /**
-   * Refund deadline from @e proposal_data.
-   */
-  struct GNUNET_TIME_Absolute refund_deadline;
-
-  /**
-   * Deadline for the customer to pay for this contract.
+   * Wire transfer deadline. How soon would the merchant like the
+   * wire transfer to be executed? (Can be given by the frontend
+   * or be determined by our configuration via #wire_transfer_delay.)
    */
-  struct GNUNET_TIME_Absolute pay_deadline;
+  struct GNUNET_TIME_Absolute wire_transfer_deadline;
 
   /**
-   * "H_contract" from @e proposal_data.
+   * Timestamp from @e contract_terms.
    */
-  struct GNUNET_HashCode h_proposal_data;
+  struct GNUNET_TIME_Absolute timestamp;
 
   /**
-   * "H_wire" from @e proposal_data.  Used to identify the instance's
-   * wire transfer method.
+   * Refund deadline from @e contract_terms.
    */
-  struct GNUNET_HashCode h_wire;
+  struct GNUNET_TIME_Absolute refund_deadline;
 
   /**
-   * Wire transfer deadline. How soon would the merchant like the
-   * wire transfer to be executed? (Can be given by the frontend
-   * or be determined by our configuration via #wire_transfer_delay.)
+   * Deadline for the customer to pay for this proposal.
    */
-  struct GNUNET_TIME_Absolute wire_transfer_deadline;
+  struct GNUNET_TIME_Absolute pay_deadline;
 
   /**
-   * Response to return, NULL if we don't have one yet.
+   * Number of transactions that the wire fees are expected to be
+   * amortized over.  Never zero, defaults (conservateively) to 1.
+   * May be higher if merchants expect many small transactions to
+   * be aggregated and thus wire fees to be reasonably amortized
+   * due to aggregation.
    */
-  struct MHD_Response *response;
+  uint32_t wire_fee_amortization;
 
   /**
    * Number of coins this payment is made of.  Length
@@ -257,32 +285,50 @@ struct PayContext
   unsigned int response_code;
 
   /**
-   * Task called when the (suspended) processing for
-   * the /pay request times out.
-   * Happens when we don't get a response from the exchange.
-   */
-  struct GNUNET_SCHEDULER_Task *timeout_task;
-
-  /**
    * #GNUNET_NO if the transaction is not in our database,
    * #GNUNET_YES if the transaction is known to our database,
    * #GNUNET_SYSERR if the transaction ID is used for a different
    * transaction in our database.
    */
-  int transaction_exits;
+  int transaction_exists;
 
   /**
-   * Instance of the payment's instance (in JSON format)
+   * #GNUNET_NO if the @e connection was not suspended,
+   * #GNUNET_YES if the @e connection was suspended,
+   * #GNUNET_SYSERR if @e connection was resumed to as
+   * part of #MH_force_pc_resume during shutdown.
    */
-  struct MerchantInstance *mi;
+  int suspended;
+};
 
-  /**
-   * Proposal data for the proposal that is being
-   * payed for in this context.
-   */
-  json_t *proposal_data;
 
-};
+/**
+ * Head of active pay context DLL.
+ */
+static struct PayContext *pc_head;
+
+/**
+ * Tail of active pay context DLL.
+ */
+static struct PayContext *pc_tail;
+
+
+/**
+ * Force all pay contexts to be resumed as we are about
+ * to shut down MHD.
+ */
+void
+MH_force_pc_resume ()
+{
+  for (struct PayContext *pc = pc_head; NULL != pc; pc = pc->next)
+  {
+    if (GNUNET_YES == pc->suspended)
+    {
+      pc->suspended = GNUNET_SYSERR;
+      MHD_resume_connection (pc->connection);
+    }
+  }
+}
 
 
 /**
@@ -309,6 +355,8 @@ resume_pay_with_response (struct PayContext *pc,
     GNUNET_SCHEDULER_cancel (pc->timeout_task);
     pc->timeout_task = NULL;
   }
+  GNUNET_assert (GNUNET_YES == pc->suspended);
+  pc->suspended = GNUNET_NO;
   MHD_resume_connection (pc->connection);
   TMH_trigger_daemon (); /* we resumed, kick MHD */
 }
@@ -353,19 +401,19 @@ sign_success_response (struct PayContext *pc)
 
   mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
   mr.purpose.size = htonl (sizeof (mr));
-  mr.h_proposal_data = pc->h_proposal_data;
+  mr.h_contract_terms = pc->h_contract_terms;
 
   GNUNET_CRYPTO_eddsa_sign (&pc->mi->privkey.eddsa_priv,
                             &mr.purpose,
                            &sig);
 
   return TMH_RESPONSE_make_json_pack ("{s:O, s:o, s:o}",
-                                      "proposal_data",
-                                      pc->proposal_data,
+                                      "contract_terms",
+                                      pc->contract_terms,
                                       "sig",
                                       GNUNET_JSON_from_data_auto (&sig),
-                                      "h_proposal_data",
-                                      GNUNET_JSON_from_data 
(&pc->h_proposal_data,
+                                      "h_contract_terms",
+                                      GNUNET_JSON_from_data 
(&pc->h_contract_terms,
                                                              sizeof (struct 
GNUNET_HashCode)));
 }
 
@@ -438,12 +486,12 @@ deposit_cb (void *cls,
   }
   /* store result to DB */
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Storing successful payment for h_proposal_data '%s'\n",
-              GNUNET_h2s (&pc->h_proposal_data));
+              "Storing successful payment for h_contract_terms '%s'\n",
+              GNUNET_h2s (&pc->h_contract_terms));
 
   if (GNUNET_OK !=
       db->store_deposit (db->cls,
-                        &pc->h_proposal_data,
+                        &pc->h_contract_terms,
                         &pc->mi->pubkey,
                         &dc->coin_pub,
                         &dc->amount_with_fee,
@@ -479,16 +527,14 @@ static void
 pay_context_cleanup (struct TM_HandlerContext *hc)
 {
   struct PayContext *pc = (struct PayContext *) hc;
-  unsigned int i;
 
   if (NULL != pc->timeout_task)
   {
     GNUNET_SCHEDULER_cancel (pc->timeout_task);
     pc->timeout_task = NULL;
   }
-
   TMH_PARSE_post_cleanup_callback (pc->json_parse_context);
-  for (i=0;i<pc->coins_cnt;i++)
+  for (unsigned int i=0;i<pc->coins_cnt;i++)
   {
     struct DepositConfirmation *dc = &pc->dc[i];
 
@@ -524,11 +570,14 @@ pay_context_cleanup (struct TM_HandlerContext *hc)
     GNUNET_free (pc->chosen_exchange);
     pc->chosen_exchange = NULL;
   }
-  if (NULL != pc->proposal_data)
+  if (NULL != pc->contract_terms)
   {
-    json_decref (pc->proposal_data);
-    pc->proposal_data = NULL;
+    json_decref (pc->contract_terms);
+    pc->contract_terms = NULL;
   }
+  GNUNET_CONTAINER_DLL_remove (pc_head,
+                               pc_tail,
+                               pc);
   GNUNET_free (pc);
 }
 
@@ -553,7 +602,6 @@ process_pay_with_exchange (void *cls,
   struct TALER_Amount wire_fee_delta;
   struct TALER_Amount wire_fee_customer_contribution;
   const struct TALER_EXCHANGE_Keys *keys;
-  unsigned int i;
 
   pc->fo = NULL;
   if (NULL == mh)
@@ -580,7 +628,7 @@ process_pay_with_exchange (void *cls,
   }
 
   /* Total up the fees and the value of the deposited coins! */
-  for (i=0;i<pc->coins_cnt;i++)
+  for (unsigned int i=0;i<pc->coins_cnt;i++)
   {
     struct DepositConfirmation *dc = &pc->dc[i];
     const struct TALER_EXCHANGE_DenomPublicKey *denom_details;
@@ -784,7 +832,7 @@ process_pay_with_exchange (void *cls,
               "Exchange and fee structure OK. Initiating deposit operation for 
coins\n");
 
   /* Initiate /deposit operation for all coins */
-  for (i=0;i<pc->coins_cnt;i++)
+  for (unsigned int i=0;i<pc->coins_cnt;i++)
   {
     struct DepositConfirmation *dc = &pc->dc[i];
 
@@ -795,11 +843,12 @@ process_pay_with_exchange (void *cls,
                 "Timing for this payment, wire_deadline: %llu, 
refund_deadline: %llu\n",
                 (unsigned long long) pc->wire_transfer_deadline.abs_value_us,
                 (unsigned long long) pc->refund_deadline.abs_value_us);
+
     dc->dh = TALER_EXCHANGE_deposit (mh,
                                      &dc->amount_with_fee,
                                      pc->wire_transfer_deadline,
                                      pc->mi->j_wire,
-                                     &pc->h_proposal_data,
+                                     &pc->h_contract_terms,
                                      &dc->coin_pub,
                                      &dc->ub_sig,
                                      &dc->denom,
@@ -856,7 +905,7 @@ handle_pay_timeout (void *cls)
  * Function called with information about a coin that was deposited.
  *
  * @param cls closure
- * @param transaction_id of the contract
+ * @param h_contract_terms hashed proposal data
  * @param coin_pub public key of the coin
  * @param amount_with_fee amount the exchange will deposit for this coin
  * @param deposit_fee fee the exchange will charge for this coin
@@ -864,7 +913,7 @@ handle_pay_timeout (void *cls)
  */
 static void
 check_coin_paid (void *cls,
-                 const struct GNUNET_HashCode *h_proposal_data,
+                 const struct GNUNET_HashCode *h_contract_terms,
                  const struct TALER_CoinSpendPublicKeyP *coin_pub,
                  const struct TALER_Amount *amount_with_fee,
                  const struct TALER_Amount *deposit_fee,
@@ -873,8 +922,8 @@ check_coin_paid (void *cls,
   struct PayContext *pc = cls;
   unsigned int i;
 
-  if (0 != memcmp (&pc->h_proposal_data,
-                   h_proposal_data,
+  if (0 != memcmp (&pc->h_contract_terms,
+                   h_contract_terms,
                    sizeof (struct GNUNET_HashCode)))
   {
     GNUNET_break (0);
@@ -883,14 +932,23 @@ check_coin_paid (void *cls,
   for (i=0;i<pc->coins_cnt;i++)
   {
     struct DepositConfirmation *dc = &pc->dc[i];
-
+    /* Get matching coin from results*/
     if ( (0 != memcmp (coin_pub,
                        &dc->coin_pub,
                        sizeof (struct TALER_CoinSpendPublicKeyP))) ||
          (0 != TALER_amount_cmp (amount_with_fee,
                                  &dc->amount_with_fee)) )
       continue;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Coin (%s) already found in our DB.\n",
+                TALER_b2s (coin_pub, sizeof (*coin_pub)));
+
     dc->found_in_db = GNUNET_YES;
+    /**
+     * What happens if a (mad) wallet sends new coins on a
+     * contract that it already paid for?
+     */
     pc->pending--;
   }
 }
@@ -898,12 +956,12 @@ check_coin_paid (void *cls,
 
 /**
  * Check if the existing transaction matches our transaction.
- * Update `transaction_exits` accordingly.
+ * Update `transaction_exists` accordingly.
  *
  * @param cls closure with the `struct PayContext`
- * @param transaction_id of the contract
  * @param merchant_pub merchant's public key
  * @param exchange_uri URI of the exchange
+ * @param h_contract_terms hashed proposal data
  * @param h_xwire hash of our wire details
  * @param timestamp time of the confirmation
  * @param refund refund deadline
@@ -913,7 +971,7 @@ static void
 check_transaction_exists (void *cls,
                          const struct TALER_MerchantPublicKeyP *merchant_pub,
                          const char *exchange_uri,
-                         const struct GNUNET_HashCode *h_proposal_data,
+                         const struct GNUNET_HashCode *h_contract_terms,
                          const struct GNUNET_HashCode *h_xwire,
                          struct GNUNET_TIME_Absolute timestamp,
                          struct GNUNET_TIME_Absolute refund,
@@ -921,8 +979,8 @@ check_transaction_exists (void *cls,
 {
   struct PayContext *pc = cls;
 
-  if ( (0 == memcmp (h_proposal_data,
-                    &pc->h_proposal_data,
+  if ( (0 == memcmp (h_contract_terms,
+                    &pc->h_contract_terms,
                      sizeof (struct GNUNET_HashCode))) &&
        (0 == memcmp (h_xwire,
                     &pc->mi->h_wire,
@@ -932,12 +990,12 @@ check_transaction_exists (void *cls,
        (0 == TALER_amount_cmp (total_amount,
                               &pc->amount) ) )
   {
-    pc->transaction_exits = GNUNET_YES;
+    pc->transaction_exists = GNUNET_YES;
   }
   else
   {
     GNUNET_break_op (0);
-    pc->transaction_exits = GNUNET_SYSERR;
+    pc->transaction_exists = GNUNET_SYSERR;
   }
 }
 
@@ -949,7 +1007,6 @@ get_instance (struct json_t *json);
 
 /**
  * Try to parse the pay request into the given pay context.
- *
  * Schedules an error response in the connection on failure.
  *
  *
@@ -989,8 +1046,8 @@ parse_pay (struct MHD_Connection *connection,
     GNUNET_break (0);
     return res;
   }
-  res = db->find_proposal_data (db->cls,
-                                &pc->proposal_data,
+  res = db->find_contract_terms (db->cls,
+                                &pc->contract_terms,
                                 order_id,
                                 &merchant_pub);
   if (GNUNET_OK != res)
@@ -1008,8 +1065,8 @@ parse_pay (struct MHD_Connection *connection,
   }
 
   if (GNUNET_OK !=
-      TALER_JSON_hash (pc->proposal_data,
-                       &pc->h_proposal_data))
+      TALER_JSON_hash (pc->contract_terms,
+                       &pc->h_contract_terms))
   {
     GNUNET_JSON_parse_free (spec);
     if (MHD_YES !=
@@ -1023,7 +1080,7 @@ parse_pay (struct MHD_Connection *connection,
     return GNUNET_NO;
   }
 
-  merchant = json_object_get (pc->proposal_data,
+  merchant = json_object_get (pc->contract_terms,
                               "merchant");
   if (NULL == merchant)
   {
@@ -1033,7 +1090,7 @@ parse_pay (struct MHD_Connection *connection,
     if (MHD_YES !=
         TMH_RESPONSE_reply_internal_error (connection,
                                            TALER_EC_PAY_MERCHANT_FIELD_MISSING,
-                                           "No merchant field in contract"))
+                                           "No merchant field in proposal"))
     {
       GNUNET_break (0);
       return GNUNET_SYSERR;
@@ -1081,7 +1138,7 @@ parse_pay (struct MHD_Connection *connection,
     };
 
     res = TMH_PARSE_json_data (connection,
-                               pc->proposal_data,
+                               pc->contract_terms,
                                espec);
     if (GNUNET_YES != res)
     {
@@ -1118,7 +1175,7 @@ parse_pay (struct MHD_Connection *connection,
   }
 
   /* parse optional details */
-  if (NULL != json_object_get (pc->proposal_data,
+  if (NULL != json_object_get (pc->contract_terms,
                                "max_wire_fee"))
   {
     struct GNUNET_JSON_Specification espec[] = {
@@ -1128,7 +1185,7 @@ parse_pay (struct MHD_Connection *connection,
     };
 
     res = TMH_PARSE_json_data (connection,
-                               pc->proposal_data,
+                               pc->contract_terms,
                                espec);
     if (GNUNET_YES != res)
     {
@@ -1146,7 +1203,7 @@ parse_pay (struct MHD_Connection *connection,
                    TALER_amount_get_zero (pc->max_fee.currency,
                                           &pc->max_wire_fee));
   }
-  if (NULL != json_object_get (pc->proposal_data,
+  if (NULL != json_object_get (pc->contract_terms,
                                "wire_fee_amortization"))
   {
     struct GNUNET_JSON_Specification espec[] = {
@@ -1156,7 +1213,7 @@ parse_pay (struct MHD_Connection *connection,
     };
 
     res = TMH_PARSE_json_data (connection,
-                               pc->proposal_data,
+                               pc->contract_terms,
                                espec);
     if ( (GNUNET_YES != res) ||
          (0 == pc->wire_fee_amortization) )
@@ -1240,7 +1297,7 @@ handler_pay_json (struct MHD_Connection *connection,
   /* Check if this payment attempt has already succeeded */
   if (GNUNET_SYSERR ==
       db->find_payments (db->cls,
-                        &pc->h_proposal_data,
+                        &pc->h_contract_terms,
                          &pc->mi->pubkey,
                         &check_coin_paid,
                         pc))
@@ -1257,6 +1314,8 @@ handler_pay_json (struct MHD_Connection *connection,
 
     /* Payment succeeded in the past; take short cut
        and accept immediately */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Payment succeeded in the past; taking short cut");
     resp = MHD_create_response_from_buffer (0,
                                            NULL,
                                            MHD_RESPMEM_PERSISTENT);
@@ -1269,7 +1328,7 @@ handler_pay_json (struct MHD_Connection *connection,
   /* Check if transaction is already known, if not store it. */
   if (GNUNET_SYSERR ==
       db->find_transaction (db->cls,
-                           &pc->h_proposal_data,
+                           &pc->h_contract_terms,
                            &pc->mi->pubkey,
                            &check_transaction_exists,
                             pc))
@@ -1279,31 +1338,31 @@ handler_pay_json (struct MHD_Connection *connection,
                                              
TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR,
                                                "Merchant database error");
   }
-  if (GNUNET_SYSERR == pc->transaction_exits)
+  if (GNUNET_SYSERR == pc->transaction_exists)
   {
     GNUNET_break (0);
     return TMH_RESPONSE_reply_external_error (connection,
                                               
TALER_EC_PAY_DB_TRANSACTION_ID_CONFLICT,
                                              "Transaction ID reused with 
different transaction details");
   }
-  if (GNUNET_NO == pc->transaction_exits)
+  if (GNUNET_NO == pc->transaction_exists)
   {
     struct GNUNET_TIME_Absolute now;
+
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Dealing with new transaction '%s'\n",
-                GNUNET_h2s (&pc->h_proposal_data));
+                GNUNET_h2s (&pc->h_contract_terms));
 
     now = GNUNET_TIME_absolute_get ();
     if (now.abs_value_us > pc->pay_deadline.abs_value_us)
     {
       /* Time expired, we don't accept this payment now! */
       const char *pd_str;
-      pd_str = GNUNET_STRINGS_absolute_time_to_string (pc->pay_deadline);
 
+      pd_str = GNUNET_STRINGS_absolute_time_to_string (pc->pay_deadline);
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Attempt to get coins for expired contract. Deadline: 
'%s'\n",
                  pd_str);
-
       return TMH_RESPONSE_reply_bad_request (connection,
                                             TALER_EC_PAY_OFFER_EXPIRED,
                                              "The time to pay for this 
contract has expired.");
@@ -1311,10 +1370,10 @@ handler_pay_json (struct MHD_Connection *connection,
 
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Storing transaction '%s'\n",
-                GNUNET_h2s (&pc->h_proposal_data));
+                GNUNET_h2s (&pc->h_contract_terms));
     if (GNUNET_OK !=
         db->store_transaction (db->cls,
-                               &pc->h_proposal_data,
+                               &pc->h_contract_terms,
                                &pc->mi->pubkey,
                                pc->chosen_exchange,
                                &pc->mi->h_wire,
@@ -1330,6 +1389,7 @@ handler_pay_json (struct MHD_Connection *connection,
   }
 
   MHD_suspend_connection (connection);
+  pc->suspended = GNUNET_YES;
 
   /* Find the responsible exchange, this may take a while... */
   pc->fo = TMH_EXCHANGES_find_exchange (pc->chosen_exchange,
@@ -1379,6 +1439,9 @@ MH_handler_pay (struct TMH_RequestHandler *rh,
   if (NULL == *connection_cls)
   {
     pc = GNUNET_new (struct PayContext);
+    GNUNET_CONTAINER_DLL_insert (pc_head,
+                                 pc_tail,
+                                 pc);
     pc->hc.cc = &pay_context_cleanup;
     pc->connection = connection;
     *connection_cls = pc;
diff --git a/src/backend/taler-merchant-httpd_pay.h 
b/src/backend/taler-merchant-httpd_pay.h
index 124a9d9..d4f4958 100644
--- a/src/backend/taler-merchant-httpd_pay.h
+++ b/src/backend/taler-merchant-httpd_pay.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015 GNUnet e.V.
+  (C) 2014-2017 GNUnet e.V.
 
   TALER is free 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,6 +23,15 @@
 #include <microhttpd.h>
 #include "taler-merchant-httpd.h"
 
+
+/**
+ * Force all pay contexts to be resumed as we are about
+ * to shut down MHD.
+ */
+void
+MH_force_pc_resume (void);
+
+
 /**
  * Manage a payment
  *
diff --git a/src/backend/taler-merchant-httpd_proposal.c 
b/src/backend/taler-merchant-httpd_proposal.c
index 0d96a1f..fa8251c 100644
--- a/src/backend/taler-merchant-httpd_proposal.c
+++ b/src/backend/taler-merchant-httpd_proposal.c
@@ -183,8 +183,7 @@ proposal_put (struct MHD_Connection *connection,
                      json_string (buf));
   }
 
-  if (NULL == json_object_get (order,
-                               "timestamp"))
+  if (NULL == json_object_get (order, "timestamp"))
   {
     struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
 
@@ -277,6 +276,9 @@ proposal_put (struct MHD_Connection *connection,
                        "H_wire",
                       GNUNET_JSON_from_data_auto (&mi->h_wire));
   json_object_set_new (order,
+                       "wire_method",
+                      json_string (mi->wire_method));
+  json_object_set_new (order,
                        "merchant_pub",
                       GNUNET_JSON_from_data_auto (&mi->pubkey));
 
@@ -294,7 +296,7 @@ proposal_put (struct MHD_Connection *connection,
   /* fetch timestamp from order */
 
   if (GNUNET_OK !=
-      db->insert_proposal_data (db->cls,
+      db->insert_contract_terms (db->cls,
                                 order_id,
                                 &mi->pubkey,
                                 timestamp,
@@ -403,7 +405,7 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
   const char *order_id;
   const char *instance;
   int res;
-  json_t *proposal_data;
+  json_t *contract_terms;
   struct MerchantInstance *mi;
 
   instance = MHD_lookup_connection_value (connection,
@@ -425,8 +427,8 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
                                           TALER_EC_PARAMETER_MISSING,
                                            "order_id");
 
-  res = db->find_proposal_data (db->cls,
-                                &proposal_data,
+  res = db->find_contract_terms (db->cls,
+                                &contract_terms,
                                 order_id,
                                 &mi->pubkey);
   if (GNUNET_NO == res)
@@ -441,7 +443,7 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
 
 
   return TMH_RESPONSE_reply_json (connection,
-                                  proposal_data,
+                                  contract_terms,
                                   MHD_HTTP_OK);
 
 
diff --git a/src/backend/taler-merchant-httpd_track-transaction.c 
b/src/backend/taler-merchant-httpd_track-transaction.c
index 9f6e6d1..eb1ee16 100644
--- a/src/backend/taler-merchant-httpd_track-transaction.c
+++ b/src/backend/taler-merchant-httpd_track-transaction.c
@@ -207,7 +207,7 @@ struct TrackTransactionContext
   /**
    *  Proposal's hashcode.
    */
-  struct GNUNET_HashCode h_proposal_data;
+  struct GNUNET_HashCode h_contract_terms;
 
   /**
    * Response code to return upon resume.
@@ -364,6 +364,7 @@ wire_deposits_cb (void *cls,
   tctx->wdh = NULL;
   if (MHD_HTTP_OK != http_status)
   {
+    GNUNET_break_op (0);
     resume_track_transaction_with_response
       (tctx,
        MHD_HTTP_FAILED_DEPENDENCY,
@@ -404,7 +405,7 @@ wire_deposits_cb (void *cls,
 
       if (GNUNET_OK !=
           db->store_coin_to_transfer (db->cls,
-                                      &details[i].h_proposal_data,
+                                      &details[i].h_contract_terms,
                                       &details[i].coin_pub,
                                       &tctx->current_wtid))
       {
@@ -560,7 +561,7 @@ trace_coins (struct TrackTransactionContext *tctx)
     tcc->dwh = TALER_EXCHANGE_track_transaction (tctx->eh,
                                                  &tctx->mi->privkey,
                                                  &tctx->h_wire,
-                                                 &tctx->h_proposal_data,
+                                                 &tctx->h_contract_terms,
                                                  &tcc->coin_pub,
                                                  &wtid_cb,
                                                  tcc);
@@ -730,7 +731,7 @@ static void
 transaction_cb (void *cls,
                const struct TALER_MerchantPublicKeyP *merchant_pub,
                 const char *exchange_uri,
-                const struct GNUNET_HashCode *h_proposal_data,
+                const struct GNUNET_HashCode *h_contract_terms,
                 const struct GNUNET_HashCode *h_wire,
                 struct GNUNET_TIME_Absolute timestamp,
                 struct GNUNET_TIME_Absolute refund,
@@ -738,7 +739,7 @@ transaction_cb (void *cls,
 {
   struct TrackTransactionContext *tctx = cls;
 
-  tctx->h_proposal_data = *h_proposal_data;
+  tctx->h_contract_terms = *h_contract_terms;
   tctx->exchange_uri = GNUNET_strdup (exchange_uri);
   tctx->h_wire = *h_wire;
   tctx->timestamp = timestamp;
@@ -766,7 +767,7 @@ transaction_cb (void *cls,
  */
 static void
 transfer_cb (void *cls,
-             const struct GNUNET_HashCode *h_proposal_data,
+             const struct GNUNET_HashCode *h_contract_terms,
              const struct TALER_CoinSpendPublicKeyP *coin_pub,
              const struct TALER_WireTransferIdentifierRawP *wtid,
              struct GNUNET_TIME_Absolute execution_time,
@@ -796,7 +797,7 @@ transfer_cb (void *cls,
  */
 static void
 coin_cb (void *cls,
-         const struct GNUNET_HashCode *h_proposal_data,
+         const struct GNUNET_HashCode *h_contract_terms,
          const struct TALER_CoinSpendPublicKeyP *coin_pub,
          const struct TALER_Amount *amount_with_fee,
          const struct TALER_Amount *deposit_fee,
@@ -815,7 +816,7 @@ coin_cb (void *cls,
                                tcc);
   GNUNET_break (GNUNET_SYSERR !=
                 db->find_transfers_by_hash (db->cls,
-                                            h_proposal_data,
+                                            h_contract_terms,
                                             &transfer_cb,
                                             tcc));
 }
@@ -842,8 +843,8 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh,
   const char *instance;
   int ret;
   struct GNUNET_HashCode h_instance;
-  struct GNUNET_HashCode h_proposal_data;
-  struct json_t *proposal_data;
+  struct GNUNET_HashCode h_contract_terms;
+  struct json_t *contract_terms;
 
   if (NULL == *connection_cls)
   {
@@ -916,37 +917,37 @@ MH_handler_track_transaction (struct TMH_RequestHandler 
*rh,
                                         
TALER_EC_TRACK_TRANSACTION_INSTANCE_UNKNOWN,
                                         "unknown instance");
 
-  if (GNUNET_YES != db->find_proposal_data (db->cls,
-                                            &proposal_data,
+  if (GNUNET_YES != db->find_contract_terms (db->cls,
+                                            &contract_terms,
                                             order_id,
                                             &tctx->mi->pubkey))
 
     return TMH_RESPONSE_reply_not_found (connection,
                                         TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
                                         "Given order_id doesn't map to any 
proposal");
-  TALER_JSON_hash (proposal_data,
-                   &h_proposal_data);
+  TALER_JSON_hash (contract_terms,
+                   &h_contract_terms);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Trying to track h_proposal_data '%s'\n",
-              GNUNET_h2s (&h_proposal_data));
+              "Trying to track h_contract_terms '%s'\n",
+              GNUNET_h2s (&h_contract_terms));
 
   ret = db->find_transaction (db->cls,
-                              &h_proposal_data,
+                              &h_contract_terms,
                              &tctx->mi->pubkey,
                               &transaction_cb,
                               tctx);
   if (GNUNET_NO == ret)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "h_proposal_data not found\n");
+                "h_contract_terms not found\n");
     return TMH_RESPONSE_reply_not_found (connection,
                                         
TALER_EC_TRACK_TRANSACTION_TRANSACTION_UNKNOWN,
-                                         "h_proposal_data is unknown");
+                                         "h_contract_terms is unknown");
   }
   if ( (GNUNET_SYSERR == ret) ||
-       (0 != memcmp (&tctx->h_proposal_data,
-                     &h_proposal_data,
+       (0 != memcmp (&tctx->h_contract_terms,
+                     &h_contract_terms,
                      sizeof (struct GNUNET_HashCode))) ||
        (NULL == tctx->exchange_uri) )
   {
@@ -956,7 +957,7 @@ MH_handler_track_transaction (struct TMH_RequestHandler *rh,
                                               "Database error");
   }
   ret = db->find_payments (db->cls,
-                           &h_proposal_data,
+                           &h_contract_terms,
                            &tctx->mi->pubkey,
                            &coin_cb,
                            tctx);
diff --git a/src/backend/taler-merchant-httpd_track-transfer.c 
b/src/backend/taler-merchant-httpd_track-transfer.c
index 3635c1d..4ca22af 100644
--- a/src/backend/taler-merchant-httpd_track-transfer.c
+++ b/src/backend/taler-merchant-httpd_track-transfer.c
@@ -125,6 +125,27 @@ struct TrackTransferContext
   int check_transfer_result;
 };
 
+/**
+ * Represents an entry in the table used to sum up
+ * individual deposits for each h_contract_terms.
+ */
+struct Entry {
+  /**
+   * Sum accumulator for deposited value.
+   */
+  struct TALER_Amount deposit_value;
+
+  /**
+   * Sum accumulator for deposit fee.
+   */
+  struct TALER_Amount deposit_fee;
+
+  };
+
+/**
+ * Modified response to return to the frontend.
+ */
+static json_t *deposits_response;
 
 /**
  * Free the @a rctx.
@@ -157,6 +178,168 @@ free_transfer_track_context (struct TrackTransferContext 
*rctx)
   GNUNET_free (rctx);
 }
 
+/**
+ * Callback that frees all the elements in the hashmap
+ *
+ * @param cls closure, NULL
+ * @param key current key
+ * @param value a `struct MerchantInstance`
+ * @return GNUNET_YES if the iteration should continue,
+ * GNUNET_NO otherwise.
+ */
+static int
+hashmap_free (void *cls,
+              const struct GNUNET_HashCode *key,
+              void *value)
+{
+  struct TALER_Amount *amount = value;
+  GNUNET_free (amount);
+  /*NOTE: how to find out when iteration should stop?*/
+  return GNUNET_YES;
+}
+
+
+/**
+ * Builds JSON response containing the summed-up amounts
+ * from individual deposits.
+ *
+ * @param cls closure
+ * @param key map's current key
+ * @param map's current value
+ * @return GNUNET_YES if iteration is to be continued,
+ * GNUNET_NO otherwise.
+ */
+int
+build_deposits_response (void *cls,
+                         const struct GNUNET_HashCode *key,
+                         void *value)
+{
+  struct TrackTransferContext *rctx = cls;
+  json_t *element;
+  struct Entry *entry = value;
+  json_t *contract_terms;
+  json_t *order_id;
+
+  if (GNUNET_OK != db->find_contract_terms_from_hash (db->cls,
+                                                     &contract_terms,
+                                                     key,
+                                                     &rctx->mi->pubkey))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_NO;
+  }
+
+  order_id = json_object_get (contract_terms, "order_id");
+
+  element = json_pack ("{s:s, s:o, s:o}",
+                       "order_id", json_string_value (order_id),
+                       "deposit_value", TALER_JSON_from_amount 
(&entry->deposit_value),
+                       "deposit_fee", TALER_JSON_from_amount 
(&entry->deposit_fee));
+
+  if (NULL == order_id || NULL == element)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_NO;
+  }
+
+  json_array_append_new (deposits_response, element);
+
+  return GNUNET_YES;
+}
+
+/**
+ * Transform /track/transfer result as gotten from the exchange
+ * and transforms it in a format liked by the backoffice Web interface.
+ *
+ * @param result response from exchange's /track/transfer
+ * @result pointer to new JSON, or NULL upon errors.
+ */
+json_t *
+transform_response (const json_t *result, struct TrackTransferContext *rctx)
+{
+  json_t *deposits;
+  json_t *value;
+  json_t *result_mod = NULL;
+  size_t index;
+  const char *key;
+  struct GNUNET_HashCode h_key;
+  struct GNUNET_CONTAINER_MultiHashMap *map;
+  struct TALER_Amount iter_value;
+  struct TALER_Amount iter_fee;
+  struct Entry *current_entry;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Transforming /track/transfer response.\n");
+  struct GNUNET_JSON_Specification spec[] = {
+    TALER_JSON_spec_amount ("deposit_value", &iter_value),
+    TALER_JSON_spec_amount ("deposit_fee", &iter_fee),
+    GNUNET_JSON_spec_string ("h_contract_terms", &key),
+    GNUNET_JSON_spec_end ()
+  };
+  
+  map = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
+  deposits = json_object_get (result, "deposits");
+
+  json_array_foreach (deposits, index, value)
+  {
+    if (GNUNET_OK != GNUNET_JSON_parse (value,
+                                        spec,
+                                        NULL,
+                                        NULL))
+    {
+      GNUNET_break_op (0); 
+      return NULL;
+    }
+
+    GNUNET_CRYPTO_hash_from_string (key, &h_key);
+
+    if (NULL != (current_entry = GNUNET_CONTAINER_multihashmap_get (map, 
(const struct GNUNET_HashCode *) &h_key)))
+    {
+      /*The map already knows this h_contract_terms*/
+      if ((GNUNET_SYSERR == TALER_amount_add (&current_entry->deposit_value,
+                                             &current_entry->deposit_value,
+                                             &iter_value)) ||
+          (GNUNET_SYSERR == TALER_amount_add (&current_entry->deposit_fee,
+                                              &current_entry->deposit_fee,
+                                              &iter_fee)))
+        goto cleanup;
+    }
+    else
+    {
+      /*First time in the map for this h_contract_terms*/
+      current_entry = GNUNET_malloc (sizeof (struct Entry));
+      memcpy (&current_entry->deposit_value, &iter_value, sizeof (struct 
TALER_Amount));
+      memcpy (&current_entry->deposit_fee, &iter_fee, sizeof (struct 
TALER_Amount));
+
+      if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (map,
+                                                              (const struct 
GNUNET_HashCode *) &h_key,
+                                                              current_entry,
+                                                              
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+        goto cleanup;
+    }
+  }
+  deposits_response = json_array ();
+  
+  if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_iterate (map,
+                                                              
build_deposits_response,
+                                                              rctx))
+    goto cleanup;
+
+
+  result_mod = json_copy ((struct json_t *) result);
+  json_object_del (result_mod, "deposits");
+  json_object_set (result_mod, "deposits_sums", deposits_response);
+
+  goto cleanup;
+
+  cleanup:
+    GNUNET_CONTAINER_multihashmap_iterate (map,
+                                           &hashmap_free,
+                                           NULL);  
+    GNUNET_JSON_parse_free (spec);
+    GNUNET_CONTAINER_multihashmap_destroy (map);
+    return result_mod;
+}
 
 /**
  * Resume the given /track/transfer operation and send the given response.
@@ -215,7 +398,7 @@ track_transfer_cleanup (struct TM_HandlerContext *hc)
  */
 static void
 check_transfer (void *cls,
-                const struct GNUNET_HashCode *h_proposal_data,
+                const struct GNUNET_HashCode *h_contract_terms,
                 const struct TALER_CoinSpendPublicKeyP *coin_pub,
                 const struct TALER_Amount *amount_with_fee,
                 const struct TALER_Amount *deposit_fee,
@@ -244,7 +427,7 @@ check_transfer (void *cls,
                                      "conflict_offset", (json_int_t) 
rctx->current_offset,
                                      "exchange_transfer_proof", 
rctx->original_response,
                                      "coin_pub", GNUNET_JSON_from_data_auto 
(coin_pub),
-                                     "h_proposal_data", 
GNUNET_JSON_from_data_auto (&ttd->h_proposal_data),
+                                     "h_contract_terms", 
GNUNET_JSON_from_data_auto (&ttd->h_contract_terms),
                                      "amount_with_fee", TALER_JSON_from_amount 
(amount_with_fee),
                                      "deposit_fee", TALER_JSON_from_amount 
(deposit_fee));
     return;
@@ -287,6 +470,7 @@ wire_transfer_cb (void *cls,
   struct TrackTransferContext *rctx = cls;
   unsigned int i;
   int ret;
+  json_t *jresponse;
 
   rctx->wdh = NULL;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -330,7 +514,7 @@ wire_transfer_cb (void *cls,
     rctx->current_detail = &details[i];
     rctx->check_transfer_result = GNUNET_NO;
     ret = db->find_payments_by_hash_and_coin (db->cls,
-                                              &details[i].h_proposal_data,
+                                              &details[i].h_contract_terms,
                                               &rctx->mi->pubkey,
                                               &details[i].coin_pub,
                                               &check_transfer,
@@ -386,7 +570,7 @@ wire_transfer_cb (void *cls,
     /* Response is consistent with the /deposit we made, remember
        it for future reference */
     ret = db->store_coin_to_transfer (db->cls,
-                                      &details[i].h_proposal_data,
+                                      &details[i].h_contract_terms,
                                       &details[i].coin_pub,
                                       &rctx->wtid);
     if (GNUNET_OK != ret)
@@ -403,10 +587,24 @@ wire_transfer_cb (void *cls,
     }
   }
   rctx->original_response = NULL;
-  resume_track_transfer_with_response
-    (rctx,
-     MHD_HTTP_OK,
-     TMH_RESPONSE_make_json (json));
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "About to call tracks transformator.\n");
+
+  if (NULL == (jresponse = transform_response (json, rctx)))
+  {
+    resume_track_transfer_with_response
+      (rctx,
+       MHD_HTTP_INTERNAL_SERVER_ERROR,
+       TMH_RESPONSE_make_internal_error 
(TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR,
+                                         "Fail to elaborate the response."));
+    return;
+  }
+
+  resume_track_transfer_with_response (rctx,
+                                       MHD_HTTP_OK,
+                                       TMH_RESPONSE_make_json (jresponse));
+  json_decref (jresponse);
 }
 
 
@@ -485,9 +683,18 @@ proof_cb (void *cls,
           const json_t *proof)
 {
   struct TrackTransferContext *rctx = cls;
+  json_t *transformed_response;
+
+  if (NULL == (transformed_response = transform_response (proof, rctx)))
+  {
+    rctx->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
+    rctx->response = TMH_RESPONSE_make_internal_error 
(TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR,
+                                                       "Fail to elaborate 
response.");
+    return;
+  }
 
   rctx->response_code = MHD_HTTP_OK;
-  rctx->response = TMH_RESPONSE_make_json (proof);
+  rctx->response = TMH_RESPONSE_make_json (transformed_response);
 }
 
 
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 5381888..5299690 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -18,6 +18,7 @@
  * @brief database helper functions for postgres used by the merchant
  * @author Sree Harsha Totakura <address@hidden>
  * @author Christian Grothoff
+ * @author Marcello Stanisci
  */
 #include "platform.h"
 #include <gnunet/gnunet_util_lib.h>
@@ -146,7 +147,7 @@ postgres_drop_tables (void *cls)
   PG_EXEC_INDEX (pg, "DROP TABLE merchant_deposits;");
   PG_EXEC_INDEX (pg, "DROP TABLE merchant_transactions;");
   PG_EXEC_INDEX (pg, "DROP TABLE merchant_proofs;");
-  PG_EXEC_INDEX (pg, "DROP TABLE merchant_proposal_data;");
+  PG_EXEC_INDEX (pg, "DROP TABLE merchant_contract_terms;");
   return GNUNET_OK;
 }
 
@@ -164,18 +165,19 @@ postgres_initialize (void *cls)
 
   /* Setup tables */
   PG_EXEC (pg,
-           "CREATE TABLE IF NOT EXISTS merchant_proposal_data ("
+           "CREATE TABLE IF NOT EXISTS merchant_contract_terms ("
            "order_id VARCHAR NOT NULL"
            ",merchant_pub BYTEA NOT NULL"
-           ",proposal_data BYTEA NOT NULL"
-           ",h_proposal_data BYTEA NOT NULL"
+           ",contract_terms BYTEA NOT NULL"
+           ",h_contract_terms BYTEA NOT NULL"
            ",timestamp INT8 NOT NULL"
+           ",row_id BIGSERIAL"
           ",PRIMARY KEY (order_id, merchant_pub)"
            ");");
 
   PG_EXEC (pg,
            "CREATE TABLE IF NOT EXISTS merchant_transactions ("
-           " h_proposal_data BYTEA NOT NULL"
+           " h_contract_terms BYTEA NOT NULL"
            ",exchange_uri VARCHAR NOT NULL"
           ",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)"
            ",h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)"
@@ -184,13 +186,13 @@ postgres_initialize (void *cls)
            ",total_amount_val INT8 NOT NULL"
            ",total_amount_frac INT4 NOT NULL"
            ",total_amount_curr VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL"
-          ",PRIMARY KEY (h_proposal_data, merchant_pub)"
+          ",PRIMARY KEY (h_contract_terms, merchant_pub)"
            ");");
   PG_EXEC (pg,
            "CREATE TABLE IF NOT EXISTS merchant_deposits ("
-          " h_proposal_data BYTEA NOT NULL"
+          " h_contract_terms BYTEA NOT NULL"
           ",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)"
-          ",FOREIGN KEY (h_proposal_data, merchant_pub) REFERENCES 
merchant_transactions (h_proposal_data, merchant_pub)"
+          ",FOREIGN KEY (h_contract_terms, merchant_pub) REFERENCES 
merchant_transactions (h_contract_terms, merchant_pub)"
            ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)"
            ",amount_with_fee_val INT8 NOT NULL"
            ",amount_with_fee_frac INT4 NOT NULL"
@@ -200,7 +202,7 @@ postgres_initialize (void *cls)
            ",deposit_fee_curr VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL"
            ",signkey_pub BYTEA NOT NULL CHECK (LENGTH(signkey_pub)=32)"
            ",exchange_proof BYTEA NOT NULL"
-           ",PRIMARY KEY (h_proposal_data, coin_pub)"
+           ",PRIMARY KEY (h_contract_terms, coin_pub)"
            ");");
   PG_EXEC (pg,
            "CREATE TABLE IF NOT EXISTS merchant_proofs ("
@@ -211,19 +213,19 @@ postgres_initialize (void *cls)
            ",proof BYTEA NOT NULL"
            ",PRIMARY KEY (wtid, exchange_uri)"
            ");");
-  /* Note that transaction_id + coin_pub may actually be unknown to
+  /* Note that h_contract_terms + coin_pub may actually be unknown to
      us, e.g. someone else deposits something for us at the exchange.
      Hence those cannot be foreign keys into deposits/transactions! */
   PG_EXEC (pg,
            "CREATE TABLE IF NOT EXISTS merchant_transfers ("
-           " h_proposal_data BYTEA NOT NULL"
+           " h_contract_terms BYTEA NOT NULL"
            ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)"
            ",wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32)"
-           ",PRIMARY KEY (h_proposal_data, coin_pub)"
+           ",PRIMARY KEY (h_contract_terms, coin_pub)"
            ");");
   PG_EXEC_INDEX (pg,
                  "CREATE INDEX IF NOT EXISTS merchant_transfers_by_coin"
-                 " ON merchant_transfers (transaction_id, coin_pub)");
+                 " ON merchant_transfers (h_contract_terms, coin_pub)");
   PG_EXEC_INDEX (pg,
                  "CREATE INDEX IF NOT EXISTS merchant_transfers_by_wtid"
                  " ON merchant_transfers (wtid)");
@@ -232,7 +234,7 @@ postgres_initialize (void *cls)
   PG_PREPARE (pg,
               "insert_transaction",
               "INSERT INTO merchant_transactions"
-              "(h_proposal_data"
+              "(h_contract_terms"
               ",exchange_uri"
              ",merchant_pub"
               ",h_wire"
@@ -247,7 +249,7 @@ postgres_initialize (void *cls)
   PG_PREPARE (pg,
               "insert_deposit",
               "INSERT INTO merchant_deposits"
-              "(h_proposal_data"
+              "(h_contract_terms"
              ",merchant_pub"
               ",coin_pub"
               ",amount_with_fee_val"
@@ -263,7 +265,7 @@ postgres_initialize (void *cls)
   PG_PREPARE (pg,
               "insert_transfer",
               "INSERT INTO merchant_transfers"
-              "(h_proposal_data"
+              "(h_contract_terms"
               ",coin_pub"
               ",wtid) VALUES "
               "($1, $2, $3)",
@@ -280,48 +282,80 @@ postgres_initialize (void *cls)
               5);
 
   PG_PREPARE (pg,
-              "insert_proposal_data",
-              "INSERT INTO merchant_proposal_data"
+              "insert_contract_terms",
+              "INSERT INTO merchant_contract_terms"
               "(order_id"
               ",merchant_pub"
               ",timestamp"
-              ",proposal_data"
-              ",h_proposal_data)"
+              ",contract_terms"
+              ",h_contract_terms)"
               " VALUES "
               "($1, $2, $3, $4, $5)",
               4);
 
   PG_PREPARE (pg,
-              "find_proposal_data_from_hash",
+              "find_contract_terms_from_hash",
               "SELECT"
-              " proposal_data"
-              " FROM merchant_proposal_data"
+              " contract_terms"
+              " FROM merchant_contract_terms"
               " WHERE"
-              " h_proposal_data=$1"
+              " h_contract_terms=$1"
               " AND merchant_pub=$2",
               2);
 
   PG_PREPARE (pg,
-              "find_proposal_data",
+              "find_contract_terms",
               "SELECT"
-              " proposal_data"
-              " FROM merchant_proposal_data"
+              " contract_terms"
+              " FROM merchant_contract_terms"
               " WHERE"
               " order_id=$1"
               " AND merchant_pub=$2",
               2);
 
   PG_PREPARE (pg,
-              "find_proposal_data_by_date",
+              "find_contract_terms_by_date",
               "SELECT"
-              " proposal_data"
+              " contract_terms"
               ",order_id"
-              " FROM merchant_proposal_data"
+              ",row_id"
+              " FROM merchant_contract_terms"
               " WHERE"
-              " timestamp>=$1"
+              " timestamp<$1"
               " AND merchant_pub=$2"
-              " ORDER BY timestamp DESC",
-              2);
+              " ORDER BY row_id DESC, timestamp DESC"
+              " LIMIT $3",
+              3);
+
+  PG_PREPARE (pg,
+              "find_contract_terms_by_date_and_range",
+              "SELECT"
+              " contract_terms"
+              ",order_id"
+              ",row_id"
+              " FROM merchant_contract_terms"
+              " WHERE"
+              " timestamp<$1"
+              " AND merchant_pub=$2"
+              " AND row_id<$3"
+              " ORDER BY row_id DESC, timestamp DESC"
+              " LIMIT $4",
+              4);
+
+  PG_PREPARE (pg,
+              "find_contract_terms_by_date_and_range_future",
+              "SELECT"
+              " contract_terms"
+              ",order_id"
+              ",row_id"
+              " FROM merchant_contract_terms"
+              " WHERE"
+              " timestamp>$1"
+              " AND merchant_pub=$2"
+              " AND row_id>$3"
+              " ORDER BY row_id DESC, timestamp DESC"
+              " LIMIT $4",
+              4);
 
   /* Setup prepared "SELECT" statements */
   PG_PREPARE (pg,
@@ -335,7 +369,7 @@ postgres_initialize (void *cls)
               ",total_amount_frac"
               ",total_amount_curr"
               " FROM merchant_transactions"
-              " WHERE h_proposal_data=$1"
+              " WHERE h_contract_terms=$1"
              " AND merchant_pub=$2",
               2);
   PG_PREPARE (pg,
@@ -350,11 +384,11 @@ postgres_initialize (void *cls)
               ",deposit_fee_curr"
               ",exchange_proof"
               " FROM merchant_deposits"
-              " WHERE h_proposal_data=$1"
+              " WHERE h_contract_terms=$1"
               " AND merchant_pub=$2",
               2);
   PG_PREPARE (pg,
-              "find_deposits_by_tid_and_coin",
+              "find_deposits_by_hash_and_coin",
               "SELECT"
               " amount_with_fee_val"
               ",amount_with_fee_frac"
@@ -364,7 +398,7 @@ postgres_initialize (void *cls)
               ",deposit_fee_curr"
               ",exchange_proof"
               " FROM merchant_deposits"
-              " WHERE h_proposal_data=$1"
+              " WHERE h_contract_terms=$1"
               " AND merchant_pub=$2"
               " AND coin_pub=$3",
               3);
@@ -377,12 +411,12 @@ postgres_initialize (void *cls)
               ",merchant_proofs.proof"
               " FROM merchant_transfers"
               "   JOIN merchant_proofs USING (wtid)"
-              " WHERE h_proposal_data=$1",
+              " WHERE h_contract_terms=$1",
               1);
   PG_PREPARE (pg,
               "find_deposits_by_wtid",
               "SELECT"
-              " merchant_transfers.h_proposal_data"
+              " merchant_transfers.h_contract_terms"
               ",merchant_transfers.coin_pub"
               ",merchant_deposits.amount_with_fee_val"
               ",merchant_deposits.amount_with_fee_frac"
@@ -393,7 +427,7 @@ postgres_initialize (void *cls)
               ",merchant_deposits.exchange_proof"
               " FROM merchant_transfers"
               "   JOIN merchant_deposits"
-              "     ON (merchant_deposits.h_proposal_data = 
merchant_transfers.h_proposal_data"
+              "     ON (merchant_deposits.h_contract_terms = 
merchant_transfers.h_contract_terms"
               "       AND"
               "         merchant_deposits.coin_pub = 
merchant_transfers.coin_pub)"
               " WHERE wtid=$1",
@@ -410,19 +444,19 @@ postgres_initialize (void *cls)
 }
 
 /**
- * Retrieve proposal data given its transaction id's hashcode
+ * Retrieve proposal data given its proposal data's hashcode
  *
  * @param cls closure
- * @param h_transaction_id hashcode of the transaction id mentioned in this
- * proposal data
- * @param proposal_data where to store the retrieved proposal data
- * @return #GNUNET_OK on success, #GNUNET_NO if no contract is
+ * @param contract_terms where to store the retrieved proposal data
+ * @param h_contract_terms proposal data's hashcode that will be used to
+ * perform the lookup
+ * @return #GNUNET_OK on success, #GNUNET_NO if no proposal is
  * found, #GNUNET_SYSERR upon error
  */
 static int
-postgres_find_proposal_data_from_hash (void *cls,
-                                       json_t **proposal_data,
-                                       const struct GNUNET_HashCode 
*h_proposal_data,
+postgres_find_contract_terms_from_hash (void *cls,
+                                       json_t **contract_terms,
+                                       const struct GNUNET_HashCode 
*h_contract_terms,
                                        const struct TALER_MerchantPublicKeyP 
*merchant_pub)
 {
   struct PostgresClosure *pg = cls;
@@ -430,13 +464,13 @@ postgres_find_proposal_data_from_hash (void *cls,
   unsigned int i;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "find_proposal_data_from_hash",
+                                    "find_contract_terms_from_hash",
                                     params);
   i = PQntuples (result);
   if (1 < i)
@@ -450,8 +484,8 @@ postgres_find_proposal_data_from_hash (void *cls,
     return GNUNET_NO;
 
   struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_result_spec_json ("proposal_data",
-                               proposal_data),
+    TALER_PQ_result_spec_json ("contract_terms",
+                               contract_terms),
     GNUNET_PQ_result_spec_end
   };
   if (GNUNET_OK !=
@@ -469,18 +503,17 @@ postgres_find_proposal_data_from_hash (void *cls,
 
 
 /**
- * Retrieve proposal data given its transaction id's hashcode
+ * Retrieve proposal data given its order id.
  *
  * @param cls closure
- * @param h_transaction_id hashcode of the transaction id mentioned in this
- * proposal data
- * @param proposal_data where to store the retrieved proposal data
- * @return #GNUNET_OK on success, #GNUNET_NO if no contract is
+ * @param contract_terms where to store the retrieved proposal data
+ * @param order id order id used to perform the lookup
+ * @return #GNUNET_OK on success, #GNUNET_NO if no proposal is
  * found, #GNUNET_SYSERR upon error
  */
 static int
-postgres_find_proposal_data (void *cls,
-                             json_t **proposal_data,
+postgres_find_contract_terms (void *cls,
+                             json_t **contract_terms,
                              const char *order_id,
                              const struct TALER_MerchantPublicKeyP 
*merchant_pub)
 {
@@ -495,7 +528,7 @@ postgres_find_proposal_data (void *cls,
   };
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "find_proposal_data",
+                                    "find_contract_terms",
                                     params);
   i = PQntuples (result);
   if (1 < i)
@@ -509,8 +542,8 @@ postgres_find_proposal_data (void *cls,
     return GNUNET_NO;
 
   struct GNUNET_PQ_ResultSpec rs[] = {
-    TALER_PQ_result_spec_json ("proposal_data",
-                               proposal_data),
+    TALER_PQ_result_spec_json ("contract_terms",
+                               contract_terms),
     GNUNET_PQ_result_spec_end
   };
   if (GNUNET_OK !=
@@ -528,47 +561,46 @@ postgres_find_proposal_data (void *cls,
 
 
 /**
- * Insert proposal data and its transaction id's hashcode into db
+ * Insert proposal data and its hashcode into db
  *
  * @param cls closure
- * @param h_transaction_id hashcode of the transaction id mentioned in this
- * proposal data
- * @param proposal_data proposal data to store
+ * @param order_id identificator of the proposal being stored
+ * @param contract_terms proposal data to store
  * @return #GNUNET_OK on success, #GNUNET_SYSERR upon error
  */
 static int
-postgres_insert_proposal_data (void *cls,
+postgres_insert_contract_terms (void *cls,
                                const char *order_id,
                                const struct TALER_MerchantPublicKeyP 
*merchant_pub,
                                struct GNUNET_TIME_Absolute timestamp,
-                               const json_t *proposal_data)
+                               const json_t *contract_terms)
 {
   struct PostgresClosure *pg = cls;
   PGresult *result;
   int ret;
-  struct GNUNET_HashCode h_proposal_data;
+  struct GNUNET_HashCode h_contract_terms;
 
-  if (GNUNET_OK != TALER_JSON_hash (proposal_data,
-                                    &h_proposal_data))
+  if (GNUNET_OK != TALER_JSON_hash (contract_terms,
+                                    &h_contract_terms))
     return GNUNET_SYSERR;
 
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_string (order_id),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_absolute_time (&timestamp),
-    TALER_PQ_query_param_json (proposal_data),
-    GNUNET_PQ_query_param_auto_from_type (&h_proposal_data),
+    TALER_PQ_query_param_json (contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (&h_contract_terms),
     GNUNET_PQ_query_param_end
   };
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "insert_proposal_data",
+                                    "insert_contract_terms",
                                     params);
 
   /**
    * We don't treat a unique_violation (code '23505') error as
    * an actual error, since there is no problem if a frontend tries
-   * to store twice the same contract.  That is especially needed
+   * to store twice the same proposal.  That is especially needed
    * when DB-less frontends perform replayed payments.
    */
   if (PGRES_COMMAND_OK != PQresultStatus (result)
@@ -591,7 +623,8 @@ postgres_insert_proposal_data (void *cls,
  * Insert transaction data into the database.
  *
  * @param cls closure
- * @param transaction_id of the proposal
+ * @param h_contract_terms hashcode of the proposal data associated with the
+ * transaction being stored
  * @param merchant_pub merchant's public key
  * @param exchange_uri URI of the exchange
  * @param h_wire hash of our wire details
@@ -602,7 +635,7 @@ postgres_insert_proposal_data (void *cls,
  */
 static int
 postgres_store_transaction (void *cls,
-                            const struct GNUNET_HashCode *h_proposal_data,
+                            const struct GNUNET_HashCode *h_contract_terms,
                            const struct TALER_MerchantPublicKeyP *merchant_pub,
                             const char *exchange_uri,
                             const struct GNUNET_HashCode *h_wire,
@@ -615,7 +648,7 @@ postgres_store_transaction (void *cls,
   int ret;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_string (exchange_uri),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_auto_from_type (h_wire),
@@ -626,8 +659,8 @@ postgres_store_transaction (void *cls,
   };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Storing transaction with h_proposal_data '%s'\n",
-              GNUNET_h2s (h_proposal_data));
+              "Storing transaction with h_contract_terms '%s'\n",
+              GNUNET_h2s (h_contract_terms));
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "insert_transaction",
@@ -650,7 +683,7 @@ postgres_store_transaction (void *cls,
  * Insert payment confirmation from the exchange into the database.
  *
  * @param cls closure
- * @param transaction_id of the contract
+ * @param order_id identificator of the proposal associated with this revenue
  * @param merchant_pub merchant's public key
  * @param coin_pub public key of the coin
  * @param amount_with_fee amount the exchange will deposit for this coin
@@ -661,7 +694,7 @@ postgres_store_transaction (void *cls,
  */
 static int
 postgres_store_deposit (void *cls,
-                        const struct GNUNET_HashCode *h_proposal_data,
+                        const struct GNUNET_HashCode *h_contract_terms,
                         const struct TALER_MerchantPublicKeyP *merchant_pub,
                         const struct TALER_CoinSpendPublicKeyP *coin_pub,
                         const struct TALER_Amount *amount_with_fee,
@@ -674,7 +707,7 @@ postgres_store_deposit (void *cls,
   int ret;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
     TALER_PQ_query_param_amount (amount_with_fee),
@@ -685,8 +718,8 @@ postgres_store_deposit (void *cls,
   };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "storing payment for h_proposal_data '%s'\n",
-              GNUNET_h2s (h_proposal_data));
+              "storing payment for h_contract_terms '%s'\n",
+              GNUNET_h2s (h_contract_terms));
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "insert_deposit",
                                     params);
@@ -705,11 +738,11 @@ postgres_store_deposit (void *cls,
 
 
 /**
- * Insert mapping of @a coin_pub and @a transaction_id to
+ * Insert mapping of @a coin_pub and @a h_contract_terms to
  * corresponding @a wtid.
  *
  * @param cls closure
- * @param transaction_id ID of the contract
+ * @param h_contract_terms hashcode of the proposal data paid by @a coin_pub
  * @param coin_pub public key of the coin
  * @param wtid identifier of the wire transfer in which the exchange
  *             send us the money for the coin deposit
@@ -717,7 +750,7 @@ postgres_store_deposit (void *cls,
  */
 static int
 postgres_store_coin_to_transfer (void *cls,
-                                 const struct GNUNET_HashCode *h_proposal_data,
+                                 const struct GNUNET_HashCode 
*h_contract_terms,
                                  const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
                                  const struct TALER_WireTransferIdentifierRawP 
*wtid)
 {
@@ -726,7 +759,7 @@ postgres_store_coin_to_transfer (void *cls,
   int ret;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
     GNUNET_PQ_query_param_auto_from_type (wtid),
     GNUNET_PQ_query_param_end
@@ -798,22 +831,205 @@ postgres_store_transfer_to_proof (void *cls,
 }
 
 /**
- * Return transactions younger than the given date
+ * Lookup for a proposal, respecting the signature used by the
+ * /history's db methods.
  *
- * @param cls our plugin handle
- * @param date limit to transactions' age
- * @param cb function to call with transaction data, can be NULL
+ * @param cls db plugin handle
+ * @param order_id order id used to search for the proposal data
+ * @param merchant_pub public key of the merchant using this method
+ * @param cb the callback
+ * @param cb_cls closure to pass to the callback
+ * @return GNUNET_YES, GNUNET_NO, GNUNET_SYSERR according to the
+ * query being successful, unsuccessful, or generated errors.
+ */
+static int
+postgres_find_contract_terms_history (void *cls,
+                                     const char *order_id,
+                                     const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                     TALER_MERCHANTDB_ProposalDataCallback cb,
+                                     void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+  PGresult *result;
+  unsigned int i;
+  json_t *contract_terms;
+
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_string (order_id),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_end
+  };
+
+  result = GNUNET_PQ_exec_prepared (pg->conn,
+                                    "find_contract_terms",
+                                    params);
+  i = PQntuples (result);
+  if (1 < i)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Mupltiple proposal data share the same hashcode.\n");
+    return GNUNET_SYSERR;
+  }
+
+  if (0 == i)
+    return GNUNET_NO;
+
+  struct GNUNET_PQ_ResultSpec rs[] = {
+    TALER_PQ_result_spec_json ("contract_terms",
+                               &contract_terms),
+    GNUNET_PQ_result_spec_end
+  };
+  if (GNUNET_OK !=
+      GNUNET_PQ_extract_result (result,
+                                rs,
+                                0))
+  {
+    GNUNET_break (0);
+    PQclear (result);
+    return GNUNET_SYSERR;
+  }
+
+  cb (cb_cls,
+      order_id,
+      0,
+      contract_terms);
+
+  PQclear (result);
+  return GNUNET_OK;
+
+}                                     
+
+
+/**
+ * Return proposals whose timestamp are older than `date`.
+ * Among those proposals, only those ones being between the
+ * start-th and (start-nrows)-th record are returned.  The rows
+ * are sorted having the youngest first.
+ *
+ * @param cls our plugin handle.
+ * @param date only results older than this date are returned.
+ * @param merchant_pub instance's public key; only rows related to this
+ * instance are returned.
+ * @param start only rows with serial id less than start are returned.
+ * In other words, you lower `start` to get older records. The tipical
+ * usage is to firstly call `find_contract_terms_by_date`, so that you get
+ * the `nrows` youngest records. The oldest of those records will tell you
+ * from which timestamp and `start` you can query the DB in order to get
+ * furtherly older records, and so on. Alternatively, you can use always
+ * the same timestamp and just go behind in history by tuning `start`.
+ * @param nrows only nrows rows are returned.
+ * @param future if set to GNUNET_YES, retrieves rows younger than `date`.
+ * This is tipically used to show live updates on the merchant's backoffice
+ * Web interface.
+ * @param cb function to call with transaction data, can be NULL.
  * @param cb_cls closure for @a cb
  * @return numer of found tuples, #GNUNET_SYSERR upon error
  */
 static int
-postgres_find_proposal_data_by_date (void *cls,
+postgres_find_contract_terms_by_date_and_range (void *cls,
+                                               struct GNUNET_TIME_Absolute 
date,
+                                               const struct 
TALER_MerchantPublicKeyP *merchant_pub,
+                                               unsigned int start,
+                                               unsigned int nrows,
+                                               unsigned int future,
+                                               
TALER_MERCHANTDB_ProposalDataCallback cb,
+                                               void *cb_cls)
+{
+  uint64_t s64 = start;
+  uint64_t r64 = nrows;
+  struct PostgresClosure *pg = cls;
+  PGresult *result;
+  unsigned int n;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_absolute_time (&date),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_uint64 (&s64),
+    GNUNET_PQ_query_param_uint64 (&r64),
+    GNUNET_PQ_query_param_end
+  };
+
+  if (GNUNET_YES == future)
+    result = GNUNET_PQ_exec_prepared (pg->conn,
+                                      
"find_contract_terms_by_date_and_range_future",
+                                      params);
+  else
+    result = GNUNET_PQ_exec_prepared (pg->conn,
+                                      "find_contract_terms_by_date_and_range",
+                                      params);
+  if (PGRES_TUPLES_OK != PQresultStatus (result))
+  {
+    BREAK_DB_ERR (result);
+    PQclear (result);
+    return GNUNET_SYSERR;
+  }
+  if ( (0 == (n = PQntuples (result))) ||
+       (NULL == cb) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "No records found.\n");
+    PQclear (result);
+    return n;
+  }
+  for (unsigned int i = 0; i < n; i++)
+  {
+    char *order_id;
+    json_t *contract_terms;
+    uint64_t row_id;
+
+    struct GNUNET_PQ_ResultSpec rs[] = {
+      GNUNET_PQ_result_spec_string ("order_id",
+                                    &order_id),
+      TALER_PQ_result_spec_json ("contract_terms",
+                                 &contract_terms),
+      GNUNET_PQ_result_spec_uint64 ("row_id",
+                                    &row_id),
+      GNUNET_PQ_result_spec_end
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_PQ_extract_result (result,
+                                  rs,
+                                  i))
+    {
+      GNUNET_break (0);
+      PQclear (result);
+      return GNUNET_SYSERR;
+    }
+    cb (cb_cls,
+        order_id,
+        row_id,
+        contract_terms);
+
+    GNUNET_PQ_cleanup_result (rs);
+  }
+  PQclear (result);
+  return n;
+}
+
+
+/**
+ * Return proposals whose timestamp are older than `date`.
+ * The rows are sorted having the youngest first.
+ *
+ * @param cls our plugin handle.
+ * @param date only results older than this date are returned.
+ * @param merchant_pub instance's public key; only rows related to this
+ * instance are returned.
+ * @param nrows at most nrows rows are returned.
+ * @param cb function to call with transaction data, can be NULL.
+ * @param cb_cls closure for @a cb
+ * @return numer of found tuples, #GNUNET_SYSERR upon error
+ */
+static int
+postgres_find_contract_terms_by_date (void *cls,
                                      struct GNUNET_TIME_Absolute date,
                                      const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                     unsigned int nrows,
                                      TALER_MERCHANTDB_ProposalDataCallback cb,
                                      void *cb_cls)
 {
 
+  uint64_t r64 = nrows;
   struct PostgresClosure *pg = cls;
   PGresult *result;
   unsigned int n;
@@ -822,10 +1038,11 @@ postgres_find_proposal_data_by_date (void *cls,
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_absolute_time (&date),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_uint64 (&r64),
     GNUNET_PQ_query_param_end
   };
   result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "find_proposal_data_by_date",
+                                    "find_contract_terms_by_date",
                                     params);
   if (PGRES_TUPLES_OK != PQresultStatus (result))
   {
@@ -841,13 +1058,16 @@ postgres_find_proposal_data_by_date (void *cls,
   for (i = 0; i < n; i++)
   {
     char *order_id;
-    json_t *proposal_data;
+    json_t *contract_terms;
+    uint64_t row_id;
 
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_string ("order_id",
                                     &order_id),
-      TALER_PQ_result_spec_json ("proposal_data",
-                                 &proposal_data),
+      TALER_PQ_result_spec_json ("contract_terms",
+                                 &contract_terms),
+      GNUNET_PQ_result_spec_uint64 ("row_id",
+                                    &row_id),
       GNUNET_PQ_result_spec_end
     };
 
@@ -862,7 +1082,8 @@ postgres_find_proposal_data_by_date (void *cls,
     }
     cb (cb_cls,
         order_id,
-        proposal_data);
+        row_id,
+        contract_terms);
 
     GNUNET_PQ_cleanup_result (rs);
   }
@@ -874,9 +1095,8 @@ postgres_find_proposal_data_by_date (void *cls,
  * Find information about a transaction.
  *
  * @param cls our plugin handle
- * @param transaction_id the transaction id to search
- * @param merchant_pub merchant's public key. It's AND'd with transaction_id
- * in order to find the result.
+ * @param h_contract_terms value used to perform the lookup
+ * @param merchant_pub merchant's public key
  * @param cb function to call with transaction data
  * @param cb_cls closure for @a cb
  * @return #GNUNET_OK if found, #GNUNET_NO if not, #GNUNET_SYSERR
@@ -884,7 +1104,7 @@ postgres_find_proposal_data_by_date (void *cls,
  */
 static int
 postgres_find_transaction (void *cls,
-                           const struct GNUNET_HashCode *h_proposal_data,
+                           const struct GNUNET_HashCode *h_contract_terms,
                           const struct TALER_MerchantPublicKeyP *merchant_pub,
                            TALER_MERCHANTDB_TransactionCallback cb,
                            void *cb_cls)
@@ -892,14 +1112,14 @@ postgres_find_transaction (void *cls,
   struct PostgresClosure *pg = cls;
   PGresult *result;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Finding transaction for h_proposal_data '%s'\n",
-              GNUNET_h2s (h_proposal_data));
+              "Finding transaction for h_contract_terms '%s'\n",
+              GNUNET_h2s (h_contract_terms));
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "find_transaction",
@@ -913,8 +1133,8 @@ postgres_find_transaction (void *cls,
   if (0 == PQntuples (result))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Could NOT find transaction for h_proposal_data '%s'\n",
-                GNUNET_h2s (h_proposal_data));
+                "Could NOT find transaction for h_contract_terms '%s'\n",
+                GNUNET_h2s (h_contract_terms));
 
     PQclear (result);
     return GNUNET_NO;
@@ -958,7 +1178,7 @@ postgres_find_transaction (void *cls,
     cb (cb_cls,
        merchant_pub,
         exchange_uri,
-        h_proposal_data,
+        h_contract_terms,
         &h_wire,
         timestamp,
         refund_deadline,
@@ -971,10 +1191,11 @@ postgres_find_transaction (void *cls,
 
 
 /**
- * Lookup information about coin payments by transaction ID (and @a 
merchant_pub)
+ * Lookup information about coin payments by proposal data hash
+ * (and @a merchant_pub)
  *
  * @param cls closure
- * @param transaction_id key for the search
+ * @param h_contract_terms key for the search
  * @param merchant_pub merchant's public key
  * @param cb function to call with payment data
  * @param cb_cls closure for @a cb
@@ -983,7 +1204,7 @@ postgres_find_transaction (void *cls,
  */
 static int
 postgres_find_payments (void *cls,
-                        const struct GNUNET_HashCode *h_proposal_data,
+                        const struct GNUNET_HashCode *h_contract_terms,
                        const struct TALER_MerchantPublicKeyP *merchant_pub,
                         TALER_MERCHANTDB_CoinDepositCallback cb,
                         void *cb_cls)
@@ -993,13 +1214,13 @@ postgres_find_payments (void *cls,
   unsigned int i;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_end
   };
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "finding payment for h_proposal_data '%s'\n",
-              GNUNET_h2s (h_proposal_data));
+              "finding payment for h_contract_terms '%s'\n",
+              GNUNET_h2s (h_contract_terms));
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "find_deposits",
                                     params);
@@ -1044,7 +1265,7 @@ postgres_find_payments (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        h_proposal_data,
+        h_contract_terms,
         &coin_pub,
         &amount_with_fee,
         &deposit_fee,
@@ -1060,13 +1281,12 @@ postgres_find_payments (void *cls,
 
 
 /**
- * Lookup information about coin payments by transaction ID.
+ * Retrieve information about a deposited coin.
  *
  * @param cls closure
- * @param transaction_id key for the search
- * @param merchant_pub merchant's public key. It's AND'd with @a transaction_id
- *        in order to find the result.
- * @param coin_pub public key to use for the search
+ * @param h_contract_terms hashcode of the proposal data paid by @a coin_pub
+ * @param merchant_pub merchant's public key.
+ * @param coin_pub coin's public key used for the search
  * @param cb function to call with payment data
  * @param cb_cls closure for @a cb
  * @return #GNUNET_OK on success, #GNUNET_NO if transaction Id is unknown,
@@ -1074,7 +1294,7 @@ postgres_find_payments (void *cls,
  */
 static int
 postgres_find_payments_by_hash_and_coin (void *cls,
-                                         const struct GNUNET_HashCode 
*h_proposal_data,
+                                         const struct GNUNET_HashCode 
*h_contract_terms,
                                          const struct TALER_MerchantPublicKeyP 
*merchant_pub,
                                          const struct 
TALER_CoinSpendPublicKeyP *coin_pub,
                                          TALER_MERCHANTDB_CoinDepositCallback 
cb,
@@ -1085,14 +1305,14 @@ postgres_find_payments_by_hash_and_coin (void *cls,
   unsigned int i;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
     GNUNET_PQ_query_param_auto_from_type (coin_pub),
     GNUNET_PQ_query_param_end
   };
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
-                                    "find_deposits_by_tid_and_coin",
+                                    "find_deposits_by_hash_and_coin",
                                     params);
   if (PGRES_TUPLES_OK != PQresultStatus (result))
   {
@@ -1132,7 +1352,7 @@ postgres_find_payments_by_hash_and_coin (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        h_proposal_data,
+        h_contract_terms,
         coin_pub,
         &amount_with_fee,
         &deposit_fee,
@@ -1148,14 +1368,14 @@ postgres_find_payments_by_hash_and_coin (void *cls,
 
 
 /**
- * Lookup information about a transfer by @a transaction_id.  Note
+ * Lookup information about a transfer by @a h_contract_terms.  Note
  * that in theory there could be multiple wire transfers for a
- * single @a transaction_id, as the transaction may have involved
+ * single @a h_contract_terms, as the transaction may have involved
  * multiple coins and the coins may be spread over different wire
  * transfers.
  *
  * @param cls closure
- * @param transaction_id key for the search
+ * @param h_contract_terms key for the search
  * @param cb function to call with transfer data
  * @param cb_cls closure for @a cb
  * @return #GNUNET_OK on success, #GNUNET_NO if transaction Id is unknown,
@@ -1163,7 +1383,7 @@ postgres_find_payments_by_hash_and_coin (void *cls,
  */
 static int
 postgres_find_transfers_by_hash (void *cls,
-                                 const struct GNUNET_HashCode *h_proposal_data,
+                                 const struct GNUNET_HashCode 
*h_contract_terms,
                                  TALER_MERCHANTDB_TransferCallback cb,
                                  void *cb_cls)
 {
@@ -1172,7 +1392,7 @@ postgres_find_transfers_by_hash (void *cls,
   unsigned int i;
 
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (h_proposal_data),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_end
   };
   result = GNUNET_PQ_exec_prepared (pg->conn,
@@ -1219,7 +1439,7 @@ postgres_find_transfers_by_hash (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        h_proposal_data,
+        h_contract_terms,
         &coin_pub,
         &wtid,
         execution_time,
@@ -1272,15 +1492,15 @@ postgres_find_deposits_by_wtid (void *cls,
 
   for (i=0;i<PQntuples (result);i++)
   {
-    struct GNUNET_HashCode h_proposal_data;
+    struct GNUNET_HashCode h_contract_terms;
     struct TALER_CoinSpendPublicKeyP coin_pub;
     struct TALER_Amount amount_with_fee;
     struct TALER_Amount deposit_fee;
     json_t *exchange_proof;
 
     struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("h_proposal_data",
-                                            &h_proposal_data),
+      GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
+                                            &h_contract_terms),
       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                             &coin_pub),
       TALER_PQ_result_spec_amount ("amount_with_fee",
@@ -1302,7 +1522,7 @@ postgres_find_deposits_by_wtid (void *cls,
       return GNUNET_SYSERR;
     }
     cb (cb_cls,
-        &h_proposal_data,
+        &h_contract_terms,
         &coin_pub,
         &amount_with_fee,
         &deposit_fee,
@@ -1445,10 +1665,12 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
   plugin->find_transfers_by_hash = &postgres_find_transfers_by_hash;
   plugin->find_deposits_by_wtid = &postgres_find_deposits_by_wtid;
   plugin->find_proof_by_wtid = &postgres_find_proof_by_wtid;
-  plugin->insert_proposal_data = &postgres_insert_proposal_data;
-  plugin->find_proposal_data = &postgres_find_proposal_data;
-  plugin->find_proposal_data_by_date = &postgres_find_proposal_data_by_date;
-  plugin->find_proposal_data_from_hash = 
&postgres_find_proposal_data_from_hash;
+  plugin->insert_contract_terms = &postgres_insert_contract_terms;
+  plugin->find_contract_terms = &postgres_find_contract_terms;
+  plugin->find_contract_terms_history = &postgres_find_contract_terms_history;
+  plugin->find_contract_terms_by_date = &postgres_find_contract_terms_by_date;
+  plugin->find_contract_terms_by_date_and_range = 
&postgres_find_contract_terms_by_date_and_range;
+  plugin->find_contract_terms_from_hash = 
&postgres_find_contract_terms_from_hash;
 
   return plugin;
 }
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index fe52039..c512651 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -21,6 +21,7 @@
 
 #include "platform.h"
 #include <taler/taler_util.h>
+#include <taler/taler_json_lib.h>
 #include "taler_merchantdb_lib.h"
 #include <jansson.h>
 
@@ -70,14 +71,20 @@ static struct GNUNET_HashCode h_wire;
 const char *order_id;
 
 /**
+ * Transaction ID used to test the db query
+ * `find_contract_terms_by_date_and_range_future`
+ */
+const char *order_id_future;
+
+/**
  * Proposal's hash
  */
-struct GNUNET_HashCode h_proposal_data;
+struct GNUNET_HashCode h_contract_terms;
 
 /**
  * Proposal's hash.
  */
-struct GNUNET_HashCode h_proposal_data2;
+struct GNUNET_HashCode h_contract_terms2;
 
 /**
  * Time of the transaction.
@@ -143,7 +150,7 @@ static json_t *contract;
 /**
  * Mock proposal data, not need to be well-formed
  */
-static json_t *proposal_data;
+static json_t *contract_terms;
 
 
 
@@ -163,7 +170,7 @@ static void
 transaction_cb (void *cls,
                const struct TALER_MerchantPublicKeyP *amerchant_pub,
                 const char *aexchange_uri,
-                const struct GNUNET_HashCode *ah_proposal_data,
+                const struct GNUNET_HashCode *ah_contract_terms,
                 const struct GNUNET_HashCode *ah_wire,
                 struct GNUNET_TIME_Absolute atimestamp,
                 struct GNUNET_TIME_Absolute arefund_deadline,
@@ -173,8 +180,8 @@ transaction_cb (void *cls,
   CHECK (0 == memcmp (amerchant_pub,
                       &merchant_pub,
                      sizeof (struct TALER_MerchantPublicKeyP)));
-  CHECK (0 == memcmp (ah_proposal_data,
-                      &h_proposal_data,
+  CHECK (0 == memcmp (ah_contract_terms,
+                      &h_contract_terms,
                       sizeof (struct GNUNET_HashCode)));
   CHECK (0 == strcmp (aexchange_uri,
                       EXCHANGE_URI));
@@ -188,16 +195,18 @@ transaction_cb (void *cls,
 }
 
 /**
- * Callback for `find_proposal_data_by_date`.
+ * Callback for `find_contract_terms_by_date`.
  *
  * @param cls closure
  * @param order_id order id
- * @param proposal_data proposal data
+ * @param row_id row id in db
+ * @param contract_terms proposal data
  */
 static void
 pd_cb (void *cls,
        const char *order_id,
-       const json_t *proposal_data)
+       uint64_t row_id,
+       const json_t *contract_terms)
 {
   return;
 }
@@ -214,14 +223,14 @@ pd_cb (void *cls,
  */
 static void
 deposit_cb (void *cls,
-            const struct GNUNET_HashCode *ah_proposal_data,
+            const struct GNUNET_HashCode *ah_contract_terms,
             const struct TALER_CoinSpendPublicKeyP *acoin_pub,
             const struct TALER_Amount *aamount_with_fee,
             const struct TALER_Amount *adeposit_fee,
             const json_t *aexchange_proof)
 {
-  CHECK ((0 == memcmp (ah_proposal_data,
-                       &h_proposal_data,
+  CHECK ((0 == memcmp (ah_contract_terms,
+                       &h_contract_terms,
                        sizeof (struct GNUNET_HashCode))));
   CHECK (0 == memcmp (acoin_pub,
                       &coin_pub,
@@ -254,14 +263,14 @@ deposit_cb (void *cls,
  */
 static void
 transfer_cb (void *cls,
-             const struct GNUNET_HashCode *ah_proposal_data,
+             const struct GNUNET_HashCode *ah_contract_terms,
              const struct TALER_CoinSpendPublicKeyP *acoin_pub,
              const struct TALER_WireTransferIdentifierRawP *awtid,
              struct GNUNET_TIME_Absolute execution_time,
              const json_t *exchange_proof)
 {
-  CHECK (0 == memcmp (ah_proposal_data,
-                      &h_proposal_data,
+  CHECK (0 == memcmp (ah_contract_terms,
+                      &h_contract_terms,
                       sizeof (struct GNUNET_HashCode)));
 
   CHECK (0 == memcmp (acoin_pub,
@@ -321,15 +330,16 @@ run (void *cls)
 
   /* Prepare data for 'store_payment()' */
   RND_BLK (&h_wire);
-  RND_BLK (&h_proposal_data);
+  RND_BLK (&h_contract_terms);
   order_id = "test_ID";
+  order_id_future = "test_ID_future";
   RND_BLK (&signkey_pub);
   RND_BLK (&merchant_pub);
   RND_BLK (&wtid);
-  timestamp = GNUNET_TIME_absolute_get();
+  timestamp = GNUNET_TIME_absolute_get ();
   GNUNET_TIME_round_abs (&timestamp);
   delta = GNUNET_TIME_UNIT_MINUTES;
-  fake_now = GNUNET_TIME_absolute_subtract (timestamp, delta);
+  fake_now = GNUNET_TIME_absolute_add (timestamp, delta);
   refund_deadline = GNUNET_TIME_absolute_get();
   GNUNET_TIME_round_abs (&refund_deadline);
   GNUNET_assert (GNUNET_OK ==
@@ -350,40 +360,80 @@ run (void *cls)
                                       "test",
                                       json_string ("backenddb test B")));
   contract = json_object ();
-  proposal_data = json_object ();
+  contract_terms = json_object ();
 
-  TALER_JSON_hash (proposal_data,
-                   &h_proposal_data2);
+  TALER_JSON_hash (contract_terms,
+                   &h_contract_terms2);
 
   FAILIF (GNUNET_OK !=
-          plugin->insert_proposal_data (plugin->cls,
+          plugin->insert_contract_terms (plugin->cls,
                                         order_id,
                                         &merchant_pub,
                                         timestamp,
-                                        proposal_data));
+                                        contract_terms));
 
   json_t *out;
 
   FAILIF (GNUNET_OK !=
-          plugin->find_proposal_data (plugin->cls,
-                                      &out, // plain data
+          plugin->find_contract_terms (plugin->cls,
+                                      &out,
                                       order_id,
                                       &merchant_pub));
 
   FAILIF (GNUNET_OK !=
-          plugin->find_proposal_data_from_hash (plugin->cls,
-                                                &out, // plain data
-                                                &h_proposal_data2,
+          plugin->find_contract_terms_history (plugin->cls,
+                                              order_id,
+                                              &merchant_pub,
+                                              pd_cb,
+                                              NULL));
+
+  FAILIF (GNUNET_OK !=
+          plugin->find_contract_terms_from_hash (plugin->cls,
+                                                &out,
+                                                &h_contract_terms2,
                                                 &merchant_pub));
   FAILIF (1 !=
-          plugin->find_proposal_data_by_date (plugin->cls,
+          plugin->find_contract_terms_by_date_and_range (plugin->cls,
+                                                        fake_now,
+                                                        &merchant_pub,
+                                                        2,
+                                                        1,
+                                                        GNUNET_NO,
+                                                        pd_cb,
+                                                        NULL));
+  timestamp = GNUNET_TIME_absolute_get ();
+  GNUNET_TIME_round_abs (&timestamp);
+
+  FAILIF (GNUNET_OK !=
+          plugin->insert_contract_terms (plugin->cls,
+                                        order_id_future,
+                                        &merchant_pub,
+                                        timestamp,
+                                        contract_terms));
+
+  fake_now = GNUNET_TIME_absolute_subtract (timestamp, delta);
+
+  FAILIF (2 !=
+          plugin->find_contract_terms_by_date_and_range (plugin->cls,
+                                                        fake_now,
+                                                        &merchant_pub,
+                                                        0,
+                                                        5,
+                                                        GNUNET_YES,
+                                                        pd_cb,
+                                                        NULL));
+
+  FAILIF (0 !=
+          plugin->find_contract_terms_by_date (plugin->cls,
                                               fake_now,
                                               &merchant_pub,
+                                              1,
                                               pd_cb,
                                               NULL));
+
   FAILIF (GNUNET_OK !=
           plugin->store_transaction (plugin->cls,
-                                     &h_proposal_data,
+                                     &h_contract_terms,
                                     &merchant_pub,
                                      EXCHANGE_URI,
                                      &h_wire,
@@ -392,7 +442,7 @@ run (void *cls)
                                      &amount_with_fee));
   FAILIF (GNUNET_OK !=
           plugin->store_deposit (plugin->cls,
-                                 &h_proposal_data,
+                                 &h_contract_terms,
                                 &merchant_pub,
                                  &coin_pub,
                                  &amount_with_fee,
@@ -401,7 +451,7 @@ run (void *cls)
                                  deposit_proof));
   FAILIF (GNUNET_OK !=
           plugin->store_coin_to_transfer (plugin->cls,
-                                          &h_proposal_data,
+                                          &h_contract_terms,
                                           &coin_pub,
                                           &wtid));
   FAILIF (GNUNET_OK !=
@@ -413,20 +463,20 @@ run (void *cls)
                                            transfer_proof));
   FAILIF (GNUNET_OK !=
           plugin->find_transaction (plugin->cls,
-                                    &h_proposal_data,
+                                    &h_contract_terms,
                                    &merchant_pub,
                                     &transaction_cb,
                                     NULL));
 
   FAILIF (GNUNET_OK !=
           plugin->find_payments (plugin->cls,
-                                 &h_proposal_data,
+                                 &h_contract_terms,
                                  &merchant_pub,
                                  &deposit_cb,
                                  NULL));
   FAILIF (GNUNET_OK !=
           plugin->find_transfers_by_hash (plugin->cls,
-                                        &h_proposal_data,
+                                        &h_contract_terms,
                                         &transfer_cb,
                                         NULL));
   FAILIF (GNUNET_OK !=
diff --git a/src/include/taler_merchant_service.h 
b/src/include/taler_merchant_service.h
index 68ffe7f..aee46af 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -50,9 +50,9 @@ struct TALER_MERCHANT_ProposalLookupOperation;
  * @param cls closure
  * @param http_status HTTP response code, 200 indicates success;
  *                    0 if the backend's reply is bogus (fails to follow the 
protocol)
- * @param ec taler-specific error code 
+ * @param ec taler-specific error code
  * @param obj raw JSON reply, or error details if the request failed
- * @param proposal_data completed contract, NULL on error
+ * @param contract_terms completed contract, NULL on error
  * @param sig merchant's signature over the contract, NULL on error
  * @param hash proposal data's hashcode, NULL on error
  */
@@ -61,7 +61,7 @@ typedef void
                                     unsigned int http_status,
                                    enum TALER_ErrorCode ec,
                                     const json_t *obj,
-                                    const json_t *proposal_data,
+                                    const json_t *contract_terms,
                                     const struct TALER_MerchantSignatureP *sig,
                                     const struct GNUNET_HashCode *hash);
 
@@ -88,7 +88,7 @@ typedef void
  * backend
  * @param proposal_cb the callback to call when a reply for this request is 
available
  * @param proposal_cb_cls closure for @a proposal_cb
- * @return a handle for this request
+ * @return a handle for this request, NULL on error
  */
 struct TALER_MERCHANT_ProposalOperation *
 TALER_MERCHANT_order_put (struct GNUNET_CURL_Context *ctx,
@@ -162,7 +162,7 @@ struct TALER_MERCHANT_Pay;
  *                    can indicate success, depending on whether the 
interaction
  *                    was with a merchant frontend or backend;
  *                    0 if the merchant's reply is bogus (fails to follow the 
protocol)
- * @param ec taler-specific error code 
+ * @param ec taler-specific error code
  * @param obj the received JSON reply, with error details if the request failed
  */
 typedef void
@@ -359,11 +359,35 @@ TALER_MERCHANT_pay_cancel (struct TALER_MERCHANT_Pay *ph);
 struct TALER_MERCHANT_TrackTransferHandle;
 
 /**
+ * Information about the _total_ amount that was paid back
+ * by the exchange for a given h_contract_terms, by _one_ wire
+ * transfer.
+ */
+struct TALER_MERCHANT_TrackTransferDetails {
+
+  /**
+   * Total amount paid back by the exchange.
+   */
+  struct TALER_Amount deposit_value;
+
+  /**
+   * Total amount of deposit fees.
+   */
+  struct TALER_Amount deposit_fee;
+
+  /**
+   * Order ID associated whit this payment.
+   */
+  const char *order_id;
+
+};
+
+/**
  * Callbacks of this type are used to work the result of submitting a 
/track/transfer request to a merchant
  *
  * @param cls closure
  * @param http_status HTTP status code we got, 0 on exchange protocol violation
- * @param ec taler-specific error code 
+ * @param ec taler-specific error code
  * @param sign_key exchange key used to sign @a json, or NULL
  * @param json original json reply (may include signatures, those have then 
been
  *        validated already)
@@ -382,7 +406,7 @@ typedef void
                                          const struct GNUNET_HashCode *h_wire,
                                          const struct TALER_Amount 
*total_amount,
                                          unsigned int details_length,
-                                         const struct 
TALER_TrackTransferDetails *details);
+                                         const struct 
TALER_MERCHANT_TrackTransferDetails *details);
 
 /**
  * Request backend to return deposits associated with a given wtid.
@@ -484,7 +508,7 @@ struct TALER_MERCHANT_TransactionWireTransfer
  *
  * @param cls closure
  * @param http_status HTTP status code we got, 0 on exchange protocol violation
- * @param ec taler-specific error code 
+ * @param ec taler-specific error code
  * @param json original json reply from the backend
  * @param num_transfers number of wire transfers the exchange used for the 
transaction
  * @param transfers details about each transfer and which coins are aggregated 
in it
@@ -536,7 +560,7 @@ struct TALER_MERCHANT_HistoryOperation;
  *
  * @param cls closure
  * @param http_status HTTP status returned by the merchant backend
- * @param ec taler-specific error code 
+ * @param ec taler-specific error code
  * @param json actual body containing history
  */
 typedef void
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index 0dfbea8..db27e0e 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -32,16 +32,18 @@ struct TALER_MERCHANTDB_Plugin;
 
 
 /**
- * Tipically called by `find_proposal_data_by_date`.
+ * Tipically called by `find_contract_terms_by_date`.
  *
  * @param cls closure
  * @param order_id order id
- * @param proposal_data proposal data related to order id
+ * @param row_id serial numer of the transaction in the table,
+ * @param contract_terms proposal data related to order id
  */
  typedef void
  (*TALER_MERCHANTDB_ProposalDataCallback)(void *cls,
                                           const char *order_id,
-                                          const json_t *proposal_data);
+                                          uint64_t row_id,
+                                          const json_t *contract_terms);
 
 /**
  * Function called with information about a transaction.
@@ -49,7 +51,7 @@ struct TALER_MERCHANTDB_Plugin;
  * @param cls closure
  * @param merchant_pub merchant's public key
  * @param exchange_uri URI of the exchange
- * @param transaction_id proposal's transaction id
+ * @param h_contract_terms proposal data's hashcode
  * @param h_wire hash of our wire details
  * @param timestamp time of the confirmation
  * @param refund refund deadline
@@ -59,7 +61,7 @@ typedef void
 (*TALER_MERCHANTDB_TransactionCallback)(void *cls,
                                        const struct TALER_MerchantPublicKeyP 
*merchant_pub,
                                         const char *exchange_uri,
-                                        const struct GNUNET_HashCode 
*h_proposal_data,
+                                        const struct GNUNET_HashCode 
*h_contract_terms,
                                         const struct GNUNET_HashCode *h_wire,
                                         struct GNUNET_TIME_Absolute timestamp,
                                         struct GNUNET_TIME_Absolute refund,
@@ -70,7 +72,7 @@ typedef void
  * Function called with information about a coin that was deposited.
  *
  * @param cls closure
- * @param transaction_id of the contract
+ * @param h_contract_terms proposal data's hashcode
  * @param coin_pub public key of the coin
  * @param amount_with_fee amount the exchange will deposit for this coin
  * @param deposit_fee fee the exchange will charge for this coin
@@ -79,7 +81,7 @@ typedef void
  */
 typedef void
 (*TALER_MERCHANTDB_CoinDepositCallback)(void *cls,
-                                        const struct GNUNET_HashCode 
*h_proposal_data,
+                                        const struct GNUNET_HashCode 
*h_contract_terms,
                                         const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
                                         const struct TALER_Amount 
*amount_with_fee,
                                         const struct TALER_Amount *deposit_fee,
@@ -89,13 +91,13 @@ typedef void
 /**
  * Information about the wire transfer corresponding to
  * a deposit operation.  Note that it is in theory possible
- * that we have a @a transaction_id and @a coin_pub in the
+ * that we have a @a h_contract_terms and @a coin_pub in the
  * result that do not match a deposit that we know about,
  * for example because someone else deposited funds into
  * our account.
  *
  * @param cls closure
- * @param transaction_id ID of the contract
+ * @param h_contract_terms hashcode of the proposal data
  * @param coin_pub public key of the coin
  * @param wtid identifier of the wire transfer in which the exchange
  *             send us the money for the coin deposit
@@ -105,7 +107,7 @@ typedef void
  */
 typedef void
 (*TALER_MERCHANTDB_TransferCallback)(void *cls,
-                                     const struct GNUNET_HashCode 
*h_proposal_data,
+                                     const struct GNUNET_HashCode 
*h_contract_terms,
                                      const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
                                      const struct 
TALER_WireTransferIdentifierRawP *wtid,
                                      struct GNUNET_TIME_Absolute 
execution_time,
@@ -160,34 +162,36 @@ struct TALER_MERCHANTDB_Plugin
 
 
   /**
-   * Insert proposal data and its transaction id's hashcode into db
+   * Insert proposal data into db; the routine will internally hash and
+   * insert the proposal data's hashcode into the same row.
    *
    * @param cls closure
-   * @param h_transaction_id hashcode of the transaction id mentioned in this
-   * proposal data
-   * @param proposal_data proposal data to store
+   * @param order_id alphanumeric string that uniquely identifies the proposal
+   * @param merchant_pub merchant's public key
+   * @param timestamp timestamp of this proposal data
+   * @param contract_terms proposal data to store
    * @return #GNUNET_OK on success, #GNUNET_SYSERR upon error
    */
   int
-  (*insert_proposal_data) (void *cls,
+  (*insert_contract_terms) (void *cls,
                            const char *order_id,
                            const struct TALER_MerchantPublicKeyP *merchant_pub,
                            struct GNUNET_TIME_Absolute timestamp,
-                           const json_t *proposal_data);
+                           const json_t *contract_terms);
 
   /**
    * Retrieve proposal data given its order ID.
    *
    * @param cls closure
-   * @param proposal_data where to store the result
+   * @param contract_terms where to store the result
    * @param order_id order_id used to lookup.
    * @param merchant_pub instance's public key.
    * @return #GNUNET_OK on success, #GNUNET_NO if no contract is
    * found, #GNUNET_SYSERR upon error
    */
   int
-  (*find_proposal_data) (void *cls,
-                         json_t **proposal_data,
+  (*find_contract_terms) (void *cls,
+                         json_t **contract_terms,
                          const char *order_id,
                          const struct TALER_MerchantPublicKeyP *merchant_pub);
 
@@ -196,32 +200,86 @@ struct TALER_MERCHANTDB_Plugin
    * Retrieve proposal data given its hashcode
    *
    * @param cls closure
-   * @param proposal_data where to store the result
-   * @param h_proposal_data hashcode used to lookup.
+   * @param contract_terms where to store the result
+   * @param h_contract_terms hashcode used to lookup.
    * @param merchant_pub instance's public key.
    * @return #GNUNET_OK on success, #GNUNET_NO if no contract is
    * found, #GNUNET_SYSERR upon error
    */
   int
-  (*find_proposal_data_from_hash) (void *cls,
-                                   json_t **proposal_data,
-                                   const struct GNUNET_HashCode 
*h_proposal_data,
+  (*find_contract_terms_from_hash) (void *cls,
+                                   json_t **contract_terms,
+                                   const struct GNUNET_HashCode 
*h_contract_terms,
                                    const struct TALER_MerchantPublicKeyP 
*merchant_pub);
 
 
+
   /**
-   * Return proposal data and order id for all proposals younger than
-   * date.
+   * Return proposals whose timestamp are older than `date`.
+   * Among those proposals, only those ones being between the
+   * start-th and (start-nrows)-th record are returned.  The rows
+   * are sorted having the youngest first.
    *
-   * @param cls closure
-   * @param date limit to the oldest record
-   * @param cb callback called with proposal data and order id
-   * @param cb_cls closure for cb
+   * @param cls our plugin handle.
+   * @param date only results older than this date are returned.
+   * @param merchant_pub instance's public key; only rows related to this
+   * instance are returned.
+   * @param start only rows with serial id less than start are returned.
+   * @param nrows only nrows rows are returned.
+   * @param future if set to GNUNET_YES, retrieves rows younger than `date`.
+   * This is tipically used to show live updates on the merchant's backoffice
+   * @param cb function to call with transaction data, can be NULL.
+   * @param cb_cls closure for @a cb
+   * @return numer of found tuples, #GNUNET_SYSERR upon error
+   */
+  int
+  (*find_contract_terms_by_date_and_range) (void *cls,
+                                           struct GNUNET_TIME_Absolute date,
+                                           const struct 
TALER_MerchantPublicKeyP *merchant_pub,
+                                           unsigned int start,
+                                           unsigned int nrows,
+                                           unsigned int future,
+                                           
TALER_MERCHANTDB_ProposalDataCallback cb,
+                                           void *cb_cls);
+
+  /**
+   * Lookup for a proposal, respecting the signature used by the
+   * /history's db methods.
+   *
+   * @param cls db plugin handle
+   * @param order_id order id used to search for the proposal data
+   * @param merchant_pub public key of the merchant using this method
+   * @param cb the callback
+   * @param cb_cls closure to pass to the callback
+   * @return GNUNET_YES, GNUNET_NO, GNUNET_SYSERR according to the
+   * query being successful, unsuccessful, or generated errors.
+   */
+  int
+  (*find_contract_terms_history) (void *cls,
+                                 const char *order_id,
+                                 const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                 TALER_MERCHANTDB_ProposalDataCallback cb,
+                                 void *cb_cls);
+
+
+  /**
+   * Return proposals whose timestamp are older than `date`.
+   * The rows are sorted having the youngest first.*
+   *
+   * @param cls our plugin handle.
+   * @param date only results older than this date are returned.
+   * @param merchant_pub instance's public key; only rows related to this
+   * instance are returned.
+   * @param nrows only nrows rows are returned.
+   * @param cb function to call with transaction data, can be NULL.
+   * @param cb_cls closure for @a cb
+   * @return numer of found tuples, #GNUNET_SYSERR upon error
    */
   int
-  (*find_proposal_data_by_date) (void *cls,
+  (*find_contract_terms_by_date) (void *cls,
                                  struct GNUNET_TIME_Absolute date,
                                  const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                                 unsigned int nrows,
                                  TALER_MERCHANTDB_ProposalDataCallback cb,
                                  void *cb_cls);
 
@@ -230,10 +288,9 @@ struct TALER_MERCHANTDB_Plugin
    * Insert transaction data into the database.
    *
    * @param cls closure
-   * @param transaction_id of the contract
+   * @param h_contract_terms proposal data's hashcode
    * @param merchant_pub merchant's public key
    * @param exchange_uri URI of the exchange
-   * @param h_contract hash of the contract
    * @param h_wire hash of our wire details
    * @param timestamp time of the confirmation
    * @param refund refund deadline
@@ -242,7 +299,7 @@ struct TALER_MERCHANTDB_Plugin
    */
   int
   (*store_transaction) (void *cls,
-                        const struct GNUNET_HashCode *h_proposal_data,
+                        const struct GNUNET_HashCode *h_contract_terms,
                        const struct TALER_MerchantPublicKeyP *merchant_pub,
                         const char *exchange_uri,
                         const struct GNUNET_HashCode *h_wire,
@@ -255,7 +312,7 @@ struct TALER_MERCHANTDB_Plugin
    * Insert payment confirmation from the exchange into the database.
    *
    * @param cls closure
-   * @param transaction_id of the contract
+   * @param h_contract_terms proposal data's hashcode
    * @param merchant_pub merchant's public key
    * @param coin_pub public key of the coin
    * @param amount_with_fee amount the exchange will deposit for this coin
@@ -266,7 +323,7 @@ struct TALER_MERCHANTDB_Plugin
    */
   int
   (*store_deposit) (void *cls,
-                    const struct GNUNET_HashCode *h_proposal_data,
+                    const struct GNUNET_HashCode *h_contract_terms,
                     const struct TALER_MerchantPublicKeyP *merchant_pub,
                     const struct TALER_CoinSpendPublicKeyP *coin_pub,
                     const struct TALER_Amount *amount_with_fee,
@@ -276,11 +333,11 @@ struct TALER_MERCHANTDB_Plugin
 
 
   /**
-   * Insert mapping of @a coin_pub and @a transaction_id to
+   * Insert mapping of @a coin_pub and @a h_contract_terms to
    * corresponding @a wtid.
    *
    * @param cls closure
-   * @param transaction_id ID of the contract
+   * @param h_contract_terms proposal data's hashcode
    * @param coin_pub public key of the coin
    * @param wtid identifier of the wire transfer in which the exchange
    *             send us the money for the coin deposit
@@ -288,7 +345,7 @@ struct TALER_MERCHANTDB_Plugin
    */
   int
   (*store_coin_to_transfer) (void *cls,
-                             const struct GNUNET_HashCode *h_proposal_data,
+                             const struct GNUNET_HashCode *h_contract_terms,
                              const struct TALER_CoinSpendPublicKeyP *coin_pub,
                              const struct TALER_WireTransferIdentifierRawP 
*wtid);
 
@@ -333,56 +390,55 @@ struct TALER_MERCHANTDB_Plugin
    * Find information about a transaction.
    *
    * @param cls our plugin handle
-   * @param transaction_id the transaction id to search
-   * @param merchant_pub merchant's public key. It's AND'd with @a 
transaction_id
-   * in order to find the result.
+   * @param h_contract_terms proposal data's hashcode
+   * @param merchant_pub merchant's public key.
    * @param cb function to call with transaction data
    * @param cb_cls closure for @a cb
    * @return number of found tuples, #GNUNET_SYSERR upon error
    */
   int
   (*find_transaction) (void *cls,
-                       const struct GNUNET_HashCode *h_proposal_data,
+                       const struct GNUNET_HashCode *h_contract_terms,
                       const struct TALER_MerchantPublicKeyP *merchant_pub,
                        TALER_MERCHANTDB_TransactionCallback cb,
                        void *cb_cls);
 
 
   /**
-   * Lookup information about coin payments by transaction ID.
+   * Lookup information about coin payments by proposal data's hashcode.
    *
    * @param cls closure
-   * @param transaction_id key for the search
-   * @param merchant_pub merchant's public key. It's AND'd with @a 
transaction_id
+   * @param h_contract_terms proposal data's hashcode
+   * @param merchant_pub merchant's public key. It's AND'd with @a 
h_contract_terms
    *        in order to find the result.
    * @param cb function to call with payment data
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success, #GNUNET_NO if transaction Id is unknown,
+   * @return #GNUNET_OK on success, #GNUNET_NO if h_contract_terms is unknown,
    *         #GNUNET_SYSERR on hard errors
    */
   int
   (*find_payments) (void *cls,
-                    const struct GNUNET_HashCode *h_proposal_data,
+                    const struct GNUNET_HashCode *h_contract_terms,
                     const struct TALER_MerchantPublicKeyP *merchant_pub,
                     TALER_MERCHANTDB_CoinDepositCallback cb,
                     void *cb_cls);
 
   /**
-   * Lookup information about coin payments by transaction ID and coin.
+   * Lookup information about coin payments by h_contract_terms and coin.
    *
    * @param cls closure
-   * @param transaction_id key for the search
-   * @param merchant_pub merchant's public key. It's AND'd with @a 
transaction_id
+   * @param h_contract_terms proposal data's hashcode
+   * @param merchant_pub merchant's public key. It's AND'd with @a 
h_contract_terms
    *        in order to find the result.
    * @param coin_pub public key to use for the search
    * @param cb function to call with payment data
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success, #GNUNET_NO if transaction Id is unknown,
+   * @return #GNUNET_OK on success, #GNUNET_NO if h_contract_terms is unknown,
    *         #GNUNET_SYSERR on hard errors
    */
   int
   (*find_payments_by_hash_and_coin) (void *cls,
-                                     const struct GNUNET_HashCode 
*h_proposal_data,
+                                     const struct GNUNET_HashCode 
*h_contract_terms,
                                      const struct TALER_MerchantPublicKeyP 
*merchant_pub,
                                      const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
                                      TALER_MERCHANTDB_CoinDepositCallback cb,
@@ -390,22 +446,22 @@ struct TALER_MERCHANTDB_Plugin
 
 
   /**
-   * Lookup information about a transfer by @a transaction_id.  Note
+   * Lookup information about a transfer by @a h_contract_terms.  Note
    * that in theory there could be multiple wire transfers for a
-   * single @a transaction_id, as the transaction may have involved
+   * single @a h_contract_terms, as the transaction may have involved
    * multiple coins and the coins may be spread over different wire
    * transfers.
    *
    * @param cls closure
-   * @param transaction_id key for the search
+   * @param h_contract_terms proposal data's hashcode
    * @param cb function to call with transfer data
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success, #GNUNET_NO if transaction Id is unknown,
+   * @return #GNUNET_OK on success, #GNUNET_NO if h_contract_terms is unknown,
    *         #GNUNET_SYSERR on hard errors
    */
   int
   (*find_transfers_by_hash) (void *cls,
-                             const struct GNUNET_HashCode *h_proposal_data,
+                             const struct GNUNET_HashCode *h_contract_terms,
                              TALER_MERCHANTDB_TransferCallback cb,
                              void *cb_cls);
 
@@ -417,7 +473,7 @@ struct TALER_MERCHANTDB_Plugin
    * @param wtid wire transfer identifier to find matching transactions for
    * @param cb function to call with payment data
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success, #GNUNET_NO if transaction Id is unknown,
+   * @return #GNUNET_OK on success, #GNUNET_NO if h_contract_terms is unknown,
    *         #GNUNET_SYSERR on hard errors
    */
   int
@@ -435,7 +491,7 @@ struct TALER_MERCHANTDB_Plugin
    * @param wtid wire transfer identifier for the search
    * @param cb function to call with proof data
    * @param cb_cls closure for @a cb
-   * @return #GNUNET_OK on success, #GNUNET_NO if transaction Id is unknown,
+   * @return #GNUNET_OK on success, #GNUNET_NO if h_contract_terms is unknown,
    *         #GNUNET_SYSERR on hard errors
    */
   int
diff --git a/src/lib/merchant_api_history.c b/src/lib/merchant_api_history.c
index 69d09b8..a2c2d5f 100644
--- a/src/lib/merchant_api_history.c
+++ b/src/lib/merchant_api_history.c
@@ -137,7 +137,8 @@ history_raw_cb (void *cls,
  * @param ctx execution context
  * @param backend_uri base URL of the merchant backend
  * @param instance which merchant instance is performing this call
- * @param start return `delta` records starting from position `start`
+ * @param start return `delta` records starting from position `start`.
+ * If given as zero, then no initial skip of `start` records is done.
  * @param delta return `delta` records starting from position `start`
  * @param date only transactions younger than/equals to date will be returned
  * @param history_cb callback which will work the response gotten from the 
backend
@@ -163,6 +164,7 @@ TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
   ho->cb = history_cb;
   ho->cb_cls = history_cb_cls;
   seconds = date.abs_value_us / 1000LL / 1000LL;
+
   GNUNET_asprintf (&ho->url,
                    "%s/history?date=%llu&instance=%s&start=%d&delta=%d",
                    backend_uri,
@@ -170,6 +172,7 @@ TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
                    instance,
                    start,
                    delta);
+
   eh = curl_easy_init ();
   if (CURLE_OK != curl_easy_setopt (eh,
                                     CURLOPT_URL,
diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c
index 6910bde..9422e07 100644
--- a/src/lib/merchant_api_pay.c
+++ b/src/lib/merchant_api_pay.c
@@ -252,24 +252,19 @@ handle_pay_finished (void *cls,
  * @param ctx the execution loop context
  * @param merchant_uri base URI of the merchant's backend
  * @param instance which merchant instance will receive this payment
- * @param h_wire hash of the merchant’s account details
- * @param h_contract hash of the contact of the merchant with the customer
- * @param transaction_id transaction id for the transaction between merchant 
and customer
+ * @param h_contract_terms hashcode of the proposal being paid
  * @param amount total value of the contract to be paid to the merchant
  * @param max_fee maximum fee covered by the merchant (according to the 
contract)
  * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
  * @param merchant_sig signature from the merchant over the original contract
  * @param timestamp timestamp when the contract was finalized, must match 
approximately the current time of the merchant
- * @param transaction_id transaction id for the transaction between merchant 
and customer
- * @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 merchant (can be zero if refunds are not allowed)
  * @param pay_deadline maximum time limit to pay for this contract
+ * @param h_wire hash of the merchant’s account details
  * @param exchange_uri URI of the exchange that the coins belong to
+ * @param order_id order id of the proposal being paid
  * @param num_coins number of coins used to pay
  * @param coins array of coins we use to pay
- * @param coin_sig the signature made with purpose 
#TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s 
private key.
- * @param max_fee maximum fee covered by the merchant (according to the 
contract)
- * @param amount total value of the contract to be paid to the merchant
  * @param pay_cb the callback to call when a reply for this request is 
available
  * @param pay_cb_cls closure for @a pay_cb
  * @return a handle for this request
@@ -278,7 +273,7 @@ struct TALER_MERCHANT_Pay *
 TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
                           const char *merchant_uri,
                           const char *instance,
-                           const struct GNUNET_HashCode *h_proposal_data,
+                           const struct GNUNET_HashCode *h_contract_terms,
                           const struct TALER_Amount *amount,
                           const struct TALER_Amount *max_fee,
                            const struct TALER_MerchantPublicKeyP *merchant_pub,
@@ -312,7 +307,7 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
 
   dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
   dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
-  dr.h_proposal_data = *h_proposal_data;
+  dr.h_contract_terms = *h_contract_terms;
   dr.h_wire = *h_wire;
   dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
   dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
@@ -340,6 +335,12 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
     }
     TALER_amount_hton (&dr.deposit_fee,
                       &fee);
+    {
+      TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
+                       TALER_amount2s (&coin->amount_with_fee));
+      TALER_LOG_DEBUG ("... fee was %s\n",
+                       TALER_amount2s (&fee));
+    }
 
     GNUNET_CRYPTO_eddsa_sign (&coin->coin_priv.eddsa_priv,
                              &dr.purpose,
@@ -371,6 +372,7 @@ TALER_MERCHANT_pay_wallet (struct GNUNET_CURL_Context *ctx,
  *
  * @param ctx the execution loop context
  * @param merchant_uri base URI of the merchant's backend
+ * @param merchant_pub public key of the merchant
  * @param exchange_uri URI of the exchange that the coins belong to
  * @param num_coins number of coins used to pay
  * @param coins array of coins we use to pay
diff --git a/src/lib/merchant_api_proposal.c b/src/lib/merchant_api_proposal.c
index c3e5873..c200ce5 100644
--- a/src/lib/merchant_api_proposal.c
+++ b/src/lib/merchant_api_proposal.c
@@ -115,14 +115,14 @@ handle_proposal_finished (void *cls,
                           const json_t *json)
 {
   struct TALER_MERCHANT_ProposalOperation *po = cls;
-  json_t *proposal_data;
+  json_t *contract_terms;
   const struct TALER_MerchantSignatureP *sigp;
   const struct GNUNET_HashCode *hashp;
   struct TALER_MerchantSignatureP sig;
   struct GNUNET_HashCode hash;
 
   po->job = NULL;
-  proposal_data = NULL;
+  contract_terms = NULL;
   sigp = NULL;
   hashp = NULL;
   switch (response_code)
@@ -132,12 +132,12 @@ handle_proposal_finished (void *cls,
     case MHD_HTTP_OK:
     {
       struct GNUNET_JSON_Specification spec[] = {
-        GNUNET_JSON_spec_json ("data", &proposal_data),
+        GNUNET_JSON_spec_json ("data", &contract_terms),
         GNUNET_JSON_spec_fixed_auto ("sig", &sig),
         GNUNET_JSON_spec_fixed_auto ("hash", &hash),
         GNUNET_JSON_spec_end()
       };
-  
+
       if (GNUNET_OK !=
           GNUNET_JSON_parse (json,
                              spec,
@@ -182,11 +182,11 @@ handle_proposal_finished (void *cls,
           response_code,
          TALER_JSON_get_error_code (json),
           json,
-          proposal_data,
+          contract_terms,
           sigp,
           hashp);
-  if (NULL != proposal_data)
-    json_decref (proposal_data);
+  if (NULL != contract_terms)
+    json_decref (contract_terms);
 }
 
 
@@ -200,7 +200,7 @@ handle_proposal_finished (void *cls,
  * @param proposal_cb the callback to call when a reply for this request is
  * available
  * @param proposal_cb_cls closure for @a proposal_cb
- * @return a handle for this request
+ * @return a handle for this request, NULL on error
  */
 struct TALER_MERCHANT_ProposalOperation *
 TALER_MERCHANT_order_put (struct GNUNET_CURL_Context *ctx,
@@ -225,10 +225,15 @@ TALER_MERCHANT_order_put (struct GNUNET_CURL_Context *ctx,
   req = json_pack ("{s:O}",
                    "order", (json_t *) order);
   eh = curl_easy_init ();
-  GNUNET_assert (NULL != (po->json_enc =
-                          json_dumps (req,
-                                      JSON_COMPACT)));
+  po->json_enc = json_dumps (req,
+                             JSON_COMPACT);
   json_decref (req);
+  if (NULL == po->json_enc)
+  {
+    GNUNET_break (0);
+    GNUNET_free (po);
+    return NULL;
+  }
   GNUNET_assert (CURLE_OK ==
                  curl_easy_setopt (eh,
                                    CURLOPT_URL,
@@ -310,7 +315,7 @@ TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context 
*ctx,
                                     CURLOPT_URL,
                                     plo->url))
   {
-    GNUNET_break (0);  
+    GNUNET_break (0);
     return NULL;
   }
 
diff --git a/src/lib/merchant_api_track_transaction.c 
b/src/lib/merchant_api_track_transaction.c
index abb1d29..4e11acc 100644
--- a/src/lib/merchant_api_track_transaction.c
+++ b/src/lib/merchant_api_track_transaction.c
@@ -64,24 +64,6 @@ struct TALER_MERCHANT_TrackTransactionHandle
   struct GNUNET_CURL_Context *ctx;
 };
 
-
-/**
- * Free data in @a transfers.
- *
- * @param num_transfers length of the @a transfers array
- * @param transfers information about wire transfers to free
- */
-static void
-free_transfers (unsigned int num_transfers,
-                struct TALER_MERCHANT_TransactionWireTransfer *transfers)
-{
-  unsigned int i;
-
-  for (i=0;i<num_transfers;i++)
-    GNUNET_free (transfers[i].coins);
-}
-
-
 /**
  * Handle #MHD_HTTP_OK response to /track/transaction.
  * Parse @a json and if successful call the callback in @a tdo.
@@ -167,7 +149,7 @@ handle_track_transaction_finished (void *cls,
  * @param ctx execution context
  * @param backend_uri base URI of the backend
  * @param instance which merchant instance is going to be tracked
- * @param transaction_id which transaction should we trace
+ * @param order_id order id pointing to the transaction being tracked
  * @param track_transaction_cb the callback to call when a reply for this 
request is available
  * @param track_transaction_cb_cls closure for @a track_transaction_cb
  * @return a handle for this request
@@ -213,7 +195,7 @@ TALER_MERCHANT_track_transaction (struct 
GNUNET_CURL_Context *ctx,
  * Cancel a /track/transaction request.  This function cannot be used
  * on a request handle if a response is already served for it.
  *
- * @param co the transaction's tracking handle
+ * @param tdo handle to the tracking operation being cancelled
  */
 void
 TALER_MERCHANT_track_transaction_cancel (struct 
TALER_MERCHANT_TrackTransactionHandle *tdo)
diff --git a/src/lib/merchant_api_track_transfer.c 
b/src/lib/merchant_api_track_transfer.c
index 10e6981..0de4ac8 100644
--- a/src/lib/merchant_api_track_transfer.c
+++ b/src/lib/merchant_api_track_transfer.c
@@ -85,7 +85,7 @@ static int
 check_track_transfer_response_ok (struct TALER_MERCHANT_TrackTransferHandle 
*wdh,
                                   const json_t *json)
 {
-  json_t *details_j;
+  json_t *deposits;
   struct GNUNET_HashCode h_wire;
   struct TALER_Amount total_amount;
   struct TALER_MerchantPublicKeyP merchant_pub;
@@ -95,7 +95,7 @@ check_track_transfer_response_ok (struct 
TALER_MERCHANT_TrackTransferHandle *wdh
     TALER_JSON_spec_amount ("total", &total_amount),
     GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
     GNUNET_JSON_spec_fixed_auto ("H_wire", &h_wire),
-    GNUNET_JSON_spec_json ("deposits", &details_j),
+    GNUNET_JSON_spec_json ("deposits_sums", &deposits),
     GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub),
     GNUNET_JSON_spec_end()
   };
@@ -108,25 +108,24 @@ check_track_transfer_response_ok (struct 
TALER_MERCHANT_TrackTransferHandle *wdh
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  num_details = json_array_size (details_j);
+  num_details = json_array_size (deposits);
   {
-    struct TALER_TrackTransferDetails details[num_details];
+    struct TALER_MERCHANT_TrackTransferDetails details[num_details];
     unsigned int i;
 
     for (i=0;i<num_details;i++)
     {
-      struct TALER_TrackTransferDetails *detail = &details[i];
-      struct json_t *detail_j = json_array_get (details_j, i);
+      struct TALER_MERCHANT_TrackTransferDetails *detail = &details[i];
+      json_t *deposit = json_array_get (deposits, i);
       struct GNUNET_JSON_Specification spec_detail[] = {
-        GNUNET_JSON_spec_fixed_auto ("h_proposal_data", 
&detail->h_proposal_data),
-        GNUNET_JSON_spec_fixed_auto ("coin_pub", &detail->coin_pub),
-        TALER_JSON_spec_amount ("deposit_value", &detail->coin_value),
-        TALER_JSON_spec_amount ("deposit_fee", &detail->coin_fee),
+        GNUNET_JSON_spec_string ("order_id", &detail->order_id),
+        TALER_JSON_spec_amount ("deposit_value", &detail->deposit_value),
+        TALER_JSON_spec_amount ("deposit_fee", &detail->deposit_fee),
         GNUNET_JSON_spec_end()
       };
 
       if (GNUNET_OK !=
-          GNUNET_JSON_parse (detail_j,
+          GNUNET_JSON_parse (deposit,
                              spec_detail,
                              NULL, NULL))
       {
@@ -214,7 +213,7 @@ handle_track_transfer_finished (void *cls,
  * @param backend_uri base URI of the backend
  * @param instance which merchant instance is going to be tracked
  * @param wtid base32 string indicating a wtid
- * @param exchange base URL of the exchange in charge of returning the wanted 
information
+ * @param exchange_uri base URL of the exchange in charge of returning the 
wanted information
  * @param track_transfer_cb the callback to call when a reply for this request 
is available
  * @param track_transfer_cb_cls closure for @a contract_cb
  * @return a handle for this request
@@ -264,7 +263,7 @@ TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context 
*ctx,
  * Cancel a /track/transfer request.  This function cannot be used
  * on a request handle if a response is already served for it.
  *
- * @param co the transfer's tracking handle
+ * @param tdo handle to the tracking operation being cancelled
  */
 void
 TALER_MERCHANT_track_transfer_cancel (struct 
TALER_MERCHANT_TrackTransferHandle *tdo)
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
index c2d728c..6d0f613 100644
--- a/src/lib/test_merchant_api.c
+++ b/src/lib/test_merchant_api.c
@@ -421,7 +421,7 @@ struct Command
        * FIXME: verify in the code that this bit is actually proposal
        * data and not the whole proposal.
        */
-      json_t *proposal_data;
+      json_t *contract_terms;
 
       /**
        * Proposal's signature.
@@ -481,7 +481,7 @@ struct Command
       /**
        * Hashcode of the proposal data associated to this payment.
        */
-      struct GNUNET_HashCode h_proposal_data;
+      struct GNUNET_HashCode h_contract_terms;
 
       /**
        * Merchant's public key
@@ -596,6 +596,17 @@ struct Command
        */
       struct TALER_MERCHANT_HistoryOperation *ho;
 
+      /**
+       * The backend will return records with row_id
+       * less than this value.
+       */
+      unsigned int start;
+
+      /**
+       * The backend will return at most `nrows` records.
+       */
+      unsigned int nrows;
+
     } history;
 
 
@@ -1032,7 +1043,7 @@ reserve_withdraw_cb (void *cls,
  * @param ec taler-specific error code
  * @param obj the full received JSON reply, or
  *            error details if the request failed
- * @param proposal_data the order + additional information provided by the
+ * @param contract_terms the order + additional information provided by the
  * backend, NULL on error.
  * @param sig merchant's signature over the contract, NULL on error
  * @param h_contract hash of the contract, NULL on error
@@ -1042,7 +1053,7 @@ proposal_cb (void *cls,
              unsigned int http_status,
             enum TALER_ErrorCode ec,
              const json_t *obj,
-             const json_t *proposal_data,
+             const json_t *contract_terms,
              const struct TALER_MerchantSignatureP *sig,
              const struct GNUNET_HashCode *hash)
 {
@@ -1053,7 +1064,7 @@ proposal_cb (void *cls,
   switch (http_status)
   {
   case MHD_HTTP_OK:
-    cmd->details.proposal.proposal_data = json_incref ((json_t *) 
proposal_data);
+    cmd->details.proposal.contract_terms = json_incref ((json_t *) 
contract_terms);
     cmd->details.proposal.merchant_sig = *sig;
     cmd->details.proposal.hash = *hash;
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1094,7 +1105,7 @@ pay_cb (void *cls,
   struct Command *cmd = &is->commands[is->ip];
   struct PaymentResponsePS mr;
   struct GNUNET_CRYPTO_EddsaSignature sig;
-  struct GNUNET_HashCode h_proposal_data;
+  struct GNUNET_HashCode h_contract_terms;
   const char *error_name;
   unsigned int error_line;
 
@@ -1114,7 +1125,7 @@ pay_cb (void *cls,
     /* Check signature */
     struct GNUNET_JSON_Specification spec[] = {
       GNUNET_JSON_spec_fixed_auto ("sig", &sig),
-      GNUNET_JSON_spec_fixed_auto ("h_proposal_data", &h_proposal_data),
+      GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &h_contract_terms),
       GNUNET_JSON_spec_end ()
     };
     if (GNUNET_OK !=
@@ -1133,7 +1144,7 @@ pay_cb (void *cls,
     }
     mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
     mr.purpose.size = htonl (sizeof (mr));
-    mr.h_proposal_data = h_proposal_data;
+    mr.h_contract_terms = h_contract_terms;
     if (GNUNET_OK !=
         GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
                                     &mr.purpose,
@@ -1200,11 +1211,15 @@ track_transfer_cb (void *cls,
                    const struct GNUNET_HashCode *h_wire,
                    const struct TALER_Amount *total_amount,
                    unsigned int details_length,
-                   const struct TALER_TrackTransferDetails *details)
+                   const struct TALER_MERCHANT_TrackTransferDetails *details)
 {
   struct InterpreterState *is = cls;
   struct Command *cmd = &is->commands[is->ip];
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Tracked transfers: '%s'.\n",
+              json_dumps (json, JSON_INDENT (1)));
+
   cmd->details.track_transfer.tdo = NULL;
   if (cmd->expected_response_code != http_status)
   {
@@ -1218,90 +1233,12 @@ track_transfer_cb (void *cls,
   }
   switch (http_status)
   {
-  case MHD_HTTP_OK:
-    {
-      const struct Command *ref;
-      unsigned int i;
-      int found;
-
-      /**
-       * Retrieve the deposit operation that is supposed
-       * to have been paid by the wtid used in this operation.
-       * After that, check if that operation is actually mentioned
-       * in the returned data.
-       */
-      ref = find_command (is,
-                          cmd->details.track_transfer.expected_pay_ref);
-      GNUNET_assert (NULL != ref);
-      found = GNUNET_NO;
-
-      /**
-       * Iterating over the details makes little sense now,
-       * as each payment involves exatcly one coin.
-       */
-      for (i=0;i<details_length;i++)
-      {
-        struct TALER_Amount amount_with_fee;
-        struct TALER_Amount amount_without_fee;
-        struct TALER_Amount deposit_fee;
-        const struct Command *cref;
-        const struct Command *proposal_ref;
-        struct TALER_CoinSpendPublicKeyP coin_pub;
-
-        /* Extract */
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_string_to_amount 
(ref->details.pay.amount_without_fee,
-                                               &amount_without_fee));
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_string_to_amount 
(ref->details.pay.amount_with_fee,
-                                               &amount_with_fee));
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_subtract (&deposit_fee,
-                                              &amount_with_fee,
-                                              &amount_without_fee));
-
-        /* Find coin ('s public key) associated with the retrieved
-           deposit. Yes, one deposit - one coin. */
-       cref = find_command (is,
-                             ref->details.pay.coin_ref);
-        proposal_ref = find_command (is,
-                                     ref->details.pay.contract_ref);
-        GNUNET_assert (NULL != cref);
-        GNUNET_assert (NULL != proposal_ref);
-       switch (cref->oc)
-       {
-       case OC_WITHDRAW_SIGN:
-          GNUNET_CRYPTO_eddsa_key_get_public
-            (&cref->details.reserve_withdraw.coin_priv.eddsa_priv,
-             &coin_pub.eddsa_pub);
-         break;
-       default:
-         GNUNET_assert (0);
-       }
-
-        if ( (0 == memcmp (&details[i].h_proposal_data,
-                           &proposal_ref->details.proposal.hash,
-                           sizeof (struct GNUNET_HashCode))) &&
-             (0 == TALER_amount_cmp (&details[i].coin_value,
-                                     &amount_with_fee)) &&
-             (0 == TALER_amount_cmp (&details[i].coin_fee,
-                                     &deposit_fee)) &&
-             (0 == memcmp (&details[i].coin_pub,
-                           &coin_pub,
-                           sizeof (struct TALER_CoinSpendPublicKeyP))) )
-          found = GNUNET_YES;
-      }
-      if (GNUNET_NO == found)
-      {
-        GNUNET_break (0);
-        json_dumpf (json, stderr, 0);
-        fail (is);
-        return;
-      }
+    case MHD_HTTP_OK:
       break;
-    }
-  default:
-    break;
+
+    default:
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Unhandled HTTP status.\n");
   }
   next_command (is);
 }
@@ -1361,9 +1298,6 @@ track_transaction_cb (void *cls,
   }
   if (MHD_HTTP_OK != http_status)
     fail (is);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "/track/order response: %s\n",
-              json_dumps (json, JSON_INDENT (1)));
   next_command (is);
 }
 
@@ -1484,7 +1418,7 @@ interpreter_run (void *cls)
       GNUNET_assert (NULL != ref);
 
       order_id =
-        json_string_value (json_object_get 
(ref->details.proposal.proposal_data,
+        json_string_value (json_object_get 
(ref->details.proposal.contract_terms,
                                             "order_id"));
       GNUNET_assert (NULL !=
                       (cmd->details.proposal_lookup.plo
@@ -1719,7 +1653,7 @@ interpreter_run (void *cls)
                           cmd->details.pay.contract_ref);
       GNUNET_assert (NULL != ref);
       merchant_sig = ref->details.proposal.merchant_sig;
-      GNUNET_assert (NULL != ref->details.proposal.proposal_data);
+      GNUNET_assert (NULL != ref->details.proposal.contract_terms);
       {
         /* Get information that need to be replied in the deposit permission */
         struct GNUNET_JSON_Specification spec[] = {
@@ -1735,7 +1669,7 @@ interpreter_run (void *cls)
         };
 
         if (GNUNET_OK !=
-            GNUNET_JSON_parse (ref->details.proposal.proposal_data,
+            GNUNET_JSON_parse (ref->details.proposal.contract_terms,
                                spec,
                                &error_name,
                                &error_line))
@@ -1910,7 +1844,7 @@ interpreter_run (void *cls)
     GNUNET_assert (NULL != ref);
     proposal_ref = find_command (is,
                                  ref->details.pay.contract_ref);
-    order_id = json_string_value (json_object_get 
(proposal_ref->details.proposal.proposal_data,
+    order_id = json_string_value (json_object_get 
(proposal_ref->details.proposal.contract_terms,
                                         "order_id"));
     cmd->details.track_transaction.tth =
       TALER_MERCHANT_track_transaction (ctx,
@@ -1927,8 +1861,8 @@ interpreter_run (void *cls)
        (cmd->details.history.ho = TALER_MERCHANT_history (ctx,
                                                          MERCHANT_URI,
                                                           instance,
-                                                          0,
-                                                          20,
+                                                          
cmd->details.history.start,
+                                                          
cmd->details.history.nrows,
                                                          
cmd->details.history.date,
                                                          history_cb,
                                                          is)))
@@ -2049,10 +1983,10 @@ do_shutdown (void *cls)
         TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
         cmd->details.proposal.po = NULL;
       }
-      if (NULL != cmd->details.proposal.proposal_data)
+      if (NULL != cmd->details.proposal.contract_terms)
       {
-        json_decref (cmd->details.proposal.proposal_data);
-        cmd->details.proposal.proposal_data = NULL;
+        json_decref (cmd->details.proposal.contract_terms);
+        cmd->details.proposal.contract_terms = NULL;
       }
       break;
     case OC_PAY:
@@ -2418,15 +2352,19 @@ run (void *cls)
       .label = "history-1",
       .expected_response_code = MHD_HTTP_OK,
       /*all records to be returned*/
-      .details.history.date.abs_value_us = 0,
-      .details.history.nresult = 2
+      .details.history.date.abs_value_us = 43 * 1000LL * 1000LL,
+      .details.history.nresult = 2,
+      .details.history.start = 10,
+      .details.history.nrows = 10
     },
     { .oc = OC_HISTORY,
       .label = "history-2",
       .expected_response_code = MHD_HTTP_OK,
-      /*no records to be returned, as limit is in the future*/
-      .details.history.date.abs_value_us = 43 * 1000LL * 1000LL,
-      .details.history.nresult = 0
+      /*no records returned, time limit too ancient*/
+      .details.history.date.abs_value_us = 0,
+      .details.history.nresult = 0,
+      .details.history.start = 10,
+      .details.history.nrows = 10
     },
 
     /* end of testcase */
diff --git a/src/lib/test_merchant_api.conf b/src/lib/test_merchant_api.conf
index 8a9b80c..5e72ed0 100644
--- a/src/lib/test_merchant_api.conf
+++ b/src/lib/test_merchant_api.conf
@@ -53,6 +53,16 @@ WIRE-FEE-2023 = EUR:0.01
 WIRE-FEE-2024 = EUR:0.01
 WIRE-FEE-2025 = EUR:0.01
 WIRE-FEE-2026 = EUR:0.01
+CLOSING-FEE-2017 = EUR:0.01
+CLOSING-FEE-2018 = EUR:0.01
+CLOSING-FEE-2019 = EUR:0.01
+CLOSING-FEE-2020 = EUR:0.01
+CLOSING-FEE-2021 = EUR:0.01
+CLOSING-FEE-2022 = EUR:0.01
+CLOSING-FEE-2023 = EUR:0.01
+CLOSING-FEE-2024 = EUR:0.01
+CLOSING-FEE-2025 = EUR:0.01
+CLOSING-FEE-2026 = EUR:0.01
 
 
 [merchant-exchange-test]
@@ -115,14 +125,13 @@ MASTER_PUBLIC_KEY = 
T1VVFQZZARQ1CMF4BN58EE7SKTW5AV2BS18S87ZEGYS4S29J6DNG
 [exchangedb-postgres]
 DB_CONN_STR = "postgres:///talercheck"
 
-[exchange-wire-incoming-test]
+[exchange-wire-test]
 # This is the response we give out for the /wire request.  It provides
 # wallets with the bank information for transfers to the exchange.
 # Note that the _incoming_ account is #3, while the
 # outgoing account of the exchange (see below) is #2.
 TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.json
 
-[exchange-wire-outgoing-test]
 # What is the main website of the bank?
 BANK_URI = "http://localhost:8083/";
 # From which account at the 'bank' should outgoing wire transfers be made?
diff --git a/src/merchant-tools/Makefile.am b/src/merchant-tools/Makefile.am
index 97f448d..2adee91 100644
--- a/src/merchant-tools/Makefile.am
+++ b/src/merchant-tools/Makefile.am
@@ -1,10 +1,9 @@
-
-
 # This Makefile.am is in the public domain
 AM_CPPFLAGS = -I$(top_srcdir)/src/include
 
 bin_PROGRAMS = \
-  taler-merchant-dbinit
+  taler-merchant-dbinit \
+  taler-merchant-generate-payments
 
 taler_merchant_dbinit_SOURCES = \
   taler-merchant-dbinit.c
@@ -15,3 +14,21 @@ taler_merchant_dbinit_LDADD = \
   -lgnunetutil \
   -ltalerutil \
   -ltalerpq
+
+taler_merchant_generate_payments_SOURCES = \
+  taler-merchant-generate-payments.c
+
+taler_merchant_generate_payments_LDADD = \
+  $(top_srcdir)/src/backenddb/libtalermerchantdb.la \
+  $(top_srcdir)/src/lib/libtalermerchant.la \
+  $(LIBGCRYPT_LIBS) \
+  -ltalerfakebank \
+  -ltalerexchange \
+  -ltalerjson \
+  -ltalerutil \
+  -lgnunetjson \
+  -lgnunetcurl \
+  -lgnunetutil \
+  -ljansson
+
+SUBDIRS = mitm
diff --git a/src/merchant-tools/README b/src/merchant-tools/README
new file mode 100644
index 0000000..993a87e
--- /dev/null
+++ b/src/merchant-tools/README
@@ -0,0 +1,51 @@
+
+** Taler Merchant Payments Generator **
+
+=== INTRODUCTION ===
+
+The tool contained in this directory is used to populate the
+merchant's and exchange's database with fake payments.
+It is mainly used for debugging applications that need some
+payments to be in place.
+
+It is mandatory to give it a config file that contains information
+about the setup to target. Note that the merchant and the exchange
+tun by this command will use their own config files, so just few values
+are required for it to run.
+
+
+=== COFIGURATION ===
+
+Any config file must look like the following one.
+
+[payments-generator]
+
+# where on this machine the exchange listens; note that
+# this exchange must be among the ones accepted by the
+# merchant
+exchange = http://localexchange/
+
+# where on this machine the merchant listens
+merchant = http://localshop/
+
+# bank's URI of the customer who withdraws coins.
+# Must be known by the exchange.
+bank = http://localbank/
+
+# must match an instance known by the merchant
+instance = FSF
+
+# must match the currency used by merchant and exchange
+currency = EUR
+
+
+=== INVOCATION ===
+
+taler-merchant-generate-payments -c config/file.conf [-n ITERATIONS]
+
+The -n option instructs the tools about how many iteration of all
+the (internal) commands we want to execute.
+
+** Taler Merchant Dbinit **
+
+TBD
diff --git a/src/merchant-tools/mitm/Makefile.in 
b/src/merchant-tools/mitm/Makefile.in
new file mode 100644
index 0000000..4a9f33a
--- /dev/null
+++ b/src/merchant-tools/mitm/Makefile.in
@@ -0,0 +1,21 @@
+
+.PHONY: all
+all:
+       true
+
+.PHONY: install-data
+install-data:
+       install -m 444 -Dt @prefix@/share/taler/ merchant-mitm.wsgi
+
+.PHONY: install
+install: install-data
+       pip3 install . --install-option="address@hidden@" --upgrade --no-deps
+       install -m 544 -Dt @prefix@/bin taler-merchant-mitm
+
+# need a way to make 'make check' happy in this subdir.
+# This component is still too young to be tested.
+.PHONY: check
+check:
+       true
+clean:
+       true
diff --git a/src/merchant-tools/mitm/README b/src/merchant-tools/mitm/README
new file mode 100644
index 0000000..662cbe3
--- /dev/null
+++ b/src/merchant-tools/mitm/README
@@ -0,0 +1,25 @@
+
+=== INTRODUCTION ===
+
+This directory contain a Web server that listens for
+requests addressed to the exchange, relays them to the
+exchange, and returns a modified response to the caller.
+
+The modifications are made to test error management in the
+merchant, and are driven by a HTTP header that instructs the
+proxy about the modifications to be made.
+
+=== INVOCATION ===
+
+After a successful 'make install', a command called 'taler-merchant-mitm'
+is placed under <prefix>/bin - make sure PATH points at it.
+
+To run the mitm, give the following commands:
+
+$ taler-merchant-mitm --exchange URL [--port PORT]
+
+The '--exchange' option is mandatory, telling the mitm where to
+forward the requests addressed to the exchange.
+
+The second option just sets the port number where the mitm
+listens, defaulting to 5000.
diff --git a/src/merchant-tools/mitm/merchant-mitm.wsgi.in 
b/src/merchant-tools/mitm/merchant-mitm.wsgi.in
new file mode 100644
index 0000000..3fb4cfb
--- /dev/null
+++ b/src/merchant-tools/mitm/merchant-mitm.wsgi.in
@@ -0,0 +1,21 @@
+
+import sys
+
+if sys.version_info.major < 3:
+    print("The merchant mitm needs to run with Python>=3.4")
+    sys.exit(1)
+
+import os
+import site
+import logging
+
+logging.basicConfig(level=logging.INFO)
+
+site.addsitedir("%s/lib/python%d.%d/site-packages" % (
+    "@prefix@", 
+    sys.version_info.major,
+    sys.version_info.minor))
+
+import talermerchantmitm.mitm
+
+application = talermerchantmitm.mitm.app
diff --git a/src/merchant-tools/mitm/setup.py b/src/merchant-tools/mitm/setup.py
new file mode 100644
index 0000000..f5eedea
--- /dev/null
+++ b/src/merchant-tools/mitm/setup.py
@@ -0,0 +1,11 @@
+from setuptools import setup, find_packages
+setup(name='talermerchantmitm',
+      version='0.0',
+      description='Layer generating errors for testing',
+      url='git://taler.net/merchant',
+      author='Marcello Stanisci',
+      author_email='address@hidden',
+      license='GPL',
+      packages=find_packages(),
+      install_requires=["Flask>=0.10"],
+      zip_safe=False)
diff --git a/src/merchant-tools/mitm/taler-merchant-mitm.in 
b/src/merchant-tools/mitm/taler-merchant-mitm.in
new file mode 100644
index 0000000..39a7275
--- /dev/null
+++ b/src/merchant-tools/mitm/taler-merchant-mitm.in
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+"""
+Stand-alone script to manage the merchant's MITM
+error generator.
+"""
+
+import argparse
+import sys
+import os
+
+parser = argparse.ArgumentParser()
+
+parser.add_argument('--exchange',
+                    '-e',
+                    help="Exchange URL",
+                    metavar="URL",
+                    type=str,
+                    dest="exchange_url",
+                    default=None)
+
+
+parser.add_argument("--port",
+                    "-p",
+                    help="Port where the MITM listens",
+                    dest="port",
+                    type=int,
+                    default=5000,
+                    metavar="PORT")
+
+args = parser.parse_args()
+
+if getattr(args, 'exchange_url', None) is None:
+    parser.print_help()
+    sys.exit(1)
+
+uwsgi_logfmt = "%(ltime) %(proto) %(method) %(uri) %(proto) => %(status)"
+
+os.environ["TALER_EXCHANGE_URL"] = args.exchange_url
+os.execlp("uwsgi", "uwsgi",
+            "--master",
+            "--die-on-term",
+            "--log-format", uwsgi_logfmt,
+            "--http", ":%d" % args.port,
+            "--wsgi-file", "@prefix@/share/taler/merchant-mitm.wsgi")
diff --git a/NEWS b/src/merchant-tools/mitm/talermerchantmitm/__init__.py
similarity index 100%
copy from NEWS
copy to src/merchant-tools/mitm/talermerchantmitm/__init__.py
diff --git a/src/merchant-tools/mitm/talermerchantmitm/mitm.py 
b/src/merchant-tools/mitm/talermerchantmitm/mitm.py
new file mode 100644
index 0000000..c998a1c
--- /dev/null
+++ b/src/merchant-tools/mitm/talermerchantmitm/mitm.py
@@ -0,0 +1,78 @@
+#This file is part of TALER
+#Copyright (C) 2014, 2015, 2016, 2017 GNUnet e.V. and INRIA
+#
+#TALER is free software; you can redistribute it and/or modify it under the
+#terms of the GNU Lesser General Public License as published by the Free 
Software
+#Foundation; either version 2.1, or (at your option) any later version.
+#
+#TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+#WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+#A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
details.
+#
+#You should have received a copy of the GNU Lesser General Public License 
along with
+#TALER; see the file COPYING.LGPL.  If not, see <http://www.gnu.org/licenses/>
+
+# @author Marcello Stanisci
+# @brief Error generator for responses coming from the exchange
+
+from flask import (request,
+                   Flask,
+                   make_response)
+import requests
+from urllib.parse import (urljoin,
+                          urlencode,
+                          urlparse,
+                          urlunparse)
+from pytaler import amount
+import base64
+import os
+import logging
+import json
+from random import randint
+from datetime import datetime
+
+app = Flask(__name__)
+app.secret_key = base64.b64encode(os.urandom(64)).decode('utf-8')
+logger = logging.getLogger(__name__)
+exchange_url = os.environ.get("TALER_EXCHANGE_URL")
+assert(None != exchange_url)
+
+def track_transaction(resp):
+    return resp.text
+
+def track_transfer(resp):
+    return resp.text
+
+def keys(resp):
+    try:
+        keys = resp.json()
+        # Put here data perturbation logic
+        return json.dumps(keys)
+    except Exception:
+        return resp.text
+
address@hidden('/', defaults={'path': ''})
address@hidden('/<path:path>', methods=["GET", "POST"])
+def all(path):
+    body = request.get_json()
+    url = list(urlparse(request.url))
+    xurl = urlparse(exchange_url)
+    url[0] = xurl[0]
+    url[1] = xurl[1]
+    url = urlunparse(url)
+    if "POST" == request.method:
+        r = requests.post(urljoin(url, path), json=body)
+    else:
+        r = requests.get(urljoin(url, path), json=body)
+    dispatcher = {
+        "track_transaction": track_transaction,
+        "track_transfer": track_transfer,
+        "keys": keys
+    }
+    func = dispatcher.get(request.headers.get("X-Taler-Mitm"),
+                          lambda x: x.text)
+    response = make_response(func(r))
+    for key, value in r.headers.items():
+        if key not in ("Server", "Content-Length"):
+            response.headers[key] = value
+    return response, r.status_code
diff --git a/src/merchant-tools/taler-merchant-dbinit.c 
b/src/merchant-tools/taler-merchant-dbinit.c
index 35b5a1b..e846100 100644
--- a/src/merchant-tools/taler-merchant-dbinit.c
+++ b/src/merchant-tools/taler-merchant-dbinit.c
@@ -87,10 +87,13 @@ int
 main (int argc,
       char *const *argv)
 {
-  const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    {'r', "reset", NULL,
-     "reset database (DANGEROUS: all existing data is lost!)", 0,
-     &GNUNET_GETOPT_set_one, &reset_db},
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+
+    GNUNET_GETOPT_option_flag ('r',
+                                  "reset",
+                                  "reset database (DANGEROUS: all existing 
data is lost!)",
+                                  &reset_db),
+
     GNUNET_GETOPT_OPTION_END
   };
 
diff --git a/src/samples/generate_payments.c 
b/src/merchant-tools/taler-merchant-generate-payments.c
similarity index 69%
rename from src/samples/generate_payments.c
rename to src/merchant-tools/taler-merchant-generate-payments.c
index d887eff..9a4c3c0 100644
--- a/src/samples/generate_payments.c
+++ b/src/merchant-tools/taler-merchant-generate-payments.c
@@ -26,13 +26,69 @@
 #include <gnunet/gnunet_curl_lib.h>
 #include <microhttpd.h>
 
-#define EXCHANGE_URI "http://localexchange/";
-#define MERCHANT_URI "http://localshop/";
-#define BANK_URI "http://localbank/";
-#define INSTANCE "FSF"
-#define CURRENCY "EUR"
+/**
+ * The exchange process launched by the generator
+ */
+static struct GNUNET_OS_Process *exchanged;
+
+/**
+ * The merchant process launched by the generator
+ */
+static struct GNUNET_OS_Process *merchantd;
+
+/**
+ * How many times the command list should be rerun.
+ */
+static unsigned int times = 1;
+
+/**
+ * Current iteration of commands
+ */
+static unsigned int j = 0;
+
+/**
+ * Indicates whether we use an external exchange.
+ * By default, the generator forks a local exchange.
+ */
+static int remote_exchange = 0;
+
+/**
+ * Indicates whether we use an external merchant.
+ * By default, the generator tries to fork a local
+ * merchant.
+ */
+static int remote_merchant = 0;
+
+/**
+ * Exchange URI to withdraw from and deposit to.
+ */
+static char *exchange_uri;
+
+/**
+ * Base URL of exchange's admin interface.
+ */
+static char *exchange_uri_admin;
+
+/**
+ * Merchant backend to get proposals from and pay.
+ */
+static char *merchant_uri;
 
-#define ORDER_MAX_SIZE 1000
+/**
+ * Customer's bank URI, communicated at withdrawal time
+ * to the exchange; must be the same as the exchange's bank.
+ */
+static char *bank_uri;
+
+/**
+ * Which merchant instance we use.
+ */
+static char *instance;
+
+/**
+ * Currency used to generate payments.
+ */
+static char *currency;
 
 /**
  * Task run on timeout.
@@ -175,9 +231,11 @@ struct Command
       /**
        * String describing the denomination value we should withdraw.
        * A corresponding denomination key must exist in the exchange's
-       * offerings.  Can be NULL if @e pk is set instead.
+       * offerings. Can be NULL if @e pk is set instead.
+       * The interpreter must free this value after it doesn't need it
+       * anymore.
        */
-      const char *amount;
+      char *amount;
 
       /**
        * If @e amount is NULL, this specifies the denomination key to
@@ -257,11 +315,16 @@ struct Command
     {
 
       /**
-       * The order.
-       * It's dynamically generated because we need different transaction_id
-       * for different merchant instances.
+       * Max deposit fee accepted by the merchant.
+       * Given in the form "CURRENCY:X.Y".
+       */
+      char *max_fee;
+
+      /**
+       * Proposal overall price.
+       * Given in the form "CURRENCY:X.Y".
        */
-      char order[ORDER_MAX_SIZE];
+      char *amount;
 
       /**
        * Handle to the active PUT /proposal operation, or NULL.
@@ -273,7 +336,7 @@ struct Command
        * FIXME: verify in the code that this bit is actually proposal
        * data and not the whole proposal.
        */
-      json_t *proposal_data;
+      json_t *contract_terms;
 
       /**
        * Proposal's signature.
@@ -333,7 +396,7 @@ struct Command
       /**
        * Hashcode of the proposal data associated to this payment.
        */
-      struct GNUNET_HashCode h_proposal_data;
+      struct GNUNET_HashCode h_contract_terms;
 
       /**
        * Merchant's public key
@@ -406,7 +469,7 @@ next_command (struct InterpreterState *is)
  * @param ec taler-specific error code
  * @param obj the full received JSON reply, or
  *            error details if the request failed
- * @param proposal_data the order + additional information provided by the
+ * @param contract_terms the order + additional information provided by the
  * backend, NULL on error.
  * @param sig merchant's signature over the contract, NULL on error
  * @param h_contract hash of the contract, NULL on error
@@ -416,7 +479,7 @@ proposal_cb (void *cls,
              unsigned int http_status,
             enum TALER_ErrorCode ec,
              const json_t *obj,
-             const json_t *proposal_data,
+             const json_t *contract_terms,
              const struct TALER_MerchantSignatureP *sig,
              const struct GNUNET_HashCode *hash)
 {
@@ -427,7 +490,7 @@ proposal_cb (void *cls,
   switch (http_status)
   {
   case MHD_HTTP_OK:
-    cmd->details.proposal.proposal_data = json_incref ((json_t *) 
proposal_data);
+    cmd->details.proposal.contract_terms = json_incref ((json_t *) 
contract_terms);
     cmd->details.proposal.merchant_sig = *sig;
     cmd->details.proposal.hash = *hash;
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -467,7 +530,7 @@ pay_cb (void *cls,
   struct Command *cmd = &is->commands[is->ip];
   struct PaymentResponsePS mr;
   struct GNUNET_CRYPTO_EddsaSignature sig;
-  struct GNUNET_HashCode h_proposal_data;
+  struct GNUNET_HashCode h_contract_terms;
   const char *error_name;
   unsigned int error_line;
 
@@ -487,7 +550,7 @@ pay_cb (void *cls,
     /* Check signature */
     struct GNUNET_JSON_Specification spec[] = {
       GNUNET_JSON_spec_fixed_auto ("sig", &sig),
-      GNUNET_JSON_spec_fixed_auto ("h_proposal_data", &h_proposal_data),
+      GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &h_contract_terms),
       GNUNET_JSON_spec_end ()
     };
     if (GNUNET_OK !=
@@ -506,7 +569,7 @@ pay_cb (void *cls,
     }
     mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
     mr.purpose.size = htonl (sizeof (mr));
-    mr.h_proposal_data = h_proposal_data;
+    mr.h_contract_terms = h_contract_terms;
     if (GNUNET_OK !=
         GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
                                     &mr.purpose,
@@ -546,6 +609,9 @@ add_incoming_cb (void *cls,
   if (MHD_HTTP_OK != http_status)
   {
     GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "%s",
+                json_dumps (full_response, JSON_INDENT (2)));
     fail (is);
     return;
   }
@@ -692,6 +758,47 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys,
 }
 
 /**
+ * Allocates and return a string representing a order.
+ * In this process, this function gives the order those
+ * prices specified by the user. Please NOTE that any amount
+ * must be given in the form "XX.YY".
+ *
+ * @param max_fee merchant's allowed max_fee
+ * @param amount total amount for this order
+ */
+json_t *
+make_order (char *maxfee,
+            char *total)
+{
+  struct TALER_Amount tmp_amount;
+  json_t *total_j;
+  json_t *maxfee_j;
+  json_t *ret;
+  unsigned long long id;
+
+  TALER_string_to_amount (maxfee, &tmp_amount);
+  maxfee_j = TALER_JSON_from_amount (&tmp_amount);
+  TALER_string_to_amount (total, &tmp_amount);
+  total_j = TALER_JSON_from_amount (&tmp_amount);
+
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                              &id,
+                              sizeof (id));
+  ret = json_pack ("{s:O, s:s, s:s, s:s, s:s, s:O, s:s, s:[{s:s}]}",
+                   "max_fee", maxfee_j,
+                   "order_id", TALER_b2s (&id, sizeof (id)),
+                   "timestamp", "/Date(42)/",
+                   "refund_deadline", "/Date(0)/",
+                   "pay_deadline", "/Date(9999999999)/",
+                   "amount", total_j,
+                   "summary", "payments generator..",
+                   "products", "description", "ice cream");
+
+   GNUNET_assert (NULL != ret);
+   return ret;
+}
+
+/**
  * Run the main interpreter loop that performs exchange operations.
  *
  * @param cls contains the `struct InterpreterState`
@@ -710,6 +817,12 @@ interpreter_run (void *cls)
   json_t *sender_details;
   json_t *transfer_details;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Interpreter runs command %u/%s(%u)\n",
+             is->ip,
+             cmd->label,
+             cmd->oc);
+
   is->task = NULL;
   tc = GNUNET_SCHEDULER_get_task_context ();
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
@@ -719,17 +832,27 @@ interpreter_run (void *cls)
     fail (is);
     return;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Interpreter runs command %u/%s(%u)\n",
-             is->ip,
-             cmd->label,
-             cmd->oc);
 
   switch (cmd->oc)
   {
     case OC_END:
+
+      j++;
+
+      if (j < times)
+      {
+        is->ip = 0;
+
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Rewinding the interpreter.\n");
+
+        GNUNET_SCHEDULER_add_now (&interpreter_run,
+                                  is);
+        return;
+      }
       result = GNUNET_OK;
       GNUNET_SCHEDULER_shutdown ();
+
       return;
 
     case OC_PAY:
@@ -746,13 +869,13 @@ interpreter_run (void *cls)
         struct TALER_Amount max_fee;
         const char *error_name;
         unsigned int error_line;
-  
+
         /* get proposal */
         ref = find_command (is,
                             cmd->details.pay.contract_ref);
         GNUNET_assert (NULL != ref);
         merchant_sig = ref->details.proposal.merchant_sig;
-        GNUNET_assert (NULL != ref->details.proposal.proposal_data);
+        GNUNET_assert (NULL != ref->details.proposal.contract_terms);
         {
           /* Get information that need to be replied in the deposit permission 
*/
           struct GNUNET_JSON_Specification spec[] = {
@@ -766,9 +889,9 @@ interpreter_run (void *cls)
             TALER_JSON_spec_amount ("max_fee", &max_fee),
             GNUNET_JSON_spec_end()
           };
-  
+
           if (GNUNET_OK !=
-              GNUNET_JSON_parse (ref->details.proposal.proposal_data,
+              GNUNET_JSON_parse (ref->details.proposal.contract_terms,
                                  spec,
                                  &error_name,
                                  &error_line))
@@ -783,9 +906,9 @@ interpreter_run (void *cls)
           }
           cmd->details.pay.merchant_pub = merchant_pub;
         }
-  
+
         {
-          const struct Command *coin_ref;
+        const struct Command *coin_ref;
        memset (&pc, 0, sizeof (pc));
        coin_ref = find_command (is,
                                 cmd->details.pay.coin_ref);
@@ -801,7 +924,7 @@ interpreter_run (void *cls)
        default:
          GNUNET_assert (0);
        }
-  
+
        if (GNUNET_OK !=
            TALER_string_to_amount (cmd->details.pay.amount_without_fee,
                                    &pc.amount_without_fee))
@@ -813,7 +936,7 @@ interpreter_run (void *cls)
          fail (is);
          return;
        }
-  
+
        if (GNUNET_OK !=
            TALER_string_to_amount (cmd->details.pay.amount_with_fee,
                                    &pc.amount_with_fee))
@@ -826,21 +949,21 @@ interpreter_run (void *cls)
          return;
        }
         }
-  
+
         cmd->details.pay.ph
        = TALER_MERCHANT_pay_wallet (ctx,
-                                    MERCHANT_URI,
-                                     INSTANCE,
+                                    merchant_uri,
+                                     instance,
                                     &ref->details.proposal.hash,
                                     &total_amount,
                                     &max_fee,
                                     &merchant_pub,
-                                       &merchant_sig,
+                                     &merchant_sig,
                                     timestamp,
                                     refund_deadline,
                                     pay_deadline,
                                     &h_wire,
-                                    EXCHANGE_URI,
+                                    exchange_uri,
                                      order_id,
                                     1 /* num_coins */,
                                     &pc /* coins */,
@@ -859,26 +982,32 @@ interpreter_run (void *cls)
     case OC_PROPOSAL:
       {
         json_t *order;
-        json_error_t error;
-  
-        order = json_loads (cmd->details.proposal.order,
-                            JSON_REJECT_DUPLICATES,
-                            &error);
+        json_t *merchant_obj;
+
+        order = make_order (cmd->details.proposal.max_fee,
+                            cmd->details.proposal.amount);
+
+
         if (NULL == order)
         {
           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Failed to parse the order `%s' at command #%u: %s at 
%u\n",
-                      cmd->details.proposal.order,
-                      is->ip,
-                      error.text,
-                      (unsigned int) error.column);
+                      "Failed to create the order at command #%u\n",
+                      is->ip);
           fail (is);
           return;
         }
-        
+
+        GNUNET_assert (NULL != (merchant_obj = json_pack ("{s:{s:s}}",
+                                                          "merchant",
+                                                          "instance",
+                                                          instance)));
+
+
+        GNUNET_assert (-1 != json_object_update (order, merchant_obj));
+
         cmd->details.proposal.po
           = TALER_MERCHANT_order_put (ctx,
-                                      MERCHANT_URI,
+                                      merchant_uri,
                                       order,
                                       &proposal_cb,
                                       is);
@@ -906,7 +1035,7 @@ interpreter_run (void *cls)
       else
       {
         struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
-  
+
         priv = GNUNET_CRYPTO_eddsa_key_create ();
         cmd->details.admin_add_incoming.reserve_priv.eddsa_priv = *priv;
         GNUNET_free (priv);
@@ -924,7 +1053,7 @@ interpreter_run (void *cls)
         fail (is);
         return;
       }
-  
+
       execution_date = GNUNET_TIME_absolute_get ();
       GNUNET_TIME_round_abs (&execution_date);
       sender_details = json_loads 
(cmd->details.admin_add_incoming.sender_details,
@@ -939,10 +1068,12 @@ interpreter_run (void *cls)
         fail (is);
         return;
       }
+      json_object_set (sender_details, "bank_uri", json_string (bank_uri));
+
       transfer_details = json_loads 
(cmd->details.admin_add_incoming.transfer_details,
                                      JSON_REJECT_DUPLICATES,
                                      NULL);
-  
+
       if (NULL == transfer_details)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -954,7 +1085,7 @@ interpreter_run (void *cls)
       }
       cmd->details.admin_add_incoming.aih
         = TALER_EXCHANGE_admin_add_incoming (exchange,
-                                             EXCHANGE_URI,
+                                             exchange_uri_admin,
                                              &reserve_pub,
                                              &amount,
                                              execution_date,
@@ -1003,11 +1134,11 @@ interpreter_run (void *cls)
         fail (is);
         return;
       }
-  
+
       /* create coin's private key */
       {
         struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
-  
+
         priv = GNUNET_CRYPTO_eddsa_key_create ();
         cmd->details.reserve_withdraw.coin_priv.eddsa_priv = *priv;
         GNUNET_free (priv);
@@ -1017,7 +1148,7 @@ interpreter_run (void *cls)
       GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                                   &cmd->details.reserve_withdraw.blinding_key,
                                   sizeof 
(cmd->details.reserve_withdraw.blinding_key));
-  
+
       cmd->details.reserve_withdraw.wsh
         = TALER_EXCHANGE_reserve_withdraw (exchange,
                                            cmd->details.reserve_withdraw.pk,
@@ -1074,6 +1205,7 @@ cert_cb (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Certificate callback invoked, starting interpreter\n");
   is->keys = keys;
+
   is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
                                        is);
 }
@@ -1106,7 +1238,6 @@ do_shutdown (void *cls)
 {
   struct InterpreterState *is = cls;
   struct Command *cmd;
-  unsigned int i;
 
   if (NULL != timeout_task)
   {
@@ -1114,13 +1245,13 @@ do_shutdown (void *cls)
     timeout_task = NULL;
   }
 
-  for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++)
+  for (unsigned int i=0;OC_END != (cmd = &is->commands[i])->oc;i++)
     switch (cmd->oc)
     {
       case OC_END:
         GNUNET_assert (0);
         break;
-  
+
       case OC_PAY:
         if (NULL != cmd->details.pay.ph)
         {
@@ -1132,7 +1263,7 @@ do_shutdown (void *cls)
           cmd->details.pay.ph = NULL;
         }
         break;
-  
+
       case OC_PROPOSAL:
         if (NULL != cmd->details.proposal.po)
         {
@@ -1143,13 +1274,13 @@ do_shutdown (void *cls)
           TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
           cmd->details.proposal.po = NULL;
         }
-        if (NULL != cmd->details.proposal.proposal_data)
+        if (NULL != cmd->details.proposal.contract_terms)
         {
-          json_decref (cmd->details.proposal.proposal_data);
-          cmd->details.proposal.proposal_data = NULL;
+          json_decref (cmd->details.proposal.contract_terms);
+          cmd->details.proposal.contract_terms = NULL;
         }
         break;
-  
+
       case OC_WITHDRAW_SIGN:
         if (NULL != cmd->details.reserve_withdraw.wsh)
         {
@@ -1165,8 +1296,9 @@ do_shutdown (void *cls)
           GNUNET_CRYPTO_rsa_signature_free 
(cmd->details.reserve_withdraw.sig.rsa_signature);
           cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
         }
+        GNUNET_free_non_null (cmd->details.reserve_withdraw.amount);
         break;
-  
+
       case OC_ADMIN_ADD_INCOMING:
         if (NULL != cmd->details.admin_add_incoming.aih)
         {
@@ -1178,7 +1310,7 @@ do_shutdown (void *cls)
           cmd->details.admin_add_incoming.aih = NULL;
         }
         break;
-  
+
       default:
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                     "Shutdown: unknown instruction %d at %u (%s)\n",
@@ -1212,272 +1344,399 @@ do_shutdown (void *cls)
 }
 
 /**
+ * Take currency and the part after ":" in the
+ * "CURRENCY:XX.YY" format, and return a string
+ * in the format "CURRENCY:XX.YY".
+ *
+ * @param currency currency
+ * @param rpart float numbers after the ":", in string form
+ * @return pointer to allocated and concatenated "CURRENCY:XX.YY"
+ * formatted string.
+ *
+ */
+char *
+concat_amount (char *currency, char *rpart)
+{
+  char *str;
+
+  GNUNET_asprintf (&str, "%s:%s",
+                   currency, rpart);
+  return str;
+}
+
+
+/**
  * Main function that will be run by the scheduler.
  *
  * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be
+ *        NULL!)
+ * @param config configuration
  */
 static void
-run (void *cls)
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *config)
 {
   struct InterpreterState *is;
-  static struct Command commands[] =
+  unsigned int cnt;
+  char *wget_cmd;
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (config,
+                                                              
"payments-generator",
+                                                              "exchange",
+                                                              &exchange_uri))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "payments-generator",
+                               "exchange");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (config,
+                                                              
"payments-generator",
+                                                              "exchange_admin",
+                                                              
&exchange_uri_admin))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "payments-generator",
+                               "exchange_admin");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (config,
+                                                              
"payments-generator",
+                                                              "merchant",
+                                                              &merchant_uri))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "payments-generator",
+                               "merchant");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (config,
+                                                              
"payments-generator",
+                                                              "bank",
+                                                              &bank_uri))
+  {
+
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "payments-generator",
+                               "bank");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (config,
+                                                              
"payments-generator",
+                                                              "instance",
+                                                              &instance))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "payments-generator",
+                               "instance");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (config,
+                                                              
"payments-generator",
+                                                              "currency",
+                                                              &currency))
+  {
+
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "payments-generator",
+                               "currency");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
+  if (!remote_exchange)
+  {
+    exchanged = GNUNET_OS_start_process (GNUNET_NO,
+                                         GNUNET_OS_INHERIT_STD_ALL,
+                                         NULL, NULL, NULL,
+                                         "taler-exchange-httpd",
+                                         "taler-exchange-httpd",
+                                         NULL);
+    if (NULL == exchanged)
+    {
+      fprintf (stderr,
+               "Failed to run taler-exchange-httpd. Check your PATH.\n");
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+
+    fprintf (stderr,
+             "Waiting for taler-exchange-httpd to be ready\n");
+    cnt = 0;
+
+    GNUNET_asprintf (&wget_cmd, "wget -q -t 1 -T 1 %skeys -o /dev/null -O 
/dev/null", exchange_uri);
+
+    do
+      {
+        fprintf (stderr, ".");
+        sleep (1);
+        cnt++;
+        if (cnt > 60)
+        {
+          fprintf (stderr,
+                   "\nFailed to start taler-exchange-httpd\n");
+          GNUNET_OS_process_kill (exchanged,
+                                  SIGKILL);
+          GNUNET_OS_process_wait (exchanged);
+          GNUNET_OS_process_destroy (exchanged);
+          GNUNET_SCHEDULER_shutdown ();
+          return;
+        }
+      }
+    while (0 != system (wget_cmd));
+    GNUNET_free (wget_cmd);
+
+    fprintf (stderr, "\n");
+  }
+
+
+  if (!remote_merchant)
+  {
+    merchantd = GNUNET_OS_start_process (GNUNET_NO,
+                                         GNUNET_OS_INHERIT_STD_ALL,
+                                         NULL, NULL, NULL,
+                                         "taler-merchant-httpd",
+                                         "taler-merchant-httpd",
+                                         "-L", "DEBUG",
+                                         NULL);
+    if (NULL == merchantd)
+    {
+      fprintf (stderr,
+               "Failed to run taler-merchant-httpd. Check your PATH.\n");
+      GNUNET_OS_process_kill (exchanged,
+                              SIGKILL);
+      GNUNET_OS_process_wait (exchanged);
+      GNUNET_OS_process_destroy (exchanged);
+
+      GNUNET_SCHEDULER_shutdown ();
+      return;
+    }
+    /* give child time to start and bind against the socket */
+    fprintf (stderr,
+             "Waiting for taler-merchant-httpd to be ready\n");
+    cnt = 0;
+    GNUNET_asprintf (&wget_cmd, "wget -q -t 1 -T 1 %s -o /dev/null -O 
/dev/null", merchant_uri);
+
+    do
+      {
+        fprintf (stderr, ".");
+        sleep (1);
+        cnt++;
+        if (cnt > 60)
+        {
+          fprintf (stderr,
+                   "\nFailed to start taler-merchant-httpd\n");
+          GNUNET_OS_process_kill (merchantd,
+                                  SIGKILL);
+          GNUNET_OS_process_wait (merchantd);
+          GNUNET_OS_process_destroy (merchantd);
+          GNUNET_OS_process_kill (exchanged,
+                                  SIGKILL);
+          GNUNET_OS_process_wait (exchanged);
+          GNUNET_OS_process_destroy (exchanged);
+
+          GNUNET_SCHEDULER_shutdown ();
+          return;
+        }
+      }
+    while (0 != system (wget_cmd));
+    fprintf (stderr, "\n");
+    GNUNET_free (wget_cmd);
+  }
+
+  struct Command commands[] =
   {
     /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
     { .oc = OC_ADMIN_ADD_INCOMING,
       .label = "create-reserve-1",
       .expected_response_code = MHD_HTTP_OK,
-      .details.admin_add_incoming.sender_details = "{ \"bank_uri\":\"" 
BANK_URI "\", \"type\":\"test\", \"account_number\":62, \"uuid\":1 }",
+      .details.admin_add_incoming.sender_details = "{ \"type\":\"test\", 
\"account_number\":62, \"uuid\":1 }",
       .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
-      .details.admin_add_incoming.amount = CURRENCY ":5.01" },
+      .details.admin_add_incoming.amount = concat_amount (currency, "5.01") },
+
     /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
     { .oc = OC_ADMIN_ADD_INCOMING,
       .label = "create-reserve-2",
       .expected_response_code = MHD_HTTP_OK,
-      .details.admin_add_incoming.sender_details = "{ \"bank_uri\":\"" 
BANK_URI "\", \"type\":\"test\", \"account_number\":62, \"uuid\":1 }",
+      .details.admin_add_incoming.sender_details = "{ \"type\":\"test\", 
\"account_number\":62, \"uuid\":1 }",
       .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
-      .details.admin_add_incoming.amount = CURRENCY ":5.01" },
+      .details.admin_add_incoming.amount = concat_amount (currency, "5.01") },
     /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
     { .oc = OC_ADMIN_ADD_INCOMING,
       .label = "create-reserve-3",
       .expected_response_code = MHD_HTTP_OK,
-      .details.admin_add_incoming.sender_details = "{ \"bank_uri\":\"" 
BANK_URI "\", \"type\":\"test\", \"account_number\":62, \"uuid\":1 }",
+      .details.admin_add_incoming.sender_details = "{ \"type\":\"test\", 
\"account_number\":62, \"uuid\":1 }",
       .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
-      .details.admin_add_incoming.amount = CURRENCY ":5.01" },
+      .details.admin_add_incoming.amount = concat_amount (currency, "5.01") },
+
     /* Withdraw a 5 EUR coin, at fee of 1 ct */
     { .oc = OC_WITHDRAW_SIGN,
       .label = "withdraw-coin-1",
       .expected_response_code = MHD_HTTP_OK,
       .details.reserve_withdraw.reserve_reference = "create-reserve-1",
-      .details.reserve_withdraw.amount = CURRENCY ":5" },
+      .details.reserve_withdraw.amount = concat_amount (currency, "5") },
+
     /* Withdraw a 5 EUR coin, at fee of 1 ct */
     { .oc = OC_WITHDRAW_SIGN,
       .label = "withdraw-coin-2",
       .expected_response_code = MHD_HTTP_OK,
       .details.reserve_withdraw.reserve_reference = "create-reserve-2",
-      .details.reserve_withdraw.amount = CURRENCY ":5" },
+      .details.reserve_withdraw.amount = concat_amount (currency, "5") },
+
     /* Withdraw a 5 EUR coin, at fee of 1 ct */
     { .oc = OC_WITHDRAW_SIGN,
       .label = "withdraw-coin-3",
       .expected_response_code = MHD_HTTP_OK,
       .details.reserve_withdraw.reserve_reference = "create-reserve-3",
-      .details.reserve_withdraw.amount = CURRENCY ":5" },
+      .details.reserve_withdraw.amount = concat_amount (currency, "5") },
 
     /* Create proposal */
     { .oc = OC_PROPOSAL,
       .label = "create-proposal-1",
       .expected_response_code = MHD_HTTP_OK,
-      .details.proposal.order = "{\
-                  \"max_fee\":\
-                     {\"currency\":\"" CURRENCY "\", \"value\":0, 
\"fraction\":50000000},\
-                  \"order_id\":\"1\",\
-                  \"timestamp\":\"\\/Date(42)\\/\",\
-                  \"refund_deadline\":\"\\/Date(0)\\/\",\
-                  \"pay_deadline\":\"\\/Date(9999999999)\\/\",\
-                  \"amount\":{\"currency\":\"" CURRENCY "\", \"value\":5, 
\"fraction\":0},\
-                  \"merchant\":{\"instance\":\"" INSTANCE "\"},\
-                 \"summary\": \"merchant-lib testcase\",\
-                  \"products\":\
-                     [ {\"description\":\"ice cream\", \"value\":\"{" CURRENCY 
":5}\"} ] }"},
+      .details.proposal.max_fee = concat_amount (currency, "0.5"),
+      .details.proposal.amount = concat_amount (currency, "0.5") },
 
     /* Create proposal */
     { .oc = OC_PROPOSAL,
       .label = "create-proposal-2",
       .expected_response_code = MHD_HTTP_OK,
-      .details.proposal.order = "{\
-                  \"max_fee\":\
-                     {\"currency\":\"" CURRENCY "\", \"value\":0, 
\"fraction\":50000000},\
-                  \"order_id\":\"2\",\
-                  \"timestamp\":\"\\/Date(42)\\/\",\
-                  \"refund_deadline\":\"\\/Date(0)\\/\",\
-                  \"pay_deadline\":\"\\/Date(9999999999)\\/\",\
-                  \"amount\":{\"currency\":\"" CURRENCY "\", \"value\":5, 
\"fraction\":0},\
-                  \"merchant\":{\"instance\":\"" INSTANCE "\"},\
-                 \"summary\": \"merchant-lib testcase\",\
-                  \"products\":\
-                     [ {\"description\":\"ice cream\", \"value\":\"{" CURRENCY 
":5}\"} ] }"},
+      .details.proposal.max_fee = concat_amount (currency, "0.5"),
+      .details.proposal.amount = concat_amount (currency, "0.5") },
 
     /* Create proposal */
     { .oc = OC_PROPOSAL,
       .label = "create-proposal-3",
       .expected_response_code = MHD_HTTP_OK,
-      .details.proposal.order = "{\
-                  \"max_fee\":\
-                     {\"currency\":\"" CURRENCY "\", \"value\":0, 
\"fraction\":50000000},\
-                  \"order_id\":\"3\",\
-                  \"timestamp\":\"\\/Date(42)\\/\",\
-                  \"refund_deadline\":\"\\/Date(0)\\/\",\
-                  \"pay_deadline\":\"\\/Date(9999999999)\\/\",\
-                  \"amount\":{\"currency\":\"" CURRENCY "\", \"value\":5, 
\"fraction\":0},\
-                  \"merchant\":{\"instance\":\"" INSTANCE "\"},\
-                 \"summary\": \"merchant-lib testcase\",\
-                  \"products\":\
-                     [ {\"description\":\"ice cream\", \"value\":\"{" CURRENCY 
":5}\"} ] }"},
+      .details.proposal.max_fee = concat_amount (currency, "0.5"),
+      .details.proposal.amount = concat_amount (currency, "5.0") },
 
     { .oc = OC_PAY,
-      .label = "deposit-simple",
+      .label = "deposit-simple-1",
       .expected_response_code = MHD_HTTP_OK,
       .details.pay.contract_ref = "create-proposal-1",
       .details.pay.coin_ref = "withdraw-coin-1",
-      .details.pay.amount_with_fee = CURRENCY ":5",
-      .details.pay.amount_without_fee = CURRENCY ":4.99" },
+      .details.pay.amount_with_fee = concat_amount (currency, "5"),
+      .details.pay.amount_without_fee = concat_amount (currency, "4.99") },
 
     { .oc = OC_PAY,
-      .label = "deposit-simple",
+      .label = "deposit-simple-2",
       .expected_response_code = MHD_HTTP_OK,
       .details.pay.contract_ref = "create-proposal-2",
       .details.pay.coin_ref = "withdraw-coin-2",
-      .details.pay.amount_with_fee = CURRENCY ":5",
-      .details.pay.amount_without_fee = CURRENCY ":4.99" },
+      .details.pay.amount_with_fee = concat_amount (currency, "5"),
+      .details.pay.amount_without_fee = concat_amount (currency, "4.99") },
 
     { .oc = OC_PAY,
-      .label = "deposit-simple",
+      .label = "deposit-simple-3",
       .expected_response_code = MHD_HTTP_OK,
       .details.pay.contract_ref = "create-proposal-3",
       .details.pay.coin_ref = "withdraw-coin-3",
-      .details.pay.amount_with_fee = CURRENCY ":5",
-      .details.pay.amount_without_fee = CURRENCY ":4.99" },
+      .details.pay.amount_with_fee = concat_amount (currency, "5"),
+      .details.pay.amount_without_fee = concat_amount (currency, "4.99") },
 
     { .oc = OC_END,
       .label = "end-of-commands"}
   };
 
+
   is = GNUNET_new (struct InterpreterState);
-  is->commands = commands;
+  is->commands = GNUNET_malloc (sizeof (commands));
+  memcpy (is->commands,
+          commands,
+          sizeof (commands));
 
   ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
                           &rc);
   GNUNET_assert (NULL != ctx);
   rc = GNUNET_CURL_gnunet_rc_create (ctx);
   exchange = TALER_EXCHANGE_connect (ctx,
-                                     EXCHANGE_URI,
-                                     &cert_cb, is,
+                                     exchange_uri,
+                                     &cert_cb,
+                                     is,
                                      TALER_EXCHANGE_OPTION_END);
   GNUNET_assert (NULL != exchange);
   timeout_task
     = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
                                     (GNUNET_TIME_UNIT_SECONDS, 150),
                                     &do_timeout, NULL);
-  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is);
-
-
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+                                 is);
 }
 
+
 int
 main (int argc,
       char *argv[])
 {
-  struct GNUNET_OS_Process *exchanged;
-  struct GNUNET_OS_Process *merchantd;
-  unsigned int cnt;
   struct GNUNET_SIGNAL_Context *shc_chld;
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_option_uint ('n',
+                               "times",
+                               "TIMES",
+                               "How many times the commands should be run.",
+                               &times),
+    GNUNET_GETOPT_option_flag ('e',
+                               "remote-exchange",
+                               "Do not fork any exchange",
+                               &remote_exchange),
+    GNUNET_GETOPT_option_flag ('m',
+                               "remote-merchant",
+                               "Do not fork any merchant",
+                               &remote_merchant),
+    GNUNET_GETOPT_OPTION_END
+  };
 
   unsetenv ("XDG_DATA_HOME");
   unsetenv ("XDG_CONFIG_HOME");
-
-  GNUNET_log_setup ("merchant-create-payments",
+  GNUNET_log_setup ("taler-merchant-generate-payments",
                     "DEBUG",
                     NULL);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "About to launch the exchange.\n");
-
-  exchanged = GNUNET_OS_start_process (GNUNET_NO,
-                                       GNUNET_OS_INHERIT_STD_ALL,
-                                       NULL, NULL, NULL,
-                                       "taler-exchange-httpd",
-                                       "taler-exchange-httpd",
-                                       NULL);
-  if (NULL == exchanged)
-  {
-    fprintf (stderr,
-             "Failed to run taler-exchange-httpd. Check your PATH.\n");
-    return 77;
-  }
-
-  fprintf (stderr,
-           "Waiting for taler-exchange-httpd to be ready\n");
-  cnt = 0;
-  do
-    {
-      fprintf (stderr, ".");
-      sleep (1);
-      cnt++;
-      if (cnt > 60)
-      {
-        fprintf (stderr,
-                 "\nFailed to start taler-exchange-httpd\n");
-        GNUNET_OS_process_kill (exchanged,
-                                SIGKILL);
-        GNUNET_OS_process_wait (exchanged);
-        GNUNET_OS_process_destroy (exchanged);
-        return 77;
-      }
-    }
-  while (0 != system ("wget -q -t 1 -T 1 " EXCHANGE_URI "keys -o /dev/null -O 
/dev/null"));
-  fprintf (stderr, "\n");
-
-  merchantd = GNUNET_OS_start_process (GNUNET_NO,
-                                       GNUNET_OS_INHERIT_STD_ALL,
-                                       NULL, NULL, NULL,
-                                       "taler-merchant-httpd",
-                                       "taler-merchant-httpd",
-                                       "-L", "DEBUG",
-                                       NULL);
-  if (NULL == merchantd)
-  {
-    fprintf (stderr,
-             "Failed to run taler-merchant-httpd. Check your PATH.\n");
-    GNUNET_OS_process_kill (exchanged,
-                            SIGKILL);
-    GNUNET_OS_process_wait (exchanged);
-    GNUNET_OS_process_destroy (exchanged);
-    return 77;
-  }
-  /* give child time to start and bind against the socket */
-  fprintf (stderr,
-           "Waiting for taler-merchant-httpd to be ready\n");
-  cnt = 0;
-  do
-    {
-      fprintf (stderr, ".");
-      sleep (1);
-      cnt++;
-      if (cnt > 60)
-      {
-        fprintf (stderr,
-                 "\nFailed to start taler-merchant-httpd\n");
-        GNUNET_OS_process_kill (merchantd,
-                                SIGKILL);
-        GNUNET_OS_process_wait (merchantd);
-        GNUNET_OS_process_destroy (merchantd);
-        GNUNET_OS_process_kill (exchanged,
-                                SIGKILL);
-        GNUNET_OS_process_wait (exchanged);
-        GNUNET_OS_process_destroy (exchanged);
-        return 77;
-      }
-    }
-  while (0 != system ("wget -q -t 1 -T 1 " MERCHANT_URI " -o /dev/null -O 
/dev/null"));
-  fprintf (stderr, "\n");
-
   result = GNUNET_SYSERR;
-  sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
+  sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO,
+                              GNUNET_NO, GNUNET_NO);
   GNUNET_assert (NULL != sigpipe);
   shc_chld = GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD,
                                             &sighandler_child_death);
-  GNUNET_SCHEDULER_run (&run, NULL);
+  if (GNUNET_OK !=
+      GNUNET_PROGRAM_run (argc, argv,
+                          "taler-merchant-generate-payments",
+                          "Populates DB with fake payments",
+                          options,
+                          &run, NULL))
+    return 77;
+
 
   GNUNET_SIGNAL_handler_uninstall (shc_chld);
   shc_chld = NULL;
   GNUNET_DISK_pipe_close (sigpipe);
-  GNUNET_OS_process_kill (merchantd,
-                          SIGTERM);
-  GNUNET_OS_process_wait (merchantd);
-  GNUNET_OS_process_destroy (merchantd);
-  GNUNET_OS_process_kill (exchanged,
-                          SIGTERM);
-  GNUNET_OS_process_wait (exchanged);
-  GNUNET_OS_process_destroy (exchanged);
+  if (!remote_merchant && NULL != merchantd)
+  {
+    GNUNET_OS_process_kill (merchantd,
+                            SIGTERM);
+    GNUNET_OS_process_wait (merchantd);
+    GNUNET_OS_process_destroy (merchantd);
+  }
+  if (!remote_exchange && NULL != exchanged)
+  {
+    GNUNET_OS_process_kill (exchanged,
+                            SIGTERM);
+    GNUNET_OS_process_wait (exchanged);
+    GNUNET_OS_process_destroy (exchanged);
+  }
   if (77 == result)
     return 77;
   return (GNUNET_OK == result) ? 0 : 1;
diff --git a/src/samples/Makefile.am b/src/samples/Makefile.am
deleted file mode 100644
index 54c6d8f..0000000
--- a/src/samples/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
-
-bin_PROGRAMS = \
-  taler-merchant-generate-payments
-
-taler_merchant_generate_payments_SOURCES = \
-  generate_payments.c
-
-taler_merchant_generate_payments_LDADD = \
-  $(top_srcdir)/src/backenddb/libtalermerchantdb.la \
-  $(top_srcdir)/src/lib/libtalermerchant.la \
-  $(LIBGCRYPT_LIBS) \
-  -ltalerfakebank \
-  -ltalerexchange \
-  -ltalerjson \
-  -ltalerutil \
-  -lgnunetjson \
-  -lgnunetcurl \
-  -lgnunetutil \
-  -ljansson
diff --git a/src/samples/README b/src/samples/README
deleted file mode 100644
index 4926db6..0000000
--- a/src/samples/README
+++ /dev/null
@@ -1,3 +0,0 @@
-Here is the logic that creates dummy payments into the
-merchant's DB, mainly used for debugging applications that
-need some real data from the merchant backend. 
diff --git 
a/src/samples/generate_payments_home/.config/taler/merchant/wire/test.json 
b/src/samples/generate_payments_home/.config/taler/merchant/wire/test.json
deleted file mode 100644
index 99c9c66..0000000
--- a/src/samples/generate_payments_home/.config/taler/merchant/wire/test.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "type":"test",
-  "bank_uri":"http://localhost:8083/";,
-  "account_number":62
-}
diff --git a/src/samples/generate_payments_home/.config/taler/test.json 
b/src/samples/generate_payments_home/.config/taler/test.json
deleted file mode 100644
index 6c29eab..0000000
--- a/src/samples/generate_payments_home/.config/taler/test.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "type": "test",
-  "account_number": 3,
-  "bank_uri": "http://localhost:8083/";,
-  "name": "The exchange"
-}
diff --git a/src/samples/generate_payments_home/.config/taler/test.signed.json 
b/src/samples/generate_payments_home/.config/taler/test.signed.json
deleted file mode 100644
index 532640f..0000000
--- a/src/samples/generate_payments_home/.config/taler/test.signed.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "type": "test",
-  "salt": 
"0STGVVCSNJBKCP92596RSHN54Y4YW46J6D910KMPB6FF5ZYXG1C8MTMRFG32H9HFBA2XNNKRPRTKGD0KKKM805QGZ0AR28W5DB00MDG",
-  "account_number": 3,
-  "bank_uri": "http://localhost:8083/";,
-  "name": "The exchange",
-  "sig": 
"6EZF2DQBJP7WFQK93MHW1B21N12DFPJ5KMB9KS6Y775W1YS1ZZ0CAP9Y2CDK14Q01S0HR51SGHVNGA1WDNV5C07K941BRCRE9MSSP0G"
-}
\ No newline at end of file
diff --git 
a/src/samples/generate_payments_home/.local/share/taler/exchange/offline-keys/master.priv
 
b/src/samples/generate_payments_home/.local/share/taler/exchange/offline-keys/master.priv
deleted file mode 100644
index 0a17bb2..0000000
--- 
a/src/samples/generate_payments_home/.local/share/taler/exchange/offline-keys/master.priv
+++ /dev/null
@@ -1 +0,0 @@
-�QJ�_�#��O4(�kTr�$N ��8��2
\ No newline at end of file
diff --git a/src/samples/merchant_generate_payments.conf 
b/src/samples/merchant_generate_payments.conf
deleted file mode 100644
index 07f7692..0000000
--- a/src/samples/merchant_generate_payments.conf
+++ /dev/null
@@ -1,132 +0,0 @@
-# This file is in the public domain.
-#
-[PATHS]
-# Persistant data storage for the testcase
-TALER_TEST_HOME = generate_payments_home/
-
-[taler]
-# What currency do we use?
-CURRENCY = EUR
-
-[exchange-wire-test]
-# Enable 'test' for testing of the actual coin operations.
-ENABLE = YES
-
-# Fees for the forseeable future...
-# If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2017 = EUR:0.01
-WIRE-FEE-2018 = EUR:0.01
-WIRE-FEE-2019 = EUR:0.01
-WIRE-FEE-2020 = EUR:0.01
-WIRE-FEE-2021 = EUR:0.01
-WIRE-FEE-2022 = EUR:0.01
-WIRE-FEE-2023 = EUR:0.01
-WIRE-FEE-2024 = EUR:0.01
-WIRE-FEE-2025 = EUR:0.01
-WIRE-FEE-2026 = EUR:0.01
-
-############################
-# Exchange's configuration #
-############################
-
-[exchange]
-# How to access our database
-DB = postgres
-
-# HTTP port the exchange listens to
-PORT = 8081
-
-# Our public key
-MASTER_PUBLIC_KEY = BNFX90SBRFRMFW7E598BKVH6CTM83YD2AAKRZ0ADGH15M1XXJGBG
-
-# This value must match the DB we want payments to persist in.
-[exchangedb-postgres]
-DB_CONN_STR = "postgres:///taler"
-
-
-[exchange-wire-incoming-test]
-TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/test.signed.json
-
-[exchange-wire-outgoing-test]
-BANK_URI = "http://localhost:8083/";
-BANK_ACCOUNT_NUMBER = 2
-
-[coin_eur_ct_1]
-value = EUR:0.01
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.00
-fee_deposit = EUR:0.00
-fee_refresh = EUR:0.01
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_ct_10]
-value = EUR:0.10
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_1]
-value = EUR:1
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_5]
-value = EUR:5
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-
-[merchant]
-
-# Which port do we run the backend on? (HTTP server)
-PORT = 8082
-
-# How quickly do we want the exchange to send us our money?
-# Used only if the frontend does not specify a value.
-# FIXME: EDATE is a bit short, 'execution_delay'?
-EDATE = 3 week
-
-# Which plugin (backend) do we use for the DB.
-DB = postgres
-
-# Wire format supported by the merchant.
-WIREFORMAT = test
-
-INSTANCES = default
-
-[merchant-exchange-test]
-URI = http://localhost:8081/
-MASTER_KEY = BNFX90SBRFRMFW7E598BKVH6CTM83YD2AAKRZ0ADGH15M1XXJGBG
-
-[merchant-instance-default]
-KEYFILE = test_merchant.priv
-
-[merchant-instance-wireformat-default]
-TEST_RESPONSE_FILE = ${TALER_CONFIG_HOME}/merchant/wire/test.json
-
-[merchantdb-postgres]
-CONFIG = postgres:///taler
diff --git a/src/samples/test_merchant.priv b/src/samples/test_merchant.priv
deleted file mode 100644
index 9c18c35..0000000
--- a/src/samples/test_merchant.priv
+++ /dev/null
@@ -1 +0,0 @@
-`�&-���./��� jx�GݢO:6l,ζXT4�
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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