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 (64929e2 -> ecaa766)


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant] branch stable updated (64929e2 -> ecaa766)
Date: Tue, 06 Jun 2017 11:32:35 +0200

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

grothoff pushed a change to branch stable
in repository merchant.

    from 64929e2  fix doc compilartion warning
     add 0878d31  moving database backend to modern PQ API
     add fc6ee7d  more diagnostics when storing/retrieving contract terms
     add d3522a1  fix merge issue: proposal_data -> contract_terms rename
     add 5d0c4c6  update ignore file
     add b94526a  no longer need to link against libgnunetpostgres
     add 013210e  fixing #5056
     add 5ed9ada  must still define WITH_DOC
     add c3f49bc  simply remove --with-doc (#5048)
     add d274ac3  fix misc memory leaks
     add f1395b9  fix misc leaks
     add 979e9d3  fix more leaks, failure to reset job ptr when done
     add bfd145a  fix more leaks
     add a2793a5  fix leak from instance-passes not resetting is
     add 31b7acf  fix style issues and leaks in taler-merchant-generate-payments
     add a3017d9  move python mitm to its own git, work on #5064
     add f108a56  Fix some signed/unsigned issues, plus some doxygen typos
     add ecaa766  fix sign issue of 'start'

No new revisions were added by this update.

Summary of changes:
 .gitignore                                         |   5 +
 Doxyfile                                           | 247 +++++++
 Makefile.am                                        |  18 +-
 configure.ac                                       |  55 +-
 contrib/gnunet.tag                                 |  55 ++
 contrib/microhttpd.tag                             |  74 +++
 doc/version.texi                                   |   4 +-
 m4/ax_prog_doxygen.m4                              | 586 +++++++++++++++++
 src/backend/taler-merchant-httpd_exchanges.c       |  17 +
 src/backend/taler-merchant-httpd_history.c         |  68 +-
 src/backend/taler-merchant-httpd_mhd.c             |  20 +-
 src/backend/taler-merchant-httpd_pay.c             |   6 +-
 src/backend/taler-merchant-httpd_proposal.c        |  81 +--
 .../taler-merchant-httpd_track-transaction.c       |  11 +-
 src/backend/taler-merchant-httpd_track-transfer.c  | 174 ++---
 src/backenddb/Makefile.am                          |   1 -
 src/backenddb/plugin_merchantdb_postgres.c         | 729 ++++++++++-----------
 src/include/taler_merchantdb_plugin.h              |  10 +-
 src/lib/merchant_api_history.c                     |  11 +-
 src/lib/merchant_api_pay.c                         |   1 +
 src/lib/merchant_api_proposal.c                    |  64 +-
 src/lib/merchant_api_track_transaction.c           |   4 +
 src/lib/merchant_api_track_transfer.c              |   4 +
 src/lib/test_merchant_api.c                        | 331 +++++-----
 src/merchant-tools/Makefile.am                     |   1 -
 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 ---
 .../taler-merchant-generate-payments.c             | 618 +++++++++--------
 33 files changed, 2137 insertions(+), 1259 deletions(-)
 create mode 100644 Doxyfile
 create mode 100644 contrib/gnunet.tag
 create mode 100644 contrib/microhttpd.tag
 create mode 100644 m4/ax_prog_doxygen.m4
 delete mode 100644 src/merchant-tools/mitm/Makefile.in
 delete mode 100644 src/merchant-tools/mitm/README
 delete mode 100644 src/merchant-tools/mitm/merchant-mitm.wsgi.in
 delete mode 100644 src/merchant-tools/mitm/setup.py
 delete mode 100644 src/merchant-tools/mitm/taler-merchant-mitm.in
 delete mode 100644 src/merchant-tools/mitm/talermerchantmitm/__init__.py
 delete mode 100644 src/merchant-tools/mitm/talermerchantmitm/mitm.py

diff --git a/.gitignore b/.gitignore
index 4cab3d0..06e6ce0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,8 @@ doc/*
 !doc/*.sh
 !doc/examples/
 src/lib/test_merchant_api_home/.local/share/taler/exchange/wirefees/
+src/merchant-tools/taler-merchant-generate-payments
+src/merchant-tools/mitm/taler-merchant-mitm
+src/merchant-tools/mitm/merchant-mitm.wsgi
+doxygen-doc/
+contrib/taler-merchant.tag
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..3c068db
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,247 @@
+# Doxyfile 1.5.5
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NAME           = "GNU Taler: Merchant"
+PROJECT_NUMBER         = 0.3
+OUTPUT_DIRECTORY       = doxygen-doc/
+CREATE_SUBDIRS         = YES
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = .
+STRIP_FROM_INC_PATH    = src/include
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+QT_AUTOBRIEF           = NO
+MULTILINE_CPP_IS_BRIEF = NO
+INHERIT_DOCS           = NO
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 8
+ALIASES                =
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+OPTIMIZE_FOR_FORTRAN   = NO
+OPTIMIZE_OUTPUT_VHDL   = NO
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+SIP_SUPPORT            = NO
+DISTRIBUTE_GROUP_DOC   = NO
+SUBGROUPING            = YES
+TYPEDEF_HIDES_STRUCT   = NO
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = YES
+EXTRACT_LOCAL_CLASSES  = NO
+EXTRACT_LOCAL_METHODS  = YES
+EXTRACT_ANON_NSPACES   = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_GROUP_NAMES       = NO
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = NO
+GENERATE_TESTLIST      = NO
+GENERATE_BUGLIST       = NO
+GENERATE_DEPRECATEDLIST= NO
+ENABLED_SECTIONS       =
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+FILE_VERSION_FILTER    =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = YES
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = YES
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = src/
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          = *.c \
+                         *.h
+RECURSIVE              = YES
+EXCLUDE                =
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = */test_* */.git/* */perf_* */tls_test_*  
taler_config.h
+EXCLUDE_SYMBOLS        = GNUNET_* JSON_*
+EXAMPLE_PATH           =
+EXAMPLE_PATTERNS       = *
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             =
+INPUT_FILTER           =
+FILTER_PATTERNS        =
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = TALER_
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+#GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            =
+HTML_FOOTER            =
+HTML_STYLESHEET        =
+GENERATE_HTMLHELP      = NO
+GENERATE_DOCSET        = NO
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+HTML_DYNAMIC_SECTIONS  = NO
+CHM_FILE               =
+HHC_LOCATION           =
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = YES
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+#GENERATE_LATEX         = YES
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = YES
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         =
+LATEX_HEADER           =
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = YES
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+#GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = YES
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    =
+RTF_EXTENSIONS_FILE    =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+#GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           =
+INCLUDE_FILE_PATTERNS  =
+PREDEFINED             =
+EXPAND_AS_DEFINED      =
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES               = contrib/gnunet.tag \
+                         contrib/microhttpd.tag \
+                         contrib/taler-exchange.tag
+GENERATE_TAGFILE       = contrib/taler-merchant.tag
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = NO
+MSCGEN_PATH            =
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+CLASS_GRAPH            = NO
+COLLABORATION_GRAPH    = NO
+GROUP_GRAPHS           = NO
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = YES
+CALLER_GRAPH           = YES
+GRAPHICAL_HIERARCHY    = NO
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               =
+DOTFILE_DIRS           =
+DOT_GRAPH_MAX_NODES    = 100
+MAX_DOT_GRAPH_DEPTH    = 2
+DOT_TRANSPARENT        = YES
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE           = YES
diff --git a/Makefile.am b/Makefile.am
index 5f796c5..c42e33d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,12 +1,22 @@
 # This Makefile is in the public domain
 
-SUBDIRS = src
-if WITH_DOC
-  SUBDIRS += doc
+if DOC_ONLY
+  SUBDIRS = . doc
+else
+  SUBDIRS = . src doc
 endif
 
address@hidden@
+
 ACLOCAL_AMFLAGS = -I m4
-EXTRA_DIST = AUTHORS COPYING.GPL COPYING.AGPL COPYING.LGPL
+EXTRA_DIST = \
+ AUTHORS \
+ COPYING.GPL \
+ COPYING.AGPL \
+ COPYING.LGPL \
+ contrib/gnunet.tag \
+ contrib/microhttpd.tag \
+ Doxyfile
 
 app:
        mkdir -p $(PACKAGE)-frontend-$(VERSION)-app
diff --git a/configure.ac b/configure.ac
index b60ae5d..5378a99 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,25 @@ AC_CONFIG_MACRO_DIR([m4])
 
 LT_INIT
 
+DX_INIT_DOXYGEN([taler-merchant],,,
+DX_PS_FEATURE(OFF),
+DX_PDF_FEATURE(OFF),
+DX_RTF_FEATURE(OFF),
+DX_CHI_FEATURE(OFF),
+DX_XML_FEATURE(OFF))
+
+AC_MSG_CHECKING([whether to compile documentation ONLY])
+AC_ARG_ENABLE([only-doc],
+  [AS_HELP_STRING([--enable-only-doc], [only compile Taler documentation])],
+  [doc_only=${enableval}],
+  [doc_only=no])
+AC_MSG_RESULT($doc_only)
+AM_CONDITIONAL([DOC_ONLY], [test "$doc_only" = "yes"])
+
+if test "$doc_only" != yes
+then
+
+
 # Checks for programs.
 AC_PROG_CC
 AC_PROG_CC_C99
@@ -26,20 +45,6 @@ CFLAGS="-Wall $CFLAGS"
 # Checks for header files.
 AC_CHECK_HEADERS([stdint.h stdlib.h string.h unistd.h])
 
-# Check for compiling documentation
-with_doc = yes
-AC_MSG_CHECKING([for compiling documentation])
-AC_ARG_WITH(doc,
-            [AS_HELP_STRING([--with-doc], [Compile documentation])],
-            [AC_MSG_RESULT([given])],
-            [AC_MSG_RESULT(not given)
-           with_doc = no])
-
-AS_CASE([$with_doc],
-        [yes], AC_CHECK_PROG([texicomp], [texi2pdf], [yes]))
-AS_IF([test "x$with_doc" = "xyes" -a "x$texicomp" != "xyes"], AC_MSG_ERROR([A 
texinfo compiler is needed. Install texi2pdf.]))
-AM_CONDITIONAL([WITH_DOC], [test "x$with_doc" = "xyes"])
-
 # Check for GNUnet's libgnunetutil.
 libgnunetutil=0
 AC_MSG_CHECKING([for libgnunetutil])
@@ -92,7 +97,7 @@ CPPFLAGS="$CPPFLAGS $POSTGRESQL_CPPFLAGS"
 LDFLAGS="$LDFLAGS -L/usr/local/lib"
 
 AC_CHECK_HEADERS([gnunet/gnunet_pq_lib.h],
- [AC_CHECK_LIB([gnunetpq], [GNUNET_PQ_exec_prepared], libgnunetpq=1)],
+ [AC_CHECK_LIB([gnunetpq], [GNUNET_PQ_connect_with_cfg], libgnunetpq=1)],
    [], [#ifdef HAVE_GNUNET_PLATFORM_H
         #include <gnunet/platform.h>
        #endif])
@@ -273,6 +278,22 @@ AC_CHECK_PROG([tsc],[tsc],[yes],[no])
 AM_CONDITIONAL([HAVE_TSC], [test "x$tsc" = xyes])
 
 
+else
+
+# logic if doc_only is set, make sure conditionals are still defined
+AM_CONDITIONAL([HAVE_GNUNETPQ], [false])
+AM_CONDITIONAL([HAVE_POSTGRESQL], [false])
+AM_CONDITIONAL([HAVE_TALERFAKEBANK], [false])
+AM_CONDITIONAL([HAVE_LIBCURL], [false])
+AM_CONDITIONAL([HAVE_LIBGNURL], [false])
+AM_CONDITIONAL([HAVE_TSC], [false])
+AM_CONDITIONAL([USE_COVERAGE], [false])
+
+
+# end of 'doc_only'
+fi
+
+
 AC_CONFIG_FILES([Makefile
 doc/Makefile
 src/Makefile
@@ -281,7 +302,5 @@ src/include/Makefile
 src/backenddb/Makefile
 src/backend/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/contrib/gnunet.tag b/contrib/gnunet.tag
new file mode 100644
index 0000000..1cf4f0d
--- /dev/null
+++ b/contrib/gnunet.tag
@@ -0,0 +1,55 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
+<tagfile>
+  <compound kind="file">
+    <name>gnunet_util_lib.h</name>
+    <path></path>
+    <filename>gnunet_util_lib.h</filename>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_YES</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_OK</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_NO</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_SYSERR</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_TIME_UNIT_FOREVER_ABS</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+  </compound>
+  <compound kind="file">
+    <name>gnunet_pq_lib.h</name>
+    <path></path>
+    <filename>gnunet_pq_lib.h</filename>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_PQ_query_param_end</name>
+      <anchorfile>gnunet_pq_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="typedef">
+      <type>int</type>
+      <name>GNUNET_PQ_ResultConverter</name>
+      <anchorfile>gnunet_pq_lib.h</anchorfile>
+      <arglist>)(void *cls, PGresult *result, int row, const char *fname, 
size_t *dst_size, void *dst)</arglist>
+    </member>
+  </compound>
+</tagfile>
diff --git a/contrib/microhttpd.tag b/contrib/microhttpd.tag
new file mode 100644
index 0000000..8fab93d
--- /dev/null
+++ b/contrib/microhttpd.tag
@@ -0,0 +1,74 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
+<tagfile>
+  <compound kind="file">
+    <name>microhttpd_lib.h</name>
+    <path></path>
+    <filename>microhttpd.h</filename>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_YES</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_NO</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_HTTP_OK</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_HTTP_NO_CONTENT</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_HTTP_METHOD_GET</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_HTTP_METHOD_PUT</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_HTTP_METHOD_DELETE</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_HTTP_METHOD_POST</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_HTTP_VERSION_1_1</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_OPTION_NOTIFY_COMPLETED</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="typedef">
+      <type>int</type>
+      <name>MHD_AccessHandlerCallback</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist>)(void *cls, struct MHD_Connection *connection, const char 
*url, const char *method, const char *version, const char *upload_data, size_t 
*upload_data_size, void **con_cls)</arglist>
+    </member>
+  </compound>
+</tagfile>
diff --git a/doc/version.texi b/doc/version.texi
index d4370a3..b4f9054 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -1,4 +1,4 @@
address@hidden UPDATED 30 May 2017
address@hidden UPDATED-MONTH May 2017
address@hidden UPDATED 3 June 2017
address@hidden UPDATED-MONTH June 2017
 @set EDITION 0.2.0
 @set VERSION 0.2.0
diff --git a/m4/ax_prog_doxygen.m4 b/m4/ax_prog_doxygen.m4
new file mode 100644
index 0000000..a371f7f
--- /dev/null
+++ b/m4/ax_prog_doxygen.m4
@@ -0,0 +1,586 @@
+# ===========================================================================
+#     https://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   DX_INIT_DOXYGEN(PROJECT-NAME, [DOXYFILE-PATH], [OUTPUT-DIR], ...)
+#   DX_DOXYGEN_FEATURE(ON|OFF)
+#   DX_DOT_FEATURE(ON|OFF)
+#   DX_HTML_FEATURE(ON|OFF)
+#   DX_CHM_FEATURE(ON|OFF)
+#   DX_CHI_FEATURE(ON|OFF)
+#   DX_MAN_FEATURE(ON|OFF)
+#   DX_RTF_FEATURE(ON|OFF)
+#   DX_XML_FEATURE(ON|OFF)
+#   DX_PDF_FEATURE(ON|OFF)
+#   DX_PS_FEATURE(ON|OFF)
+#
+# DESCRIPTION
+#
+#   The DX_*_FEATURE macros control the default setting for the given
+#   Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
+#   generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
+#   help (for MS users), 'CHI' for generating a separate .chi file by the
+#   .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
+#   output formats. The environment variable DOXYGEN_PAPER_SIZE may be
+#   specified to override the default 'a4wide' paper size.
+#
+#   By default, HTML, PDF and PS documentation is generated as this seems to
+#   be the most popular and portable combination. MAN pages created by
+#   Doxygen are usually problematic, though by picking an appropriate subset
+#   and doing some massaging they might be better than nothing. CHM and RTF
+#   are specific for MS (note that you can't generate both HTML and CHM at
+#   the same time). The XML is rather useless unless you apply specialized
+#   post-processing to it.
+#
+#   The macros mainly control the default state of the feature. The use can
+#   override the default by specifying --enable or --disable. The macros
+#   ensure that contradictory flags are not given (e.g.,
+#   --enable-doxygen-html and --enable-doxygen-chm,
+#   --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
+#   feature will be automatically disabled (with a warning) if the required
+#   programs are missing.
+#
+#   Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
+#   with the following parameters: a one-word name for the project for use
+#   as a filename base etc., an optional configuration file name (the
+#   default is '$(srcdir)/Doxyfile', the same as Doxygen's default), and an
+#   optional output directory name (the default is 'doxygen-doc'). To run
+#   doxygen multiple times for different configuration files and output
+#   directories provide more parameters: the second, forth, sixth, etc
+#   parameter are configuration file names and the third, fifth, seventh,
+#   etc parameter are output directories. No checking is done to catch
+#   duplicates.
+#
+#   Automake Support
+#
+#   The DX_RULES substitution can be used to add all needed rules to the
+#   Makefile. Note that this is a substitution without being a variable:
+#   only the @DX_RULES@ syntax will work.
+#
+#   The provided targets are:
+#
+#     doxygen-doc: Generate all doxygen documentation.
+#
+#     doxygen-run: Run doxygen, which will generate some of the
+#                  documentation (HTML, CHM, CHI, MAN, RTF, XML)
+#                  but will not do the post processing required
+#                  for the rest of it (PS, PDF).
+#
+#     doxygen-ps:  Generate doxygen PostScript documentation.
+#
+#     doxygen-pdf: Generate doxygen PDF documentation.
+#
+#   Note that by default these are not integrated into the automake targets.
+#   If doxygen is used to generate man pages, you can achieve this
+#   integration by setting man3_MANS to the list of man pages generated and
+#   then adding the dependency:
+#
+#     $(man3_MANS): doxygen-doc
+#
+#   This will cause make to run doxygen and generate all the documentation.
+#
+#   The following variable is intended for use in Makefile.am:
+#
+#     DX_CLEANFILES = everything to clean.
+#
+#   Then add this variable to MOSTLYCLEANFILES.
+#
+# LICENSE
+#
+#   Copyright (c) 2009 Oren Ben-Kiki <address@hidden>
+#   Copyright (c) 2015 Olaf Mandel <address@hidden>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 23
+
+## ----------##
+## Defaults. ##
+## ----------##
+
+DX_ENV=""
+AC_DEFUN([DX_FEATURE_doc],  ON)
+AC_DEFUN([DX_FEATURE_dot],  OFF)
+AC_DEFUN([DX_FEATURE_man],  OFF)
+AC_DEFUN([DX_FEATURE_html], ON)
+AC_DEFUN([DX_FEATURE_chm],  OFF)
+AC_DEFUN([DX_FEATURE_chi],  OFF)
+AC_DEFUN([DX_FEATURE_rtf],  OFF)
+AC_DEFUN([DX_FEATURE_xml],  OFF)
+AC_DEFUN([DX_FEATURE_pdf],  ON)
+AC_DEFUN([DX_FEATURE_ps],   ON)
+
+## --------------- ##
+## Private macros. ##
+## --------------- ##
+
+# DX_ENV_APPEND(VARIABLE, VALUE)
+# ------------------------------
+# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen and add it
+# as a substitution (but not a Makefile variable). The substitution
+# is skipped if the variable name is VERSION.
+AC_DEFUN([DX_ENV_APPEND],
+[AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])dnl
+m4_if([$1], [VERSION], [], [AC_SUBST([$1], [$2])dnl
+AM_SUBST_NOTMAKE([$1])])dnl
+])
+
+# DX_DIRNAME_EXPR
+# ---------------
+# Expand into a shell expression prints the directory part of a path.
+AC_DEFUN([DX_DIRNAME_EXPR],
+         [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
+
+# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
+# -------------------------------------
+# Expands according to the M4 (static) status of the feature.
+AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
+
+# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
+# ----------------------------------
+# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
+AC_DEFUN([DX_REQUIRE_PROG], [
+AC_PATH_TOOL([$1], [$2])
+if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
+    AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
+    AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+fi
+])
+
+# DX_TEST_FEATURE(FEATURE)
+# ------------------------
+# Expand to a shell expression testing whether the feature is active.
+AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
+
+# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
+# -------------------------------------------------
+# Verify that a required features has the right state before trying to turn on
+# the DX_CURRENT_FEATURE.
+AC_DEFUN([DX_CHECK_DEPEND], [
+test "$DX_FLAG_$1" = "$2" \
+|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
+                            requires, contradicts) doxygen-DX_CURRENT_FEATURE])
+])
+
+# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
+# ----------------------------------------------------------
+# Turn off the DX_CURRENT_FEATURE if the required feature is off.
+AC_DEFUN([DX_CLEAR_DEPEND], [
+test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+])
+
+# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
+#                CHECK_DEPEND, CLEAR_DEPEND,
+#                REQUIRE, DO-IF-ON, DO-IF-OFF)
+# --------------------------------------------
+# Parse the command-line option controlling a feature. CHECK_DEPEND is called
+# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
+# otherwise CLEAR_DEPEND is called to turn off the default state if a required
+# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
+# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
+# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
+AC_DEFUN([DX_ARG_ABLE], [
+    AC_DEFUN([DX_CURRENT_FEATURE], [$1])
+    AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
+    AC_ARG_ENABLE(doxygen-$1,
+                  [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
+                                                      [--enable-doxygen-$1]),
+                                  DX_IF_FEATURE([$1], [don't $2], [$2]))],
+                  [
+case "$enableval" in
+#(
+y|Y|yes|Yes|YES)
+    AC_SUBST([DX_FLAG_$1], 1)
+    $3
+;; #(
+n|N|no|No|NO)
+    AC_SUBST([DX_FLAG_$1], 0)
+;; #(
+*)
+    AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
+;;
+esac
+], [
+AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
+$4
+])
+if DX_TEST_FEATURE([$1]); then
+    $5
+    :
+fi
+if DX_TEST_FEATURE([$1]); then
+    $6
+    :
+else
+    $7
+    :
+fi
+])
+
+## -------------- ##
+## Public macros. ##
+## -------------- ##
+
+# DX_XXX_FEATURE(DEFAULT_STATE)
+# -----------------------------
+AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc],  [$1])])
+AC_DEFUN([DX_DOT_FEATURE],     [AC_DEFUN([DX_FEATURE_dot], [$1])])
+AC_DEFUN([DX_MAN_FEATURE],     [AC_DEFUN([DX_FEATURE_man],  [$1])])
+AC_DEFUN([DX_HTML_FEATURE],    [AC_DEFUN([DX_FEATURE_html], [$1])])
+AC_DEFUN([DX_CHM_FEATURE],     [AC_DEFUN([DX_FEATURE_chm],  [$1])])
+AC_DEFUN([DX_CHI_FEATURE],     [AC_DEFUN([DX_FEATURE_chi],  [$1])])
+AC_DEFUN([DX_RTF_FEATURE],     [AC_DEFUN([DX_FEATURE_rtf],  [$1])])
+AC_DEFUN([DX_XML_FEATURE],     [AC_DEFUN([DX_FEATURE_xml],  [$1])])
+AC_DEFUN([DX_XML_FEATURE],     [AC_DEFUN([DX_FEATURE_xml],  [$1])])
+AC_DEFUN([DX_PDF_FEATURE],     [AC_DEFUN([DX_FEATURE_pdf],  [$1])])
+AC_DEFUN([DX_PS_FEATURE],      [AC_DEFUN([DX_FEATURE_ps],   [$1])])
+
+# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR], ...)
+# --------------------------------------------------------------
+# PROJECT also serves as the base name for the documentation files.
+# The default CONFIG-FILE is "$(srcdir)/Doxyfile" and OUTPUT-DOC-DIR is
+# "doxygen-doc".
+# More arguments are interpreted as interleaved CONFIG-FILE and
+# OUTPUT-DOC-DIR values.
+AC_DEFUN([DX_INIT_DOXYGEN], [
+
+# Files:
+AC_SUBST([DX_PROJECT], [$1])
+AC_SUBST([DX_CONFIG], ['ifelse([$2], [], [$(srcdir)/Doxyfile], [$2])'])
+AC_SUBST([DX_DOCDIR], ['ifelse([$3], [], [doxygen-doc], [$3])'])
+m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 4, m4_count($@), 2,
+      [AC_SUBST([DX_CONFIG]m4_eval(DX_i[/2]),
+                'm4_default_nblank_quoted(m4_argn(DX_i, $@),
+                                          [$(srcdir)/Doxyfile])')])])dnl
+m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 5, m4_count($@,), 2,
+      [AC_SUBST([DX_DOCDIR]m4_eval([(]DX_i[-1)/2]),
+                'm4_default_nblank_quoted(m4_argn(DX_i, $@),
+                                          [doxygen-doc])')])])dnl
+m4_define([DX_loop], m4_dquote(m4_if(m4_eval(3 < m4_count($@)), 1,
+          [m4_for([DX_i], 4, m4_count($@), 2, [, m4_eval(DX_i[/2])])],
+          [])))dnl
+
+# Environment variables used inside doxygen.cfg:
+DX_ENV_APPEND(SRCDIR, $srcdir)
+DX_ENV_APPEND(PROJECT, $DX_PROJECT)
+DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
+
+# Doxygen itself:
+DX_ARG_ABLE(doc, [generate any doxygen documentation],
+            [],
+            [],
+            [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
+             DX_REQUIRE_PROG([DX_PERL], perl)],
+            [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
+
+# Dot for graphics:
+DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [DX_REQUIRE_PROG([DX_DOT], dot)],
+            [DX_ENV_APPEND(HAVE_DOT, YES)
+             DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
+            [DX_ENV_APPEND(HAVE_DOT, NO)])
+
+# Man pages generation:
+DX_ARG_ABLE(man, [generate doxygen manual pages],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [],
+            [DX_ENV_APPEND(GENERATE_MAN, YES)],
+            [DX_ENV_APPEND(GENERATE_MAN, NO)])
+
+# RTF file generation:
+DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [],
+            [DX_ENV_APPEND(GENERATE_RTF, YES)],
+            [DX_ENV_APPEND(GENERATE_RTF, NO)])
+
+# XML file generation:
+DX_ARG_ABLE(xml, [generate doxygen XML documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [],
+            [DX_ENV_APPEND(GENERATE_XML, YES)],
+            [DX_ENV_APPEND(GENERATE_XML, NO)])
+
+# (Compressed) HTML help generation:
+DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [DX_REQUIRE_PROG([DX_HHC], hhc)],
+            [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
+             DX_ENV_APPEND(GENERATE_HTML, YES)
+             DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
+            [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
+
+# Separate CHI file generation.
+DX_ARG_ABLE(chi, [generate doxygen separate compressed HTML help index file],
+            [DX_CHECK_DEPEND(chm, 1)],
+            [DX_CLEAR_DEPEND(chm, 1)],
+            [],
+            [DX_ENV_APPEND(GENERATE_CHI, YES)],
+            [DX_ENV_APPEND(GENERATE_CHI, NO)])
+
+# Plain HTML pages generation:
+DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
+            [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
+            [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
+            [],
+            [DX_ENV_APPEND(GENERATE_HTML, YES)],
+            [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
+
+# PostScript file generation:
+DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [DX_REQUIRE_PROG([DX_LATEX], latex)
+             DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+             DX_REQUIRE_PROG([DX_DVIPS], dvips)
+             DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# PDF file generation:
+DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
+             DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+             DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# LaTeX generation for PS and/or PDF:
+if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
+    DX_ENV_APPEND(GENERATE_LATEX, YES)
+else
+    DX_ENV_APPEND(GENERATE_LATEX, NO)
+fi
+
+# Paper size for PS and/or PDF:
+AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
+           [a4wide (default), a4, letter, legal or executive])
+case "$DOXYGEN_PAPER_SIZE" in
+#(
+"")
+    AC_SUBST(DOXYGEN_PAPER_SIZE, "")
+;; #(
+a4wide|a4|letter|legal|executive)
+    DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
+;; #(
+*)
+    AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
+;;
+esac
+
+# Rules:
+AS_IF([[test $DX_FLAG_html -eq 1]],
+[[DX_SNIPPET_html="## ------------------------------- ##
+## Rules specific for HTML output. ##
+## ------------------------------- ##
+
+DX_CLEAN_HTML = \$(DX_DOCDIR)/html]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+                \$(DX_DOCDIR]DX_i[)/html]])[
+
+"]],
+[[DX_SNIPPET_html=""]])
+AS_IF([[test $DX_FLAG_chi -eq 1]],
+[[DX_SNIPPET_chi="
+DX_CLEAN_CHI = \$(DX_DOCDIR)/\$(PACKAGE).chi]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).chi]])["]],
+[[DX_SNIPPET_chi=""]])
+AS_IF([[test $DX_FLAG_chm -eq 1]],
+[[DX_SNIPPET_chm="## ------------------------------ ##
+## Rules specific for CHM output. ##
+## ------------------------------ ##
+
+DX_CLEAN_CHM = \$(DX_DOCDIR)/chm]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/chm]])[\
+${DX_SNIPPET_chi}
+
+"]],
+[[DX_SNIPPET_chm=""]])
+AS_IF([[test $DX_FLAG_man -eq 1]],
+[[DX_SNIPPET_man="## ------------------------------ ##
+## Rules specific for MAN output. ##
+## ------------------------------ ##
+
+DX_CLEAN_MAN = \$(DX_DOCDIR)/man]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/man]])[
+
+"]],
+[[DX_SNIPPET_man=""]])
+AS_IF([[test $DX_FLAG_rtf -eq 1]],
+[[DX_SNIPPET_rtf="## ------------------------------ ##
+## Rules specific for RTF output. ##
+## ------------------------------ ##
+
+DX_CLEAN_RTF = \$(DX_DOCDIR)/rtf]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/rtf]])[
+
+"]],
+[[DX_SNIPPET_rtf=""]])
+AS_IF([[test $DX_FLAG_xml -eq 1]],
+[[DX_SNIPPET_xml="## ------------------------------ ##
+## Rules specific for XML output. ##
+## ------------------------------ ##
+
+DX_CLEAN_XML = \$(DX_DOCDIR)/xml]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/xml]])[
+
+"]],
+[[DX_SNIPPET_xml=""]])
+AS_IF([[test $DX_FLAG_ps -eq 1]],
+[[DX_SNIPPET_ps="## ----------------------------- ##
+## Rules specific for PS output. ##
+## ----------------------------- ##
+
+DX_CLEAN_PS = \$(DX_DOCDIR)/\$(PACKAGE).ps]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+              \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps]])[
+
+DX_PS_GOAL = doxygen-ps
+
+doxygen-ps: \$(DX_CLEAN_PS)
+
+]m4_foreach([DX_i], [DX_loop],
+[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
+       \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
+       rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
+       \$(DX_LATEX) refman.tex; \\
+       \$(DX_MAKEINDEX) refman.idx; \\
+       \$(DX_LATEX) refman.tex; \\
+       countdown=5; \\
+       while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
+                         refman.log > /dev/null 2>&1 \\
+          && test \$\$countdown -gt 0; do \\
+           \$(DX_LATEX) refman.tex; \\
+            countdown=\`expr \$\$countdown - 1\`; \\
+       done; \\
+       \$(DX_DVIPS) -o ../\$(PACKAGE).ps refman.dvi
+
+]])["]],
+[[DX_SNIPPET_ps=""]])
+AS_IF([[test $DX_FLAG_pdf -eq 1]],
+[[DX_SNIPPET_pdf="## ------------------------------ ##
+## Rules specific for PDF output. ##
+## ------------------------------ ##
+
+DX_CLEAN_PDF = \$(DX_DOCDIR)/\$(PACKAGE).pdf]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf]])[
+
+DX_PDF_GOAL = doxygen-pdf
+
+doxygen-pdf: \$(DX_CLEAN_PDF)
+
+]m4_foreach([DX_i], [DX_loop],
+[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
+       \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
+       rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
+       \$(DX_PDFLATEX) refman.tex; \\
+       \$(DX_MAKEINDEX) refman.idx; \\
+       \$(DX_PDFLATEX) refman.tex; \\
+       countdown=5; \\
+       while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
+                         refman.log > /dev/null 2>&1 \\
+          && test \$\$countdown -gt 0; do \\
+           \$(DX_PDFLATEX) refman.tex; \\
+           countdown=\`expr \$\$countdown - 1\`; \\
+       done; \\
+       mv refman.pdf ../\$(PACKAGE).pdf
+
+]])["]],
+[[DX_SNIPPET_pdf=""]])
+AS_IF([[test $DX_FLAG_ps -eq 1 -o $DX_FLAG_pdf -eq 1]],
+[[DX_SNIPPET_latex="## ------------------------------------------------- ##
+## Rules specific for LaTeX (shared for PS and PDF). ##
+## ------------------------------------------------- ##
+
+DX_V_LATEX = \$(_DX_v_LATEX_\$(V))
+_DX_v_LATEX_ = \$(_DX_v_LATEX_\$(AM_DEFAULT_VERBOSITY))
+_DX_v_LATEX_0 = @echo \"  LATEX \" \$][@;
+
+DX_CLEAN_LATEX = \$(DX_DOCDIR)/latex]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+                 \$(DX_DOCDIR]DX_i[)/latex]])[
+
+"]],
+[[DX_SNIPPET_latex=""]])
+
+AS_IF([[test $DX_FLAG_doc -eq 1]],
+[[DX_SNIPPET_doc="## --------------------------------- ##
+## Format-independent Doxygen rules. ##
+## --------------------------------- ##
+
+${DX_SNIPPET_html}\
+${DX_SNIPPET_chm}\
+${DX_SNIPPET_man}\
+${DX_SNIPPET_rtf}\
+${DX_SNIPPET_xml}\
+${DX_SNIPPET_ps}\
+${DX_SNIPPET_pdf}\
+${DX_SNIPPET_latex}\
+DX_V_DXGEN = \$(_DX_v_DXGEN_\$(V))
+_DX_v_DXGEN_ = \$(_DX_v_DXGEN_\$(AM_DEFAULT_VERBOSITY))
+_DX_v_DXGEN_0 = @echo \"  DXGEN \" \$<;
+
+.PHONY: doxygen-run doxygen-doc \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
+
+.INTERMEDIATE: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
+
+doxygen-run:]m4_foreach([DX_i], [DX_loop],
+                         [[ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag]])[
+
+doxygen-doc: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
+
+]m4_foreach([DX_i], [DX_loop],
+[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag: \$(DX_CONFIG]DX_i[) 
\$(pkginclude_HEADERS)
+       \$(A""M_V_at)rm -rf \$(DX_DOCDIR]DX_i[)
+       \$(DX_V_DXGEN)\$(DX_ENV) DOCDIR=\$(DX_DOCDIR]DX_i[) \$(DX_DOXYGEN) 
\$(DX_CONFIG]DX_i[)
+       \$(A""M_V_at)echo Timestamp >\$][@
+
+]])dnl
+[DX_CLEANFILES = \\]
+m4_foreach([DX_i], [DX_loop],
+[[     \$(DX_DOCDIR]DX_i[)/doxygen_sqlite3.db \\
+       \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \\
+]])dnl
+[      -r \\
+       \$(DX_CLEAN_HTML) \\
+       \$(DX_CLEAN_CHM) \\
+       \$(DX_CLEAN_CHI) \\
+       \$(DX_CLEAN_MAN) \\
+       \$(DX_CLEAN_RTF) \\
+       \$(DX_CLEAN_XML) \\
+       \$(DX_CLEAN_PS) \\
+       \$(DX_CLEAN_PDF) \\
+       \$(DX_CLEAN_LATEX)"]],
+[[DX_SNIPPET_doc=""]])
+AC_SUBST([DX_RULES],
+["${DX_SNIPPET_doc}"])dnl
+AM_SUBST_NOTMAKE([DX_RULES])
+
+#For debugging:
+#echo DX_FLAG_doc=$DX_FLAG_doc
+#echo DX_FLAG_dot=$DX_FLAG_dot
+#echo DX_FLAG_man=$DX_FLAG_man
+#echo DX_FLAG_html=$DX_FLAG_html
+#echo DX_FLAG_chm=$DX_FLAG_chm
+#echo DX_FLAG_chi=$DX_FLAG_chi
+#echo DX_FLAG_rtf=$DX_FLAG_rtf
+#echo DX_FLAG_xml=$DX_FLAG_xml
+#echo DX_FLAG_pdf=$DX_FLAG_pdf
+#echo DX_FLAG_ps=$DX_FLAG_ps
+#echo DX_ENV=$DX_ENV
+])
diff --git a/src/backend/taler-merchant-httpd_exchanges.c 
b/src/backend/taler-merchant-httpd_exchanges.c
index aab5b27..3883d57 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -930,9 +930,26 @@ TMH_EXCHANGES_done ()
 
   while (NULL != (exchange = exchange_head))
   {
+    struct FeesByWireMethod *f;
+
     GNUNET_CONTAINER_DLL_remove (exchange_head,
                                  exchange_tail,
                                  exchange);
+    while (NULL != (f = exchange->wire_fees_head))
+    {
+      struct TALER_EXCHANGE_WireAggregateFees *af;
+
+      GNUNET_CONTAINER_DLL_remove (exchange->wire_fees_head,
+                                   exchange->wire_fees_tail,
+                                   f);
+      while (NULL != (af = f->af))
+      {
+        f->af = af->next;
+        GNUNET_free (af);
+      }
+      GNUNET_free (f->wire_method);
+      GNUNET_free (f);
+    }
     if (NULL != exchange->wire_request)
     {
       TALER_EXCHANGE_wire_cancel (exchange->wire_request);
diff --git a/src/backend/taler-merchant-httpd_history.c 
b/src/backend/taler-merchant-httpd_history.c
index a06259c..4ad6a26 100644
--- a/src/backend/taler-merchant-httpd_history.c
+++ b/src/backend/taler-merchant-httpd_history.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015, 2016 INRIA
+  (C) 2014, 2015, 2016, 2017 INRIA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -96,11 +96,10 @@ MH_handler_history (struct TMH_RequestHandler *rh,
   int start = -1;
   unsigned int delta;
 
-  response = json_array (); /*FIXME who decrefs this?*/
+  response = json_array ();
   str = MHD_lookup_connection_value (connection,
                                      MHD_GET_ARGUMENT_KIND,
                                      "date");
-
   date = GNUNET_TIME_absolute_get ();
 
   if (NULL != str)
@@ -113,25 +112,21 @@ MH_handler_history (struct TMH_RequestHandler *rh,
                                              "date");
     }
 
-  date.abs_value_us = seconds * 1000LL * 1000LL;
-
-  if (date.abs_value_us / 1000LL / 1000LL != seconds)
-  {
-    json_decref (response);
-    return TMH_RESPONSE_reply_bad_request (connection,
-                                           TALER_EC_HISTORY_TIMESTAMP_OVERFLOW,
-                                           "Timestamp overflowed");
-  }
-
+    date.abs_value_us = seconds * 1000LL * 1000LL;
 
+    if (date.abs_value_us / 1000LL / 1000LL != seconds)
+    {
+      json_decref (response);
+      return TMH_RESPONSE_reply_bad_request (connection,
+                                             
TALER_EC_HISTORY_TIMESTAMP_OVERFLOW,
+                                             "Timestamp overflowed");
+    }
   }
 
-  mi = TMH_lookup_instance ("default");
   str = MHD_lookup_connection_value (connection,
                                      MHD_GET_ARGUMENT_KIND,
                                      "instance");
-  if (NULL != str)
-    mi = TMH_lookup_instance (str);
+  mi = TMH_lookup_instance (NULL != str ? str : "default");
 
   if (NULL == mi)
   {
@@ -151,10 +146,10 @@ MH_handler_history (struct TMH_RequestHandler *rh,
   {
 
     ret = db->find_contract_terms_history (db->cls,
-                                          str,
-                                          &mi->pubkey,
-                                          pd_cb,
-                                          response);
+                                           str,
+                                           &mi->pubkey,
+                                           &pd_cb,
+                                           response);
     if (GNUNET_SYSERR == ret)
     {
       json_decref (response);
@@ -176,8 +171,8 @@ MH_handler_history (struct TMH_RequestHandler *rh,
                                      "start");
   if (NULL != str)
   {
-    if ((1 != sscanf (str, "%d", &start)) ||
-        0 > start)
+    if ( (1 != sscanf (str, "%d", &start)) ||
+         (0 > start) )
     {
       json_decref (response);
       return TMH_RESPONSE_reply_arg_invalid (connection,
@@ -192,34 +187,33 @@ MH_handler_history (struct TMH_RequestHandler *rh,
 
   if (NULL != str)
   {
-    if ((1 != sscanf (str, "%d", &delta)) ||
-        delta < 0)
+    if (1 != sscanf (str, "%u", &delta))
       return TMH_RESPONSE_reply_arg_invalid (connection,
                                              TALER_EC_PARAMETER_MALFORMED,
                                              "delta");
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Querying history back to %s, start: %d, delta: %d\n",
+              "Querying history back to %s, start: %u, delta: %u\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);
+                                           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);
+                                                     date,
+                                                     &mi->pubkey,
+                                                     (unsigned int) start,
+                                                     delta,
+                                                     GNUNET_NO,
+                                                     &pd_cb,
+                                                     response);
   if (GNUNET_SYSERR == ret)
   {
     json_decref (response);
diff --git a/src/backend/taler-merchant-httpd_mhd.c 
b/src/backend/taler-merchant-httpd_mhd.c
index 7e0a6f3..9debb67 100644
--- a/src/backend/taler-merchant-httpd_mhd.c
+++ b/src/backend/taler-merchant-httpd_mhd.c
@@ -108,12 +108,20 @@ TMH_MHD_handler_agpl_redirect (struct TMH_RequestHandler 
*rh,
     (void) MHD_add_response_header (response,
                                     MHD_HTTP_HEADER_CONTENT_TYPE,
                                     rh->mime_type);
-  MHD_add_response_header (response,
-                           MHD_HTTP_HEADER_LOCATION,
-                           "http://www.git.taler.net/?p=exchange.git";);
-  ret = MHD_queue_response (connection,
-                            rh->response_code,
-                            response);
+  if (MHD_NO ==
+      MHD_add_response_header (response,
+                               MHD_HTTP_HEADER_LOCATION,
+                               "http://www.git.taler.net/?p=exchange.git";))
+  {
+    GNUNET_break (0);
+    ret = MHD_NO;
+  }
+  else
+  {
+    ret = MHD_queue_response (connection,
+                              rh->response_code,
+                              response);
+  }
   MHD_destroy_response (response);
   return ret;
 }
diff --git a/src/backend/taler-merchant-httpd_pay.c 
b/src/backend/taler-merchant-httpd_pay.c
index 97b7ac4..837b17d 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -1316,12 +1316,10 @@ handler_pay_json (struct MHD_Connection *connection,
        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);
+    resp = sign_success_response (pc);
     ret = MHD_queue_response (connection,
                              MHD_HTTP_OK,
-                             sign_success_response (pc));
+                             resp);
     MHD_destroy_response (resp);
     return ret;
   }
diff --git a/src/backend/taler-merchant-httpd_proposal.c 
b/src/backend/taler-merchant-httpd_proposal.c
index fa8251c..a431179 100644
--- a/src/backend/taler-merchant-httpd_proposal.c
+++ b/src/backend/taler-merchant-httpd_proposal.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  (C) 2014, 2015, 2016 INRIA
+  (C) 2014, 2015, 2016, 2017 INRIA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -14,7 +14,7 @@
   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
 /**
- * @file backend/taler-merchant-httpd_propose.c
+ * @file backend/taler-merchant-httpd_proposal.c
  * @brief HTTP serving layer mainly intended to communicate with the frontend
  * @author Marcello Stanisci
  */
@@ -160,7 +160,8 @@ proposal_put (struct MHD_Connection *connection,
 
   /* Add order_id if it doesn't exist. */
 
-  if (NULL == json_string_value (json_object_get (order, "order_id")))
+  if (NULL == json_string_value (json_object_get (order,
+                                                  "order_id")))
   {
     char buf[256];
     time_t timer;
@@ -178,19 +179,20 @@ proposal_put (struct MHD_Connection *connection,
               "-%llX",
               (long long unsigned) GNUNET_CRYPTO_random_u64 
(GNUNET_CRYPTO_QUALITY_WEAK,
                                                              UINT64_MAX));
-    json_object_set (order,
-                     "order_id",
-                     json_string (buf));
+    json_object_set_new (order,
+                         "order_id",
+                         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 ();
 
     (void) GNUNET_TIME_round_abs (&now);
-    json_object_set (order,
-                     "timestamp",
-                     GNUNET_JSON_from_time_abs (now));
+    json_object_set_new (order,
+                         "timestamp",
+                         GNUNET_JSON_from_time_abs (now));
   }
 
   if (NULL == json_object_get (order,
@@ -198,9 +200,9 @@ proposal_put (struct MHD_Connection *connection,
   {
     struct GNUNET_TIME_Absolute zero = { 0 };
 
-    json_object_set (order,
-                     "refund_deadline",
-                     GNUNET_JSON_from_time_abs (zero));
+    json_object_set_new (order,
+                         "refund_deadline",
+                         GNUNET_JSON_from_time_abs (zero));
   }
 
   if (NULL == json_object_get (order,
@@ -211,27 +213,31 @@ proposal_put (struct MHD_Connection *connection,
     /* FIXME: read the delay for pay_deadline from config */
     t = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS);
     (void) GNUNET_TIME_round_abs (&t);
-    json_object_set (order, "pay_deadline", GNUNET_JSON_from_time_abs (t));
+    json_object_set_new (order,
+                         "pay_deadline",
+                         GNUNET_JSON_from_time_abs (t));
   }
 
   if (NULL == json_object_get (order,
                                "max_wire_fee"))
   {
-    json_object_set (order,
-                     "max_wire_fee",
-                     TALER_JSON_from_amount (&default_max_wire_fee));
+    json_object_set_new (order,
+                         "max_wire_fee",
+                         TALER_JSON_from_amount (&default_max_wire_fee));
   }
 
   if (NULL == json_object_get (order,
                                "wire_fee_amortization"))
   {
-    json_object_set (order,
-                     "wire_fee_amortization",
-                     json_integer ((json_int_t) 
default_wire_fee_amortization));
+    json_object_set_new (order,
+                         "wire_fee_amortization",
+                         json_integer ((json_int_t) 
default_wire_fee_amortization));
   }
 
   /* extract fields we need to sign separately */
-  res = TMH_PARSE_json_data (connection, order, spec);
+  res = TMH_PARSE_json_data (connection,
+                             order,
+                             spec);
   if (GNUNET_NO == res)
   {
     return MHD_YES;
@@ -243,7 +249,6 @@ proposal_put (struct MHD_Connection *connection,
                                              "Impossible to parse the order");
   }
 
-
   /* check contract is well-formed */
   if (GNUNET_OK != check_products (products))
   {
@@ -258,6 +263,7 @@ proposal_put (struct MHD_Connection *connection,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Not able to find the specified instance\n");
+    GNUNET_JSON_parse_free (spec);
     return TMH_RESPONSE_reply_not_found (connection,
                                         TALER_EC_CONTRACT_INSTANCE_UNKNOWN,
                                         "Unknown instance given");
@@ -341,6 +347,8 @@ MH_handler_proposal_put (struct TMH_RequestHandler *rh,
 {
   int res;
   struct TMH_JsonParseContext *ctx;
+  json_t *root;
+  json_t *order;
 
   if (NULL == *connection_cls)
   {
@@ -353,8 +361,6 @@ MH_handler_proposal_put (struct TMH_RequestHandler *rh,
     ctx = *connection_cls;
   }
 
-  json_t *root;
-
   res = TMH_PARSE_post_json (connection,
                              &ctx->json_parse_context,
                              upload_data,
@@ -366,8 +372,8 @@ MH_handler_proposal_put (struct TMH_RequestHandler *rh,
   if ((GNUNET_NO == res) || (NULL == root))
     return MHD_YES;
 
-  json_t *order = json_object_get (root, "order");
-
+  order = json_object_get (root,
+                           "order");
   if (NULL == order)
   {
     res = TMH_RESPONSE_reply_arg_missing (connection,
@@ -376,7 +382,8 @@ MH_handler_proposal_put (struct TMH_RequestHandler *rh,
   }
   else
   {
-    res = proposal_put (connection, order);
+    res = proposal_put (connection,
+                        order);
   }
   json_decref (root);
   return res;
@@ -428,26 +435,24 @@ MH_handler_proposal_lookup (struct TMH_RequestHandler *rh,
                                            "order_id");
 
   res = db->find_contract_terms (db->cls,
-                                &contract_terms,
-                                order_id,
-                                &mi->pubkey);
+                                 &contract_terms,
+                                 order_id,
+                                 &mi->pubkey);
   if (GNUNET_NO == res)
     return TMH_RESPONSE_reply_not_found (connection,
                                          TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND,
                                          "unknown transaction id");
-
   if (GNUNET_SYSERR == res)
     return TMH_RESPONSE_reply_internal_error (connection,
                                               
TALER_EC_PROPOSAL_LOOKUP_DB_ERROR,
                                               "An error occurred while 
retrieving proposal data from db");
 
-
-  return TMH_RESPONSE_reply_json (connection,
-                                  contract_terms,
-                                  MHD_HTTP_OK);
-
-
+  res = TMH_RESPONSE_reply_json (connection,
+                                 contract_terms,
+                                 MHD_HTTP_OK);
+  json_decref (contract_terms);
+  return res;
 }
 
 
-/* end of taler-merchant-httpd_contract.c */
+/* end of taler-merchant-httpd_proposal.c */
diff --git a/src/backend/taler-merchant-httpd_track-transaction.c 
b/src/backend/taler-merchant-httpd_track-transaction.c
index eb1ee16..e9610ae 100644
--- a/src/backend/taler-merchant-httpd_track-transaction.c
+++ b/src/backend/taler-merchant-httpd_track-transaction.c
@@ -917,16 +917,17 @@ MH_handler_track_transaction (struct TMH_RequestHandler 
*rh,
                                         
TALER_EC_TRACK_TRANSACTION_INSTANCE_UNKNOWN,
                                         "unknown instance");
 
-  if (GNUNET_YES != db->find_contract_terms (db->cls,
-                                            &contract_terms,
-                                            order_id,
-                                            &tctx->mi->pubkey))
-
+  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 (contract_terms,
                    &h_contract_terms);
+  json_decref (contract_terms);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Trying to track h_contract_terms '%s'\n",
diff --git a/src/backend/taler-merchant-httpd_track-transfer.c 
b/src/backend/taler-merchant-httpd_track-transfer.c
index 4ca22af..3df9703 100644
--- a/src/backend/taler-merchant-httpd_track-transfer.c
+++ b/src/backend/taler-merchant-httpd_track-transfer.c
@@ -108,6 +108,11 @@ struct TrackTransferContext
   const json_t *original_response;
 
   /**
+   * Modified response to return to the frontend.
+   */
+  json_t *deposits_response;
+
+  /**
    * Which transaction detail are we currently looking at?
    */
   unsigned int current_offset;
@@ -130,6 +135,7 @@ struct TrackTransferContext
  * individual deposits for each h_contract_terms.
  */
 struct Entry {
+
   /**
    * Sum accumulator for deposited value.
    */
@@ -140,12 +146,8 @@ struct Entry {
    */
   struct TALER_Amount deposit_fee;
 
-  };
+};
 
-/**
- * Modified response to return to the frontend.
- */
-static json_t *deposits_response;
 
 /**
  * Free the @a rctx.
@@ -184,8 +186,8 @@ free_transfer_track_context (struct TrackTransferContext 
*rctx)
  * @param cls closure, NULL
  * @param key current key
  * @param value a `struct MerchantInstance`
- * @return GNUNET_YES if the iteration should continue,
- * GNUNET_NO otherwise.
+ * @return #GNUNET_YES if the iteration should continue,
+ *         #GNUNET_NO otherwise.
  */
 static int
 hashmap_free (void *cls,
@@ -206,47 +208,55 @@ hashmap_free (void *cls,
  * @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.
+ * @return #GNUNET_YES if iteration is to be continued,
+ *         #GNUNET_NO otherwise.
  */
-int
+static 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 *element;
   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))
+  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),
+  order_id = json_object_get (contract_terms,
+                              "order_id");
+  if (NULL == order_id)
+  {
+    GNUNET_break_op (0);
+    json_decref (contract_terms);
+    return GNUNET_NO;
+  }
+  element = json_pack ("{s:O, s:o, s:o}",
+                       "order_id", 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)
+  json_decref (contract_terms);
+  if (NULL == element)
   {
     GNUNET_break_op (0);
     return GNUNET_NO;
   }
-
-  json_array_append_new (deposits_response, element);
-
+  GNUNET_break (0 ==
+                json_array_append_new (rctx->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.
@@ -254,8 +264,9 @@ build_deposits_response (void *cls,
  * @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)
+static json_t *
+transform_response (const json_t *result,
+                    struct TrackTransferContext *rctx)
 {
   json_t *deposits;
   json_t *value;
@@ -267,80 +278,93 @@ transform_response (const json_t *result, struct 
TrackTransferContext *rctx)
   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 ()
   };
-  
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Transforming /track/transfer response.\n");
   map = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
-  deposits = json_object_get (result, "deposits");
+  deposits = json_object_get (result,
+                              "deposits");
 
   json_array_foreach (deposits, index, value)
   {
-    if (GNUNET_OK != GNUNET_JSON_parse (value,
-                                        spec,
-                                        NULL,
-                                        NULL))
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (value,
+                           spec,
+                           NULL,
+                           NULL))
     {
-      GNUNET_break_op (0); 
+      GNUNET_break_op (0);
       return NULL;
     }
+    GNUNET_CRYPTO_hash_from_string (key,
+                                    &h_key);
 
-    GNUNET_CRYPTO_hash_from_string (key, &h_key);
-
-    if (NULL != (current_entry = GNUNET_CONTAINER_multihashmap_get (map, 
(const struct GNUNET_HashCode *) &h_key)))
+    if (NULL != (current_entry = GNUNET_CONTAINER_multihashmap_get (map,
+                                                                    &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)))
+      /* 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)) )
+      {
+        GNUNET_JSON_parse_free (spec);
         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))
+      /* First time in the map for this h_contract_terms*/
+      current_entry = GNUNET_new (struct Entry);
+      current_entry->deposit_value = iter_value;
+      current_entry->deposit_fee = iter_fee;
+
+      if (GNUNET_SYSERR ==
+          GNUNET_CONTAINER_multihashmap_put (map,
+                                             &h_key,
+                                             current_entry,
+                                             
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+      {
+        GNUNET_JSON_parse_free (spec);
         goto cleanup;
+      }
     }
+    GNUNET_JSON_parse_free (spec);
   }
-  deposits_response = json_array ();
-  
-  if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_iterate (map,
-                                                              
build_deposits_response,
-                                                              rctx))
-    goto cleanup;
+  rctx->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;
+  json_object_del (result_mod,
+                   "deposits");
+  json_object_set_new (result_mod,
+                       "deposits_sums",
+                       rctx->deposits_response);
+  rctx->deposits_response = NULL;
+ cleanup:
+  GNUNET_CONTAINER_multihashmap_iterate (map,
+                                         &hashmap_free,
+                                         NULL);
+  GNUNET_CONTAINER_multihashmap_destroy (map);
+  return result_mod;
 }
 
+
 /**
  * Resume the given /track/transfer operation and send the given response.
  * Stores the response in the @a rctx and signals MHD to resume
@@ -685,7 +709,8 @@ proof_cb (void *cls,
   struct TrackTransferContext *rctx = cls;
   json_t *transformed_response;
 
-  if (NULL == (transformed_response = transform_response (proof, rctx)))
+  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,
@@ -695,6 +720,7 @@ proof_cb (void *cls,
 
   rctx->response_code = MHD_HTTP_OK;
   rctx->response = TMH_RESPONSE_make_json (transformed_response);
+  json_decref (transformed_response);
 }
 
 
diff --git a/src/backenddb/Makefile.am b/src/backenddb/Makefile.am
index a5adb21..d1478cf 100644
--- a/src/backenddb/Makefile.am
+++ b/src/backenddb/Makefile.am
@@ -38,7 +38,6 @@ libtaler_plugin_merchantdb_postgres_la_LDFLAGS = \
   -ltalerutil \
   -ltalerjson \
   -lpq \
-  -lgnunetpostgres \
   -lgnunetutil $(XLIB)
 
 if HAVE_POSTGRESQL
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 5299690..5237e76 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -22,7 +22,7 @@
  */
 #include "platform.h"
 #include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_postgres_lib.h>
+#include <gnunet/gnunet_pq_lib.h>
 #include <taler/taler_util.h>
 #include <taler/taler_pq_lib.h>
 #include <taler/taler_json_lib.h>
@@ -66,60 +66,6 @@ struct PostgresClosure
 
 
 /**
- * Macro to run @a s SQL statement using #GNUNET_POSTGRES_exec()
- * and return with #GNUNET_SYSERR if the operation fails.
- *
- * @param pg context for running the statement
- * @param s SQL statement to run
- */
-#define PG_EXEC(pg,s) do {                                            \
-    if (GNUNET_OK != GNUNET_POSTGRES_exec (pg->conn, s))              \
-    {                                                                 \
-      GNUNET_break (0);                                               \
-      return GNUNET_SYSERR;                                           \
-    }                                                                 \
-  } while (0)
-
-
-/**
- * Macro to run @a s SQL statement using #GNUNET_POSTGRES_exec().
- * Ignore errors, they happen.
- *
- * @param pg context for running the statement
- * @param s SQL statement to run
- */
-#define PG_EXEC_INDEX(pg,s) do {                                        \
-    PGresult *result = PQexec (pg->conn, s);                            \
-    PQclear (result);                                                   \
-  } while (0)
-
-
-/**
- * Prepare an SQL statement and log errors on failure.
- *
- * @param pg context for running the preparation
- * @param n name of the prepared statement
- * @param s SQL statement to run
- * @param c number of arguments @a s expects
- */
-#define PG_PREPARE(pg,n,s,c) do {                                       \
-    ExecStatusType status;                                              \
-    PGresult *res = PQprepare (pg->conn, n, s, c, NULL);                \
-    if ( (NULL == res) ||                                               \
-         (PGRES_COMMAND_OK != (status = PQresultStatus (res))) )        \
-    {                                                                   \
-      if (NULL != res)                                                  \
-      {                                                                 \
-        PQSQL_strerror (GNUNET_ERROR_TYPE_ERROR, "PQprepare", res);     \
-        PQclear (res);                                                  \
-      }                                                                 \
-      return GNUNET_SYSERR;                                             \
-    }                                                                   \
-    PQclear (res);                                                      \
-  } while (0)
-
-
-/**
  * Log a really unexpected PQ error.
  *
  * @param result PQ result object of the PQ operation that failed
@@ -142,13 +88,17 @@ static int
 postgres_drop_tables (void *cls)
 {
   struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_try_execute ("DROP TABLE merchant_transfers;"),
+    GNUNET_PQ_make_try_execute ("DROP TABLE merchant_deposits;"),
+    GNUNET_PQ_make_try_execute ("DROP TABLE merchant_transactions;"),
+    GNUNET_PQ_make_try_execute ("DROP TABLE merchant_proofs;"),
+    GNUNET_PQ_make_try_execute ("DROP TABLE merchant_contract_terms;"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
 
-  PG_EXEC_INDEX (pg, "DROP TABLE merchant_transfers;");
-  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_contract_terms;");
-  return GNUNET_OK;
+  return GNUNET_PQ_exec_statements (pg->conn,
+                                    es);
 }
 
 
@@ -162,287 +112,274 @@ static int
 postgres_initialize (void *cls)
 {
   struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS 
merchant_contract_terms ("
+                            "order_id VARCHAR NOT NULL"
+                            ",merchant_pub 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)"
+                            ");"),
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_transactions 
("
+                            " 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)"
+                            ",timestamp INT8 NOT NULL"
+                            ",refund_deadline INT8 NOT NULL"
+                            ",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_contract_terms, merchant_pub)"
+                            ");"),
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_deposits ("
+                            " h_contract_terms BYTEA NOT NULL"
+                            ",merchant_pub BYTEA NOT NULL CHECK 
(LENGTH(merchant_pub)=32)"
+                            ",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"
+                            ",amount_with_fee_curr VARCHAR(" 
TALER_CURRENCY_LEN_STR ") NOT NULL"
+                            ",deposit_fee_val INT8 NOT NULL"
+                            ",deposit_fee_frac INT4 NOT NULL"
+                            ",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_contract_terms, coin_pub)"
+                            ");"),
+  GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_proofs ("
+                          " exchange_uri VARCHAR NOT NULL"
+                          ",wtid BYTEA CHECK (LENGTH(wtid)=32)"
+                          ",execution_time INT8 NOT NULL"
+                          ",signkey_pub BYTEA NOT NULL CHECK 
(LENGTH(signkey_pub)=32)"
+                          ",proof BYTEA NOT NULL"
+                          ",PRIMARY KEY (wtid, exchange_uri)"
+                          ");"),
+    /* 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! */
+    GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS merchant_transfers ("
+                            " 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_contract_terms, coin_pub)"
+                            ");"),
+    GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS 
merchant_transfers_by_coin"
+                                " ON merchant_transfers (h_contract_terms, 
coin_pub)"),
+    GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS 
merchant_transfers_by_wtid"
+                                " ON merchant_transfers (wtid)"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+  struct GNUNET_PQ_PreparedStatement ps[] = {
+    GNUNET_PQ_make_prepare ("insert_transaction",
+                            "INSERT INTO merchant_transactions"
+                            "(h_contract_terms"
+                            ",exchange_uri"
+                            ",merchant_pub"
+                            ",h_wire"
+                            ",timestamp"
+                            ",refund_deadline"
+                            ",total_amount_val"
+                            ",total_amount_frac"
+                            ",total_amount_curr"
+                            ") VALUES "
+                            "($1, $2, $3, $4, $5, $6, $7, $8, $9)",
+                            9),
+    GNUNET_PQ_make_prepare ("insert_deposit",
+                            "INSERT INTO merchant_deposits"
+                            "(h_contract_terms"
+                            ",merchant_pub"
+                            ",coin_pub"
+                            ",amount_with_fee_val"
+                            ",amount_with_fee_frac"
+                            ",amount_with_fee_curr"
+                            ",deposit_fee_val"
+                            ",deposit_fee_frac"
+                            ",deposit_fee_curr"
+                            ",signkey_pub"
+                            ",exchange_proof) VALUES "
+                            "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
+                            11),
+    GNUNET_PQ_make_prepare ("insert_transfer",
+                            "INSERT INTO merchant_transfers"
+                            "(h_contract_terms"
+                            ",coin_pub"
+                            ",wtid) VALUES "
+                            "($1, $2, $3)",
+                            3),
+    GNUNET_PQ_make_prepare ("insert_proof",
+                            "INSERT INTO merchant_proofs"
+                            "(exchange_uri"
+                            ",wtid"
+                            ",execution_time"
+                            ",signkey_pub"
+                            ",proof) VALUES "
+                            "($1, $2, $3, $4, $5)",
+                            5),
+    GNUNET_PQ_make_prepare ("insert_contract_terms",
+                            "INSERT INTO merchant_contract_terms"
+                            "(order_id"
+                            ",merchant_pub"
+                            ",timestamp"
+                            ",contract_terms"
+                            ",h_contract_terms)"
+                            " VALUES "
+                            "($1, $2, $3, $4, $5)",
+                            4),
+    GNUNET_PQ_make_prepare ("find_contract_terms_from_hash",
+                            "SELECT"
+                            " contract_terms"
+                            " FROM merchant_contract_terms"
+                            " WHERE"
+                            " h_contract_terms=$1"
+                            " AND merchant_pub=$2",
+                            2),
+    GNUNET_PQ_make_prepare ("find_contract_terms",
+                            "SELECT"
+                            " contract_terms"
+                            " FROM merchant_contract_terms"
+                            " WHERE"
+                            " order_id=$1"
+                            " AND merchant_pub=$2",
+                            2),
+    GNUNET_PQ_make_prepare ("find_contract_terms_by_date",
+                            "SELECT"
+                            " contract_terms"
+                            ",order_id"
+                            ",row_id"
+                            " FROM merchant_contract_terms"
+                            " WHERE"
+                            " timestamp<$1"
+                            " AND merchant_pub=$2"
+                            " ORDER BY row_id DESC, timestamp DESC"
+                            " LIMIT $3",
+                            3),
+    GNUNET_PQ_make_prepare ("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),
+    GNUNET_PQ_make_prepare ("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),
+    GNUNET_PQ_make_prepare ("find_transaction",
+                            "SELECT"
+                            " exchange_uri"
+                            ",h_wire"
+                            ",timestamp"
+                            ",refund_deadline"
+                            ",total_amount_val"
+                            ",total_amount_frac"
+                            ",total_amount_curr"
+                            " FROM merchant_transactions"
+                            " WHERE h_contract_terms=$1"
+                            " AND merchant_pub=$2",
+                            2),
+    GNUNET_PQ_make_prepare ("find_deposits",
+                            "SELECT"
+                            " coin_pub"
+                            ",amount_with_fee_val"
+                            ",amount_with_fee_frac"
+                            ",amount_with_fee_curr"
+                            ",deposit_fee_val"
+                            ",deposit_fee_frac"
+                            ",deposit_fee_curr"
+                            ",exchange_proof"
+                            " FROM merchant_deposits"
+                            " WHERE h_contract_terms=$1"
+                            " AND merchant_pub=$2",
+                            2),
+    GNUNET_PQ_make_prepare ("find_deposits_by_hash_and_coin",
+                            "SELECT"
+                            " amount_with_fee_val"
+                            ",amount_with_fee_frac"
+                            ",amount_with_fee_curr"
+                            ",deposit_fee_val"
+                            ",deposit_fee_frac"
+                            ",deposit_fee_curr"
+                            ",exchange_proof"
+                            " FROM merchant_deposits"
+                            " WHERE h_contract_terms=$1"
+                            " AND merchant_pub=$2"
+                            " AND coin_pub=$3",
+                            3),
+    GNUNET_PQ_make_prepare ("find_transfers_by_hash",
+                            "SELECT"
+                            " coin_pub"
+                            ",wtid"
+                            ",merchant_proofs.execution_time"
+                            ",merchant_proofs.proof"
+                            " FROM merchant_transfers"
+                            "   JOIN merchant_proofs USING (wtid)"
+                            " WHERE h_contract_terms=$1",
+                            1),
+    GNUNET_PQ_make_prepare ("find_deposits_by_wtid",
+                            "SELECT"
+                            " merchant_transfers.h_contract_terms"
+                            ",merchant_transfers.coin_pub"
+                            ",merchant_deposits.amount_with_fee_val"
+                            ",merchant_deposits.amount_with_fee_frac"
+                            ",merchant_deposits.amount_with_fee_curr"
+                            ",merchant_deposits.deposit_fee_val"
+                            ",merchant_deposits.deposit_fee_frac"
+                            ",merchant_deposits.deposit_fee_curr"
+                            ",merchant_deposits.exchange_proof"
+                            " FROM merchant_transfers"
+                            "   JOIN merchant_deposits"
+                            "     ON (merchant_deposits.h_contract_terms = 
merchant_transfers.h_contract_terms"
+                            "       AND"
+                            "         merchant_deposits.coin_pub = 
merchant_transfers.coin_pub)"
+                            " WHERE wtid=$1",
+                            1),
+    GNUNET_PQ_make_prepare ("find_proof_by_wtid",
+                            "SELECT"
+                            " proof"
+                            " FROM merchant_proofs"
+                            " WHERE wtid=$1"
+                            "  AND exchange_uri=$2",
+                            2),
+    GNUNET_PQ_PREPARED_STATEMENT_END
+  };
 
-  /* Setup tables */
-  PG_EXEC (pg,
-           "CREATE TABLE IF NOT EXISTS merchant_contract_terms ("
-           "order_id VARCHAR NOT NULL"
-           ",merchant_pub 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_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)"
-           ",timestamp INT8 NOT NULL"
-           ",refund_deadline INT8 NOT NULL"
-           ",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_contract_terms, merchant_pub)"
-           ");");
-  PG_EXEC (pg,
-           "CREATE TABLE IF NOT EXISTS merchant_deposits ("
-          " h_contract_terms BYTEA NOT NULL"
-          ",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)"
-          ",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"
-           ",amount_with_fee_curr VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL"
-           ",deposit_fee_val INT8 NOT NULL"
-           ",deposit_fee_frac INT4 NOT NULL"
-           ",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_contract_terms, coin_pub)"
-           ");");
-  PG_EXEC (pg,
-           "CREATE TABLE IF NOT EXISTS merchant_proofs ("
-           " exchange_uri VARCHAR NOT NULL"
-           ",wtid BYTEA CHECK (LENGTH(wtid)=32)"
-           ",execution_time INT8 NOT NULL"
-           ",signkey_pub BYTEA NOT NULL CHECK (LENGTH(signkey_pub)=32)"
-           ",proof BYTEA NOT NULL"
-           ",PRIMARY KEY (wtid, exchange_uri)"
-           ");");
-  /* 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_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_contract_terms, coin_pub)"
-           ");");
-  PG_EXEC_INDEX (pg,
-                 "CREATE INDEX IF NOT EXISTS merchant_transfers_by_coin"
-                 " 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)");
-
-  /* Setup prepared "INSERT" statements */
-  PG_PREPARE (pg,
-              "insert_transaction",
-              "INSERT INTO merchant_transactions"
-              "(h_contract_terms"
-              ",exchange_uri"
-             ",merchant_pub"
-              ",h_wire"
-              ",timestamp"
-              ",refund_deadline"
-              ",total_amount_val"
-              ",total_amount_frac"
-              ",total_amount_curr"
-              ") VALUES "
-              "($1, $2, $3, $4, $5, $6, $7, $8, $9)",
-              9);
-  PG_PREPARE (pg,
-              "insert_deposit",
-              "INSERT INTO merchant_deposits"
-              "(h_contract_terms"
-             ",merchant_pub"
-              ",coin_pub"
-              ",amount_with_fee_val"
-              ",amount_with_fee_frac"
-              ",amount_with_fee_curr"
-              ",deposit_fee_val"
-              ",deposit_fee_frac"
-              ",deposit_fee_curr"
-              ",signkey_pub"
-              ",exchange_proof) VALUES "
-              "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
-              11);
-  PG_PREPARE (pg,
-              "insert_transfer",
-              "INSERT INTO merchant_transfers"
-              "(h_contract_terms"
-              ",coin_pub"
-              ",wtid) VALUES "
-              "($1, $2, $3)",
-              3);
-  PG_PREPARE (pg,
-              "insert_proof",
-              "INSERT INTO merchant_proofs"
-              "(exchange_uri"
-              ",wtid"
-              ",execution_time"
-              ",signkey_pub"
-              ",proof) VALUES "
-              "($1, $2, $3, $4, $5)",
-              5);
-
-  PG_PREPARE (pg,
-              "insert_contract_terms",
-              "INSERT INTO merchant_contract_terms"
-              "(order_id"
-              ",merchant_pub"
-              ",timestamp"
-              ",contract_terms"
-              ",h_contract_terms)"
-              " VALUES "
-              "($1, $2, $3, $4, $5)",
-              4);
-
-  PG_PREPARE (pg,
-              "find_contract_terms_from_hash",
-              "SELECT"
-              " contract_terms"
-              " FROM merchant_contract_terms"
-              " WHERE"
-              " h_contract_terms=$1"
-              " AND merchant_pub=$2",
-              2);
-
-  PG_PREPARE (pg,
-              "find_contract_terms",
-              "SELECT"
-              " contract_terms"
-              " FROM merchant_contract_terms"
-              " WHERE"
-              " order_id=$1"
-              " AND merchant_pub=$2",
-              2);
-
-  PG_PREPARE (pg,
-              "find_contract_terms_by_date",
-              "SELECT"
-              " contract_terms"
-              ",order_id"
-              ",row_id"
-              " FROM merchant_contract_terms"
-              " WHERE"
-              " timestamp<$1"
-              " AND merchant_pub=$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,
-              "find_transaction",
-              "SELECT"
-              " exchange_uri"
-              ",h_wire"
-              ",timestamp"
-              ",refund_deadline"
-              ",total_amount_val"
-              ",total_amount_frac"
-              ",total_amount_curr"
-              " FROM merchant_transactions"
-              " WHERE h_contract_terms=$1"
-             " AND merchant_pub=$2",
-              2);
-  PG_PREPARE (pg,
-              "find_deposits",
-              "SELECT"
-              " coin_pub"
-              ",amount_with_fee_val"
-              ",amount_with_fee_frac"
-              ",amount_with_fee_curr"
-              ",deposit_fee_val"
-              ",deposit_fee_frac"
-              ",deposit_fee_curr"
-              ",exchange_proof"
-              " FROM merchant_deposits"
-              " WHERE h_contract_terms=$1"
-              " AND merchant_pub=$2",
-              2);
-  PG_PREPARE (pg,
-              "find_deposits_by_hash_and_coin",
-              "SELECT"
-              " amount_with_fee_val"
-              ",amount_with_fee_frac"
-              ",amount_with_fee_curr"
-              ",deposit_fee_val"
-              ",deposit_fee_frac"
-              ",deposit_fee_curr"
-              ",exchange_proof"
-              " FROM merchant_deposits"
-              " WHERE h_contract_terms=$1"
-              " AND merchant_pub=$2"
-              " AND coin_pub=$3",
-              3);
-  PG_PREPARE (pg,
-              "find_transfers_by_hash",
-              "SELECT"
-              " coin_pub"
-              ",wtid"
-              ",merchant_proofs.execution_time"
-              ",merchant_proofs.proof"
-              " FROM merchant_transfers"
-              "   JOIN merchant_proofs USING (wtid)"
-              " WHERE h_contract_terms=$1",
-              1);
-  PG_PREPARE (pg,
-              "find_deposits_by_wtid",
-              "SELECT"
-              " merchant_transfers.h_contract_terms"
-              ",merchant_transfers.coin_pub"
-              ",merchant_deposits.amount_with_fee_val"
-              ",merchant_deposits.amount_with_fee_frac"
-              ",merchant_deposits.amount_with_fee_curr"
-              ",merchant_deposits.deposit_fee_val"
-              ",merchant_deposits.deposit_fee_frac"
-              ",merchant_deposits.deposit_fee_curr"
-              ",merchant_deposits.exchange_proof"
-              " FROM merchant_transfers"
-              "   JOIN merchant_deposits"
-              "     ON (merchant_deposits.h_contract_terms = 
merchant_transfers.h_contract_terms"
-              "       AND"
-              "         merchant_deposits.coin_pub = 
merchant_transfers.coin_pub)"
-              " WHERE wtid=$1",
-              1);
-  PG_PREPARE (pg,
-              "find_proof_by_wtid",
-              "SELECT"
-              " proof"
-              " FROM merchant_proofs"
-              " WHERE wtid=$1"
-              "  AND exchange_uri=$2",
-              2);
+  if (GNUNET_OK !=
+      GNUNET_PQ_exec_statements (pg->conn,
+                                 es))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_PQ_prepare_statements (pg->conn,
+                                    ps))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
   return GNUNET_OK;
 }
 
+
 /**
  * Retrieve proposal data given its proposal data's hashcode
  *
@@ -460,44 +397,35 @@ postgres_find_contract_terms_from_hash (void *cls,
                                        const struct TALER_MerchantPublicKeyP 
*merchant_pub)
 {
   struct PostgresClosure *pg = cls;
-  PGresult *result;
-  unsigned int i;
-
+  enum GNUNET_PQ_QueryStatus res;
   struct GNUNET_PQ_QueryParam params[] = {
     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_contract_terms_from_hash",
-                                    params);
-  i = PQntuples (result);
-  if (1 < i)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Mupltiple proposal data hash 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))
+
+  res = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                  
"find_contract_terms_from_hash",
+                                                  params,
+                                                  rs);
+  if (res < 0)
   {
     GNUNET_break (0);
-    PQclear (result);
     return GNUNET_SYSERR;
   }
-
+  if (1 < res)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Mupltiple proposal data hash the same hashcode!\n");
+    return GNUNET_SYSERR;
+  }
+  if (0 == res)
+    return GNUNET_NO;
   return GNUNET_OK;
 }
 
@@ -506,56 +434,52 @@ postgres_find_contract_terms_from_hash (void *cls,
  * Retrieve proposal data given its order id.
  *
  * @param cls closure
- * @param contract_terms where to store the retrieved proposal data
+ * @param[out] 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_contract_terms (void *cls,
-                             json_t **contract_terms,
-                             const char *order_id,
-                             const struct TALER_MerchantPublicKeyP 
*merchant_pub)
+                              json_t **contract_terms,
+                              const char *order_id,
+                              const struct TALER_MerchantPublicKeyP 
*merchant_pub)
 {
   struct PostgresClosure *pg = cls;
-  PGresult *result;
-  unsigned int i;
-
+  enum GNUNET_PQ_QueryStatus res;
   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))
+
+  *contract_terms = NULL;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finding contract term, order_id: '%s', merchant_pub: '%s'.\n",
+              order_id,
+              TALER_B2S (merchant_pub));
+  res = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                  "find_contract_terms",
+                                                  params,
+                                                  rs);
+  if (res < 0)
   {
     GNUNET_break (0);
-    PQclear (result);
     return GNUNET_SYSERR;
   }
-
+  if (res > 1)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Mupltiple proposal data share the same hashcode.\n");
+    return GNUNET_SYSERR;
+  }
+  if (0 == res)
+    return GNUNET_NO;
   return GNUNET_OK;
 }
 
@@ -584,6 +508,12 @@ postgres_insert_contract_terms (void *cls,
                                     &h_contract_terms))
     return GNUNET_SYSERR;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "inserting contract_terms: order_id: %s, merchant_pub: %s, 
h_contract_terms: %s.\n",
+              order_id,
+              TALER_B2S (merchant_pub),
+              GNUNET_h2s (&h_contract_terms));
+
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_string (order_id),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
@@ -659,8 +589,9 @@ postgres_store_transaction (void *cls,
   };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Storing transaction with h_contract_terms '%s'\n",
-              GNUNET_h2s (h_contract_terms));
+              "Storing transaction with h_contract_terms '%s', merchant_pub 
'%s'.\n",
+              GNUNET_h2s (h_contract_terms),
+              TALER_B2S (merchant_pub));
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "insert_transaction",
@@ -705,7 +636,6 @@ postgres_store_deposit (void *cls,
   struct PostgresClosure *pg = cls;
   PGresult *result;
   int ret;
-
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
     GNUNET_PQ_query_param_auto_from_type (merchant_pub),
@@ -897,7 +827,7 @@ postgres_find_contract_terms_history (void *cls,
   PQclear (result);
   return GNUNET_OK;
 
-}                                     
+}
 
 
 /**
@@ -1118,8 +1048,9 @@ postgres_find_transaction (void *cls,
   };
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Finding transaction for h_contract_terms '%s'\n",
-              GNUNET_h2s (h_contract_terms));
+              "Finding transaction for h_contract_terms '%s', merchant_pub: 
'%s'.\n",
+              GNUNET_h2s (h_contract_terms),
+              TALER_B2S (merchant_pub));
 
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "find_transaction",
@@ -1554,12 +1485,12 @@ postgres_find_proof_by_wtid (void *cls,
 {
   struct PostgresClosure *pg = cls;
   PGresult *result;
-
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (wtid),
     GNUNET_PQ_query_param_string (exchange_uri),
     GNUNET_PQ_query_param_end
   };
+
   result = GNUNET_PQ_exec_prepared (pg->conn,
                                     "find_proof_by_wtid",
                                     params);
@@ -1583,7 +1514,6 @@ postgres_find_proof_by_wtid (void *cls,
 
   {
     json_t *proof;
-
     struct GNUNET_PQ_ResultSpec rs[] = {
       TALER_PQ_result_spec_json ("proof",
                                  &proof),
@@ -1645,7 +1575,8 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
       return NULL;
     }
   }
-  pg->conn = GNUNET_POSTGRES_connect (cfg, "merchantdb-postgres");
+  pg->conn = GNUNET_PQ_connect_with_cfg (cfg,
+                                         "merchantdb-postgres");
   if (NULL == pg->conn)
   {
     GNUNET_free (pg);
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index db27e0e..92f4a53 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -183,7 +183,7 @@ struct TALER_MERCHANTDB_Plugin
    * Retrieve proposal data given its order ID.
    *
    * @param cls closure
-   * @param contract_terms where to store the result
+   * @param[out] 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
@@ -226,8 +226,8 @@ struct TALER_MERCHANTDB_Plugin
    * 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 future if set to #GNUNET_YES, retrieves rows younger than `date`.
+   * This is typically 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
@@ -250,8 +250,8 @@ struct TALER_MERCHANTDB_Plugin
    * @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
+   * @param cb_cls closure to pass to @a cb
+   * @return #GNUNET_YES, #GNUNET_NO, #GNUNET_SYSERR according to the
    * query being successful, unsuccessful, or generated errors.
    */
   int
diff --git a/src/lib/merchant_api_history.c b/src/lib/merchant_api_history.c
index a2c2d5f..c002d0a 100644
--- a/src/lib/merchant_api_history.c
+++ b/src/lib/merchant_api_history.c
@@ -61,6 +61,7 @@ struct TALER_MERCHANT_HistoryOperation
   struct GNUNET_CURL_Context *ctx;
 };
 
+
 /**
  * Cancel a pending /history request
  *
@@ -95,7 +96,6 @@ history_raw_cb (void *cls,
   struct TALER_MERCHANT_HistoryOperation *ho = cls;
 
   ho->job = NULL;
-
   switch (response_code)
   {
   case 0:
@@ -105,8 +105,8 @@ history_raw_cb (void *cls,
             MHD_HTTP_OK,
            TALER_EC_NONE,
             json);
+    TALER_MERCHANT_history_cancel (ho);
     return;
-    break;
   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                "/history URI not found\n");
@@ -128,6 +128,7 @@ history_raw_cb (void *cls,
           response_code,
          TALER_JSON_get_error_code (json),
           json);
+  TALER_MERCHANT_history_cancel (ho);
 }
 
 
@@ -178,9 +179,9 @@ TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
                                     CURLOPT_URL,
                                     ho->url))
   {
-    GNUNET_break (0);  
+    GNUNET_break (0);
     return NULL;
-  }    
+  }
 
   if (NULL == (ho->job = GNUNET_CURL_job_add (ctx,
                                               eh,
@@ -192,7 +193,7 @@ TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
     return NULL;
   }
   return ho;
-}                        
+}
 
 
 /* end of merchant_api_contract.c */
diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c
index 9422e07..aa875bc 100644
--- a/src/lib/merchant_api_pay.c
+++ b/src/lib/merchant_api_pay.c
@@ -243,6 +243,7 @@ handle_pay_finished (void *cls,
           response_code,
          TALER_JSON_get_error_code (json),
           json);
+  TALER_MERCHANT_pay_cancel (ph);
 }
 
 
diff --git a/src/lib/merchant_api_proposal.c b/src/lib/merchant_api_proposal.c
index c200ce5..84f7045 100644
--- a/src/lib/merchant_api_proposal.c
+++ b/src/lib/merchant_api_proposal.c
@@ -127,9 +127,9 @@ handle_proposal_finished (void *cls,
   hashp = NULL;
   switch (response_code)
   {
-    case 0:
-      break;
-    case MHD_HTTP_OK:
+  case 0:
+    break;
+  case MHD_HTTP_OK:
     {
       struct GNUNET_JSON_Specification spec[] = {
         GNUNET_JSON_spec_json ("data", &contract_terms),
@@ -150,33 +150,33 @@ handle_proposal_finished (void *cls,
       hashp = &hash;
       sigp = &sig;
     }
-      break;
-    case MHD_HTTP_BAD_REQUEST:
+    break;
+  case MHD_HTTP_BAD_REQUEST:
       /* This should never happen, either us or the merchant is buggy
          (or API version conflict); just pass JSON reply to the application */
-      break;
-    case MHD_HTTP_FORBIDDEN:
-      break;
-    case MHD_HTTP_UNAUTHORIZED:
-      /* Nothing really to verify, merchant says one of the signatures is
-         invalid; as we checked them, this should never happen, we
-         should pass the JSON reply to the application */
-      break;
-    case MHD_HTTP_NOT_FOUND:
-      /* Nothing really to verify, this should never
-         happen, we should pass the JSON reply to the application */
-      break;
-    case MHD_HTTP_INTERNAL_SERVER_ERROR:
-      /* Server had an internal issue; we should retry, but this API
-         leaves this to the application */
-      break;
-    default:
-      /* unexpected response code */
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Unexpected response code %u\n",
-                  (unsigned int) response_code);
-      GNUNET_break (0);
-      response_code = 0;
+    break;
+  case MHD_HTTP_FORBIDDEN:
+    break;
+  case MHD_HTTP_UNAUTHORIZED:
+    /* Nothing really to verify, merchant says one of the signatures is
+       invalid; as we checked them, this should never happen, we
+       should pass the JSON reply to the application */
+    break;
+  case MHD_HTTP_NOT_FOUND:
+    /* Nothing really to verify, this should never
+       happen, we should pass the JSON reply to the application */
+    break;
+  case MHD_HTTP_INTERNAL_SERVER_ERROR:
+    /* Server had an internal issue; we should retry, but this API
+       leaves this to the application */
+    break;
+  default:
+    /* unexpected response code */
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u\n",
+                (unsigned int) response_code);
+    GNUNET_break (0);
+    response_code = 0;
   }
   po->cb (po->cb_cls,
           response_code,
@@ -187,6 +187,7 @@ handle_proposal_finished (void *cls,
           hashp);
   if (NULL != contract_terms)
     json_decref (contract_terms);
+  TALER_MERCHANT_proposal_cancel (po);
 }
 
 
@@ -255,6 +256,7 @@ TALER_MERCHANT_order_put (struct GNUNET_CURL_Context *ctx,
   return po;
 }
 
+
 /**
  * Function called when we're done processing the GET /proposal request.
  *
@@ -269,6 +271,7 @@ handle_proposal_lookup_finished (void *cls,
 {
   struct TALER_MERCHANT_ProposalLookupOperation *plo = cls;
 
+  plo->job = NULL;
   /**
    * As no data is supposed to be extracted from this
    * call, we just invoke the provided callback.
@@ -276,8 +279,10 @@ handle_proposal_lookup_finished (void *cls,
   plo->cb (plo->cb_cls,
            response_code,
            json);
+  TALER_MERCHANT_proposal_lookup_cancel (plo);
 }
 
+
 /**
  * Calls the GET /proposal API at the backend.  That is,
  * retrieve a proposal data by providing its transaction id.
@@ -329,9 +334,9 @@ TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context 
*ctx,
     return NULL;
   }
   return plo;
-
 }
 
+
 /**
  * Cancel a PUT /proposal request.  This function cannot be used
  * on a request handle if a response is already served for it.
@@ -351,6 +356,7 @@ TALER_MERCHANT_proposal_cancel (struct 
TALER_MERCHANT_ProposalOperation *po)
   GNUNET_free (po);
 }
 
+
 /**
  * Cancel a GET /proposal request.
  *
diff --git a/src/lib/merchant_api_track_transaction.c 
b/src/lib/merchant_api_track_transaction.c
index 4e11acc..560408f 100644
--- a/src/lib/merchant_api_track_transaction.c
+++ b/src/lib/merchant_api_track_transaction.c
@@ -109,7 +109,10 @@ handle_track_transaction_finished (void *cls,
     if (GNUNET_OK ==
         parse_track_transaction_ok (tdo,
                                     json))
+    {
+      TALER_MERCHANT_track_transaction_cancel (tdo);
       return;
+    }
     response_code = 0;
     break;
   case MHD_HTTP_ACCEPTED:
@@ -140,6 +143,7 @@ handle_track_transaction_finished (void *cls,
            response_code,
           TALER_JSON_get_error_code (json),
            json);
+  TALER_MERCHANT_track_transaction_cancel (tdo);
 }
 
 
diff --git a/src/lib/merchant_api_track_transfer.c 
b/src/lib/merchant_api_track_transfer.c
index 0de4ac8..fcd208c 100644
--- a/src/lib/merchant_api_track_transfer.c
+++ b/src/lib/merchant_api_track_transfer.c
@@ -173,7 +173,10 @@ handle_track_transfer_finished (void *cls,
     if (GNUNET_OK ==
         check_track_transfer_response_ok (tdo,
                                           json))
+    {
+      TALER_MERCHANT_track_transfer_cancel (tdo);
       return;
+    }
     GNUNET_break_op (0);
     response_code = 0;
     break;
@@ -203,6 +206,7 @@ handle_track_transfer_finished (void *cls,
            NULL,
            0,
            NULL);
+  TALER_MERCHANT_track_transfer_cancel (tdo);
 }
 
 
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
index 6d0f613..4b157ee 100644
--- a/src/lib/test_merchant_api.c
+++ b/src/lib/test_merchant_api.c
@@ -772,6 +772,7 @@ history_cb (void *cls,
   struct Command *cmd = &is->commands[is->ip];
   unsigned int nresult;
 
+  cmd->details.history.ho = NULL;
   if (MHD_HTTP_OK != http_status)
   {
     fail (is);
@@ -794,6 +795,7 @@ history_cb (void *cls,
   next_command (is);
 }
 
+
 /**
  * Check if the given historic event @a h corresponds to the given
  * command @a cmd.
@@ -1019,6 +1021,7 @@ reserve_withdraw_cb (void *cls,
       fail (is);
       return;
     }
+    GNUNET_assert (NULL == cmd->details.reserve_withdraw.sig.rsa_signature);
     cmd->details.reserve_withdraw.sig.rsa_signature
       = GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
     break;
@@ -1156,9 +1159,7 @@ pay_cb (void *cls,
       fail (is);
       return;
     }
-
   }
-
   next_command (is);
 }
 
@@ -1235,7 +1236,6 @@ track_transfer_cb (void *cls,
   {
     case MHD_HTTP_OK:
       break;
-
     default:
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Unhandled HTTP status.\n");
@@ -1243,6 +1243,7 @@ track_transfer_cb (void *cls,
   next_command (is);
 }
 
+
 /**
  * Callback for GET /proposal issued at backend. Just check
  * whether response code is as expected.
@@ -1259,13 +1260,12 @@ proposal_lookup_cb (void *cls,
   struct Command *cmd = &is->commands[is->ip];
 
   cmd->details.proposal_lookup.plo = NULL;
-
   if (cmd->expected_response_code != http_status)
     fail (is);
-
   next_command (is);
 }
 
+
 /**
  * Function called with detailed wire transfer data.
  *
@@ -1357,6 +1357,153 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys,
 
 
 /**
+ * Reset the interpreter's state.
+ *
+ * @param is interpreter to reset
+ */
+static void
+cleanup_state (struct InterpreterState *is)
+{
+  struct Command *cmd;
+
+  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_PROPOSAL_LOOKUP:
+      if (NULL != cmd->details.proposal_lookup.plo)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_MERCHANT_proposal_lookup_cancel 
(cmd->details.proposal_lookup.plo);
+      }
+      break;
+    case OC_ADMIN_ADD_INCOMING:
+      if (NULL != cmd->details.admin_add_incoming.aih)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_EXCHANGE_admin_add_incoming_cancel 
(cmd->details.admin_add_incoming.aih);
+        cmd->details.admin_add_incoming.aih = NULL;
+      }
+      break;
+    case OC_WITHDRAW_STATUS:
+      if (NULL != cmd->details.reserve_status.wsh)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_EXCHANGE_reserve_status_cancel (cmd->details.reserve_status.wsh);
+        cmd->details.reserve_status.wsh = NULL;
+      }
+      break;
+    case OC_WITHDRAW_SIGN:
+      if (NULL != cmd->details.reserve_withdraw.wsh)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_EXCHANGE_reserve_withdraw_cancel 
(cmd->details.reserve_withdraw.wsh);
+        cmd->details.reserve_withdraw.wsh = NULL;
+      }
+      if (NULL != cmd->details.reserve_withdraw.sig.rsa_signature)
+      {
+        GNUNET_CRYPTO_rsa_signature_free 
(cmd->details.reserve_withdraw.sig.rsa_signature);
+        cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
+      }
+      break;
+    case OC_PROPOSAL:
+      if (NULL != cmd->details.proposal.po)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
+        cmd->details.proposal.po = NULL;
+      }
+      if (NULL != cmd->details.proposal.contract_terms)
+      {
+        json_decref (cmd->details.proposal.contract_terms);
+        cmd->details.proposal.contract_terms = NULL;
+      }
+      break;
+    case OC_PAY:
+      if (NULL != cmd->details.pay.ph)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_MERCHANT_pay_cancel (cmd->details.pay.ph);
+        cmd->details.pay.ph = NULL;
+      }
+      break;
+    case OC_RUN_AGGREGATOR:
+      if (NULL != cmd->details.run_aggregator.aggregator_proc)
+      {
+        GNUNET_break (0 ==
+                      GNUNET_OS_process_kill 
(cmd->details.run_aggregator.aggregator_proc,
+                                              SIGKILL));
+        GNUNET_OS_process_wait (cmd->details.run_aggregator.aggregator_proc);
+        GNUNET_OS_process_destroy 
(cmd->details.run_aggregator.aggregator_proc);
+        cmd->details.run_aggregator.aggregator_proc = NULL;
+      }
+      if (NULL != cmd->details.run_aggregator.child_death_task)
+      {
+        GNUNET_SCHEDULER_cancel (cmd->details.run_aggregator.child_death_task);
+        cmd->details.run_aggregator.child_death_task = NULL;
+      }
+      break;
+    case OC_CHECK_BANK_TRANSFER:
+      break;
+    case OC_CHECK_BANK_TRANSFERS_EMPTY:
+      break;
+    case OC_TRACK_TRANSFER:
+      if (NULL != cmd->details.track_transfer.tdo)
+      {
+        TALER_MERCHANT_track_transfer_cancel (cmd->details.track_transfer.tdo);
+        cmd->details.track_transfer.tdo = NULL;
+      }
+      break;
+    case OC_TRACK_TRANSACTION:
+      if (NULL != cmd->details.track_transaction.tth)
+      {
+        TALER_MERCHANT_track_transaction_cancel 
(cmd->details.track_transaction.tth);
+        cmd->details.track_transaction.tth = NULL;
+      }
+      break;
+    case OC_HISTORY:
+
+      if (NULL != cmd->details.history.ho)
+      {
+        TALER_MERCHANT_history_cancel (cmd->details.history.ho);
+        cmd->details.history.ho = NULL;
+      }
+      break;
+
+    default:
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Shutdown: unknown instruction %d at %u (%s)\n",
+                  cmd->oc,
+                  i,
+                  cmd->label);
+      break;
+    }
+  }
+}
+
+
+/**
  * Run the main interpreter loop that performs exchange operations.
  *
  * @param cls contains the `struct InterpreterState`
@@ -1398,13 +1545,13 @@ interpreter_run (void *cls)
         GNUNET_SCHEDULER_shutdown ();
         return;
       }
+      cleanup_state (is);
       is->ip = 0;
       instance_idx++;
       instance = instances[instance_idx];
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Switching instance: '%s'\n",
+                  "Switching instance: `%s'\n",
                   instance);
-
       is->task = GNUNET_SCHEDULER_add_now (interpreter_run,
                                            is);
       return;
@@ -1598,14 +1745,15 @@ interpreter_run (void *cls)
                           &error);
       if (NULL != instance)
       {
-
         json_t *merchant;
 
         merchant = json_object ();
         json_object_set_new (merchant,
                              "instance",
                              json_string (instance));
-        json_object_set (order, "merchant", merchant);
+        json_object_set_new (order,
+                             "merchant",
+                             merchant);
       }
       if (NULL == order)
       {
@@ -1864,7 +2012,7 @@ interpreter_run (void *cls)
                                                           
cmd->details.history.start,
                                                           
cmd->details.history.nrows,
                                                          
cmd->details.history.date,
-                                                         history_cb,
+                                                         &history_cb,
                                                          is)))
     {
       fail (is);
@@ -1907,8 +2055,6 @@ static void
 do_shutdown (void *cls)
 {
   struct InterpreterState *is = cls;
-  struct Command *cmd;
-  unsigned int i;
 
   if (NULL != timeout_task)
   {
@@ -1917,147 +2063,15 @@ do_shutdown (void *cls)
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Shutdown executing\n");
-  for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++)
-  {
-    switch (cmd->oc)
-    {
-    case OC_END:
-      GNUNET_assert (0);
-      break;
-    case OC_PROPOSAL_LOOKUP:
-      if (NULL != cmd->details.proposal_lookup.plo)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Command %u (%s) did not complete\n",
-                    i,
-                    cmd->label);
-        TALER_MERCHANT_proposal_lookup_cancel 
(cmd->details.proposal_lookup.plo);
-      }
-        break;
-
-    case OC_ADMIN_ADD_INCOMING:
-      if (NULL != cmd->details.admin_add_incoming.aih)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Command %u (%s) did not complete\n",
-                    i,
-                    cmd->label);
-        TALER_EXCHANGE_admin_add_incoming_cancel 
(cmd->details.admin_add_incoming.aih);
-        cmd->details.admin_add_incoming.aih = NULL;
-      }
-      break;
-    case OC_WITHDRAW_STATUS:
-      if (NULL != cmd->details.reserve_status.wsh)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Command %u (%s) did not complete\n",
-                    i,
-                    cmd->label);
-        TALER_EXCHANGE_reserve_status_cancel (cmd->details.reserve_status.wsh);
-        cmd->details.reserve_status.wsh = NULL;
-      }
-      break;
-    case OC_WITHDRAW_SIGN:
-      if (NULL != cmd->details.reserve_withdraw.wsh)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Command %u (%s) did not complete\n",
-                    i,
-                    cmd->label);
-        TALER_EXCHANGE_reserve_withdraw_cancel 
(cmd->details.reserve_withdraw.wsh);
-        cmd->details.reserve_withdraw.wsh = NULL;
-      }
-      if (NULL != cmd->details.reserve_withdraw.sig.rsa_signature)
-      {
-        GNUNET_CRYPTO_rsa_signature_free 
(cmd->details.reserve_withdraw.sig.rsa_signature);
-        cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
-      }
-      break;
-    case OC_PROPOSAL:
-      if (NULL != cmd->details.proposal.po)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Command %u (%s) did not complete\n",
-                    i,
-                    cmd->label);
-        TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
-        cmd->details.proposal.po = NULL;
-      }
-      if (NULL != cmd->details.proposal.contract_terms)
-      {
-        json_decref (cmd->details.proposal.contract_terms);
-        cmd->details.proposal.contract_terms = NULL;
-      }
-      break;
-    case OC_PAY:
-      if (NULL != cmd->details.pay.ph)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "Command %u (%s) did not complete\n",
-                    i,
-                    cmd->label);
-        TALER_MERCHANT_pay_cancel (cmd->details.pay.ph);
-        cmd->details.pay.ph = NULL;
-      }
-      break;
-    case OC_RUN_AGGREGATOR:
-      if (NULL != cmd->details.run_aggregator.aggregator_proc)
-      {
-        GNUNET_break (0 ==
-                      GNUNET_OS_process_kill 
(cmd->details.run_aggregator.aggregator_proc,
-                                              SIGKILL));
-        GNUNET_OS_process_wait (cmd->details.run_aggregator.aggregator_proc);
-        GNUNET_OS_process_destroy 
(cmd->details.run_aggregator.aggregator_proc);
-        cmd->details.run_aggregator.aggregator_proc = NULL;
-      }
-      if (NULL != cmd->details.run_aggregator.child_death_task)
-      {
-        GNUNET_SCHEDULER_cancel (cmd->details.run_aggregator.child_death_task);
-        cmd->details.run_aggregator.child_death_task = NULL;
-      }
-      break;
-    case OC_CHECK_BANK_TRANSFER:
-      break;
-    case OC_CHECK_BANK_TRANSFERS_EMPTY:
-      break;
-    case OC_TRACK_TRANSFER:
-      if (NULL != cmd->details.track_transfer.tdo)
-      {
-        TALER_MERCHANT_track_transfer_cancel (cmd->details.track_transfer.tdo);
-        cmd->details.track_transfer.tdo = NULL;
-      }
-      break;
-    case OC_TRACK_TRANSACTION:
-      if (NULL != cmd->details.track_transaction.tth)
-      {
-        TALER_MERCHANT_track_transaction_cancel 
(cmd->details.track_transaction.tth);
-        cmd->details.track_transaction.tth = NULL;
-      }
-      break;
-    case OC_HISTORY:
-
-      if (NULL != cmd->details.history.ho)
-      {
-        TALER_MERCHANT_history_cancel (cmd->details.history.ho);
-        cmd->details.history.ho = NULL;
-      }
-      break;
-
-    default:
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Shutdown: unknown instruction %d at %u (%s)\n",
-                  cmd->oc,
-                  i,
-                  cmd->label);
-      break;
-    }
-  }
+  cleanup_state (is);
   if (NULL != is->task)
   {
     GNUNET_SCHEDULER_cancel (is->task);
     is->task = NULL;
   }
   GNUNET_free (is);
+  for (unsigned int i=0;i<ninstances;i++)
+    GNUNET_free (instances[i]);
   GNUNET_free_non_null (instances);
   if (NULL != exchange)
   {
@@ -2429,16 +2443,23 @@ main (int argc,
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONFIGURATION_load (cfg,
                                             "test_merchant_api.conf"));
-  GNUNET_break (GNUNET_CONFIGURATION_get_value_string (cfg,
-                                                       "merchant",
-                                                       "INSTANCES",
-                                                       &_instances));
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                        "merchant",
+                                                        "INSTANCES",
+                                                        &_instances));
+  fprintf (stderr,
+           "Found instances `%s'\n",
+           _instances);
   GNUNET_break (NULL != (token = strtok (_instances, " ")));
-  GNUNET_array_append (instances, ninstances, token);
-
+  GNUNET_array_append (instances,
+                       ninstances,
+                       GNUNET_strdup (token));
   while (NULL != (token = strtok (NULL, " ")))
-    GNUNET_array_append(instances, ninstances, token);
-
+    GNUNET_array_append (instances,
+                         ninstances,
+                         GNUNET_strdup (token));
+  GNUNET_free (_instances);
   instance = instances[instance_idx];
   db = TALER_MERCHANTDB_plugin_load (cfg);
   if (NULL == db)
diff --git a/src/merchant-tools/Makefile.am b/src/merchant-tools/Makefile.am
index 2adee91..fb950e1 100644
--- a/src/merchant-tools/Makefile.am
+++ b/src/merchant-tools/Makefile.am
@@ -31,4 +31,3 @@ taler_merchant_generate_payments_LDADD = \
   -lgnunetutil \
   -ljansson
 
-SUBDIRS = mitm
diff --git a/src/merchant-tools/mitm/Makefile.in 
b/src/merchant-tools/mitm/Makefile.in
deleted file mode 100644
index 4a9f33a..0000000
--- a/src/merchant-tools/mitm/Makefile.in
+++ /dev/null
@@ -1,21 +0,0 @@
-
-.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
deleted file mode 100644
index 662cbe3..0000000
--- a/src/merchant-tools/mitm/README
+++ /dev/null
@@ -1,25 +0,0 @@
-
-=== 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
deleted file mode 100644
index 3fb4cfb..0000000
--- a/src/merchant-tools/mitm/merchant-mitm.wsgi.in
+++ /dev/null
@@ -1,21 +0,0 @@
-
-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
deleted file mode 100644
index f5eedea..0000000
--- a/src/merchant-tools/mitm/setup.py
+++ /dev/null
@@ -1,11 +0,0 @@
-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
deleted file mode 100644
index 39a7275..0000000
--- a/src/merchant-tools/mitm/taler-merchant-mitm.in
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/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/src/merchant-tools/mitm/talermerchantmitm/__init__.py 
b/src/merchant-tools/mitm/talermerchantmitm/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/src/merchant-tools/mitm/talermerchantmitm/mitm.py 
b/src/merchant-tools/mitm/talermerchantmitm/mitm.py
deleted file mode 100644
index c998a1c..0000000
--- a/src/merchant-tools/mitm/talermerchantmitm/mitm.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#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-generate-payments.c 
b/src/merchant-tools/taler-merchant-generate-payments.c
index 9a4c3c0..5faa55a 100644
--- a/src/merchant-tools/taler-merchant-generate-payments.c
+++ b/src/merchant-tools/taler-merchant-generate-payments.c
@@ -283,7 +283,7 @@ struct Command
       /**
        * String describing the amount to add to the reserve.
        */
-      const char *amount;
+      char *amount;
 
       /**
        * Sender's bank account details (JSON).
@@ -377,7 +377,7 @@ struct Command
       /**
        * Amount to pay (from the coin, including fee).
        */
-      const char *amount_with_fee;
+      char *amount_with_fee;
 
       /**
        * Amount to pay (from the coin, excluding fee).  The sum of the
@@ -386,7 +386,7 @@ struct Command
        * the @e amount_with_fee must be larger than the @e
        * total_amount.
        */
-      const char *amount_without_fee;
+      char *amount_without_fee;
 
       /**
        * Deposit handle while operation is running.
@@ -405,12 +405,11 @@ struct Command
 
     } pay;
 
-
-
   } details;
 
 };
 
+
 /**
  * Function run when the test times out.
  *
@@ -423,6 +422,7 @@ do_timeout (void *cls)
   GNUNET_SCHEDULER_shutdown ();
 }
 
+
 /**
  * The generator failed, return with an error code.
  *
@@ -439,6 +439,7 @@ fail (struct InterpreterState *is)
   GNUNET_SCHEDULER_shutdown ();
 }
 
+
 /**
  * Run the main interpreter loop that performs exchange operations.
  *
@@ -447,6 +448,7 @@ fail (struct InterpreterState *is)
 static void
 interpreter_run (void *cls);
 
+
 /**
  * Run the next command with the interpreter.
  *
@@ -460,6 +462,7 @@ next_command (struct InterpreterState *is)
                                        is);
 }
 
+
 /**
  * Callback that works PUT /proposal's output.
  *
@@ -510,6 +513,7 @@ proposal_cb (void *cls,
   next_command (is);
 }
 
+
 /**
  * Function called with the result of a /pay operation.
  *
@@ -583,10 +587,10 @@ pay_cb (void *cls,
     }
 
   }
-
   next_command (is);
 }
 
+
 /**
  * Function called upon completion of our /admin/add/incoming request.
  *
@@ -618,6 +622,7 @@ add_incoming_cb (void *cls,
   next_command (is);
 }
 
+
 /**
  * Find a command by label.
  *
@@ -629,7 +634,6 @@ static const struct Command *
 find_command (const struct InterpreterState *is,
               const char *label)
 {
-  unsigned int i;
   const struct Command *cmd;
 
   if (NULL == label)
@@ -638,7 +642,7 @@ find_command (const struct InterpreterState *is,
                 "Attempt to lookup command for empty label\n");
     return 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++)
     if ( (NULL != cmd->label) &&
          (0 == strcmp (cmd->label,
                        label)) )
@@ -649,6 +653,7 @@ find_command (const struct InterpreterState *is,
   return NULL;
 }
 
+
 /**
  * Function called upon completion of our /reserve/withdraw request.
  *
@@ -704,6 +709,7 @@ reserve_withdraw_cb (void *cls,
   next_command (is);
 }
 
+
 /**
  * Find denomination key matching the given amount.
  *
@@ -715,13 +721,12 @@ static const struct TALER_EXCHANGE_DenomPublicKey *
 find_pk (const struct TALER_EXCHANGE_Keys *keys,
          const struct TALER_Amount *amount)
 {
-  unsigned int i;
   struct GNUNET_TIME_Absolute now;
   struct TALER_EXCHANGE_DenomPublicKey *pk;
   char *str;
 
   now = GNUNET_TIME_absolute_get ();
-  for (i=0;i<keys->num_denom_keys;i++)
+  for (unsigned int i=0;i<keys->num_denom_keys;i++)
   {
     pk = &keys->denom_keys[i];
     if ( (0 == TALER_amount_cmp (amount,
@@ -732,7 +737,7 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys,
   }
   /* do 2nd pass to check if expiration times are to blame for failure */
   str = TALER_amount_to_string (amount);
-  for (i=0;i<keys->num_denom_keys;i++)
+  for (unsigned int i=0;i<keys->num_denom_keys;i++)
   {
     pk = &keys->denom_keys[i];
     if ( (0 == TALER_amount_cmp (amount,
@@ -757,6 +762,7 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys,
   return NULL;
 }
 
+
 /**
  * Allocates and return a string representing a order.
  * In this process, this function gives the order those
@@ -766,7 +772,7 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys,
  * @param max_fee merchant's allowed max_fee
  * @param amount total amount for this order
  */
-json_t *
+static json_t *
 make_order (char *maxfee,
             char *total)
 {
@@ -784,7 +790,7 @@ make_order (char *maxfee,
   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}]}",
+  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)/",
@@ -794,10 +800,137 @@ make_order (char *maxfee,
                    "summary", "payments generator..",
                    "products", "description", "ice cream");
 
-   GNUNET_assert (NULL != ret);
-   return ret;
+  GNUNET_assert (NULL != ret);
+  return ret;
+}
+
+
+/**
+ * Free amount stringsin interpreter state.
+ *
+ * @param is state to reset
+ */
+static void
+free_interpreter_amounts (struct InterpreterState *is)
+{
+  struct Command *cmd;
+
+  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:
+      GNUNET_free (cmd->details.pay.amount_with_fee);
+      GNUNET_free (cmd->details.pay.amount_without_fee);
+      break;
+    case OC_PROPOSAL:
+      GNUNET_free (cmd->details.proposal.max_fee);
+      GNUNET_free (cmd->details.proposal.amount);
+      break;
+    case OC_WITHDRAW_SIGN:
+      GNUNET_free (cmd->details.reserve_withdraw.amount);
+      break;
+    case OC_ADMIN_ADD_INCOMING:
+      GNUNET_free (cmd->details.admin_add_incoming.amount);
+      break;
+    default:
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Shutdown: unknown instruction %d at %u (%s)\n",
+                  cmd->oc,
+                  i,
+                  cmd->label);
+      break;
+    }
+}
+
+
+/**
+ * Reset the interpreter state.
+ *
+ * @param is state to reset
+ */
+static void
+reset_interpreter (struct InterpreterState *is)
+{
+  struct Command *cmd;
+
+  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)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_MERCHANT_pay_cancel (cmd->details.pay.ph);
+        cmd->details.pay.ph = NULL;
+      }
+      break;
+
+    case OC_PROPOSAL:
+      if (NULL != cmd->details.proposal.po)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
+        cmd->details.proposal.po = NULL;
+      }
+      if (NULL != cmd->details.proposal.contract_terms)
+      {
+        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)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_EXCHANGE_reserve_withdraw_cancel 
(cmd->details.reserve_withdraw.wsh);
+        cmd->details.reserve_withdraw.wsh = NULL;
+      }
+      if (NULL != cmd->details.reserve_withdraw.sig.rsa_signature)
+      {
+        GNUNET_CRYPTO_rsa_signature_free 
(cmd->details.reserve_withdraw.sig.rsa_signature);
+        cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
+      }
+      break;
+
+    case OC_ADMIN_ADD_INCOMING:
+      if (NULL != cmd->details.admin_add_incoming.aih)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Command %u (%s) did not complete\n",
+                    i,
+                    cmd->label);
+        TALER_EXCHANGE_admin_add_incoming_cancel 
(cmd->details.admin_add_incoming.aih);
+        cmd->details.admin_add_incoming.aih = NULL;
+      }
+      break;
+    default:
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Shutdown: unknown instruction %d at %u (%s)\n",
+                  cmd->oc,
+                  i,
+                  cmd->label);
+      break;
+    }
 }
 
+
 /**
  * Run the main interpreter loop that performs exchange operations.
  *
@@ -841,8 +974,8 @@ interpreter_run (void *cls)
 
       if (j < times)
       {
+        reset_interpreter (is);
         is->ip = 0;
-
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                     "Rewinding the interpreter.\n");
 
@@ -908,67 +1041,66 @@ interpreter_run (void *cls)
         }
 
         {
-        const struct Command *coin_ref;
-       memset (&pc, 0, sizeof (pc));
-       coin_ref = find_command (is,
-                                cmd->details.pay.coin_ref);
-       GNUNET_assert (NULL != ref);
-       switch (coin_ref->oc)
-       {
-       case OC_WITHDRAW_SIGN:
-         pc.coin_priv = coin_ref->details.reserve_withdraw.coin_priv;
-         pc.denom_pub = coin_ref->details.reserve_withdraw.pk->key;
-         pc.denom_sig = coin_ref->details.reserve_withdraw.sig;
+          const struct Command *coin_ref;
+          memset (&pc, 0, sizeof (pc));
+          coin_ref = find_command (is,
+                                   cmd->details.pay.coin_ref);
+          GNUNET_assert (NULL != ref);
+          switch (coin_ref->oc)
+          {
+          case OC_WITHDRAW_SIGN:
+            pc.coin_priv = coin_ref->details.reserve_withdraw.coin_priv;
+            pc.denom_pub = coin_ref->details.reserve_withdraw.pk->key;
+            pc.denom_sig = coin_ref->details.reserve_withdraw.sig;
             pc.denom_value = coin_ref->details.reserve_withdraw.pk->value;
-         break;
-       default:
-         GNUNET_assert (0);
-       }
-
-       if (GNUNET_OK !=
-           TALER_string_to_amount (cmd->details.pay.amount_without_fee,
-                                   &pc.amount_without_fee))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     "Failed to parse amount `%s' at %u\n",
-                     cmd->details.pay.amount_without_fee,
-                     is->ip);
-         fail (is);
-         return;
-       }
-
-       if (GNUNET_OK !=
-           TALER_string_to_amount (cmd->details.pay.amount_with_fee,
-                                   &pc.amount_with_fee))
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     "Failed to parse amount `%s' at %u\n",
-                     cmd->details.pay.amount_with_fee,
-                     is->ip);
-         fail (is);
-         return;
-       }
-        }
+            break;
+          default:
+            GNUNET_assert (0);
+          }
+
+          if (GNUNET_OK !=
+              TALER_string_to_amount (cmd->details.pay.amount_without_fee,
+                                      &pc.amount_without_fee))
+          {
+            GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                        "Failed to parse amount `%s' at %u\n",
+                        cmd->details.pay.amount_without_fee,
+                        is->ip);
+            fail (is);
+            return;
+          }
 
+          if (GNUNET_OK !=
+              TALER_string_to_amount (cmd->details.pay.amount_with_fee,
+                                      &pc.amount_with_fee))
+          {
+            GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                        "Failed to parse amount `%s' at %u\n",
+                        cmd->details.pay.amount_with_fee,
+                        is->ip);
+            fail (is);
+            return;
+          }
+        }
         cmd->details.pay.ph
-       = TALER_MERCHANT_pay_wallet (ctx,
-                                    merchant_uri,
-                                     instance,
-                                    &ref->details.proposal.hash,
-                                    &total_amount,
-                                    &max_fee,
-                                    &merchant_pub,
-                                     &merchant_sig,
-                                    timestamp,
-                                    refund_deadline,
-                                    pay_deadline,
-                                    &h_wire,
-                                    exchange_uri,
-                                     order_id,
-                                    1 /* num_coins */,
-                                    &pc /* coins */,
-                                    &pay_cb,
-                                    is);
+          = TALER_MERCHANT_pay_wallet (ctx,
+                                       merchant_uri,
+                                       instance,
+                                       &ref->details.proposal.hash,
+                                       &total_amount,
+                                       &max_fee,
+                                       &merchant_pub,
+                                       &merchant_sig,
+                                       timestamp,
+                                       refund_deadline,
+                                       pay_deadline,
+                                       &h_wire,
+                                       exchange_uri,
+                                       order_id,
+                                       1 /* num_coins */,
+                                       &pc /* coins */,
+                                       &pay_cb,
+                                       is);
       }
       if (NULL == cmd->details.pay.ph)
       {
@@ -977,8 +1109,6 @@ interpreter_run (void *cls)
         return;
       }
       return;
-
-
     case OC_PROPOSAL:
       {
         json_t *order;
@@ -1003,8 +1133,9 @@ interpreter_run (void *cls)
                                                           instance)));
 
 
-        GNUNET_assert (-1 != json_object_update (order, merchant_obj));
-
+        GNUNET_assert (-1 != json_object_update (order,
+                                                 merchant_obj));
+        json_decref (merchant_obj);
         cmd->details.proposal.po
           = TALER_MERCHANT_order_put (ctx,
                                       merchant_uri,
@@ -1068,7 +1199,9 @@ interpreter_run (void *cls)
         fail (is);
         return;
       }
-      json_object_set (sender_details, "bank_uri", json_string (bank_uri));
+      json_object_set_new (sender_details,
+                           "bank_uri",
+                           json_string (bank_uri));
 
       transfer_details = json_loads 
(cmd->details.admin_add_incoming.transfer_details,
                                      JSON_REJECT_DUPLICATES,
@@ -1174,6 +1307,7 @@ interpreter_run (void *cls)
   }
 }
 
+
 /**
  * Functions of this type are called to provide the retrieved signing and
  * denomination keys of the exchange.  No TALER_EXCHANGE_*() functions should
@@ -1227,6 +1361,7 @@ sighandler_child_death ()
   errno = old_errno;           /* restore errno */
 }
 
+
 /**
  * Function run when the test terminates (good or bad).
  * Cleans up our state.
@@ -1237,7 +1372,6 @@ static void
 do_shutdown (void *cls)
 {
   struct InterpreterState *is = cls;
-  struct Command *cmd;
 
   if (NULL != timeout_task)
   {
@@ -1245,86 +1379,14 @@ do_shutdown (void *cls)
     timeout_task = NULL;
   }
 
-  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)
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Command %u (%s) did not complete\n",
-                      i,
-                      cmd->label);
-          TALER_MERCHANT_pay_cancel (cmd->details.pay.ph);
-          cmd->details.pay.ph = NULL;
-        }
-        break;
-
-      case OC_PROPOSAL:
-        if (NULL != cmd->details.proposal.po)
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Command %u (%s) did not complete\n",
-                      i,
-                      cmd->label);
-          TALER_MERCHANT_proposal_cancel (cmd->details.proposal.po);
-          cmd->details.proposal.po = NULL;
-        }
-        if (NULL != cmd->details.proposal.contract_terms)
-        {
-          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)
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Command %u (%s) did not complete\n",
-                      i,
-                      cmd->label);
-          TALER_EXCHANGE_reserve_withdraw_cancel 
(cmd->details.reserve_withdraw.wsh);
-          cmd->details.reserve_withdraw.wsh = NULL;
-        }
-        if (NULL != cmd->details.reserve_withdraw.sig.rsa_signature)
-        {
-          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)
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Command %u (%s) did not complete\n",
-                      i,
-                      cmd->label);
-          TALER_EXCHANGE_admin_add_incoming_cancel 
(cmd->details.admin_add_incoming.aih);
-          cmd->details.admin_add_incoming.aih = NULL;
-        }
-        break;
-
-      default:
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "Shutdown: unknown instruction %d at %u (%s)\n",
-                    cmd->oc,
-                    i,
-                    cmd->label);
-        break;
-    }
-
+  reset_interpreter (is);
   if (NULL != is->task)
   {
     GNUNET_SCHEDULER_cancel (is->task);
     is->task = NULL;
   }
+  free_interpreter_amounts (is);
+  GNUNET_free (is->commands);
   GNUNET_free (is);
   if (NULL != exchange)
   {
@@ -1343,6 +1405,7 @@ do_shutdown (void *cls)
   }
 }
 
+
 /**
  * Take currency and the part after ":" in the
  * "CURRENCY:XX.YY" format, and return a string
@@ -1352,9 +1415,8 @@ do_shutdown (void *cls)
  * @param rpart float numbers after the ":", in string form
  * @return pointer to allocated and concatenated "CURRENCY:XX.YY"
  * formatted string.
- *
  */
-char *
+static char *
 concat_amount (char *currency, char *rpart)
 {
   char *str;
@@ -1366,6 +1428,128 @@ concat_amount (char *currency, char *rpart)
 
 
 /**
+ * Actually runs the test.
+ */
+static void
+run_test ()
+{
+  struct InterpreterState *is;
+  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 = "{ \"type\":\"test\", 
\"account_number\":62, \"uuid\":1 }",
+      .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
+      .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 = "{ \"type\":\"test\", 
\"account_number\":62, \"uuid\":1 }",
+      .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
+      .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 = "{ \"type\":\"test\", 
\"account_number\":62, \"uuid\":1 }",
+      .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
+      .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 = 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 = 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 = concat_amount (currency, "5") },
+
+    /* Create proposal */
+    { .oc = OC_PROPOSAL,
+      .label = "create-proposal-1",
+      .expected_response_code = MHD_HTTP_OK,
+      .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.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.max_fee = concat_amount (currency, "0.5"),
+      .details.proposal.amount = concat_amount (currency, "5.0") },
+
+    { .oc = OC_PAY,
+      .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 = concat_amount (currency, "5"),
+      .details.pay.amount_without_fee = concat_amount (currency, "4.99") },
+
+    { .oc = OC_PAY,
+      .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 = concat_amount (currency, "5"),
+      .details.pay.amount_without_fee = concat_amount (currency, "4.99") },
+
+    { .oc = OC_PAY,
+      .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 = 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 = 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,
+                                     TALER_EXCHANGE_OPTION_END);
+  GNUNET_assert (NULL != exchange);
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+                                 is);
+}
+
+
+/**
  * Main function that will be run by the scheduler.
  *
  * @param cls closure
@@ -1380,7 +1564,6 @@ run (void *cls,
      const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *config)
 {
-  struct InterpreterState *is;
   unsigned int cnt;
   char *wget_cmd;
 
@@ -1502,8 +1685,7 @@ run (void *cls,
     fprintf (stderr, "\n");
   }
 
-
-  if (!remote_merchant)
+  if (! remote_merchant)
   {
     merchantd = GNUNET_OS_start_process (GNUNET_NO,
                                          GNUNET_OS_INHERIT_STD_ALL,
@@ -1556,125 +1738,11 @@ run (void *cls,
     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 = "{ \"type\":\"test\", 
\"account_number\":62, \"uuid\":1 }",
-      .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
-      .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 = "{ \"type\":\"test\", 
\"account_number\":62, \"uuid\":1 }",
-      .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
-      .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 = "{ \"type\":\"test\", 
\"account_number\":62, \"uuid\":1 }",
-      .details.admin_add_incoming.transfer_details = "{ \"uuid\": 1}",
-      .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 = 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 = 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 = concat_amount (currency, "5") },
-
-    /* Create proposal */
-    { .oc = OC_PROPOSAL,
-      .label = "create-proposal-1",
-      .expected_response_code = MHD_HTTP_OK,
-      .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.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.max_fee = concat_amount (currency, "0.5"),
-      .details.proposal.amount = concat_amount (currency, "5.0") },
-
-    { .oc = OC_PAY,
-      .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 = concat_amount (currency, "5"),
-      .details.pay.amount_without_fee = concat_amount (currency, "4.99") },
-
-    { .oc = OC_PAY,
-      .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 = concat_amount (currency, "5"),
-      .details.pay.amount_without_fee = concat_amount (currency, "4.99") },
-
-    { .oc = OC_PAY,
-      .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 = 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 = 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,
-                                     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);
+  run_test ();
 }
 
 

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



reply via email to

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