summaryrefslogtreecommitdiff
path: root/src/exchange-lib
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-01-11 21:27:34 +0100
committerChristian Grothoff <christian@grothoff.org>2019-01-11 21:43:15 +0100
commit54fc83ee6b910d482948c6ec8185df7aab1b0cb1 (patch)
tree10c04cad1392659a9ccef469271f866e393ebb48 /src/exchange-lib
parent57ab9f9fdba607fcc3817adf58f37c5390f8d220 (diff)
downloadexchange-54fc83ee6b910d482948c6ec8185df7aab1b0cb1.tar.gz
exchange-54fc83ee6b910d482948c6ec8185df7aab1b0cb1.tar.bz2
exchange-54fc83ee6b910d482948c6ec8185df7aab1b0cb1.zip
fix cyclic dependency by combining exchange-lib and auditor-lib directories
Diffstat (limited to 'src/exchange-lib')
-rw-r--r--src/exchange-lib/Makefile.am181
-rw-r--r--src/exchange-lib/afl-generate.sh34
-rw-r--r--src/exchange-lib/backoff.h38
-rw-r--r--src/exchange-lib/baseline/admin_add_incoming.req7
-rw-r--r--src/exchange-lib/baseline/deposit.req8
-rw-r--r--src/exchange-lib/baseline/keys.req7
-rw-r--r--src/exchange-lib/baseline/refresh_link.req5
-rw-r--r--src/exchange-lib/baseline/refresh_melt.req8
-rw-r--r--src/exchange-lib/baseline/refresh_reveal.req7
-rw-r--r--src/exchange-lib/baseline/reserve_status.req4
-rw-r--r--src/exchange-lib/baseline/reserve_withdraw.req7
-rw-r--r--src/exchange-lib/baseline/wire.req5
-rw-r--r--src/exchange-lib/baseline/wire_sepa.req5
-rw-r--r--src/exchange-lib/baseline/wire_test.req5
-rw-r--r--src/exchange-lib/curl_defaults.c75
-rw-r--r--src/exchange-lib/curl_defaults.h41
-rw-r--r--src/exchange-lib/exchange_api_common.c353
-rw-r--r--src/exchange-lib/exchange_api_deposit.c597
-rw-r--r--src/exchange-lib/exchange_api_handle.c1779
-rw-r--r--src/exchange-lib/exchange_api_handle.h103
-rw-r--r--src/exchange-lib/exchange_api_payback.c374
-rw-r--r--src/exchange-lib/exchange_api_refresh.c1678
-rw-r--r--src/exchange-lib/exchange_api_refresh_link.c444
-rw-r--r--src/exchange-lib/exchange_api_refund.c416
-rw-r--r--src/exchange-lib/exchange_api_reserve.c1203
-rw-r--r--src/exchange-lib/exchange_api_track_transaction.c367
-rw-r--r--src/exchange-lib/exchange_api_track_transfer.c388
-rw-r--r--src/exchange-lib/exchange_api_wire.c442
-rw-r--r--src/exchange-lib/test_exchange_api.conf203
-rw-r--r--src/exchange-lib/test_exchange_api_expire_reserve_now.conf4
-rw-r--r--src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json5
-rw-r--r--src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json4
-rw-r--r--src/exchange-lib/test_exchange_api_home/.config/taler/sepa.json9
-rw-r--r--src/exchange-lib/test_exchange_api_home/.config/taler/test.json8
-rw-r--r--src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json4
-rw-r--r--src/exchange-lib/test_exchange_api_home/.local/share/taler/exchange/offline-keys/master.priv1
-rw-r--r--src/exchange-lib/test_exchange_api_keys_cherry_picking.conf161
-rw-r--r--src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf5
-rw-r--r--src/exchange-lib/test_exchange_api_keys_cherry_picking_extended_2.conf5
-rw-r--r--src/exchange-lib/test_exchange_api_keys_cherry_picking_new.c233
-rw-r--r--src/exchange-lib/test_exchange_api_new.c1001
-rwxr-xr-xsrc/exchange-lib/test_exchange_api_overlapping_keys_bug.c135
-rw-r--r--src/exchange-lib/test_exchange_api_twisted.c399
-rw-r--r--src/exchange-lib/test_exchange_api_twisted.conf169
-rw-r--r--src/exchange-lib/testing_api_cmd_bank_check.c379
-rw-r--r--src/exchange-lib/testing_api_cmd_batch.c208
-rw-r--r--src/exchange-lib/testing_api_cmd_check_keys.c165
-rw-r--r--src/exchange-lib/testing_api_cmd_deposit.c576
-rw-r--r--src/exchange-lib/testing_api_cmd_exec_aggregator.c166
-rw-r--r--src/exchange-lib/testing_api_cmd_exec_auditor-sign.c232
-rw-r--r--src/exchange-lib/testing_api_cmd_exec_keyup.c169
-rw-r--r--src/exchange-lib/testing_api_cmd_exec_wirewatch.c168
-rw-r--r--src/exchange-lib/testing_api_cmd_fakebank_transfer.c756
-rw-r--r--src/exchange-lib/testing_api_cmd_payback.c498
-rw-r--r--src/exchange-lib/testing_api_cmd_refresh.c1317
-rw-r--r--src/exchange-lib/testing_api_cmd_refund.c331
-rw-r--r--src/exchange-lib/testing_api_cmd_serialize_keys.c315
-rw-r--r--src/exchange-lib/testing_api_cmd_signal.c116
-rw-r--r--src/exchange-lib/testing_api_cmd_sleep.c104
-rw-r--r--src/exchange-lib/testing_api_cmd_status.c264
-rw-r--r--src/exchange-lib/testing_api_cmd_track.c810
-rw-r--r--src/exchange-lib/testing_api_cmd_wire.c238
-rw-r--r--src/exchange-lib/testing_api_cmd_withdraw.c511
-rw-r--r--src/exchange-lib/testing_api_helpers.c1050
-rw-r--r--src/exchange-lib/testing_api_loop.c825
-rw-r--r--src/exchange-lib/testing_api_trait_amount.c82
-rw-r--r--src/exchange-lib/testing_api_trait_blinding_key.c80
-rw-r--r--src/exchange-lib/testing_api_trait_cmd.c82
-rw-r--r--src/exchange-lib/testing_api_trait_coin_priv.c78
-rw-r--r--src/exchange-lib/testing_api_trait_denom_pub.c79
-rw-r--r--src/exchange-lib/testing_api_trait_denom_sig.c80
-rw-r--r--src/exchange-lib/testing_api_trait_exchange_pub.c77
-rw-r--r--src/exchange-lib/testing_api_trait_exchange_sig.c77
-rw-r--r--src/exchange-lib/testing_api_trait_fresh_coin.c79
-rw-r--r--src/exchange-lib/testing_api_trait_json.c122
-rw-r--r--src/exchange-lib/testing_api_trait_key_peer.c127
-rw-r--r--src/exchange-lib/testing_api_trait_number.c116
-rw-r--r--src/exchange-lib/testing_api_trait_process.c83
-rw-r--r--src/exchange-lib/testing_api_trait_reserve_priv.c76
-rw-r--r--src/exchange-lib/testing_api_trait_string.c305
-rw-r--r--src/exchange-lib/testing_api_trait_wtid.c76
-rw-r--r--src/exchange-lib/testing_api_traits.c80
82 files changed, 0 insertions, 21824 deletions
diff --git a/src/exchange-lib/Makefile.am b/src/exchange-lib/Makefile.am
deleted file mode 100644
index f7fb55f0b..000000000
--- a/src/exchange-lib/Makefile.am
+++ /dev/null
@@ -1,181 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/bank-lib
-
-if USE_COVERAGE
- AM_CFLAGS = --coverage -O0
- XLIB = -lgcov
-endif
-
-lib_LTLIBRARIES = \
- libtalerexchange.la \
- libtalertesting.la
-
-libtalerexchange_la_LDFLAGS = \
- -version-info 4:0:0 \
- -no-undefined
-libtalerexchange_la_SOURCES = \
- curl_defaults.c \
- exchange_api_common.c \
- exchange_api_handle.c exchange_api_handle.h \
- exchange_api_deposit.c \
- exchange_api_payback.c \
- exchange_api_refresh.c \
- exchange_api_refresh_link.c \
- exchange_api_refund.c \
- exchange_api_reserve.c \
- exchange_api_track_transaction.c \
- exchange_api_track_transfer.c \
- exchange_api_wire.c
-libtalerexchange_la_LIBADD = \
- $(top_builddir)/src/auditor-lib/libtalerauditor.la \
- $(top_builddir)/src/json/libtalerjson.la \
- $(top_builddir)/src/util/libtalerutil.la \
- -lgnunetcurl \
- -lgnunetjson \
- -lgnunetutil \
- -ljansson \
- $(XLIB)
-
-libtalertesting_la_LDFLAGS = \
- -version-info 0:0:0 \
- -no-undefined
-libtalertesting_la_SOURCES = \
- curl_defaults.c \
- testing_api_cmd_exec_aggregator.c \
- testing_api_cmd_exec_wirewatch.c \
- testing_api_cmd_exec_keyup.c \
- testing_api_cmd_exec_auditor-sign.c \
- testing_api_cmd_fakebank_transfer.c \
- testing_api_cmd_withdraw.c \
- testing_api_cmd_wire.c \
- testing_api_cmd_refund.c \
- testing_api_cmd_status.c \
- testing_api_cmd_deposit.c \
- testing_api_cmd_sleep.c \
- testing_api_cmd_refresh.c \
- testing_api_cmd_track.c \
- testing_api_cmd_bank_check.c \
- testing_api_cmd_payback.c \
- testing_api_cmd_signal.c \
- testing_api_cmd_check_keys.c \
- testing_api_cmd_batch.c \
- testing_api_cmd_serialize_keys.c \
- testing_api_helpers.c \
- testing_api_loop.c \
- testing_api_traits.c \
- testing_api_trait_blinding_key.c \
- testing_api_trait_coin_priv.c \
- testing_api_trait_denom_pub.c \
- testing_api_trait_denom_sig.c \
- testing_api_trait_exchange_pub.c \
- testing_api_trait_exchange_sig.c \
- testing_api_trait_json.c \
- testing_api_trait_process.c \
- testing_api_trait_reserve_priv.c \
- testing_api_trait_number.c \
- testing_api_trait_fresh_coin.c \
- testing_api_trait_string.c \
- testing_api_trait_key_peer.c \
- testing_api_trait_wtid.c \
- testing_api_trait_amount.c \
- testing_api_trait_cmd.c
-libtalertesting_la_LIBADD = \
- libtalerexchange.la \
- $(top_builddir)/src/wire/libtalerwire.la \
- $(top_builddir)/src/json/libtalerjson.la \
- $(top_builddir)/src/util/libtalerutil.la \
- $(top_builddir)/src/bank-lib/libtalerbank.la \
- $(top_builddir)/src/bank-lib/libtalerfakebank.la \
- -lgnunetcurl \
- -lgnunetjson \
- -lgnunetutil \
- -ljansson \
- $(XLIB)
-
-if HAVE_LIBCURL
-libtalerexchange_la_LIBADD += -lcurl
-else
-if HAVE_LIBGNURL
-libtalerexchange_la_LIBADD += -lgnurl
-endif
-endif
-
-check_PROGRAMS = \
- test_exchange_api_keys_cherry_picking_new \
- test_exchange_api_overlapping_keys_bug \
- test_exchange_api_new
-
-if HAVE_TWISTER
- check_PROGRAMS += \
- test_exchange_api_twisted
-
-test_exchange_api_twisted_SOURCES = \
- test_exchange_api_twisted.c
-test_exchange_api_twisted_LDADD = \
- $(LIBGCRYPT_LIBS) \
- $(top_builddir)/src/exchange-lib/libtalertesting.la \
- $(top_builddir)/src/bank-lib/libtalerfakebank.la \
- $(top_builddir)/src/bank-lib/libtalerbank.la \
- $(top_builddir)/src/exchange-lib/libtalerexchange.la \
- $(top_builddir)/src/json/libtalerjson.la \
- $(top_builddir)/src/util/libtalerutil.la \
- -ltalertwistertesting \
- -lgnunetjson \
- -lgnunetcurl \
- -lgnunetutil \
- -ljansson
-
-endif
-
-AM_TESTS_ENVIRONMENT=export TALER_PREFIX=$${TALER_PREFIX:-@libdir@};export PATH=$${TALER_PREFIX:-@prefix@}/bin:$$PATH;
-
-TESTS = \
- $(check_PROGRAMS)
-
-test_exchange_api_new_SOURCES = \
- test_exchange_api_new.c
-test_exchange_api_new_LDADD = \
- libtalertesting.la \
- libtalerexchange.la \
- $(LIBGCRYPT_LIBS) \
- $(top_builddir)/src/bank-lib/libtalerfakebank.la \
- $(top_builddir)/src/bank-lib/libtalerbank.la \
- $(top_builddir)/src/json/libtalerjson.la \
- $(top_builddir)/src/util/libtalerutil.la \
- -lgnunetcurl \
- -lgnunetutil \
- -ljansson
-
-test_exchange_api_overlapping_keys_bug_SOURCES = \
- test_exchange_api_overlapping_keys_bug.c
-test_exchange_api_overlapping_keys_bug_LDADD = \
- libtalertesting.la \
- libtalerexchange.la \
- $(LIBGCRYPT_LIBS) \
- $(top_builddir)/src/json/libtalerjson.la \
- $(top_builddir)/src/util/libtalerutil.la \
- $(top_builddir)/src/bank-lib/libtalerbank.la \
- -lgnunetcurl \
- -lgnunetutil \
- -ljansson
-
-test_exchange_api_keys_cherry_picking_new_SOURCES = \
- test_exchange_api_keys_cherry_picking_new.c
-test_exchange_api_keys_cherry_picking_new_LDADD = \
- libtalertesting.la \
- libtalerexchange.la \
- $(LIBGCRYPT_LIBS) \
- $(top_builddir)/src/json/libtalerjson.la \
- $(top_builddir)/src/util/libtalerutil.la \
- $(top_builddir)/src/bank-lib/libtalerbank.la \
- -lgnunetcurl \
- -lgnunetutil \
- -ljansson
-
-EXTRA_DIST = \
- test_exchange_api_home/.local/share/taler/exchange/offline-keys/master.priv \
- test_exchange_api_home/.config/taler/test.json \
- test_exchange_api_home/.config/taler/sepa.json \
- test_exchange_api.conf \
- test_exchange_api_keys_cherry_picking.conf \
- test_exchange_api_keys_cherry_picking_extended.conf
diff --git a/src/exchange-lib/afl-generate.sh b/src/exchange-lib/afl-generate.sh
deleted file mode 100644
index b0afcab35..000000000
--- a/src/exchange-lib/afl-generate.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/sh
-#
-# This file is part of TALER
-# Copyright (C) 2015 GNUnet e.V.
-#
-# 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
-# Foundation; either version 3, or (at your option) any later version.
-#
-# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License along with
-# TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
-#
-#
-# This will generate testcases in a directory 'afl-tests', which can then
-# be moved into src/exchange/afl-tests/ to be run during exchange-testing.
-#
-# This script uses American Fuzzy Loop (AFL) to fuzz the exchange to
-# automatically create tests with good coverage. You must install
-# AFL and set AFL_HOME to the directory where AFL is installed
-# before running. Also, a directory "baseline/" should exist with
-# templates for inputs for AFL to fuzz. These can be generated
-# by running wireshark on loopback while running 'make check' in
-# this directory. Save each HTTP request to a new file.
-#
-# Note that you want to switch 'TESTRUN = NO' and pre-init the
-# database before running this, otherwise it will be awfully slow.
-#
-# Must be run from this directory.
-#
-$AFL_HOME/afl-fuzz -i baseline/ -m 250 -o afl-tests/ -f /tmp/afl-input taler-exchange-httpd -i -f /tmp/afl-input -d test-exchange-home/ -C
diff --git a/src/exchange-lib/backoff.h b/src/exchange-lib/backoff.h
deleted file mode 100644
index 2af41e7c7..000000000
--- a/src/exchange-lib/backoff.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/backoff.h
- * @brief backoff computation for the exchange lib
- * @author Florian Dold
- */
-
-
-#ifndef _TALER_BACKOFF_H
-#define _TALER_BACKOFF_H
-
-#include "platform.h"
-#include <gnunet/gnunet_time_lib.h>
-
-/**
- * Random exponential backoff used in the exchange lib.
- */
-#define EXCHANGE_LIB_BACKOFF(r) GNUNET_TIME_randomized_backoff ( \
- (r), \
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2));
-
-#endif
diff --git a/src/exchange-lib/baseline/admin_add_incoming.req b/src/exchange-lib/baseline/admin_add_incoming.req
deleted file mode 100644
index 677678b5d..000000000
--- a/src/exchange-lib/baseline/admin_add_incoming.req
+++ /dev/null
@@ -1,7 +0,0 @@
-POST /admin/add/incoming HTTP/1.1
-Host: localhost:8081
-Accept: */*
-Content-Type: application/json
-Content-Length: 220
-
-{"reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","amount":{"currency":"EUR","value":5,"fraction":10000},"execution_date":"/Date(1442821651)/","wire":{"type":"TEST","bank":"source bank","account":42}} \ No newline at end of file
diff --git a/src/exchange-lib/baseline/deposit.req b/src/exchange-lib/baseline/deposit.req
deleted file mode 100644
index a400796f1..000000000
--- a/src/exchange-lib/baseline/deposit.req
+++ /dev/null
@@ -1,8 +0,0 @@
-POST /deposit HTTP/1.1
-Host: localhost:8081
-Accept: */*
-Content-Type: application/json
-Content-Length: 1658
-Expect: 100-continue
-
-{"ub_sig":"51SPJSSDESGPR80A40M74WV140520818ECG26E9M8S0M6CSH6X334GSN8RW30D9G8MT46CA660W34GSG6MT4AD9K8GT3ECSH6MVK0E2374V38H1M8MR4CDJ66MWK4E1S6MR3GCT28CV32H1Q8N23GCHG70S36C1K8MS3GCSN8RV36D9S710KGD9K6GWKEGJ28GRM4CJ56X1K6DJ18D2KGHA46D13GDA66GVK4GHJ8N13AE9J8RVK6GT184S48E1K6X336G9Q8N142CJ4692M6EA16GRKJD9N6523ADA36X13GG9G70TK6DHN68R36CT18GR4CDSJ6CW3GCT364W46CSR8RV42GJ474SMADSH851K4H9Q8GS42CHS8RV3GCSJ64V46DSN8RSM6HHN6N246D9S6934AH9P6X23JGSH652K0DJ5612KJGA26N242CH35452081918G2J2G0","timestamp":"/Date(1442821652)/","f":{"currency":"EUR","value":5,"fraction":0},"wire":{"type":"TEST","bank":"dest bank","account":42},"coin_pub":"JXWK4NS0H2W4V4BETQ90CCEDADP6QQ3MV3YZ7RV2KXEM8PWXE8Q0","H_wire":"YQED9FDYPKK2QQYB3FS19Y15ZMKBAXJP2C73CXASAF1KM6ZYY723TEJ3HBR6D864A7X5W58G92QJ0A9PFMZNB81ZP9NJAQQCCABM4RG","h_contract_terms":"1CMEEFQ5S4QJGGAMVYFV07XQRHQA311CR2MTRNC5M9KZV6ETDV1SY00WJFEV2CG9BXQTEQPZAF8A54C2HX32TZCN20VBGPFPS2Z16B0","merchant_pub":"C36TEXQXFW00170C2EJ66ZR0000CX9VPZNZG00109NX020000000","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","refund_deadline":"/Date(0)/","coin_sig":"X16E0DP8C2BJNVNX09G24FFC5GA4W7RN2YXZP9WJTAN9BY6B4GMA39QNYR51XNNEZ3H1J7TP0K9G55JZ8V7WS7CZMD7E64HWYBFWM00"}
diff --git a/src/exchange-lib/baseline/keys.req b/src/exchange-lib/baseline/keys.req
deleted file mode 100644
index a9503a864..000000000
--- a/src/exchange-lib/baseline/keys.req
+++ /dev/null
@@ -1,7 +0,0 @@
-GET /keys HTTP/1.1
-User-Agent: Wget/1.16.3 (linux-gnu)
-Accept: */*
-Accept-Encoding: identity
-Host: 127.0.0.1:8081
-Connection: Keep-Alive
-
diff --git a/src/exchange-lib/baseline/refresh_link.req b/src/exchange-lib/baseline/refresh_link.req
deleted file mode 100644
index acf3dff51..000000000
--- a/src/exchange-lib/baseline/refresh_link.req
+++ /dev/null
@@ -1,5 +0,0 @@
-GET /refresh/link?coin_pub=WQHES0X5XK43VBG1Y8FXR2YEJM04HQVMDTCS07MH691XWADG8QCG HTTP/1.1
-Host: localhost:8081
-Accept: */*
-Content-Type: application/json
-
diff --git a/src/exchange-lib/baseline/refresh_melt.req b/src/exchange-lib/baseline/refresh_melt.req
deleted file mode 100644
index 98b5b6389..000000000
--- a/src/exchange-lib/baseline/refresh_melt.req
+++ /dev/null
@@ -1,8 +0,0 @@
-POST /refresh/melt HTTP/1.1
-Host: localhost:8081
-Accept: */*
-Content-Type: application/json
-Content-Length: 34136
-Expect: 100-continue
-
-{"new_denoms":["51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSN8CV38D9G8MT46CSG650M4GHQ6N0M6HHR6X142EA26H13JG9N6RV3AD1P6GV34HHK8S0M6CT28RTMAH9R8H0K2GHN68W46G9K8RT32CT560RKCC268RRKJCSJ70S30CA564SKAD9J84VM8DSG611MAG9R6H2MAG9M8MT4CDHG8CWM8HHH84T3AD1N6X0KEH9P8RRMCCSQ8MT30CSK6MVK0GA48CW30D9J6WTK0CSN650MAD1R70TM4CHG850K2G9H89142DT488S42DT36RVM6DSS6GTK2CSJ84WMCDHP8CV3GDSP6GTM4G9H6N246GHH6GWKGD1N70R34HA689148GHP8RVK2E9M8MRKJCJ28D0KEGT26CS3EH256RVKEDSJ74WKGGT16RSM6H9M6GVKGDS354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSN8CV38D9G8MT46CSG650M4GHQ6N0M6HHR6X142EA26H13JG9N6RV3AD1P6GV34HHK8S0M6CT28RTMAH9R8H0K2GHN68W46G9K8RT32CT560RKCC268RRKJCSJ70S30CA564SKAD9J84VM8DSG611MAG9R6H2MAG9M8MT4CDHG8CWM8HHH84T3AD1N6X0KEH9P8RRMCCSQ8MT30CSK6MVK0GA48CW30D9J6WTK0CSN650MAD1R70TM4CHG850K2G9H89142DT488S42DT36RVM6DSS6GTK2CSJ84WMCDHP8CV3GDSP6GTM4G9H6N246GHH6GWKGD1N70R34HA689148GHP8RVK2E9M8MRKJCJ28D0KEGT26CS3EH256RVKEDSJ74WKGGT16RSM6H9M6GVKGDS354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSN8CV38D9G8MT46CSG650M4GHQ6N0M6HHR6X142EA26H13JG9N6RV3AD1P6GV34HHK8S0M6CT28RTMAH9R8H0K2GHN68W46G9K8RT32CT560RKCC268RRKJCSJ70S30CA564SKAD9J84VM8DSG611MAG9R6H2MAG9M8MT4CDHG8CWM8HHH84T3AD1N6X0KEH9P8RRMCCSQ8MT30CSK6MVK0GA48CW30D9J6WTK0CSN650MAD1R70TM4CHG850K2G9H89142DT488S42DT36RVM6DSS6GTK2CSJ84WMCDHP8CV3GDSP6GTM4G9H6N246GHH6GWKGD1N70R34HA689148GHP8RVK2E9M8MRKJCJ28D0KEGT26CS3EH256RVKEDSJ74WKGGT16RSM6H9M6GVKGDS354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSP8MSM2E1J70T36G9Q750K8D9P692KCHA36MSM4GHS6MWK6DJ564S32DHQ8MT3EHHG84W32G9M88RKGG9J74W3GC1R8H1M6DHQ891K8C9M84TM4CSQ6124CC1G60T30H9Q6CVK2DSH74T4CGT1751MAC1P88RK2GSR8GTKJEA46N0M2DT48CV4CDSP6MSKJE9K64SM6CSS6GVMCD9G6CT3EDT6652K2GJ46RT36GHJ85138H1Q6114AC1Q6H23ACHS8RR46H9M60VKECT688VKGC9S8CW44E1G612K6H1K70VKADSN68T34D1K70R32G9R6934AE246GRKCCJ66N142G9K8CVK8GHS6WS3GH9J74S4ADHM8MSKGD248D330CHK6MVM2DA48GSKCGHH88TKCC9354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSP8MSM2E1J70T36G9Q750K8D9P692KCHA36MSM4GHS6MWK6DJ564S32DHQ8MT3EHHG84W32G9M88RKGG9J74W3GC1R8H1M6DHQ891K8C9M84TM4CSQ6124CC1G60T30H9Q6CVK2DSH74T4CGT1751MAC1P88RK2GSR8GTKJEA46N0M2DT48CV4CDSP6MSKJE9K64SM6CSS6GVMCD9G6CT3EDT6652K2GJ46RT36GHJ85138H1Q6114AC1Q6H23ACHS8RR46H9M60VKECT688VKGC9S8CW44E1G612K6H1K70VKADSN68T34D1K70R32G9R6934AE246GRKCCJ66N142G9K8CVK8GHS6WS3GH9J74S4ADHM8MSKGD248D330CHK6MVM2DA48GSKCGHH88TKCC9354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSP8MSM2E1J70T36G9Q750K8D9P692KCHA36MSM4GHS6MWK6DJ564S32DHQ8MT3EHHG84W32G9M88RKGG9J74W3GC1R8H1M6DHQ891K8C9M84TM4CSQ6124CC1G60T30H9Q6CVK2DSH74T4CGT1751MAC1P88RK2GSR8GTKJEA46N0M2DT48CV4CDSP6MSKJE9K64SM6CSS6GVMCD9G6CT3EDT6652K2GJ46RT36GHJ85138H1Q6114AC1Q6H23ACHS8RR46H9M60VKECT688VKGC9S8CW44E1G612K6H1K70VKADSN68T34D1K70R32G9R6934AE246GRKCCJ66N142G9K8CVK8GHS6WS3GH9J74S4ADHM8MSKGD248D330CHK6MVM2DA48GSKCGHH88TKCC9354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSP8MSM2E1J70T36G9Q750K8D9P692KCHA36MSM4GHS6MWK6DJ564S32DHQ8MT3EHHG84W32G9M88RKGG9J74W3GC1R8H1M6DHQ891K8C9M84TM4CSQ6124CC1G60T30H9Q6CVK2DSH74T4CGT1751MAC1P88RK2GSR8GTKJEA46N0M2DT48CV4CDSP6MSKJE9K64SM6CSS6GVMCD9G6CT3EDT6652K2GJ46RT36GHJ85138H1Q6114AC1Q6H23ACHS8RR46H9M60VKECT688VKGC9S8CW44E1G612K6H1K70VKADSN68T34D1K70R32G9R6934AE246GRKCCJ66N142G9K8CVK8GHS6WS3GH9J74S4ADHM8MSKGD248D330CHK6MVM2DA48GSKCGHH88TKCC9354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSP8MSM2E1J70T36G9Q750K8D9P692KCHA36MSM4GHS6MWK6DJ564S32DHQ8MT3EHHG84W32G9M88RKGG9J74W3GC1R8H1M6DHQ891K8C9M84TM4CSQ6124CC1G60T30H9Q6CVK2DSH74T4CGT1751MAC1P88RK2GSR8GTKJEA46N0M2DT48CV4CDSP6MSKJE9K64SM6CSS6GVMCD9G6CT3EDT6652K2GJ46RT36GHJ85138H1Q6114AC1Q6H23ACHS8RR46H9M60VKECT688VKGC9S8CW44E1G612K6H1K70VKADSN68T34D1K70R32G9R6934AE246GRKCCJ66N142G9K8CVK8GHS6WS3GH9J74S4ADHM8MSKGD248D330CHK6MVM2DA48GSKCGHH88TKCC9354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSP8MSM2E1J70T36G9Q750K8D9P692KCHA36MSM4GHS6MWK6DJ564S32DHQ8MT3EHHG84W32G9M88RKGG9J74W3GC1R8H1M6DHQ891K8C9M84TM4CSQ6124CC1G60T30H9Q6CVK2DSH74T4CGT1751MAC1P88RK2GSR8GTKJEA46N0M2DT48CV4CDSP6MSKJE9K64SM6CSS6GVMCD9G6CT3EDT6652K2GJ46RT36GHJ85138H1Q6114AC1Q6H23ACHS8RR46H9M60VKECT688VKGC9S8CW44E1G612K6H1K70VKADSN68T34D1K70R32G9R6934AE246GRKCCJ66N142G9K8CVK8GHS6WS3GH9J74S4ADHM8MSKGD248D330CHK6MVM2DA48GSKCGHH88TKCC9354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSP8MSM2E1J70T36G9Q750K8D9P692KCHA36MSM4GHS6MWK6DJ564S32DHQ8MT3EHHG84W32G9M88RKGG9J74W3GC1R8H1M6DHQ891K8C9M84TM4CSQ6124CC1G60T30H9Q6CVK2DSH74T4CGT1751MAC1P88RK2GSR8GTKJEA46N0M2DT48CV4CDSP6MSKJE9K64SM6CSS6GVMCD9G6CT3EDT6652K2GJ46RT36GHJ85138H1Q6114AC1Q6H23ACHS8RR46H9M60VKECT688VKGC9S8CW44E1G612K6H1K70VKADSN68T34D1K70R32G9R6934AE246GRKCCJ66N142G9K8CVK8GHS6WS3GH9J74S4ADHM8MSKGD248D330CHK6MVM2DA48GSKCGHH88TKCC9354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GSP8MSM2E1J70T36G9Q750K8D9P692KCHA36MSM4GHS6MWK6DJ564S32DHQ8MT3EHHG84W32G9M88RKGG9J74W3GC1R8H1M6DHQ891K8C9M84TM4CSQ6124CC1G60T30H9Q6CVK2DSH74T4CGT1751MAC1P88RK2GSR8GTKJEA46N0M2DT48CV4CDSP6MSKJE9K64SM6CSS6GVMCD9G6CT3EDT6652K2GJ46RT36GHJ85138H1Q6114AC1Q6H23ACHS8RR46H9M60VKECT688VKGC9S8CW44E1G612K6H1K70VKADSN68T34D1K70R32G9R6934AE246GRKCCJ66N142G9K8CVK8GHS6WS3GH9J74S4ADHM8MSKGD248D330CHK6MVM2DA48GSKCGHH88TKCC9354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30H1J65244GA27533AC248MW34C1P6N136GSR88V3AC1H8N1K8CJ2891M8DA2712K8E1N6GW48DSJ8GW4CDSJ6RT48DJ28GW46DT46H136E216D14AE9Q60VKECT26S2M8EA38MSK2D9S6MTM4CHQ88T3GD9M8D34ACHJ6MR38CT46X1M6CSH74SKCG9Q712K4GHG712M2D9Q8D1K2E9K6X2K0D1H8RVK0E9Q610M2E1K612K4E9M6MTMCH9P60WMCCHR6CWKGE2168SK4GJ26WV3GGT188S38H1P8MW44D1K6S344HHP74W4CG9M8H1K0C1M8933ECA16D13AH9P6RTK4GSM6CRK0GA36RV4ADSM7524CH9G8N0KAEA288WK0GJ16RWK0CSK6N0KJGT674T3GCS354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30H1J65244GA27533AC248MW34C1P6N136GSR88V3AC1H8N1K8CJ2891M8DA2712K8E1N6GW48DSJ8GW4CDSJ6RT48DJ28GW46DT46H136E216D14AE9Q60VKECT26S2M8EA38MSK2D9S6MTM4CHQ88T3GD9M8D34ACHJ6MR38CT46X1M6CSH74SKCG9Q712K4GHG712M2D9Q8D1K2E9K6X2K0D1H8RVK0E9Q610M2E1K612K4E9M6MTMCH9P60WMCCHR6CWKGE2168SK4GJ26WV3GGT188S38H1P8MW44D1K6S344HHP74W4CG9M8H1K0C1M8933ECA16D13AH9P6RTK4GSM6CRK0GA36RV4ADSM7524CH9G8N0KAEA288WK0GJ16RWK0CSK6N0KJGT674T3GCS354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30H1J65244GA27533AC248MW34C1P6N136GSR88V3AC1H8N1K8CJ2891M8DA2712K8E1N6GW48DSJ8GW4CDSJ6RT48DJ28GW46DT46H136E216D14AE9Q60VKECT26S2M8EA38MSK2D9S6MTM4CHQ88T3GD9M8D34ACHJ6MR38CT46X1M6CSH74SKCG9Q712K4GHG712M2D9Q8D1K2E9K6X2K0D1H8RVK0E9Q610M2E1K612K4E9M6MTMCH9P60WMCCHR6CWKGE2168SK4GJ26WV3GGT188S38H1P8MW44D1K6S344HHP74W4CG9M8H1K0C1M8933ECA16D13AH9P6RTK4GSM6CRK0GA36RV4ADSM7524CH9G8N0KAEA288WK0GJ16RWK0CSK6N0KJGT674T3GCS354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30H1J65244GA27533AC248MW34C1P6N136GSR88V3AC1H8N1K8CJ2891M8DA2712K8E1N6GW48DSJ8GW4CDSJ6RT48DJ28GW46DT46H136E216D14AE9Q60VKECT26S2M8EA38MSK2D9S6MTM4CHQ88T3GD9M8D34ACHJ6MR38CT46X1M6CSH74SKCG9Q712K4GHG712M2D9Q8D1K2E9K6X2K0D1H8RVK0E9Q610M2E1K612K4E9M6MTMCH9P60WMCCHR6CWKGE2168SK4GJ26WV3GGT188S38H1P8MW44D1K6S344HHP74W4CG9M8H1K0C1M8933ECA16D13AH9P6RTK4GSM6CRK0GA36RV4ADSM7524CH9G8N0KAEA288WK0GJ16RWK0CSK6N0KJGT674T3GCS354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30H1J65244GA27533AC248MW34C1P6N136GSR88V3AC1H8N1K8CJ2891M8DA2712K8E1N6GW48DSJ8GW4CDSJ6RT48DJ28GW46DT46H136E216D14AE9Q60VKECT26S2M8EA38MSK2D9S6MTM4CHQ88T3GD9M8D34ACHJ6MR38CT46X1M6CSH74SKCG9Q712K4GHG712M2D9Q8D1K2E9K6X2K0D1H8RVK0E9Q610M2E1K612K4E9M6MTMCH9P60WMCCHR6CWKGE2168SK4GJ26WV3GGT188S38H1P8MW44D1K6S344HHP74W4CG9M8H1K0C1M8933ECA16D13AH9P6RTK4GSM6CRK0GA36RV4ADSM7524CH9G8N0KAEA288WK0GJ16RWK0CSK6N0KJGT674T3GCS354520818CMG26C1H60R30C935452081918G2J2G0","51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30H1J65244GA27533AC248MW34C1P6N136GSR88V3AC1H8N1K8CJ2891M8DA2712K8E1N6GW48DSJ8GW4CDSJ6RT48DJ28GW46DT46H136E216D14AE9Q60VKECT26S2M8EA38MSK2D9S6MTM4CHQ88T3GD9M8D34ACHJ6MR38CT46X1M6CSH74SKCG9Q712K4GHG712M2D9Q8D1K2E9K6X2K0D1H8RVK0E9Q610M2E1K612K4E9M6MTMCH9P60WMCCHR6CWKGE2168SK4GJ26WV3GGT188S38H1P8MW44D1K6S344HHP74W4CG9M8H1K0C1M8933ECA16D13AH9P6RTK4GSM6CRK0GA36RV4ADSM7524CH9G8N0KAEA288WK0GJ16RWK0CSK6N0KJGT674T3GCS354520818CMG26C1H60R30C935452081918G2J2G0"],"transfer_pubs":[["J65E5480S6ZVPBA5HV9D4APYXFS527DAJGN5HKZ5EWP89EFSKGK0"],["TYZZG5HSXTYJMA9XD3EMTX2S36V7F4VPR1RHQPKJSTWXJD2KPDAG"],["2MN2X2X7P6GJCN09Z6ZDF2R9W1W3BSYJER7FTBSDDSWMRJ7DG0DG"]],"melt_coins":[{"value_with_fee":{"currency":"EUR","value":4,"fraction":0},"coin_pub":"WQHES0X5XK43VBG1Y8FXR2YEJM04HQVMDTCS07MH691XWADG8QCG","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","denom_sig":"51SPJSSDESGPR80A40M74WV140520818ECG26DJ384R4CCHP8RTK6DJ46X344C9M6S1KEDSQ8923EE9P84SKAH9R84SMAGT670SM4GT66123EDJ46RVK0E1N65336H226H2K8CA38CVKCH9N711K2H1S6X134GHJ6924CGJ68RRMAH9P6MT30H23651KCD1N6X0M8GA58CS34E9K70V32E1S8MTK8GJ270WK0HA368V3GDHM68RK2CHS610MAH1H8RR42CT58H342DSG8D1MCC1J6N0KEHHS6WVM2GHS60WM8G9G6GTMAC258D338HHP8MWM2GSS8MW3GCA270TK6G9G6WRM2GA56RSMCC9R88T3JEA270SK0HJ284R3CC9Q6WVK0DT570TKJE9P68SK0CSG88T3CCHJ60R48C9N611KAD9N6WVMAC9N70T46GH35452081918G2J2G0","confirm_sig":"ZKYCWKVTVQCWMWTAQRNRSKGQP6AC14VF7W525ZQYFZ6J2T1GM7PE7945W3HNW32S0MZBX8K65VQPXH83NMQR2SGTY7DX2T60RKHFP00"}],"secret_encs":[["DCZPFTHF1GZRXFVSYJ4AK1HH4QE46T8F60X1AQ6T6BF1WHBNTJ3FEGH7Y1TH5A6YT10GFYGV12S8V9MB4HEKHRYBBMR7JJ9KB264TNR"],["ANBQS74BACGAWEC0F0654HYGZB3NBSNXVD4KZY4TRP4JMRADJE2Y5BYV513Y37PPMR6V5P200FEAHTZ5TS3R9G9MBYM6Z144N853PQG"],["1X6P2JR301MPR5JYMKPV1HXAFXKH9M09HWVQ4PS6JNK1K6E8ZSMW1C6NS79CPFP443QBVEW9SRWXXJQT91EHFKJ8007AB4S64SPWN3G"]],"coin_evs":[["1XB4A97X8ATPH1KG5NAMJGJY258AGK0MKVJRHN4NGKPRD17DQM0CMTT351FB7T56NTVA9E5VTH9Q12A10C3YVDEYJB4B66EC1NPXNPMNSVTBJ7HGM4DXFB03K1BXK247QK581CGE54286BTK6B5VW0FTS4AZ3NQP43V9E6VV1HTKG1CM5WQJEY14TAC8P2YSV2XH61RG4E84R","JVNGX2AR684RF4VRYFSS69WNMJBDDS9Y4AXFRX5JRFES5QBTMM51SB84BN61S5W0R7PZGK09NQ8QMX7Z90AE0JJH76J7DCM94DKWMV88K966NEA2CNMS50PG6D0K73619K67S9HJ0PQTQH8YD91P4CQQZTRPV7Y2RHEGMBB2G67ZBVVH1S9Q0HYX69Y2B3J2WYFMH3BJESVGE","6MZ6ZDF26MSAZN3VK3QDY62MD3AXZTK8K46A7ZFNBVCR33AE6H3A309F822EKPHT2YTJB6PMSPSJ3ZAE99Z5Q2J8F87X5N723J713A0QR87KYJ2NZ3PFCS5CC8FXJYK6YXZ4ND6FHNJRJZZZZRXE05VP14XW1BZFYZGQQZ8J05FYKY8AYFNCZ50WT7W8M83XS50GTYJGQTNPT","Q0JWR4WRPYT7TCNCV47RJ1FW3HEFQABN9EE27DBMDB4FYAVK8X9KM38HH9KN8QW28RXFXAKT3MGHXPGRWCY9P313CPR5Z2XSR3ZGKFHQHTP1A02SSD0DHH12RCV5TJ7M86WXWT7F00CQ8HV5H90MFEDX6J2X9JNX26NC0PRH0YXHGW7XVWXF00ZEJCGJDEZ1EVXA5BNW3SAEY","B20PSGCM77EVSXEC6T41N1T55KX76B5K3X38VBQ8NSAN2BKNH0W4DQGVZQTBA2588YCRW1TN9G721GP7ZCP9H32BBC9HM3XFTNJ4QBV2FMM7KSG6T0H418EBNBGKZXMTD9ZDVV6A2TEBMXSEKYVK9HCZT8EEQ7E44DWBDHN274N9D4ZDEFCZXNF0MKBM3TYZGHJ5T71T88CE4","F95WT8Y2WRXGK07MY3FMV1Y6PS44CMP59KK8G82EKW3Z0Y6C6QZ2CVC4A6DF9N3E6HW8SQ3CF4FSD1QC2DN5E9DM5G762DW491BAE5RC2A3YPGJTZ3XBFJ3R3NSRDRZMHR6Y755QDRZZEVFTEPN7MZ90SE6KTQS80CHNMTX15NMZPNFJSCQSEJ9RQJKZBH9ZZFMNXT8BXM7K4","1B8GKDJYJYCZ8Y2HCETV6EWA8FRVR0AAD7TRXFXBHNF7G10CZYDFTKBJ8X0J0M7VR1KQV67SF5VMM7VVG5ZQ4F9QEKRV3GSBB4M75CAXSEXSHDT36RJ6A98EKP3EZXT65HX2K788ZE4SVE5N2NJ8Q26P318PK9X69YWB4W7R1F1F9WHZ8WKJ69G5YZ1T9WR1N8CXTJASXW3A8","FV0Y6B21F01D5EH31R80BHG7GKA08C7HN3FYDMGQE6HJ2Y9ZSVJ17HR8Y22WGPN98T08E6XP4PZNMJ3RHAFK8DAVW3AYM5VNPHV3JSB5B64F0H60EMQNA59A2QAFRV3FCHJQATY87SGT9E67HRVE5QDP9HJC7A351WM55VV5MW3T251VVZ8N5V2GVX6MD14MR9ZX9TBS4N30J","K8QSPQTEV9YZC7MC6AT9R8Y0QGG4PT1V45KSSZR2YY9SBA3QEQG7R6YR4RKEKR5DGDM2K4DN9K128TQMMPFWZR8N95F29Q8E2WBD22F5SRFPJ2KJA6SEZ6RMPCHG6C4BJEV7PZAEVTNJDK8T79PJCB5B97D5WQ52TT2DB6Q4S599D61AA54FCVM9R3AB03PDTYZ0PCKBMJ23G","1655VA0GT3ASG2JVEZ93BWE01YDEA70ZW2FD1W3AZTD4B4WK9GYPMM9Y6KXDGDDB2TMDF5CWXNAX0B7E396E1NH3GCK8KFHMGXNPG0CTD2KNW9X3QB4HKK68JM2WGMF05VJ6K4G76R4A10JWPEZTD554TSFYVEM0355C9E5P9W5GFFFYQMTAXG43V8GP7P4BDBD81Q9G87MXG","J3T1MSDB9ZHCCNAYDXEQAMETNSCX5DJYQBCXGREMYAWAQ8AJCY5JV00HHX31DVT7X5S25CEX88707E81X4KNCN7RBRFMFNP8QZHFZHXNS6MN7BD4MGRVQEC50EWH6N6EFY1GA039KYJKX24XMGZXKB27H5R0RKN7YC00EKN99SGKF3YN7DPR8880MG457438G1YJR7BGRCG7J","DX73NQ14FVC978B1HP03MWBD83YT6NVP607WB126RAJPKPB11GSWB7H9W0QJSH9WD4SN9JJE6FDMQZTMJXCN1AKDBKKVPWW9VBEAE0YVCG64S16TXMSF5FTWNXYG7RDTHK03BXDGVXSPZFE7A2F6FPK9WCBBZSMKB8EJFGJK1PKKBHVA1Q2MX91NK32XPF00WFWZCC3N72JY2","PKSMQXMCT9H53FHGKVVPPTTHJ0M5X4SSR0XARN34VV7DX9ZA9N8379NVQKN4E5V6JXAPEVGPREWD720RZCVB90DDHRFW8GG6G434GR1A77SVPG9GKP2DEKBVP3CZ9WDMQD9RFZZ2Z3ZQ34YVD2J1Y4AZ52ADY5FXPB06W9NQ9NH7AQVHTPMSTP181MZM507M777SAPSCR9J8M","1XV578XYBQYYSV9V8ZRACRG3JTN103BZFPF5JXHF8YDCCCJM9XS343JYM8N6Q3J8D0NF2T8TPZKCB32MC1GXWZZRRWQW77JSSYXGA8136DNFYTCKB8EP277KBXAYXBW0ZX7S13J5NDGR7ZJ7QTAAPTEAG9MX6QBT9Z7ZZ1MECV7Z0D7GE7Z6KWASE5T4SW0MFHKVD1EAFNG0P","86PDN3KMT8AW8TVXEBGG3199YSEDMQX91QW82QVZ9TPYCNS3YKK3NCK5J64VKPKGJGQJP8E3RX97NZ4RDQ0PR21QS93MTWXSHKCTK2KTH7TQPKVQSWPGVC8CZDEGD9X484HJKMQG56RP1MZE7AWKK9C5ZK7MSN21GTG1KNF591Q8DVX0TM06BD8VGF6QNC745CFRMRSYHXK7P","KGXXZAECQ6DETR97HRYKFC4A1WAKC3S0FYNHS16J342WMPPP78NHWZXSEPN04XEQY6QNR9ECWZNXY6BZHXWAW2EV42295GBVA4R2J2KAK9EF7MR2789EHY0MVQJME1ADGEPGCQ02WHWT3C173SPDKW1DA5C8HBF847KV00A3F3ZM2HE18N5MFFQXBB014HK0MC4NW6G19AESR","92G786WTFN4BP3Z2RX1Q79ZPHGMPYC21K646XA8AB97V103DSJY0S4Y1FHHSHYQ8WZPWF0W07VY6CDG66438K8E8DWN7CCSB6R8KSC2VNAQBVC1ZD2H9VG33309B6QEKK5PYAGJZN5NG0CJXW9RFGPCNJJZW6KHM4TCMDJVKV9P953Q0TWVM2YZWK37504QJ41MZ4KXN52M30"],["NG0RYVSNPXP4B2NEYCTVC5A0EW5PFFW8V3PH9X5FFQ2VHCETMWDPZ75HBSC8QDBCWZ6EV9SEN1SMEMXABK3YTXBDDXYTN0JNKX1ME9T71JJTZZQ7XA1890DZR3ZAMD0XW8GZENDNAP4R5B80DQYFDEENSB141DZ0HG3A3FZA7JMCSBY0Y0PB2AXNS25Q6CQ5WA7GWCWA09PD2","R70NVRHFT6HCP69K8QQM9HQX0CZQYG09VV2VA7RKCVFDRTNH44XZHRBEJTBW1ASDS7WYA47PBVPB9T77B32ER6V2745Y8B1P22CZ5T70WTE6Y4HSS60CM5SFB6QT1VXTVW9G0DAC3XY2QDX6TKKQA1HX3RB0GPJH47D08KB1Y4EP1SXW851CFNEE373YJHBNYXMSE3MJBCQFP","JGZK4NS2E8D1CTR8ZAR5CHGN7T09Q41P545ZNNB7RMYV0CZ9CQWJWZZWRQZDRDCHV5PQS9G6WZB37CHQMZ7Y207D23FQAPMN6CP30CXYEQ449R3V7B8BYGJ84VYW60201B4343GG75TTTN947VVEYA3BWKRY4M5XCXSPAGW1TTAH9VAE8CBXBKAKJESX8XWS4W5PYBG8793TR","CEVHPNNSWR438ZWEK27YRYBKZXVBT8AM9QP2KXWC59ZSM8Q7J0GZNXZYBES04RB7BJY4D5YCPT3VRT7EPK0576809CG98X5SPTQPSR4TZ0R6DWMXH9893FCTVJX2A4H2EGSGP3Q6H53FD4CSDBMZFZVACXPMW1CR07A1GG7XFXSK1BP1BTGMBQD0818G6BC6SBFTXS1Z68PD8","72BFMSPJ57Q1B88JS6NX8YETQP0GSSRHXM25ZBGNW06YGYJ7FT1D7KVGF4PRKKQK8KN4MGHK5DXRQDTNEJSRZYGAN6DV5QAW9PACT7FQQXG6G4JS7J129VXFQP3DYTV0455Q37H5YPVGMWXZ4GNBQJ86HWWD670XY8JAR4WTYHX8FWJXZW57Q94KK79SD51HBJH1SJ4Q5C04W","2MDED6PYFV264D0SETN9MD4F0SADGVD75J8Y16DTSABNPW09AKE7A5F4QNB2124WDQ0HW4SGHCX26NAG46Q960Y01VYSX0GQHVKESSMEAZ2426GJ8KR0E6KTAXDZY6HZ6DRSPXXGZ07YZT2XF696CP8215HE92RGT7A50H5XXV2FDGFWJXYNCB7QND27ZWYWTK0KTCRYT104Y","267QZPCB0QGC63V9E75Y41J5285Q3FX6KQHM08MAKZ248X9WJK5H6H903C0T02W4G3EA22E0C1MHCWP5VRAEC8D0J0VYW9JNCH9YGPQJ3P941AADABVXG4M2K724C8VCFZQNXYJAMY4Q65WYHW6VYPN9H1K7ZABPAZX82SSSBPYKJZBREJ15MSS50R9HJ6FWW7T9P8ES015PY","7W8HPWAGBVFK0KTWG02RRTWKAE4W0PJH76GH9JWD7H48BS7CVD1T38QBX7HJVC6PJEAJ5NGP7MSJ9D5H1FD2T9Q5X4YQMQ1F80H4G8GRGXFKS863G48HN15D72EZSM9V8M75FXCH3639PHENNV35GA6TWPRS70HEJSBAX9A52DWTB63ZCSZXFGACZEQFGR0EKEE0AZB3HKE2J","JMGGS2DPDKNQKTM593M69Z1R331654KR6N12Q7EZPX20BMHV1P9JZZ8HNN6VHQ76YKWNMW9HR3173C2J66R8EVVWZAR001Z18F9HJ9YBVSM1Y94PJSM57GNVRNN0GH11A3ZRCA4WBKFC64A4RE6KTYMMJKJNHTR9A75QC7JWG5YY9D0J8TM9KXQW8495V702VS0E40121HNHY","REH6B17HSBJGMMPYKG7EA1J4G1D7H95N20P647AWHJKY3VA5BDZKN84FEG0G0FK6TKNN8D0TDFQ41610SK9CBR27SFD16PKEZ7AP97NB9ENPQRQ9PEKR76KB6VFWP666MJBTQJ5R7WGKTTE3ZN5Z2VWY2CPB437746CYBN52G2P2Q7V6SDGXV5HPYJBKXESS1JMVH3EHDC988","MRE9Q877Z18VMFNH1PWNH9N3Z5YE2SDZCVVFBZAA41SSRC2F81D6F9TCZP2AGYAEXWM3977KWJ6SV215ZJ24RAWA94NCKEFQ1CMW8MYJ063EP68NVVPH51SFVYQVHYC45MGNEXK61R9KFK6RWYV5Y6CHMAYZTW5M17WBSHBZ79F4DSWHVVY7774FX3WEEVM8EZ0WMJWY99A1P","2CM59NJVJ68NYX5ZJM2ZX7JK8EW7JXAVE0H2D1ZTX9X6X72P9768WK5GG3ED7MGEYGFQBK5YSSJ0DM68DRPDPTAHQGWTGJ7E79GAW96BXHYV64BQXXEV9YQ0XR84G8VZWQ8Z7T9VX7VQ0HHX1SAS3NGNZAH1H03KPFNAZMNMGV3H4Q3PC96JHGAP5JNDWA1FAFJ410REB33D0","2KEXQVJHACQX7V1XGF8PA6DV0EVAKFNSA037YJ3BP91NNQB60ZBAEFT9DKVW2M19R51B8HGQ2RCBSWBRHD0RFC95TYGJVKNJSCMQPXV7SM6A1JH18DFPWB1AJBS4SSVJXZ9V72TY2P8Q8ZTBMGCYERXCT4QJMASTQM1T22C9AXMMPZ1BHKNB2FBJ3TY9AQP4ZGHRSRBKR75E4","5Q9ZFEFF6C6XPGM78EXAWJF2CKJVJ0SPA113XT7R5JTRW7MKE70TETKK1MBRSTF566AEZB2CBX6CR10J6DPAQ92GC6XYK27A52KQGQHR5W346RGF28WE2PPC8S3XWTGCGVP318AKKTC8GZQ62FRYZVPTVF07HWYHDESQFKYNSDRNV8Q5KPGRQM27SK3CX14RA2K9KZ0NJJ0FE","7ZK7H90WBS080M9TH8XH9DNENKQ78YHYSXWF16VRM76YDKP4RG97DEM1DBX84VXH98M64CJS1GYTDKG4XA8XCNSZ4KQ12GAXCJC168DBR8Q4M29X2Q70WNR7BZDNH0DQJMR154M0C1NH2EHJBKA76PNZT2369PT9Q4961EBCY5FE85EKCX7584GXBMHQF1GRDVCCDVY7TH210","CFSSPFE27VKZHPS7D48AAHE0C2XKXS774CDPFE530P5C4EFZVZEP1PTS3NYB7KBNHNAGMZX8YZJVTNJAB1DE7GCRG43Q2JVS15RGJC4K9PDA0Q2MG4DGRX1CM28HE8CB1XWVW7MCDJHPNE28NWN0CYHDES8GHAZ6Y50NNZRN31FV8C28V0PRNZK4WFAPJ4EGV5NQPHGSZAWNG","9XJB29QY06J1DYBXQRV9F7M3T11JTGSZHX8D0Y80Q07M646VTHNFKNA19CG84BA2DKRE1D5DS3M72QH29S9EZEADW6PCS1FXGCMGZ0RQXT5ASSX7VBQ40NGPYY6PFE6CYV45YYEGPGJ2DCQCNYP2Q9E78SBD53QTQVYZG7W3QE8EASEPSZXP1VVB1TYYHN0B1BZGY2JKGWWPY"],["CSATAT8AQRB91XKHJD1B7MK1DPVPV991WZM4Y2NF0G8SNQSR391KBDGHR0AWGZ8V6EYXKNGTACT9GRBWWAPYTDPWFZ5QPY9GY8Z4YDXRK1QW30YT6JMAYQM2TH36XP81G2X55785ZJWCRXZ9QQDGGMMM8QZTWN9TPW8JXH4XM8A0DPG5354PF3782GVC8J8DXD7KY88KT0FZY","4MG8W9X1M5361HRRG6W9QF13EQDRFWVAQGMWJKEESZ3FBCWP7QQGQBBDT3ZYE3XARBVGJAVFQRQPAYA1PC4CQYRX0CZTS0E4QZB3ACMXG9XJ91VPP7X0ZG08WXWMT02M9V4HCHJ7MJQZ7EWCRJAG7E14BQ465R123P6QFGY770GN0BBNT040S3XPC88CD8X3D8497DE2YA1MT","DCSBAHV955VGACX5WE2N02QZSPQ9N375DCS0W3298N8KF59YHVTS7FYJ1NE011VWF8ET7F6SQZHW1NWJZW3XYWN2ZMWXCRGH80CD6N8YA6EE8Z2N2PW4T65M0DDX4YFXZPG61E7JJGK03VTDW5J8WS2F2R88GNNJMWBQCYBWWTZ34H7J5XAPBBY3AF4M6A8C0RAHPX0FS044W","5CKW4V17Q2XAV54F07X0C2NZCRZ21B9M79JM37F10DZJ3YMY9WPEWSYEDC6DP1QZ2DRRAXDCFG1WZH3C0Z58Y26XGSC28R9Q3ZFSKZHS0F0DC08JWY01W9GPECCN0CP0Q19N7GWX7HAFVR0PR89P0DTBPJ02NKCG14HZK933C6C62AFS8GFWNWN7FJ042YVSH69BAM9FQX4JT","G3J5ZS034N9TKESCEBQJQVXJMYB7HX48QT7QTEZA688019KSSCFVDG2TD963JA9NQF2G80Q3J1853PRB8QD2WFWDSMPP9X4FXKAEH79Q2X8K2KZJ120848KY421H81WAA1AMPZ6APD67RDRBKM0H5GN974TBQ8S5ENFRJSNTJRJEDY57GRHAN8V2R2PCNCY1VWH92EN1MJA4P","BFTC88T9TMD6EQPMBN6M7ZES14AGZMK8CYF0BQ7JAPPAPKXRTW83Q2ZF5270PG9WN0SET02R2HHFEM4J66GDWK2GYCF6GBZWF0GAH9ZC0AHVT3JW2XWDZ2X1DH2WB9Y10A7QB83S3E1S5DQEJXD6AS4J6HCBJBZJPC1EJZP3E5R5ANY1EYZ7P1692WSNABA0KWZS5T05DK51M","HFBFB0NVHM82461FBYT7SKWR1R38QD6MPMTSZXQAAH7CKVSKE21M4KZMWE3EF2C0FFJ6QGZPFWYXM58NANQMHP293WNJD5NYM31ZGV3ZS8SDP9DK1ZVSF5WXW3PEKYCAR3C7J6QZKAT1CVQF86P6M3S7XPVN8EV212SG4ENANH650EF7H5RDBN29PRREWB5JA4PSX9TQR1Y92","1JT0M6407RNBHQFZ0SKEPHQW2ZTZTQ5X7BZ1Q1FBQVR9QBH3EP20CH1KJSP71PC8Z4WFKJ97442BWG991RJC0XE7Y71PW9SXMPX4MG1SVN371ZG3GNCBX3Z9AZAAR9PGHS46AVG1RH71X1WQZ7W9HGQPRYDPCMQBQ7N2PD0AH8EJMT2ASXKPNK09S9H9B0ZTYMB5KK2VB7C72","E5PWK8V063470P271354CCZ3JS5H6GB8GWPDCDB125CVT4YHR3MGTYAFTDJP38F2WSNERY5KNE9VK85N70WC6VZ22WF7MABK2FJZM3179NHBV92FQC19BR21002AZHHE4A171QYFX69NXV3XA90HY27ECQ28YCPZNKEPQXXVCNHVSFJJE8553M68KM81EW45GXEV3797W2KX4","JQGN8RXXYMHG8MD2GSNQ6NQ8QCH8A6WDT0S0WY4ZP5424RGY975300CQC1C575K619FY2JN71RQ62RM6W2TBVZX0Z5B8A2PQ2MTN6W486AHBJKX6ST9HA05EQ9VMJN3PGDSF1GACENFK8CA1EW4KNG185PG6CP7YY1TNX3FZ43H020K8SYTQWMPM6FAZ5N4MA6CQND1ZJ6AC0","NJ5PM2Z4VNYKG6X93KWH0GQZNMBKHYM2FWX0BSNPGJ18Q7R32YC9FPC2Z45MPJ5EZY4E3FD0CD67TB9K4879SQ33SCG4Z9BARNQVWXMK975GRGAB4306D1W7PF1QD1MTVW79DHY3M2VVC01R4T41M3TXYTD1X3JF1PBGC4T63MF9MJS4KZTS03Z84AY6C9WK9RTNHXN7R0VJC","1ERPPXVG2NJ4RHCD8QED1E25R6QCAKKZWRV3EAVS4Y17ZDTXK46TSBJ1MF4HN26K3FHRE3PVBV4DA1RJ36R70BSAHSW7KTEGJNR8M5FBJ7ZDT907X2H0RMPCDANGGT9Q8VWYKBAHQ1T72S0ZAEC079SKV16XWTRX698P3P2TCJQDT7EA0G67N82YFPRE7YVGFKTMYXYC7EH1E","91CHR983Z222JN1695J11YY836RHP6J02SSZ8T5ACZ15X0D1YAW8VTCMECW3CPMCHG2RWTS5C30HSRWTYHAE3J3F61Q5N34ZSBVFPWJMN8WSFTAFEG7WZDWCM1VJZX5KZGXF7RTCS09MHJ0WRMCGC18WSR2SDV64P9HE1WTNCD8KT65JGQ3ZPWAWVJNJS63YNTGDPZ4RHTZ78","8Y2GMEETX3N9XTAB124JYKMHQH29009WJ5KF6V31WWZ99GXWZJHC5C03P3CKMB4R8M7ARQ3XD7AHPJTY2EKKPPF9QXWN7685HDTPT2SBCQ67XHHRA2RJ5E1S4VFP2YB1H0W1D9RE4C6WDT7FNVWXFHXAEQAJRJ577QNJD8G4ZSARSJ2SP6625AW9VQVVRFS0FWMBWJZNHXGWE","33MH8RQ5PXQFB0Q2T0H30VM9G4J0ZQHB3JHH8MWF5K3F3KDBAR20ZG4APHCTF1XRG530W7K2476P7BNFKENP2WXJ4HAW6RS91EQKGYD6PEHRYCVF8JJTMWR32WFVPV5Z2M1FWKNNC5N4CC3MK7S2K1V05PQMZ347KYD45FW7Y4KKJJ89TDPT7SFSQP1A0J00SN3MMTSEGXMVC","HR05CWNNQ5VBAF0WNHP8DZGN3S0DGYJ37EYP8S57MK8KDXQHXTPV2SXNJ2M5SZMS43BR168FJTB1SC9EW9P9YT7DYRBRM7G0VSD86P4QBG42NH06XYCCF7TVN9H9EB5K1G07M2Y3TT4WBAZ2Z350PV67ZANG43054GZA4N08BN2WEDFN94BNFKF45C10C3FFG77D9P3PDMGVG","JS43E6R3YEVTRZGRTS3RF0F9PCW7NBTWB6XEV146AXNTSKEKCDQ8CX76GX6HA06N0RTA699M99FXMD4JX04VY961YXJ18G96Z1AEEJ5BR5A8GYEWSNJSR5Y55ETBCKHBHR6CJ8A3659Y45FNG7H4C1K44WZ520PE4NAQVJ9QS1H2RWQ5ZZ8H8J8WGBDQC6DQYRTQHR0WF2156"]],"link_encs":[["7A1HVQDZ7C2M4K913020KMYGK4K86PM30APZ8AH5ERT5Z83QZPJRTGEFXF0TGYH36R1N36N3VKB5V845FK33ZW3R4G01X6CZNE37XHXE707T0TA4DYGYNX295QSVF5VEPD8QMK1J7ZAGDS27QP9H1QVK3NRBTZVRZ23XAV642CGEFS1ZMPWEDSHWECQ4G6CFK1V0K2118BQYS41R9P05NZ18PY3Z1FWNZH472HTKWT74KC752S0W1C2ASM428009","VN0WT37PVBAEYW3GH2ZGZ6X37R0XATMMGHJ86G953NVD6TE608Z3A6P9PG9XAFAGPQ13GSQ435C8763NR5T28RQHH4JB9N578TW7FHA5Z4Z6MDS6CMFK9A6ZGGT35G28NH6YG55EZR6GCM5E2ZKA8A9TR8Z8C6N4BTEVJCCJRWQ5MG8W4TR5N3YNPA7NAM49TYECT56BHJPCD6DHJ3XQF2XTZQTCECDJWZG4TXK3DEZM7Y55XFJ49C7F1P17MWQJ","88RWAYX9765MBR4KBM2BN9NSQ5KHWFC0AQZ6B0RF617VF5CSJJZBB69XEVDFC12K5D0T06KBE71BHK9E5ZTEWD5FK4Z2JVKD6WV6QBFHQ8Y1ZPP7Y2EYB9XFW7S9NVM27FNX8RKWTAJ45FFYKJPNR7MX5HZZ77B25ZB57Q0NJB1E7ECH4QP5BKZG63CF5M75VA633AJC7A4XWR8JJTTQDZ40KJMXE15X9KPABVZM6HSGF19P3N2SE2VSSWFXF3XH","MBPTJC2E7C7YQMAKCJN8EYBX1Z0CG8Z35G5VW3AZH3PAM6DF32AXKFX06Y9686R1CC1TP5BWX94DMN78RXSZGXFTEKPK3RSEVWQZCBR6BWB7YEEJZTV0C5MGREJE73RP40730074SPPW6CW665XV5TJA5329ZM0XC0KJ3MR9V70TDCE3M9DMB1JXPN3M97A74XG6KNJ57FKDQH4C4NV3Z3MJ276Y9MDAPDF7GM7MW7AQ7T1Y98RJ4H6163WCSN6V","Q2YNH71E69EDZ1NF8PFRS66PJYZ360SPQVQK73422944P34FGDZVJPMF59Y5KVJSB8VTJRPVMBJQX5Q8M8BHEJX1YAHDXAAWBTTBFM12CACZT72CYH6S80TJ8GYGS9ED1HBBWWT8RTZGMD8R4NMBJJRED107EASZJTH4SW32FJ04X62EA7YAMAJFTPCC5E6QJ43F0H592Y3J81NXQS66P6GQXKQMCN5W3FX8ZJ3160V542YVE2FNV3X7WD88FVX3","5H1650VJX95VFVA0G8ZNGWBCACCZ53D6SNJ2S4QVD27X2128KWC4MXRH8B3FK89QXV07NTEAJEXGDZC8BSYW11JZGF7H3D2YVXX8ZEEZBHWESCN7TNSE9AQK5NBV709PNHP9KHE0K7KEJTY2GY08CWAN1G9CQ3ZPF71NEHC7C0C47GYNVHX9PTXAYH2ZKQJSRNNSERC62CFX7NQD5TPF6WFEYC9R1AB3TWEQQF3FKY5EAE04EAEQJWSW0ZFGRCZZ","F5DZP7M59MGX6YJ3M3CEXVSJ0FGD3Q3EVHSQDSDDKSFPJ7ZBN60SYEBB293PDCFZVKC7K4HZ54E3XM7G3GECK2ENZYRCQMS6PS7VM7DYKF7S56KP0N4SE6X69Z6EDA309XPHHPDGRG1593SZ63YN63M815C2JP9M5E7H4FWYWQQNA9C81FQFNH48NVF43G3A54EEM3JV6VKB7X9H3SESC7YRA862NZF42C2FP5MCSACPQBSX0HV2Y6QRZW53BTW2","HJ9AV53HDRMNPEJJPSEPJV98XXVK1D93WT9CQNNY7B0GKY2TTAW55C83EHJQ6SHMRYEWQPBS096ZKRDFHNM5YJF09V0NFEYTTJGSMFCDYKW5GYCZRH3FGZHKEMNN3S98WV5KWDG5PT0S9TCYTDW074WPNMTH9V9KE08E6N8ATBX62PZ2X326TT3N15RG3ZKHQ09360981ANE6MVMTM2J4RXPFMA936KTXAS0EF4FTTGZA1GHS4FNG0JRFBXTNF0D","BXGHTGZ5EWJY0XKATMGECZB8QM74WH1RY4FB4KZP0VQ4STWVBY0NMQ8832YWB04GQ2B50Q5RTD61091HH1R3S2DK6QD7VJYE9BZ4EEQJTDTSSQT86DQEK2QPTXQ8W39WBTAT8PKBT037JM9DCYAC4CRPGTQWBZK3M1Q8BZHRVXYVGGVC5GWG3YQX075EQCSD9Y18N08JKNFHJKVZH6X27ABDHC323HQS30VS15BD65GZ35MH4HBFT7CAHPDZ5C4D","D3EF8ZKVNK6PCTC7KWGDGTSA3804J3N76R186NKQC3YJPW9P9B6CXDN9910S5RNEGST7MSY566PFZY2NP95WZNJTMG8988H3HFVXTXK2TST59AFBNDNTGAK3Y149WVWNDAVZ3G4NM9R75HSWC75BGNDRJ1F6DQ8QACZRAN9E4K6J3NZ3BNG5A2JY48TVXEC3E6TEDMF3E4Q9QSWQXPEHE48TJB5J7Y98WTDDWWV3S186BGM5V06PTGS3V2QRMRW1","YXS4AQF8X7VR35BBA8RBRMCJCSRJ1K2820ERJV75TZ5X3XBB4S5A1EKAGQHRF6KENMX4GEM3NT30K20FD9W03B79AKARV0KK6SMW0W1DY68KWGF69JH95RCHXCSVVV8XGVC48CBW1ZBVPFXS1BEJRDBHJV5229R5CZ9AXC3DNSS7S2QYENQZT7ZSKM9VKYGN604GT55SXD0NXJ0QCVT6TG8MTGTTKSM9D1DFKGDRMP251FCEZVG4XGZSVHKGVHGY","2QYSG97X93Z5TR1JT9FJJG05T1ZKZCPKZ4FNTBNF3DT2WPJR12QF1EPB5NSYQK068XFRKK46YGTT5GX6QEJJZ2B61A35RM30HNTP9S794V2TSME26S4RG32M6AYCNZFR6YEXBKF828ER3HMS1XAF8H475HQSM4M0004GN2S2EHMBXR62TYBEYE20GB123X5V9B31W9650S1E833Y6AH8SKQRE5JY1AK0NATPP6DBKWRC3FTEV6QBDVDGB8B3FKVB","XHTD1E2BZMY311GRBP3PJ6TNJ5S9MMWYZEPFKBF98X6Z3B9GK8EKYZ9DMN0CR9JYQ95KVWETVEKGWMF3V9VT3KK29WGDBPCX1V44J09E2AA1V72A6Y6B6KXPPESB3SM2TH0DZZC1AYQG7TNAMWTQ028ECEZAW30DE3S4ZWKE78ZZJVKP4ZXFXWN3JTRY2TX112B3TRYH94GNYJ1JKGHVG55ESYQTFN7VPPW8GMRSJRVNJZ09S4P37G21HBH46NCK","2N7GXE2T60XCGFPMTS8YJZ64G6STTNPQ4R31CCRJ9Q3F7KJK9RNW4JAQ0VP0A0SCQGR12HJ09NW0TMWKFP46XHQWRJP9WMQA8TXPP6F1SR9XQX7A8KB73EGH3BPN8X5N7YY95M7ZBD1F4SJK24HR0P0GV6BMEEQFTE86QGTP67Z7KC1JPANYM1B3MX9Z9CVESD83WX4VG459X6YR2HR8T576M0EV5K73P9397H25ZSP0NXSAMGY87R0DCQM1GFR3","7WKT07H36FAWM8W3X54AN2VAGJC5DWKP2MJMHES1NA2VFVJD3WAWJJCNWARWP17SQSEWS38HF36A63BNR5Q0Z2R7VETVASYVEYRFQYFGW3KXCVT5AS2ZHJCDMWRJ0N5EQXP0J7MNMCCCQZ8F304SKWWMAQJ8EB5Z7KKM1T0Z8WQHZACR8YTATF4XSXSSJVPGGCXNC47B11QM4RN3HDGXF9MBZZMKASBZRF8AA2EH4M1VFG8NR243ZE3ZKK3818C7","FKZQB344EWN58WPNVZ0BR5A7D30ZR58HZN0PQPVJBKWK3F4A4DPNEV3Q8QXR70E8V5WT4JX8AG9H3X5RZ74DQPKH7RT4M4747NY98P4J09R58JP7BR58KA8Q0AHS6069GHNWC0SX9GF33RV9SA5ZYA75CV37V1N5GRAPX6A0SWR76B6HYSPA94G5PY02R9B05W8Y5MDWDEY70NW4ZXWG2ZH3S68SSNP6SASAJV85KMH6CH7FZXTDYQTAR0HDB4K7","3073VTHEC9679DTAPZZ2J52N4PXFJ2B5JDQQ4FEPWCDFWMTXJK4KTSVMSF6DNMY8BH3EJDS192CK16JZG95JGDGYXMYBAFCY4X77AGA33DZSNXT32VWNVKKP6PN5E7JWRDJT8SSCRJ6C90P9YZ31SFF4PPKFPSVZFRC3PD87CKT8M9D6XDWN61D0PMXKMWGJVSNQDR8NP86MJYE8KGHSX0SWDV2J9N3X9212CXV1JDQNS3DFJ7XEX38EEKWQDSJP"],["8HRTEYDE0W9T678MM8X20QADH4XHBW7JTHJVFDJDANF90K84P7FK7TN0KJGE5BW52VQQFB10YNEQ8S9J3WVRV229RSMC9FKNRJ60968J536EYP24C5WNACGATG6AG8N4YNDQNQQM8V2KQ6DX2XVEH3Z86W9ZYKW7SS4V4B2WM1ZT9WA80SM1H73H9JN62GMMQE37XHVQZ212836WQJMFFKR29ZSYZAE45FJ14AQMP6YKF56M4F1PSATNFZ62VC87","R2CW58HWX89YHVRJ8WYRJ1A2GSC24H1BQW38VGBXP0MXYZS939BWPG8KQM4ED9M19QVXKZ4RC21RN62EC7E1SSAF5VW0BFBGER1FWW3ZHJ78FFF1TNJGRVBE2PF18W1ZXMATHZ12RRKDPSYT81YTGRGAYZ71GHYD1SKYD711P2J80ZTKC6YCWJ6172Z14VWVFA6H8JWWA8VYZ4XTARPXZRWR1Y1YE4232XYZ8X6A8HHWQXS5ZNSM0WPK8BW0KSTA","DE3DY2F0TCKEXVV65EHTWFKKAB2ANTDS435K869BXNVA8NQH4JA6X3WM0H5VAVFT3RCAVQ1WYCRWZ2PKDABAFEXF8RP1R4ABX04ZZS4XPB9K4R1T5KK2HX7GMWQX8RZ16Q40C44DJ70YTHVBD0BM6AF2R5G86SRZ8KERPS21RMPYWYBBWM8DR5YS1D3HM6CEJE6ZX6K398XJGK59E3FCHYJX0B2SCRKJB5E5G1S6PAB3QXKZ2SDGGQR7F8XSESZR","ZNXFM7CDW0M2XRNBTD1GM4FDG74G2XDMTF53N7R71J93YPMPXTT4G6CVZM9YZHCK6GQ35P9CHEKNWK9Q3VESZCYR7TDMMQYYFBNPPM8E4CVHNHFZSBSAHP6MMSWQJ07GZA9FRW7ZGDH6ZNEWNVMQK0V8GV0035C8PP2SYMH66FWMA24E3D15RMJSF4C817TD7SD4F7WG6RCBQ6Y0DDHAY4VW1TB5V4W55J3N0GEMX7AJ98T0TSZQRS6R9PSP1JA2","2J8G5KH2TYWDYHA2KX2CEPW58CRDHK05YX5TER84CGAEBAQASD9Q0ED8R67VBVMDQE2C9NG7V4T3QZ2VRPJPYGQXFPCXBQF99FXK1GBMEGCVP8Y4S4TTN8NJCRBTY6CXA03KQ00JKVJMVSWA85969C2F8YAG8GS5TBPF3D8ZT2C56D2ZD65ZB7F0E11S7B2RWWES7TXQ7HKXDWEBFMYTC2WNGZT1NET0JG21MP03KPS6BEMAX5Q5B139QJNCW8F2","K1605K54DR7EXXPBSWWFNJMXQE6QZS3BN3WWVBF2Y83WD42NMB9FZJG0HXPXVGVJTV1EFEXBAV7PY28FAXTVJHAZ06CDD13ZF7JE12D1BN6T6AT4RHN6N00A2ZJQTE1VCWGBF49Y5B75ZXNS7F9K352AR5A5ZXG21KV7VNT2ZPJ2B1YQG11QY05W920TEGSC8TW0J41HN035ZHCG8KBF5QN5RMGKSVZQV708K7DPVYM7NC2V7X2ZHZ44CBCPEXHD","MGQFD9DMYZD61RHS6KFGC5YGRG2Q56CYNX4GYBGASQ1P69N76M6P4CA3WZV163VFR71JPAXPK11BFCVVCS3A9E59WAR6R0ZWXXN5P9XJXD7DSA1PWCS0JVJ851BCMPWE54M23JGHNRJ03VE76HW8ZH45B6WGG809T8T2HQRBHBPFN3WC9NSE7NY07YWH6V3MFMVPQ2GZJ6QJP4C9D2AGM88H71PD0H65YZY07HD72F3VV1QBJX6T1GPY3NYPEHH3","KWJQX6FGX9XTEXEXYVWJ657TGZHYWHX24KEE1XA5TW5NVVQMQGQVC6HE6GA4RBC1MM0S1GWN7Q838QQEP5DQNDZS7VDBSEP7SPHC832WRN492FN8CEVSJ01AAE36HRXNM8DN6JPK160DJ4M842W9STXQRWPPF94S6HER2WZX330EZ9CECD2NKWTPTYSDGA5FVZS2GC9ERQGYP4YKZWZ8DXRJWCNVE1G7BYYPWNTHPVX0EW5F9GHT4MR29YG9YMRS","50FNFP9CQNHME6EDC0JFNXDVHW58CMC0TJRRZ0FGAYK0MAYQ9EV5WZEYBDV5Y967H72AQBJ28GXD394BDW949KGEMNSAWYE3YX5GSZZNZ9CCXEDKJJSC7W1P1Z04B9VAAM07SPWN4EMREMR9R4XXCD014YHPMMKP64C58X93FCSFJNW8XDF5FW0S2KZJHSP8FGRNQ6D62CQJCVPS615D4N52XNPWTFS1R379GVKSZ4FRR6SRTT4R3PA271HTX3ZQ","NA6QQDXM6SB52138M8CN3E4ZY7P0P9QS9AJ6EGNKYYK58XTRR4D4BANF0ARSTVZGMSJ7FP803B87J21SR2KT35V5K4FEHWVQ9WB9F9ZFMREFAA3SP3NWXNYJQQS0YA2K3RRAWJYJ2XSPQERXW71702QAEQRZQPMGXCMDKFNY9V7Q77147RQ7M87G8ZHZHX83D9C6QHKWGKTSQ0R66MZRCX29C6P6A5EGHACWVXD32Z8SA1ZPNJBDZY0PNJJM68D0","4M00E1KQVQ5KTJPXTCT3EYFN1SH975ZASNAWN7Y0NB12ANR6VZ1163GKCK9WBQJ34Q9P0G763PQ0B68WCJT2KXYXX5X3AV91BPDGGWBYB220HQ52V5VES6H7D75KYS176MA27G09X9PAGTQJ78VQHDAZCYZ5TS82D7HM5GT618605NVEYTYQYT3BA38R6V0RHYGE0CHNEXZTM0TFGDXQZ3P6CTNMYPPPM4E4PMCCQC4XR2S6CGVWYE1TXN0DC59S","N98TSJ6HGBS2N3K3MRPW6WEHBP409B4DC7PW8GMHM2QM2VGC0XQE1AQQ9AT1J4MZAK0B3RAMWF74XZT0D1CBDFABDY8M2M3X6QM7M4C8Z2DV7B2KHF3GBV4FMEG2PWAPW97QJ47383BT5XEYC4KQNXNK1K22NXYQJK0W5GS64KRFZWWKENZABG8VYZ7AYDAXMPVRSCQCCDE1RS6V8MDAVP65SAB59NSM0QQMBAPVBDTWD0P3HCZMG4F17QGTYZYP","ABT20WXHNAHYANMGCVGR9VC1QEQMS5YYRMMPS8GE04RK7XDF4CFXV9HEC1TAN77PBZJXAGX8GVZ8Y0068T84M1DQ90F2VEZGHR1JBBJ91S6RER8FKC301STT9MSF0CYBQTG5GAZK948305FBT6QRFX5BYS4NB5ZX86YMTNZ01V5C26W6Q6T78E5MHC7PH21SQ2VERSMDBWC640068HDX4PCJWBV7809DBSHR2ASJBMM32C49SG4EYVW74H4385QA","M0HBDKZV4TAYEBJJFBMMV55735T3F114RQMHBW2FRTDNNEM6NVBYR65Q25GJ1XNZJV0J7CY55CWMNEARHS2F9TYZPM0BVFZ429DVB2BTX8ZJ6Y9M1RSMVZZZM3GVE865PFEYCVG40AVC5T01Q8XGW1FDZKZTXBVCR5J7H24870S3BJB820X7MQMXDHNNT7VA4XZQJRN96JNHFC3RWB8R2X6Z4BZA9AYETNHP180MY0CJB8CJ8P9DTFHFRAY4M8WE","HV2FVXRE3NGW0WR4XMX0QZX2Z0B7MQB2ANCC95GY0FY9WD74D6CSM11YC0HNMBYCX8CTX7QJS28FGK9FC2RP79M8MKBGHHP0E3SK33AHRQ6457TSMARYKRY2SNSTV7JC8Z1KPV55EH5EH9C736G42J9W84E61JRWG8PMD24V1TS0MJZWKNP1QKSET7N40VAJXZE6B2QDPH2D7F26S4SND52B8KS1HB0NH762F41QE22ANVSXV6S2TN73Y5MXTB9S","70M04PP2WVXGK3NJCMPXGQQCCCDTRW0AF5F8N8A605DHY4CKBFFXX9F5Y512JS3CY6MD9T7K1X0ANT3N5VJRWPF9Y1S97EA2NAZ2W783DEP32Q1M3Y93VBHKCBQNM9M456VSMZA16E8SP3EGPJ9K7QVE0KYV0VWFJRXCA2CWDNNFDEKEJ6GK164SKGZ5MV1QQEDM258SKTQQ0EER895QRAA50PHNNQF1Z8MGHMZCV9WP0ZSJASVK63E4Z073TTVD","799TV24HVN9JDQBG0WFGA5FH0RNJYFJG2XF1B93W5W571CRPMEAHCAKA294YT63VV0K7C46AQYF1AVS58ZJ58CESDYWMY770P95EXPM5H38NV3F3RDTDB7EX5Q9XN0X8QRW37BTN8VBQ4PZ6Z1Y4539C7QGE2F012RBKGK47BST1TQP3XA427H1CDGT8HJBHBY8BD4TH1N7EE0XZF2QV6AJ0JCPWD0H6TKPVMGH1QYKVEKEPQBX20S8K502AYGKQ"],["23NQ8CW42D7FAY7FD7636SFA7THRQA2EGJYMFYF75FA1ZATVSMPPYSHTEC58J84PKDHRD0KPFMK811CTSGW0W274D8A3E5FKEX6P5AZ2ST0K9PK65ZP6R6CR8RMWSGQQX5VAJ2YVJ3RNV20C7YJA0CDCJNQX3JKGRX5NRY8GY3RNA38HG3SM0NW85AKZ0SXP1XRZRY0A0T3SM6E4Q6PTJMJZJ677BRZHXAGB7BEMSK6KDERXHVN9AGN4J9SZ5AY0","ZNZFHJ4X5T79G4DXBX8TPG0RV8SV4B7ZKV56CAN893MZ6Z00CNFPH6KPPXTKM8MB6MTPSCHEA0PRGRHSAKPBSAVR019GB9E75TFSXV452ZQN8Q54ZH9BJPKMAMB26X8BDQKGYK01FAWRWZXJ1TW9GVPJ9TS03WKQS64TVRNH17TTFVED3K8MFMDC9SFSJ4FZC2J19XTSWASXSY4BDE4T8Z2VGWEGDTYF0PNPMHDN2FQN2T25T6TA2DW702HM9MBC","SCC6Y84J99YQ598PR67G5VDT1N9E6S2VEZ22QWD7PQDX108ZZJ2AK16YF9PS8WSAP1PCPM0AYD1R9522XZNGWEHX92RE3R0WVM43A38450XH0EHY6XYKCK0NWJJ9XKN0FG4GACRF6X1WG4Y7AYW6FBFMBKHWDHP8BCTT0J9Q9XXZEBC88C57DMG18ABP6S248JAX9JCN0GZ4Q25AX6XYA2W2KD7CW97H23H11NS47XMC0GFKF7FDZK11JQXASJMT","PJBV9WQ064WKS9WVV0JWN3JHGNCY82T42FC0ANKNV5SEE8BBPJTQ6HXM76D8FAH00A6GNB2HMRYAAS0ZTGESRE2JFDD5HFAWW2EX9BN1QA7T6EB1G4PBFFZXVD3AN3GZKK72A4VT5AFM9QF7GHEXVWC29AHH5HH3ZHYQ1AR5TB5G7CNRCM8GA1Q61P574H0G2DWJJ35XE79D3G6SEWPCPB3VZS89B3XY9A1HV86R6BVY6C48D7FHXEA903AVVSMP","7HS65FGXB1Y1E39DHB5J0SRX8KDS7K6YBNP1XAPBQQNBM8N2T1QAVVS37XG15A2ABWK9J2CP16WCWNMG1ZCS6KEY98DXRNKNEQ099M9P392D00R8HDE1Y8C918PV0DVXKM3141CYJFXTQCYM9A5ZYKDEXNF09NTWHNDT3F990R6EWYS0TT4F4YDW9605SWTPJ2G29CKQNP13N1KKFRJS4BME8VE800YH6HTCSWTPXQ19TFXCHET6PF9EZE00RF9D","39HPW4NZCE7T1TF3ZFW6FGSSSETD2NMY5ED7T49572WAZ5FBJJSGGK8G45CQSSS488KZ2WRVM2N79ZKD78AX08X7TAW7DGWKB5KX9KRFCAF7ZZJQP5W6A1652XYNV2NWR51MS30ME0Y6RPXCMVC7K2B3HK5TFQ893HE8JJJSD2TF3AS9RGMPRBXXPCTC1R3Y5MZJQ79RKV70PVW65MA00RPMC27VGBWW5MA7FWK4X8JWQ8PHB9666MVM64AZJZSC","WFPTT5ZYQZNF2TYKSMFT6D7RP85980PTXNP6PS1HY3J5Y4ZY8DEVNPGFDP85SQ2DST4QQ1EHQQ9CHP9T1Q25XSGNKAHF9QAXX6N029SNH3C0MTG5VAQWQMCSPAYBW08EKFJS560JXX1AT9JCD0CJXZTX1P7TC4XD1JJCBDYKQ592CJZDKBCVMDN2CAG7RNXVSKQ8EWCRM7NCEF3YVWBJ7SQRE9B3BB067SVSRJQ9SB0PTGRP93WRNQ2JEGC584K8","P0VHPX17WERWA5G19P5NV2ZBWXGX3YWFTYHMSWQ2C5H82TPQ08BNDPE813NYWWT231EMTY7VRW2ZS8S447T4K5BCD7S0YQX2D92G5VRP10YTC57P16QZ37T0QZ9JENVPT6665TZ97JERST3M8SG7BD3ZDM5H0S9KCQTXXDJCR9NB1WHNJFTYZ0DJYJFDNZMTKREQG3R5VF5DQXXWKJ2GVKZG6ED2VTJR11MKYTQBMXSKP50RJYEZMVCZQ8H5KZBV","VDS1SGX5A31KBPTBPBR82C4ZD5FG2XRDM5KGVAR7X8XGXP7ZMGREXS9CYFKA9SZ3GMF0H7X4H733C81HPNDDC2NPF4443CB0KY0XSMJ34SA6TY99SE0NTZ96RZ36CZP77HRQQ93WC2EN3FBGS9WQMZEQ7GKNZSH6RBGXMF237ZGRN4FPRGX771VXY5DQXFMPTFYRDHCPWJR9FZKF7TQT0MB1K412PRFHSHM9S8FZJCHYR2PP443WF9SZWGNM2CV8","J8KEHBYBAQVMTR1XTNDY23VSTQVW5CYE2EDNRE9DBP56DV1PSC2XXFH8KKHXT8D3TM5G6MCHE0JWNHN6417G696MHY5NZ6CRAYYBNR4YBPHDF94CHBMZSXH6KD3N0AVW3F0KK88DPA9G2CZ8C82QTV8Z8C8WRRWAHRH0X6SEGK4BJPEB3WEGRMD9AFYTXCPQ0N7BXK83052V4HD6W7AB0AE7EQ789XF6C8AD4TN7ARF7MJDMTCY624B6QR5K15Y5","R5D4QJ0HM2A9E8WEVZYKG9V612D1ZRRB6RCGK4S8MDBM7NRBP7DDJGV1H7SN0JEZJSTW7DGVA7WRK0Z8HSH6VGB2NZ2CRZKZTTX15W58EB2XKJKZJYA0AR5MKTNHPP7D39PFF8BP39PJX9VRFHGXMWB84GHVMND6S2M2WWVHMBVNK2D19TJ1240NZFV6GP64416JT0QW06ZQMXVHVD4GFRESTSVBH1G78AMJ972RAHBF4DM0PJXY0PTXYWQSP2GZ","KZ0R0MPKXYKS13894TAC8SMNGYQ9F1EB9VN9S4P7VJ8KDXJEREYR64HDRAP4HBRY9D50YDKDPE9AHMW9ETR4CXK3E0YQJQ2YGPAWJ823GH7KHJXK1GTFSZ3TERT1VB31FGXC0950TY0MAHESMPHNRXSG9738C0CEJ5Z1TNBVV48WJCH2JPCKAPDMTSFYFAECZ28WJ7J9EW459NNT5H4D0DB5ZZ2CY16CCC8PBC0K4ZYP1Y2ZW5MK0N0MJTXGQ49T","YVH178SVB7QK1HM2HVSDGBZ1QJN9NRTG3RXMC9YVS74VXTW719NRFMAXKJHVZJE77HNRW53S8DSD3QTYDZ9ZNZ1185GZXP0NNP40NQFYJQSBHWVE7WDPR5KZT42BWQE1P20B3F5HCHV3VD1ZCGCZ1NF5K5P4WKT01K7XKXNGFTX9HY5YAG30THBY4S3Q3CPMQBVCBXDHW929DHRBZWHZGGGBCTVNRRNDA7J0EVBAVYYHES2PDK9YW5STCG83S5AB","MA1RKAT9SCJSXJG7T5P1QF1VW9GRBCYK03P8Z55KSCK4SN1K0MFSXR3YERD4VA5QQ1N7KKHPDAPNYHQ6QW2TPBVM932A5G42VEKZ9CH5ZH7346RKDT8BMNSFYQ799W6042CCJ3JSESFYMER8JHZNBVFWFGMKMJJ642BCP9PPA9H7B0XSSGK2CZYWK3RQX5WKZK4V40AMTRJ9JRZNX7QKXRN9W464J3X3BRYHR8Y70C42HH0HVW86CPNVKWE0Q36C","K8CP0BM60F6P218ZMC4HW307DNN3FHHEG3XMWN55KEZR4RQ86ADXGJF2FKD7QW2TVQ3AWN2KVJ6QMP6SFJHF11C6T68FWKWMQVGQWYY28591XTQ3D78FB9N06T2W3R6EERTHRQNK7X9WP2BV3VM43A39YXVJ0W0BHJ0XSZQENN218ZR4GTVDX48788WXFD6064ZXGMWGD2EKWMS4BBVWK59FVZPGDRQD6EN3TRA784HBBWE831JWBEVX3YGPX9T0","QC2WWZPKJDCFZA65QKSGKW7YTAS9RP0W4H0FP96Z5TGCCD0K9FXFX4F75MQEDNKCM0B34D8ZR46CHR97HMMEB3W2T8W6P8X5289Z729365HVDQWCGHMJSGM7AHA1HS6ZND695X67D42H7XB7NQ5X57XG2S32R767YPQJERZ0ESG3S01NGNQ0P62KM3AT28JX41GMHPEA92V1Z80RYS8GWE9CGZ6K66NVGW72SN8DJGDFVC7771HP93X6DYN0TF63","H3P6CNRKH4BSCAWG3T9RRA89EBF1F91JEYEY4RZJQ2NNCZZASY362XHME0KNM36R4SNQD956CBW15XAXVK70TZM6TBVMHJ8KKQQQKBG4Q91ZHKAS10NEVD5B36QGYM7CMJM3DVJ00KTK0ZAM8C4YRNZDZKV5CNFGDR0DDP1P38704Y3G9KFRJ455SD39J7ZYDB5GQV17ZF2PE7GY927S1KSXV4KKXQ7FRX1VZRJGAD1F3DY4KJFRZJGAT5951JNS"]]}
diff --git a/src/exchange-lib/baseline/refresh_reveal.req b/src/exchange-lib/baseline/refresh_reveal.req
deleted file mode 100644
index 3fb143960..000000000
--- a/src/exchange-lib/baseline/refresh_reveal.req
+++ /dev/null
@@ -1,7 +0,0 @@
-POST /refresh/reveal HTTP/1.1
-Host: localhost:8081
-Accept: */*
-Content-Type: application/json
-Content-Length: 255
-
-{"session_hash":"V97SB8T670M9V71D1Q0KVQ4GSJCVQ5AAKTTH9QKT0ZJZZBFNZAV4NA8NMWRRGVPFEBEGB6ANCN9BPQASJ40TM4Y1C49648TJJ07PGSG","transfer_privs":[["EQKJA401A9NJ2YJDFZJ1EV8AYXBHWZB6NT5T0TWSJHVKVDM6W8A0"],["TKDJ4DF3GZVG0DGAB9E3RGBGSTANYB6JVVWXJGPMB2AY4VQNTBA0"]]} \ No newline at end of file
diff --git a/src/exchange-lib/baseline/reserve_status.req b/src/exchange-lib/baseline/reserve_status.req
deleted file mode 100644
index 4f988f669..000000000
--- a/src/exchange-lib/baseline/reserve_status.req
+++ /dev/null
@@ -1,4 +0,0 @@
-GET /reserve/status?reserve_pub=TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0 HTTP/1.1
-Host: localhost:8081
-Accept: */*
-
diff --git a/src/exchange-lib/baseline/reserve_withdraw.req b/src/exchange-lib/baseline/reserve_withdraw.req
deleted file mode 100644
index 484950250..000000000
--- a/src/exchange-lib/baseline/reserve_withdraw.req
+++ /dev/null
@@ -1,7 +0,0 @@
-POST /reserve/withdraw HTTP/1.1
-Host: localhost:8081
-Accept: */*
-Content-Type: application/json
-Content-Length: 919
-
-{"coin_ev":"Q5X8A8TCBFH7E5BMY7HSB17SHFTM1JPJGV61P2CA7Z9EXG8P2HYS69B31NZESKXHSZHNJ2DQN3CC2AWFNC6V90J577JD3TXBMAY8Y5M9V60KKT73Z1DW24JFSNAK91G1F2WT55ADP1EG7N5F9AY7A7ZJD03MPYSH0RDP7SVZS2KRPA5JRHFR4GDJ59CFNE7A43M95ZKQHQAS8","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","reserve_pub":"TMZCK5CFM1KZQGY1WTF0CEZZPGA0670G94969RF79PA5106ARTK0","reserve_sig":"8427B3RTB217124EB1C37ZVJFC08KN17RHGHE9ENZQMQVJ0S11SAX6H8Z06SWCKT06DRQ9DQ8XD786XKQ94T27PYR9GC9EMT1Y02W10"} \ No newline at end of file
diff --git a/src/exchange-lib/baseline/wire.req b/src/exchange-lib/baseline/wire.req
deleted file mode 100644
index a4f1d0749..000000000
--- a/src/exchange-lib/baseline/wire.req
+++ /dev/null
@@ -1,5 +0,0 @@
-GET /wire HTTP/1.1
-Host: localhost:8081
-Accept: */*
-Content-Type: application/json
-
diff --git a/src/exchange-lib/baseline/wire_sepa.req b/src/exchange-lib/baseline/wire_sepa.req
deleted file mode 100644
index 80d3d4619..000000000
--- a/src/exchange-lib/baseline/wire_sepa.req
+++ /dev/null
@@ -1,5 +0,0 @@
-GET /wire/sepa HTTP/1.1
-Host: localhost:8081
-Accept: */*
-Content-Type: application/json
-
diff --git a/src/exchange-lib/baseline/wire_test.req b/src/exchange-lib/baseline/wire_test.req
deleted file mode 100644
index 684352c96..000000000
--- a/src/exchange-lib/baseline/wire_test.req
+++ /dev/null
@@ -1,5 +0,0 @@
-GET /wire/test HTTP/1.1
-Host: localhost:8081
-Accept: */*
-Content-Type: application/json
-
diff --git a/src/exchange-lib/curl_defaults.c b/src/exchange-lib/curl_defaults.c
deleted file mode 100644
index cd0f1aeba..000000000
--- a/src/exchange-lib/curl_defaults.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/curl_defaults.c
- * @brief curl easy handle defaults
- * @author Florian Dold
- */
-
-#include "curl_defaults.h"
-
-
-/**
- * Get a curl handle with the right defaults
- * for the exchange lib. In the future, we might manage a pool of connections here.
- *
- * @param url URL to query
- */
-CURL *
-TEL_curl_easy_get (const char *url)
-{
- CURL *eh;
-
- eh = curl_easy_init ();
-
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_ENCODING,
- "deflate"));
-#ifdef CURLOPT_TCP_FASTOPEN
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_TCP_FASTOPEN,
- 1L));
-#endif
- {
- /* Unfortunately libcurl needs chunk to be alive until after
- curl_easy_perform. To avoid manual cleanup, we keep
- one static list here. */
- static struct curl_slist *chunk = NULL;
- if (NULL == chunk)
- {
- /* With POST requests, we do not want to wait for the
- "100 Continue" response, as our request bodies are usually
- small and directy sending them saves us a round trip.
-
- Clearing the expect header like this disables libcurl's
- default processing of the header.
-
- Disabling this header is safe for other HTTP methods, thus
- we don't distinguish further before setting it. */
- chunk = curl_slist_append (chunk, "Expect:");
- }
- GNUNET_assert (CURLE_OK == curl_easy_setopt (eh, CURLOPT_HTTPHEADER, chunk));
- }
-
- return eh;
-}
diff --git a/src/exchange-lib/curl_defaults.h b/src/exchange-lib/curl_defaults.h
deleted file mode 100644
index 07bab8fb2..000000000
--- a/src/exchange-lib/curl_defaults.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/curl_defaults.h
- * @brief curl easy handle defaults
- * @author Florian Dold
- */
-
-#ifndef _TALER_CURL_DEFAULTS_H
-#define _TALER_CURL_DEFAULTS_H
-
-
-#include "platform.h"
-#include <gnunet/gnunet_curl_lib.h>
-
-
-/**
- * Get a curl handle with the right defaults
- * for the exchange lib. In the future, we might manage a pool of connections here.
- *
- * @param url URL to query
- */
-CURL *
-TEL_curl_easy_get (const char *url);
-
-#endif /* _TALER_CURL_DEFAULTS_H */
diff --git a/src/exchange-lib/exchange_api_common.c b/src/exchange-lib/exchange_api_common.c
deleted file mode 100644
index 6b0aa6ff6..000000000
--- a/src/exchange-lib/exchange_api_common.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2015-2017 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_common.c
- * @brief common functions for the exchange API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-
-
-/**
- * Verify a coins transaction history as returned by the exchange.
- *
- * @param currency expected currency for the coin
- * @param coin_pub public key of the coin
- * @param history history of the coin in json encoding
- * @param[out] total how much of the coin has been spent according to @a history
- * @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not
- */
-int
-TALER_EXCHANGE_verify_coin_history (const char *currency,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- json_t *history,
- struct TALER_Amount *total)
-{
- size_t len;
- int add;
- struct TALER_Amount rtotal;
-
- if (NULL == history)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- len = json_array_size (history);
- if (0 == len)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_get_zero (currency,
- total));
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_get_zero (currency,
- &rtotal));
- for (size_t off=0;off<len;off++)
- {
- json_t *transaction;
- struct TALER_Amount amount;
- const char *type;
- struct GNUNET_JSON_Specification spec_glob[] = {
- TALER_JSON_spec_amount ("amount",
- &amount),
- GNUNET_JSON_spec_string ("type",
- &type),
- GNUNET_JSON_spec_end()
- };
-
- transaction = json_array_get (history,
- off);
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec_glob,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- add = GNUNET_SYSERR;
- if (0 == strcasecmp (type,
- "DEPOSIT"))
- {
- struct TALER_DepositRequestPS dr;
- struct TALER_CoinSpendSignatureP sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &sig),
- GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
- &dr.h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("h_wire",
- &dr.h_wire),
- GNUNET_JSON_spec_absolute_time_nbo ("timestamp",
- &dr.timestamp),
- GNUNET_JSON_spec_absolute_time_nbo ("refund_deadline",
- &dr.refund_deadline),
- TALER_JSON_spec_amount_nbo ("deposit_fee",
- &dr.deposit_fee),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub",
- &dr.merchant),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- dr.purpose.size = htonl (sizeof (dr));
- dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
- TALER_amount_hton (&dr.amount_with_fee,
- &amount);
- dr.coin_pub = *coin_pub;
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
- &dr.purpose,
- &sig.eddsa_signature,
- &coin_pub->eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* TODO: check that deposit fee and coin value match
- our expectations from /keys! */
- add = GNUNET_YES;
- }
- else if (0 == strcasecmp (type,
- "MELT"))
- {
- struct TALER_RefreshMeltCoinAffirmationPS rm;
- struct TALER_CoinSpendSignatureP sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &sig),
- GNUNET_JSON_spec_fixed_auto ("rc",
- &rm.rc),
- TALER_JSON_spec_amount_nbo ("melt_fee",
- &rm.melt_fee),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rm.purpose.size = htonl (sizeof (rm));
- rm.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
- TALER_amount_hton (&rm.amount_with_fee,
- &amount);
- rm.coin_pub = *coin_pub;
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_MELT,
- &rm.purpose,
- &sig.eddsa_signature,
- &coin_pub->eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* TODO: check that deposit fee and coin value match
- our expectations from /keys! */
- add = GNUNET_YES;
- }
- else if (0 == strcasecmp (type,
- "REFUND"))
- {
- struct TALER_RefundRequestPS rr;
- struct TALER_MerchantSignatureP sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("merchant_sig",
- &sig),
- GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
- &rr.h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub",
- &rr.merchant),
- GNUNET_JSON_spec_uint64 ("rtransaction_id",
- &rr.rtransaction_id),
- TALER_JSON_spec_amount_nbo ("refund_fee",
- &rr.refund_fee),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rr.purpose.size = htonl (sizeof (rr));
- rr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND);
- rr.coin_pub = *coin_pub;
- TALER_amount_hton (&rr.refund_amount,
- &amount);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,
- &rr.purpose,
- &sig.eddsa_sig,
- &rr.merchant.eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* NOTE: theoretically, we could also check that the given
- merchant_pub and h_contract_terms appear in the
- history under deposits. However, there is really no benefit
- for the exchange to lie here, so not checking is probably OK
- (an auditor ought to check, though). Then again, we similarly
- had no reason to check the merchant's signature (other than a
- well-formendess check). */
- /* TODO: check that deposit fee and coin value match
- our expectations from /keys! */
- add = GNUNET_NO;
- }
- else if (0 == strcasecmp (type,
- "PAYBACK"))
- {
- struct TALER_PaybackConfirmationPS pc;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangeSignatureP exchange_sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &exchange_pub),
- GNUNET_JSON_spec_fixed_auto ("reserve_pub",
- &pc.reserve_pub),
- GNUNET_JSON_spec_absolute_time_nbo ("timestamp",
- &pc.timestamp),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- pc.purpose.size = htonl (sizeof (pc));
- pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
- pc.coin_pub = *coin_pub;
- TALER_amount_hton (&pc.payback_amount,
- &amount);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK,
- &pc.purpose,
- &exchange_sig.eddsa_signature,
- &exchange_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- add = GNUNET_YES;
- }
- else
- {
- /* signature not supported, new version on server? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_YES == add)
- {
- /* This amount should be added to the total */
- if (GNUNET_OK !=
- TALER_amount_add (total,
- total,
- &amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
- else
- {
- /* This amount should be subtracted from the total.
-
- However, for the implementation, we first *add* up all of
- these negative amounts, as we might get refunds before
- deposits from a semi-evil exchange. Then, at the end, we do
- the subtraction by calculating "total = total - rtotal" */
- GNUNET_assert (GNUNET_NO == add);
- if (GNUNET_OK !=
- TALER_amount_add (&rtotal,
- &rtotal,
- &amount))
- {
- /* overflow in refund history? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
- }
-
- /* Finally, subtract 'rtotal' from total to handle the subtractions */
- if (GNUNET_OK !=
- TALER_amount_subtract (total,
- total,
- &rtotal))
- {
- /* underflow in history? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- return GNUNET_OK;
-}
-
-
-/**
- * Obtain meta data about an exchange (online) signing
- * key.
- *
- * @param keys from where to obtain the meta data
- * @param exchange_pub public key to lookup
- * @return NULL on error (@a exchange_pub not known)
- */
-const struct TALER_EXCHANGE_SigningPublicKey *
-TALER_EXCHANGE_get_exchange_signing_key_info (const struct TALER_EXCHANGE_Keys *keys,
- const struct TALER_ExchangePublicKeyP *exchange_pub)
-{
- for (unsigned int i=0;i<keys->num_sign_keys;i++)
- {
- const struct TALER_EXCHANGE_SigningPublicKey *spk;
-
- spk = &keys->sign_keys[i];
- if (0 == memcmp (exchange_pub,
- &spk->key,
- sizeof (struct TALER_ExchangePublicKeyP)))
- return spk;
- }
- return NULL;
-}
-
-/* end of exchange_api_common.c */
diff --git a/src/exchange-lib/exchange_api_deposit.c b/src/exchange-lib/exchange_api_deposit.c
deleted file mode 100644
index 23066c7dc..000000000
--- a/src/exchange-lib/exchange_api_deposit.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015, 2018 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_deposit.c
- * @brief Implementation of the /deposit request of the exchange's HTTP API
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_json_lib.h"
-#include "taler_auditor_service.h"
-#include "taler_exchange_service.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "curl_defaults.h"
-
-
-/**
- * @brief A Deposit Handle
- */
-struct TALER_EXCHANGE_DepositHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_DepositResultCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Information the exchange should sign in response.
- */
- struct TALER_DepositConfirmationPS depconf;
-
- /**
- * Value of the /deposit transaction, including fee.
- */
- struct TALER_Amount amount_with_fee;
-
- /**
- * Total value of the coin being transacted with.
- */
- struct TALER_Amount coin_value;
-
-};
-
-
-/**
- * Signature of functions called with the result from our call to the
- * auditor's /deposit-confirmation handler.
- *
- * @param cls closure
- * @param http_status HTTP status code, 200 on success
- * @param ec taler protocol error status code, 0 on success
- * @param json raw json response
- */
-static void
-acc_confirmation_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *json)
-{
- /* FIXME: clean up state, some logging on errors! */
-}
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * from the exchange is valid.
- *
- * @param dh deposit handle
- * @param json json reply with the signature
- * @param exchange_sig[out] set to the exchange's signature
- * @param exchange_pub[out] set to the exchange's public key
- * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
- */
-static int
-verify_deposit_signature_ok (const struct TALER_EXCHANGE_DepositHandle *dh,
- const json_t *json,
- struct TALER_ExchangeSignatureP *exchange_sig,
- struct TALER_ExchangePublicKeyP *exchange_pub)
-{
- const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("sig", exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("pub", exchange_pub),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- key_state = TALER_EXCHANGE_get_keys (dh->exchange);
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (key_state,
- exchange_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
- &dh->depconf.purpose,
- &exchange_sig->eddsa_signature,
- &exchange_pub->eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (0 /* #5447: replace with "for all auditors, if auditor selected for DC notification... */)
- {
- struct TALER_AUDITOR_DepositConfirmationHandle *dch;
- const struct TALER_EXCHANGE_SigningPublicKey *spk;
- struct TALER_Amount amount_without_fee;
-
- spk = TALER_EXCHANGE_get_signing_key_details (key_state,
- exchange_pub);
- GNUNET_assert (NULL != spk);
- TALER_amount_ntoh (&amount_without_fee,
- &dh->depconf.amount_without_fee);
- dch = TALER_AUDITOR_deposit_confirmation (NULL /* FIXME: auditor */,
- &dh->depconf.h_wire,
- &dh->depconf.h_contract_terms,
- GNUNET_TIME_absolute_ntoh (dh->depconf.timestamp),
- GNUNET_TIME_absolute_ntoh (dh->depconf.refund_deadline),
- &amount_without_fee,
- &dh->depconf.coin_pub,
- &dh->depconf.merchant,
- exchange_pub,
- exchange_sig,
- &key_state->master_pub,
- spk->valid_from,
- spk->valid_until,
- spk->valid_legal,
- &spk->master_sig,
- &acc_confirmation_cb,
- NULL /* FIXME: context! */);
- }
-
-
- return GNUNET_OK;
-}
-
-
-/**
- * Verify that the signatures on the "403 FORBIDDEN" response from the
- * exchange demonstrating customer double-spending are valid.
- *
- * @param dh deposit handle
- * @param json json reply with the signature(s) and transaction history
- * @return #GNUNET_OK if the signature(s) is valid, #GNUNET_SYSERR if not
- */
-static int
-verify_deposit_signature_forbidden (const struct TALER_EXCHANGE_DepositHandle *dh,
- const json_t *json)
-{
- json_t *history;
- struct TALER_Amount total;
-
- history = json_object_get (json,
- "history");
- if (GNUNET_OK !=
- TALER_EXCHANGE_verify_coin_history (dh->coin_value.currency,
- &dh->depconf.coin_pub,
- history,
- &total))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_amount_add (&total,
- &total,
- &dh->amount_with_fee))
- {
- /* clearly not OK if our transaction would have caused
- the overflow... */
- return GNUNET_OK;
- }
-
- if (0 >= TALER_amount_cmp (&total,
- &dh->coin_value))
- {
- /* transaction should have still fit */
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- /* everything OK, proof of double-spending was provided */
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /deposit request.
- *
- * @param cls the `struct TALER_EXCHANGE_DepositHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_deposit_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_DepositHandle *dh = cls;
- struct TALER_ExchangeSignatureP exchange_sig;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangeSignatureP *es = NULL;
- struct TALER_ExchangePublicKeyP *ep = NULL;
- const json_t *j = response;
-
- dh->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- verify_deposit_signature_ok (dh,
- j,
- &exchange_sig,
- &exchange_pub))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- else
- {
- es = &exchange_sig;
- ep = &exchange_pub;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_FORBIDDEN:
- /* Double spending; check signatures on transaction history */
- if (GNUNET_OK !=
- verify_deposit_signature_forbidden (dh,
- j))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, exchange 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;
- }
- dh->cb (dh->cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- es,
- ep,
- j);
- TALER_EXCHANGE_deposit_cancel (dh);
-}
-
-
-/**
- * Verify signature information about the deposit.
- *
- * @param dki public key information
- * @param amount the amount to be deposited
- * @param h_wire hash of the merchant’s account details
- * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange)
- * @param coin_pub coin’s public key
- * @param denom_pub denomination key with which the coin is signed
- * @param denom_sig exchange’s unblinded signature of the coin
- * @param timestamp timestamp when the deposit was finalized
- * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests)
- * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed)
- * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s private key.
- * @return #GNUNET_OK if signatures are OK, #GNUNET_SYSERR if not
- */
-static int
-verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
- const struct TALER_Amount *amount,
- const struct GNUNET_HashCode *h_wire,
- const struct GNUNET_HashCode *h_contract_terms,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_DenominationSignature *denom_sig,
- const struct TALER_DenominationPublicKey *denom_pub,
- struct GNUNET_TIME_Absolute timestamp,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- struct GNUNET_TIME_Absolute refund_deadline,
- const struct TALER_CoinSpendSignatureP *coin_sig)
-{
- struct TALER_DepositRequestPS dr;
- struct TALER_CoinPublicInfo coin_info;
-
- dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
- dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
- dr.h_contract_terms = *h_contract_terms;
- dr.h_wire = *h_wire;
- dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
- dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
- TALER_amount_hton (&dr.amount_with_fee,
- amount);
- TALER_amount_hton (&dr.deposit_fee,
- &dki->fee_deposit);
- dr.merchant = *merchant_pub;
- dr.coin_pub = *coin_pub;
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
- &dr.purpose,
- &coin_sig->eddsa_signature,
- &coin_pub->eddsa_pub))
- {
- GNUNET_break_op (0);
- TALER_LOG_WARNING ("Invalid coin signature on /deposit request!\n");
- {
- TALER_LOG_DEBUG ("... amount_with_fee was %s\n",
- TALER_amount2s (amount));
- TALER_LOG_DEBUG ("... deposit_fee was %s\n",
- TALER_amount2s (&dki->fee_deposit));
- }
-
- return GNUNET_SYSERR;
- }
-
- /* check coin signature */
- coin_info.coin_pub = *coin_pub;
- coin_info.denom_pub = *denom_pub;
- coin_info.denom_sig = *denom_sig;
- if (GNUNET_YES !=
- TALER_test_coin_valid (&coin_info))
- {
- GNUNET_break_op (0);
- TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
- return GNUNET_SYSERR;
- }
- if (0 < TALER_amount_cmp (&dki->fee_deposit,
- amount))
- {
- GNUNET_break_op (0);
- TALER_LOG_WARNING ("Deposit amount smaller than fee\n");
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Submit a deposit permission to the exchange and get the exchange's response.
- * Note that while we return the response verbatim to the caller for
- * further processing, we do already verify that the response is
- * well-formed (i.e. that signatures included in the response are all
- * valid). If the exchange's reply is not well-formed, we return an
- * HTTP status code of zero to @a cb.
- *
- * We also verify that the @a coin_sig is valid for this deposit
- * request, and that the @a ub_sig is a valid signature for @a
- * coin_pub. Also, the @a exchange must be ready to operate (i.e. have
- * finished processing the /keys reply). If either check fails, we do
- * NOT initiate the transaction with the exchange and instead return NULL.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param amount the amount to be deposited
- * @param wire_deadline date until which the merchant would like the exchange to settle the balance (advisory, the exchange cannot be
- * forced to settle in the past or upon very short notice, but of course a well-behaved exchange will limit aggregation based on the advice received)
- * @param wire_details the merchant’s account details, in a format supported by the exchange
- * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange)
- * @param coin_pub coin’s public key
- * @param denom_pub denomination key with which the coin is signed
- * @param denom_sig exchange’s unblinded signature of the coin
- * @param timestamp timestamp when the contract was finalized, must not be too far in the future
- * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests)
- * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline
- * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s private key.
- * @param cb the callback to call when a reply for this request is available
- * @param cb_cls closure for the above callback
- * @return a handle for this request; NULL if the inputs are invalid (i.e.
- * signatures fail to verify). In this case, the callback is not called.
- */
-struct TALER_EXCHANGE_DepositHandle *
-TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute wire_deadline,
- json_t *wire_details,
- const struct GNUNET_HashCode *h_contract_terms,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_DenominationSignature *denom_sig,
- const struct TALER_DenominationPublicKey *denom_pub,
- struct GNUNET_TIME_Absolute timestamp,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- struct GNUNET_TIME_Absolute refund_deadline,
- const struct TALER_CoinSpendSignatureP *coin_sig,
- TALER_EXCHANGE_DepositResultCallback cb,
- void *cb_cls)
-{
- const struct TALER_EXCHANGE_Keys *key_state;
- const struct TALER_EXCHANGE_DenomPublicKey *dki;
- struct TALER_EXCHANGE_DepositHandle *dh;
- struct GNUNET_CURL_Context *ctx;
- json_t *deposit_obj;
- CURL *eh;
- struct GNUNET_HashCode h_wire;
- struct TALER_Amount amount_without_fee;
-
- (void) GNUNET_TIME_round_abs (&wire_deadline);
- (void) GNUNET_TIME_round_abs (&refund_deadline);
- GNUNET_assert (refund_deadline.abs_value_us <= wire_deadline.abs_value_us);
- GNUNET_assert (GNUNET_YES ==
- TEAH_handle_is_ready (exchange));
- /* initialize h_wire */
- if (GNUNET_OK !=
- TALER_JSON_merchant_wire_signature_hash (wire_details,
- &h_wire))
- {
- GNUNET_break (0);
- return NULL;
- }
- key_state = TALER_EXCHANGE_get_keys (exchange);
- dki = TALER_EXCHANGE_get_denomination_key (key_state,
- denom_pub);
- GNUNET_assert (NULL != dki);
- GNUNET_assert (GNUNET_SYSERR !=
- TALER_amount_subtract (&amount_without_fee,
- amount,
- &dki->fee_deposit));
- if (GNUNET_OK !=
- verify_signatures (dki,
- amount,
- &h_wire,
- h_contract_terms,
- coin_pub,
- denom_sig,
- denom_pub,
- timestamp,
- merchant_pub,
- refund_deadline,
- coin_sig))
- {
- GNUNET_break_op (0);
- return NULL;
- }
-
- deposit_obj = json_pack ("{s:o, s:O," /* f/wire */
- " s:o, s:o," /* H_wire, h_contract_terms */
- " s:o, s:o," /* coin_pub, denom_pub */
- " s:o, s:o," /* ub_sig, timestamp */
- " s:o," /* merchant_pub */
- " s:o, s:o," /* refund_deadline, wire_deadline */
- " s:o}", /* coin_sig */
- "contribution", TALER_JSON_from_amount (amount),
- "wire", wire_details,
- "H_wire", GNUNET_JSON_from_data_auto (&h_wire),
- "h_contract_terms", GNUNET_JSON_from_data_auto (h_contract_terms),
- "coin_pub", GNUNET_JSON_from_data_auto (coin_pub),
- "denom_pub", GNUNET_JSON_from_rsa_public_key (denom_pub->rsa_public_key),
- "ub_sig", GNUNET_JSON_from_rsa_signature (denom_sig->rsa_signature),
- "timestamp", GNUNET_JSON_from_time_abs (timestamp),
- "merchant_pub", GNUNET_JSON_from_data_auto (merchant_pub),
- "refund_deadline", GNUNET_JSON_from_time_abs (refund_deadline),
- "wire_transfer_deadline", GNUNET_JSON_from_time_abs (wire_deadline),
- "coin_sig", GNUNET_JSON_from_data_auto (coin_sig)
- );
- if (NULL == deposit_obj)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- dh = GNUNET_new (struct TALER_EXCHANGE_DepositHandle);
- dh->exchange = exchange;
- dh->cb = cb;
- dh->cb_cls = cb_cls;
- dh->url = TEAH_path_to_url (exchange, "/deposit");
- dh->depconf.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
- dh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT);
- dh->depconf.h_contract_terms = *h_contract_terms;
- dh->depconf.h_wire = h_wire;
- dh->depconf.timestamp = GNUNET_TIME_absolute_hton (timestamp);
- dh->depconf.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
- TALER_amount_hton (&dh->depconf.amount_without_fee,
- &amount_without_fee);
- dh->depconf.coin_pub = *coin_pub;
- dh->depconf.merchant = *merchant_pub;
- dh->amount_with_fee = *amount;
- dh->coin_value = dki->value;
-
- eh = TEL_curl_easy_get (dh->url);
- GNUNET_assert (NULL != (dh->json_enc =
- json_dumps (deposit_obj,
- JSON_COMPACT)));
- json_decref (deposit_obj);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "URL for deposit: `%s'\n",
- dh->url);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- dh->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (dh->json_enc)));
- ctx = TEAH_handle_to_context (exchange);
- dh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_deposit_finished,
- dh);
- return dh;
-}
-
-
-/**
- * Cancel a deposit permission request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param deposit the deposit permission request handle
- */
-void
-TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit)
-{
- if (NULL != deposit->job)
- {
- GNUNET_CURL_job_cancel (deposit->job);
- deposit->job = NULL;
- }
- GNUNET_free (deposit->url);
- GNUNET_free (deposit->json_enc);
- GNUNET_free (deposit);
-}
-
-
-/* end of exchange_api_deposit.c */
diff --git a/src/exchange-lib/exchange_api_handle.c b/src/exchange-lib/exchange_api_handle.c
deleted file mode 100644
index afaabd85b..000000000
--- a/src/exchange-lib/exchange_api_handle.c
+++ /dev/null
@@ -1,1779 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/exchange_api_handle.c
- * @brief Implementation of the "handle" component of the exchange's HTTP API
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <microhttpd.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_json_lib.h"
-#include "taler_exchange_service.h"
-#include "taler_auditor_service.h"
-#include "taler_signatures.h"
-#include "exchange_api_handle.h"
-#include "curl_defaults.h"
-#include "backoff.h"
-
-/**
- * Which revision of the Taler protocol is implemented
- * by this library? Used to determine compatibility.
- */
-#define TALER_PROTOCOL_CURRENT 2
-
-/**
- * How many revisions back are we compatible to?
- */
-#define TALER_PROTOCOL_AGE 0
-
-/**
- * Current version for (local) JSON serialization of persisted
- * /keys data.
- */
-#define TALER_SERIALIZATION_FORMAT_VERSION 0
-
-
-/**
- * Log error related to CURL operations.
- *
- * @param type log level
- * @param function which function failed to run
- * @param code what was the curl error code
- */
-#define CURL_STRERROR(type, function, code) \
- GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \
- function, __FILE__, __LINE__, curl_easy_strerror (code));
-
-/**
- * Stages of initialization for the `struct TALER_EXCHANGE_Handle`
- */
-enum ExchangeHandleState
-{
- /**
- * Just allocated.
- */
- MHS_INIT = 0,
-
- /**
- * Obtained the exchange's certification data and keys.
- */
- MHS_CERT = 1,
-
- /**
- * Failed to initialize (fatal).
- */
- MHS_FAILED = 2
-};
-
-
-/**
- * Data for the request to get the /keys of a exchange.
- */
-struct KeysRequest;
-
-
-/**
- * Entry in list of ongoing interactions with an auditor.
- */
-struct AuditorInteractionEntry
-{
- /**
- * DLL entry.
- */
- struct AuditorInteractionEntry *next;
-
- /**
- * DLL entry.
- */
- struct AuditorInteractionEntry *prev;
-
- /**
- * Interaction state.
- */
- struct TALER_AUDITOR_DepositConfirmationHandle *dch;
-};
-
-
-/**
- * Entry in DLL of auditors used by an exchange.
- */
-struct AuditorListEntry
-{
- /**
- * Next pointer of DLL.
- */
- struct AuditorListEntry *next;
-
- /**
- * Prev pointer of DLL.
- */
- struct AuditorListEntry *prev;
-
- /**
- * Base URL of the auditor.
- */
- const char *auditor_url;
-
- /**
- * Handle to the auditor.
- */
- struct TALER_AUDITOR_Handle *ah;
-
- /**
- * Head of DLL of interactions with this auditor.
- */
- struct AuditorInteractionEntry *ai_head;
-
- /**
- * Tail of DLL of interactions with this auditor.
- */
- struct AuditorInteractionEntry *ai_tail;
-
- /**
- * Public key of the auditor.
- */
- struct TALER_AuditorPublicKeyP auditor_pub;
-
- /**
- * Flag indicating that the auditor is available and that protocol
- * version compatibility is given.
- */
- int is_up;
-
-};
-
-
-/**
- * Handle to the exchange
- */
-struct TALER_EXCHANGE_Handle
-{
- /**
- * The context of this handle
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * The URL of the exchange (i.e. "http://exchange.taler.net/")
- */
- char *url;
-
- /**
- * Function to call with the exchange's certification data,
- * NULL if this has already been done.
- */
- TALER_EXCHANGE_CertificationCallback cert_cb;
-
- /**
- * Closure to pass to @e cert_cb.
- */
- void *cert_cb_cls;
-
- /**
- * Data for the request to get the /keys of a exchange,
- * NULL once we are past stage #MHS_INIT.
- */
- struct KeysRequest *kr;
-
- /**
- * Task for retrying /keys request.
- */
- struct GNUNET_SCHEDULER_Task *retry_task;
-
- /**
- * Raw key data of the exchange, only valid if
- * @e handshake_complete is past stage #MHS_CERT.
- */
- json_t *key_data_raw;
-
- /**
- * Head of DLL of auditors of this exchange.
- */
- struct AuditorListEntry *auditors_head;
-
- /**
- * Tail of DLL of auditors of this exchange.
- */
- struct AuditorListEntry *auditors_tail;
-
- /**
- * Key data of the exchange, only valid if
- * @e handshake_complete is past stage #MHS_CERT.
- */
- struct TALER_EXCHANGE_Keys key_data;
-
- /**
- * Retry /keys frequency.
- */
- struct GNUNET_TIME_Relative retry_delay;
-
- /**
- * When does @e key_data expire?
- */
- struct GNUNET_TIME_Absolute key_data_expiration;
-
- /**
- * Stage of the exchange's initialization routines.
- */
- enum ExchangeHandleState state;
-
-};
-
-
-/* ***************** Internal /keys fetching ************* */
-
-/**
- * Data for the request to get the /keys of a exchange.
- */
-struct KeysRequest
-{
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this handle
- */
- char *url;
-
- /**
- * Entry for this request with the `struct GNUNET_CURL_Context`.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Expiration time according to "Expire:" header.
- * 0 if not provided by the server.
- */
- struct GNUNET_TIME_Absolute expire;
-
-};
-
-
-/**
- * Iterate over all available auditors for @a h, calling
- * @param ah and giving it a chance to start a deposit
- * confirmation interaction.
- *
- * @param h exchange to go over auditors for
- * @param ac function to call per auditor
- * @param ac_cls closure for @a ac
- */
-void
-TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Handle *h,
- TEAH_AuditorCallback ac,
- void *ac_cls)
-{
- // FIXME!
-}
-
-
-/**
- * Release memory occupied by a keys request.
- * Note that this does not cancel the request
- * itself.
- *
- * @param kr request to free
- */
-static void
-free_keys_request (struct KeysRequest *kr)
-{
- GNUNET_free (kr->url);
- GNUNET_free (kr);
-}
-
-
-#define EXITIF(cond) \
- do { \
- if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
- } while (0)
-
-
-/**
- * Parse a exchange's signing key encoded in JSON.
- *
- * @param[out] sign_key where to return the result
- * @param check_sigs should we check signatures?
- * @param[in] sign_key_obj json to parse
- * @param master_key master key to use to verify signature
- * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
- * invalid or the json malformed.
- */
-static int
-parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey *sign_key,
- int check_sigs,
- json_t *sign_key_obj,
- const struct TALER_MasterPublicKeyP *master_key)
-{
- struct TALER_ExchangeSigningKeyValidityPS sign_key_issue;
- struct TALER_MasterSignatureP sign_key_issue_sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("master_sig",
- &sign_key_issue_sig),
- GNUNET_JSON_spec_fixed_auto ("key",
- &sign_key->key),
- GNUNET_JSON_spec_absolute_time ("stamp_start",
- &sign_key->valid_from),
- GNUNET_JSON_spec_absolute_time ("stamp_expire",
- &sign_key->valid_until),
- GNUNET_JSON_spec_absolute_time ("stamp_end",
- &sign_key->valid_legal),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (sign_key_obj,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- if (! check_sigs)
- return GNUNET_OK;
- sign_key_issue.signkey_pub = sign_key->key;
- sign_key_issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY);
- sign_key_issue.purpose.size = htonl (sizeof (struct TALER_ExchangeSigningKeyValidityPS));
- sign_key_issue.master_public_key = *master_key;
- sign_key_issue.start = GNUNET_TIME_absolute_hton (sign_key->valid_from);
- sign_key_issue.expire = GNUNET_TIME_absolute_hton (sign_key->valid_until);
- sign_key_issue.end = GNUNET_TIME_absolute_hton (sign_key->valid_legal);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY,
- &sign_key_issue.purpose,
- &sign_key_issue_sig.eddsa_signature,
- &master_key->eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- sign_key->master_sig = sign_key_issue_sig;
- return GNUNET_OK;
-}
-
-
-/**
- * Parse a exchange's denomination key encoded in JSON.
- *
- * @param[out] denom_key where to return the result
- * @param check_sigs should we check signatures?
- * @param[in] denom_key_obj json to parse
- * @param master_key master key to use to verify signature
- * @param hash_context where to accumulate data for signature verification
- * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
- * invalid or the json malformed.
- */
-static int
-parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
- int check_sigs,
- json_t *denom_key_obj,
- struct TALER_MasterPublicKeyP *master_key,
- struct GNUNET_HashContext *hash_context)
-{
- struct TALER_DenominationKeyValidityPS denom_key_issue;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("master_sig",
- &denom_key->master_sig),
- GNUNET_JSON_spec_absolute_time ("stamp_expire_deposit",
- &denom_key->expire_deposit),
- GNUNET_JSON_spec_absolute_time ("stamp_expire_withdraw",
- &denom_key->withdraw_valid_until),
- GNUNET_JSON_spec_absolute_time ("stamp_start",
- &denom_key->valid_from),
- GNUNET_JSON_spec_absolute_time ("stamp_expire_legal",
- &denom_key->expire_legal),
- TALER_JSON_spec_amount ("value",
- &denom_key->value),
- TALER_JSON_spec_amount ("fee_withdraw",
- &denom_key->fee_withdraw),
- TALER_JSON_spec_amount ("fee_deposit",
- &denom_key->fee_deposit),
- TALER_JSON_spec_amount ("fee_refresh",
- &denom_key->fee_refresh),
- TALER_JSON_spec_amount ("fee_refund",
- &denom_key->fee_refund),
- GNUNET_JSON_spec_rsa_public_key ("denom_pub",
- &denom_key->key.rsa_public_key),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (denom_key_obj,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- GNUNET_CRYPTO_rsa_public_key_hash (denom_key->key.rsa_public_key,
- &denom_key->h_key);
- if (! check_sigs)
- return GNUNET_OK;
- memset (&denom_key_issue,
- 0,
- sizeof (denom_key_issue));
- denom_key_issue.purpose.purpose
- = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY);
- denom_key_issue.purpose.size
- = htonl (sizeof (struct TALER_DenominationKeyValidityPS));
- denom_key_issue.master = *master_key;
- denom_key_issue.denom_hash = denom_key->h_key;
- denom_key_issue.start = GNUNET_TIME_absolute_hton (denom_key->valid_from);
- denom_key_issue.expire_withdraw = GNUNET_TIME_absolute_hton (denom_key->withdraw_valid_until);
- denom_key_issue.expire_deposit = GNUNET_TIME_absolute_hton (denom_key->expire_deposit);
- denom_key_issue.expire_legal = GNUNET_TIME_absolute_hton (denom_key->expire_legal);
- TALER_amount_hton (&denom_key_issue.value,
- &denom_key->value);
- TALER_amount_hton (&denom_key_issue.fee_withdraw,
- &denom_key->fee_withdraw);
- TALER_amount_hton (&denom_key_issue.fee_deposit,
- &denom_key->fee_deposit);
- TALER_amount_hton (&denom_key_issue.fee_refresh,
- &denom_key->fee_refresh);
- TALER_amount_hton (&denom_key_issue.fee_refund,
- &denom_key->fee_refund);
- EXITIF (GNUNET_SYSERR ==
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY,
- &denom_key_issue.purpose,
- &denom_key->master_sig.eddsa_signature,
- &master_key->eddsa_pub));
- GNUNET_CRYPTO_hash_context_read (hash_context,
- &denom_key_issue.denom_hash,
- sizeof (struct GNUNET_HashCode));
- return GNUNET_OK;
-
- EXITIF_exit:
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Parse a exchange's auditor information encoded in JSON.
- *
- * @param[out] auditor where to return the result
- * @param check_sig should we check signatures
- * @param[in] auditor_obj json to parse
- * @param key_data information about denomination keys
- * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
- * invalid or the json malformed.
- */
-static int
-parse_json_auditor (struct TALER_EXCHANGE_AuditorInformation *auditor,
- int check_sigs,
- json_t *auditor_obj,
- const struct TALER_EXCHANGE_Keys *key_data)
-{
- json_t *keys;
- json_t *key;
- unsigned int len;
- unsigned int off;
- unsigned int i;
- const char *auditor_url;
- struct TALER_ExchangeKeyValidityPS kv;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("auditor_pub",
- &auditor->auditor_pub),
- GNUNET_JSON_spec_string ("auditor_url",
- &auditor_url),
- GNUNET_JSON_spec_json ("denomination_keys",
- &keys),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (auditor_obj,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- auditor->auditor_url = GNUNET_strdup (auditor_url);
- kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS);
- kv.purpose.size = htonl (sizeof (struct TALER_ExchangeKeyValidityPS));
- GNUNET_CRYPTO_hash (auditor_url,
- strlen (auditor_url) + 1,
- &kv.auditor_url_hash);
- kv.master = key_data->master_pub;
- len = json_array_size (keys);
- auditor->denom_keys = GNUNET_new_array (len,
- struct TALER_EXCHANGE_AuditorDenominationInfo);
- i = 0;
- off = 0;
- json_array_foreach (keys, i, key) {
- struct TALER_AuditorSignatureP auditor_sig;
- struct GNUNET_HashCode denom_h;
- const struct TALER_EXCHANGE_DenomPublicKey *dk;
- unsigned int dk_off;
- struct GNUNET_JSON_Specification kspec[] = {
- GNUNET_JSON_spec_fixed_auto ("auditor_sig",
- &auditor_sig),
- GNUNET_JSON_spec_fixed_auto ("denom_pub_h",
- &denom_h),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (key,
- kspec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- continue;
- }
- dk = NULL;
- dk_off = UINT_MAX;
- for (unsigned int j=0;j<key_data->num_denom_keys;j++)
- {
- if (0 == memcmp (&denom_h,
- &key_data->denom_keys[j].h_key,
- sizeof (struct GNUNET_HashCode)))
- {
- dk = &key_data->denom_keys[j];
- dk_off = j;
- break;
- }
- }
- if (NULL == dk)
- {
- GNUNET_break_op (0);
- continue;
- }
- if (check_sigs)
- {
- kv.start = GNUNET_TIME_absolute_hton (dk->valid_from);
- kv.expire_withdraw = GNUNET_TIME_absolute_hton (dk->withdraw_valid_until);
- kv.expire_deposit = GNUNET_TIME_absolute_hton (dk->expire_deposit);
- kv.expire_legal = GNUNET_TIME_absolute_hton (dk->expire_legal);
- TALER_amount_hton (&kv.value,
- &dk->value);
- TALER_amount_hton (&kv.fee_withdraw,
- &dk->fee_withdraw);
- TALER_amount_hton (&kv.fee_deposit,
- &dk->fee_deposit);
- TALER_amount_hton (&kv.fee_refresh,
- &dk->fee_refresh);
- TALER_amount_hton (&kv.fee_refund,
- &dk->fee_refund);
- kv.denom_hash = dk->h_key;
-
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS,
- &kv.purpose,
- &auditor_sig.eddsa_sig,
- &auditor->auditor_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- }
- auditor->denom_keys[off].denom_key_offset = dk_off;
- auditor->denom_keys[off].auditor_sig = auditor_sig;
- off++;
- }
- auditor->num_denom_keys = off;
- GNUNET_JSON_parse_free (spec);
- return GNUNET_OK;
-}
-
-
-/**
- * Decode the JSON in @a resp_obj from the /keys response
- * and store the data in the @a key_data.
- *
- * @param[in] resp_obj JSON object to parse
- * @param check_sig #GNUNET_YES if we should check the signature
- * @param[out] key_data where to store the results we decoded
- * @param[out] where to store version compatibility data
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- * (malformed JSON)
- */
-static int
-decode_keys_json (const json_t *resp_obj,
- int check_sig,
- struct TALER_EXCHANGE_Keys *key_data,
- enum TALER_EXCHANGE_VersionCompatibility *vc)
-{
- struct TALER_ExchangeSignatureP sig;
- struct GNUNET_HashContext *hash_context;
- struct TALER_ExchangePublicKeyP pub;
- unsigned int age;
- unsigned int revision;
- unsigned int current;
- struct GNUNET_JSON_Specification mspec[] = {
- GNUNET_JSON_spec_fixed_auto ("eddsa_sig",
- &sig),
- GNUNET_JSON_spec_fixed_auto ("eddsa_pub",
- &pub),
- /* sig and pub must be first, as we skip those if
- check_sig is false! */
- GNUNET_JSON_spec_fixed_auto ("master_public_key",
- &key_data->master_pub),
- GNUNET_JSON_spec_absolute_time ("list_issue_date",
- &key_data->list_issue_date),
- GNUNET_JSON_spec_relative_time
- ("reserve_closing_delay",
- &key_data->reserve_closing_delay),
- GNUNET_JSON_spec_end()
- };
-
- if (JSON_OBJECT != json_typeof (resp_obj))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* check the version */
- {
- const char *ver;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("version",
- &ver),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (resp_obj,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (3 != sscanf (ver,
- "%u:%u:%u",
- &current,
- &revision,
- &age))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- *vc = TALER_EXCHANGE_VC_MATCH;
- if (TALER_PROTOCOL_CURRENT < current)
- {
- *vc |= TALER_EXCHANGE_VC_NEWER;
- if (TALER_PROTOCOL_CURRENT < current - age)
- *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE;
- }
- if (TALER_PROTOCOL_CURRENT > current)
- {
- *vc |= TALER_EXCHANGE_VC_OLDER;
- if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current)
- *vc |= TALER_EXCHANGE_VC_INCOMPATIBLE;
- }
- key_data->version = GNUNET_strdup (ver);
- }
-
- hash_context = NULL;
- EXITIF (GNUNET_OK !=
- GNUNET_JSON_parse (resp_obj,
- (check_sig) ? mspec : &mspec[2],
- NULL, NULL));
-
- /* parse the master public key and issue date of the response */
- if (check_sig)
- hash_context = GNUNET_CRYPTO_hash_context_start ();
-
- /* parse the signing keys */
- {
- json_t *sign_keys_array;
- json_t *sign_key_obj;
- unsigned int index;
-
- EXITIF (NULL == (sign_keys_array =
- json_object_get (resp_obj,
- "signkeys")));
- EXITIF (JSON_ARRAY != json_typeof (sign_keys_array));
- EXITIF (0 == (key_data->num_sign_keys =
- json_array_size (sign_keys_array)));
- key_data->sign_keys
- = GNUNET_new_array (key_data->num_sign_keys,
- struct TALER_EXCHANGE_SigningPublicKey);
- index = 0;
- json_array_foreach (sign_keys_array, index, sign_key_obj) {
- EXITIF (GNUNET_SYSERR ==
- parse_json_signkey (&key_data->sign_keys[index],
- check_sig,
- sign_key_obj,
- &key_data->master_pub));
- }
- }
-
- /* parse the denomination keys, merging with the
- possibly EXISTING array as required (/keys cherry picking) */
- {
- json_t *denom_keys_array;
- json_t *denom_key_obj;
- unsigned int index;
-
- EXITIF (NULL == (denom_keys_array =
- json_object_get (resp_obj,
- "denoms")));
- EXITIF (JSON_ARRAY != json_typeof (denom_keys_array));
-
- index = 0;
- json_array_foreach (denom_keys_array, index, denom_key_obj) {
- struct TALER_EXCHANGE_DenomPublicKey dk;
- bool found = false;
-
- EXITIF (GNUNET_SYSERR ==
- parse_json_denomkey (&dk,
- check_sig,
- denom_key_obj,
- &key_data->master_pub,
- hash_context));
- for (unsigned int j=0;j<key_data->num_denom_keys;j++)
- {
- if (0 == memcmp (&dk,
- &key_data->denom_keys[j],
- sizeof (dk)))
- {
- found = true;
- break;
- }
- }
- if (found)
- {
- /* 0:0:0 did not support /keys cherry picking */
- GNUNET_break_op (0 == current);
- continue;
- }
- if (key_data->denom_keys_size == key_data->num_denom_keys)
- GNUNET_array_grow (key_data->denom_keys,
- key_data->denom_keys_size,
- key_data->denom_keys_size * 2 + 2);
- key_data->denom_keys[key_data->num_denom_keys++] = dk;
-
- /* Update "last_denom_issue_date" */
- TALER_LOG_DEBUG ("Crawling DK 'valid_from': %s\n",
- GNUNET_STRINGS_absolute_time_to_string (dk.valid_from));
- key_data->last_denom_issue_date
- = GNUNET_TIME_absolute_max (key_data->last_denom_issue_date,
- dk.valid_from);
- };
- }
- /* parse the auditor information */
- {
- json_t *auditors_array;
- json_t *auditor_info;
- unsigned int index;
-
- EXITIF (NULL == (auditors_array =
- json_object_get (resp_obj,
- "auditors")));
- EXITIF (JSON_ARRAY != json_typeof (auditors_array));
-
- /* Merge with the existing auditor information we have (/keys cherry picking) */
- index = 0;
- json_array_foreach (auditors_array, index, auditor_info) {
- struct TALER_EXCHANGE_AuditorInformation ai;
- bool found = false;
-
- memset (&ai,
- 0,
- sizeof (ai));
- EXITIF (GNUNET_SYSERR ==
- parse_json_auditor (&ai,
- check_sig,
- auditor_info,
- key_data));
- for (unsigned int j=0;j<key_data->num_auditors;j++)
- {
- struct TALER_EXCHANGE_AuditorInformation *aix = &key_data->auditors[j];
-
- if (0 == memcmp (&ai.auditor_pub,
- &aix->auditor_pub,
- sizeof (struct TALER_AuditorPublicKeyP)))
- {
- found = true;
- /* Merge denomination key signatures of downloaded /keys into existing
- auditor information 'aix'. */
- GNUNET_array_grow (aix->denom_keys,
- aix->num_denom_keys,
- aix->num_denom_keys + ai.num_denom_keys);
- memcpy (&aix->denom_keys[aix->num_denom_keys - ai.num_denom_keys],
- ai.denom_keys,
- ai.num_denom_keys * sizeof (struct TALER_EXCHANGE_AuditorDenominationInfo));
- break;
- }
- }
- if (found)
- continue; /* we are done */
- if (key_data->auditors_size == key_data->num_auditors)
- GNUNET_array_grow (key_data->auditors,
- key_data->auditors_size,
- key_data->auditors_size * 2 + 2);
- key_data->auditors[key_data->num_auditors++] = ai;
- };
- }
-
- if (check_sig)
- {
- struct TALER_ExchangeKeySetPS ks;
-
- /* Validate signature... */
- ks.purpose.size = htonl (sizeof (ks));
- ks.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET);
- ks.list_issue_date = GNUNET_TIME_absolute_hton (key_data->list_issue_date);
- GNUNET_CRYPTO_hash_context_finish (hash_context,
- &ks.hc);
- hash_context = NULL;
- EXITIF (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (key_data,
- &pub));
- EXITIF (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_KEY_SET,
- &ks.purpose,
- &sig.eddsa_signature,
- &pub.eddsa_pub));
- }
- return GNUNET_OK;
- EXITIF_exit:
-
- if (NULL != hash_context)
- GNUNET_CRYPTO_hash_context_abort (hash_context);
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Free key data object.
- *
- * @param key_data data to free (pointer itself excluded)
- */
-static void
-free_key_data (struct TALER_EXCHANGE_Keys *key_data)
-{
- GNUNET_array_grow (key_data->sign_keys,
- key_data->num_sign_keys,
- 0);
- for (unsigned int i=0;i<key_data->num_denom_keys;i++)
- GNUNET_CRYPTO_rsa_public_key_free (key_data->denom_keys[i].key.rsa_public_key);
-
- GNUNET_array_grow (key_data->denom_keys,
- key_data->denom_keys_size,
- 0);
- for (unsigned int i=0;i<key_data->num_auditors;i++)
- {
- GNUNET_array_grow (key_data->auditors[i].denom_keys,
- key_data->auditors[i].num_denom_keys,
- 0);
- GNUNET_free (key_data->auditors[i].auditor_url);
- }
- GNUNET_array_grow (key_data->auditors,
- key_data->auditors_size,
- 0);
- GNUNET_free_non_null (key_data->version);
- key_data->version = NULL;
-}
-
-
-/**
- * Initiate download of /keys from the exchange.
- *
- * @param cls exchange where to download /keys from
- */
-static void
-request_keys (void *cls);
-
-
-/**
- * Check if our current response for /keys is valid, and if
- * not trigger download.
- *
- * @param exchange exchange to check keys for
- * @param force_download #GNUNET_YES to force download even if /keys is still valid
- * @return until when the response is current, 0 if we are re-downloading
- */
-struct GNUNET_TIME_Absolute
-TALER_EXCHANGE_check_keys_current (struct TALER_EXCHANGE_Handle *exchange,
- int force_download)
-{
- if (NULL != exchange->kr)
- return GNUNET_TIME_UNIT_ZERO_ABS;
- if ( (GNUNET_NO == force_download) &&
- (0 < GNUNET_TIME_absolute_get_remaining (exchange->key_data_expiration).rel_value_us) )
- return exchange->key_data_expiration;
- if (NULL == exchange->retry_task)
- exchange->retry_task = GNUNET_SCHEDULER_add_now (&request_keys,
- exchange);
- return GNUNET_TIME_UNIT_ZERO_ABS;
-}
-
-
-/**
- * Callback used when downloading the reply to a /keys request
- * is complete.
- *
- * @param cls the `struct KeysRequest`
- * @param response_code HTTP response code, 0 on error
- * @param resp_obj parsed JSON result, NULL on error
- */
-static void
-keys_completed_cb (void *cls,
- long response_code,
- const void *resp_obj)
-{
- struct KeysRequest *kr = cls;
- struct TALER_EXCHANGE_Handle *exchange = kr->exchange;
- struct TALER_EXCHANGE_Keys kd;
- struct TALER_EXCHANGE_Keys kd_old;
- enum TALER_EXCHANGE_VersionCompatibility vc;
- const json_t *j = resp_obj;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Received keys from URL `%s' with status %ld.\n",
- kr->url,
- response_code);
- kd_old = exchange->key_data;
- memset (&kd,
- 0,
- sizeof (struct TALER_EXCHANGE_Keys));
- vc = TALER_EXCHANGE_VC_PROTOCOL_ERROR;
- switch (response_code)
- {
- case 0:
- free_keys_request (kr);
- exchange->kr = NULL;
- GNUNET_assert (NULL == exchange->retry_task);
- exchange->retry_delay = EXCHANGE_LIB_BACKOFF (exchange->retry_delay);
- exchange->retry_task = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay,
- &request_keys,
- exchange);
- return;
- case MHD_HTTP_OK:
- if (NULL == j)
- {
- response_code = 0;
- break;
- }
- /* We keep the denomination keys and auditor signatures from the
- previous iteration (/keys cherry picking) */
- kd.num_denom_keys = kd_old.num_denom_keys;
- kd.last_denom_issue_date = kd_old.last_denom_issue_date;
- GNUNET_array_grow (kd.denom_keys,
- kd.denom_keys_size,
- kd.num_denom_keys);
-
- /* First make a shallow copy, we then need another pass for the RSA key... */
- memcpy (kd.denom_keys,
- kd_old.denom_keys,
- kd_old.num_denom_keys * sizeof (struct TALER_EXCHANGE_DenomPublicKey));
- for (unsigned int i=0;i<kd_old.num_denom_keys;i++)
- kd.denom_keys[i].key.rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_dup (kd_old.denom_keys[i].key.rsa_public_key);
-
- kd.num_auditors = kd_old.num_auditors;
- kd.auditors = GNUNET_new_array (kd.num_auditors,
- struct TALER_EXCHANGE_AuditorInformation);
- /* Now the necessary deep copy... */
- for (unsigned int i=0;i<kd_old.num_auditors;i++)
- {
- const struct TALER_EXCHANGE_AuditorInformation *aold = &kd_old.auditors[i];
- struct TALER_EXCHANGE_AuditorInformation *anew = &kd.auditors[i];
-
- anew->auditor_pub = aold->auditor_pub;
- anew->auditor_url = GNUNET_strdup (aold->auditor_url);
- GNUNET_array_grow (anew->denom_keys,
- anew->num_denom_keys,
- aold->num_denom_keys);
- memcpy (anew->denom_keys,
- aold->denom_keys,
- aold->num_denom_keys * sizeof (struct TALER_EXCHANGE_AuditorDenominationInfo));
- }
-
- if (GNUNET_OK !=
- decode_keys_json (j,
- GNUNET_YES,
- &kd,
- &vc))
- {
- TALER_LOG_ERROR ("Could not decode /keys response\n");
- response_code = 0;
- for (unsigned int i=0;i<kd.num_auditors;i++)
- {
- struct TALER_EXCHANGE_AuditorInformation *anew = &kd.auditors[i];
-
- GNUNET_array_grow (anew->denom_keys,
- anew->num_denom_keys,
- 0);
- GNUNET_free (anew->auditor_url);
- }
- GNUNET_free (kd.auditors);
- kd.auditors = NULL;
- kd.num_auditors = 0;
- for (unsigned int i=0;i<kd_old.num_denom_keys;i++)
- GNUNET_CRYPTO_rsa_public_key_free (kd.denom_keys[i].key.rsa_public_key);
- GNUNET_array_grow (kd.denom_keys,
- kd.denom_keys_size,
- 0);
- kd.num_denom_keys = 0;
- break;
- }
- json_decref (exchange->key_data_raw);
- exchange->key_data_raw = json_deep_copy (j);
- exchange->retry_delay = GNUNET_TIME_UNIT_ZERO;
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- break;
- }
- exchange->key_data = kd;
- TALER_LOG_DEBUG ("Last DK issue date update to: %s\n",
- GNUNET_STRINGS_absolute_time_to_string
- (exchange->key_data.last_denom_issue_date));
-
-
- if (MHD_HTTP_OK != response_code)
- {
- exchange->kr = NULL;
- free_keys_request (kr);
- exchange->state = MHS_FAILED;
- if (NULL != exchange->key_data_raw)
- {
- json_decref (exchange->key_data_raw);
- exchange->key_data_raw = NULL;
- }
- free_key_data (&kd_old);
- /* notify application that we failed */
- exchange->cert_cb (exchange->cert_cb_cls,
- NULL,
- vc);
- return;
- }
-
- exchange->kr = NULL;
- exchange->key_data_expiration = kr->expire;
- free_keys_request (kr);
- exchange->state = MHS_CERT;
- /* notify application about the key information */
- exchange->cert_cb (exchange->cert_cb_cls,
- &exchange->key_data,
- vc);
- free_key_data (&kd_old);
-}
-
-
-/* ********************* library internal API ********* */
-
-
-/**
- * Get the context of a exchange.
- *
- * @param h the exchange handle to query
- * @return ctx context to execute jobs in
- */
-struct GNUNET_CURL_Context *
-TEAH_handle_to_context (struct TALER_EXCHANGE_Handle *h)
-{
- return h->ctx;
-}
-
-
-/**
- * Check if the handle is ready to process requests.
- *
- * @param h the exchange handle to query
- * @return #GNUNET_YES if we are ready, #GNUNET_NO if not
- */
-int
-TEAH_handle_is_ready (struct TALER_EXCHANGE_Handle *h)
-{
- return (MHS_CERT == h->state) ? GNUNET_YES : GNUNET_NO;
-}
-
-
-/**
- * Obtain the URL to use for an API request.
- *
- * @param h handle for the exchange
- * @param path Taler API path (i.e. "/reserve/withdraw")
- * @return the full URL to use with cURL
- */
-char *
-TEAH_path_to_url (struct TALER_EXCHANGE_Handle *h,
- const char *path)
-{
- return TEAH_path_to_url2 (h->url,
- path);
-}
-
-
-/**
- * Obtain the URL to use for an API request.
- *
- * @param base_url base URL of the exchange (i.e. "http://exchange/")
- * @param path Taler API path (i.e. "/reserve/withdraw")
- * @return the full URL to use with cURL
- */
-char *
-TEAH_path_to_url2 (const char *base_url,
- const char *path)
-{
- char *url;
-
- if ( ('/' == path[0]) &&
- (0 < strlen (base_url)) &&
- ('/' == base_url[strlen (base_url) - 1]) )
- path++; /* avoid generating URL with "//" from concat */
- GNUNET_asprintf (&url,
- "%s%s",
- base_url,
- path);
- return url;
-}
-
-
-/**
- * Parse HTTP timestamp.
- *
- * @param date header to parse header
- * @param at where to write the result
- * @return #GNUNET_OK on success
- */
-static int
-parse_date_string (const char *date,
- struct GNUNET_TIME_Absolute *at)
-{
- struct tm now;
- time_t t;
- const char *end;
-
- memset (&now,
- 0,
- sizeof (now));
- end = strptime (date,
- "%a, %d %b %Y %H:%M:%S %Z", /* RFC-1123 standard spec */
- &now);
- if ( (NULL == end) ||
- ( (*end != '\n') &&
- (*end != '\r') ) )
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- t = mktime (&now);
- if (((time_t) -1) == t)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
- "mktime");
- return GNUNET_SYSERR;
- }
- if (t < 0)
- t = 0; /* can happen due to timezone issues if date was 1.1.1970 */
- at->abs_value_us = 1000LL * 1000LL * t;
- return GNUNET_OK;
-}
-
-
-/**
- * Function called for each header in the HTTP /keys response.
- * Finds the "Expire:" header and parses it, storing the result
- * in the "expire" field fo the keys request.
- *
- * @param buffer header data received
- * @param size size of an item in @a buffer
- * @param nitems number of items in @a buffer
- * @param userdata the `struct KeysRequest`
- * @return `size * nitems` on success (everything else aborts)
- */
-static size_t
-header_cb (char *buffer,
- size_t size,
- size_t nitems,
- void *userdata)
-{
- struct KeysRequest *kr = userdata;
- size_t total = size * nitems;
- char *val;
-
- if (total < strlen (MHD_HTTP_HEADER_EXPIRES ": "))
- return total;
- if (0 != strncasecmp (MHD_HTTP_HEADER_EXPIRES ": ",
- buffer,
- strlen (MHD_HTTP_HEADER_EXPIRES ": ")))
- return total;
- val = GNUNET_strndup (&buffer[strlen (MHD_HTTP_HEADER_EXPIRES ": ")],
- total - strlen (MHD_HTTP_HEADER_EXPIRES ": "));
- if (GNUNET_OK !=
- parse_date_string (val,
- &kr->expire))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to parse %s-header `%s'\n",
- MHD_HTTP_HEADER_EXPIRES,
- val);
- kr->expire = GNUNET_TIME_UNIT_ZERO_ABS;
- }
- GNUNET_free (val);
- return total;
-}
-
-
-/* ********************* public API ******************* */
-
-
-/**
- * Deserialize the key data and use it to bootstrap @a exchange to
- * more efficiently recover the state. Errors in @a data must be
- * tolerated (i.e. by re-downloading instead).
- *
- * @param exchange which exchange's key and wire data should be deserialized
- * @return data the data to deserialize
- */
-static void
-deserialize_data (struct TALER_EXCHANGE_Handle *exchange,
- const json_t *data)
-{
- enum TALER_EXCHANGE_VersionCompatibility vc;
- json_t *keys;
- const char *url;
- uint32_t version;
- struct GNUNET_TIME_Absolute expire;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint32 ("version",
- &version),
- GNUNET_JSON_spec_json ("keys",
- &keys),
- GNUNET_JSON_spec_string ("url",
- &url),
- GNUNET_JSON_spec_absolute_time ("expire",
- &expire),
- GNUNET_JSON_spec_end()
- };
- struct TALER_EXCHANGE_Keys key_data;
-
- if (NULL == data)
- return;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (data,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return;
- }
- if (0 != version)
- return; /* unsupported version */
- if (0 != strcmp (url,
- exchange->url))
- {
- GNUNET_break (0);
- return;
- }
- memset (&key_data,
- 0,
- sizeof (struct TALER_EXCHANGE_Keys));
- if (GNUNET_OK !=
- decode_keys_json (keys,
- GNUNET_NO,
- &key_data,
- &vc))
- {
- GNUNET_break (0);
- return;
- }
- /* decode successful, initialize with the result */
- GNUNET_assert (NULL == exchange->key_data_raw);
- exchange->key_data_raw = json_deep_copy (keys);
- exchange->key_data = key_data;
- exchange->key_data_expiration = expire;
- exchange->state = MHS_CERT;
- /* notify application about the key information */
- exchange->cert_cb (exchange->cert_cb_cls,
- &exchange->key_data,
- vc);
-}
-
-
-/**
- * Serialize the latest key data from @a exchange to be persisted on
- * disk (to be used with #TALER_EXCHANGE_OPTION_DATA to more
- * efficiently recover the state).
- *
- * @param exchange which exchange's key and wire data should be
- * serialized
- * @return NULL on error (i.e. no current data available);
- * otherwise JSON object owned by the caller
- */
-json_t *
-TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange)
-{
- const struct TALER_EXCHANGE_Keys *kd = &exchange->key_data;
- struct GNUNET_TIME_Absolute now;
- json_t *keys;
- json_t *signkeys;
- json_t *denoms;
- json_t *auditors;
-
- now = GNUNET_TIME_absolute_get ();
- signkeys = json_array ();
- for (unsigned int i=0;i<kd->num_sign_keys;i++)
- {
- const struct TALER_EXCHANGE_SigningPublicKey *sk = &kd->sign_keys[i];
- json_t *signkey;
-
- if (now.abs_value_us > sk->valid_until.abs_value_us)
- continue; /* skip keys that have expired */
- signkey = json_pack ("{s:o, s:o, s:o, s:o, s:o}",
- "key",
- GNUNET_JSON_from_data_auto (&sk->key),
- "master_sig",
- GNUNET_JSON_from_data_auto (&sk->master_sig),
- "stamp_start",
- GNUNET_JSON_from_time_abs (sk->valid_from),
- "stamp_expire",
- GNUNET_JSON_from_time_abs (sk->valid_until),
- "stamp_end",
- GNUNET_JSON_from_time_abs (sk->valid_legal));
- if (NULL == signkey)
- {
- GNUNET_break (0);
- continue;
- }
- json_array_append_new (signkeys,
- signkey);
- }
- denoms = json_array ();
- for (unsigned int i=0;i<kd->num_denom_keys;i++)
- {
- const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[i];
- json_t *denom;
-
- if (now.abs_value_us > dk->expire_deposit.abs_value_us)
- continue; /* skip keys that have expired */
- denom = json_pack ("{s:o, s:o, s:o, s:o, s:o "
- ",s:o, s:o, s:o, s:o, s:o "
- ",s:o}",
- "stamp_expire_deposit",
- GNUNET_JSON_from_time_abs (dk->expire_deposit),
- "stamp_expire_withdraw",
- GNUNET_JSON_from_time_abs (dk->withdraw_valid_until),
- "stamp_start",
- GNUNET_JSON_from_time_abs (dk->valid_from),
- "stamp_expire_legal",
- GNUNET_JSON_from_time_abs (dk->expire_legal),
- "value",
- TALER_JSON_from_amount (&dk->value),
- "fee_withdraw",
- /* #6 */
- TALER_JSON_from_amount (&dk->fee_withdraw),
- "fee_deposit",
- TALER_JSON_from_amount (&dk->fee_deposit),
- "fee_refresh",
- TALER_JSON_from_amount (&dk->fee_refresh),
- "fee_refund",
- TALER_JSON_from_amount (&dk->fee_refund),
- "master_sig",
- GNUNET_JSON_from_data_auto (&dk->master_sig),
- /* #10 */
- "denom_pub",
- GNUNET_JSON_from_rsa_public_key (dk->key.rsa_public_key));
- if (NULL == denom)
- {
- GNUNET_break (0);
- continue;
- }
- json_array_append_new (denoms,
- denom);
- }
- auditors = json_array ();
- for (unsigned int i=0;i<kd->num_auditors;i++)
- {
- const struct TALER_EXCHANGE_AuditorInformation *ai = &kd->auditors[i];
- json_t *a;
- json_t *adenoms;
-
- adenoms = json_array ();
- for (unsigned int j=0;j<ai->num_denom_keys;j++)
- {
- const struct TALER_EXCHANGE_AuditorDenominationInfo *adi = &ai->denom_keys[j];
- const struct TALER_EXCHANGE_DenomPublicKey *dk = &kd->denom_keys[adi->denom_key_offset];
- json_t *k;
-
- if (now.abs_value_us > dk->expire_deposit.abs_value_us)
- continue; /* skip auditor signatures for denomination keys that have expired */
- GNUNET_assert (adi->denom_key_offset < kd->num_denom_keys);
- k = json_pack ("{s:o, s:o}",
- "denom_pub_h",
- GNUNET_JSON_from_data_auto (&dk->h_key),
- "auditor_sig",
- GNUNET_JSON_from_data_auto (&adi->auditor_sig));
- if (NULL == k)
- {
- GNUNET_break (0);
- continue;
- }
- json_array_append_new (adenoms,
- k);
- }
-
- a = json_pack ("{s:o, s:s, s:o}",
- "auditor_pub",
- GNUNET_JSON_from_data_auto (&ai->auditor_pub),
- "auditor_url",
- ai->auditor_url,
- "denomination_keys",
- adenoms);
- if (NULL == a)
- {
- GNUNET_break (0);
- continue;
- }
- json_array_append_new (auditors,
- a);
- }
- keys = json_pack ("{s:s, s:o, s:o, s:o, s:o"
- ",s:o, s:o}",
- /* 1 */
- "version",
- kd->version,
- "master_public_key",
- GNUNET_JSON_from_data_auto (&kd->master_pub),
- "reserve_closing_delay",
- GNUNET_JSON_from_time_rel (kd->reserve_closing_delay),
- "list_issue_date",
- GNUNET_JSON_from_time_abs (kd->list_issue_date),
- "signkeys",
- signkeys,
- /* #6 */
- "denoms",
- denoms,
- "auditors",
- auditors);
- if (NULL == keys)
- {
- GNUNET_break (0);
- return NULL;
- }
- return json_pack ("{s:I, s:o, s:s, s:o}",
- "version",
- (json_int_t) TALER_SERIALIZATION_FORMAT_VERSION,
- "expire",
- GNUNET_JSON_from_time_abs (exchange->key_data_expiration),
- "url",
- exchange->url,
- "keys",
- keys);
-}
-
-
-/**
- * Initialise a connection to the exchange. Will connect to the
- * exchange and obtain information about the exchange's master
- * public key and the exchange's auditor.
- * The respective information will be passed to the @a cert_cb
- * once available, and all future interactions with the exchange
- * will be checked to be signed (where appropriate) by the
- * respective master key.
- *
- * @param ctx the context
- * @param url HTTP base URL for the exchange
- * @param cert_cb function to call with the exchange's
- * certification information
- * @param cert_cb_cls closure for @a cert_cb
- * @param ... list of additional arguments,
- * terminated by #TALER_EXCHANGE_OPTION_END.
- * @return the exchange handle; NULL upon error
- */
-struct TALER_EXCHANGE_Handle *
-TALER_EXCHANGE_connect
- (struct GNUNET_CURL_Context *ctx,
- const char *url,
- TALER_EXCHANGE_CertificationCallback cert_cb,
- void *cert_cb_cls,
- ...)
-{
- struct TALER_EXCHANGE_Handle *exchange;
- va_list ap;
- enum TALER_EXCHANGE_Option opt;
-
- exchange = GNUNET_new (struct TALER_EXCHANGE_Handle);
- exchange->ctx = ctx;
- exchange->url = GNUNET_strdup (url);
- exchange->cert_cb = cert_cb;
- exchange->cert_cb_cls = cert_cb_cls;
- exchange->retry_task = GNUNET_SCHEDULER_add_now (&request_keys,
- exchange);
- va_start (ap, cert_cb_cls);
- while (TALER_EXCHANGE_OPTION_END !=
- (opt = va_arg (ap, int)))
- {
- switch (opt) {
- case TALER_EXCHANGE_OPTION_END:
- GNUNET_assert (0);
- break;
- case TALER_EXCHANGE_OPTION_DATA:
- {
- const json_t *data = va_arg (ap, const json_t *);
-
- deserialize_data (exchange,
- data);
- break;
- }
- default:
- GNUNET_assert (0);
- break;
- }
- }
- va_end (ap);
- return exchange;
-}
-
-
-/**
- * Initiate download of /keys from the exchange.
- *
- * @param cls exchange where to download /keys from
- */
-static void
-request_keys (void *cls)
-{
- struct TALER_EXCHANGE_Handle *exchange = cls;
- struct KeysRequest *kr;
- CURL *eh;
-
- exchange->retry_task = NULL;
- GNUNET_assert (NULL == exchange->kr);
- kr = GNUNET_new (struct KeysRequest);
- kr->exchange = exchange;
- if (GNUNET_YES ==
- TEAH_handle_is_ready (exchange))
- {
- char *arg;
-
- TALER_LOG_DEBUG ("Last DK issue date (before GETting /keys): %s\n",
- GNUNET_STRINGS_absolute_time_to_string (exchange->key_data.last_denom_issue_date));
- GNUNET_asprintf (&arg,
- "/keys?last_issue_date=%llu",
- (unsigned long long) exchange->key_data.last_denom_issue_date.abs_value_us / 1000000LLU);
- kr->url = TEAH_path_to_url (exchange,
- arg);
- GNUNET_free (arg);
- }
- else
- {
- kr->url = TEAH_path_to_url (exchange,
- "/keys");
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Requesting keys with URL `%s'.\n",
- kr->url);
- eh = TEL_curl_easy_get (kr->url);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_VERBOSE,
- 0));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_TIMEOUT,
- (long) 300));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_HEADERFUNCTION,
- &header_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_HEADERDATA,
- kr));
- kr->job = GNUNET_CURL_job_add (exchange->ctx,
- eh,
- GNUNET_YES,
- &keys_completed_cb,
- kr);
- exchange->kr = kr;
-}
-
-
-/**
- * Disconnect from the exchange
- *
- * @param exchange the exchange handle
- */
-void
-TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange)
-{
- if (NULL != exchange->kr)
- {
- GNUNET_CURL_job_cancel (exchange->kr->job);
- free_keys_request (exchange->kr);
- exchange->kr = NULL;
- }
- free_key_data (&exchange->key_data);
- if (NULL != exchange->key_data_raw)
- {
- json_decref (exchange->key_data_raw);
- exchange->key_data_raw = NULL;
- }
- if (NULL != exchange->retry_task)
- {
- GNUNET_SCHEDULER_cancel (exchange->retry_task);
- exchange->retry_task = NULL;
- }
- GNUNET_free (exchange->url);
- GNUNET_free (exchange);
-}
-
-
-/**
- * Lookup the given @a pub in @a keys.
- *
- * @param keys the exchange's key set
- * @param pub claimed current online signing key for the exchange
- * @return NULL if @a pub was not found
- */
-const struct TALER_EXCHANGE_SigningPublicKey *
-TALER_EXCHANGE_get_signing_key_details (const struct TALER_EXCHANGE_Keys *keys,
- const struct TALER_ExchangePublicKeyP *pub)
-{
- for (unsigned int i=0;i<keys->num_sign_keys;i++)
- {
- struct TALER_EXCHANGE_SigningPublicKey *spk = &keys->sign_keys[i];
-
- if (0 == memcmp (pub,
- &spk->key,
- sizeof (struct TALER_ExchangePublicKeyP)))
- return spk;
- }
- return NULL;
-}
-
-
-/**
- * Test if the given @a pub is a the current signing key from the exchange
- * according to @a keys.
- *
- * @param keys the exchange's key set
- * @param pub claimed current online signing key for the exchange
- * @return #GNUNET_OK if @a pub is (according to /keys) a current signing key
- */
-int
-TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys,
- const struct TALER_ExchangePublicKeyP *pub)
-{
- struct GNUNET_TIME_Absolute now;
-
- /* we will check using a tolerance of 1h for the time */
- now = GNUNET_TIME_absolute_get ();
- for (unsigned int i=0;i<keys->num_sign_keys;i++)
- if ( (keys->sign_keys[i].valid_from.abs_value_us <= now.abs_value_us + 60 * 60 * 1000LL * 1000LL) &&
- (keys->sign_keys[i].valid_until.abs_value_us > now.abs_value_us - 60 * 60 * 1000LL * 1000LL) &&
- (0 == memcmp (pub,
- &keys->sign_keys[i].key,
- sizeof (struct TALER_ExchangePublicKeyP))) )
- return GNUNET_OK;
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Get exchange's base URL.
- *
- * @param exchange exchange handle.
- * @return the base URL from the handle.
- */
-const char *
-TALER_EXCHANGE_get_base_url (const struct TALER_EXCHANGE_Handle *exchange)
-{
- return exchange->url;
-}
-
-
-/**
- * Obtain the denomination key details from the exchange.
- *
- * @param keys the exchange's key set
- * @param pk public key of the denomination to lookup
- * @return details about the given denomination key, NULL if the key is
- * not found
- */
-const struct TALER_EXCHANGE_DenomPublicKey *
-TALER_EXCHANGE_get_denomination_key (const struct TALER_EXCHANGE_Keys *keys,
- const struct TALER_DenominationPublicKey *pk)
-{
- for (unsigned int i=0;i<keys->num_denom_keys;i++)
- if (0 == GNUNET_CRYPTO_rsa_public_key_cmp (pk->rsa_public_key,
- keys->denom_keys[i].key.rsa_public_key))
- return &keys->denom_keys[i];
- return NULL;
-}
-
-
-/**
- * Obtain the denomination key details from the exchange.
- *
- * @param keys the exchange's key set
- * @param hc hash of the public key of the denomination to lookup
- * @return details about the given denomination key
- */
-const struct TALER_EXCHANGE_DenomPublicKey *
-TALER_EXCHANGE_get_denomination_key_by_hash (const struct TALER_EXCHANGE_Keys *keys,
- const struct GNUNET_HashCode *hc)
-{
- for (unsigned int i=0;i<keys->num_denom_keys;i++)
- if (0 == memcmp (hc,
- &keys->denom_keys[i].h_key,
- sizeof (struct GNUNET_HashCode)))
- return &keys->denom_keys[i];
- return NULL;
-}
-
-
-/**
- * Obtain the keys from the exchange.
- *
- * @param exchange the exchange handle
- * @return the exchange's key set
- */
-const struct TALER_EXCHANGE_Keys *
-TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange)
-{
- (void) TALER_EXCHANGE_check_keys_current (exchange,
- GNUNET_NO);
- return &exchange->key_data;
-}
-
-
-/**
- * Obtain the keys from the exchange in the
- * raw JSON format
- *
- * @param exchange the exchange handle
- * @return the exchange's keys in raw JSON
- */
-json_t *
-TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange)
-{
- (void) TALER_EXCHANGE_check_keys_current (exchange,
- GNUNET_NO);
- return json_deep_copy (exchange->key_data_raw);
-}
-
-
-/* end of exchange_api_handle.c */
diff --git a/src/exchange-lib/exchange_api_handle.h b/src/exchange-lib/exchange_api_handle.h
deleted file mode 100644
index f06fa4eef..000000000
--- a/src/exchange-lib/exchange_api_handle.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_handle.h
- * @brief Internal interface to the handle part of the exchange's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_auditor_service.h"
-#include "taler_exchange_service.h"
-#include "taler_crypto_lib.h"
-
-
-/**
- * Function called for each auditor to give us a chance to possibly
- * launch a deposit confirmation interaction.
- *
- * @param cls closure
- * @param ah handle to the auditor
- * @param auditor_pub public key of the auditor
- * @return NULL if no deposit confirmation interaction was launched
- */
-typedef struct TALER_AUDITOR_DepositConfirmationHandle *
-(*TEAH_AuditorCallback)(void *cls,
- struct TALER_AUDITOR_Handle *ah,
- const struct TALER_AuditorPublicKeyP *auditor_pub);
-
-
-/**
- * Iterate over all available auditors for @a h, calling
- * @param ah and giving it a chance to start a deposit
- * confirmation interaction.
- *
- * @param h exchange to go over auditors for
- * @param ac function to call per auditor
- * @param ac_cls closure for @a ac
- */
-void
-TEAH_get_auditors_for_dc (struct TALER_EXCHANGE_Handle *h,
- TEAH_AuditorCallback ac,
- void *ac_cls);
-
-
-/**
- * Get the context of a exchange.
- *
- * @param h the exchange handle to query
- * @return ctx context to execute jobs in
- */
-struct GNUNET_CURL_Context *
-TEAH_handle_to_context (struct TALER_EXCHANGE_Handle *h);
-
-
-/**
- * Check if the handle is ready to process requests.
- *
- * @param h the exchange handle to query
- * @return #GNUNET_YES if we are ready, #GNUNET_NO if not
- */
-int
-TEAH_handle_is_ready (struct TALER_EXCHANGE_Handle *h);
-
-
-/**
- * Obtain the URL to use for an API request.
- *
- * @param h the exchange handle to query
- * @param path Taler API path (i.e. "/reserve/withdraw")
- * @return the full URL to use with cURL
- */
-char *
-TEAH_path_to_url (struct TALER_EXCHANGE_Handle *h,
- const char *path);
-
-
-/**
- * Obtain the URL to use for an API request.
- *
- * @param base_url base URL of the exchange (i.e. "http://exchange/")
- * @param path Taler API path (i.e. "/reserve/withdraw")
- * @return the full URL to use with cURL
- */
-char *
-TEAH_path_to_url2 (const char *base_url,
- const char *path);
-
-
-/* end of exchange_api_handle.h */
diff --git a/src/exchange-lib/exchange_api_payback.c b/src/exchange-lib/exchange_api_payback.c
deleted file mode 100644
index 9f8005558..000000000
--- a/src/exchange-lib/exchange_api_payback.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2017 GNUnet e.V. and Inria
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_payback.c
- * @brief Implementation of the /payback request of the exchange's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_json_lib.h"
-#include "taler_exchange_service.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "curl_defaults.h"
-
-
-/**
- * @brief A Payback Handle
- */
-struct TALER_EXCHANGE_PaybackHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Denomination key of the coin.
- */
- const struct TALER_EXCHANGE_DenomPublicKey *pk;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_PaybackResultCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Public key of the coin we are trying to get paid back.
- */
- struct TALER_CoinSpendPublicKeyP coin_pub;
-
-};
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * from the exchange is valid. If it is, call the
- * callback.
- *
- * @param ph payback handle
- * @param json json reply with the signature
- * @return #GNUNET_OK if the signature is valid and we called the callback;
- * #GNUNET_SYSERR if not (callback must still be called)
- */
-static int
-verify_payback_signature_ok (const struct TALER_EXCHANGE_PaybackHandle *ph,
- const json_t *json)
-{
- struct TALER_PaybackConfirmationPS pc;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangeSignatureP exchange_sig;
- struct TALER_Amount amount;
- struct GNUNET_TIME_Absolute timestamp;
- const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub),
- TALER_JSON_spec_amount ("amount", &amount),
- GNUNET_JSON_spec_absolute_time ("timestamp", &timestamp),
- GNUNET_JSON_spec_fixed_auto ("reserve_pub", &pc.reserve_pub),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- key_state = TALER_EXCHANGE_get_keys (ph->exchange);
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (key_state,
- &exchange_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
- pc.purpose.size = htonl (sizeof (pc));
- pc.timestamp = GNUNET_TIME_absolute_hton (timestamp);
- TALER_amount_hton (&pc.payback_amount,
- &amount);
- pc.coin_pub = ph->coin_pub;
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK,
- &pc.purpose,
- &exchange_sig.eddsa_signature,
- &exchange_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- ph->cb (ph->cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- &amount,
- timestamp,
- &pc.reserve_pub,
- json);
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /payback request.
- *
- * @param cls the `struct TALER_EXCHANGE_PaybackHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_payback_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_PaybackHandle *ph = cls;
- const json_t *j = response;
-
- ph->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- verify_payback_signature_ok (ph,
- j))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- TALER_EXCHANGE_payback_cancel (ph);
- return;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_FORBIDDEN:
- {
- /* Insufficient funds, proof attached */
- json_t *history;
- struct TALER_Amount total;
- const struct TALER_EXCHANGE_DenomPublicKey *dki;
-
- dki = ph->pk;
- history = json_object_get (j,
- "history");
- if (GNUNET_OK !=
- TALER_EXCHANGE_verify_coin_history (dki->fee_deposit.currency,
- &ph->coin_pub,
- history,
- &total))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- ph->cb (ph->cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- &total,
- GNUNET_TIME_UNIT_FOREVER_ABS,
- NULL,
- j);
- TALER_EXCHANGE_payback_cancel (ph);
- return;
- }
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, exchange 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_GONE:
- /* Kind of normal: the money was already sent to the merchant
- (it was too late for the refund). */
- 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;
- }
- ph->cb (ph->cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- NULL,
- GNUNET_TIME_UNIT_FOREVER_ABS,
- NULL,
- j);
- TALER_EXCHANGE_payback_cancel (ph);
-}
-
-
-/**
- * Ask the exchange to pay back a coin due to the exchange triggering
- * the emergency payback protocol for a given denomination. The value
- * of the coin will be refunded to the original customer (without fees).
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param pk kind of coin to pay back
- * @param denom_sig signature over the coin by the exchange using @a pk
- * @param ps secret internals of the original planchet
- * @param payback_cb the callback to call when the final result for this request is available
- * @param payback_cb_cls closure for @a payback_cb
- * @return NULL
- * if the inputs are invalid (i.e. denomination key not with this exchange).
- * In this case, the callback is not called.
- */
-struct TALER_EXCHANGE_PaybackHandle *
-TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_EXCHANGE_DenomPublicKey *pk,
- const struct TALER_DenominationSignature *denom_sig,
- const struct TALER_PlanchetSecretsP *ps,
- TALER_EXCHANGE_PaybackResultCallback payback_cb,
- void *payback_cb_cls)
-{
- struct TALER_EXCHANGE_PaybackHandle *ph;
- struct GNUNET_CURL_Context *ctx;
- struct TALER_PaybackRequestPS pr;
- struct TALER_CoinSpendSignatureP coin_sig;
- json_t *payback_obj;
- CURL *eh;
-
- GNUNET_assert (GNUNET_YES ==
- TEAH_handle_is_ready (exchange));
- pr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_PAYBACK);
- pr.purpose.size = htonl (sizeof (struct TALER_PaybackRequestPS));
- GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
- &pr.coin_pub.eddsa_pub);
- pr.h_denom_pub = pk->h_key;
- pr.coin_blind = ps->blinding_key;
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_eddsa_sign (&ps->coin_priv.eddsa_priv,
- &pr.purpose,
- &coin_sig.eddsa_signature));
-
- payback_obj = json_pack ("{s:o, s:o," /* denom pub/sig */
- " s:o, s:o," /* coin pub/sig */
- " s:o}", /* coin_bks */
- "denom_pub", GNUNET_JSON_from_rsa_public_key (pk->key.rsa_public_key),
- "denom_sig", GNUNET_JSON_from_rsa_signature (denom_sig->rsa_signature),
- "coin_pub", GNUNET_JSON_from_data_auto (&pr.coin_pub),
- "coin_sig", GNUNET_JSON_from_data_auto (&coin_sig),
- "coin_blind_key_secret", GNUNET_JSON_from_data_auto (&ps->blinding_key)
- );
- if (NULL == payback_obj)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- ph = GNUNET_new (struct TALER_EXCHANGE_PaybackHandle);
- ph->coin_pub = pr.coin_pub;
- ph->exchange = exchange;
- ph->pk = pk;
- ph->cb = payback_cb;
- ph->cb_cls = payback_cb_cls;
- ph->url = TEAH_path_to_url (exchange, "/payback");
-
- ph->json_enc = json_dumps (payback_obj,
- JSON_COMPACT);
- json_decref (payback_obj);
- if (NULL == ph->json_enc)
- {
- GNUNET_break (0);
- GNUNET_free (ph->url);
- GNUNET_free (ph);
- return NULL;
- }
- eh = TEL_curl_easy_get (ph->url);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "URL for payback: `%s'\n",
- ph->url);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- ph->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (ph->json_enc)));
- ctx = TEAH_handle_to_context (exchange);
- ph->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_payback_finished,
- ph);
- return ph;
-}
-
-
-/**
- * Cancel a payback request. This function cannot be used on a
- * request handle if the callback was already invoked.
- *
- * @param ph the payback handle
- */
-void
-TALER_EXCHANGE_payback_cancel (struct TALER_EXCHANGE_PaybackHandle *ph)
-{
- if (NULL != ph->job)
- {
- GNUNET_CURL_job_cancel (ph->job);
- ph->job = NULL;
- }
- GNUNET_free (ph->url);
- GNUNET_free (ph->json_enc);
- GNUNET_free (ph);
-}
-
-
-/* end of exchange_api_payback.c */
diff --git a/src/exchange-lib/exchange_api_refresh.c b/src/exchange-lib/exchange_api_refresh.c
deleted file mode 100644
index 50c55835b..000000000
--- a/src/exchange-lib/exchange_api_refresh.c
+++ /dev/null
@@ -1,1678 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2015, 2016, 2017 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_refresh.c
- * @brief Implementation of the /refresh/melt+reveal requests of the exchange's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_json_lib.h"
-#include "taler_exchange_service.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "curl_defaults.h"
-
-
-/* ********************* /refresh/ common ***************************** */
-
-/* structures for committing refresh data to disk before doing the
- network interaction(s) */
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Header of serialized information about a coin we are melting.
- */
-struct MeltedCoinP
-{
- /**
- * Private key of the coin.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
- /**
- * Amount this coin contributes to the melt, including fee.
- */
- struct TALER_AmountNBO melt_amount_with_fee;
-
- /**
- * The applicable fee for withdrawing a coin of this denomination
- */
- struct TALER_AmountNBO fee_melt;
-
- /**
- * The original value of the coin.
- */
- struct TALER_AmountNBO original_value;
-
- /**
- * Transfer private keys for each cut-and-choose dimension.
- */
- struct TALER_TransferPrivateKeyP transfer_priv[TALER_CNC_KAPPA];
-
- /**
- * Timestamp indicating when coins of this denomination become invalid.
- */
- struct GNUNET_TIME_AbsoluteNBO expire_deposit;
-
- /**
- * Size of the encoded public key that follows.
- */
- uint16_t pbuf_size;
-
- /**
- * Size of the encoded signature that follows.
- */
- uint16_t sbuf_size;
-
- /* Followed by serializations of:
- 1) struct TALER_DenominationPublicKey pub_key;
- 2) struct TALER_DenominationSignature sig;
- */
-};
-
-
-/**
- * Header of serialized data about a melt operation, suitable for
- * persisting it on disk.
- */
-struct MeltDataP
-{
-
- /**
- * Hash over the melting session.
- */
- struct TALER_RefreshCommitmentP rc;
-
- /**
- * Number of coins we are melting, in NBO
- */
- uint16_t num_melted_coins GNUNET_PACKED;
-
- /**
- * Number of coins we are creating, in NBO
- */
- uint16_t num_fresh_coins GNUNET_PACKED;
-
- /* Followed by serializations of:
- 1) struct MeltedCoinP melted_coins[num_melted_coins];
- 2) struct TALER_EXCHANGE_DenomPublicKey fresh_pks[num_fresh_coins];
- 3) TALER_CNC_KAPPA times:
- 3a) struct TALER_PlanchetSecretsP fresh_coins[num_fresh_coins];
- */
-};
-
-
-GNUNET_NETWORK_STRUCT_END
-
-
-/**
- * Information about a coin we are melting.
- */
-struct MeltedCoin
-{
- /**
- * Private key of the coin.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
- /**
- * Amount this coin contributes to the melt, including fee.
- */
- struct TALER_Amount melt_amount_with_fee;
-
- /**
- * The applicable fee for melting a coin of this denomination
- */
- struct TALER_Amount fee_melt;
-
- /**
- * The original value of the coin.
- */
- struct TALER_Amount original_value;
-
- /**
- * Transfer private keys for each cut-and-choose dimension.
- */
- struct TALER_TransferPrivateKeyP transfer_priv[TALER_CNC_KAPPA];
-
- /**
- * Timestamp indicating when coins of this denomination become invalid.
- */
- struct GNUNET_TIME_Absolute expire_deposit;
-
- /**
- * Denomination key of the original coin.
- */
- struct TALER_DenominationPublicKey pub_key;
-
- /**
- * Exchange's signature over the coin.
- */
- struct TALER_DenominationSignature sig;
-
-};
-
-
-/**
- * Melt data in non-serialized format for convenient processing.
- */
-struct MeltData
-{
-
- /**
- * Hash over the committed data during refresh operation.
- */
- struct TALER_RefreshCommitmentP rc;
-
- /**
- * Number of coins we are creating
- */
- uint16_t num_fresh_coins;
-
- /**
- * Information about the melted coin.
- */
- struct MeltedCoin melted_coin;
-
- /**
- * Array of @e num_fresh_coins denomination keys for the coins to be
- * freshly exchangeed.
- */
- struct TALER_DenominationPublicKey *fresh_pks;
-
- /**
- * Arrays of @e num_fresh_coins with information about the fresh
- * coins to be created, for each cut-and-choose dimension.
- */
- struct TALER_PlanchetSecretsP *fresh_coins[TALER_CNC_KAPPA];
-};
-
-
-/**
- * Free all information associated with a melted coin session.
- *
- * @param mc melted coin to release, the pointer itself is NOT
- * freed (as it is typically not allocated by itself)
- */
-static void
-free_melted_coin (struct MeltedCoin *mc)
-{
- if (NULL != mc->pub_key.rsa_public_key)
- GNUNET_CRYPTO_rsa_public_key_free (mc->pub_key.rsa_public_key);
- if (NULL != mc->sig.rsa_signature)
- GNUNET_CRYPTO_rsa_signature_free (mc->sig.rsa_signature);
-}
-
-
-/**
- * Free all information associated with a melting session. Note
- * that we allow the melting session to be only partially initialized,
- * as we use this function also when freeing melt data that was not
- * fully initialized (i.e. due to failures in #deserialize_melt_data()).
- *
- * @param md melting data to release, the pointer itself is NOT
- * freed (as it is typically not allocated by itself)
- */
-static void
-free_melt_data (struct MeltData *md)
-{
- free_melted_coin (&md->melted_coin);
- if (NULL != md->fresh_pks)
- {
- for (unsigned int i=0;i<md->num_fresh_coins;i++)
- if (NULL != md->fresh_pks[i].rsa_public_key)
- GNUNET_CRYPTO_rsa_public_key_free (md->fresh_pks[i].rsa_public_key);
- GNUNET_free (md->fresh_pks);
- }
-
- for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
- GNUNET_free (md->fresh_coins[i]);
- /* Finally, clean up a bit...
- (NOTE: compilers might optimize this away, so this is
- not providing any strong assurances that the key material
- is purged.) */
- memset (md,
- 0,
- sizeof (struct MeltData));
-}
-
-
-/**
- * Serialize information about a coin we are melting.
- *
- * @param mc information to serialize
- * @param buf buffer to write data in, NULL to just compute
- * required size
- * @param off offeset at @a buf to use
- * @return number of bytes written to @a buf at @a off, or if
- * @a buf is NULL, number of bytes required; 0 on error
- */
-static size_t
-serialize_melted_coin (const struct MeltedCoin *mc,
- char *buf,
- size_t off)
-{
- struct MeltedCoinP mcp;
- unsigned int i;
- char *pbuf;
- size_t pbuf_size;
- char *sbuf;
- size_t sbuf_size;
-
- sbuf_size = GNUNET_CRYPTO_rsa_signature_encode (mc->sig.rsa_signature,
- &sbuf);
- pbuf_size = GNUNET_CRYPTO_rsa_public_key_encode (mc->pub_key.rsa_public_key,
- &pbuf);
- if (NULL == buf)
- {
- GNUNET_free (sbuf);
- GNUNET_free (pbuf);
- return sizeof (struct MeltedCoinP) + sbuf_size + pbuf_size;
- }
- if ( (sbuf_size > UINT16_MAX) ||
- (pbuf_size > UINT16_MAX) )
- {
- GNUNET_break (0);
- return 0;
- }
- mcp.coin_priv = mc->coin_priv;
- TALER_amount_hton (&mcp.melt_amount_with_fee,
- &mc->melt_amount_with_fee);
- TALER_amount_hton (&mcp.fee_melt,
- &mc->fee_melt);
- TALER_amount_hton (&mcp.original_value,
- &mc->original_value);
- for (i=0;i<TALER_CNC_KAPPA;i++)
- mcp.transfer_priv[i] = mc->transfer_priv[i];
- mcp.expire_deposit = GNUNET_TIME_absolute_hton (mc->expire_deposit);
- mcp.pbuf_size = htons ((uint16_t) pbuf_size);
- mcp.sbuf_size = htons ((uint16_t) sbuf_size);
- memcpy (&buf[off],
- &mcp,
- sizeof (struct MeltedCoinP));
- memcpy (&buf[off + sizeof (struct MeltedCoinP)],
- pbuf,
- pbuf_size);
- memcpy (&buf[off + sizeof (struct MeltedCoinP) + pbuf_size],
- sbuf,
- sbuf_size);
- GNUNET_free (sbuf);
- GNUNET_free (pbuf);
- return sizeof (struct MeltedCoinP) + sbuf_size + pbuf_size;
-}
-
-
-/**
- * Deserialize information about a coin we are melting.
- *
- * @param[out] mc information to deserialize
- * @param buf buffer to read data from
- * @param size number of bytes available at @a buf to use
- * @param[out] ok set to #GNUNET_NO to report errors
- * @return number of bytes read from @a buf, 0 on error
- */
-static size_t
-deserialize_melted_coin (struct MeltedCoin *mc,
- const char *buf,
- size_t size,
- int *ok)
-{
- struct MeltedCoinP mcp;
- unsigned int i;
- size_t pbuf_size;
- size_t sbuf_size;
- size_t off;
-
- if (size < sizeof (struct MeltedCoinP))
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
- memcpy (&mcp,
- buf,
- sizeof (struct MeltedCoinP));
- pbuf_size = ntohs (mcp.pbuf_size);
- sbuf_size = ntohs (mcp.sbuf_size);
- if (size < sizeof (struct MeltedCoinP) + pbuf_size + sbuf_size)
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
- off = sizeof (struct MeltedCoinP);
- mc->pub_key.rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_decode (&buf[off],
- pbuf_size);
- off += pbuf_size;
- mc->sig.rsa_signature
- = GNUNET_CRYPTO_rsa_signature_decode (&buf[off],
- sbuf_size);
- off += sbuf_size;
- if ( (NULL == mc->pub_key.rsa_public_key) ||
- (NULL == mc->sig.rsa_signature) )
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
-
- mc->coin_priv = mcp.coin_priv;
- TALER_amount_ntoh (&mc->melt_amount_with_fee,
- &mcp.melt_amount_with_fee);
- TALER_amount_ntoh (&mc->fee_melt,
- &mcp.fee_melt);
- TALER_amount_ntoh (&mc->original_value,
- &mcp.original_value);
- for (i=0;i<TALER_CNC_KAPPA;i++)
- mc->transfer_priv[i] = mcp.transfer_priv[i];
- mc->expire_deposit = GNUNET_TIME_absolute_ntoh (mcp.expire_deposit);
- return off;
-}
-
-
-/**
- * Serialize information about a denomination key.
- *
- * @param dk information to serialize
- * @param buf buffer to write data in, NULL to just compute
- * required size
- * @param off offeset at @a buf to use
- * @return number of bytes written to @a buf at @a off, or if
- * @a buf is NULL, number of bytes required
- */
-static size_t
-serialize_denomination_key (const struct TALER_DenominationPublicKey *dk,
- char *buf,
- size_t off)
-{
- char *pbuf;
- size_t pbuf_size;
- uint32_t be;
-
- pbuf_size = GNUNET_CRYPTO_rsa_public_key_encode (dk->rsa_public_key,
- &pbuf);
- if (NULL == buf)
- {
- GNUNET_free (pbuf);
- return pbuf_size + sizeof (uint32_t);
- }
- be = htonl ((uint32_t) pbuf_size);
- memcpy (&buf[off],
- &be,
- sizeof (uint32_t));
- memcpy (&buf[off + sizeof (uint32_t)],
- pbuf,
- pbuf_size);
- GNUNET_free (pbuf);
- return pbuf_size + sizeof (uint32_t);
-}
-
-
-/**
- * Deserialize information about a denomination key.
- *
- * @param[out] dk information to deserialize
- * @param buf buffer to read data from
- * @param size number of bytes available at @a buf to use
- * @param[out] ok set to #GNUNET_NO to report errors
- * @return number of bytes read from @a buf, 0 on error
- */
-static size_t
-deserialize_denomination_key (struct TALER_DenominationPublicKey *dk,
- const char *buf,
- size_t size,
- int *ok)
-{
- size_t pbuf_size;
- uint32_t be;
-
- if (size < sizeof (uint32_t))
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
- memcpy (&be,
- buf,
- sizeof (uint32_t));
- pbuf_size = ntohl (be);
- if (size < sizeof (uint32_t) + pbuf_size)
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
- dk->rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_decode (&buf[sizeof (uint32_t)],
- pbuf_size);
- if (NULL == dk->rsa_public_key)
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
- return sizeof (uint32_t) + pbuf_size;
-}
-
-
-/**
- * Serialize information about a fresh coin we are generating.
- *
- * @param fc information to serialize
- * @param buf buffer to write data in, NULL to just compute
- * required size
- * @param off offeset at @a buf to use
- * @return number of bytes written to @a buf at @a off, or if
- * @a buf is NULL, number of bytes required
- */
-static size_t
-serialize_fresh_coin (const struct TALER_PlanchetSecretsP *fc,
- char *buf,
- size_t off)
-{
- if (NULL != buf)
- memcpy (&buf[off],
- fc,
- sizeof (struct TALER_PlanchetSecretsP));
- return sizeof (struct TALER_PlanchetSecretsP);
-}
-
-
-/**
- * Deserialize information about a fresh coin we are generating.
- *
- * @param[out] fc information to deserialize
- * @param buf buffer to read data from
- * @param size number of bytes available at @a buf to use
- * @param[out] ok set to #GNUNET_NO to report errors
- * @return number of bytes read from @a buf, 0 on error
- */
-static size_t
-deserialize_fresh_coin (struct TALER_PlanchetSecretsP *fc,
- const char *buf,
- size_t size,
- int *ok)
-{
- if (size < sizeof (struct TALER_PlanchetSecretsP))
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
- memcpy (fc,
- buf,
- sizeof (struct TALER_PlanchetSecretsP));
- return sizeof (struct TALER_PlanchetSecretsP);
-}
-
-
-/**
- * Serialize melt data.
- *
- * @param md data to serialize
- * @param[out] res_size size of buffer returned
- * @return serialized melt data
- */
-static char *
-serialize_melt_data (const struct MeltData *md,
- size_t *res_size)
-{
- size_t size;
- size_t asize;
- char *buf;
-
- size = 0;
- asize = (size_t) -1; /* make the compiler happy */
- buf = NULL;
- /* we do 2 iterations, #1 to determine total size, #2 to
- actually construct the buffer */
- do {
- if (0 == size)
- {
- size = sizeof (struct MeltDataP);
- }
- else
- {
- struct MeltDataP *mdp;
-
- buf = GNUNET_malloc (size);
- asize = size; /* just for invariant check later */
- size = sizeof (struct MeltDataP);
- mdp = (struct MeltDataP *) buf;
- mdp->rc = md->rc;
- mdp->num_fresh_coins = htons (md->num_fresh_coins);
- }
- size += serialize_melted_coin (&md->melted_coin,
- buf,
- size);
- for (unsigned int i=0;i<md->num_fresh_coins;i++)
- size += serialize_denomination_key (&md->fresh_pks[i],
- buf,
- size);
- for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
- for(unsigned int j=0;j<md->num_fresh_coins;j++)
- size += serialize_fresh_coin (&md->fresh_coins[i][j],
- buf,
- size);
- } while (NULL == buf);
- GNUNET_assert (size == asize);
- *res_size = size;
- return buf;
-}
-
-
-/**
- * Deserialize melt data.
- *
- * @param buf serialized data
- * @param buf_size size of @a buf
- * @return deserialized melt data, NULL on error
- */
-static struct MeltData *
-deserialize_melt_data (const char *buf,
- size_t buf_size)
-{
- struct MeltData *md;
- struct MeltDataP mdp;
- size_t off;
- int ok;
-
- if (buf_size < sizeof (struct MeltDataP))
- return NULL;
- memcpy (&mdp,
- buf,
- sizeof (struct MeltDataP));
- md = GNUNET_new (struct MeltData);
- md->rc = mdp.rc;
- md->num_fresh_coins = ntohs (mdp.num_fresh_coins);
- md->fresh_pks = GNUNET_new_array (md->num_fresh_coins,
- struct TALER_DenominationPublicKey);
- for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
- md->fresh_coins[i] = GNUNET_new_array (md->num_fresh_coins,
- struct TALER_PlanchetSecretsP);
- off = sizeof (struct MeltDataP);
- ok = GNUNET_YES;
- off += deserialize_melted_coin (&md->melted_coin,
- &buf[off],
- buf_size - off,
- &ok);
- for (unsigned int i=0;(i<md->num_fresh_coins)&&(GNUNET_YES == ok);i++)
- off += deserialize_denomination_key (&md->fresh_pks[i],
- &buf[off],
- buf_size - off,
- &ok);
-
- for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
- for (unsigned int j=0;(j<md->num_fresh_coins)&&(GNUNET_YES == ok);j++)
- off += deserialize_fresh_coin (&md->fresh_coins[i][j],
- &buf[off],
- buf_size - off,
- &ok);
- if (off != buf_size)
- {
- GNUNET_break (0);
- ok = GNUNET_NO;
- }
- if (GNUNET_YES != ok)
- {
- free_melt_data (md);
- GNUNET_free (md);
- return NULL;
- }
- return md;
-}
-
-
-/**
- * Melt (partially spent) coins to obtain fresh coins that are
- * unlinkable to the original coin(s). Note that melting more
- * than one coin in a single request will make those coins linkable,
- * so the safest operation only melts one coin at a time.
- *
- * This API is typically used by a wallet. Note that to ensure that
- * no money is lost in case of hardware failures, is operation does
- * not actually initiate the request. Instead, it generates a buffer
- * which the caller must store before proceeding with the actual call
- * to #TALER_EXCHANGE_refresh_melt() that will generate the request.
- *
- * This function does verify that the given request data is internally
- * consistent. However, the @a melts_sigs are only verified if
- * @a check_sigs is set to #GNUNET_YES, as this may be relatively
- * expensive and should be redundant.
- *
- * Aside from some non-trivial cryptographic operations that might
- * take a bit of CPU time to complete, this function returns
- * its result immediately and does not start any asynchronous
- * processing. This function is also thread-safe.
- *
- * @param melt_priv private key of the coin to melt
- * @param melt_amount amount specifying how much
- * the coin will contribute to the melt (including fee)
- * @param melt_sig signature affirming the
- * validity of the public keys corresponding to the
- * @a melt_priv private key
- * @param melt_pk denomination key information
- * record corresponding to the @a melt_sig
- * validity of the keys
- * @param check_sig verify the validity of the @a melt_sig signature
- * @param fresh_pks_len length of the @a pks array
- * @param fresh_pks array of @a pks_len denominations of fresh coins to create
- * @param[out] res_size set to the size of the return value, or 0 on error
- * @return NULL
- * if the inputs are invalid (i.e. denomination key not with this exchange).
- * Otherwise, pointer to a buffer of @a res_size to store persistently
- * before proceeding to #TALER_EXCHANGE_refresh_melt().
- * Non-null results should be freed using GNUNET_free().
- */
-char *
-TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_priv,
- const struct TALER_Amount *melt_amount,
- const struct TALER_DenominationSignature *melt_sig,
- const struct TALER_EXCHANGE_DenomPublicKey *melt_pk,
- int check_sig,
- unsigned int fresh_pks_len,
- const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks,
- size_t *res_size)
-{
- struct MeltData md;
- char *buf;
- struct TALER_Amount total;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_TransferSecretP trans_sec[TALER_CNC_KAPPA];
- struct TALER_RefreshCommitmentEntry rce[TALER_CNC_KAPPA];
-
- GNUNET_CRYPTO_eddsa_key_get_public (&melt_priv->eddsa_priv,
- &coin_pub.eddsa_pub);
- /* build up melt data structure */
- md.num_fresh_coins = fresh_pks_len;
- md.melted_coin.coin_priv = *melt_priv;
- md.melted_coin.melt_amount_with_fee = *melt_amount;
- md.melted_coin.fee_melt = melt_pk->fee_refresh;
- md.melted_coin.original_value = melt_pk->value;
- md.melted_coin.expire_deposit
- = melt_pk->expire_deposit;
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_get_zero (melt_amount->currency,
- &total));
- md.melted_coin.pub_key.rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_dup (melt_pk->key.rsa_public_key);
- md.melted_coin.sig.rsa_signature
- = GNUNET_CRYPTO_rsa_signature_dup (melt_sig->rsa_signature);
- md.fresh_pks = GNUNET_new_array (fresh_pks_len,
- struct TALER_DenominationPublicKey);
- for (unsigned int i=0;i<fresh_pks_len;i++)
- {
- md.fresh_pks[i].rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_dup (fresh_pks[i].key.rsa_public_key);
- if ( (GNUNET_OK !=
- TALER_amount_add (&total,
- &total,
- &fresh_pks[i].value)) ||
- (GNUNET_OK !=
- TALER_amount_add (&total,
- &total,
- &fresh_pks[i].fee_withdraw)) )
- {
- GNUNET_break (0);
- free_melt_data (&md);
- return NULL;
- }
- }
- /* verify that melt_amount is above total cost */
- if (1 ==
- TALER_amount_cmp (&total,
- melt_amount) )
- {
- /* Eh, this operation is more expensive than the
- @a melt_amount. This is not OK. */
- GNUNET_break (0);
- free_melt_data (&md);
- return NULL;
- }
-
- /* build up coins */
- for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
- {
- struct GNUNET_CRYPTO_EcdhePrivateKey *tpk;
-
- tpk = GNUNET_CRYPTO_ecdhe_key_create ();
- md.melted_coin.transfer_priv[i].ecdhe_priv = *tpk;
- GNUNET_free (tpk);
-
- GNUNET_CRYPTO_ecdhe_key_get_public (&md.melted_coin.transfer_priv[i].ecdhe_priv,
- &rce[i].transfer_pub.ecdhe_pub);
- TALER_link_derive_transfer_secret (melt_priv,
- &md.melted_coin.transfer_priv[i],
- &trans_sec[i]);
- md.fresh_coins[i] = GNUNET_new_array (fresh_pks_len,
- struct TALER_PlanchetSecretsP);
- rce[i].new_coins = GNUNET_new_array (fresh_pks_len,
- struct TALER_RefreshCoinData);
- for (unsigned int j=0;j<fresh_pks_len;j++)
- {
- struct TALER_PlanchetSecretsP *fc = &md.fresh_coins[i][j];
- struct TALER_RefreshCoinData *rcd = &rce[i].new_coins[j];
- struct TALER_PlanchetDetail pd;
-
- TALER_planchet_setup_refresh (&trans_sec[i],
- j,
- fc);
- if (GNUNET_OK !=
- TALER_planchet_prepare (&md.fresh_pks[j],
- fc,
- &pd))
- {
- GNUNET_break_op (0);
- free_melt_data (&md);
- return NULL;
- }
- rcd->dk = &md.fresh_pks[j];
- rcd->coin_ev = pd.coin_ev;
- rcd->coin_ev_size = pd.coin_ev_size;
- }
- }
-
- /* Compute refresh commitment */
- TALER_refresh_get_commitment (&md.rc,
- TALER_CNC_KAPPA,
- fresh_pks_len,
- rce,
- &coin_pub,
- melt_amount);
- /* finally, serialize everything */
- buf = serialize_melt_data (&md,
- res_size);
- for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
- {
- for (unsigned int j = 0; j < fresh_pks_len; j++)
- GNUNET_free_non_null (rce[i].new_coins[j].coin_ev);
- GNUNET_free_non_null (rce[i].new_coins);
- }
- free_melt_data (&md);
- return buf;
-}
-
-
-/* ********************* /refresh/melt ***************************** */
-
-
-/**
- * @brief A /refresh/melt Handle
- */
-struct TALER_EXCHANGE_RefreshMeltHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with refresh melt failure results.
- */
- TALER_EXCHANGE_RefreshMeltCallback melt_cb;
-
- /**
- * Closure for @e result_cb and @e melt_failure_cb.
- */
- void *melt_cb_cls;
-
- /**
- * Actual information about the melt operation.
- */
- struct MeltData *md;
-};
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * from the exchange is valid.
- *
- * @param rmh melt handle
- * @param json json reply with the signature
- * @param[out] exchange_pub public key of the exchange used for the signature
- * @param[out] noreveal_index set to the noreveal index selected by the exchange
- * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
- */
-static int
-verify_refresh_melt_signature_ok (struct TALER_EXCHANGE_RefreshMeltHandle *rmh,
- const json_t *json,
- struct TALER_ExchangePublicKeyP *exchange_pub,
- uint32_t *noreveal_index)
-{
- struct TALER_ExchangeSignatureP exchange_sig;
- const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub", exchange_pub),
- GNUNET_JSON_spec_uint32 ("noreveal_index", noreveal_index),
- GNUNET_JSON_spec_end()
- };
- struct TALER_RefreshMeltConfirmationPS confirm;
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* check that exchange signing key is permitted */
- key_state = TALER_EXCHANGE_get_keys (rmh->exchange);
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (key_state,
- exchange_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* check that noreveal index is in permitted range */
- if (TALER_CNC_KAPPA <= *noreveal_index)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* verify signature by exchange */
- confirm.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT);
- confirm.purpose.size = htonl (sizeof (struct TALER_RefreshMeltConfirmationPS));
- confirm.rc = rmh->md->rc;
- confirm.noreveal_index = htonl (*noreveal_index);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT,
- &confirm.purpose,
- &exchange_sig.eddsa_signature,
- &exchange_pub->eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Verify that the signatures on the "403 FORBIDDEN" response from the
- * exchange demonstrating customer double-spending are valid.
- *
- * @param rmh melt handle
- * @param json json reply with the signature(s) and transaction history
- * @return #GNUNET_OK if the signature(s) is valid, #GNUNET_SYSERR if not
- */
-static int
-verify_refresh_melt_signature_forbidden (struct TALER_EXCHANGE_RefreshMeltHandle *rmh,
- const json_t *json)
-{
- json_t *history;
- struct TALER_Amount original_value;
- struct TALER_Amount melt_value_with_fee;
- struct TALER_Amount total;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("history", &history),
- GNUNET_JSON_spec_fixed_auto ("coin_pub", &coin_pub),
- TALER_JSON_spec_amount ("original_value", &original_value),
- TALER_JSON_spec_amount ("requested_value", &melt_value_with_fee),
- GNUNET_JSON_spec_end()
- };
- const struct MeltedCoin *mc;
-
- /* parse JSON reply */
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* Find out which coin was deemed problematic by the exchange */
- mc = &rmh->md->melted_coin;
-
- /* check basic coin properties */
- if (0 != TALER_amount_cmp (&original_value,
- &mc->original_value))
- {
- /* We disagree on the value of the coin */
- GNUNET_break_op (0);
- json_decref (history);
- return GNUNET_SYSERR;
- }
- if (0 != TALER_amount_cmp (&melt_value_with_fee,
- &mc->melt_amount_with_fee))
- {
- /* We disagree on the value of the coin */
- GNUNET_break_op (0);
- json_decref (history);
- return GNUNET_SYSERR;
- }
-
- /* verify coin history */
- history = json_object_get (json,
- "history");
- if (GNUNET_OK !=
- TALER_EXCHANGE_verify_coin_history (original_value.currency,
- &coin_pub,
- history,
- &total))
- {
- GNUNET_break_op (0);
- json_decref (history);
- return GNUNET_SYSERR;
- }
- json_decref (history);
-
- /* check if melt operation was really too expensive given history */
- if (GNUNET_OK !=
- TALER_amount_add (&total,
- &total,
- &melt_value_with_fee))
- {
- /* clearly not OK if our transaction would have caused
- the overflow... */
- return GNUNET_OK;
- }
-
- if (0 >= TALER_amount_cmp (&total,
- &original_value))
- {
- /* transaction should have still fit */
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
-
- /* everything OK, valid proof of double-spending was provided */
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /refresh/melt request.
- *
- * @param cls the `struct TALER_EXCHANGE_RefreshMeltHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_refresh_melt_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_RefreshMeltHandle *rmh = cls;
- uint32_t noreveal_index = TALER_CNC_KAPPA; /* invalid value */
- struct TALER_ExchangePublicKeyP exchange_pub;
- const json_t *j = response;
-
- rmh->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- verify_refresh_melt_signature_ok (rmh,
- j,
- &exchange_pub,
- &noreveal_index))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- if (NULL != rmh->melt_cb)
- {
- rmh->melt_cb (rmh->melt_cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- noreveal_index,
- (0 == response_code) ? NULL : &exchange_pub,
- j);
- rmh->melt_cb = NULL;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_FORBIDDEN:
- /* Double spending; check signatures on transaction history */
- if (GNUNET_OK !=
- verify_refresh_melt_signature_forbidden (rmh,
- j))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, exchange says one of the signatures is
- invalid; assuming 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;
- }
- if (NULL != rmh->melt_cb)
- rmh->melt_cb (rmh->melt_cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- UINT32_MAX,
- NULL,
- j);
- TALER_EXCHANGE_refresh_melt_cancel (rmh);
-}
-
-
-/**
- * Submit a melt request to the exchange and get the exchange's
- * response.
- *
- * This API is typically used by a wallet. Note that to ensure that
- * no money is lost in case of hardware failures, the provided
- * argument should have been constructed using
- * #TALER_EXCHANGE_refresh_prepare and committed to persistent storage
- * prior to calling this function.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param refresh_data_length size of the @a refresh_data (returned
- * in the `res_size` argument from #TALER_EXCHANGE_refresh_prepare())
- * @param refresh_data the refresh data as returned from
- #TALER_EXCHANGE_refresh_prepare())
- * @param melt_cb the callback to call with the result
- * @param melt_cb_cls closure for @a melt_cb
- * @return a handle for this request; NULL if the argument was invalid.
- * In this case, neither callback will be called.
- */
-struct TALER_EXCHANGE_RefreshMeltHandle *
-TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
- size_t refresh_data_length,
- const char *refresh_data,
- TALER_EXCHANGE_RefreshMeltCallback melt_cb,
- void *melt_cb_cls)
-{
- json_t *melt_obj;
- struct TALER_EXCHANGE_RefreshMeltHandle *rmh;
- CURL *eh;
- struct GNUNET_CURL_Context *ctx;
- struct MeltData *md;
- struct TALER_CoinSpendSignatureP confirm_sig;
- struct TALER_RefreshMeltCoinAffirmationPS melt;
-
- GNUNET_assert (GNUNET_YES ==
- TEAH_handle_is_ready (exchange));
- md = deserialize_melt_data (refresh_data,
- refresh_data_length);
- if (NULL == md)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- melt.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
- melt.purpose.size = htonl (sizeof (struct TALER_RefreshMeltCoinAffirmationPS));
- melt.rc = md->rc;
- TALER_amount_hton (&melt.amount_with_fee,
- &md->melted_coin.melt_amount_with_fee);
- TALER_amount_hton (&melt.melt_fee,
- &md->melted_coin.fee_melt);
- GNUNET_CRYPTO_eddsa_key_get_public (&md->melted_coin.coin_priv.eddsa_priv,
- &melt.coin_pub.eddsa_pub);
- GNUNET_CRYPTO_eddsa_sign (&md->melted_coin.coin_priv.eddsa_priv,
- &melt.purpose,
- &confirm_sig.eddsa_signature);
- melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}",
- "coin_pub",
- GNUNET_JSON_from_data_auto (&melt.coin_pub),
- "denom_pub",
- GNUNET_JSON_from_rsa_public_key (md->melted_coin.pub_key.rsa_public_key),
- "denom_sig",
- GNUNET_JSON_from_rsa_signature (md->melted_coin.sig.rsa_signature),
- "confirm_sig",
- GNUNET_JSON_from_data_auto (&confirm_sig),
- "value_with_fee",
- TALER_JSON_from_amount (&md->melted_coin.melt_amount_with_fee),
- "rc",
- GNUNET_JSON_from_data_auto (&melt.rc));
- if (NULL == melt_obj)
- {
- GNUNET_break (0);
- free_melt_data (md);
- return NULL;
- }
-
- /* and now we can at last begin the actual request handling */
- rmh = GNUNET_new (struct TALER_EXCHANGE_RefreshMeltHandle);
- rmh->exchange = exchange;
- rmh->melt_cb = melt_cb;
- rmh->melt_cb_cls = melt_cb_cls;
- rmh->md = md;
- rmh->url = TEAH_path_to_url (exchange,
- "/refresh/melt");
- eh = TEL_curl_easy_get (rmh->url);
- GNUNET_assert (NULL != (rmh->json_enc =
- json_dumps (melt_obj,
- JSON_COMPACT)));
- json_decref (melt_obj);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- rmh->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (rmh->json_enc)));
- ctx = TEAH_handle_to_context (exchange);
- rmh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_refresh_melt_finished,
- rmh);
- return rmh;
-}
-
-
-/**
- * Cancel a refresh execute request. This function cannot be used
- * on a request handle if either callback was already invoked.
- *
- * @param rmh the refresh melt handle
- */
-void
-TALER_EXCHANGE_refresh_melt_cancel (struct TALER_EXCHANGE_RefreshMeltHandle *rmh)
-{
- if (NULL != rmh->job)
- {
- GNUNET_CURL_job_cancel (rmh->job);
- rmh->job = NULL;
- }
- free_melt_data (rmh->md); /* does not free 'md' itself */
- GNUNET_free (rmh->md);
- GNUNET_free (rmh->url);
- GNUNET_free (rmh->json_enc);
- GNUNET_free (rmh);
-}
-
-
-/* ********************* /refresh/reveal ***************************** */
-
-
-/**
- * @brief A /refresh/reveal Handle
- */
-struct TALER_EXCHANGE_RefreshRevealHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_RefreshRevealCallback reveal_cb;
-
- /**
- * Closure for @e reveal_cb.
- */
- void *reveal_cb_cls;
-
- /**
- * Actual information about the melt operation.
- */
- struct MeltData *md;
-
- /**
- * The index selected by the exchange in cut-and-choose to not be revealed.
- */
- uint16_t noreveal_index;
-
-};
-
-
-/**
- * We got a 200 OK response for the /refresh/reveal operation.
- * Extract the coin signatures and return them to the caller.
- * The signatures we get from the exchange is for the blinded value.
- * Thus, we first must unblind them and then should verify their
- * validity.
- *
- * If everything checks out, we return the unblinded signatures
- * to the application via the callback.
- *
- * @param rrh operation handle
- * @param json reply from the exchange
- * @param[out] coin_privs array of length `num_fresh_coins`, initialized to contain private keys
- * @param[out] sigs array of length `num_fresh_coins`, initialized to cointain RSA signatures
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static int
-refresh_reveal_ok (struct TALER_EXCHANGE_RefreshRevealHandle *rrh,
- const json_t *json,
- struct TALER_CoinSpendPrivateKeyP *coin_privs,
- struct TALER_DenominationSignature *sigs)
-{
- json_t *jsona;
- struct GNUNET_JSON_Specification outer_spec[] = {
- GNUNET_JSON_spec_json ("ev_sigs", &jsona),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- outer_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (! json_is_array (jsona))
- {
- /* We expected an array of coins */
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (outer_spec);
- return GNUNET_SYSERR;
- }
- if (rrh->md->num_fresh_coins != json_array_size (jsona))
- {
- /* Number of coins generated does not match our expectation */
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (outer_spec);
- return GNUNET_SYSERR;
- }
- for (unsigned int i=0;i<rrh->md->num_fresh_coins;i++)
- {
- const struct TALER_PlanchetSecretsP *fc;
- struct TALER_DenominationPublicKey *pk;
- json_t *jsonai;
- struct GNUNET_CRYPTO_RsaSignature *blind_sig;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct GNUNET_HashCode coin_hash;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_rsa_signature ("ev_sig", &blind_sig),
- GNUNET_JSON_spec_end()
- };
- struct TALER_FreshCoin coin;
-
- fc = &rrh->md->fresh_coins[rrh->noreveal_index][i];
- pk = &rrh->md->fresh_pks[i];
- jsonai = json_array_get (jsona, i);
- GNUNET_assert (NULL != jsonai);
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (jsonai,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (outer_spec);
- return GNUNET_SYSERR;
- }
-
- /* needed to verify the signature, and we didn't store it earlier,
- hence recomputing it here... */
- GNUNET_CRYPTO_eddsa_key_get_public (&fc->coin_priv.eddsa_priv,
- &coin_pub.eddsa_pub);
- GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
- &coin_hash);
- if (GNUNET_OK !=
- TALER_planchet_to_coin (pk,
- blind_sig,
- fc,
- &coin_hash,
- &coin))
- {
- GNUNET_break_op (0);
- GNUNET_CRYPTO_rsa_signature_free (blind_sig);
- GNUNET_JSON_parse_free (outer_spec);
- return GNUNET_SYSERR;
- }
- GNUNET_CRYPTO_rsa_signature_free (blind_sig);
- coin_privs[i] = coin.coin_priv;
- sigs[i] = coin.sig;
- }
- GNUNET_JSON_parse_free (outer_spec);
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /refresh/reveal request.
- *
- * @param cls the `struct TALER_EXCHANGE_RefreshHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_refresh_reveal_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_RefreshRevealHandle *rrh = cls;
- const json_t *j = response;
-
- rrh->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- struct TALER_CoinSpendPrivateKeyP coin_privs[rrh->md->num_fresh_coins];
- struct TALER_DenominationSignature sigs[rrh->md->num_fresh_coins];
- int ret;
-
- memset (sigs, 0, sizeof (sigs));
- ret = refresh_reveal_ok (rrh,
- j,
- coin_privs,
- sigs);
- if (GNUNET_OK != ret)
- {
- response_code = 0;
- }
- else
- {
- rrh->reveal_cb (rrh->reveal_cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- rrh->md->num_fresh_coins,
- coin_privs,
- sigs,
- j);
- rrh->reveal_cb = NULL;
- }
- for (unsigned int i=0;i<rrh->md->num_fresh_coins;i++)
- if (NULL != sigs[i].rsa_signature)
- GNUNET_CRYPTO_rsa_signature_free (sigs[i].rsa_signature);
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_CONFLICT:
- /* Nothing really to verify, exchange says our reveal is inconsitent
- with our commitment, so either side is buggy; 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;
- }
- if (NULL != rrh->reveal_cb)
- rrh->reveal_cb (rrh->reveal_cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- 0,
- NULL,
- NULL,
- j);
- TALER_EXCHANGE_refresh_reveal_cancel (rrh);
-}
-
-
-/**
- * Submit a /refresh/reval request to the exchange and get the exchange's
- * response.
- *
- * This API is typically used by a wallet. Note that to ensure that
- * no money is lost in case of hardware failures, the provided
- * arguments should have been committed to persistent storage
- * prior to calling this function.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param refresh_data_length size of the @a refresh_data (returned
- * in the `res_size` argument from #TALER_EXCHANGE_refresh_prepare())
- * @param refresh_data the refresh data as returned from
- #TALER_EXCHANGE_refresh_prepare())
- * @param noreveal_index response from the exchange to the
- * #TALER_EXCHANGE_refresh_melt() invocation
- * @param reveal_cb the callback to call with the final result of the
- * refresh operation
- * @param reveal_cb_cls closure for the above callback
- * @return a handle for this request; NULL if the argument was invalid.
- * In this case, neither callback will be called.
- */
-struct TALER_EXCHANGE_RefreshRevealHandle *
-TALER_EXCHANGE_refresh_reveal (struct TALER_EXCHANGE_Handle *exchange,
- size_t refresh_data_length,
- const char *refresh_data,
- uint32_t noreveal_index,
- TALER_EXCHANGE_RefreshRevealCallback reveal_cb,
- void *reveal_cb_cls)
-{
- struct TALER_EXCHANGE_RefreshRevealHandle *rrh;
- json_t *transfer_privs;
- json_t *new_denoms_h;
- json_t *coin_evs;
- json_t *reveal_obj;
- CURL *eh;
- struct GNUNET_CURL_Context *ctx;
- struct MeltData *md;
- struct TALER_TransferPublicKeyP transfer_pub;
-
- GNUNET_assert (GNUNET_YES ==
- TEAH_handle_is_ready (exchange));
- md = deserialize_melt_data (refresh_data,
- refresh_data_length);
- if (NULL == md)
- {
- GNUNET_break (0);
- return NULL;
- }
- if (noreveal_index >= TALER_CNC_KAPPA)
- {
- /* We check this here, as it would be really bad to below just
- disclose all the transfer keys. Note that this error should
- have been caught way earlier when the exchange replied, but maybe
- we had some internal corruption that changed the value... */
- GNUNET_break (0);
- return NULL;
- }
-
- /* now transfer_pub */
- GNUNET_CRYPTO_ecdhe_key_get_public (&md->melted_coin.transfer_priv[noreveal_index].ecdhe_priv,
- &transfer_pub.ecdhe_pub);
-
- /* now new_denoms */
- GNUNET_assert (NULL != (new_denoms_h = json_array ()));
- GNUNET_assert (NULL != (coin_evs = json_array ()));
- for (unsigned int i=0;i<md->num_fresh_coins;i++)
- {
- struct GNUNET_HashCode denom_hash;
- struct TALER_PlanchetDetail pd;
-
- GNUNET_CRYPTO_rsa_public_key_hash (md->fresh_pks[i].rsa_public_key,
- &denom_hash);
- GNUNET_assert (0 ==
- json_array_append_new (new_denoms_h,
- GNUNET_JSON_from_data_auto (&denom_hash)));
-
- if (GNUNET_OK !=
- TALER_planchet_prepare (&md->fresh_pks[i],
- &md->fresh_coins[noreveal_index][i],
- &pd))
- {
- /* This should have been noticed during the preparation stage. */
- GNUNET_break (0);
- json_decref (new_denoms_h);
- json_decref (coin_evs);
- return NULL;
- }
- GNUNET_assert (0 ==
- json_array_append_new (coin_evs,
- GNUNET_JSON_from_data (pd.coin_ev,
- pd.coin_ev_size)));
- GNUNET_free (pd.coin_ev);
- }
-
- /* build array of transfer private keys */
- GNUNET_assert (NULL != (transfer_privs = json_array ()));
- for (unsigned int j=0;j<TALER_CNC_KAPPA;j++)
- {
- if (j == noreveal_index)
- {
- /* This is crucial: exclude the transfer key for the
- noreval index! */
- continue;
- }
- GNUNET_assert (0 ==
- json_array_append_new (transfer_privs,
- GNUNET_JSON_from_data_auto (&md->melted_coin.transfer_priv[j])));
- }
-
- /* build main JSON request */
- reveal_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o}",
- "rc",
- GNUNET_JSON_from_data_auto (&md->rc),
- "transfer_pub",
- GNUNET_JSON_from_data_auto (&transfer_pub),
- "transfer_privs",
- transfer_privs,
- "new_denoms_h",
- new_denoms_h,
- "coin_evs",
- coin_evs);
- if (NULL == reveal_obj)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- /* finally, we can actually issue the request */
- rrh = GNUNET_new (struct TALER_EXCHANGE_RefreshRevealHandle);
- rrh->exchange = exchange;
- rrh->noreveal_index = noreveal_index;
- rrh->reveal_cb = reveal_cb;
- rrh->reveal_cb_cls = reveal_cb_cls;
- rrh->md = md;
- rrh->url = TEAH_path_to_url (rrh->exchange,
- "/refresh/reveal");
-
- eh = TEL_curl_easy_get (rrh->url);
- GNUNET_assert (NULL != (rrh->json_enc =
- json_dumps (reveal_obj,
- JSON_COMPACT)));
- json_decref (reveal_obj);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- rrh->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (rrh->json_enc)));
- ctx = TEAH_handle_to_context (rrh->exchange);
- rrh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_refresh_reveal_finished,
- rrh);
- return rrh;
-}
-
-
-/**
- * Cancel a refresh reveal request. This function cannot be used
- * on a request handle if the callback was already invoked.
- *
- * @param rrh the refresh reval handle
- */
-void
-TALER_EXCHANGE_refresh_reveal_cancel (struct TALER_EXCHANGE_RefreshRevealHandle *rrh)
-{
- if (NULL != rrh->job)
- {
- GNUNET_CURL_job_cancel (rrh->job);
- rrh->job = NULL;
- }
- GNUNET_free (rrh->url);
- GNUNET_free (rrh->json_enc);
- free_melt_data (rrh->md); /* does not free 'md' itself */
- GNUNET_free (rrh->md);
- GNUNET_free (rrh);
-}
-
-
-/* end of exchange_api_refresh.c */
diff --git a/src/exchange-lib/exchange_api_refresh_link.c b/src/exchange-lib/exchange_api_refresh_link.c
deleted file mode 100644
index 796608db5..000000000
--- a/src/exchange-lib/exchange_api_refresh_link.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2015, 2016 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_refresh_link.c
- * @brief Implementation of the /refresh/link request of the exchange's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_exchange_service.h"
-#include "taler_json_lib.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "curl_defaults.h"
-
-
-/**
- * @brief A /refresh/link Handle
- */
-struct TALER_EXCHANGE_RefreshLinkHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_RefreshLinkCallback link_cb;
-
- /**
- * Closure for @e cb.
- */
- void *link_cb_cls;
-
- /**
- * Private key of the coin, required to decode link information.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
-};
-
-
-/**
- * Parse the provided linkage data from the "200 OK" response
- * for one of the coins.
- *
- * @param rlh refresh link handle
- * @param json json reply with the data for one coin
- * @param coin_num number of the coin to decode
- * @param trans_pub our transfer public key
- * @param[out] coin_priv where to return private coin key
- * @param[out] sig where to return private coin signature
- * @param[out] pub where to return the public key for the coin
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-static int
-parse_refresh_link_coin (const struct TALER_EXCHANGE_RefreshLinkHandle *rlh,
- const json_t *json,
- unsigned int coin_num,
- const struct TALER_TransferPublicKeyP *trans_pub,
- struct TALER_CoinSpendPrivateKeyP *coin_priv,
- struct TALER_DenominationSignature *sig,
- struct TALER_DenominationPublicKey *pub)
-{
- struct GNUNET_CRYPTO_RsaSignature *bsig;
- struct GNUNET_CRYPTO_RsaPublicKey *rpub;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_rsa_public_key ("denom_pub", &rpub),
- GNUNET_JSON_spec_rsa_signature ("ev_sig", &bsig),
- GNUNET_JSON_spec_end()
- };
- struct TALER_TransferSecretP secret;
- struct TALER_PlanchetSecretsP fc;
-
- /* parse reply */
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- TALER_link_recover_transfer_secret (trans_pub,
- &rlh->coin_priv,
- &secret);
- TALER_planchet_setup_refresh (&secret,
- coin_num,
- &fc);
-
- /* extract coin and signature */
- *coin_priv = fc.coin_priv;
- sig->rsa_signature
- = GNUNET_CRYPTO_rsa_unblind (bsig,
- &fc.blinding_key.bks,
- rpub);
- /* clean up */
- pub->rsa_public_key = GNUNET_CRYPTO_rsa_public_key_dup (rpub);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_OK;
-}
-
-
-/**
- * Parse the provided linkage data from the "200 OK" response
- * for one of the coins.
- *
- * @param[in,out] rlh refresh link handle (callback may be zero'ed out)
- * @param json json reply with the data for one coin
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-static int
-parse_refresh_link_ok (struct TALER_EXCHANGE_RefreshLinkHandle *rlh,
- const json_t *json)
-{
- unsigned int session;
- unsigned int num_coins;
- int ret;
-
- if (! json_is_array (json))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- num_coins = 0;
- /* Theoretically, a coin may have been melted repeatedly
- into different sessions; so the response is an array
- which contains information by melting session. That
- array contains another array. However, our API returns
- a single 1d array, so we flatten the 2d array that is
- returned into a single array. Note that usually a coin
- is melted at most once, and so we'll only run this
- loop once for 'session=0' in most cases.
-
- num_coins tracks the size of the 1d array we return,
- whilst 'i' and 'session' track the 2d array. */
- for (session=0;session<json_array_size (json); session++)
- {
- json_t *jsona;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("new_coins", &jsona),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (json,
- session),
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (! json_is_array (jsona))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
-
- /* count all coins over all sessions */
- num_coins += json_array_size (jsona);
- GNUNET_JSON_parse_free (spec);
- }
- /* Now that we know how big the 1d array is, allocate
- and fill it. */
- {
- unsigned int off_coin; /* index into 1d array */
- unsigned int i;
- struct TALER_CoinSpendPrivateKeyP coin_privs[num_coins];
- struct TALER_DenominationSignature sigs[num_coins];
- struct TALER_DenominationPublicKey pubs[num_coins];
-
- memset (sigs, 0, sizeof (sigs));
- memset (pubs, 0, sizeof (pubs));
- off_coin = 0;
- for (session=0;session<json_array_size (json); session++)
- {
- json_t *jsona;
- struct TALER_TransferPublicKeyP trans_pub;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("new_coins",
- &jsona),
- GNUNET_JSON_spec_fixed_auto ("transfer_pub",
- &trans_pub),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json_array_get (json,
- session),
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (! json_is_array (jsona))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
-
- /* decode all coins */
- for (i=0;i<json_array_size (jsona);i++)
- {
- GNUNET_assert (i + off_coin < num_coins);
- if (GNUNET_OK !=
- parse_refresh_link_coin (rlh,
- json_array_get (jsona,
- i),
- i,
- &trans_pub,
- &coin_privs[i+off_coin],
- &sigs[i+off_coin],
- &pubs[i+off_coin]))
- {
- GNUNET_break_op (0);
- break;
- }
- }
- /* check if we really got all, then invoke callback */
- off_coin += i;
- if (i != json_array_size (jsona))
- {
- GNUNET_break_op (0);
- ret = GNUNET_SYSERR;
- GNUNET_JSON_parse_free (spec);
- break;
- }
- GNUNET_JSON_parse_free (spec);
- } /* end of for (session) */
-
- if (off_coin == num_coins)
- {
- rlh->link_cb (rlh->link_cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- num_coins,
- coin_privs,
- sigs,
- pubs,
- json);
- rlh->link_cb = NULL;
- ret = GNUNET_OK;
- }
- else
- {
- GNUNET_break_op (0);
- ret = GNUNET_SYSERR;
- }
-
- /* clean up */
- GNUNET_assert (off_coin <= num_coins);
- for (i=0;i<off_coin;i++)
- {
- if (NULL != sigs[i].rsa_signature)
- GNUNET_CRYPTO_rsa_signature_free (sigs[i].rsa_signature);
- if (NULL != pubs[i].rsa_public_key)
- GNUNET_CRYPTO_rsa_public_key_free (pubs[i].rsa_public_key);
- }
- }
- return ret;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /refresh/link request.
- *
- * @param cls the `struct TALER_EXCHANGE_RefreshLinkHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_refresh_link_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_RefreshLinkHandle *rlh = cls;
- const json_t *j = response;
-
- rlh->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- parse_refresh_link_ok (rlh,
- j))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_NOT_FOUND:
- /* Nothing really to verify, exchange says this coin was not melted; 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;
- }
- if (NULL != rlh->link_cb)
- rlh->link_cb (rlh->link_cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- 0,
- NULL,
- NULL,
- NULL,
- j);
- TALER_EXCHANGE_refresh_link_cancel (rlh);
-}
-
-
-/**
- * Submit a link request to the exchange and get the exchange's response.
- *
- * This API is typically not used by anyone, it is more a threat
- * against those trying to receive a funds transfer by abusing the
- * /refresh protocol.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param coin_priv private key to request link data for
- * @param link_cb the callback to call with the useful result of the
- * refresh operation the @a coin_priv was involved in (if any)
- * @param link_cb_cls closure for @a link_cb
- * @return a handle for this request
- */
-struct TALER_EXCHANGE_RefreshLinkHandle *
-TALER_EXCHANGE_refresh_link (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- TALER_EXCHANGE_RefreshLinkCallback link_cb,
- void *link_cb_cls)
-{
- struct TALER_EXCHANGE_RefreshLinkHandle *rlh;
- CURL *eh;
- struct GNUNET_CURL_Context *ctx;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- char *pub_str;
- char *arg_str;
-
- if (GNUNET_YES !=
- TEAH_handle_is_ready (exchange))
- {
- GNUNET_break (0);
- return NULL;
- }
-
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
- &coin_pub.eddsa_pub);
- pub_str = GNUNET_STRINGS_data_to_string_alloc (&coin_pub,
- sizeof (struct TALER_CoinSpendPublicKeyP));
- GNUNET_asprintf (&arg_str,
- "/refresh/link?coin_pub=%s",
- pub_str);
- GNUNET_free (pub_str);
-
- rlh = GNUNET_new (struct TALER_EXCHANGE_RefreshLinkHandle);
- rlh->exchange = exchange;
- rlh->link_cb = link_cb;
- rlh->link_cb_cls = link_cb_cls;
- rlh->coin_priv = *coin_priv;
- rlh->url = TEAH_path_to_url (exchange, arg_str);
- GNUNET_free (arg_str);
-
-
- eh = TEL_curl_easy_get (rlh->url);
- ctx = TEAH_handle_to_context (exchange);
- rlh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_refresh_link_finished,
- rlh);
- return rlh;
-}
-
-
-/**
- * Cancel a refresh link request. This function cannot be used
- * on a request handle if the callback was already invoked.
- *
- * @param rlh the refresh link handle
- */
-void
-TALER_EXCHANGE_refresh_link_cancel (struct TALER_EXCHANGE_RefreshLinkHandle *rlh)
-{
- if (NULL != rlh->job)
- {
- GNUNET_CURL_job_cancel (rlh->job);
- rlh->job = NULL;
- }
- GNUNET_free (rlh->url);
- GNUNET_free (rlh);
-}
-
-
-/* end of exchange_api_refresh_link.c */
diff --git a/src/exchange-lib/exchange_api_refund.c b/src/exchange-lib/exchange_api_refund.c
deleted file mode 100644
index 447e9ce08..000000000
--- a/src/exchange-lib/exchange_api_refund.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015, 2016 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_refund.c
- * @brief Implementation of the /refund request of the exchange's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_json_lib.h"
-#include "taler_exchange_service.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "curl_defaults.h"
-
-
-/**
- * @brief A Refund Handle
- */
-struct TALER_EXCHANGE_RefundHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_RefundResultCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Information the exchange should sign in response.
- */
- struct TALER_RefundConfirmationPS depconf;
-
-};
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * from the exchange is valid.
- *
- * @param rh refund handle
- * @param json json reply with the signature
- * @param[out] exchange_pub set to the exchange's public key
- * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
- */
-static int
-verify_refund_signature_ok (const struct TALER_EXCHANGE_RefundHandle *rh,
- const json_t *json,
- struct TALER_ExchangePublicKeyP *exchange_pub)
-{
- struct TALER_ExchangeSignatureP exchange_sig;
- const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("sig", &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("pub", exchange_pub),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- key_state = TALER_EXCHANGE_get_keys (rh->exchange);
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (key_state,
- exchange_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND,
- &rh->depconf.purpose,
- &exchange_sig.eddsa_signature,
- &exchange_pub->eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /refund request.
- *
- * @param cls the `struct TALER_EXCHANGE_RefundHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_refund_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_RefundHandle *rh = cls;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangePublicKeyP *ep = NULL;
- const json_t *j = response;
-
- rh->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- verify_refund_signature_ok (rh,
- j,
- &exchange_pub))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- else
- {
- ep = &exchange_pub;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, exchange 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_GONE:
- /* Kind of normal: the money was already sent to the merchant
- (it was too late for the refund). */
- break;
- case MHD_HTTP_PRECONDITION_FAILED:
- /* Client request was inconsistent; might be a currency missmatch
- problem. */
- break;
- case MHD_HTTP_CONFLICT:
- /* Two refund requests were made about the same deposit, but
- carrying different refund transaction ids. */
- 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;
- }
- rh->cb (rh->cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- ep,
- j);
- TALER_EXCHANGE_refund_cancel (rh);
-}
-
-
-/**
- * Submit a refund request to the exchange and get the exchange's
- * response. This API is used by a merchant. Note that
- * while we return the response verbatim to the caller for further
- * processing, we do already verify that the response is well-formed
- * (i.e. that signatures included in the response are all valid). If
- * the exchange's reply is not well-formed, we return an HTTP status code
- * of zero to @a cb.
- *
- * The @a exchange must be ready to operate (i.e. have
- * finished processing the /keys reply). If this check fails, we do
- * NOT initiate the transaction with the exchange and instead return NULL.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param amount the amount to be refunded; must be larger than the refund fee
- * (as that fee is still being subtracted), and smaller than the amount
- * (with deposit fee) of the original deposit contribution of this coin
- * @param refund_fee fee applicable to this coin for the refund
- * @param h_contract_terms hash of the contact of the merchant with the customer that is being refunded
- * @param coin_pub coin’s public key of the coin from the original deposit operation
- * @param rtransaction_id transaction id for the transaction between merchant and customer (of refunding operation);
- * this is needed as we may first do a partial refund and later a full refund. If both
- * refunds are also over the same amount, we need the @a rtransaction_id to make the disjoint
- * refund requests different (as requests are idempotent and otherwise the 2nd refund might not work).
- * @param merchant_priv the private key of the merchant, used to generate signature for refund request
- * @param cb the callback to call when a reply for this request is available
- * @param cb_cls closure for the above callback
- * @return a handle for this request; NULL if the inputs are invalid (i.e.
- * signatures fail to verify). In this case, the callback is not called.
- */
-struct TALER_EXCHANGE_RefundHandle *
-TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_Amount *amount,
- const struct TALER_Amount *refund_fee,
- const struct GNUNET_HashCode *h_contract_terms,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- uint64_t rtransaction_id,
- const struct TALER_MerchantPrivateKeyP *merchant_priv,
- TALER_EXCHANGE_RefundResultCallback cb,
- void *cb_cls)
-{
- struct TALER_RefundRequestPS rr;
- struct TALER_MerchantSignatureP merchant_sig;
-
- GNUNET_assert (GNUNET_YES ==
- TEAH_handle_is_ready (exchange));
- rr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND);
- rr.purpose.size = htonl (sizeof (struct TALER_RefundRequestPS));
- rr.h_contract_terms = *h_contract_terms;
- rr.coin_pub = *coin_pub;
- GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv,
- &rr.merchant.eddsa_pub);
- rr.rtransaction_id = GNUNET_htonll (rtransaction_id);
- TALER_amount_hton (&rr.refund_amount,
- amount);
- TALER_amount_hton (&rr.refund_fee,
- refund_fee);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
- &rr.purpose,
- &merchant_sig.eddsa_sig));
- return TALER_EXCHANGE_refund2 (exchange,
- amount,
- refund_fee,
- h_contract_terms,
- coin_pub,
- rtransaction_id,
- &rr.merchant,
- &merchant_sig,
- cb,
- cb_cls);
-}
-
-
-/**
- * Submit a refund request to the exchange and get the exchange's
- * response. This API is used by a merchant. Note that
- * while we return the response verbatim to the caller for further
- * processing, we do already verify that the response is well-formed
- * (i.e. that signatures included in the response are all valid). If
- * the exchange's reply is not well-formed, we return an HTTP status code
- * of zero to @a cb.
- *
- * The @a exchange must be ready to operate (i.e. have
- * finished processing the /keys reply). If this check fails, we do
- * NOT initiate the transaction with the exchange and instead return NULL.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param amount the amount to be refunded; must be larger than the refund fee
- * (as that fee is still being subtracted), and smaller than the amount
- * (with deposit fee) of the original deposit contribution of this coin
- * @param refund_fee fee applicable to this coin for the refund
- * @param h_contract_terms hash of the contact of the merchant with the customer that is being refunded
- * @param coin_pub coin’s public key of the coin from the original deposit operation
- * @param rtransaction_id transaction id for the transaction between merchant and customer (of refunding operation);
- * this is needed as we may first do a partial refund and later a full refund. If both
- * refunds are also over the same amount, we need the @a rtransaction_id to make the disjoint
- * refund requests different (as requests are idempotent and otherwise the 2nd refund might not work).
- * @param merchant_pub public key of the merchant
- * @param merchant_sig signature affirming the refund from the merchant
- * @param cb the callback to call when a reply for this request is available
- * @param cb_cls closure for the above callback
- * @return a handle for this request; NULL if the inputs are invalid (i.e.
- * signatures fail to verify). In this case, the callback is not called.
- */
-struct TALER_EXCHANGE_RefundHandle *
-TALER_EXCHANGE_refund2 (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_Amount *amount,
- const struct TALER_Amount *refund_fee,
- const struct GNUNET_HashCode *h_contract_terms,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- uint64_t rtransaction_id,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct TALER_MerchantSignatureP *merchant_sig,
- TALER_EXCHANGE_RefundResultCallback cb,
- void *cb_cls)
-{
- struct TALER_EXCHANGE_RefundHandle *rh;
- struct GNUNET_CURL_Context *ctx;
- json_t *refund_obj;
- CURL *eh;
-
-refund_obj = json_pack ("{s:o, s:o," /* amount/fee */
- " s:o, s:o," /* h_contract_terms, coin_pub */
- " s:I," /* rtransaction id */
- " s:o, s:o}", /* merchant_pub, merchant_sig */
- "refund_amount", TALER_JSON_from_amount (amount),
- "refund_fee", TALER_JSON_from_amount (refund_fee),
- "h_contract_terms", GNUNET_JSON_from_data_auto (h_contract_terms),
- "coin_pub", GNUNET_JSON_from_data_auto (coin_pub),
- "rtransaction_id", (json_int_t) rtransaction_id,
- "merchant_pub", GNUNET_JSON_from_data_auto (merchant_pub),
- "merchant_sig", GNUNET_JSON_from_data_auto (merchant_sig)
- );
- if (NULL == refund_obj)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- rh = GNUNET_new (struct TALER_EXCHANGE_RefundHandle);
- rh->exchange = exchange;
- rh->cb = cb;
- rh->cb_cls = cb_cls;
- rh->url = TEAH_path_to_url (exchange, "/refund");
- rh->depconf.purpose.size = htonl (sizeof (struct TALER_RefundConfirmationPS));
- rh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND);
- rh->depconf.h_contract_terms = *h_contract_terms;
- rh->depconf.coin_pub = *coin_pub;
- rh->depconf.merchant = *merchant_pub;
- rh->depconf.rtransaction_id = GNUNET_htonll (rtransaction_id);
- TALER_amount_hton (&rh->depconf.refund_amount,
- amount);
- TALER_amount_hton (&rh->depconf.refund_fee,
- refund_fee);
-
- eh = TEL_curl_easy_get (rh->url);
- GNUNET_assert (NULL != (rh->json_enc =
- json_dumps (refund_obj,
- JSON_COMPACT)));
- json_decref (refund_obj);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "URL for refund: `%s'\n",
- rh->url);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- rh->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (rh->json_enc)));
- ctx = TEAH_handle_to_context (exchange);
- rh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_refund_finished,
- rh);
- return rh;
-}
-
-
-/**
- * Cancel a refund permission request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param refund the refund permission request handle
- */
-void
-TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund)
-{
- if (NULL != refund->job)
- {
- GNUNET_CURL_job_cancel (refund->job);
- refund->job = NULL;
- }
- GNUNET_free (refund->url);
- GNUNET_free (refund->json_enc);
- GNUNET_free (refund);
-}
-
-
-/* end of exchange_api_refund.c */
diff --git a/src/exchange-lib/exchange_api_reserve.c b/src/exchange-lib/exchange_api_reserve.c
deleted file mode 100644
index aa153f210..000000000
--- a/src/exchange-lib/exchange_api_reserve.c
+++ /dev/null
@@ -1,1203 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_reserve.c
- * @brief Implementation of the /reserve requests of the exchange's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_exchange_service.h"
-#include "taler_json_lib.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "curl_defaults.h"
-
-
-/* ********************** /reserve/status ********************** */
-
-/**
- * @brief A Withdraw Status Handle
- */
-struct TALER_EXCHANGE_ReserveStatusHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_ReserveStatusResultCallback cb;
-
- /**
- * Public key of the reserve we are querying.
- */
- struct TALER_ReservePublicKeyP reserve_pub;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
-};
-
-
-/**
- * Parse history given in JSON format and return it in binary
- * format.
- *
- * @param exchange connection to the exchange we can use
- * @param history JSON array with the history
- * @param reserve_pub public key of the reserve to inspect
- * @param currency currency we expect the balance to be in
- * @param[out] balance final balance
- * @param history_length number of entries in @a history
- * @param[out] rhistory array of length @a history_length, set to the
- * parsed history entries
- * @return #GNUNET_OK if history was valid and @a rhistory and @a balance
- * were set,
- * #GNUNET_SYSERR if there was a protocol violation in @a history
- */
-static int
-parse_reserve_history (struct TALER_EXCHANGE_Handle *exchange,
- const json_t *history,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const char *currency,
- struct TALER_Amount *balance,
- unsigned int history_length,
- struct TALER_EXCHANGE_ReserveHistory *rhistory)
-{
- struct GNUNET_HashCode uuid[history_length];
- unsigned int uuid_off;
- struct TALER_Amount total_in;
- struct TALER_Amount total_out;
- size_t off;
-
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_get_zero (currency,
- &total_in));
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_get_zero (currency,
- &total_out));
- uuid_off = 0;
- for (off=0;off<history_length;off++)
- {
- json_t *transaction;
- struct TALER_Amount amount;
- const char *type;
- struct GNUNET_JSON_Specification hist_spec[] = {
- GNUNET_JSON_spec_string ("type", &type),
- TALER_JSON_spec_amount ("amount",
- &amount),
- /* 'wire' and 'signature' are optional depending on 'type'! */
- GNUNET_JSON_spec_end()
- };
-
- transaction = json_array_get (history,
- off);
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- hist_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rhistory[off].amount = amount;
-
- if (0 == strcasecmp (type,
- "DEPOSIT"))
- {
- const char *wire_url;
- void *wire_reference;
- size_t wire_reference_size;
- struct GNUNET_TIME_Absolute timestamp;
-
- struct GNUNET_JSON_Specification withdraw_spec[] = {
- GNUNET_JSON_spec_varsize ("wire_reference",
- &wire_reference,
- &wire_reference_size),
- GNUNET_JSON_spec_absolute_time ("timestamp",
- &timestamp),
- GNUNET_JSON_spec_string ("sender_account_url",
- &wire_url),
- GNUNET_JSON_spec_end()
- };
-
- rhistory[off].type = TALER_EXCHANGE_RTT_DEPOSIT;
- if (GNUNET_OK !=
- TALER_amount_add (&total_in,
- &total_in,
- &amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- withdraw_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rhistory[off].details.in_details.sender_url = GNUNET_strdup (wire_url);
- rhistory[off].details.in_details.wire_reference = wire_reference;
- rhistory[off].details.in_details.wire_reference_size = wire_reference_size;
- rhistory[off].details.in_details.timestamp = timestamp;
- /* end type==DEPOSIT */
- }
- else if (0 == strcasecmp (type,
- "WITHDRAW"))
- {
- struct TALER_ReserveSignatureP sig;
- struct TALER_WithdrawRequestPS withdraw_purpose;
- struct GNUNET_JSON_Specification withdraw_spec[] = {
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &sig),
- TALER_JSON_spec_amount_nbo ("withdraw_fee",
- &withdraw_purpose.withdraw_fee),
- GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
- &withdraw_purpose.h_denomination_pub),
- GNUNET_JSON_spec_fixed_auto ("h_coin_envelope",
- &withdraw_purpose.h_coin_envelope),
- GNUNET_JSON_spec_end()
- };
- unsigned int i;
-
- rhistory[off].type = TALER_EXCHANGE_RTT_WITHDRAWAL;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- withdraw_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- withdraw_purpose.purpose.size
- = htonl (sizeof (withdraw_purpose));
- withdraw_purpose.purpose.purpose
- = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
- withdraw_purpose.reserve_pub = *reserve_pub;
- TALER_amount_hton (&withdraw_purpose.amount_with_fee,
- &amount);
- /* Check that the signature is a valid withdraw request */
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
- &withdraw_purpose.purpose,
- &sig.eddsa_signature,
- &reserve_pub->eddsa_pub))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- /* TODO: check that withdraw fee matches expectations! */
- rhistory[off].details.out_authorization_sig
- = json_object_get (transaction,
- "signature");
- /* Check check that the same withdraw transaction
- isn't listed twice by the exchange. We use the
- "uuid" array to remember the hashes of all
- purposes, and compare the hashes to find
- duplicates. */
- GNUNET_CRYPTO_hash (&withdraw_purpose,
- ntohl (withdraw_purpose.purpose.size),
- &uuid[uuid_off]);
- for (i=0;i<uuid_off;i++)
- {
- if (0 == memcmp (&uuid[uuid_off],
- &uuid[i],
- sizeof (struct GNUNET_HashCode)))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- }
- uuid_off++;
-
- if (GNUNET_OK !=
- TALER_amount_add (&total_out,
- &total_out,
- &amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- /* end type==WITHDRAW */
- }
- else if (0 == strcasecmp (type,
- "PAYBACK"))
- {
- struct TALER_PaybackConfirmationPS pc;
- struct GNUNET_TIME_Absolute timestamp;
- const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_JSON_Specification payback_spec[] = {
- GNUNET_JSON_spec_fixed_auto ("coin_pub",
- &pc.coin_pub),
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &rhistory[off].details.payback_details.exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &rhistory[off].details.payback_details.exchange_pub),
- GNUNET_JSON_spec_absolute_time_nbo ("timestamp",
- &pc.timestamp),
- GNUNET_JSON_spec_end()
- };
-
- rhistory[off].type = TALER_EXCHANGE_RTT_PAYBACK;
- rhistory[off].amount = amount;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- payback_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rhistory[off].details.payback_details.coin_pub = pc.coin_pub;
- TALER_amount_hton (&pc.payback_amount,
- &amount);
- pc.purpose.size = htonl (sizeof (pc));
- pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK);
- pc.reserve_pub = *reserve_pub;
- timestamp = GNUNET_TIME_absolute_ntoh (pc.timestamp);
- rhistory[off].details.payback_details.timestamp = timestamp;
-
- key_state = TALER_EXCHANGE_get_keys (exchange);
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (key_state,
- &rhistory[off].details.payback_details.exchange_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK,
- &pc.purpose,
- &rhistory[off].details.payback_details.exchange_sig.eddsa_signature,
- &rhistory[off].details.payback_details.exchange_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_amount_add (&total_in,
- &total_in,
- &rhistory[off].amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* end type==PAYBACK */
- }
- else if (0 == strcasecmp (type,
- "CLOSING"))
- {
- const struct TALER_EXCHANGE_Keys *key_state;
- struct TALER_ReserveCloseConfirmationPS rcc;
- struct GNUNET_TIME_Absolute timestamp;
- struct GNUNET_JSON_Specification closing_spec[] = {
- GNUNET_JSON_spec_string ("receiver_account_details",
- &rhistory[off].details.close_details.receiver_account_details),
- GNUNET_JSON_spec_fixed_auto ("wtid",
- &rhistory[off].details.close_details.wtid),
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &rhistory[off].details.close_details.exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &rhistory[off].details.close_details.exchange_pub),
- TALER_JSON_spec_amount_nbo ("closing_fee",
- &rcc.closing_fee),
- GNUNET_JSON_spec_absolute_time_nbo ("timestamp",
- &rcc.timestamp),
- GNUNET_JSON_spec_end()
- };
-
- rhistory[off].type = TALER_EXCHANGE_RTT_CLOSE;
- rhistory[off].amount = amount;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- closing_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- TALER_amount_hton (&rcc.closing_amount,
- &amount);
- GNUNET_CRYPTO_hash (rhistory[off].details.close_details.receiver_account_details,
- strlen (rhistory[off].details.close_details.receiver_account_details) + 1,
- &rcc.h_wire);
- rcc.wtid = rhistory[off].details.close_details.wtid;
- rcc.purpose.size = htonl (sizeof (rcc));
- rcc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED);
- rcc.reserve_pub = *reserve_pub;
- timestamp = GNUNET_TIME_absolute_ntoh (rcc.timestamp);
- rhistory[off].details.close_details.timestamp = timestamp;
-
- key_state = TALER_EXCHANGE_get_keys (exchange);
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (key_state,
- &rhistory[off].details.close_details.exchange_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED,
- &rcc.purpose,
- &rhistory[off].details.close_details.exchange_sig.eddsa_signature,
- &rhistory[off].details.close_details.exchange_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_amount_add (&total_out,
- &total_out,
- &rhistory[off].amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* end type==CLOSING */
- }
- else
- {
- /* unexpected 'type', protocol incompatibility, complain! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
-
- /* check balance = total_in - total_out < withdraw-amount */
- if (GNUNET_SYSERR ==
- TALER_amount_subtract (balance,
- &total_in,
- &total_out))
- {
- /* total_in < total_out, why did the exchange ever allow this!? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Free memory (potentially) allocated by #parse_reserve_history().
- *
- * @param rhistory result to free
- * @param len number of entries in @a rhistory
- */
-static void
-free_rhistory (struct TALER_EXCHANGE_ReserveHistory *rhistory,
- unsigned int len)
-{
- for (unsigned int i=0;i<len;i++)
- {
- switch (rhistory[i].type)
- {
- case TALER_EXCHANGE_RTT_DEPOSIT:
- GNUNET_free_non_null (rhistory[i].details.in_details.wire_reference);
- GNUNET_free_non_null (rhistory[i].details.in_details.sender_url);
- break;
- case TALER_EXCHANGE_RTT_WITHDRAWAL:
- break;
- case TALER_EXCHANGE_RTT_PAYBACK:
- break;
- case TALER_EXCHANGE_RTT_CLOSE:
- // should we free "receiver_account_details" ?
- break;
- }
- }
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /reserve/status request.
- *
- * @param cls the `struct TALER_EXCHANGE_ReserveStatusHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_reserve_status_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_ReserveStatusHandle *rsh = cls;
- const json_t *j = response;
-
- rsh->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- /* TODO: move into separate function... */
- json_t *history;
- unsigned int len;
- struct TALER_Amount balance;
- struct TALER_Amount balance_from_history;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount ("balance", &balance),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL,
- NULL))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- history = json_object_get (j,
- "history");
- if (NULL == history)
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- len = json_array_size (history);
- {
- struct TALER_EXCHANGE_ReserveHistory rhistory[len];
-
- memset (rhistory, 0, sizeof (rhistory));
- if (GNUNET_OK !=
- parse_reserve_history (rsh->exchange,
- history,
- &rsh->reserve_pub,
- balance.currency,
- &balance_from_history,
- len,
- rhistory))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- if ( (0 != response_code) &&
- (0 !=
- TALER_amount_cmp (&balance_from_history,
- &balance)) )
- {
- /* exchange cannot add up balances!? */
- GNUNET_break_op (0);
- response_code = 0;
- }
- if (0 != response_code)
- {
- rsh->cb (rsh->cb_cls,
- response_code,
- TALER_EC_NONE,
- j,
- &balance,
- len,
- rhistory);
- rsh->cb = NULL;
- }
- free_rhistory (rhistory,
- len);
- }
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_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;
- }
- if (NULL != rsh->cb)
- {
- rsh->cb (rsh->cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- j,
- NULL,
- 0, NULL);
- rsh->cb = NULL;
- }
- TALER_EXCHANGE_reserve_status_cancel (rsh);
-}
-
-
-/**
- * Submit a request to obtain the transaction history of a reserve
- * from the exchange. Note that while we return the full response to the
- * caller for further processing, we do already verify that the
- * response is well-formed (i.e. that signatures included in the
- * response are all valid and add up to the balance). If the exchange's
- * reply is not well-formed, we return an HTTP status code of zero to
- * @a cb.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param reserve_pub public key of the reserve to inspect
- * @param cb the callback to call when a reply for this request is available
- * @param cb_cls closure for the above callback
- * @return a handle for this request; NULL if the inputs are invalid (i.e.
- * signatures fail to verify). In this case, the callback is not called.
- */
-struct TALER_EXCHANGE_ReserveStatusHandle *
-TALER_EXCHANGE_reserve_status (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- TALER_EXCHANGE_ReserveStatusResultCallback cb,
- void *cb_cls)
-{
- struct TALER_EXCHANGE_ReserveStatusHandle *rsh;
- struct GNUNET_CURL_Context *ctx;
- CURL *eh;
- char *pub_str;
- char *arg_str;
-
- if (GNUNET_YES !=
- TEAH_handle_is_ready (exchange))
- {
- GNUNET_break (0);
- return NULL;
- }
- pub_str = GNUNET_STRINGS_data_to_string_alloc (reserve_pub,
- sizeof (struct TALER_ReservePublicKeyP));
- GNUNET_asprintf (&arg_str,
- "/reserve/status?reserve_pub=%s",
- pub_str);
- GNUNET_free (pub_str);
- rsh = GNUNET_new (struct TALER_EXCHANGE_ReserveStatusHandle);
- rsh->exchange = exchange;
- rsh->cb = cb;
- rsh->cb_cls = cb_cls;
- rsh->reserve_pub = *reserve_pub;
- rsh->url = TEAH_path_to_url (exchange,
- arg_str);
- GNUNET_free (arg_str);
-
- eh = TEL_curl_easy_get (rsh->url);
- ctx = TEAH_handle_to_context (exchange);
- rsh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_NO,
- &handle_reserve_status_finished,
- rsh);
- return rsh;
-}
-
-
-/**
- * Cancel a reserve status request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param rsh the reserve status request handle
- */
-void
-TALER_EXCHANGE_reserve_status_cancel (struct TALER_EXCHANGE_ReserveStatusHandle *rsh)
-{
- if (NULL != rsh->job)
- {
- GNUNET_CURL_job_cancel (rsh->job);
- rsh->job = NULL;
- }
- GNUNET_free (rsh->url);
- GNUNET_free (rsh);
-}
-
-
-/* ********************** /reserve/withdraw ********************** */
-
-/**
- * @brief A Withdraw Sign Handle
- */
-struct TALER_EXCHANGE_ReserveWithdrawHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_ReserveWithdrawResultCallback cb;
-
- /**
- * Secrets of the planchet.
- */
- struct TALER_PlanchetSecretsP ps;
-
- /**
- * Denomination key we are withdrawing.
- */
- const struct TALER_EXCHANGE_DenomPublicKey *pk;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Hash of the public key of the coin we are signing.
- */
- struct GNUNET_HashCode c_hash;
-
- /**
- * Public key of the reserve we are withdrawing from.
- */
- struct TALER_ReservePublicKeyP reserve_pub;
-
-};
-
-
-/**
- * We got a 200 OK response for the /reserve/withdraw operation.
- * Extract the coin's signature and return it to the caller.
- * The signature we get from the exchange is for the blinded value.
- * Thus, we first must unblind it and then should verify its
- * validity against our coin's hash.
- *
- * If everything checks out, we return the unblinded signature
- * to the application via the callback.
- *
- * @param wsh operation handle
- * @param json reply from the exchange
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static int
-reserve_withdraw_ok (struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh,
- const json_t *json)
-{
- struct GNUNET_CRYPTO_RsaSignature *blind_sig;
- struct TALER_FreshCoin fc;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_rsa_signature ("ev_sig",
- &blind_sig),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_planchet_to_coin (&wsh->pk->key,
- blind_sig,
- &wsh->ps,
- &wsh->c_hash,
- &fc))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- GNUNET_JSON_parse_free (spec);
-
- /* signature is valid, return it to the application */
- wsh->cb (wsh->cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- &fc.sig,
- json);
- /* make sure callback isn't called again after return */
- wsh->cb = NULL;
- GNUNET_CRYPTO_rsa_signature_free (fc.sig.rsa_signature);
- return GNUNET_OK;
-}
-
-
-/**
- * We got a 403 FORBIDDEN response for the /reserve/withdraw operation.
- * Check the signatures on the withdraw transactions in the provided
- * history and that the balances add up. We don't do anything directly
- * with the information, as the JSON will be returned to the application.
- * However, our job is ensuring that the exchange followed the protocol, and
- * this in particular means checking all of the signatures in the history.
- *
- * @param wsh operation handle
- * @param json reply from the exchange
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static int
-reserve_withdraw_payment_required (struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh,
- const json_t *json)
-{
- struct TALER_Amount balance;
- struct TALER_Amount balance_from_history;
- struct TALER_Amount requested_amount;
- json_t *history;
- size_t len;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount ("balance", &balance),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- history = json_object_get (json,
- "history");
- if (NULL == history)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* go over transaction history and compute
- total incoming and outgoing amounts */
- len = json_array_size (history);
- {
- struct TALER_EXCHANGE_ReserveHistory *rhistory;
-
- /* Use heap allocation as "len" may be very big and thus this may
- not fit on the stack. Use "GNUNET_malloc_large" as a malicious
- exchange may theoretically try to crash us by giving a history
- that does not fit into our memory. */
- rhistory = GNUNET_malloc_large (sizeof (struct TALER_EXCHANGE_ReserveHistory) * len);
- if (NULL == rhistory)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
-
- if (GNUNET_OK !=
- parse_reserve_history (wsh->exchange,
- history,
- &wsh->reserve_pub,
- balance.currency,
- &balance_from_history,
- len,
- rhistory))
- {
- GNUNET_break_op (0);
- free_rhistory (rhistory,
- len);
- return GNUNET_SYSERR;
- }
- free_rhistory (rhistory,
- len);
- }
-
- if (0 !=
- TALER_amount_cmp (&balance_from_history,
- &balance))
- {
- /* exchange cannot add up balances!? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* Compute how much we expected to charge to the reserve */
- if (GNUNET_OK !=
- TALER_amount_add (&requested_amount,
- &wsh->pk->value,
- &wsh->pk->fee_withdraw))
- {
- /* Overflow here? Very strange, our CPU must be fried... */
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- /* Check that funds were really insufficient */
- if (0 >= TALER_amount_cmp (&requested_amount,
- &balance))
- {
- /* Requested amount is smaller or equal to reported balance,
- so this should not have failed. */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /reserve/withdraw request.
- *
- * @param cls the `struct TALER_EXCHANGE_ReserveWithdrawHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_reserve_withdraw_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh = cls;
- const json_t *j = response;
-
- wsh->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- reserve_withdraw_ok (wsh,
- j))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_FORBIDDEN:
- /* The exchange says that the reserve has insufficient funds;
- check the signatures in the history... */
- if (GNUNET_OK !=
- reserve_withdraw_payment_required (wsh,
- j))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_UNAUTHORIZED:
- GNUNET_break (0);
- /* Nothing really to verify, exchange 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, the exchange basically just says
- that it doesn't know this reserve. Can happen if we
- query before the wire transfer went through.
- We should simply 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;
- }
- if (NULL != wsh->cb)
- {
- wsh->cb (wsh->cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- NULL,
- j);
- wsh->cb = NULL;
- }
- TALER_EXCHANGE_reserve_withdraw_cancel (wsh);
-}
-
-
-/**
- * Helper function for #TALER_EXCHANGE_reserve_withdraw2() and
- * #TALER_EXCHANGE_reserve_withdraw().
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param pk kind of coin to create
- * @param reserve_sig signature from the reserve authorizing the withdrawal
- * @param reserve_pub public key of the reserve to withdraw from
- * @param ps secrets of the planchet
- * caller must have committed this value to disk before the call (with @a pk)
- * @param pd planchet details matching @a ps
- * @param res_cb the callback to call when the final result for this request is available
- * @param res_cb_cls closure for @a res_cb
- * @return NULL
- * if the inputs are invalid (i.e. denomination key not with this exchange).
- * In this case, the callback is not called.
- */
-struct TALER_EXCHANGE_ReserveWithdrawHandle *
-reserve_withdraw_internal (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_EXCHANGE_DenomPublicKey *pk,
- const struct TALER_ReserveSignatureP *reserve_sig,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_PlanchetSecretsP *ps,
- const struct TALER_PlanchetDetail *pd,
- TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
- void *res_cb_cls)
-{
- struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
- struct GNUNET_CURL_Context *ctx;
- json_t *withdraw_obj;
- CURL *eh;
-
- wsh = GNUNET_new (struct TALER_EXCHANGE_ReserveWithdrawHandle);
- wsh->exchange = exchange;
- wsh->cb = res_cb;
- wsh->cb_cls = res_cb_cls;
- wsh->pk = pk;
- wsh->reserve_pub = *reserve_pub;
- wsh->c_hash = pd->c_hash;
- withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub and coin_ev */
- " s:o, s:o}",/* reserve_pub and reserve_sig */
- "denom_pub", GNUNET_JSON_from_rsa_public_key (pk->key.rsa_public_key),
- "coin_ev", GNUNET_JSON_from_data (pd->coin_ev,
- pd->coin_ev_size),
- "reserve_pub", GNUNET_JSON_from_data_auto (reserve_pub),
- "reserve_sig", GNUNET_JSON_from_data_auto (reserve_sig));
- if (NULL == withdraw_obj)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- wsh->ps = *ps;
- wsh->url = TEAH_path_to_url (exchange, "/reserve/withdraw");
-
- eh = TEL_curl_easy_get (wsh->url);
- GNUNET_assert (NULL != (wsh->json_enc =
- json_dumps (withdraw_obj,
- JSON_COMPACT)));
- json_decref (withdraw_obj);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- wsh->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (wsh->json_enc)));
- ctx = TEAH_handle_to_context (exchange);
- wsh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_reserve_withdraw_finished,
- wsh);
- return wsh;
-}
-
-
-/**
- * Withdraw a coin from the exchange using a /reserve/withdraw request. Note
- * that to ensure that no money is lost in case of hardware failures,
- * the caller must have committed (most of) the arguments to disk
- * before calling, and be ready to repeat the request with the same
- * arguments in case of failures.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param pk kind of coin to create
- * @param reserve_priv private key of the reserve to withdraw from
- * @param ps secrets of the planchet
- * caller must have committed this value to disk before the call (with @a pk)
- * @param res_cb the callback to call when the final result for this request is available
- * @param res_cb_cls closure for the above callback
- * @return handle for the operation on success, NULL on error, i.e.
- * if the inputs are invalid (i.e. denomination key not with this exchange).
- * In this case, the callback is not called.
- */
-struct TALER_EXCHANGE_ReserveWithdrawHandle *
-TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_EXCHANGE_DenomPublicKey *pk,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_PlanchetSecretsP *ps,
- TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
- void *res_cb_cls)
-{
- struct TALER_Amount amount_with_fee;
- struct TALER_ReserveSignatureP reserve_sig;
- struct TALER_WithdrawRequestPS req;
- struct TALER_PlanchetDetail pd;
- struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
-
- GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
- &req.reserve_pub.eddsa_pub);
- req.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
- req.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
- if (GNUNET_OK !=
- TALER_amount_add (&amount_with_fee,
- &pk->fee_withdraw,
- &pk->value))
- {
- /* exchange gave us denomination keys that overflow like this!? */
- GNUNET_break_op (0);
- return NULL;
- }
- TALER_amount_hton (&req.amount_with_fee,
- &amount_with_fee);
- TALER_amount_hton (&req.withdraw_fee,
- &pk->fee_withdraw);
- if (GNUNET_OK !=
- TALER_planchet_prepare (&pk->key,
- ps,
- &pd))
- {
- GNUNET_break_op (0);
- return NULL;
- }
- req.h_denomination_pub = pd.denom_pub_hash;
- GNUNET_CRYPTO_hash (pd.coin_ev,
- pd.coin_ev_size,
- &req.h_coin_envelope);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
- &req.purpose,
- &reserve_sig.eddsa_signature));
- wsh = reserve_withdraw_internal (exchange,
- pk,
- &reserve_sig,
- &req.reserve_pub,
- ps,
- &pd,
- res_cb,
- res_cb_cls);
- GNUNET_free (pd.coin_ev);
- return wsh;
-}
-
-
-/**
- * Withdraw a coin from the exchange using a /reserve/withdraw
- * request. This API is typically used by a wallet to withdraw a tip
- * where the reserve's signature was created by the merchant already.
- *
- * Note that to ensure that no money is lost in case of hardware
- * failures, the caller must have committed (most of) the arguments to
- * disk before calling, and be ready to repeat the request with the
- * same arguments in case of failures.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param pk kind of coin to create
- * @param reserve_sig signature from the reserve authorizing the withdrawal
- * @param reserve_pub public key of the reserve to withdraw from
- * @param ps secrets of the planchet
- * caller must have committed this value to disk before the call (with @a pk)
- * @param res_cb the callback to call when the final result for this request is available
- * @param res_cb_cls closure for @a res_cb
- * @return NULL
- * if the inputs are invalid (i.e. denomination key not with this exchange).
- * In this case, the callback is not called.
- */
-struct TALER_EXCHANGE_ReserveWithdrawHandle *
-TALER_EXCHANGE_reserve_withdraw2 (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_EXCHANGE_DenomPublicKey *pk,
- const struct TALER_ReserveSignatureP *reserve_sig,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_PlanchetSecretsP *ps,
- TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
- void *res_cb_cls)
-{
- struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
- struct TALER_PlanchetDetail pd;
-
- if (GNUNET_OK !=
- TALER_planchet_prepare (&pk->key,
- ps,
- &pd))
- {
- GNUNET_break_op (0);
- return NULL;
- }
- wsh = reserve_withdraw_internal (exchange,
- pk,
- reserve_sig,
- reserve_pub,
- ps,
- &pd,
- res_cb,
- res_cb_cls);
- GNUNET_free (pd.coin_ev);
- return wsh;
-}
-
-
-/**
- * Cancel a withdraw status request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param sign the withdraw sign request handle
- */
-void
-TALER_EXCHANGE_reserve_withdraw_cancel (struct TALER_EXCHANGE_ReserveWithdrawHandle *sign)
-{
- if (NULL != sign->job)
- {
- GNUNET_CURL_job_cancel (sign->job);
- sign->job = NULL;
- }
- GNUNET_free (sign->url);
- GNUNET_free (sign->json_enc);
- GNUNET_free (sign);
-}
-
-
-/* end of exchange_api_reserve.c */
diff --git a/src/exchange-lib/exchange_api_track_transaction.c b/src/exchange-lib/exchange_api_track_transaction.c
deleted file mode 100644
index d61344e59..000000000
--- a/src/exchange-lib/exchange_api_track_transaction.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015, 2016 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_track_transaction.c
- * @brief Implementation of the /track/transaction request of the exchange's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_json_lib.h"
-#include "taler_exchange_service.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "curl_defaults.h"
-
-
-/**
- * @brief A Deposit Wtid Handle
- */
-struct TALER_EXCHANGE_TrackTransactionHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_TrackTransactionCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Information the exchange should sign in response.
- * (with pre-filled fields from the request).
- */
- struct TALER_ConfirmWirePS depconf;
-
-};
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * from the exchange is valid.
- *
- * @param dwh deposit wtid handle
- * @param json json reply with the signature
- * @param[out] exchange_pub set to the exchange's public key
- * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
- */
-static int
-verify_deposit_wtid_signature_ok (const struct TALER_EXCHANGE_TrackTransactionHandle *dwh,
- const json_t *json,
- struct TALER_ExchangePublicKeyP *exchange_pub)
-{
- struct TALER_ExchangeSignatureP exchange_sig;
- const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub", exchange_pub),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- key_state = TALER_EXCHANGE_get_keys (dwh->exchange);
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (key_state,
- exchange_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE,
- &dwh->depconf.purpose,
- &exchange_sig.eddsa_signature,
- &exchange_pub->eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /track/transaction request.
- *
- * @param cls the `struct TALER_EXCHANGE_TrackTransactionHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_deposit_wtid_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_TrackTransactionHandle *dwh = cls;
- const struct TALER_WireTransferIdentifierRawP *wtid = NULL;
- struct GNUNET_TIME_Absolute execution_time = GNUNET_TIME_UNIT_FOREVER_ABS;
- const struct TALER_Amount *coin_contribution = NULL;
- struct TALER_Amount coin_contribution_s;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangePublicKeyP *ep = NULL;
- const json_t *j = response;
-
- dwh->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("wtid", &dwh->depconf.wtid),
- GNUNET_JSON_spec_absolute_time ("execution_time", &execution_time),
- TALER_JSON_spec_amount ("coin_contribution", &coin_contribution_s),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- wtid = &dwh->depconf.wtid;
- dwh->depconf.execution_time = GNUNET_TIME_absolute_hton (execution_time);
- TALER_amount_hton (&dwh->depconf.coin_contribution,
- &coin_contribution_s);
- coin_contribution = &coin_contribution_s;
- if (GNUNET_OK !=
- verify_deposit_wtid_signature_ok (dwh,
- j,
- &exchange_pub))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- else
- {
- ep = &exchange_pub;
- }
- }
- break;
- case MHD_HTTP_ACCEPTED:
- {
- /* Transaction known, but not executed yet */
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_absolute_time ("execution_time", &execution_time),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, exchange 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:
- /* Exchange does not know about transaction;
- we should pass the 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;
- }
- dwh->cb (dwh->cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- ep,
- j,
- wtid,
- execution_time,
- coin_contribution);
- TALER_EXCHANGE_track_transaction_cancel (dwh);
-}
-
-
-/**
- * Obtain wire transfer details about an existing deposit operation.
- *
- * @param exchange the exchange to query
- * @param merchant_priv the merchant's private key
- * @param h_wire hash of merchant's wire transfer details
- * @param h_contract_terms hash of the proposal data from the contract
- * between merchant and customer
- * @param coin_pub public key of the coin
- * @param cb function to call with the result
- * @param cb_cls closure for @a cb
- * @return handle to abort request
- */
-struct TALER_EXCHANGE_TrackTransactionHandle *
-TALER_EXCHANGE_track_transaction (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_MerchantPrivateKeyP *merchant_priv,
- const struct GNUNET_HashCode *h_wire,
- const struct GNUNET_HashCode *h_contract_terms,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- TALER_EXCHANGE_TrackTransactionCallback cb,
- void *cb_cls)
-{
- struct TALER_DepositTrackPS dtp;
- struct TALER_MerchantSignatureP merchant_sig;
- struct TALER_EXCHANGE_TrackTransactionHandle *dwh;
- struct GNUNET_CURL_Context *ctx;
- json_t *deposit_wtid_obj;
- CURL *eh;
-
- if (GNUNET_YES !=
- TEAH_handle_is_ready (exchange))
- {
- GNUNET_break (0);
- return NULL;
- }
- dtp.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION);
- dtp.purpose.size = htonl (sizeof (dtp));
- dtp.h_contract_terms = *h_contract_terms;
- dtp.h_wire = *h_wire;
- GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv,
- &dtp.merchant.eddsa_pub);
-
- dtp.coin_pub = *coin_pub;
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_eddsa_sign (&merchant_priv->eddsa_priv,
- &dtp.purpose,
- &merchant_sig.eddsa_sig));
- deposit_wtid_obj = json_pack ("{s:o, s:o," /* H_wire, h_contract_terms */
- " s:o," /* coin_pub */
- " s:o, s:o}", /* merchant_pub, merchant_sig */
- "H_wire", GNUNET_JSON_from_data_auto (h_wire),
- "h_contract_terms", GNUNET_JSON_from_data_auto (h_contract_terms),
- "coin_pub", GNUNET_JSON_from_data_auto (coin_pub),
- "merchant_pub", GNUNET_JSON_from_data_auto (&dtp.merchant),
- "merchant_sig", GNUNET_JSON_from_data_auto (&merchant_sig));
- if (NULL == deposit_wtid_obj)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- dwh = GNUNET_new (struct TALER_EXCHANGE_TrackTransactionHandle);
- dwh->exchange = exchange;
- dwh->cb = cb;
- dwh->cb_cls = cb_cls;
- dwh->url = TEAH_path_to_url (exchange, "/track/transaction");
- dwh->depconf.purpose.size = htonl (sizeof (struct TALER_ConfirmWirePS));
- dwh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE);
- dwh->depconf.h_wire = *h_wire;
- dwh->depconf.h_contract_terms = *h_contract_terms;
- dwh->depconf.coin_pub = *coin_pub;
-
- eh = TEL_curl_easy_get (dwh->url);
- GNUNET_assert (NULL != (dwh->json_enc =
- json_dumps (deposit_wtid_obj,
- JSON_COMPACT)));
- json_decref (deposit_wtid_obj);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- dwh->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (dwh->json_enc)));
- ctx = TEAH_handle_to_context (exchange);
- dwh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_deposit_wtid_finished,
- dwh);
- return dwh;
-}
-
-
-/**
- * Cancel deposit wtid request. This function cannot be used on a request
- * handle if a response is already served for it.
- *
- * @param dwh the wire deposits request handle
- */
-void
-TALER_EXCHANGE_track_transaction_cancel (struct TALER_EXCHANGE_TrackTransactionHandle *dwh)
-{
- if (NULL != dwh->job)
- {
- GNUNET_CURL_job_cancel (dwh->job);
- dwh->job = NULL;
- }
- GNUNET_free (dwh->url);
- GNUNET_free (dwh->json_enc);
- GNUNET_free (dwh);
-}
-
-
-/* end of exchange_api_deposit_wtid.c */
diff --git a/src/exchange-lib/exchange_api_track_transfer.c b/src/exchange-lib/exchange_api_track_transfer.c
deleted file mode 100644
index cf87fe77a..000000000
--- a/src/exchange-lib/exchange_api_track_transfer.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014, 2015, 2016 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_track_transfer.c
- * @brief Implementation of the /track/transfer request of the exchange's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_exchange_service.h"
-#include "taler_json_lib.h"
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "curl_defaults.h"
-
-
-/**
- * @brief A /track/transfer Handle
- */
-struct TALER_EXCHANGE_TrackTransferHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_TrackTransferCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
-};
-
-
-/**
- * We got a #MHD_HTTP_OK response for the /track/transfer request.
- * Check that the response is well-formed and if it is, call the
- * callback. If not, return an error code.
- *
- * This code is very similar to
- * merchant_api_track_transfer.c::check_track_transfer_response_ok.
- * Any changes should likely be reflected there as well.
- *
- * @param wdh handle to the operation
- * @param json response we got
- * @return #GNUNET_OK if we are done and all is well,
- * #GNUNET_SYSERR if the response was bogus
- */
-static int
-check_track_transfer_response_ok (struct TALER_EXCHANGE_TrackTransferHandle *wdh,
- const json_t *json)
-{
- json_t *details_j;
- struct GNUNET_HashCode h_wire;
- struct GNUNET_TIME_Absolute exec_time;
- struct TALER_Amount total_amount;
- struct TALER_Amount total_expected;
- struct TALER_Amount wire_fee;
- struct TALER_MerchantPublicKeyP merchant_pub;
- unsigned int num_details;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangeSignatureP exchange_sig;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount ("total", &total_amount),
- TALER_JSON_spec_amount ("wire_fee", &wire_fee),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub", &merchant_pub),
- GNUNET_JSON_spec_fixed_auto ("H_wire", &h_wire),
- GNUNET_JSON_spec_absolute_time ("execution_time", &exec_time),
- GNUNET_JSON_spec_json ("deposits", &details_j),
- GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_amount_get_zero (total_amount.currency,
- &total_expected))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- num_details = json_array_size (details_j);
- {
- struct TALER_TrackTransferDetails details[num_details];
- unsigned int i;
- struct GNUNET_HashContext *hash_context;
- struct TALER_WireDepositDetailP dd;
- struct TALER_WireDepositDataPS wdp;
-
- hash_context = GNUNET_CRYPTO_hash_context_start ();
- for (i=0;i<num_details;i++)
- {
- struct TALER_TrackTransferDetails *detail = &details[i];
- struct json_t *detail_j = json_array_get (details_j, i);
- struct GNUNET_JSON_Specification spec_detail[] = {
- GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &detail->h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("coin_pub", &detail->coin_pub),
- TALER_JSON_spec_amount ("deposit_value", &detail->coin_value),
- TALER_JSON_spec_amount ("deposit_fee", &detail->coin_fee),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (detail_j,
- spec_detail,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- GNUNET_CRYPTO_hash_context_abort (hash_context);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- /* build up big hash for signature checking later */
- dd.h_contract_terms = detail->h_contract_terms;
- dd.execution_time = GNUNET_TIME_absolute_hton (exec_time);
- dd.coin_pub = detail->coin_pub;
- TALER_amount_hton (&dd.deposit_value,
- &detail->coin_value);
- TALER_amount_hton (&dd.deposit_fee,
- &detail->coin_fee);
- if ( (GNUNET_OK !=
- TALER_amount_add (&total_expected,
- &total_expected,
- &detail->coin_value)) ||
- (GNUNET_OK !=
- TALER_amount_subtract (&total_expected,
- &total_expected,
- &detail->coin_fee)) )
- {
- GNUNET_break_op (0);
- GNUNET_CRYPTO_hash_context_abort (hash_context);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- GNUNET_CRYPTO_hash_context_read (hash_context,
- &dd,
- sizeof (struct TALER_WireDepositDetailP));
- }
- /* Check signature */
- wdp.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT);
- wdp.purpose.size = htonl (sizeof (struct TALER_WireDepositDataPS));
- TALER_amount_hton (&wdp.total,
- &total_amount);
- TALER_amount_hton (&wdp.wire_fee,
- &wire_fee);
- wdp.merchant_pub = merchant_pub;
- wdp.h_wire = h_wire;
- GNUNET_CRYPTO_hash_context_finish (hash_context,
- &wdp.h_details);
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (TALER_EXCHANGE_get_keys (wdh->exchange),
- &exchange_pub))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify
- (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT,
- &wdp.purpose,
- &exchange_sig.eddsa_signature,
- &exchange_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
-
- if (GNUNET_OK !=
- TALER_amount_subtract (&total_expected,
- &total_expected,
- &wire_fee))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- if (0 !=
- TALER_amount_cmp (&total_expected,
- &total_amount))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return GNUNET_SYSERR;
- }
- wdh->cb (wdh->cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- &exchange_pub,
- json,
- &h_wire,
- exec_time,
- &total_amount,
- &wire_fee,
- num_details,
- details);
- }
- GNUNET_JSON_parse_free (spec);
- TALER_EXCHANGE_track_transfer_cancel (wdh);
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /track/transfer request.
- *
- * @param cls the `struct TALER_EXCHANGE_TrackTransferHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_track_transfer_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_TrackTransferHandle *wdh = cls;
- const json_t *j = response;
-
- wdh->job = NULL;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK ==
- check_track_transfer_response_ok (wdh,
- j))
- return;
- GNUNET_break_op (0);
- response_code = 0;
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, exchange 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:
- /* Exchange does not know about transaction;
- we should pass the 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;
- }
- wdh->cb (wdh->cb_cls,
- response_code,
- TALER_JSON_get_error_code (j),
- NULL,
- j,
- NULL,
- GNUNET_TIME_UNIT_ZERO_ABS,
- NULL,
- NULL,
- 0, NULL);
- TALER_EXCHANGE_track_transfer_cancel (wdh);
-}
-
-
-/**
- * Query the exchange about which transactions were combined
- * to create a wire transfer.
- *
- * @param exchange exchange to query
- * @param wtid raw wire transfer identifier to get information about
- * @param cb callback to call
- * @param cb_cls closure for @a cb
- * @return handle to cancel operation
- */
-struct TALER_EXCHANGE_TrackTransferHandle *
-TALER_EXCHANGE_track_transfer (struct TALER_EXCHANGE_Handle *exchange,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- TALER_EXCHANGE_TrackTransferCallback cb,
- void *cb_cls)
-{
- struct TALER_EXCHANGE_TrackTransferHandle *wdh;
- struct GNUNET_CURL_Context *ctx;
- char *buf;
- char *path;
- CURL *eh;
-
- if (GNUNET_YES !=
- TEAH_handle_is_ready (exchange))
- {
- GNUNET_break (0);
- return NULL;
- }
-
- wdh = GNUNET_new (struct TALER_EXCHANGE_TrackTransferHandle);
- wdh->exchange = exchange;
- wdh->cb = cb;
- wdh->cb_cls = cb_cls;
-
- buf = GNUNET_STRINGS_data_to_string_alloc (wtid,
- sizeof (struct TALER_WireTransferIdentifierRawP));
- GNUNET_asprintf (&path,
- "/track/transfer?wtid=%s",
- buf);
- wdh->url = TEAH_path_to_url (wdh->exchange,
- path);
- GNUNET_free (buf);
- GNUNET_free (path);
-
- eh = TEL_curl_easy_get (wdh->url);
- ctx = TEAH_handle_to_context (exchange);
- wdh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_track_transfer_finished,
- wdh);
- return wdh;
-}
-
-
-/**
- * Cancel wire deposits request. This function cannot be used on a request
- * handle if a response is already served for it.
- *
- * @param wdh the wire deposits request handle
- */
-void
-TALER_EXCHANGE_track_transfer_cancel (struct TALER_EXCHANGE_TrackTransferHandle *wdh)
-{
- if (NULL != wdh->job)
- {
- GNUNET_CURL_job_cancel (wdh->job);
- wdh->job = NULL;
- }
- GNUNET_free (wdh->url);
- GNUNET_free (wdh);
-}
-
-
-/* end of exchange_api_wire_deposits.c */
diff --git a/src/exchange-lib/exchange_api_wire.c b/src/exchange-lib/exchange_api_wire.c
deleted file mode 100644
index 0d4644dbf..000000000
--- a/src/exchange-lib/exchange_api_wire.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/exchange_api_wire.c
- * @brief Implementation of the /wire request of the exchange's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_exchange_service.h"
-#include "taler_json_lib.h"
-#include "taler_wire_lib.h"
-#include "taler_signatures.h"
-#include "taler_wire_plugin.h"
-#include "exchange_api_handle.h"
-#include "curl_defaults.h"
-
-
-/**
- * @brief A Wire Handle
- */
-struct TALER_EXCHANGE_WireHandle
-{
-
- /**
- * The connection to exchange this request handle will use
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_EXCHANGE_WireResultCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
-};
-
-
-/**
- * List of wire fees by method.
- */
-struct FeeMap
-{
- /**
- * Next entry in list.
- */
- struct FeeMap *next;
-
- /**
- * Wire method this fee structure is for.
- */
- char *method;
-
- /**
- * Array of wire fees, also linked list, but allocated
- * only once.
- */
- struct TALER_EXCHANGE_WireAggregateFees *fee_list;
-};
-
-
-/**
- * Frees @a fm.
- *
- * @param fm memory to release
- */
-static void
-free_fees (struct FeeMap *fm)
-{
- while (NULL != fm)
- {
- struct FeeMap *fe = fm->next;
-
- GNUNET_free (fm->fee_list);
- GNUNET_free (fm->method);
- GNUNET_free (fm);
- fm = fe;
- }
-}
-
-
-/**
- * Parse wire @a fees and return map.
- *
- * @param fees json AggregateTransferFee to parse
- * @return NULL on error
- */
-static struct FeeMap *
-parse_fees (json_t *fees)
-{
- struct FeeMap *fm = NULL;
- const char *key;
- json_t *fee_array;
-
- json_object_foreach (fees, key, fee_array) {
- struct FeeMap *fe = GNUNET_new (struct FeeMap);
- int len;
- unsigned int idx;
- json_t *fee;
-
- if (0 == (len = json_array_size (fee_array)))
- {
- GNUNET_break_op (0);
- GNUNET_free (fe);
- continue; /* skip */
- }
- fe->method = GNUNET_strdup (key);
- fe->next = fm;
- fe->fee_list = GNUNET_new_array (len,
- struct TALER_EXCHANGE_WireAggregateFees);
- fm = fe;
- json_array_foreach (fee_array, idx, fee)
- {
- struct TALER_EXCHANGE_WireAggregateFees *wa = &fe->fee_list[idx];
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("sig",
- &wa->master_sig),
- TALER_JSON_spec_amount ("wire_fee",
- &wa->wire_fee),
- TALER_JSON_spec_amount ("closing_fee",
- &wa->closing_fee),
- GNUNET_JSON_spec_absolute_time ("start_date",
- &wa->start_date),
- GNUNET_JSON_spec_absolute_time ("end_date",
- &wa->end_date),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (fee,
- spec,
- NULL,
- NULL))
- {
- GNUNET_break_op (0);
- free_fees (fm);
- return NULL;
- }
- if (idx + 1 < len)
- wa->next = &fe->fee_list[idx + 1];
- else
- wa->next = NULL;
- }
- }
- return fm;
-}
-
-
-/**
- * Find fee by @a method.
- *
- * @param fm map to look in
- * @param method key to look for
- * @return NULL if fee is not specified in @a fm
- */
-static const struct TALER_EXCHANGE_WireAggregateFees *
-lookup_fee (const struct FeeMap *fm,
- const char *method)
-{
- for (;NULL != fm; fm = fm->next)
- if (0 == strcasecmp (fm->method,
- method))
- return fm->fee_list;
- return NULL;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /wire request.
- *
- * @param cls the `struct TALER_EXCHANGE_WireHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_wire_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_EXCHANGE_WireHandle *wh = cls;
- enum TALER_ErrorCode ec;
- const json_t *j = response;
-
- TALER_LOG_DEBUG ("Checking raw /wire response\n");
- wh->job = NULL;
- ec = TALER_EC_NONE;
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- json_t *accounts;
- json_t *fees;
- int num_accounts;
- struct FeeMap *fm;
- const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("accounts", &accounts),
- GNUNET_JSON_spec_json ("fees", &fees),
- GNUNET_JSON_spec_end()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- /* bogus reply */
- GNUNET_break_op (0);
- response_code = 0;
- ec = TALER_EC_SERVER_JSON_INVALID;
- break;
- }
- if (0 == (num_accounts = json_array_size (accounts)))
- {
- /* bogus reply */
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- response_code = 0;
- ec = TALER_EC_SERVER_JSON_INVALID;
- break;
- }
- if (NULL == (fm = parse_fees (fees)))
- {
- /* bogus reply */
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- response_code = 0;
- ec = TALER_EC_SERVER_JSON_INVALID;
- break;
- }
-
- key_state = TALER_EXCHANGE_get_keys (wh->exchange);
- /* parse accounts */
- {
- struct TALER_EXCHANGE_WireAccount was[num_accounts];
-
- for (unsigned int i=0;i<num_accounts;i++)
- {
- struct TALER_EXCHANGE_WireAccount *wa = &was[i];
- json_t *account;
- struct GNUNET_JSON_Specification spec_account[] = {
- GNUNET_JSON_spec_string ("url", &wa->url),
- GNUNET_JSON_spec_fixed_auto ("master_sig", &wa->master_sig),
- GNUNET_JSON_spec_end()
- };
- char *method;
-
- account = json_array_get (accounts,
- i);
- if (GNUNET_OK !=
- TALER_JSON_exchange_wire_signature_check (account,
- &key_state->master_pub))
- {
- /* bogus reply */
- GNUNET_break_op (0);
- response_code = 0;
- ec = TALER_EC_SERVER_SIGNATURE_INVALID;
- break;
- }
- if (GNUNET_OK !=
- GNUNET_JSON_parse (account,
- spec_account,
- NULL, NULL))
- {
- /* bogus reply */
- GNUNET_break_op (0);
- response_code = 0;
- ec = TALER_EC_SERVER_JSON_INVALID;
- break;
- }
- if (NULL == (method = TALER_WIRE_payto_get_method (wa->url)))
- {
- /* bogus reply */
- GNUNET_break_op (0);
- response_code = 0;
- ec = TALER_EC_SERVER_JSON_INVALID;
- break;
- }
- if (NULL == (wa->fees = lookup_fee (fm,
- method)))
- {
- /* bogus reply */
- GNUNET_break_op (0);
- response_code = 0;
- ec = TALER_EC_SERVER_JSON_INVALID;
- GNUNET_free (method);
- break;
- }
- GNUNET_free (method);
- } /* end 'for all accounts */
- if ( (0 != response_code) &&
- (NULL != wh->cb) )
- {
- wh->cb (wh->cb_cls,
- response_code,
- TALER_EC_NONE,
- num_accounts,
- was);
- wh->cb = NULL;
- }
- } /* end of 'parse accounts */
- free_fees (fm);
- GNUNET_JSON_parse_free (spec);
- } /* end of MHD_HTTP_OK */
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the exchange is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_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;
- }
- if (NULL != wh->cb)
- wh->cb (wh->cb_cls,
- response_code,
- (0 == response_code) ? ec : TALER_JSON_get_error_code (j),
- 0,
- NULL);
- TALER_EXCHANGE_wire_cancel (wh);
-}
-
-
-/**
- * Obtain information about a exchange's wire instructions.
- * A exchange may provide wire instructions for creating
- * a reserve. The wire instructions also indicate
- * which wire formats merchants may use with the exchange.
- * This API is typically used by a wallet for wiring
- * funds, and possibly by a merchant to determine
- * supported wire formats.
- *
- * Note that while we return the (main) response verbatim to the
- * caller for further processing, we do already verify that the
- * response is well-formed (i.e. that signatures included in the
- * response are all valid). If the exchange's reply is not well-formed,
- * we return an HTTP status code of zero to @a cb.
- *
- * @param exchange the exchange handle; the exchange must be ready to operate
- * @param wire_cb the callback to call when a reply for this request is available
- * @param wire_cb_cls closure for the above callback
- * @return a handle for this request
- */
-struct TALER_EXCHANGE_WireHandle *
-TALER_EXCHANGE_wire (struct TALER_EXCHANGE_Handle *exchange,
- TALER_EXCHANGE_WireResultCallback wire_cb,
- void *wire_cb_cls)
-{
- struct TALER_EXCHANGE_WireHandle *wh;
- struct GNUNET_CURL_Context *ctx;
- CURL *eh;
-
- if (GNUNET_YES !=
- TEAH_handle_is_ready (exchange))
- {
- GNUNET_break (0);
- return NULL;
- }
- wh = GNUNET_new (struct TALER_EXCHANGE_WireHandle);
- wh->exchange = exchange;
- wh->cb = wire_cb;
- wh->cb_cls = wire_cb_cls;
- wh->url = TEAH_path_to_url (exchange, "/wire");
-
- eh = TEL_curl_easy_get (wh->url);
- ctx = TEAH_handle_to_context (exchange);
- wh->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_wire_finished,
- wh);
- return wh;
-}
-
-
-/**
- * Cancel a wire information request. This function cannot be used
- * on a request handle if a response is already served for it.
- *
- * @param wh the wire information request handle
- */
-void
-TALER_EXCHANGE_wire_cancel (struct TALER_EXCHANGE_WireHandle *wh)
-{
- if (NULL != wh->job)
- {
- GNUNET_CURL_job_cancel (wh->job);
- wh->job = NULL;
- }
- GNUNET_free (wh->url);
- GNUNET_free (wh);
-}
-
-
-/* end of exchange_api_wire.c */
diff --git a/src/exchange-lib/test_exchange_api.conf b/src/exchange-lib/test_exchange_api.conf
deleted file mode 100644
index a44bab3ae..000000000
--- a/src/exchange-lib/test_exchange_api.conf
+++ /dev/null
@@ -1,203 +0,0 @@
-
-# This file is in the public domain.
-#
-[PATHS]
-# Persistant data storage for the testcase
-TALER_TEST_HOME = test_exchange_api_home/
-
-[taler]
-# Currency supported by the exchange (can only be one)
-CURRENCY = EUR
-
-[auditor]
-BASE_URL = "http://localhost:8083/"
-
-# HTTP port the auditor listens to
-PORT = 8083
-
-
-[exchange]
-
-# how long is one signkey valid?
-signkey_duration = 4 weeks
-
-# how long are the signatures with the signkey valid?
-legal_duration = 2 years
-
-# how long do we provide to clients denomination and signing keys
-# ahead of time?
-lookahead_provide = 4 weeks 1 day
-
-# HTTP port the exchange listens to
-PORT = 8081
-
-# Master public key used to sign the exchange's various keys
-MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
-
-# How to access our database
-DB = postgres
-
-# Base URL of the exchange. Must be set to a URL where the
-# exchange (or the twister) is actually listening.
-BASE_URL = "http://localhost:8081/"
-
-# Keep it short so the test runs fast.
-LOOKAHEAD_SIGN = 12 h
-
-[exchangedb-postgres]
-CONFIG = "postgres:///talercheck"
-
-[auditordb-postgres]
-CONFIG = "postgres:///talercheck"
-
-# Sections starting with "account-" configure the bank accounts
-# of the exchange. The "URL" specifies the account in
-# payto://-format, while the WIRE_JSON specifies the
-# (possibly offline) signed version to be returned in /wire.
-# WIRE_JSON is optional, as not all accounts must be
-# advertised in /wire.
-[account-1]
-# What is the URL of our account?
-URL = "payto://sepa/CH9300762011623852957"
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-1.json
-# Which wire plugin should we used to access the account?
-PLUGIN = ebics
-
-# ENABLE_CREDIT = YES
-
-[account-2]
-# What is the bank account (with the "Taler Bank" demo system)?
-URL = "payto://x-taler-bank/localhost:8082/2"
-
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-2.json
-
-# Which wire plugin should we used to access the account?
-PLUGIN = taler_bank
-
-# Authentication information for basic authentication
-TALER_BANK_AUTH_METHOD = "basic"
-USERNAME = user
-PASSWORD = pass
-
-ENABLE_DEBIT = YES
-
-ENABLE_CREDIT = YES
-
-
-# Sections starting with "fee-" configure the wire fee for the
-# respective wire method.
-[fees-sepa]
-# Fees for the forseeable future...
-# If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2018 = EUR:0.01
-WIRE-FEE-2019 = EUR:0.01
-WIRE-FEE-2020 = EUR:0.01
-WIRE-FEE-2021 = EUR:0.01
-WIRE-FEE-2022 = EUR:0.01
-WIRE-FEE-2023 = EUR:0.01
-WIRE-FEE-2024 = EUR:0.01
-WIRE-FEE-2025 = EUR:0.01
-WIRE-FEE-2026 = EUR:0.01
-WIRE-FEE-2027 = EUR:0.01
-
-CLOSING-FEE-2018 = EUR:0.01
-CLOSING-FEE-2019 = EUR:0.01
-CLOSING-FEE-2020 = EUR:0.01
-CLOSING-FEE-2021 = EUR:0.01
-CLOSING-FEE-2022 = EUR:0.01
-CLOSING-FEE-2023 = EUR:0.01
-CLOSING-FEE-2024 = EUR:0.01
-CLOSING-FEE-2025 = EUR:0.01
-CLOSING-FEE-2026 = EUR:0.01
-CLOSING-FEE-2027 = EUR:0.01
-
-[fees-x-taler-bank]
-# Fees for the forseeable future...
-# If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2018 = EUR:0.01
-WIRE-FEE-2019 = EUR:0.01
-WIRE-FEE-2020 = EUR:0.01
-WIRE-FEE-2021 = EUR:0.01
-WIRE-FEE-2022 = EUR:0.01
-WIRE-FEE-2023 = EUR:0.01
-WIRE-FEE-2024 = EUR:0.01
-WIRE-FEE-2025 = EUR:0.01
-WIRE-FEE-2026 = EUR:0.01
-WIRE-FEE-2027 = EUR:0.01
-
-CLOSING-FEE-2018 = EUR:0.01
-CLOSING-FEE-2019 = EUR:0.01
-CLOSING-FEE-2020 = EUR:0.01
-CLOSING-FEE-2021 = EUR:0.01
-CLOSING-FEE-2022 = EUR:0.01
-CLOSING-FEE-2023 = EUR:0.01
-CLOSING-FEE-2024 = EUR:0.01
-CLOSING-FEE-2025 = EUR:0.01
-CLOSING-FEE-2026 = EUR:0.01
-CLOSING-FEE-2027 = EUR:0.01
-
-# Sections starting with "coin_" specify which denominations
-# the exchange should support (and their respective fee structure)
-[coin_eur_ct_1]
-value = EUR:0.01
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.00
-fee_deposit = EUR:0.00
-fee_refresh = EUR:0.01
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_ct_10]
-value = EUR:0.10
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_1]
-value = EUR:1
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_5]
-value = EUR:5
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_10]
-value = EUR:10
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
diff --git a/src/exchange-lib/test_exchange_api_expire_reserve_now.conf b/src/exchange-lib/test_exchange_api_expire_reserve_now.conf
deleted file mode 100644
index 05bca956b..000000000
--- a/src/exchange-lib/test_exchange_api_expire_reserve_now.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-@INLINE@ test_exchange_api.conf
-
-[exchangedb]
-IDLE_RESERVE_EXPIRATION_TIME = 0 s
diff --git a/src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json b/src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json
deleted file mode 100644
index 48093f2aa..000000000
--- a/src/exchange-lib/test_exchange_api_home/.config/taler/account-1.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "url": "payto://sepa/CH9300762011623852957",
- "salt": "N83T9J9202WCC8TQFDMJDWEGZNBEKA33C1ZM241VNYH88RZNTHPW509Y1M2YF7Y098R8VRESWQ05H03BK1SPAZCWE54KARDCKT5N8AG",
- "master_sig": "D4V5GJ998YK7D6N0N56AD0J6MZNFEW6MRZT2CFPVQ5ME3NMQ59AA2007CXYESSFGRN70CNCFM06858QSSENCWTZM8VHEJ93YQ20ZJ1R"
-} \ No newline at end of file
diff --git a/src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json b/src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json
deleted file mode 100644
index 159e03171..000000000
--- a/src/exchange-lib/test_exchange_api_home/.config/taler/account-2.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "url": "payto://x-taler-bank/localhost:8082/2",
- "master_sig": "HC47BZN3C0KJ2VPMJ5EJWD2FXJ72AET0NWFE6JGSGK5CXS4GSKJJ6Z7BTS56JWM7B40SD61Z5GYYMRRE3X9JTJBVMWE0X7XHNXQ9P38"
-} \ No newline at end of file
diff --git a/src/exchange-lib/test_exchange_api_home/.config/taler/sepa.json b/src/exchange-lib/test_exchange_api_home/.config/taler/sepa.json
deleted file mode 100644
index b435ce86b..000000000
--- a/src/exchange-lib/test_exchange_api_home/.config/taler/sepa.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "Max Musterman",
- "bic": "COBADEFF370",
- "type": "sepa",
- "sig": "4EVRC2MCJPXQC8MC00831DNWEXMZAP4JQDDE1A7R6KR3MANG24RC1VQ55AX5A2E35S58VW1VSTENFTPHG5MWG9BSN8B8WXSV21KKW20",
- "address": "Musterstadt",
- "salt": "3KTM1ZRMWGEQPQ254S4R5R4Q8XM0ZYWTCTE01TZ76MVBSQ6RX7A5DR08WXVH1DCHR1R7ACRB7X0EVC2XDW1CBZM9WFSD9TRMZ90BR98",
- "iban": "DE89370400440532013000"
-} \ No newline at end of file
diff --git a/src/exchange-lib/test_exchange_api_home/.config/taler/test.json b/src/exchange-lib/test_exchange_api_home/.config/taler/test.json
deleted file mode 100644
index eca394241..000000000
--- a/src/exchange-lib/test_exchange_api_home/.config/taler/test.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "salt": "AZPRFVJ58NM6M7J5CZQPJAH3EW5DYM52AEZ9Y1C1ER3W94QV8D8TQKF6CK8MYQRA9QMSKDQTGZ306ZS9GQ0M6R01CJ20KPP49WFDZK8",
- "name": "The exchange",
- "account_number": 3,
- "bank_url": "http://localhost:8082/",
- "type": "test",
- "sig": "RPQXP9S4P8PQP7HEZQNRSZCT0ATNEP8GW0P5TPM34V5RX86FCD670V44R9NETSYDDKB8SZV7TKY9PAJYTY51D3VDWY9XXQ5BPFRXR28"
-}
diff --git a/src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json b/src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json
deleted file mode 100644
index a15df27ca..000000000
--- a/src/exchange-lib/test_exchange_api_home/.config/taler/x-taler-bank.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "url": "payto://x-taler-bank/http://localhost:8082/2",
- "master_sig": "KQ0BWSCNVR7HGGSAMCYK8ZM30RBS1MHMXT3QBN01PZWC9TV72FEE5RJ7T84C8134EPV6WEBXXY2MTFNE8ZXST6JEJQKR8HX6FQPVY10"
-} \ No newline at end of file
diff --git a/src/exchange-lib/test_exchange_api_home/.local/share/taler/exchange/offline-keys/master.priv b/src/exchange-lib/test_exchange_api_home/.local/share/taler/exchange/offline-keys/master.priv
deleted file mode 100644
index 394926938..000000000
--- a/src/exchange-lib/test_exchange_api_home/.local/share/taler/exchange/offline-keys/master.priv
+++ /dev/null
@@ -1 +0,0 @@
-pÚ^ó-Ú33ˆ€XXÁ!ˆ\0qúýµmUþ_‰ˆ \ No newline at end of file
diff --git a/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf b/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf
deleted file mode 100644
index 8d5585e3a..000000000
--- a/src/exchange-lib/test_exchange_api_keys_cherry_picking.conf
+++ /dev/null
@@ -1,161 +0,0 @@
-# This file is in the public domain.
-#
-[PATHS]
-# Persistent data storage for the testcase
-TALER_TEST_HOME = test_exchange_api_home/
-
-[taler]
-# Currency supported by the exchange (can only be one)
-CURRENCY = EUR
-
-[auditor]
-BASE_URL = "http://localhost:8083/"
-
-# HTTP port the auditor listens to
-PORT = 8083
-
-[exchange]
-
-# how long is one signkey valid?
-signkey_duration = 5 seconds
-
-# how long are the signatures with the signkey valid?
-legal_duration = 2 years
-
-# how long do we provide to clients denomination and signing keys
-# ahead of time?
-lookahead_provide = 30 seconds
-
-# Keep it short so we can prolong later!
-LOOKAHEAD_SIGN = 60 s
-
-
-# HTTP port the exchange listens to
-PORT = 8081
-
-# Master public key used to sign the exchange's various keys
-MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
-
-# How to access our database
-DB = postgres
-
-# Base URL of the exchange. Must be set to a URL where the
-# exchange (or the twister) is actually listening.
-BASE_URL = "http://localhost:8081/"
-
-
-[exchangedb-postgres]
-CONFIG = "postgres:///talercheck"
-
-[auditordb-postgres]
-CONFIG = "postgres:///talercheck"
-
-
-[account-1]
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-WIRE_RESPONSE = ${TALER_CONFIG_HOME}/iban.json
-
-# What is the URL of our bank account? Must match WIRE_RESPONSE above!
-URL = payto://sepa/FIXME
-
-# Which plugin implements access for this account?
-PLUGIN = "ebics"
-
-
-[account-2]
-# This is the response we give out for the /wire request. It provides
-# wallets with the bank information for transfers to the exchange.
-WIRE_RESPONSE = ${TALER_CONFIG_HOME}/x-taler-bank.json
-
-# What is the URL of our bank account? Must match WIRE_RESPONSE above!
-URL = payto://x-taler-bank/http://localhost:8082/2
-
-# Which plugin implements access for this account?
-PLUGIN = "taler_bank"
-
-# Authentication information for basic authentication
-TALER_BANK_AUTH_METHOD = "basic"
-USERNAME = user
-PASSWORD = pass
-
-ENABLE_DEBIT = YES
-
-ENABLE_CREDIT = YES
-
-
-
-
-[fees-x-taler-bank]
-# Fees for the forseeable future...
-# If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2017 = EUR:0.01
-WIRE-FEE-2018 = EUR:0.01
-WIRE-FEE-2019 = EUR:0.01
-WIRE-FEE-2020 = EUR:0.01
-WIRE-FEE-2021 = EUR:0.01
-WIRE-FEE-2022 = EUR:0.01
-WIRE-FEE-2023 = EUR:0.01
-WIRE-FEE-2024 = EUR:0.01
-WIRE-FEE-2025 = EUR:0.01
-WIRE-FEE-2026 = EUR:0.01
-
-CLOSING-FEE-2017 = EUR:0.01
-CLOSING-FEE-2018 = EUR:0.01
-CLOSING-FEE-2019 = EUR:0.01
-CLOSING-FEE-2020 = EUR:0.01
-CLOSING-FEE-2021 = EUR:0.01
-CLOSING-FEE-2022 = EUR:0.01
-CLOSING-FEE-2023 = EUR:0.01
-CLOSING-FEE-2024 = EUR:0.01
-CLOSING-FEE-2025 = EUR:0.01
-CLOSING-FEE-2026 = EUR:0.01
-
-[fees-sepa]
-# Fees for the forseeable future...
-# If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2017 = EUR:0.01
-WIRE-FEE-2018 = EUR:0.01
-WIRE-FEE-2019 = EUR:0.01
-WIRE-FEE-2020 = EUR:0.01
-WIRE-FEE-2021 = EUR:0.01
-WIRE-FEE-2022 = EUR:0.01
-WIRE-FEE-2023 = EUR:0.01
-WIRE-FEE-2024 = EUR:0.01
-WIRE-FEE-2025 = EUR:0.01
-WIRE-FEE-2026 = EUR:0.01
-
-CLOSING-FEE-2017 = EUR:0.01
-CLOSING-FEE-2018 = EUR:0.01
-CLOSING-FEE-2019 = EUR:0.01
-CLOSING-FEE-2020 = EUR:0.01
-CLOSING-FEE-2021 = EUR:0.01
-CLOSING-FEE-2022 = EUR:0.01
-CLOSING-FEE-2023 = EUR:0.01
-CLOSING-FEE-2024 = EUR:0.01
-CLOSING-FEE-2025 = EUR:0.01
-CLOSING-FEE-2026 = EUR:0.01
-
-[coin_eur_ct_1]
-value = EUR:0.01
-duration_overlap = 1 s
-duration_withdraw = 25 s
-duration_spend = 40 s
-duration_legal = 60 s
-fee_withdraw = EUR:0.00
-fee_deposit = EUR:0.00
-fee_refresh = EUR:0.01
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_ct_2]
-value = EUR:0.02
-duration_overlap = 1 s
-duration_withdraw = 25 s
-duration_spend = 40 s
-duration_legal = 60 s
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.01
-fee_refund = EUR:0.01
-rsa_keysize = 1024
diff --git a/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf b/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf
deleted file mode 100644
index 29290c99c..000000000
--- a/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-@INLINE@ test_exchange_api_keys_cherry_picking.conf
-
-[exchange]
-# Lengthen over original value (60 s)
-LOOKAHEAD_SIGN = 100 s
diff --git a/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended_2.conf b/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended_2.conf
deleted file mode 100644
index cfa8b1347..000000000
--- a/src/exchange-lib/test_exchange_api_keys_cherry_picking_extended_2.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-@INLINE@ test_exchange_api_keys_cherry_picking_extended.conf
-
-[exchange]
-# Lengthen over firstly extended value (100 s)
-LOOKAHEAD_SIGN = 1500 s
diff --git a/src/exchange-lib/test_exchange_api_keys_cherry_picking_new.c b/src/exchange-lib/test_exchange_api_keys_cherry_picking_new.c
deleted file mode 100644
index 45222a66c..000000000
--- a/src/exchange-lib/test_exchange_api_keys_cherry_picking_new.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/test_exchange_api_keys_cherry_picking_new.c
- * @brief testcase to test exchange's /keys cherry picking ability
- * @author Marcello Stanisci
- * @author Christian Grothoff
- */
-
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_signatures.h"
-#include "taler_exchange_service.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <microhttpd.h>
-#include "taler_bank_service.h"
-#include "taler_fakebank_lib.h"
-#include "taler_testing_lib.h"
-
-/**
- * Configuration file we use. One (big) configuration is used
- * for the various components for this test.
- */
-#define CONFIG_FILE "test_exchange_api_keys_cherry_picking.conf"
-
-/**
- * Used to increase the number of denomination keys.
- */
-#define CONFIG_FILE_EXTENDED \
- "test_exchange_api_keys_cherry_picking_extended.conf"
-
-/**
- * Used to increase the number of denomination keys.
- */
-#define CONFIG_FILE_EXTENDED_2 \
- "test_exchange_api_keys_cherry_picking_extended_2.conf"
-
-/**
- * Exchange base URL; mainly purpose is to make the compiler happy.
- */
-static char *exchange_url;
-
-/**
- * Auditor base URL; mainly purpose is to make the compiler happy.
- */
-static char *auditor_url;
-
-
-/**
- * Main function that will tell the interpreter what commands to
- * run.
- *
- * @param cls closure
- */
-static void
-run (void *cls,
- struct TALER_TESTING_Interpreter *is)
-{
-
- struct TALER_TESTING_Command keys_serialization[] = {
-
- /**
- * Serialize keys, and disconnect from the exchange.
- */
- TALER_TESTING_cmd_serialize_keys ("serialize-keys"),
-
- /**
- * Reconnect to the exchange using the serialized keys.
- */
- TALER_TESTING_cmd_connect_with_state ("reconnect-with-state",
- "serialize-keys"),
-
- TALER_TESTING_cmd_wire ("verify-/wire-with-serialized-keys",
- "x-taler-bank",
- NULL,
- MHD_HTTP_OK),
-
- TALER_TESTING_cmd_exec_keyup ("keyup-serialization",
- CONFIG_FILE_EXTENDED_2),
-
- TALER_TESTING_cmd_exec_auditor_sign
- ("auditor-sign-serialization",
- CONFIG_FILE_EXTENDED_2),
-
- TALER_TESTING_cmd_sleep ("sleep-serialization",
- 3),
-
- TALER_TESTING_cmd_signal ("reload-keys-serialization",
- is->exchanged,
- SIGUSR1),
-
- TALER_TESTING_cmd_sleep ("sleep-serialization",
- 3),
-
- /**
- * XXX.
- *
- * Current bug: this CMD here uses the "reconnect cert_cb",
- * that has its 'consumed' field already set to GNUNET_YES.
- * This way, there is no way to pass control to the next
- * CMD making therefore the interpreter stuck.
- *
- * Doable solution: adapt the global "cert_cb" to handle
- * "reconnect situations", or even provide some method to
- * switch the 'consumed' field back to GNUNET_NO.
- */
- TALER_TESTING_cmd_check_keys ("check-freshest-keys",
- 4,
- 10),
-
- TALER_TESTING_cmd_wire ("verify-/wire-with-fresh-keys",
- "x-taler-bank",
- NULL,
- MHD_HTTP_OK),
- TALER_TESTING_cmd_end ()
- };
-
- struct TALER_TESTING_Command commands[] = {
- /* Trigger keys reloading from disk. */
- TALER_TESTING_cmd_signal ("signal-reaction-1",
- is->exchanged,
- SIGUSR1),
-
- TALER_TESTING_cmd_check_keys ("check-keys-1",
- 1,
- 4),
- /* sleep a bit */
- TALER_TESTING_cmd_sleep ("sleep",
- 10),
-
- /* 1st keyup happens at start-up */
- TALER_TESTING_cmd_exec_keyup ("keyup-2",
- CONFIG_FILE_EXTENDED),
-
- TALER_TESTING_cmd_exec_auditor_sign ("sign-keys-1",
- CONFIG_FILE_EXTENDED),
-
- /* Cause exchange to reload (new) keys */
- TALER_TESTING_cmd_signal ("trigger-keys-reload-1",
- is->exchanged,
- SIGUSR1),
-
- TALER_TESTING_cmd_check_keys ("check-keys-2",
- 2,
- 6),
- /* sleep a bit */
- TALER_TESTING_cmd_sleep ("sleep",
- 20),
-
- /* Do 2nd keyup */
- TALER_TESTING_cmd_exec_keyup ("keyup-3",
- CONFIG_FILE_EXTENDED),
-
- TALER_TESTING_cmd_exec_auditor_sign ("sign-keys-2",
- CONFIG_FILE),
-
- TALER_TESTING_cmd_signal ("trigger-keys-reload-2",
- is->exchanged,
- SIGUSR1),
-
- TALER_TESTING_cmd_check_keys ("check-keys-3",
- 3,
- 8),
-
- TALER_TESTING_cmd_batch ("keys-serialization",
- keys_serialization),
- TALER_TESTING_cmd_end ()
- };
-
- TALER_TESTING_run (is,
- commands);
-}
-
-
-int
-main (int argc,
- char * const *argv)
-{
- /* These environment variables get in the way... */
- unsetenv ("XDG_DATA_HOME");
- unsetenv ("XDG_CONFIG_HOME");
- GNUNET_log_setup ("test-exchange-api-cherry-picking-new",
- "DEBUG", NULL);
- TALER_TESTING_cleanup_files (CONFIG_FILE);
- /* @helpers. Run keyup, create tables, ... Note: it
- * fetches the port number from config in order to see
- * if it's available. */
- switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
- &auditor_url,
- &exchange_url))
- {
- case GNUNET_SYSERR:
- GNUNET_break (0);
- return 1;
- case GNUNET_NO:
- return 77;
- case GNUNET_OK:
- if (GNUNET_OK !=
- /* Set up event loop and reschedule context, plus
- * start/stop the exchange. It calls TALER_TESTING_setup
- * which creates the 'is' object.
- */
- TALER_TESTING_setup_with_exchange (&run,
- NULL,
- CONFIG_FILE))
- return 1;
- break;
- default:
- GNUNET_break (0);
- return 1;
- }
- return 0;
-}
-
-/* end of test_exchange_api_keys_cherry_picking_new.c */
diff --git a/src/exchange-lib/test_exchange_api_new.c b/src/exchange-lib/test_exchange_api_new.c
deleted file mode 100644
index bcbdb5ea4..000000000
--- a/src/exchange-lib/test_exchange_api_new.c
+++ /dev/null
@@ -1,1001 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange/test_exchange_api_new.c
- * @brief testcase to test exchange's HTTP API interface
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_signatures.h"
-#include "taler_exchange_service.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <microhttpd.h>
-#include "taler_bank_service.h"
-#include "taler_fakebank_lib.h"
-#include "taler_testing_lib.h"
-
-/**
- * Configuration file we use. One (big) configuration is used
- * for the various components for this test.
- */
-#define CONFIG_FILE "test_exchange_api.conf"
-
-#define CONFIG_FILE_EXPIRE_RESERVE_NOW "test_exchange_api_expire_reserve_now.conf"
-
-/**
- * Is the configuration file is set to include wire format 'ebics'?
- * Requires that EBICS /history function is implemented, which it
- * is currently not. Once it is, set ENABLE_CREDIT to YES in the
- * configuration and then set this option to 1.
- */
-#define WIRE_EBICS 0
-
-/**
- * URL of the fakebank. Obtained from CONFIG_FILE's
- * "exchange-wire-test:BANK_URI" option.
- */
-static char *fakebank_url;
-
-/**
- * Exchange base URL as it appears in the configuration. Note
- * that it might differ from the one where the exchange actually
- * listens from.
- */
-static char *exchange_url;
-
-/**
- * Auditor base URL as it appears in the configuration. Note
- * that it might differ from the one where the auditor actually
- * listens from.
- */
-static char *auditor_url;
-
-/**
- * Account number of the exchange at the bank.
- */
-#define EXCHANGE_ACCOUNT_NO 2
-
-/**
- * Account number of some user.
- */
-#define USER_ACCOUNT_NO 42
-
-/**
- * User name. Never checked by fakebank.
- */
-#define USER_LOGIN_NAME "user42"
-
-/**
- * User password. Never checked by fakebank.
- */
-#define USER_LOGIN_PASS "pass42"
-
-/**
- * Execute the taler-exchange-wirewatch command with
- * our configuration file.
- *
- * @param label label to use for the command.
- */
-#define CMD_EXEC_WIREWATCH(label) \
- TALER_TESTING_cmd_exec_wirewatch (label, CONFIG_FILE)
-
-/**
- * Execute the taler-exchange-aggregator command with
- * our configuration file.
- *
- * @param label label to use for the command.
- */
-#define CMD_EXEC_AGGREGATOR(label) \
- TALER_TESTING_cmd_exec_aggregator (label, CONFIG_FILE)
-
-/**
- * Run wire transfer of funds from some user's account to the
- * exchange.
- *
- * @param label label to use for the command.
- * @param amount amount to transfer, i.e. "EUR:1"
- */
-#define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
- TALER_TESTING_cmd_fakebank_transfer (label, amount, \
- fakebank_url, USER_ACCOUNT_NO, EXCHANGE_ACCOUNT_NO, \
- USER_LOGIN_NAME, USER_LOGIN_PASS, exchange_url)
-
-/**
- * Run wire transfer of funds from some user's account to the
- * exchange.
- *
- * @param label label to use for the command.
- * @param amount amount to transfer, i.e. "EUR:1"
- */
-#define CMD_TRANSFER_TO_EXCHANGE_SUBJECT(label,amount,subject) \
- TALER_TESTING_cmd_fakebank_transfer_with_subject \
- (label, amount, fakebank_url, USER_ACCOUNT_NO, \
- EXCHANGE_ACCOUNT_NO, USER_LOGIN_NAME, USER_LOGIN_PASS, \
- subject, exchange_url)
-
-/**
- * Main function that will tell the interpreter what commands to
- * run.
- *
- * @param cls closure
- */
-static void
-run (void *cls,
- struct TALER_TESTING_Interpreter *is)
-{
-
- /**
- * Checks made against /wire response.
- */
- struct TALER_TESTING_Command wire[] = {
- /**
- * Check if 'x-taler-bank' wire method is offered
- * by the exchange.
- */
- TALER_TESTING_cmd_wire ("wire-taler-bank-1",
- "x-taler-bank",
- NULL,
- MHD_HTTP_OK),
- #if WIRE_EBICS
- /**
- * Check if 'ebics' wire method is offered by the exchange.
- */
- TALER_TESTING_cmd_wire ("wire-sepa-1",
- "ebics",
- NULL,
- MHD_HTTP_OK),
- #endif
-
- TALER_TESTING_cmd_end ()
- };
-
- /**
- * Test withdrawal plus spending.
- */
- struct TALER_TESTING_Command withdraw[] = {
-
- /**
- * Move money to the exchange's bank account.
- */
- CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1",
- "EUR:5.01"),
-
- /**
- * Make a reserve exist, according to the previous
- * transfer.
- */
- CMD_EXEC_WIREWATCH ("wirewatch-1"),
-
-
- /**
- * Withdraw EUR:5.
- */
- TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1",
- "create-reserve-1",
- "EUR:5",
- MHD_HTTP_OK),
-
- /**
- * Check the reserve is depleted.
- */
- TALER_TESTING_cmd_status ("status-1",
- "create-reserve-1",
- "EUR:0",
- MHD_HTTP_OK),
-
- TALER_TESTING_cmd_end ()
- };
-
- struct TALER_TESTING_Command spend[] = {
- /**
- * Spend the coin.
- */
- TALER_TESTING_cmd_deposit
- ("deposit-simple", "withdraw-coin-1", 0,
- TALER_TESTING_make_wire_details (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_OK),
-
- /**
- * Try to overdraw.
- */
- TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-2",
- "create-reserve-1",
- "EUR:5",
- MHD_HTTP_FORBIDDEN),
-
- /**
- * Try to double spend using different wire details.
- */
- TALER_TESTING_cmd_deposit
- ("deposit-double-1", "withdraw-coin-1", 0,
- TALER_TESTING_make_wire_details (43,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN),
-
- /**
- * Try to double spend using a different transaction id.
- * (copied verbatim from old exchange-lib tests.)
- * FIXME: how can it get a different transaction id? There
- * isn't such a thing actually, the exchange only knows about
- * contract terms' hashes. So since the contract terms are
- * exactly the same as the previous command,
- * how can a different id be generated?
- */
- TALER_TESTING_cmd_deposit
- ("deposit-double-1", "withdraw-coin-1", 0,
- TALER_TESTING_make_wire_details (43,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN),
-
- /**
- * Try to double spend with different proposal.
- */
- TALER_TESTING_cmd_deposit
- ("deposit-double-2", "withdraw-coin-1", 0,
- TALER_TESTING_make_wire_details (43,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\",\"value\":2}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_FORBIDDEN),
-
- TALER_TESTING_cmd_end ()
- };
-
-
- struct TALER_TESTING_Command refresh[] = {
-
- /**
- * Fill reserve with EUR:5, 1ct is for fees. NOTE: the old
- * test-suite gave a account number of _424_ to the user at
- * this step; to type less, here the _42_ number is reused.
- * Does this change the tests semantics?
- */
- CMD_TRANSFER_TO_EXCHANGE ("refresh-create-reserve-1",
- "EUR:5.01"),
-
- /**
- * Make previous command effective.
- */
- CMD_EXEC_WIREWATCH ("wirewatch-2"),
-
- /**
- * Withdraw EUR:5.
- */
- TALER_TESTING_cmd_withdraw_amount
- ("refresh-withdraw-coin-1",
- "refresh-create-reserve-1",
- "EUR:5",
- MHD_HTTP_OK),
- /**
- * Try to partially spend (deposit) 1 EUR of the 5 EUR coin
- * (in full) (merchant would receive EUR:0.99 due to 1 ct
- * deposit fee)
- */
- TALER_TESTING_cmd_deposit
- ("refresh-deposit-partial",
- "refresh-withdraw-coin-1", 0,
- TALER_TESTING_make_wire_details (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\",\
- \"value\":\"EUR:1\"}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_OK),
-
- /**
- * Melt the rest of the coin's value
- * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
- TALER_TESTING_cmd_refresh_melt_double
- ("refresh-melt-1", "EUR:4",
- "refresh-withdraw-coin-1", MHD_HTTP_OK),
- /**
- * Complete (successful) melt operation, and
- * withdraw the coins
- */
- TALER_TESTING_cmd_refresh_reveal
- ("refresh-reveal-1",
- "refresh-melt-1", MHD_HTTP_OK),
-
- /**
- * Do it again to check idempotency
- */
- TALER_TESTING_cmd_refresh_reveal
- ("refresh-reveal-1-idempotency",
- "refresh-melt-1", MHD_HTTP_OK),
-
- /**
- * Test that /refresh/link works
- */
- TALER_TESTING_cmd_refresh_link
- ("refresh-link-1",
- "refresh-reveal-1", MHD_HTTP_OK),
-
- /**
- * Try to spend a refreshed EUR:1 coin
- */
- TALER_TESTING_cmd_deposit
- ("refresh-deposit-refreshed-1a",
- "refresh-reveal-1-idempotency", 0,
- TALER_TESTING_make_wire_details (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\",\
- \"value\":3}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_OK),
-
- /**
- * Try to spend a refreshed EUR:0.1 coin
- */
- TALER_TESTING_cmd_deposit
- ("refresh-deposit-refreshed-1b",
- "refresh-reveal-1", 3,
- TALER_TESTING_make_wire_details (43,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\",\
- \"value\":3}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:0.1", MHD_HTTP_OK),
-
- /* Test running a failing melt operation (same operation
- * again must fail) */
- TALER_TESTING_cmd_refresh_melt
- ("refresh-melt-failing", "EUR:4",
- "refresh-withdraw-coin-1", MHD_HTTP_FORBIDDEN),
-
- /* FIXME: also test with coin that was already melted
- * (signature differs from coin that was deposited...) */
-
- TALER_TESTING_cmd_end ()
- };
-
- struct TALER_TESTING_Command track[] = {
- /**
- * Try resolving a deposit's WTID, as we never triggered
- * execution of transactions, the answer should be that
- * the exchange knows about the deposit, but has no WTID yet.
- */
- TALER_TESTING_cmd_track_transaction
- ("deposit-wtid-found",
- "deposit-simple", 0, MHD_HTTP_ACCEPTED, NULL),
-
- /**
- * Try resolving a deposit's WTID for a failed deposit.
- * As the deposit failed, the answer should be that the
- * exchange does NOT know about the deposit.
- */
- TALER_TESTING_cmd_track_transaction
- ("deposit-wtid-failing",
- "deposit-double-2", 0, MHD_HTTP_NOT_FOUND, NULL),
-
- /**
- * Try resolving an undefined (all zeros) WTID; this
- * should fail as obviously the exchange didn't use that
- * WTID value for any transaction.
- */
- TALER_TESTING_cmd_track_transfer_empty
- ("wire-deposit-failing",
- NULL, 0, MHD_HTTP_NOT_FOUND),
-
- /**
- * Run transfers. Note that _actual_ aggregation will NOT
- * happen here, as each deposit operation is run with a
- * fresh merchant public key! NOTE: this comment comes
- * "verbatim" from the old test-suite, and IMO does not explain
- * a lot!
- */
- CMD_EXEC_AGGREGATOR ("run-aggregator"),
-
- /**
- * Check all the transfers took place.
- */
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-499c", exchange_url,
- "EUR:4.98", 2, 42),
-
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-99c1", exchange_url,
- "EUR:0.98", 2, 42),
-
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-99c2", exchange_url,
- "EUR:0.98", 2, 42),
-
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-99c", exchange_url,
- "EUR:0.08", 2, 43),
-
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-aai-1", exchange_url,
- "EUR:5.01", 42, 2),
-
- /**
- * NOTE: the old test-suite had this "check bank transfer"
- * command with debit account == 424.
- */
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-aai-2", exchange_url,
- "EUR:5.01", 42, 2),
-
- TALER_TESTING_cmd_check_bank_empty ("check_bank_empty"),
-
- TALER_TESTING_cmd_track_transaction
- ("deposit-wtid-ok",
- "deposit-simple", 0, MHD_HTTP_OK, "check_bank_transfer-499c"),
-
- TALER_TESTING_cmd_track_transfer
- ("wire-deposit-success-bank",
- "check_bank_transfer-99c1", 0, MHD_HTTP_OK, "EUR:0.98",
- "EUR:0.01"),
-
- TALER_TESTING_cmd_track_transfer
- ("wire-deposits-success-wtid",
- "deposit-wtid-ok", 0, MHD_HTTP_OK, "EUR:4.98",
- "EUR:0.01"),
-
- TALER_TESTING_cmd_end ()
- };
-
-
- /**
- * This block checks whether a wire deadline
- * very far in the future does NOT get aggregated now.
- */
- struct TALER_TESTING_Command unaggregation[] = {
-
- TALER_TESTING_cmd_check_bank_empty
- ("far-future-aggregation-a"),
-
- CMD_TRANSFER_TO_EXCHANGE ("create-reserve-unaggregated",
- "EUR:5.01"),
-
- CMD_EXEC_WIREWATCH ("wirewatch-unaggregated"),
-
- /* "consume" reserve creation transfer. */
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-unaggregated",
- exchange_url,
- "EUR:5.01",
- 42,
- 2),
-
- TALER_TESTING_cmd_withdraw_amount
- ("withdraw-coin-unaggregated",
- "create-reserve-unaggregated",
- "EUR:5",
- MHD_HTTP_OK),
-
- TALER_TESTING_cmd_deposit
- ("deposit-unaggregated",
- "withdraw-coin-unaggregated",
- 0,
- TALER_TESTING_make_wire_details
- (43,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\",\"value\":1}]}",
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_YEARS,
- 3000),
- "EUR:5",
- MHD_HTTP_OK),
-
- CMD_EXEC_AGGREGATOR ("aggregation-attempt"),
-
- TALER_TESTING_cmd_check_bank_empty
- ("far-future-aggregation-b"),
-
- TALER_TESTING_cmd_end ()
- };
-
-
- struct TALER_TESTING_Command refund[] = {
-
- /**
- * Fill reserve with EUR:5.01, as withdraw fee is 1 ct per
- * config.
- */
- CMD_TRANSFER_TO_EXCHANGE ("create-reserve-r1",
- "EUR:5.01"),
-
-
- /**
- * Run wire-watch to trigger the reserve creation.
- */
- CMD_EXEC_WIREWATCH ("wirewatch-3"),
-
- /* Withdraw a 5 EUR coin, at fee of 1 ct */
- TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-r1",
- "create-reserve-r1",
- "EUR:5",
- MHD_HTTP_OK),
- /**
- * Spend 5 EUR of the 5 EUR coin (in full) (merchant would
- * receive EUR:4.99 due to 1 ct deposit fee)
- */
- TALER_TESTING_cmd_deposit
- ("deposit-refund-1", "withdraw-coin-r1", 0,
- TALER_TESTING_make_wire_details (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\","
- "\"value\":\"EUR:5\"}]}",
- GNUNET_TIME_UNIT_MINUTES, "EUR:5", MHD_HTTP_OK),
-
-
- /**
- * Run transfers. Should do nothing as refund deadline blocks
- * it
- */
- CMD_EXEC_AGGREGATOR ("run-aggregator-refund"),
-
- /**
- * Check that aggregator didn't do anything, as expected.
- * Note, this operation takes two commands: one to "flush"
- * the preliminary transfer (used to withdraw) from the
- * fakebank and the second to actually check there are not
- * other transfers around.
- */
-
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-pre-refund", exchange_url,
- "EUR:5.01", 42, 2),
-
- TALER_TESTING_cmd_check_bank_empty
- ("check_bank_transfer-pre-refund"),
-
- TALER_TESTING_cmd_refund
- ("refund-ok", MHD_HTTP_OK,
- "EUR:5", "EUR:0.01", "deposit-refund-1"),
-
- TALER_TESTING_cmd_refund
- ("refund-ok-double", MHD_HTTP_OK,
- "EUR:5", "EUR:0.01", "deposit-refund-1"),
-
- /* Previous /refund(s) had id == 0. */
- TALER_TESTING_cmd_refund_with_id
- ("refund-conflicting", MHD_HTTP_CONFLICT,
- "EUR:5", "EUR:0.01", "deposit-refund-1", 1),
-
- /**
- * Spend 4.99 EUR of the refunded 4.99 EUR coin (1ct gone
- * due to refund) (merchant would receive EUR:4.98 due to
- * 1 ct deposit fee) */
- TALER_TESTING_cmd_deposit
- ("deposit-refund-2", "withdraw-coin-r1", 0,
- TALER_TESTING_make_wire_details (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"more ice cream\","
- "\"value\":\"EUR:5\"}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:4.99", MHD_HTTP_OK),
-
-
- /**
- * Run transfers. This will do the transfer as refund deadline
- * was 0
- */
- CMD_EXEC_AGGREGATOR ("run-aggregator-3"),
-
- /**
- * Check that deposit did run.
- */
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-pre-refund", exchange_url,
- "EUR:4.97", 2, 42),
-
- /**
- * Run failing refund, as past deadline & aggregation.
- */
- TALER_TESTING_cmd_refund
- ("refund-fail", MHD_HTTP_GONE,
- "EUR:4.99", "EUR:0.01", "deposit-refund-2"),
-
- TALER_TESTING_cmd_check_bank_empty
- ("check-empty-after-refund"),
-
- /**
- * Test refunded coins are never executed, even past
- * refund deadline
- */
- CMD_TRANSFER_TO_EXCHANGE ("create-reserve-rb",
- "EUR:5.01"),
-
- CMD_EXEC_WIREWATCH ("wirewatch-rb"),
-
- TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-rb",
- "create-reserve-rb",
- "EUR:5",
- MHD_HTTP_OK),
-
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-aai-3b", exchange_url,
- "EUR:5.01", 42, 2),
-
-
- TALER_TESTING_cmd_deposit
- ("deposit-refund-1b", "withdraw-coin-rb", 0,
- TALER_TESTING_make_wire_details (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\","
- "\"value\":\"EUR:5\"}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:5", MHD_HTTP_OK),
-
- /**
- * Trigger refund (before aggregator had a chance to execute
- * deposit, even though refund deadline was zero).
- */
- TALER_TESTING_cmd_refund
- ("refund-ok-fast", MHD_HTTP_OK,
- "EUR:5", "EUR:0.01", "deposit-refund-1b"),
-
- /**
- * Run transfers. This will do the transfer as refund deadline
- * was 0, except of course because the refund succeeded, the
- * transfer should no longer be done.
- */
- CMD_EXEC_AGGREGATOR ("run-aggregator-3b"),
-
- /* check that aggregator didn't do anything, as expected */
- TALER_TESTING_cmd_check_bank_empty
- ("check-refund-fast-not-run"),
-
- TALER_TESTING_cmd_end ()
- };
-
- struct TALER_TESTING_Command payback[] = {
- /**
- * Fill reserve with EUR:5.01, as withdraw fee is 1 ct per
- * config.
- */
- CMD_TRANSFER_TO_EXCHANGE ("payback-create-reserve-1",
- "EUR:5.01"),
-
- /**
- * Run wire-watch to trigger the reserve creation.
- */
- CMD_EXEC_WIREWATCH ("wirewatch-4"),
-
- /* Withdraw a 5 EUR coin, at fee of 1 ct */
- TALER_TESTING_cmd_withdraw_amount ("payback-withdraw-coin-1",
- "payback-create-reserve-1",
- "EUR:5",
- MHD_HTTP_OK),
- /* Make coin invalid */
- TALER_TESTING_cmd_revoke ("revoke-1",
- MHD_HTTP_OK,
- "payback-withdraw-coin-1",
- CONFIG_FILE),
-
- /* Refund coin to bank account */
- TALER_TESTING_cmd_payback ("payback-1",
- MHD_HTTP_OK,
- "payback-withdraw-coin-1",
- "EUR:5"),
-
- /* Check the money is back with the reserve */
- TALER_TESTING_cmd_status ("payback-reserve-status-1",
- "payback-create-reserve-1",
- "EUR:5.0",
- MHD_HTTP_OK),
-
- /* Re-withdraw from this reserve */
- TALER_TESTING_cmd_withdraw_amount ("payback-withdraw-coin-2",
- "payback-create-reserve-1",
- "EUR:1",
- MHD_HTTP_OK),
-
- /**
- * This withdrawal will test the logic to create a "payback"
- * element to insert into the reserve's history.
- */
- TALER_TESTING_cmd_withdraw_amount
- ("payback-withdraw-coin-2-over",
- "payback-create-reserve-1",
- "EUR:10",
- MHD_HTTP_FORBIDDEN),
-
- TALER_TESTING_cmd_status ("payback-reserve-status-2",
- "payback-create-reserve-1",
- "EUR:3.99",
- MHD_HTTP_OK),
-
- /**
- * These commands should close the reserve because
- * the aggregator is given a config file that ovverrides
- * the reserve expiration time (making it now-ish)
- */
- CMD_TRANSFER_TO_EXCHANGE
- ("short-lived-reserve",
- "EUR:5.01"),
-
- TALER_TESTING_cmd_exec_wirewatch
- ("short-lived-aggregation",
- CONFIG_FILE_EXPIRE_RESERVE_NOW),
-
- TALER_TESTING_cmd_exec_aggregator
- ("close-reserves",
- CONFIG_FILE_EXPIRE_RESERVE_NOW),
-
- TALER_TESTING_cmd_status ("short-lived-status",
- "short-lived-reserve",
- "EUR:0",
- MHD_HTTP_OK),
-
- TALER_TESTING_cmd_withdraw_amount
- ("expired-withdraw",
- "short-lived-reserve",
- "EUR:1",
- MHD_HTTP_FORBIDDEN),
-
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_short-lived_transfer",
- exchange_url,
- "EUR:5.01",
- 42,
- 2),
-
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_short-lived_reimburse",
- exchange_url,
- "EUR:5",
- 2,
- 42),
-
- /**
- * Fill reserve with EUR:2.02, as withdraw fee is 1 ct per
- * config, then withdraw two coin, partially spend one, and
- * then have the rest paid back. Check deposit of other coin
- * fails. (Do not use EUR:5 here as the EUR:5 coin was
- * revoked and we did not bother to create a new one...)
- */
- CMD_TRANSFER_TO_EXCHANGE ("payback-create-reserve-2",
- "EUR:2.02"),
-
- /* Make previous command effective. */
- CMD_EXEC_WIREWATCH ("wirewatch-5"),
-
- /* Withdraw a 1 EUR coin, at fee of 1 ct */
- TALER_TESTING_cmd_withdraw_amount ("payback-withdraw-coin-2a",
- "payback-create-reserve-2",
- "EUR:1",
- MHD_HTTP_OK),
-
- /* Withdraw a 1 EUR coin, at fee of 1 ct */
- TALER_TESTING_cmd_withdraw_amount ("payback-withdraw-coin-2b",
- "payback-create-reserve-2",
- "EUR:1",
- MHD_HTTP_OK),
-
- TALER_TESTING_cmd_deposit
- ("payback-deposit-partial",
- "payback-withdraw-coin-2a", 0,
- TALER_TESTING_make_wire_details (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:0.5", MHD_HTTP_OK),
-
-
- TALER_TESTING_cmd_revoke ("revoke-2", MHD_HTTP_OK,
- "payback-withdraw-coin-2a",
- CONFIG_FILE),
-
- TALER_TESTING_cmd_payback ("payback-2", MHD_HTTP_OK,
- "payback-withdraw-coin-2a",
- "EUR:0.5"),
-
- TALER_TESTING_cmd_payback ("payback-2b", MHD_HTTP_FORBIDDEN,
- "payback-withdraw-coin-2a",
- "EUR:0.5"),
-
- TALER_TESTING_cmd_deposit
- ("payback-deposit-revoked",
- "payback-withdraw-coin-2b", 0,
- TALER_TESTING_make_wire_details (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"more ice cream\",\"value\":1}]}",
- GNUNET_TIME_UNIT_ZERO, "EUR:1", MHD_HTTP_NOT_FOUND),
-
-
- /* Test deposit fails after payback, with proof in payback */
-
- /* FIXME: #3887: right now, the exchange will never return the
- * coin's transaction history with payback data, as we get a
- * 404 on the DK! */
- TALER_TESTING_cmd_deposit
- ("payback-deposit-partial-after-payback",
- "payback-withdraw-coin-2a",
- 0,
- TALER_TESTING_make_wire_details
- (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"extra ice cream\",\"value\":1}]}",
- GNUNET_TIME_UNIT_ZERO,
- "EUR:0.5",
- MHD_HTTP_NOT_FOUND),
-
- /* Test that revoked coins cannot be withdrawn */
- CMD_TRANSFER_TO_EXCHANGE ("payback-create-reserve-3",
- "EUR:1.01"),
-
- CMD_EXEC_WIREWATCH ("wirewatch-6"),
-
- TALER_TESTING_cmd_withdraw_amount
- ("payback-withdraw-coin-3-revoked",
- "payback-create-reserve-3",
- "EUR:1",
- MHD_HTTP_NOT_FOUND),
-
- /* check that we are empty before the rejection test */
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-pr1", exchange_url,
- "EUR:5.01", 42, 2),
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-pr2", exchange_url,
- "EUR:2.02", 42, 2),
- TALER_TESTING_cmd_check_bank_transfer
- ("check_bank_transfer-pr3", exchange_url,
- "EUR:1.01", 42, 2),
-
- TALER_TESTING_cmd_check_bank_empty
- ("check-empty-again"),
-
- /* Test rejection of bogus wire transfers */
- CMD_TRANSFER_TO_EXCHANGE_SUBJECT
- ("bogus-subject",
- "EUR:1.01",
- "not a reserve public key"),
-
- CMD_EXEC_WIREWATCH ("wirewatch-7"),
-
- TALER_TESTING_cmd_check_bank_empty
- ("check-empty-from-reject"),
-
- TALER_TESTING_cmd_end ()
- };
-
- #define RESERVE_OPEN_CLOSE_CHUNK 4
- #define RESERVE_OPEN_CLOSE_ITERATIONS 3
- #define CONSTANT_KEY \
- "09QGYPEKNHBACK135BNXZFHA0YTQXT1KJDRVXF4J822G99AYNQ8G"
-
- struct TALER_TESTING_Command reserve_open_close
- [(RESERVE_OPEN_CLOSE_ITERATIONS
- * RESERVE_OPEN_CLOSE_CHUNK) + 1];
-
- for (unsigned int i = 0;
- i < RESERVE_OPEN_CLOSE_ITERATIONS;
- i++)
- {
- reserve_open_close[i * RESERVE_OPEN_CLOSE_CHUNK]
- = CMD_TRANSFER_TO_EXCHANGE_SUBJECT
- ("reserve-open-close-key",
- "EUR:20",
- CONSTANT_KEY);
-
- reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 1]
- = TALER_TESTING_cmd_exec_wirewatch
- ("reserve-open-close-wirewatch",
- CONFIG_FILE_EXPIRE_RESERVE_NOW);
-
- reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 2]
- = TALER_TESTING_cmd_exec_aggregator
- ("reserve-open-close-aggregation",
- CONFIG_FILE_EXPIRE_RESERVE_NOW);
-
- reserve_open_close[(i * RESERVE_OPEN_CLOSE_CHUNK) + 3]
- = TALER_TESTING_cmd_status ("reserve-open-close-status",
- "reserve-open-close-key",
- "EUR:0",
- MHD_HTTP_OK);
- }
- reserve_open_close
- [RESERVE_OPEN_CLOSE_ITERATIONS * RESERVE_OPEN_CLOSE_CHUNK]
- = TALER_TESTING_cmd_end ();
-
- struct TALER_TESTING_Command commands[] = {
-
- TALER_TESTING_cmd_batch ("wire",
- wire),
-
- TALER_TESTING_cmd_batch ("withdraw",
- withdraw),
-
- TALER_TESTING_cmd_batch ("spend",
- spend),
-
- TALER_TESTING_cmd_batch ("refresh",
- refresh),
-
- TALER_TESTING_cmd_batch ("track",
- track),
-
- TALER_TESTING_cmd_batch ("unaggregation",
- unaggregation),
-
- TALER_TESTING_cmd_batch ("refund",
- refund),
-
- TALER_TESTING_cmd_batch ("payback",
- payback),
- /* Fix #5462. */
- TALER_TESTING_cmd_batch ("reserve-open-close",
- reserve_open_close),
- /**
- * End the suite. Fixme: better to have a label for this
- * too, as it shows as "(null)" on logs.
- */
- TALER_TESTING_cmd_end ()
- };
-
- TALER_TESTING_run_with_fakebank (is,
- commands,
- fakebank_url);
-}
-
-
-int
-main (int argc,
- char * const *argv)
-{
- /* These environment variables get in the way... */
- unsetenv ("XDG_DATA_HOME");
- unsetenv ("XDG_CONFIG_HOME");
- GNUNET_log_setup ("test-exchange-api-new",
- "INFO",
- NULL);
- if (NULL == (fakebank_url
- /* Check fakebank port is available and config cares
- * about bank url. */
- = TALER_TESTING_prepare_fakebank (CONFIG_FILE,
- "account-2")))
- return 77;
- TALER_TESTING_cleanup_files (CONFIG_FILE);
- /* @helpers. Run keyup, create tables, ... Note: it
- * fetches the port number from config in order to see
- * if it's available. */
- switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
- &auditor_url,
- &exchange_url))
- {
- case GNUNET_SYSERR:
- GNUNET_break (0);
- return 1;
- case GNUNET_NO:
- return 77;
- case GNUNET_OK:
- if (GNUNET_OK !=
- /* Set up event loop and reschedule context, plus
- * start/stop the exchange. It calls TALER_TESTING_setup
- * which creates the 'is' object.
- */
- TALER_TESTING_setup_with_exchange (&run,
- NULL,
- CONFIG_FILE))
- return 1;
- break;
- default:
- GNUNET_break (0);
- return 1;
- }
- return 0;
-}
-
-/* end of test_exchange_api_new.c */
diff --git a/src/exchange-lib/test_exchange_api_overlapping_keys_bug.c b/src/exchange-lib/test_exchange_api_overlapping_keys_bug.c
deleted file mode 100755
index d1fd7123b..000000000
--- a/src/exchange-lib/test_exchange_api_overlapping_keys_bug.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/test_exchange_api_keys_cherry_picking_new.c
- * @brief testcase to test exchange's /keys cherry picking ability
- * @author Marcello Stanisci
- * @author Christian Grothoff
- */
-
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_signatures.h"
-#include "taler_exchange_service.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <microhttpd.h>
-#include "taler_bank_service.h"
-#include "taler_fakebank_lib.h"
-#include "taler_testing_lib.h"
-
-/**
- * Configuration file we use. One (big) configuration is used
- * for the various components for this test.
- */
-#define CONFIG_FILE "test_exchange_api_keys_cherry_picking.conf"
-
-/**
- * Used to increase the number of denomination keys.
- */
-#define CONFIG_FILE_EXTENDED \
- "test_exchange_api_keys_cherry_picking_extended.conf"
-
-/**
- * Used to increase the number of denomination keys.
- */
-#define CONFIG_FILE_EXTENDED_2 \
- "test_exchange_api_keys_cherry_picking_extended_2.conf"
-
-/**
- * Exchange base URL; mainly purpose is to make the compiler happy.
- */
-static char *exchange_url;
-
-/**
- * Auditor base URL; mainly purpose is to make the compiler happy.
- */
-static char *auditor_url;
-
-
-/**
- * Main function that will tell the interpreter what commands to
- * run.
- *
- * @param cls closure
- */
-static void
-run (void *cls,
- struct TALER_TESTING_Interpreter *is)
-{
-
- struct TALER_TESTING_Command commands[] = {
-
- TALER_TESTING_cmd_check_keys ("first-download",
- 1,
- 4),
-
- TALER_TESTING_cmd_check_keys ("second-download",
- 2,
- 6),
- TALER_TESTING_cmd_end ()
- };
-
- TALER_TESTING_run (is,
- commands);
-}
-
-
-int
-main (int argc,
- char * const *argv)
-{
- /* These environment variables get in the way... */
- unsetenv ("XDG_DATA_HOME");
- unsetenv ("XDG_CONFIG_HOME");
- GNUNET_log_setup ("test-exchange-api-cherry-picking-new",
- "DEBUG", NULL);
- TALER_TESTING_cleanup_files (CONFIG_FILE);
- /* @helpers. Run keyup, create tables, ... Note: it
- * fetches the port number from config in order to see
- * if it's available. */
- switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
- &auditor_url,
- &exchange_url))
- {
- case GNUNET_SYSERR:
- GNUNET_break (0);
- return 1;
- case GNUNET_NO:
- return 77;
- case GNUNET_OK:
- if (GNUNET_OK !=
- /* Set up event loop and reschedule context, plus
- * start/stop the exchange. It calls TALER_TESTING_setup
- * which creates the 'is' object.
- */
- TALER_TESTING_setup_with_exchange (&run,
- NULL,
- CONFIG_FILE))
- return 1;
- break;
- default:
- GNUNET_break (0);
- return 1;
- }
- return 0;
-}
-
-/* end of test_exchange_api_keys_cherry_picking_new.c */
diff --git a/src/exchange-lib/test_exchange_api_twisted.c b/src/exchange-lib/test_exchange_api_twisted.c
deleted file mode 100644
index 1c5300586..000000000
--- a/src/exchange-lib/test_exchange_api_twisted.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange/test_exchange_api_twister.c
- * @brief testcase to test exchange's HTTP API interface
- * @author Marcello Stanisci
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- */
-
-#include "platform.h"
-#include <taler/taler_util.h>
-#include <taler/taler_signatures.h>
-#include <taler/taler_exchange_service.h>
-#include <taler/taler_json_lib.h>
-#include <gnunet/gnunet_util_lib.h>
-#include <microhttpd.h>
-#include <taler/taler_bank_service.h>
-#include <taler/taler_fakebank_lib.h>
-#include <taler/taler_testing_lib.h>
-#include <taler/taler_twister_testing_lib.h>
-#include <taler/taler_twister_service.h>
-
-/**
- * Configuration file we use. One (big) configuration is used
- * for the various components for this test.
- */
-#define CONFIG_FILE "test_exchange_api_twisted.conf"
-
-/**
- * (real) Twister URL. Used at startup time to check if it runs.
- */
-static char *twister_url;
-
-/**
- * URL of the fakebank. Obtained from CONFIG_FILE's
- * "exchange-wire-test:BANK_URI" option.
- */
-static char *fakebank_url;
-
-/**
- * Exchange base URL.
- */
-static char *exchange_url;
-
-/**
- * Auditor URL, unused but needed to achieve compilation.
- */
-static char *auditor_url;
-
-/**
- * Twister process.
- */
-static struct GNUNET_OS_Process *twisterd;
-
-/**
- * Account number of the exchange at the bank.
- */
-#define EXCHANGE_ACCOUNT_NO 2
-
-/**
- * Account number of some user.
- */
-#define USER_ACCOUNT_NO 62
-
-/**
- * User name. Never checked by fakebank.
- */
-#define USER_LOGIN_NAME "user42"
-
-/**
- * User password. Never checked by fakebank.
- */
-#define USER_LOGIN_PASS "pass42"
-
-/**
- * Execute the taler-exchange-wirewatch command with
- * our configuration file.
- *
- * @param label label to use for the command.
- */
-#define CMD_EXEC_WIREWATCH(label) \
- TALER_TESTING_cmd_exec_wirewatch (label, CONFIG_FILE)
-
-/**
- * Execute the taler-exchange-aggregator command with
- * our configuration file.
- *
- * @param label label to use for the command.
- */
-#define CMD_EXEC_AGGREGATOR(label) \
- TALER_TESTING_cmd_exec_aggregator (label, CONFIG_FILE)
-
-/**
- * Run wire transfer of funds from some user's account to the
- * exchange.
- *
- * @param label label to use for the command.
- * @param amount amount to transfer, i.e. "EUR:1"
- * @param url exchange_url
- */
-#define CMD_TRANSFER_TO_EXCHANGE(label,amount) \
- TALER_TESTING_cmd_fakebank_transfer (label, amount, \
- fakebank_url, USER_ACCOUNT_NO, EXCHANGE_ACCOUNT_NO, \
- USER_LOGIN_NAME, USER_LOGIN_PASS, exchange_url)
-
-/**
- * Run wire transfer of funds from some user's account to the
- * exchange.
- *
- * @param label label to use for the command.
- * @param amount amount to transfer, i.e. "EUR:1"
- */
-#define CMD_TRANSFER_TO_EXCHANGE_SUBJECT(label,amount,subject) \
- TALER_TESTING_cmd_fakebank_transfer_with_subject \
- (label, amount, fakebank_url, USER_ACCOUNT_NO, \
- EXCHANGE_ACCOUNT_NO, USER_LOGIN_NAME, USER_LOGIN_PASS, \
- subject)
-
-/**
- * Main function that will tell the interpreter what commands to
- * run.
- *
- * @param cls closure
- */
-static void
-run (void *cls,
- struct TALER_TESTING_Interpreter *is)
-{
-
-
- /**
- * This batch aims to trigger the 409 Conflict
- * response from a refresh-reveal operation.
- */
- struct TALER_TESTING_Command refresh_409_conflict[] = {
-
- CMD_TRANSFER_TO_EXCHANGE
- ("refresh-create-reserve",
- "EUR:5.01"),
-
- /**
- * Make previous command effective.
- */
- CMD_EXEC_WIREWATCH
- ("wirewatch"),
-
- /**
- * Withdraw EUR:5.
- */
- TALER_TESTING_cmd_withdraw_amount
- ("refresh-withdraw-coin",
- "refresh-create-reserve",
- "EUR:5",
- MHD_HTTP_OK),
-
- TALER_TESTING_cmd_deposit
- ("refresh-deposit-partial",
- "refresh-withdraw-coin",
- 0,
- TALER_TESTING_make_wire_details
- (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\",\
- \"value\":\"EUR:1\"}]}",
- GNUNET_TIME_UNIT_ZERO,
- "EUR:1",
- MHD_HTTP_OK),
-
- /**
- * Melt the rest of the coin's value
- * (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
- TALER_TESTING_cmd_refresh_melt
- ("refresh-melt",
- "EUR:4",
- "refresh-withdraw-coin",
- MHD_HTTP_OK),
-
- /* Trigger 409 Conflict. */
- TALER_TESTING_cmd_flip_upload
- ("flip-upload",
- CONFIG_FILE,
- "transfer_privs.0"),
-
- TALER_TESTING_cmd_refresh_reveal
- ("refresh-(flipped-)reveal",
- "refresh-melt",
- MHD_HTTP_CONFLICT),
-
- TALER_TESTING_cmd_end ()
-
- };
-
-
- /**
- * NOTE: not all CMDs actually need the twister,
- * so it may be better to move those into the "main"
- * lib test suite.
- */
- struct TALER_TESTING_Command refund[] = {
-
- CMD_TRANSFER_TO_EXCHANGE
- ("create-reserve-r1",
- "EUR:5.01"),
-
- CMD_EXEC_WIREWATCH
- ("wirewatch-r1"),
-
- TALER_TESTING_cmd_withdraw_amount
- ("withdraw-coin-r1",
- "create-reserve-r1",
- "EUR:5",
- MHD_HTTP_OK),
-
- TALER_TESTING_cmd_deposit
- ("deposit-refund-1",
- "withdraw-coin-r1",
- 0,
- TALER_TESTING_make_wire_details
- (42,
- fakebank_url),
- "{\"items\":[{\"name\":\"ice cream\","
- "\"value\":\"EUR:5\"}]}",
- GNUNET_TIME_UNIT_MINUTES,
- "EUR:5",
- MHD_HTTP_OK),
-
- TALER_TESTING_cmd_refund
- ("refund-currency-missmatch",
- MHD_HTTP_PRECONDITION_FAILED,
- "USD:5",
- "USD:0.01",
- "deposit-refund-1"),
-
- TALER_TESTING_cmd_refund
- ("refund-fee-above-amount",
- MHD_HTTP_BAD_REQUEST,
- "EUR:5",
- "EUR:10",
- "deposit-refund-1"),
-
- TALER_TESTING_cmd_flip_upload
- ("flip-upload",
- CONFIG_FILE,
- "merchant_sig"),
-
- TALER_TESTING_cmd_refund
- ("refund-bad-sig",
- MHD_HTTP_UNAUTHORIZED,
- "EUR:5",
- "EUR:0.01",
- "deposit-refund-1"),
-
- /* This next deposit CMD is only used to provide a
- * good merchant signature to the next (failing) refund
- * operations. */
-
- TALER_TESTING_cmd_deposit
- ("deposit-refund-to-fail",
- "withdraw-coin-r1",
- 0, /* coin index. */
- TALER_TESTING_make_wire_details
- (42,
- fakebank_url),
- /* This parameter will make any comparison about
- h_contract_terms fail, when /refund will be handled.
- So in other words, this is h_contract missmatch. */
- "{\"items\":[{\"name\":\"ice skate\","
- "\"value\":\"EUR:5\"}]}",
- GNUNET_TIME_UNIT_MINUTES,
- "EUR:5",
- MHD_HTTP_FORBIDDEN),
-
- TALER_TESTING_cmd_refund
- ("refund-deposit-not-found",
- MHD_HTTP_NOT_FOUND,
- "EUR:5",
- "EUR:0.01",
- "deposit-refund-to-fail"),
-
- TALER_TESTING_cmd_refund
- ("refund-insufficient-funds",
- MHD_HTTP_PRECONDITION_FAILED,
- "EUR:50",
- "EUR:0.01",
- "deposit-refund-1"),
-
- TALER_TESTING_cmd_refund
- ("refund-fee-too-low",
- MHD_HTTP_BAD_REQUEST,
- "EUR:5",
- "EUR:0.000001",
- "deposit-refund-1"),
-
- TALER_TESTING_cmd_end ()
-
- };
-
- struct TALER_TESTING_Command commands[] = {
-
- TALER_TESTING_cmd_batch ("refresh-reveal-409-conflict",
- refresh_409_conflict),
-
- TALER_TESTING_cmd_batch ("refund",
- refund),
-
- TALER_TESTING_cmd_end ()
- };
-
- TALER_TESTING_run_with_fakebank (is,
- commands,
- fakebank_url);
-}
-
-/**
- * Kill, wait, and destroy convenience function.
- *
- * @param process process to purge.
- */
-static void
-purge_process (struct GNUNET_OS_Process *process)
-{
- GNUNET_OS_process_kill (process, SIGINT);
- GNUNET_OS_process_wait (process);
- GNUNET_OS_process_destroy (process);
-}
-
-int
-main (int argc,
- char * const *argv)
-{
- unsigned int ret;
- /* These environment variables get in the way... */
- unsetenv ("XDG_DATA_HOME");
- unsetenv ("XDG_CONFIG_HOME");
- GNUNET_log_setup ("test-exchange-api-new-twisted",
- "DEBUG", NULL);
-
- if (NULL == (fakebank_url = TALER_TESTING_prepare_fakebank
- (CONFIG_FILE,
- "account-2")))
- return 77;
-
- if (NULL == (twister_url = TALER_TESTING_prepare_twister
- (CONFIG_FILE)))
- return 77;
-
- TALER_TESTING_cleanup_files (CONFIG_FILE);
-
- switch (TALER_TESTING_prepare_exchange (CONFIG_FILE,
- &auditor_url,
- &exchange_url))
- {
- case GNUNET_SYSERR:
- GNUNET_break (0);
- return 1;
- case GNUNET_NO:
- return 77;
-
- case GNUNET_OK:
-
- if (NULL == (twisterd = TALER_TESTING_run_twister
- (CONFIG_FILE)))
- return 77;
-
- ret = TALER_TESTING_setup_with_exchange (&run,
- NULL,
- CONFIG_FILE);
- purge_process (twisterd);
- GNUNET_free (twister_url);
-
- if (GNUNET_OK != ret)
- return 1;
- break;
- default:
- GNUNET_break (0);
- return 1;
- }
- return 0;
-}
-
-/* end of test_exchange_api_twisted.c */
diff --git a/src/exchange-lib/test_exchange_api_twisted.conf b/src/exchange-lib/test_exchange_api_twisted.conf
deleted file mode 100644
index ba59b5a60..000000000
--- a/src/exchange-lib/test_exchange_api_twisted.conf
+++ /dev/null
@@ -1,169 +0,0 @@
-# This file is in the public domain.
-#
-
-[twister]
-# HTTP listen port for twister
-HTTP_PORT = 8888
-
-# HTTP Destination for twister. The test-Webserver needs
-# to listen on the port used here. Note: no trailing '/'!
-DESTINATION_BASE_URL = "http://localhost:8081"
-
-# Control port for TCP
-# PORT = 8889
-HOSTNAME = localhost
-ACCEPT_FROM = 127.0.0.1;
-ACCEPT_FROM6 = ::1;
-
-# Control port for UNIX
-UNIXPATH = /tmp/taler-service-twister.sock
-UNIX_MATCH_UID = NO
-UNIX_MATCH_GID = YES
-
-# Launching of twister by ARM
-# BINARY = taler-service-twister
-# AUTOSTART = NO
-# FORCESTART = NO
-
-[PATHS]
-# Persistant data storage for the testcase
-TALER_TEST_HOME = test_exchange_api_home/
-
-[taler]
-# Currency supported by the exchange (can only be one)
-CURRENCY = EUR
-
-[exchange]
-
-# how long is one signkey valid?
-SIGNKEY_DURATION = 4 weeks
-
-# how long are the signatures with the signkey valid?
-LEGAL_DURATION = 2 years
-
-# how long do we provide to clients denomination and signing keys
-# ahead of time?
-LOOKAHEAD_PROVIDE = 4 weeks 1 day
-
-# Keep it short so the test runs fast.
-LOOKAHEAD_SIGN = 12 h
-
-# HTTP port the exchange listens to
-PORT = 8081
-
-# Master public key used to sign the exchange's various keys
-MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
-
-# How to access our database
-DB = postgres
-
-# Base URL of the exchange ('S PROXY). This URL is where the
-# twister listens at, so that it will be able to get all the
-# connection addressed to the exchange. In fact, the presence
-# of the twister is 100% transparent to the test case, as it
-# only seeks the exchange/BASE_URL URL to connect to the exchange.
-BASE_URL = "http://localhost:8888/"
-
-[exchangedb-postgres]
-DB_CONN_STR = "postgres:///talercheck"
-
-[auditor]
-BASE_URL = "http://the.auditor/"
-
-[auditordb-postgres]
-CONFIG = "postgres:///talercheck"
-
-[account-2]
-URL = payto://x-taler-bank/localhost:8082/2
-PLUGIN = taler_bank
-WIRE_RESPONSE = ${TALER_CONFIG_HOME}/account-2.json
-TALER_BANK_AUTH_METHOD = "basic"
-USERNAME = user
-PASSWORD = pass
-ENABLE_DEBIT = YES
-ENABLE_CREDIT = YES
-
-[fees-x-taler-bank]
-# Fees for the forseeable future...
-# If you see this after 2017, update to match the next 10 years...
-WIRE-FEE-2018 = EUR:0.01
-WIRE-FEE-2019 = EUR:0.01
-WIRE-FEE-2020 = EUR:0.01
-WIRE-FEE-2021 = EUR:0.01
-WIRE-FEE-2022 = EUR:0.01
-WIRE-FEE-2023 = EUR:0.01
-WIRE-FEE-2024 = EUR:0.01
-WIRE-FEE-2025 = EUR:0.01
-WIRE-FEE-2026 = EUR:0.01
-WIRE-FEE-2027 = EUR:0.01
-
-CLOSING-FEE-2018 = EUR:0.01
-CLOSING-FEE-2019 = EUR:0.01
-CLOSING-FEE-2020 = EUR:0.01
-CLOSING-FEE-2021 = EUR:0.01
-CLOSING-FEE-2022 = EUR:0.01
-CLOSING-FEE-2023 = EUR:0.01
-CLOSING-FEE-2024 = EUR:0.01
-CLOSING-FEE-2025 = EUR:0.01
-CLOSING-FEE-2026 = EUR:0.01
-CLOSING-FEE-2027 = EUR:0.01
-
-[coin_eur_ct_1]
-value = EUR:0.01
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.00
-fee_deposit = EUR:0.00
-fee_refresh = EUR:0.01
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_ct_10]
-value = EUR:0.10
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_1]
-value = EUR:1
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_5]
-value = EUR:5
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
-
-[coin_eur_10]
-value = EUR:10
-duration_overlap = 5 minutes
-duration_withdraw = 7 days
-duration_spend = 2 years
-duration_legal = 3 years
-fee_withdraw = EUR:0.01
-fee_deposit = EUR:0.01
-fee_refresh = EUR:0.03
-fee_refund = EUR:0.01
-rsa_keysize = 1024
diff --git a/src/exchange-lib/testing_api_cmd_bank_check.c b/src/exchange-lib/testing_api_cmd_bank_check.c
deleted file mode 100644
index 265cba176..000000000
--- a/src/exchange-lib/testing_api_cmd_bank_check.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_bank_check.c
- * @brief command to check if a particular wire transfer took
- * place.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-#include "taler_fakebank_lib.h"
-
-
-/**
- * State for a "bank check" CMD.
- */
-struct BankCheckState
-{
-
- /**
- * Base URL of the exchange supposed to be
- * involved in the bank transaction.
- */
- const char *exchange_base_url;
-
- /**
- * Expected transferred amount.
- */
- const char *amount;
-
- /**
- * Expected debit bank account.
- */
- uint64_t debit_account;
-
- /**
- * Expected credit bank account.
- */
- uint64_t credit_account;
-
- /**
- * Wire transfer subject (set by fakebank-lib).
- */
- char *subject;
-
- /**
- * Binary form of the wire transfer subject.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Reference to a CMD that provides all the data
- * needed to issue the bank check. If NULL, that data
- * must exist here in the state.
- */
- const char *deposit_reference;
-};
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-check_bank_transfer_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct BankCheckState *bcs = cls;
-
- struct TALER_Amount amount;
- const uint64_t *debit_account;
- const uint64_t *credit_account;
- const char *exchange_base_url;
-
-
- if (NULL == bcs->deposit_reference)
- {
- TALER_LOG_INFO ("Deposit reference NOT given\n");
- debit_account = &bcs->debit_account;
- credit_account = &bcs->credit_account;
- exchange_base_url = bcs->exchange_base_url;
-
- if (GNUNET_OK !=
- TALER_string_to_amount (bcs->amount,
- &amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u\n",
- bcs->amount,
- is->ip);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- }
-
- if (NULL != bcs->deposit_reference)
- {
- const struct TALER_TESTING_Command *deposit_cmd;
- const struct TALER_Amount *amount_ptr;
-
- TALER_LOG_INFO ("`%s' uses reference (%s/%p)\n",
- TALER_TESTING_interpreter_get_current_label
- (is),
- bcs->deposit_reference,
- bcs->deposit_reference);
- deposit_cmd = TALER_TESTING_interpreter_lookup_command
- (is, bcs->deposit_reference);
-
- if (NULL == deposit_cmd)
- TALER_TESTING_FAIL (is);
-
- GNUNET_assert
- (GNUNET_OK == TALER_TESTING_get_trait_amount_obj
- (deposit_cmd, 0, &amount_ptr));
- amount = *amount_ptr;
-
- GNUNET_assert
- (GNUNET_OK == TALER_TESTING_GET_TRAIT_DEBIT_ACCOUNT
- (deposit_cmd, &debit_account));
-
- GNUNET_assert
- (GNUNET_OK == TALER_TESTING_GET_TRAIT_CREDIT_ACCOUNT
- (deposit_cmd, &credit_account));
-
- GNUNET_assert
- (GNUNET_OK == TALER_TESTING_get_trait_url
- (deposit_cmd, 0, &exchange_base_url)); // check 0 works!
-
- }
-
- if (GNUNET_OK !=
- TALER_FAKEBANK_check (is->fakebank,
- &amount,
- *debit_account,
- *credit_account,
- exchange_base_url,
- &bcs->subject))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_TESTING_interpreter_next (is);
-}
-
-/**
- * Free the state of a "bank check" CMD.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-check_bank_transfer_cleanup
- (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct BankCheckState *bcs = cls;
-
- GNUNET_free_non_null (bcs->subject);
- GNUNET_free (bcs);
-}
-
-/**
- * Offer internal data from a "bank check" CMD state.
- *
- * @param cls closure.
- * @param ret[out] result.
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success.
- */
-static int
-check_bank_transfer_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct BankCheckState *bcs = cls;
- struct TALER_WireTransferIdentifierRawP *wtid_ptr;
-
- if (GNUNET_OK != GNUNET_STRINGS_string_to_data
- (bcs->subject,
- strlen (bcs->subject),
- &bcs->wtid,
- sizeof (struct TALER_WireTransferIdentifierRawP)))
- wtid_ptr = NULL;
- else
- wtid_ptr = &bcs->wtid;
-
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_transfer_subject (0, bcs->subject),
- TALER_TESTING_make_trait_wtid (0, wtid_ptr),
- TALER_TESTING_make_trait_url (0, bcs->exchange_base_url),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-
-/**
- * Make a "bank check" CMD. It checks whether a
- * particular wire transfer has been made or not.
- *
- * @param label the command label.
- * @param exchange_base_url base url of the exchange involved in
- * the wire transfer.
- * @param amount the amount expected to be transferred.
- * @param debit_account the account that gave money.
- * @param credit_account the account that received money.
- *
- * @return the command
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_check_bank_transfer
- (const char *label,
- const char *exchange_base_url,
- const char *amount,
- uint64_t debit_account,
- uint64_t credit_account)
-{
- struct BankCheckState *bcs;
-
- bcs = GNUNET_new (struct BankCheckState);
- bcs->exchange_base_url = exchange_base_url;
- bcs->amount = amount;
- bcs->debit_account = debit_account;
- bcs->credit_account = credit_account;
-
- bcs->deposit_reference = NULL;
-
- struct TALER_TESTING_Command cmd = {
- .label = label,
- .cls = bcs,
- .run = &check_bank_transfer_run,
- .cleanup = &check_bank_transfer_cleanup,
- .traits = &check_bank_transfer_traits
- };
-
- return cmd;
-}
-
-/**
- * Cleanup the state, only defined to respect the API.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-check_bank_empty_cleanup
- (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- return;
-}
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-check_bank_empty_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
-
- if (GNUNET_OK != TALER_FAKEBANK_check_empty (is->fakebank))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Some commands (notably "bank history") could randomly
- * look for traits; this way makes sure we don't segfault.
- */
-static int
-check_bank_empty_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Checks wheter all the wire transfers got "checked"
- * by the "bank check" CMD.
- *
- * @param label command label.
- *
- * @return the command
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_check_bank_empty (const char *label)
-{
- struct TALER_TESTING_Command cmd;
-
- cmd.label = label;
- cmd.run = &check_bank_empty_run;
- cmd.cleanup = &check_bank_empty_cleanup;
- cmd.traits = &check_bank_empty_traits;
-
- return cmd;
-}
-
-
-/**
- * Define a "bank check" CMD that takes the input
- * data from another CMD that offers it.
- *
- * @param label command label.
- * @param deposit_reference reference to a CMD that is
- * able to provide the "check bank transfer" operation
- * input data.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_check_bank_transfer_with_ref
- (const char *label,
- const char *deposit_reference)
-{
-
- struct BankCheckState *bcs;
- struct TALER_TESTING_Command cmd;
-
- bcs = GNUNET_new (struct BankCheckState);
- bcs->deposit_reference = deposit_reference;
-
- cmd.label = label;
- cmd.cls = bcs;
- cmd.run = &check_bank_transfer_run;
- cmd.cleanup = &check_bank_transfer_cleanup;
- cmd.traits = &check_bank_transfer_traits;
-
- return cmd;
-}
diff --git a/src/exchange-lib/testing_api_cmd_batch.c b/src/exchange-lib/testing_api_cmd_batch.c
deleted file mode 100644
index a56c959a0..000000000
--- a/src/exchange-lib/testing_api_cmd_batch.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange/testing_api_cmd_batch.c
- * @brief Implement batch-execution of CMDs.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "batch" CMD.
- */
-struct BatchState
-{
- /**
- * CMDs batch.
- */
- struct TALER_TESTING_Command *batch;
-
- /**
- * Internal comand pointer.
- */
- int batch_ip;
-};
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command being executed.
- * @param is the interpreter state.
- */
-static void
-batch_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct BatchState *bs = cls;
-
- bs->batch_ip++;
- if (NULL != bs->batch[bs->batch_ip].label)
- TALER_LOG_DEBUG ("Running batched command: %s\n",
- bs->batch[bs->batch_ip].label);
-
- /* hit end command, leap to next top-level command. */
- if (NULL == bs->batch[bs->batch_ip].label)
- {
- TALER_LOG_INFO ("Exiting from batch: %s\n",
- cmd->label);
- TALER_TESTING_interpreter_next (is);
- return;
- }
-
- bs->batch[bs->batch_ip].run (bs->batch[bs->batch_ip].cls,
- &bs->batch[bs->batch_ip],
- is);
-}
-
-
-/**
- * Cleanup the state from a "reserve status" CMD, and possibly
- * cancel a pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-batch_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct BatchState *bs = cls;
-
- for (unsigned int i=0;
- NULL != bs->batch[i].label;
- i++)
- bs->batch[i].cleanup (bs->batch[i].cls,
- &bs->batch[i]);
- GNUNET_free_non_null (bs->batch);
- GNUNET_free (bs);
-}
-
-
-/**
- * Offer internal data from a "batch" CMD, to other commands.
- *
- * @param cls closure.
- * @param ret[out] result.
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success.
- */
-static int
-batch_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
-#define CURRENT_CMD_INDEX 0
-#define BATCH_INDEX 1
-
- struct BatchState *bs = cls;
-
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_cmd
- (CURRENT_CMD_INDEX, &bs->batch[bs->batch_ip]),
- TALER_TESTING_make_trait_cmd
- (BATCH_INDEX, bs->batch),
- TALER_TESTING_trait_end ()
- };
-
- /* Always return current command. */
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-/**
- * Create a "batch" command. Such command takes a
- * end_CMD-terminated array of CMDs and executed them.
- * Once it hits the end CMD, it passes the control
- * to the next top-level CMD, regardless of it being
- * another batch or ordinary CMD.
- *
- * @param label the command label.
- * @param batch array of CMDs to execute.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_batch (const char *label,
- struct TALER_TESTING_Command *batch)
-{
- struct BatchState *bs;
- unsigned int i;
-
- bs = GNUNET_new (struct BatchState);
- bs->batch_ip = -1;
-
- /* Get number of commands. */
- for (i=0;NULL != batch[i].label;i++)
- /* noop */
- ;
-
- bs->batch = GNUNET_new_array (i + 1,
- struct TALER_TESTING_Command);
- memcpy (bs->batch,
- batch,
- sizeof (struct TALER_TESTING_Command) * i);
-
- struct TALER_TESTING_Command cmd = {
- .cls = bs,
- .label = label,
- .run = &batch_run,
- .cleanup = &batch_cleanup,
- .traits = &batch_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Test if this command is a batch command.
- *
- * @return false if not, true if it is a batch command
- */
-int
-TALER_TESTING_cmd_is_batch (const struct TALER_TESTING_Command *cmd)
-{
- return cmd->run == &batch_run;
-}
-
-
-/**
- * Obtain what command the batch is at.
- *
- * @return cmd current batch command
- */
-struct TALER_TESTING_Command *
-TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd)
-{
- struct BatchState *bs = cmd->cls;
-
- return &bs->batch[bs->batch_ip];
-}
diff --git a/src/exchange-lib/testing_api_cmd_check_keys.c b/src/exchange-lib/testing_api_cmd_check_keys.c
deleted file mode 100644
index d329f31a4..000000000
--- a/src/exchange-lib/testing_api_cmd_check_keys.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- This file is part of TALER
- (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_check_keys.c
- * @brief Implementation of "check keys" test command.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "check keys" CMD.
- */
-struct CheckKeysState
-{
- /**
- * This number will instruct the CMD interpreter to
- * make sure that /keys was downloaded `generation` times
- * _before_ running the very CMD logic.
- */
- unsigned int generation;
-
- /**
- * How many denomination keys the exchange is
- * supposed to have.
- */
- unsigned int num_denom_keys;
-};
-
-
-/**
- * Run the "check keys" command.
- *
- * @param cls closure.
- * @param cmd the command currently being executed.
- * @param is the interpreter state.
- */
-static void
-check_keys_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct CheckKeysState *cks = cls;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "cmd `%s', key generation: %d\n",
- cmd->label,
- is->key_generation);
-
- if (is->key_generation < cks->generation)
- {
- is->working = GNUNET_NO;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Triggering GET /keys, cmd `%s'\n",
- cmd->label);
-
- /* Means re-download /keys. */
- GNUNET_break (0 == TALER_EXCHANGE_check_keys_current
- (is->exchange, GNUNET_YES).abs_value_us);
- return;
- }
- if (is->key_generation > cks->generation)
- {
- /* We got /keys too often, strange. Fatal. May theoretically
- happen if somehow we were really unlucky and /keys expired
- "naturally", but obviously with a sane configuration this
- should also not be. */
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- /* /keys was updated, let's check they were OK! */
- if (cks->num_denom_keys != is->keys->num_denom_keys)
- {
- /* Did not get the expected number of denomination keys! */
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Got %u keys in step %s, expected %u\n",
- is->keys->num_denom_keys,
- cmd->label,
- cks->num_denom_keys);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Cleanup the state.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-check_keys_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct CheckKeysState *cks = cls;
-
- GNUNET_free (cks);
-}
-
-
-/**
- * Make a "check keys" command. This type of command
- * checks whether the number of denomination keys from
- * @a exchange matches @a num_denom_keys.
- *
- * @param label command label
- * @param generation when this command is run, exactly @a
- * generation /keys downloads took place. If the number
- * of downloads is less than @a generation, the logic will
- * first make sure that @a generation downloads are done,
- * and _then_ execute the rest of the command.
- * @param num_denom_keys expected number of denomination keys.
- * @param exchange connection handle to the exchange to test.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_check_keys
- (const char *label,
- unsigned int generation,
- unsigned int num_denom_keys)
-{
- struct CheckKeysState *cks;
-
- cks = GNUNET_new (struct CheckKeysState);
- cks->generation = generation;
- cks->num_denom_keys = num_denom_keys;
-
- struct TALER_TESTING_Command cmd = {
- .cls = cks,
- .label = label,
- .run = &check_keys_run,
- .cleanup = &check_keys_cleanup
- };
-
- return cmd;
-}
-
-/* end of testing_api_cmd_check_keys.c */
diff --git a/src/exchange-lib/testing_api_cmd_deposit.c b/src/exchange-lib/testing_api_cmd_deposit.c
deleted file mode 100644
index 6fa2310d3..000000000
--- a/src/exchange-lib/testing_api_cmd_deposit.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_deposit.c
- * @brief command for testing /deposit.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-#include "taler_signatures.h"
-#include "backoff.h"
-
-
-/**
- * State for a "deposit" CMD.
- */
-struct DepositState
-{
-
- /**
- * Amount to deposit.
- */
- const char *amount;
-
- /**
- * Reference to any command that is able to provide a coin.
- */
- const char *coin_reference;
-
- /**
- * If @e coin_reference refers to an operation that generated
- * an array of coins, this value determines which coin to pick.
- */
- unsigned int coin_index;
-
- /**
- * Wire details of who is depositing -- this would be merchant
- * wire details in a normal scenario.
- */
- json_t *wire_details;
-
- /**
- * JSON string describing what a proposal is about.
- */
- json_t *contract_terms;
-
- /**
- * Relative time (to add to 'now') to compute the refund
- * deadline. Zero for no refunds.
- */
- struct GNUNET_TIME_Relative refund_deadline;
-
- /**
- * Set (by the interpreter) to a fresh private key. This
- * key will be used to sign the deposit request.
- */
- struct TALER_MerchantPrivateKeyP merchant_priv;
-
- /**
- * Deposit handle while operation is running.
- */
- struct TALER_EXCHANGE_DepositHandle *dh;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Task scheduled to try later.
- */
- struct GNUNET_SCHEDULER_Task *retry_task;
-
- /**
- * How long do we wait until we retry?
- */
- struct GNUNET_TIME_Relative backoff;
-
- /**
- * Expected HTTP response code.
- */
- unsigned int expected_response_code;
-
- /**
- * Should we retry on (transient) failures?
- */
- int do_retry;
-
- /**
- * Set to #GNUNET_YES if the /deposit succeeded
- * and we now can provide the resulting traits.
- */
- int traits_ready;
-
- /**
- * Signing key used by the exchange to sign the
- * deposit confirmation.
- */
- struct TALER_ExchangePublicKeyP exchange_pub;
-
- /**
- * Signature from the exchange on the
- * deposit confirmation.
- */
- struct TALER_ExchangeSignatureP exchange_sig;
-};
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-deposit_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is);
-
-
-/**
- * Task scheduled to re-try #deposit_run.
- *
- * @param cls a `struct DepositState`
- */
-static void
-do_retry (void *cls)
-{
- struct DepositState *ds = cls;
-
- ds->retry_task = NULL;
- deposit_run (ds,
- NULL,
- ds->is);
-}
-
-
-/**
- * Callback to analyze the /deposit response, just used to
- * check if the response code is acceptable.
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- * @param exchange_sig signature provided by the exchange
- * (NULL on errors)
- * @param exchange_pub public key of the exchange,
- * used for signing the response.
- * @param obj raw response from the exchange.
- */
-static void
-deposit_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct TALER_ExchangeSignatureP *exchange_sig,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- const json_t *obj)
-{
- struct DepositState *ds = cls;
-
- ds->dh = NULL;
- if (ds->expected_response_code != http_status)
- {
- if (GNUNET_YES == ds->do_retry)
- {
- if ( (0 == http_status) ||
- (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
- (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Retrying deposit failed with %u/%d\n",
- http_status,
- (int) ec);
- /* on DB conflicts, do not use backoff */
- if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
- ds->backoff = GNUNET_TIME_UNIT_ZERO;
- else
- ds->backoff = EXCHANGE_LIB_BACKOFF (ds->backoff);
- ds->retry_task
- = GNUNET_SCHEDULER_add_delayed (ds->backoff,
- &do_retry,
- ds);
- return;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s in %s:%u\n",
- http_status,
- ds->is->commands[ds->is->ip].label,
- __FILE__,
- __LINE__);
- json_dumpf (obj, stderr, 0);
- TALER_TESTING_interpreter_fail (ds->is);
- return;
- }
- if (MHD_HTTP_OK == http_status)
- {
- ds->traits_ready = GNUNET_YES;
- ds->exchange_pub = *exchange_pub;
- ds->exchange_sig = *exchange_sig;
- }
- TALER_TESTING_interpreter_next (ds->is);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-deposit_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct DepositState *ds = cls;
- const struct TALER_TESTING_Command *coin_cmd;
- struct TALER_TESTING_Command *this_cmd;
- const struct TALER_CoinSpendPrivateKeyP *coin_priv;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
- const struct TALER_DenominationSignature *denom_pub_sig;
- struct TALER_CoinSpendSignatureP coin_sig;
- struct GNUNET_TIME_Absolute refund_deadline;
- struct GNUNET_TIME_Absolute wire_deadline;
- struct GNUNET_TIME_Absolute timestamp;
- struct GNUNET_CRYPTO_EddsaPrivateKey *merchant_priv;
- struct TALER_MerchantPublicKeyP merchant_pub;
- struct GNUNET_HashCode h_contract_terms;
- struct TALER_Amount amount;
-
- ds->is = is;
- this_cmd = &is->commands[is->ip];
-
- GNUNET_assert (ds->coin_reference);
- coin_cmd = TALER_TESTING_interpreter_lookup_command
- (is,
- ds->coin_reference);
- if (NULL == coin_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- /* Fixme: do prefer "interpreter fail" over assertions,
- * as the former takes care of shutting down processes too */
- GNUNET_assert (NULL != coin_cmd);
-
- GNUNET_assert (GNUNET_OK
- == TALER_TESTING_get_trait_coin_priv (coin_cmd,
- ds->coin_index,
- &coin_priv));
-
- GNUNET_assert (GNUNET_OK
- == TALER_TESTING_get_trait_denom_pub (coin_cmd,
- ds->coin_index,
- &denom_pub));
-
- GNUNET_assert (GNUNET_OK
- == TALER_TESTING_get_trait_denom_sig (coin_cmd,
- ds->coin_index,
- &denom_pub_sig));
- if (GNUNET_OK !=
- TALER_string_to_amount (ds->amount,
- &amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at '%u/%s'\n",
- ds->amount, is->ip, this_cmd->label);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_assert (GNUNET_OK ==
- TALER_JSON_hash (ds->contract_terms,
- &h_contract_terms));
-
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
- &coin_pub.eddsa_pub);
-
- merchant_priv = GNUNET_CRYPTO_eddsa_key_create ();
- ds->merchant_priv.eddsa_priv = *merchant_priv;
- GNUNET_free (merchant_priv);
-
- if (0 != ds->refund_deadline.rel_value_us)
- {
- refund_deadline = GNUNET_TIME_relative_to_absolute
- (ds->refund_deadline);
- wire_deadline = GNUNET_TIME_relative_to_absolute
- (GNUNET_TIME_relative_multiply
- (ds->refund_deadline, 2));
- }
- else
- {
- refund_deadline = GNUNET_TIME_UNIT_ZERO_ABS;
- wire_deadline = GNUNET_TIME_relative_to_absolute
- (GNUNET_TIME_UNIT_ZERO);
- }
- GNUNET_CRYPTO_eddsa_key_get_public
- (&ds->merchant_priv.eddsa_priv,
- &merchant_pub.eddsa_pub);
-
- timestamp = GNUNET_TIME_absolute_get ();
- GNUNET_TIME_round_abs (&timestamp);
- GNUNET_TIME_round_abs (&refund_deadline);
- GNUNET_TIME_round_abs (&wire_deadline);
-
- {
- struct TALER_DepositRequestPS dr;
-
- memset (&dr, 0, sizeof (dr));
- dr.purpose.size = htonl
- (sizeof (struct TALER_DepositRequestPS));
- dr.purpose.purpose = htonl
- (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
- dr.h_contract_terms = h_contract_terms;
- GNUNET_assert
- (GNUNET_OK ==
- TALER_JSON_merchant_wire_signature_hash (ds->wire_details,
- &dr.h_wire));
- dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
- dr.refund_deadline = GNUNET_TIME_absolute_hton
- (refund_deadline);
- TALER_amount_hton (&dr.amount_with_fee, &amount);
- TALER_amount_hton
- (&dr.deposit_fee, &denom_pub->fee_deposit);
- dr.merchant = merchant_pub;
- dr.coin_pub = coin_pub;
- GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign
- (&coin_priv->eddsa_priv,
- &dr.purpose,
- &coin_sig.eddsa_signature));
- }
- ds->dh = TALER_EXCHANGE_deposit
- (is->exchange,
- &amount,
- wire_deadline,
- ds->wire_details,
- &h_contract_terms,
- &coin_pub,
- denom_pub_sig,
- &denom_pub->key,
- timestamp,
- &merchant_pub,
- refund_deadline,
- &coin_sig,
- &deposit_cb,
- ds);
-
- if (NULL == ds->dh)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- return;
-}
-
-
-/**
- * Free the state of a "deposit" CMD, and possibly cancel a
- * pending operation thereof.
- *
- * @param cls closure, typically a #struct WireState.
- * @param cmd the command which is being cleaned up.
- */
-static void
-deposit_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct DepositState *ds = cls;
-
- if (NULL != ds->dh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- ds->is->ip,
- cmd->label);
- TALER_EXCHANGE_deposit_cancel (ds->dh);
- ds->dh = NULL;
- }
- if (NULL != ds->retry_task)
- {
- GNUNET_SCHEDULER_cancel (ds->retry_task);
- ds->retry_task = NULL;
- }
- json_decref (ds->wire_details);
- json_decref (ds->contract_terms);
- GNUNET_free (ds);
-}
-
-
-/**
- * Offer internal data from a "deposit" CMD, to other commands.
- *
- * @param cls closure.
- * @param ret[out] result.
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- *
- * @return #GNUNET_OK on success.
- */
-static int
-deposit_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct DepositState *ds = cls;
- const struct TALER_TESTING_Command *coin_cmd;
- /* Will point to coin cmd internals. */
- const struct TALER_CoinSpendPrivateKeyP *coin_spent_priv;
-
- coin_cmd = TALER_TESTING_interpreter_lookup_command
- (ds->is,
- ds->coin_reference);
-
- if (NULL == coin_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (ds->is);
- return GNUNET_NO;
- }
-
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_coin_priv (coin_cmd,
- ds->coin_index,
- &coin_spent_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (ds->is);
- return GNUNET_NO;
- }
-
- struct TALER_TESTING_Trait traits[] = {
- /* First two traits are only available if
- ds->traits is #GNUNET_YES */
- TALER_TESTING_make_trait_exchange_pub (0,
- &ds->exchange_pub),
- TALER_TESTING_make_trait_exchange_sig (0,
- &ds->exchange_sig),
- /* These traits are always available */
- TALER_TESTING_make_trait_coin_priv (0,
- coin_spent_priv),
- TALER_TESTING_make_trait_wire_details (0,
- ds->wire_details),
- TALER_TESTING_make_trait_contract_terms (0,
- ds->contract_terms),
- TALER_TESTING_make_trait_peer_key (0,
- &ds->merchant_priv.eddsa_priv),
- TALER_TESTING_make_trait_amount (0,
- ds->amount),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait ((ds->traits_ready)
- ? traits
- : &traits[2],
- ret,
- trait,
- index);
-}
-
-/**
- * Create a "deposit" command.
- *
- * @param label command label.
- * @param coin_reference reference to any operation that can
- * provide a coin.
- * @param coin_index if @a withdraw_reference offers an array of
- * coins, this parameter selects which one in that array.
- * This value is currently ignored, as only one-coin
- * withdrawals are implemented.
- * @param wire_details wire details associated with the "deposit"
- * request.
- * @param contract_terms contract terms to be signed over by the
- * coin.
- * @param refund_deadline refund deadline, zero means 'no refunds'.
- * Note, if time were absolute, then it would have come
- * one day and disrupt tests meaning.
- * @param amount how much is going to be deposited.
- * @param expected_response_code expected HTTP response code.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_deposit
- (const char *label,
- const char *coin_reference,
- unsigned int coin_index,
- json_t *wire_details,
- const char *contract_terms,
- struct GNUNET_TIME_Relative refund_deadline,
- const char *amount,
- unsigned int expected_response_code)
-{
- struct DepositState *ds;
-
- ds = GNUNET_new (struct DepositState);
- ds->coin_reference = coin_reference;
- ds->coin_index = coin_index;
- ds->wire_details = wire_details;
- ds->contract_terms = json_loads (contract_terms,
- JSON_REJECT_DUPLICATES,
- NULL);
- if (NULL == ds->contract_terms)
- {
- GNUNET_log
- (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse contract terms `%s' for CMD `%s'\n",
- contract_terms,
- label);
- GNUNET_assert (0);
- }
-
- ds->refund_deadline = refund_deadline;
- ds->amount = amount;
- ds->expected_response_code = expected_response_code;
-
- struct TALER_TESTING_Command cmd = {
- .cls = ds,
- .label = label,
- .run = &deposit_run,
- .cleanup = &deposit_cleanup,
- .traits = &deposit_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Modify a deposit command to enable retries when we get transient
- * errors from the exchange.
- *
- * @param cmd a deposit command
- * @return the command with retries enabled
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_deposit_with_retry (struct TALER_TESTING_Command cmd)
-{
- struct DepositState *ds;
-
- GNUNET_assert (&deposit_run == cmd.run);
- ds = cmd.cls;
- ds->do_retry = GNUNET_YES;
- return cmd;
-}
-
-
-/* end of testing_api_cmd_deposit.c */
diff --git a/src/exchange-lib/testing_api_cmd_exec_aggregator.c b/src/exchange-lib/testing_api_cmd_exec_aggregator.c
deleted file mode 100644
index c51d44989..000000000
--- a/src/exchange-lib/testing_api_cmd_exec_aggregator.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not,
- see <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_exec_aggregator.c
- * @brief run the taler-exchange-aggregator command
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "aggregator" CMD.
- */
-struct AggregatorState
-{
-
- /**
- * Aggregator process.
- */
- struct GNUNET_OS_Process *aggregator_proc;
-
- /**
- * Configuration file used by the aggregator.
- */
- const char *config_filename;
-};
-
-
-/**
- * Run the command. Use the `taler-exchange-aggregator' program.
- *
- * @param cls closure.
- * @param cmd command being run.
- * @param is interpreter state.
- */
-static void
-aggregator_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct AggregatorState *as = cls;
-
- as->aggregator_proc
- = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-exchange-aggregator",
- "taler-exchange-aggregator",
- "-c", as->config_filename,
- "-t", /* exit when done */
- NULL);
- if (NULL == as->aggregator_proc)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_TESTING_wait_for_sigchld (is);
-}
-
-
-/**
- * Free the state of a "aggregator" CMD, and possibly kill its
- * process if it did not terminate correctly.
- *
- * @param cls closure.
- * @param cmd the command being freed.
- */
-static void
-aggregator_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct AggregatorState *as = cls;
-
- if (NULL != as->aggregator_proc)
- {
- GNUNET_break (0 ==
- GNUNET_OS_process_kill (as->aggregator_proc,
- SIGKILL));
- GNUNET_OS_process_wait (as->aggregator_proc);
- GNUNET_OS_process_destroy (as->aggregator_proc);
- as->aggregator_proc = NULL;
- }
- GNUNET_free (as);
-}
-
-
-/**
- * Offer "aggregator" CMD internal data to other commands.
- *
- * @param cls closure.
- * @param ret[out] result.
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success
- */
-static int
-aggregator_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct AggregatorState *as = cls;
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_process (0, &as->aggregator_proc),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Make a "aggregator" CMD.
- *
- * @param label command label.
- * @param config_filename configuration file for the
- * aggregator to use.
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_exec_aggregator (const char *label,
- const char *config_filename)
-{
- struct AggregatorState *as;
-
- as = GNUNET_new (struct AggregatorState);
- as->config_filename = config_filename;
-
- struct TALER_TESTING_Command cmd = {
- .cls = as,
- .label = label,
- .run = &aggregator_run,
- .cleanup = &aggregator_cleanup,
- .traits = &aggregator_traits
- };
-
- return cmd;
-}
-
-/* end of testing_api_cmd_exec_aggregator.c */
diff --git a/src/exchange-lib/testing_api_cmd_exec_auditor-sign.c b/src/exchange-lib/testing_api_cmd_exec_auditor-sign.c
deleted file mode 100644
index 90a1654ce..000000000
--- a/src/exchange-lib/testing_api_cmd_exec_auditor-sign.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not,
- see <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_exec_auditor-sign.c
- * @brief run the taler-exchange-aggregator command
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-
-
-/**
- * State for a "auditor sign" CMD.
- */
-struct AuditorSignState
-{
-
- /**
- * Handle to the process making the signature.
- */
- struct GNUNET_OS_Process *auditor_sign_proc;
-
- /**
- * Configuration file used by the command.
- */
- const char *config_filename;
-
- /**
- * File name of signed blob.
- */
- char *signed_keys_out;
-};
-
-
-/**
- * Run the command; calls the `taler-auditor-sign' program.
- *
- * @param cls closure.
- * @param cmd the command.
- * @param is interpreter state.
- */
-static void
-auditor_sign_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct AuditorSignState *ass = cls;
-
- struct GNUNET_CONFIGURATION_Handle *cfg;
- char *test_home_dir;
- char *exchange_master_pub;
- struct GNUNET_TIME_Absolute now;
-
- cfg = GNUNET_CONFIGURATION_create ();
- if (GNUNET_OK != GNUNET_CONFIGURATION_load
- (cfg, ass->config_filename))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- "paths",
- "TALER_TEST_HOME",
- &test_home_dir))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "paths",
- "TALER_TEST_HOME");
- GNUNET_CONFIGURATION_destroy (cfg);
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- now = GNUNET_TIME_absolute_get ();
- GNUNET_asprintf
- (&ass->signed_keys_out,
- "%s/.local/share/taler/auditors/auditor-%llu.out",
- test_home_dir,
- (unsigned long long) now.abs_value_us);
- GNUNET_free (test_home_dir);
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange",
- "MASTER_PUBLIC_KEY",
- &exchange_master_pub))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange",
- "MASTER_PUBLIC_KEY");
- GNUNET_CONFIGURATION_destroy (cfg);
-
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_CONFIGURATION_destroy (cfg);
-
- ass->auditor_sign_proc = GNUNET_OS_start_process
- (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-auditor-sign",
- "taler-auditor-sign",
- "-c", ass->config_filename,
- "-u", "http://auditor/",
- "-m", exchange_master_pub,
- "-r", "auditor.in",
- "-o", ass->signed_keys_out,
- NULL);
- GNUNET_free (exchange_master_pub);
- if (NULL == ass->auditor_sign_proc)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_TESTING_wait_for_sigchld (is);
-}
-
-
-/**
- * Free the state of a "auditor sign" CMD, and possibly
- * kill its process if it did not terminate correctly.
- *
- * @param cls closure.
- * @param cmd the command being freed.
- */
-static void
-auditor_sign_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct AuditorSignState *ass = cls;
-
- if (NULL != ass->auditor_sign_proc)
- {
- GNUNET_break (0 == GNUNET_OS_process_kill
- (ass->auditor_sign_proc, SIGKILL));
- GNUNET_OS_process_wait (ass->auditor_sign_proc);
- GNUNET_OS_process_destroy (ass->auditor_sign_proc);
- ass->auditor_sign_proc = NULL;
- }
- GNUNET_free_non_null (ass->signed_keys_out);
- GNUNET_free (ass);
-}
-
-
-/**
- * Offer "auditor sign" CMD internal data to other commands.
- *
- * @param cls closure.
- * @param ret[out] result.
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success.
- */
-static int
-auditor_sign_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct AuditorSignState *ass = cls;
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_process (0, &ass->auditor_sign_proc),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Make a "auditor sign" CMD.
- *
- * @param label command label
- * @param config_filename configuration filename
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_exec_auditor_sign (const char *label,
- const char *config_filename)
-{
- struct AuditorSignState *ass;
-
- ass = GNUNET_new (struct AuditorSignState);
- ass->config_filename = config_filename;
-
-
- struct TALER_TESTING_Command cmd = {
- .cls = ass,
- .label = label,
- .run = &auditor_sign_run,
- .cleanup = &auditor_sign_cleanup,
- .traits = &auditor_sign_traits
- };
-
- return cmd;
-}
-
-/* end of testing_api_cmd_exec_auditor-sign.c */
diff --git a/src/exchange-lib/testing_api_cmd_exec_keyup.c b/src/exchange-lib/testing_api_cmd_exec_keyup.c
deleted file mode 100644
index 576aab3c7..000000000
--- a/src/exchange-lib/testing_api_cmd_exec_keyup.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not,
- see <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_exec_keyup.c
- * @brief run the taler-exchange-keyup command
- * @author Marcello Stanisci
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "keyup" CMD.
- */
-struct KeyupState
-{
-
- /**
- * Process for the "keyup" command.
- */
- struct GNUNET_OS_Process *keyup_proc;
-
- /**
- * Configuration file used by the command.
- */
- const char *config_filename;
-};
-
-
-/**
- * Run the command; calls the `taler-exchange-keyup' program.
- *
- * @param cls closure.
- * @param cmd the commaind being run.
- * @param is interpreter state.
- */
-static void
-keyup_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct KeyupState *ks = cls;
-
- ks->keyup_proc = GNUNET_OS_start_process
- (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-exchange-keyup",
- "taler-exchange-keyup",
- "-c", ks->config_filename,
- "-o", "auditor.in",
- NULL);
-
- if (NULL == ks->keyup_proc)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_TESTING_wait_for_sigchld (is);
-}
-
-
-/**
- * Free the state of a "keyup" CMD, and possibly kills its
- * process if it did not terminate correctly.
- *
- * @param cls closure.
- * @param cmd the command being freed.
- */
-static void
-keyup_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct KeyupState *ks = cls;
-
- if (NULL != ks->keyup_proc)
- {
- GNUNET_break (0 ==
- GNUNET_OS_process_kill (ks->keyup_proc,
- SIGKILL));
- GNUNET_OS_process_wait (ks->keyup_proc);
- GNUNET_OS_process_destroy (ks->keyup_proc);
- ks->keyup_proc = NULL;
- }
- GNUNET_free (ks);
-}
-
-
-/**
- * Offer "keyup" CMD internal data to other commands.
- *
- * @param cls closure.
- * @param ret[out] result
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- *
- * @return #GNUNET_OK on success.
- */
-static int
-keyup_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct KeyupState *ks = cls;
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_process (0, &ks->keyup_proc),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Make the "keyup" CMD.
- *
- * @param label command label.
- * @param config_filename configuration filename.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_exec_keyup (const char *label,
- const char *config_filename)
-{
- struct KeyupState *ks;
-
- ks = GNUNET_new (struct KeyupState);
- ks->config_filename = config_filename;
-
- struct TALER_TESTING_Command cmd = {
- .cls = ks,
- .label = label,
- .run = &keyup_run,
- .cleanup = &keyup_cleanup,
- .traits = &keyup_traits
- };
-
- return cmd;
-}
-
-/* end of testing_api_cmd_exec_keyup.c */
diff --git a/src/exchange-lib/testing_api_cmd_exec_wirewatch.c b/src/exchange-lib/testing_api_cmd_exec_wirewatch.c
deleted file mode 100644
index a81bf5c2b..000000000
--- a/src/exchange-lib/testing_api_cmd_exec_wirewatch.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3,
- or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_exec_wirewatch.c
- * @brief run the taler-exchange-wirewatch command
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-
-
-/**
- * State for a "wirewatch" CMD.
- */
-struct WirewatchState
-{
-
- /**
- * Process for the wirewatcher.
- */
- struct GNUNET_OS_Process *wirewatch_proc;
-
- /**
- * Configuration file used by the wirewatcher.
- */
- const char *config_filename;
-};
-
-/**
- * Run the command; use the `taler-exchange-wirewatch' program.
- *
- * @param cls closure.
- * @param cmd command currently being executed.
- * @param is interpreter state.
- */
-static void
-wirewatch_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct WirewatchState *ws = cls;
-
- ws->wirewatch_proc
- = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-exchange-wirewatch",
- "taler-exchange-wirewatch",
- "-c", ws->config_filename,
- "-T", /* exit when done */
- NULL);
- if (NULL == ws->wirewatch_proc)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_TESTING_wait_for_sigchld (is);
-}
-
-
-/**
- * Free the state of a "wirewatch" CMD, and possibly
- * kills its process if it did not terminate regularly.
- *
- * @param cls closure.
- * @param cmd the command being freed.
- */
-static void
-wirewatch_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct WirewatchState *ws = cls;
-
- if (NULL != ws->wirewatch_proc)
- {
- GNUNET_break (0 ==
- GNUNET_OS_process_kill (ws->wirewatch_proc,
- SIGKILL));
- GNUNET_OS_process_wait (ws->wirewatch_proc);
- GNUNET_OS_process_destroy (ws->wirewatch_proc);
- ws->wirewatch_proc = NULL;
- }
- GNUNET_free (ws);
-}
-
-
-/**
- * Offer "wirewatch" CMD internal data to other commands.
- *
- * @param cls closure.
- * @param ret[out] result.
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success.
- */
-static int
-wirewatch_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct WirewatchState *ws = cls;
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_process (0,
- &ws->wirewatch_proc),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Make a "wirewatch" CMD.
- *
- * @param label command label.
- * @param config_filename configuration filename.
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_exec_wirewatch (const char *label,
- const char *config_filename)
-{
- struct WirewatchState *ws;
-
- ws = GNUNET_new (struct WirewatchState);
- ws->config_filename = config_filename;
-
-
- struct TALER_TESTING_Command cmd = {
- .cls = ws,
- .label = label,
- .run = &wirewatch_run,
- .cleanup = &wirewatch_cleanup,
- .traits = &wirewatch_traits
- };
-
- return cmd;
-}
-
-/* end of testing_api_cmd_exec_wirewatch.c */
diff --git a/src/exchange-lib/testing_api_cmd_fakebank_transfer.c b/src/exchange-lib/testing_api_cmd_fakebank_transfer.c
deleted file mode 100644
index 43f72573b..000000000
--- a/src/exchange-lib/testing_api_cmd_fakebank_transfer.c
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_fakebank_transfer.c
- * @brief implementation of a fakebank wire transfer command
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_bank_service.h"
-#include "taler_fakebank_lib.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-#include "taler_testing_bank_lib.h"
-#include "backoff.h"
-
-/**
- * State for a "fakebank transfer" CMD.
- */
-struct FakebankTransferState
-{
-
- /**
- * Label of any command that can trait-offer a reserve priv.
- */
- const char *reserve_reference;
-
- /**
- * Wire transfer amount.
- */
- struct TALER_Amount amount;
-
- /**
- * Wire transfer subject.
- */
- const char *subject;
-
- /**
- * Base URL of the bank serving the request.
- */
- const char *bank_url;
-
- /**
- * Money sender account number.
- */
- uint64_t debit_account_no;
-
- /**
- * Money receiver account number.
- */
- uint64_t credit_account_no;
-
- /**
- * Username to use for authentication.
- */
- const char *auth_username;
-
- /**
- * Password to use for authentication.
- */
- const char *auth_password;
-
- /**
- * Set (by the interpreter) to the reserve's private key
- * we used to make a wire transfer subject line with.
- */
- struct TALER_ReservePrivateKeyP reserve_priv;
-
- /**
- * Handle to the pending request at the fakebank.
- */
- struct TALER_BANK_AdminAddIncomingHandle *aih;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Set to the wire transfer's unique ID.
- */
- uint64_t serial_id;
-
- /**
- * Exchange URL. This value is fed to the bank when requesting
- * the wire transfer; note: the bank needs it because a merchant
- * might want to know which exchange performed a wire transfer to
- * them, just by looking at bank records.
- */
- const char *exchange_url;
-
- /**
- * Merchant instance. Sometimes used to get the tip reserve
- * private key by reading the appropriate config section.
- */
- const char *instance;
-
- /**
- * Configuration filename. Used to get the tip reserve key
- * filename (used to obtain a public key to write in the
- * transfer subject).
- */
- const char *config_filename;
-
- /**
- * Task scheduled to try later.
- */
- struct GNUNET_SCHEDULER_Task *retry_task;
-
- /**
- * How long do we wait until we retry?
- */
- struct GNUNET_TIME_Relative backoff;
-
- /**
- * Was this command modified via
- * #TALER_TESTING_cmd_fakebank_transfer_with_retry to
- * enable retries?
- */
- int do_retry;
-};
-
-
-/**
- * Run the "fakebank transfer" CMD.
- *
- * @param cls closure.
- * @param cmd CMD being run.
- * @param is interpreter state.
- */
-static void
-fakebank_transfer_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is);
-
-
-/**
- * Task scheduled to re-try #fakebank_transfer_run.
- *
- * @param cls a `struct FakebankTransferState`
- */
-static void
-do_retry (void *cls)
-{
- struct FakebankTransferState *fts = cls;
-
- fts->retry_task = NULL;
- fakebank_transfer_run (fts,
- NULL,
- fts->is);
-}
-
-
-/**
- * This callback will process the fakebank response to the wire
- * transfer. It just checks whether the HTTP response code is
- * acceptable.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for
- * successful status request; 0 if the exchange's reply is
- * bogus (fails to follow the protocol)
- * @param ec taler-specific error code, #TALER_EC_NONE on success
- * @param serial_id unique ID of the wire transfer
- * @param full_response full response from the exchange (for
- * logging, in case of errors)
- */
-static void
-add_incoming_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- uint64_t serial_id,
- const json_t *full_response)
-{
- struct FakebankTransferState *fts = cls;
- struct TALER_TESTING_Interpreter *is = fts->is;
-
- fts->aih = NULL;
- fts->serial_id = serial_id;
- if (MHD_HTTP_OK != http_status)
- {
- if (GNUNET_YES == fts->do_retry)
- {
- if ( (0 == http_status) ||
- (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
- (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Retrying fakebank transfer failed with %u/%d\n",
- http_status,
- (int) ec);
- /* on DB conflicts, do not use backoff */
- if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
- fts->backoff = GNUNET_TIME_UNIT_ZERO;
- else
- fts->backoff = EXCHANGE_LIB_BACKOFF (fts->backoff);
- fts->retry_task = GNUNET_SCHEDULER_add_delayed (fts->backoff,
- &do_retry,
- fts);
- return;
- }
- }
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Fakebank returned HTTP status %u/%d\n",
- http_status,
- (int) ec);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Run the "fakebank transfer" CMD.
- *
- * @param cls closure.
- * @param cmd CMD being run.
- * @param is interpreter state.
- */
-static void
-fakebank_transfer_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct FakebankTransferState *fts = cls;
- char *subject;
- struct TALER_BANK_AuthenticationData auth;
- struct TALER_ReservePublicKeyP reserve_pub;
-
- if (NULL != fts->subject)
- {
- subject = GNUNET_strdup (fts->subject);
- }
- else
- {
- /* Use reserve public key as subject */
- if (NULL != fts->reserve_reference)
- {
- const struct TALER_TESTING_Command *ref;
- const struct TALER_ReservePrivateKeyP *reserve_priv;
-
- ref = TALER_TESTING_interpreter_lookup_command
- (is, fts->reserve_reference);
- if (NULL == ref)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_reserve_priv (ref,
- 0,
- &reserve_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- fts->reserve_priv.eddsa_priv = reserve_priv->eddsa_priv;
- }
- else
- {
- if (NULL != fts->instance)
- {
- char *section;
- char *keys;
- struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
- struct GNUNET_CONFIGURATION_Handle *cfg;
-
- GNUNET_assert (NULL != fts->config_filename);
- cfg = GNUNET_CONFIGURATION_create ();
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_load (cfg,
- fts->config_filename))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_asprintf (&section,
- "instance-%s",
- fts->instance);
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename
- (cfg,
- section,
- "TIP_RESERVE_PRIV_FILENAME",
- &keys))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Configuration fails to specify reserve"
- " private key filename in section %s\n",
- section);
- GNUNET_free (section);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- priv = GNUNET_CRYPTO_eddsa_key_create_from_file (keys);
- if (NULL == priv)
- {
- GNUNET_log_config_invalid
- (GNUNET_ERROR_TYPE_ERROR,
- section,
- "TIP_RESERVE_PRIV_FILENAME",
- "Failed to read private key");
- GNUNET_free (keys);
- GNUNET_free (section);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- fts->reserve_priv.eddsa_priv = *priv;
- GNUNET_free (priv);
- GNUNET_CONFIGURATION_destroy (cfg);
- }
- else
- {
- /* No referenced reserve, no instance to take priv
- * from, no explicit subject given: create new key! */
- struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
-
- priv = GNUNET_CRYPTO_eddsa_key_create ();
- fts->reserve_priv.eddsa_priv = *priv;
- GNUNET_free (priv);
- }
- }
- GNUNET_CRYPTO_eddsa_key_get_public
- (&fts->reserve_priv.eddsa_priv, &reserve_pub.eddsa_pub);
- subject = GNUNET_STRINGS_data_to_string_alloc
- (&reserve_pub, sizeof (reserve_pub));
- }
-
- auth.method = TALER_BANK_AUTH_BASIC;
- auth.details.basic.username = (char *) fts->auth_username;
- auth.details.basic.password = (char *) fts->auth_password;
- fts->is = is;
- fts->aih = TALER_BANK_admin_add_incoming
- (TALER_TESTING_interpreter_get_context (is),
- fts->bank_url,
- &auth,
- fts->exchange_url,
- subject,
- &fts->amount,
- fts->debit_account_no,
- fts->credit_account_no,
- &add_incoming_cb,
- fts);
- GNUNET_free (subject);
- if (NULL == fts->aih)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-}
-
-
-/**
- * Free the state of a "fakebank transfer" CMD, and possibly
- * cancel a pending operation thereof.
- *
- * @param cls closure
- * @param cmd current CMD being cleaned up.
- */
-static void
-fakebank_transfer_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct FakebankTransferState *fts = cls;
-
- if (NULL != fts->aih)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %s did not complete\n",
- cmd->label);
- TALER_BANK_admin_add_incoming_cancel (fts->aih);
- }
- if (NULL != fts->retry_task)
- {
- GNUNET_SCHEDULER_cancel (fts->retry_task);
- fts->retry_task = NULL;
- }
- GNUNET_free (fts);
-}
-
-/**
- * Offer internal data from a "fakebank transfer" CMD to other
- * commands.
- *
- * @param cls closure.
- * @param ret[out] result
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success.
- */
-static int
-fakebank_transfer_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct FakebankTransferState *fts = cls;
- #define MANDATORY 6
- struct TALER_TESTING_Trait traits[MANDATORY + 1] = {
- TALER_TESTING_MAKE_TRAIT_DEBIT_ACCOUNT
- (&fts->debit_account_no),
- TALER_TESTING_MAKE_TRAIT_CREDIT_ACCOUNT
- (&fts->credit_account_no),
- TALER_TESTING_make_trait_url (0, fts->exchange_url),
- TALER_TESTING_MAKE_TRAIT_ROW_ID (&fts->serial_id),
- TALER_TESTING_make_trait_amount_obj (0, &fts->amount),
- };
-
- /**
- * The user gave explicit subject,
- * there must be NO reserve priv. */
- if (NULL != fts->subject)
- traits[MANDATORY - 1] =
- TALER_TESTING_make_trait_transfer_subject (0,
- fts->subject);
- /* A reserve priv must exist if no subject was given. */
- else
- traits[MANDATORY - 1] = TALER_TESTING_make_trait_reserve_priv
- (0, &fts->reserve_priv),
-
- traits[MANDATORY] = TALER_TESTING_trait_end ();
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Create fakebank_transfer command, the subject line will be
- * derived from a randomly created reserve priv. Note that that
- * reserve priv will then be offered as trait.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- * wire transer. For simplicity, both credit and debit
- * bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
- * @param auth_username username identifying the @a
- * debit_account_no at the bank.
- * @param auth_password password for @a auth_username.
- * @param exchange_url which exchange is involved in this transfer.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer
- (const char *label,
- const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
- const char *auth_username,
- const char *auth_password,
- const char *exchange_url)
-{
- struct FakebankTransferState *fts;
-
- fts = GNUNET_new (struct FakebankTransferState);
- fts->bank_url = bank_url;
- fts->credit_account_no = credit_account_no;
- fts->debit_account_no = debit_account_no;
- fts->auth_username = auth_username;
- fts->auth_password = auth_password;
- fts->exchange_url = exchange_url;
- if (GNUNET_OK !=
- TALER_string_to_amount (amount,
- &fts->amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %s\n",
- amount,
- label);
- GNUNET_assert (0);
- }
-
- struct TALER_TESTING_Command cmd = {
- .cls = fts,
- .label = label,
- .run = &fakebank_transfer_run,
- .cleanup = &fakebank_transfer_cleanup,
- .traits = &fakebank_transfer_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Create "fakebank transfer" CMD, letting the caller specifying
- * the subject line.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- * wire transer. For simplicity, both credit and debit
- * bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
- *
- * @param auth_username username identifying the @a
- * debit_account_no at the bank.
- * @param auth_password password for @a auth_username.
- * @param subject wire transfer's subject line.
- * @param exchange_url which exchange is involved in this transfer.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_subject
- (const char *label,
- const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
- const char *auth_username,
- const char *auth_password,
- const char *subject,
- const char *exchange_url)
-{
- struct FakebankTransferState *fts;
-
- fts = GNUNET_new (struct FakebankTransferState);
-
- TALER_LOG_DEBUG ("%s:FTS@%p\n",
- label,
- fts);
-
- fts->bank_url = bank_url;
- fts->credit_account_no = credit_account_no;
- fts->debit_account_no = debit_account_no;
- fts->auth_username = auth_username;
- fts->auth_password = auth_password;
- fts->subject = subject;
- fts->exchange_url = exchange_url;
- if (GNUNET_OK !=
- TALER_string_to_amount (amount,
- &fts->amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %s\n",
- amount,
- label);
- GNUNET_assert (0);
- }
-
- struct TALER_TESTING_Command cmd = {
- .cls = fts,
- .label = label,
- .run = &fakebank_transfer_run,
- .cleanup = &fakebank_transfer_cleanup,
- .traits = &fakebank_transfer_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Create "fakebank transfer" CMD, letting the caller specify
- * a reference to a command that can offer a reserve private key.
- * This private key will then be used to construct the subject line
- * of the wire transfer.
- *
- * @param label command label.
- * @param amount the amount to transfer.
- * @param bank_url base URL of the bank running the transfer.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
- * @param auth_username username identifying the @a
- * debit_account_no at the bank.
- * @param auth_password password for @a auth_username.
- * @param ref reference to a command that can offer a reserve
- * private key.
- * @param exchange_url the exchage involved in the transfer,
- * tipically receiving the money in order to fuel a reserve.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_ref
- (const char *label,
- const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
- const char *auth_username,
- const char *auth_password,
- const char *ref,
- const char *exchange_url)
-{
- struct FakebankTransferState *fts;
-
- fts = GNUNET_new (struct FakebankTransferState);
- fts->bank_url = bank_url;
- fts->credit_account_no = credit_account_no;
- fts->debit_account_no = debit_account_no;
- fts->auth_username = auth_username;
- fts->auth_password = auth_password;
- fts->reserve_reference = ref;
- fts->exchange_url = exchange_url;
- if (GNUNET_OK !=
- TALER_string_to_amount (amount,
- &fts->amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %s\n",
- amount,
- label);
- GNUNET_assert (0);
- }
-
- struct TALER_TESTING_Command cmd = {
- .cls = fts,
- .label = label,
- .run = &fakebank_transfer_run,
- .cleanup = &fakebank_transfer_cleanup,
- .traits = &fakebank_transfer_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Create "fakebank transfer" CMD, letting the caller specifying
- * the merchant instance. This version is useful when a tip
- * reserve should be topped up, in fact the interpreter will need
- * the "tipping instance" in order to get the instance public key
- * and make a wire transfer subject out of it.
- *
- * @param label command label.
- * @param amount amount to transfer.
- * @param bank_url base URL of the bank that implements this
- * wire transer. For simplicity, both credit and debit
- * bank account exist at the same bank.
- * @param debit_account_no which account (expressed as a number)
- * gives money.
- * @param credit_account_no which account (expressed as a number)
- * receives money.
- *
- * @param auth_username username identifying the @a
- * debit_account_no at the bank.
- * @param auth_password password for @a auth_username.
- * @param instance the instance that runs the tipping. Under this
- * instance, the configuration file will provide the private
- * key of the tipping reserve. This data will then used to
- * construct the wire transfer subject line.
- * @param exchange_url which exchange is involved in this transfer.
- * @param config_filename configuration file to use.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_with_instance
- (const char *label,
- const char *amount,
- const char *bank_url,
- uint64_t debit_account_no,
- uint64_t credit_account_no,
- const char *auth_username,
- const char *auth_password,
- const char *instance,
- const char *exchange_url,
- const char *config_filename)
-{
- struct FakebankTransferState *fts;
-
- fts = GNUNET_new (struct FakebankTransferState);
- fts->bank_url = bank_url;
- fts->credit_account_no = credit_account_no;
- fts->debit_account_no = debit_account_no;
- fts->auth_username = auth_username;
- fts->auth_password = auth_password;
- fts->instance = instance;
- fts->exchange_url = exchange_url;
- fts->config_filename = config_filename;
- if (GNUNET_OK !=
- TALER_string_to_amount (amount,
- &fts->amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %s\n",
- amount,
- label);
- GNUNET_assert (0);
- }
-
- struct TALER_TESTING_Command cmd = {
- .cls = fts,
- .label = label,
- .run = &fakebank_transfer_run,
- .cleanup = &fakebank_transfer_cleanup,
- .traits = &fakebank_transfer_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Modify a fakebank transfer command to enable retries when the
- * reserve is not yet full or we get other transient errors from the
- * fakebank.
- *
- * @param cmd a fakebank transfer command
- * @return the command with retries enabled
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_fakebank_transfer_retry (struct TALER_TESTING_Command cmd)
-{
- struct FakebankTransferState *fts;
-
- GNUNET_assert (&fakebank_transfer_run == cmd.run);
- fts = cmd.cls;
- fts->do_retry = GNUNET_YES;
- return cmd;
-}
-
-/* end of testing_api_cmd_fakebank_transfer.c */
diff --git a/src/exchange-lib/testing_api_cmd_payback.c b/src/exchange-lib/testing_api_cmd_payback.c
deleted file mode 100644
index a4a3aeff1..000000000
--- a/src/exchange-lib/testing_api_cmd_payback.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange/testing_api_cmd_payback.c
- * @brief Implement the /revoke and /payback test commands.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "revoke" CMD.
- */
-struct RevokeState
-{
- /**
- * Expected HTTP status code.
- */
- unsigned int expected_response_code;
-
- /**
- * Command that offers a denomination to revoke.
- */
- const char *coin_reference;
-
- /**
- * The interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * The revoke process handle.
- */
- struct GNUNET_OS_Process *revoke_proc;
-
- /**
- * Configuration file name.
- */
- const char *config_filename;
-
- /**
- * Encoding of the denomination (to revoke) public key hash.
- */
- char *dhks;
-
-};
-
-
-/**
- * State for a "pay back" CMD.
- */
-struct PaybackState
-{
- /**
- * Expected HTTP status code.
- */
- unsigned int expected_response_code;
-
- /**
- * Command that offers a reserve private key,
- * plus a coin to be paid back.
- */
- const char *coin_reference;
-
- /**
- * The interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Amount expected to be paid back.
- */
- const char *amount;
-
- /**
- * Handle to the ongoing operation.
- */
- struct TALER_EXCHANGE_PaybackHandle *ph;
-};
-
-/**
- * Check the result of the payback request: checks whether
- * the HTTP response code is good, and that the coin that
- * was paid back belonged to the right reserve.
- *
- * @param cls closure
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- * @param amount amount the exchange will wire back for this coin.
- * @param timestamp what time did the exchange receive the
- * /payback request
- * @param reserve_pub public key of the reserve affected by the
- * payback.
- * @param full_response raw response from the exchange.
- */
-static void
-payback_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute timestamp,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const json_t *full_response)
-{
-
- struct PaybackState *ps = cls;
- struct TALER_TESTING_Interpreter *is = ps->is;
- struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
- const struct TALER_TESTING_Command *reserve_cmd;
- const struct TALER_ReservePrivateKeyP *reserve_priv;
- struct TALER_ReservePublicKeyP rp;
- struct TALER_Amount expected_amount;
-
- ps->ph = NULL;
- if (ps->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s in %s:%u\n",
- http_status,
- cmd->label,
- __FILE__,
- __LINE__);
- json_dumpf (full_response, stderr, 0);
- fprintf (stderr, "\n");
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- reserve_cmd = TALER_TESTING_interpreter_lookup_command
- (is, ps->coin_reference);
-
- if (NULL == reserve_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_reserve_priv
- (reserve_cmd, 0, &reserve_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
- &rp.eddsa_pub);
-
- switch (http_status)
- {
- case MHD_HTTP_OK:
- if (GNUNET_OK != TALER_string_to_amount
- (ps->amount, &expected_amount))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- if (0 != TALER_amount_cmp (amount, &expected_amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Total amount missmatch to command %s\n",
- cmd->label);
- json_dumpf (full_response, stderr, 0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- if (0 != memcmp (reserve_pub, &rp,
- sizeof (struct TALER_ReservePublicKeyP)))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Unmanaged HTTP status code.\n");
- break;
- }
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-payback_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct PaybackState *ps = cls;
- const struct TALER_TESTING_Command *coin_cmd;
- const struct TALER_CoinSpendPrivateKeyP *coin_priv;
- const struct TALER_DenominationBlindingKeyP *blinding_key;
- const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
- const struct TALER_DenominationSignature *coin_sig;
- struct TALER_PlanchetSecretsP planchet;
-
- ps->is = is;
- coin_cmd = TALER_TESTING_interpreter_lookup_command
- (is, ps->coin_reference);
-
- if (NULL == coin_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
- (coin_cmd, 0, &coin_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_blinding_key
- (coin_cmd, 0, &blinding_key))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- planchet.coin_priv = *coin_priv;
- planchet.blinding_key = *blinding_key;
-
- if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub
- (coin_cmd, 0, &denom_pub))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_denom_sig
- (coin_cmd, 0, &coin_sig))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Trying to get '%s..' paid back\n",
- TALER_B2S (&denom_pub->h_key));
-
- ps->ph = TALER_EXCHANGE_payback (is->exchange,
- denom_pub,
- coin_sig,
- &planchet,
- payback_cb,
- ps);
- GNUNET_assert (NULL != ps->ph);
-}
-
-
-/**
- * Cleanup the state.
- *
- * @param cls closure, typically a #struct WireState.
- * @param cmd the command which is being cleaned up.
- */
-static void
-revoke_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
-
- struct RevokeState *rs = cls;
-
- if (NULL != rs->revoke_proc)
- {
- GNUNET_break (0 == GNUNET_OS_process_kill
- (rs->revoke_proc, SIGKILL));
- GNUNET_OS_process_wait (rs->revoke_proc);
- GNUNET_OS_process_destroy (rs->revoke_proc);
- rs->revoke_proc = NULL;
- }
-
- GNUNET_free_non_null (rs->dhks);
- GNUNET_free (rs);
-}
-
-
-/**
- * Cleanup the "payback" CMD state, and possibly cancel
- * a pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-payback_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct PaybackState *ps = cls;
- if (NULL != ps->ph)
- {
- TALER_EXCHANGE_payback_cancel (ps->ph);
- ps->ph = NULL;
- }
- GNUNET_free (ps);
-}
-
-
-/**
- * Offer internal data from a "revoke" CMD to other CMDs.
- *
- * @param cls closure
- * @param ret[out] result (could be anything)
- * @param trait name of the trait
- * @param index index number of the object to offer.
- * @return #GNUNET_OK on success
- */
-static int
-revoke_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
-
- struct RevokeState *rs = cls;
- struct TALER_TESTING_Trait traits[] = {
- /* Needed by the handler which waits the proc'
- * death and calls the next command */
- TALER_TESTING_make_trait_process (0, &rs->revoke_proc),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-/**
- * Run the "revoke" command. The core of the function
- * is to call the "keyup" utility passing it the base32
- * encoding of the denomination to revoke.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-revoke_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct RevokeState *rs = cls;
- const struct TALER_TESTING_Command *coin_cmd;
- const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
-
- rs->is = is;
- /* Get denom pub from trait */
- coin_cmd = TALER_TESTING_interpreter_lookup_command
- (is, rs->coin_reference);
-
- if (NULL == coin_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_denom_pub
- (coin_cmd, 0, &denom_pub));
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Trying to revoke denom '%s..'\n",
- TALER_B2S (&denom_pub->h_key));
-
- rs->dhks = GNUNET_STRINGS_data_to_string_alloc
- (&denom_pub->h_key, sizeof (struct GNUNET_HashCode));
-
- rs->revoke_proc = GNUNET_OS_start_process
- (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-exchange-keyup",
- "taler-exchange-keyup",
- "-c", rs->config_filename,
- "-r", rs->dhks,
- NULL);
-
- if (NULL == rs->revoke_proc)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Revoke is ongoing..\n");
-
- is->reload_keys = GNUNET_OK;
- TALER_TESTING_wait_for_sigchld (is);
-}
-
-
-/**
- * Make a "payback" command.
- *
- * @param label the command label
- * @param expected_response_code expected HTTP status code
- * @param coin_reference reference to any command which
- * offers a coin & reserve private key.
- * @param amount denomination to pay back.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_payback (const char *label,
- unsigned int expected_response_code,
- const char *coin_reference,
- const char *amount)
-{
- struct PaybackState *ps;
-
- ps = GNUNET_new (struct PaybackState);
- ps->expected_response_code = expected_response_code;
- ps->coin_reference = coin_reference;
- ps->amount = amount;
-
- struct TALER_TESTING_Command cmd = {
- .cls = ps,
- .label = label,
- .run = &payback_run,
- .cleanup = &payback_cleanup
- };
-
- return cmd;
-}
-
-
-/**
- * Make a "revoke" command.
- *
- * @param label the command label.
- * @param expected_response_code expected HTTP status code.
- * @param coin_reference reference to a CMD that will offer the
- * denomination to revoke.
- * @param config_filename configuration file name.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_revoke (const char *label,
- unsigned int expected_response_code,
- const char *coin_reference,
- const char *config_filename)
-{
-
- struct RevokeState *rs;
-
- rs = GNUNET_new (struct RevokeState);
- rs->expected_response_code = expected_response_code;
- rs->coin_reference = coin_reference;
- rs->config_filename = config_filename;
-
- struct TALER_TESTING_Command cmd = {
- .cls = rs,
- .label = label,
- .run = &revoke_run,
- .cleanup = &revoke_cleanup,
- .traits = &revoke_traits
- };
-
- return cmd;
-}
diff --git a/src/exchange-lib/testing_api_cmd_refresh.c b/src/exchange-lib/testing_api_cmd_refresh.c
deleted file mode 100644
index 55900cf27..000000000
--- a/src/exchange-lib/testing_api_cmd_refresh.c
+++ /dev/null
@@ -1,1317 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_refresh.c
- * @brief commands for testing all "refresh" features.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-#include "taler_signatures.h"
-#include "backoff.h"
-
-/**
- * Data for a coin to be melted.
- */
-struct MeltDetails
-{
-
- /**
- * Amount to melt (including fee).
- */
- const char *amount;
-
- /**
- * Reference to reserve_withdraw operations for coin to
- * be used for the /refresh/melt operation.
- */
- const char *coin_reference;
-};
-
-
-/**
- * State for a "refresh melt" command.
- */
-struct RefreshMeltState
-{
-
- /**
- * Information about coins to be melted.
- */
- struct MeltDetails melted_coin;
-
- /**
- * "Crypto data" used in the refresh operation.
- */
- char *refresh_data;
-
- /**
- * Reference to a previous melt command.
- */
- const char *melt_reference;
-
- /**
- * Melt handle while operation is running.
- */
- struct TALER_EXCHANGE_RefreshMeltHandle *rmh;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Array of the denomination public keys
- * corresponding to the @e fresh_amounts.
- */
- struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
-
- /**
- * Task scheduled to try later.
- */
- struct GNUNET_SCHEDULER_Task *retry_task;
-
- /**
- * How long do we wait until we retry?
- */
- struct GNUNET_TIME_Relative backoff;
-
- /**
- * Number of bytes in @e refresh_data.
- */
- size_t refresh_data_length;
-
- /**
- * Expected HTTP response code.
- */
- unsigned int expected_response_code;
-
- /**
- * if set to #GNUNET_YES, then two /refresh/melt operations
- * will be performed. This is needed to trigger the logic
- * that manages those already-made requests. Note: it
- * is not possible to just copy-and-paste a test refresh melt
- * CMD to have the same effect, because every data preparation
- * generates new planchets that (in turn) make the whole "hash"
- * different from any previous one, therefore NOT allowing the
- * exchange to pick any previous /rerfesh/melt operation from
- * the database.
- */
- unsigned int double_melt;
-
- /**
- * Should we retry on (transient) failures?
- */
- int do_retry;
-
- /**
- * Set by the melt callback as it comes from the exchange.
- */
- uint16_t noreveal_index;
-};
-
-
-/**
- * State for a "refresh reveal" CMD.
- */
-struct RefreshRevealState
-{
- /**
- * Link to a "refresh melt" command.
- */
- const char *melt_reference;
-
- /**
- * Reveal handle while operation is running.
- */
- struct TALER_EXCHANGE_RefreshRevealHandle *rrh;
-
- /**
- * Convenience struct to keep in one place all the
- * data related to one fresh coin, set by the reveal callback
- * as it comes from the exchange.
- */
- struct FreshCoin *fresh_coins;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Task scheduled to try later.
- */
- struct GNUNET_SCHEDULER_Task *retry_task;
-
- /**
- * How long do we wait until we retry?
- */
- struct GNUNET_TIME_Relative backoff;
-
- /**
- * Number of fresh coins withdrawn, set by the
- * reveal callback as it comes from the exchange,
- * it is the length of the @e fresh_coins array.
- */
- unsigned int num_fresh_coins;
-
- /**
- * Expected HTTP response code.
- */
- unsigned int expected_response_code;
-
- /**
- * Should we retry on (transient) failures?
- */
- int do_retry;
-
-};
-
-
-/**
- * State for a "refresh link" CMD.
- */
-struct RefreshLinkState
-{
- /**
- * Link to a "refresh reveal" command.
- */
- const char *reveal_reference;
-
- /**
- * Handle to the ongoing operation.
- */
- struct TALER_EXCHANGE_RefreshLinkHandle *rlh;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Task scheduled to try later.
- */
- struct GNUNET_SCHEDULER_Task *retry_task;
-
- /**
- * How long do we wait until we retry?
- */
- struct GNUNET_TIME_Relative backoff;
-
- /**
- * Expected HTTP response code.
- */
- unsigned int expected_response_code;
-
- /**
- * Should we retry on (transient) failures?
- */
- int do_retry;
-
-};
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-refresh_reveal_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is);
-
-
-/**
- * Task scheduled to re-try #refresh_reveal_run.
- *
- * @param cls a `struct RefreshRevealState`
- */
-static void
-do_reveal_retry (void *cls)
-{
- struct RefreshRevealState *rrs = cls;
-
- rrs->retry_task = NULL;
- refresh_reveal_run (rrs,
- NULL,
- rrs->is);
-}
-
-
-/**
- * "refresh reveal" request callback; it checks that the response
- * code is expected and copies into its command's state the data
- * coming from the exchange, namely the fresh coins.
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- * @param num_coins number of fresh coins created, length of the
- * @a sigs and @a coin_privs arrays, 0 if the operation
- * failed.
- * @param coin_privs array of @a num_coins private keys for the
- * coins that were created, NULL on error.
- * @param sigs array of signature over @a num_coins coins,
- * NULL on error.
- * @param full_response raw exchange response.
- */
-static void
-reveal_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- unsigned int num_coins,
- const struct TALER_CoinSpendPrivateKeyP *coin_privs,
- const struct TALER_DenominationSignature *sigs,
- const json_t *full_response)
-{
- struct RefreshRevealState *rrs = cls;
- const struct TALER_TESTING_Command *melt_cmd;
-
- rrs->rrh = NULL;
- if (rrs->expected_response_code != http_status)
- {
- if (GNUNET_YES == rrs->do_retry)
- {
- if ( (0 == http_status) ||
- (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
- (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Retrying refresh reveal failed with %u/%d\n",
- http_status,
- (int) ec);
- /* on DB conflicts, do not use backoff */
- if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
- rrs->backoff = GNUNET_TIME_UNIT_ZERO;
- else
- rrs->backoff = EXCHANGE_LIB_BACKOFF (rrs->backoff);
- rrs->retry_task = GNUNET_SCHEDULER_add_delayed (rrs->backoff,
- &do_reveal_retry,
- rrs);
- return;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d to command %s in %s:%u\n",
- http_status,
- (int) ec,
- rrs->is->commands[rrs->is->ip].label,
- __FILE__,
- __LINE__);
- json_dumpf (full_response, stderr, 0);
- TALER_TESTING_interpreter_fail (rrs->is);
- return;
- }
- melt_cmd = TALER_TESTING_interpreter_lookup_command
- (rrs->is, rrs->melt_reference);
- if (NULL == melt_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rrs->is);
- return;
- }
- rrs->num_fresh_coins = num_coins;
- switch (http_status)
- {
- case MHD_HTTP_OK:
- rrs->fresh_coins = GNUNET_new_array
- (num_coins, struct FreshCoin);
-
- const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks;
-
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_denom_pub (melt_cmd,
- 0,
- &fresh_pks))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rrs->is);
- return;
- }
-
- for (unsigned int i=0; i<num_coins; i++)
- {
- struct FreshCoin *fc = &rrs->fresh_coins[i];
-
- fc->pk = &fresh_pks[i];
- fc->coin_priv = coin_privs[i];
- fc->sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup
- (sigs[i].rsa_signature);
- }
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Unknown HTTP status %d\n",
- http_status);
- }
- TALER_TESTING_interpreter_next (rrs->is);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-refresh_reveal_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct RefreshRevealState *rrs = cls;
- struct RefreshMeltState *rms;
- const struct TALER_TESTING_Command *melt_cmd;
-
- rrs->is = is;
- melt_cmd = TALER_TESTING_interpreter_lookup_command
- (is, rrs->melt_reference);
-
- if (NULL == melt_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rrs->is);
- return;
- }
- rms = melt_cmd->cls;
- rrs->rrh = TALER_EXCHANGE_refresh_reveal
- (is->exchange,
- rms->refresh_data_length,
- rms->refresh_data,
- rms->noreveal_index,
- &reveal_cb, rrs);
-
- if (NULL == rrs->rrh)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-}
-
-
-/**
- * Free the state from a "refresh reveal" CMD, and possibly
- * cancel a pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-refresh_reveal_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct RefreshRevealState *rrs = cls;
-
- if (NULL != rrs->rrh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- rrs->is->ip,
- cmd->label);
-
- TALER_EXCHANGE_refresh_reveal_cancel (rrs->rrh);
- rrs->rrh = NULL;
- }
- if (NULL != rrs->retry_task)
- {
- GNUNET_SCHEDULER_cancel (rrs->retry_task);
- rrs->retry_task = NULL;
- }
-
- for (unsigned int j=0; j < rrs->num_fresh_coins; j++)
- GNUNET_CRYPTO_rsa_signature_free (rrs->fresh_coins[j].sig.rsa_signature);
-
- GNUNET_free_non_null (rrs->fresh_coins);
- rrs->fresh_coins = NULL;
- rrs->num_fresh_coins = 0;
- GNUNET_free (rrs);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-refresh_link_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is);
-
-
-/**
- * Task scheduled to re-try #refresh_link_run.
- *
- * @param cls a `struct RefreshLinkState`
- */
-static void
-do_link_retry (void *cls)
-{
- struct RefreshLinkState *rls = cls;
-
- rls->retry_task = NULL;
- refresh_link_run (rls,
- NULL,
- rls->is);
-}
-
-
-/**
- * "refresh link" operation callback, checks that HTTP response
- * code is expected _and_ that all the linked coins were actually
- * withdrawn by the "refresh reveal" CMD.
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec taler-specific error code
- * @param num_coins number of fresh coins created, length of the
- * @a sigs and @a coin_privs arrays, 0 if the operation
- * failed.
- * @param coin_privs array of @a num_coins private keys for the
- * coins that were created, NULL on error.
- * @param sigs array of signature over @a num_coins coins, NULL on
- * error.
- * @param pubs array of public keys for the @a sigs,
- * NULL on error.
- * @param full_response raw response from the exchange.
- */
-static void
-link_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- unsigned int num_coins,
- const struct TALER_CoinSpendPrivateKeyP *coin_privs,
- const struct TALER_DenominationSignature *sigs,
- const struct TALER_DenominationPublicKey *pubs,
- const json_t *full_response)
-{
-
- struct RefreshLinkState *rls = cls;
- const struct TALER_TESTING_Command *reveal_cmd;
- struct TALER_TESTING_Command *link_cmd
- = &rls->is->commands[rls->is->ip];
- unsigned int found;
- const unsigned int *num_fresh_coins;
-
- rls->rlh = NULL;
- if (rls->expected_response_code != http_status)
- {
- if (GNUNET_YES == rls->do_retry)
- {
- if ( (0 == http_status) ||
- (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
- (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Retrying refresh link failed with %u/%d\n",
- http_status,
- (int) ec);
- /* on DB conflicts, do not use backoff */
- if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
- rls->backoff = GNUNET_TIME_UNIT_ZERO;
- else
- rls->backoff = EXCHANGE_LIB_BACKOFF (rls->backoff);
- rls->retry_task = GNUNET_SCHEDULER_add_delayed (rls->backoff,
- &do_link_retry,
- rls);
- return;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d to command %s in %s:%u\n",
- http_status,
- (int) ec,
- link_cmd->label,
- __FILE__,
- __LINE__);
- json_dumpf (full_response, stderr, 0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
- reveal_cmd = TALER_TESTING_interpreter_lookup_command
- (rls->is, rls->reveal_reference);
-
- if (NULL == reveal_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
-
- switch (http_status)
- {
- case MHD_HTTP_OK:
- /* check that number of coins returned matches */
- if (GNUNET_OK != TALER_TESTING_get_trait_uint
- (reveal_cmd, 0, &num_fresh_coins))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
- if (num_coins != *num_fresh_coins)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected number of fresh coins: %d vs %d in %s:%u\n",
- num_coins,
- *num_fresh_coins,
- __FILE__,
- __LINE__);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
- /* check that the coins match */
- for (unsigned int i=0;i<num_coins;i++)
- for (unsigned int j=i+1;j<num_coins;j++)
- if (0 == memcmp
- (&coin_privs[i], &coin_privs[j],
- sizeof (struct TALER_CoinSpendPrivateKeyP)))
- GNUNET_break (0);
- /* Note: coins might be legitimately permutated in here... */
- found = 0;
-
- /* Will point to the pointer inside the cmd state. */
- const struct FreshCoin *fc = NULL;
-
- if (GNUNET_OK != TALER_TESTING_get_trait_fresh_coins
- (reveal_cmd, 0, &fc))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
-
- for (unsigned int i=0;i<num_coins;i++)
- for (unsigned int j=0;j<num_coins;j++)
- {
- if ( (0 == memcmp
- (&coin_privs[i], &fc[j].coin_priv,
- sizeof (struct TALER_CoinSpendPrivateKeyP))) &&
- (0 == GNUNET_CRYPTO_rsa_signature_cmp
- (fc[i].sig.rsa_signature,
- sigs[j].rsa_signature)) &&
- (0 == GNUNET_CRYPTO_rsa_public_key_cmp
- (fc[i].pk->key.rsa_public_key,
- pubs[j].rsa_public_key)) )
- {
- found++;
- break;
- }
- }
- if (found != num_coins)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Only %u/%u coins match expectations\n",
- found, num_coins);
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown HTTP response code %u.\n",
- http_status);
- }
- TALER_TESTING_interpreter_next (rls->is);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-refresh_link_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct RefreshLinkState *rls = cls;
- struct RefreshRevealState *rrs;
- struct RefreshMeltState *rms;
- const struct TALER_TESTING_Command *reveal_cmd;
- const struct TALER_TESTING_Command *melt_cmd;
- const struct TALER_TESTING_Command *coin_cmd;
- rls->is = is;
-
- reveal_cmd = TALER_TESTING_interpreter_lookup_command
- (rls->is, rls->reveal_reference);
-
- if (NULL == reveal_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
- rrs = reveal_cmd->cls;
- melt_cmd = TALER_TESTING_interpreter_lookup_command
- (rls->is, rrs->melt_reference);
-
- if (NULL == melt_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
-
- /* find reserve_withdraw command */
- {
- const struct MeltDetails *md;
-
- rms = melt_cmd->cls;
- md = &rms->melted_coin;
- coin_cmd = TALER_TESTING_interpreter_lookup_command
- (rls->is, md->coin_reference);
- if (NULL == coin_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
- }
-
- const struct TALER_CoinSpendPrivateKeyP *coin_priv;
- if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
- (coin_cmd, 0, &coin_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
-
- /* finally, use private key from withdraw sign command */
- rls->rlh = TALER_EXCHANGE_refresh_link
- (is->exchange, coin_priv, &link_cb, rls);
-
- if (NULL == rls->rlh)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rls->is);
- return;
- }
-}
-
-
-/**
- * Free the state of the "refresh link" CMD, and possibly
- * cancel a operation thereof.
- *
- * @param cls closure
- * @param cmd the command which is being cleaned up.
- */
-static void
-refresh_link_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct RefreshLinkState *rls = cls;
-
- if (NULL != rls->rlh)
- {
-
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- rls->is->ip,
- cmd->label);
- TALER_EXCHANGE_refresh_link_cancel (rls->rlh);
- rls->rlh = NULL;
- }
- if (NULL != rls->retry_task)
- {
- GNUNET_SCHEDULER_cancel (rls->retry_task);
- rls->retry_task = NULL;
- }
- GNUNET_free (rls);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-refresh_melt_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is);
-
-
-/**
- * Task scheduled to re-try #refresh_melt_run.
- *
- * @param cls a `struct RefreshMeltState`
- */
-static void
-do_melt_retry (void *cls)
-{
- struct RefreshMeltState *rms = cls;
-
- rms->retry_task = NULL;
- refresh_melt_run (rms,
- NULL,
- rms->is);
-}
-
-
-/**
- * Callback for a "refresh melt" operation; checks if the HTTP
- * response code is okay and re-run the melt operation if the
- * CMD was set to do so.
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- * @param noreveal_index choice by the exchange in the
- * cut-and-choose protocol, UINT16_MAX on error.
- * @param exchange_pub public key the exchange used for signing.
- * @param full_response raw response body from the exchange.
- */
-static void
-melt_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- uint32_t noreveal_index,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- const json_t *full_response)
-{
- struct RefreshMeltState *rms = cls;
-
- rms->rmh = NULL;
- if (rms->expected_response_code != http_status)
- {
- if (GNUNET_YES == rms->do_retry)
- {
- if ( (0 == http_status) ||
- (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
- (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Retrying refresh melt failed with %u/%d\n",
- http_status,
- (int) ec);
- /* on DB conflicts, do not use backoff */
- if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
- rms->backoff = GNUNET_TIME_UNIT_ZERO;
- else
- rms->backoff = EXCHANGE_LIB_BACKOFF (rms->backoff);
- rms->retry_task = GNUNET_SCHEDULER_add_delayed (rms->backoff,
- &do_melt_retry,
- rms);
- return;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d to command %s in %s:%u\n",
- http_status,
- (int) ec,
- rms->is->commands[rms->is->ip].label,
- __FILE__,
- __LINE__);
- json_dumpf (full_response, stderr, 0);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
- rms->noreveal_index = noreveal_index;
-
- if (GNUNET_YES == rms->double_melt)
- {
- TALER_LOG_DEBUG ("Doubling the melt (%s)\n",
- rms->is->commands[rms->is->ip].label);
- rms->rmh = TALER_EXCHANGE_refresh_melt
- (rms->is->exchange, rms->refresh_data_length,
- rms->refresh_data, &melt_cb, rms);
- rms->double_melt = GNUNET_NO;
- return;
- }
- TALER_TESTING_interpreter_next (rms->is);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-refresh_melt_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct RefreshMeltState *rms = cls;
- unsigned int num_fresh_coins;
- const struct TALER_TESTING_Command *coin_command;
- /* FIXME: this should be dynamic */
- const char *melt_fresh_amounts[] = {
- "EUR:1", "EUR:1", "EUR:1", "EUR:0.1",
- NULL};
- const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk;
-
- rms->is = is;
- rms->noreveal_index = UINT16_MAX;
- for (num_fresh_coins=0;
- NULL != melt_fresh_amounts[num_fresh_coins];
- num_fresh_coins++) ;
-
- rms->fresh_pks = GNUNET_new_array
- (num_fresh_coins,
- struct TALER_EXCHANGE_DenomPublicKey);
- {
- const struct TALER_CoinSpendPrivateKeyP *melt_priv;
- struct TALER_Amount melt_amount;
- struct TALER_Amount fresh_amount;
- const struct TALER_DenominationSignature *melt_sig;
- const struct TALER_EXCHANGE_DenomPublicKey *melt_denom_pub;
-
- const struct MeltDetails *md = &rms->melted_coin;
- if (NULL == (coin_command
- = TALER_TESTING_interpreter_lookup_command
- (is, md->coin_reference)))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
- (coin_command, 0, &melt_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
-
- if (GNUNET_OK !=
- TALER_string_to_amount (md->amount,
- &melt_amount))
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u\n",
- md->amount,
- is->ip);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_denom_sig (coin_command,
- 0,
- &melt_sig))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
- if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub
- (coin_command, 0, &melt_denom_pub))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
-
- for (unsigned int i=0;i<num_fresh_coins;i++)
- {
- if (GNUNET_OK != TALER_string_to_amount
- (melt_fresh_amounts[i], &fresh_amount))
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at index %u\n",
- melt_fresh_amounts[i], i);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
- fresh_pk = TALER_TESTING_find_pk
- (TALER_EXCHANGE_get_keys (is->exchange), &fresh_amount);
- if (NULL == fresh_pk)
- {
- GNUNET_break (0);
- /* Subroutine logs specific error */
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
-
- rms->fresh_pks[i] = *fresh_pk;
- }
- rms->refresh_data = TALER_EXCHANGE_refresh_prepare
- (melt_priv, &melt_amount, melt_sig, melt_denom_pub,
- GNUNET_YES, num_fresh_coins, rms->fresh_pks,
- &rms->refresh_data_length);
-
- if (NULL == rms->refresh_data)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
- rms->rmh = TALER_EXCHANGE_refresh_melt
- (is->exchange, rms->refresh_data_length,
- rms->refresh_data, &melt_cb, rms);
-
- if (NULL == rms->rmh)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (rms->is);
- return;
- }
- }
-}
-
-
-/**
- * Free the "refresh melt" CMD state, and possibly cancel a
- * pending operation thereof.
- *
- * @param cls closure, typically a #struct RefreshMeltState.
- * @param cmd the command which is being cleaned up.
- */
-static void
-refresh_melt_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct RefreshMeltState *rms = cls;
-
- if (NULL != rms->rmh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- rms->is->ip, rms->is->commands[rms->is->ip].label);
- TALER_EXCHANGE_refresh_melt_cancel (rms->rmh);
- rms->rmh = NULL;
- }
- if (NULL != rms->retry_task)
- {
- GNUNET_SCHEDULER_cancel (rms->retry_task);
- rms->retry_task = NULL;
- }
- GNUNET_free_non_null (rms->fresh_pks);
- rms->fresh_pks = NULL;
- GNUNET_free_non_null (rms->refresh_data);
- rms->refresh_data = NULL;
- rms->refresh_data_length = 0;
- GNUNET_free (rms);
-}
-
-
-/**
- * Offer internal data to the "refresh melt" CMD.
- *
- * @param cls closure.
- * @param ret[out] result (could be anything).
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- *
- * @return #GNUNET_OK on success.
- */
-static int
-refresh_melt_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct RefreshMeltState *rms = cls;
-
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_denom_pub (0, rms->fresh_pks),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Create a "refresh melt" command.
- *
- * @param label command label.
- * @param amount amount to be melted.
- * @param coin_reference reference to a command
- * that will provide a coin to refresh.
- * @param expected_response_code expected HTTP code.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_refresh_melt
- (const char *label,
- const char *amount,
- const char *coin_reference,
- unsigned int expected_response_code)
-{
- struct RefreshMeltState *rms;
- struct MeltDetails md;
-
- md.coin_reference = coin_reference;
- md.amount = amount;
-
- rms = GNUNET_new (struct RefreshMeltState);
- rms->melted_coin = md;
- rms->expected_response_code = expected_response_code;
-
- struct TALER_TESTING_Command cmd = {
- .label = label,
- .cls = rms,
- .run = &refresh_melt_run,
- .cleanup = &refresh_melt_cleanup,
- .traits = &refresh_melt_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Create a "refresh melt" CMD that does TWO /refresh/melt
- * requests. This was needed to test the replay of a valid melt
- * request, see #5312.
- *
- * @param label command label
- * @param exchange connection to the exchange
- * @param amount amount to be melted.
- * @param coin_reference reference to a command that will provide
- * a coin to refresh
- * @param expected_response_code expected HTTP code
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_refresh_melt_double
- (const char *label,
- const char *amount,
- const char *coin_reference,
- unsigned int expected_response_code)
-{
- struct RefreshMeltState *rms;
- struct MeltDetails md;
-
- md.coin_reference = coin_reference;
- md.amount = amount;
-
- rms = GNUNET_new (struct RefreshMeltState);
- rms->melted_coin = md;
- rms->expected_response_code = expected_response_code;
- rms->double_melt = GNUNET_YES;
-
- struct TALER_TESTING_Command cmd = {
- .label = label,
- .cls = rms,
- .run = &refresh_melt_run,
- .cleanup = &refresh_melt_cleanup,
- .traits = &refresh_melt_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Modify a "refresh melt" command to enable retries.
- *
- * @param cmd command
- * @return modified command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_refresh_melt_with_retry (struct TALER_TESTING_Command cmd)
-{
- struct RefreshMeltState *rms;
-
- GNUNET_assert (&refresh_melt_run == cmd.run);
- rms = cmd.cls;
- rms->do_retry = GNUNET_YES;
- return cmd;
-}
-
-
-/**
- * Offer internal data from a "refresh reveal" CMD.
- *
- * @param cls closure.
- * @param ret[out] result (could be anything).
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- *
- * @return #GNUNET_OK on success.
- */
-static int
-refresh_reveal_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct RefreshRevealState *rrs = cls;
- unsigned int num_coins = rrs->num_fresh_coins;
-#define NUM_TRAITS ((num_coins * 3) + 3)
- struct TALER_TESTING_Trait traits[NUM_TRAITS];
-
- /* Making coin privs traits */
- for (unsigned int i=0; i<num_coins; i++)
- traits[i] = TALER_TESTING_make_trait_coin_priv
- (i, &rrs->fresh_coins[i].coin_priv);
-
- /* Making denom pubs traits */
- for (unsigned int i=0; i<num_coins; i++)
- traits[num_coins + i]
- = TALER_TESTING_make_trait_denom_pub
- (i, rrs->fresh_coins[i].pk);
-
- /* Making denom sigs traits */
- for (unsigned int i=0; i<num_coins; i++)
- traits[(num_coins * 2) + i]
- = TALER_TESTING_make_trait_denom_sig
- (i, &rrs->fresh_coins[i].sig);
-
- /* number of fresh coins */
- traits[(num_coins * 3)] = TALER_TESTING_make_trait_uint
- (0, &rrs->num_fresh_coins);
-
- /* whole array of fresh coins */
- traits[(num_coins * 3) + 1]
- = TALER_TESTING_make_trait_fresh_coins (0, rrs->fresh_coins),
-
- /* end of traits */
- traits[(num_coins * 3) + 2] = TALER_TESTING_trait_end ();
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Create a "refresh reveal" command.
- *
- * @param label command label.
- * @param exchange connection to the exchange.
- * @param melt_reference reference to a "refresh melt" command.
- * @param expected_response_code expected HTTP response code.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_refresh_reveal
- (const char *label,
- const char *melt_reference,
- unsigned int expected_response_code)
-{
- struct RefreshRevealState *rrs;
-
- rrs = GNUNET_new (struct RefreshRevealState);
- rrs->melt_reference = melt_reference;
- rrs->expected_response_code = expected_response_code;
-
- struct TALER_TESTING_Command cmd = {
- .cls = rrs,
- .label = label,
- .run = &refresh_reveal_run,
- .cleanup = &refresh_reveal_cleanup,
- .traits = &refresh_reveal_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Modify a "refresh reveal" command to enable retries.
- *
- * @param cmd command
- * @return modified command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_refresh_reveal_with_retry (struct TALER_TESTING_Command cmd)
-{
- struct RefreshRevealState *rrs;
-
- GNUNET_assert (&refresh_reveal_run == cmd.run);
- rrs = cmd.cls;
- rrs->do_retry = GNUNET_YES;
- return cmd;
-}
-
-
-/**
- * Create a "refresh link" command.
- *
- * @param label command label.
- * @param reveal_reference reference to a "refresh reveal" CMD.
- * @param expected_response_code expected HTTP response code
- *
- * @return the "refresh link" command
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_refresh_link
- (const char *label,
- const char *reveal_reference,
- unsigned int expected_response_code)
-{
- struct RefreshLinkState *rrs;
-
- rrs = GNUNET_new (struct RefreshLinkState);
- rrs->reveal_reference = reveal_reference;
- rrs->expected_response_code = expected_response_code;
-
- struct TALER_TESTING_Command cmd = {
- .cls = rrs,
- .label = label,
- .run = &refresh_link_run,
- .cleanup = &refresh_link_cleanup
- };
-
- return cmd;
-}
-
-
-/**
- * Modify a "refresh link" command to enable retries.
- *
- * @param cmd command
- * @return modified command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_refresh_link_with_retry (struct TALER_TESTING_Command cmd)
-{
- struct RefreshLinkState *rls;
-
- GNUNET_assert (&refresh_link_run == cmd.run);
- rls = cmd.cls;
- rls->do_retry = GNUNET_YES;
- return cmd;
-}
diff --git a/src/exchange-lib/testing_api_cmd_refund.c b/src/exchange-lib/testing_api_cmd_refund.c
deleted file mode 100644
index f6640d0fc..000000000
--- a/src/exchange-lib/testing_api_cmd_refund.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange/testing_api_cmd_refund.c
- * @brief Implement the /refund test command, plus other
- * corollary commands (?).
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "refund" CMD.
- */
-struct RefundState
-{
- /**
- * Expected HTTP response code.
- */
- unsigned int expected_response_code;
-
- /**
- * Amount to be refunded.
- */
- const char *refund_amount;
-
- /**
- * Expected refund fee.
- */
- const char *refund_fee;
-
- /**
- * Reference to any command that can provide a coin to refund.
- */
- const char *coin_reference;
-
- /**
- * Refund transaction identifier.
- */
- uint64_t refund_transaction_id;
-
- /**
- * Connection to the exchange.
- */
- struct TALER_EXCHANGE_Handle *exchange;
-
- /**
- * Handle to the refund operation.
- */
- struct TALER_EXCHANGE_RefundHandle *rh;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-};
-
-
-/**
- * Check the result for the refund request, just check if the
- * response code is acceptable.
- *
- * @param cls closure
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- * @param exchange_pub public key the exchange
- * used for signing @a obj.
- * @param obj response object.
- */
-static void
-refund_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- const json_t *obj)
-{
-
- struct RefundState *rs = cls;
- struct TALER_TESTING_Command *refund_cmd;
-
- refund_cmd = &rs->is->commands[rs->is->ip];
- rs->rh = NULL;
- if (rs->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s in %s:%u\n",
- http_status,
- refund_cmd->label,
- __FILE__,
- __LINE__);
- json_dumpf (obj, stderr, 0);
- TALER_TESTING_interpreter_fail (rs->is);
- return;
- }
-
- TALER_TESTING_interpreter_next (rs->is);
-}
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-refund_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct RefundState *rs = cls;
- const struct TALER_CoinSpendPrivateKeyP *coin_priv;
- struct TALER_CoinSpendPublicKeyP coin;
- const json_t *contract_terms;
- struct GNUNET_HashCode h_contract_terms;
- struct TALER_Amount refund_fee;
- struct TALER_Amount refund_amount;
- const struct GNUNET_CRYPTO_EddsaPrivateKey *merchant_priv;
- const struct TALER_TESTING_Command *coin_cmd;
-
- rs->exchange = is->exchange;
- rs->is = is;
-
- if (GNUNET_OK !=
- TALER_string_to_amount (rs->refund_amount,
- &refund_amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u/%s\n",
- rs->refund_amount,
- is->ip,
- cmd->label);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- if (GNUNET_OK !=
- TALER_string_to_amount (rs->refund_fee,
- &refund_fee))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u/%s\n",
- rs->refund_fee,
- is->ip,
- cmd->label);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- coin_cmd = TALER_TESTING_interpreter_lookup_command
- (is, rs->coin_reference);
-
- if (NULL == coin_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_contract_terms
- (coin_cmd, 0, &contract_terms))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_assert (GNUNET_OK ==
- TALER_JSON_hash (contract_terms,
- &h_contract_terms));
-
- /* Hunting for a coin .. */
- if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
- (coin_cmd, 0, &coin_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
- &coin.eddsa_pub);
- if (GNUNET_OK != TALER_TESTING_get_trait_peer_key
- (coin_cmd, 0, &merchant_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- rs->rh = TALER_EXCHANGE_refund
- (rs->exchange,
- &refund_amount,
- &refund_fee,
- &h_contract_terms,
- &coin,
- rs->refund_transaction_id,
- (const struct TALER_MerchantPrivateKeyP *) merchant_priv,
- &refund_cb, rs);
-
- GNUNET_assert (NULL != rs->rh);
-}
-
-
-/**
- * Free the state from a "refund" CMD, and possibly cancel
- * a pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-refund_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct RefundState *rs = cls;
-
- if (NULL != rs->rh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- rs->is->ip,
- cmd->label);
- TALER_EXCHANGE_refund_cancel (rs->rh);
- rs->rh = NULL;
- }
- GNUNET_free (rs);
-}
-
-/**
- * Create a "refund" command.
- *
- * @param label command label.
- * @param expected_response_code expected HTTP status code.
- * @param refund_amount the amount to ask a refund for.
- * @param refund_fee expected refund fee.
- * @param coin_reference reference to a command that can
- * provide a coin to be refunded.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_refund (const char *label,
- unsigned int expected_response_code,
- const char *refund_amount,
- const char *refund_fee,
- const char *coin_reference)
-{
- struct RefundState *rs;
-
- rs = GNUNET_new (struct RefundState);
-
- rs->expected_response_code = expected_response_code;
- rs->refund_amount = refund_amount;
- rs->refund_fee = refund_fee;
- rs->coin_reference = coin_reference;
-
- struct TALER_TESTING_Command cmd = {
- .cls = rs,
- .label = label,
- .run = &refund_run,
- .cleanup = &refund_cleanup
- };
-
- return cmd;
-}
-
-/**
- * Create a "refund" command, allow to specify refund transaction
- * id. Mainly used to create conflicting requests.
- *
- * @param label command label.
- * @param expected_response_code expected HTTP status code.
- * @param refund_amount the amount to ask a refund for.
- * @param refund_fee expected refund fee.
- * @param coin_reference reference to a command that can
- * provide a coin to be refunded.
- * @param refund_transaction_id transaction id to use
- * in the request.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_refund_with_id
- (const char *label,
- unsigned int expected_response_code,
- const char *refund_amount,
- const char *refund_fee,
- const char *coin_reference,
- uint64_t refund_transaction_id)
-{
- struct RefundState *rs;
-
- rs = GNUNET_new (struct RefundState);
-
- rs->expected_response_code = expected_response_code;
- rs->refund_amount = refund_amount;
- rs->refund_fee = refund_fee;
- rs->coin_reference = coin_reference;
- rs->refund_transaction_id = refund_transaction_id;
-
- struct TALER_TESTING_Command cmd = {
- .cls = rs,
- .label = label,
- .run = &refund_run,
- .cleanup = &refund_cleanup
- };
-
- return cmd;
-}
diff --git a/src/exchange-lib/testing_api_cmd_serialize_keys.c b/src/exchange-lib/testing_api_cmd_serialize_keys.c
deleted file mode 100644
index 38d32eadd..000000000
--- a/src/exchange-lib/testing_api_cmd_serialize_keys.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- This file is part of TALER
- (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_serialize_keys.c
- * @brief Lets tests use the keys serialization API.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include <jansson.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * Internal state for a serialize-keys CMD.
- */
-struct SerializeKeysState
-{
- /**
- * Serialized keys.
- */
- json_t *keys;
-
- /**
- * Exchange URL. Needed because the exchange gets disconnected
- * from, after keys serialization. This value is then needed by
- * subsequent commands that have to reconnect to the exchagne.
- */
- const char *exchange_url;
-};
-
-
-/**
- * Internal state for a connect-with-state CMD.
- */
-struct ConnectWithStateState
-{
-
- /**
- * Reference to a CMD that offers a serialized key-state
- * that will be used in the reconnection.
- */
- const char *state_reference;
-
- /**
- * If set to GNUNET_YES, then the /keys callback has already
- * been passed the control to the next CMD. This is necessary
- * because it is not uncommon that the /keys callback gets
- * invoked multiple times, and without this flag, we would keep
- * going "next" CMD upon every invocation (causing impredictable
- * behaviour as for the instruction pointer.)
- */
- unsigned int consumed;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-};
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-serialize_keys_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct SerializeKeysState *sks = cls;
-
- sks->keys = TALER_EXCHANGE_serialize_data (is->exchange);
- if (NULL == sks->keys)
- TALER_TESTING_interpreter_fail (is);
-
- sks->exchange_url = GNUNET_strdup
- (TALER_EXCHANGE_get_base_url (is->exchange));
- TALER_EXCHANGE_disconnect (is->exchange);
- is->exchange = NULL;
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Cleanup the state of a "serialize keys" CMD.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-void
-serialize_keys_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct SerializeKeysState *sks = cls;
-
- if (NULL != sks->keys)
- {
- json_decref (sks->keys);
- }
-
- GNUNET_free ((char *) sks->exchange_url);
- GNUNET_free (sks);
-}
-
-
-/**
- * Offer serialized keys as trait.
- *
- * @param cls closure.
- * @param ret[out] result.
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- *
- * @return #GNUNET_OK on success.
- */
-static int
-serialize_keys_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct SerializeKeysState *sks = cls;
-
- struct TALER_TESTING_Trait traits[] = {
-
- TALER_TESTING_make_trait_exchange_keys (0, sks->keys),
- TALER_TESTING_make_trait_url (0, sks->exchange_url),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-/**
- * /keys callback. Just checks HTTP status is OK,
- * and step forward to next command.
- *
- * @param cls closure
- * @param keys information about the various keys used
- * by the exchange, NULL if /keys failed
- * @param compat protocol compatibility information*
- */
-static void
-cb (void *cls,
- const struct TALER_EXCHANGE_Keys *keys,
- enum TALER_EXCHANGE_VersionCompatibility compat)
-{
- struct ConnectWithStateState *cwss = cls;
-
- if (GNUNET_YES == cwss->consumed)
- {
- TALER_LOG_DEBUG ("Reconnection /keys 'cb' invoked already,"
- " nothing to do\n");
- return;
- }
-
- cwss->consumed = GNUNET_YES;
- if (NULL == keys)
- TALER_TESTING_interpreter_fail (cwss->is);
-
- TALER_LOG_DEBUG ("reconnect next CMD\n");
- TALER_TESTING_interpreter_next (cwss->is);
-}
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-connect_with_state_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct ConnectWithStateState *cwss = cls;
- const struct TALER_TESTING_Command *state_cmd;
- const json_t *serialized_keys;
- const char *exchange_url;
-
- cwss->is = is;
- state_cmd = TALER_TESTING_interpreter_lookup_command
- (is, cwss->state_reference);
-
- /* Command providing serialized keys not found. */
- if (NULL == state_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_assert
- (GNUNET_OK == TALER_TESTING_get_trait_exchange_keys
- (state_cmd,
- 0,
- &serialized_keys));
-
- TALER_LOG_DEBUG ("Serialized key-state: %s\n",
- json_dumps (serialized_keys,
- JSON_INDENT (1)));
-
- GNUNET_assert
- (GNUNET_OK == TALER_TESTING_get_trait_url
- (state_cmd,
- 0,
- &exchange_url));
-
- is->exchange = TALER_EXCHANGE_connect
- (is->ctx,
- exchange_url,
- cb,
- cwss,
- TALER_EXCHANGE_OPTION_DATA,
- serialized_keys,
- TALER_EXCHANGE_OPTION_END);
-}
-
-
-/**
- * Cleanup the state of a "connect with state" CMD. Just
- * a placeholder to avoid jumping on an invalid address.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-void
-connect_with_state_cleanup
- (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct ConnectWithStateState *cwss = cls;
-
- GNUNET_free (cwss);
-}
-
-/**
- * Make a serialize-keys CMD. It will ask for
- * keys serialization __and__ disconnect from the
- * exchange.
- *
- * @param label CMD label
- * @return the CMD.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_serialize_keys (const char *label)
-{
- struct SerializeKeysState *sks;
-
- sks = GNUNET_new (struct SerializeKeysState);
- struct TALER_TESTING_Command cmd = {
- .cls = sks,
- .label = label,
- .run = serialize_keys_run,
- .cleanup = serialize_keys_cleanup,
- .traits = serialize_keys_traits
- };
-
- return cmd;
-}
-
-/**
- * Make a connect-with-state CMD. This command
- * will use a serialized key state to reconnect
- * to the exchange.
- *
- * @param label command label
- * @param state_reference label of a CMD offering
- * a serialized key state.
- * @return the CMD.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_connect_with_state (const char *label,
- const char *state_reference)
-{
- struct ConnectWithStateState *cwss;
-
- cwss = GNUNET_new (struct ConnectWithStateState);
- cwss->state_reference = state_reference;
- cwss->consumed = GNUNET_NO;
-
- struct TALER_TESTING_Command cmd = {
- .cls = cwss,
- .label = label,
- .run = connect_with_state_run,
- .cleanup = connect_with_state_cleanup
- };
-
- return cmd;
-}
diff --git a/src/exchange-lib/testing_api_cmd_signal.c b/src/exchange-lib/testing_api_cmd_signal.c
deleted file mode 100644
index f4fd8bb76..000000000
--- a/src/exchange-lib/testing_api_cmd_signal.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- This file is part of TALER
- (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/testing_api_cmd_signal.c
- * @brief command(s) to send signals to processes.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "signal" CMD.
- */
-struct SignalState
-{
- /**
- * The process to send the signal to.
- */
- struct GNUNET_OS_Process *process;
-
- /**
- * The signal to send to the process.
- */
- int signal;
-};
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-signal_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct SignalState *ss = cls;
-
- GNUNET_break (0 == GNUNET_OS_process_kill
- (ss->process, ss->signal));
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Signaling '%d'..\n",
- ss->signal);
- sleep (6);
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Cleanup the state from a "signal" CMD.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-signal_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct SignalState *ss = cls;
-
- GNUNET_free (ss);
-}
-
-
-/**
- * Create a "signal" CMD.
- *
- * @param label command label.
- * @param process handle to the process to signal.
- * @param signal signal to send.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_signal (const char *label,
- struct GNUNET_OS_Process *process,
- int signal)
-{
- struct SignalState *ss;
-
- ss = GNUNET_new (struct SignalState);
- ss->process = process;
- ss->signal = signal;
-
-
- struct TALER_TESTING_Command cmd = {
- .cls = ss,
- .label = label,
- .run = &signal_run,
- .cleanup = &signal_cleanup
- };
-
- return cmd;
-}
diff --git a/src/exchange-lib/testing_api_cmd_sleep.c b/src/exchange-lib/testing_api_cmd_sleep.c
deleted file mode 100644
index 165d0aae4..000000000
--- a/src/exchange-lib/testing_api_cmd_sleep.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- This file is part of TALER
- (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/testing_api_cmd_sleep.c
- * @brief command(s) to sleep for a bit
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "sleep" CMD.
- */
-struct SleepState
-{
-
- /**
- * How long should we sleep?
- */
- unsigned int duration;
-};
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-sleep_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct SleepState *ss = cls;
-
- sleep (ss->duration);
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Cleanup the state from a "sleep" CMD.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-sleep_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct SleepState *ss = cls;
-
- GNUNET_free (ss);
-}
-
-
-/**
- * Sleep for @a duration_s seconds.
- *
- * @param label command label.
- * @param duration_s number of seconds to sleep
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_sleep (const char *label,
- unsigned int duration_s)
-{
- struct SleepState *ss;
-
- ss = GNUNET_new (struct SleepState);
- ss->duration = duration_s;
-
-
- struct TALER_TESTING_Command cmd = {
- .cls = ss,
- .label = label,
- .run = &sleep_run,
- .cleanup = &sleep_cleanup
- };
-
- return cmd;
-}
diff --git a/src/exchange-lib/testing_api_cmd_status.c b/src/exchange-lib/testing_api_cmd_status.c
deleted file mode 100644
index 8e9290f6d..000000000
--- a/src/exchange-lib/testing_api_cmd_status.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange/testing_api_cmd_status.c
- * @brief Implement the /reserve/status test command.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "status" CMD.
- */
-struct StatusState
-{
- /**
- * Label to the command which created the reserve to check,
- * needed to resort the reserve key.
- */
- const char *reserve_reference;
-
- /**
- * Handle to the "reserve status" operation.
- */
- struct TALER_EXCHANGE_ReserveStatusHandle *rsh;
-
- /**
- * Expected reserve balance.
- */
- const char *expected_balance;
-
- /**
- * Expected HTTP response code.
- */
- unsigned int expected_response_code;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-};
-
-
-/**
- * Check that the reserve balance and HTTP response code are
- * both acceptable.
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- * @param balance current balance in the reserve, NULL on error.
- * @param history_length number of entries in the transaction
- * history, 0 on error.
- * @param history detailed transaction history, NULL on error.
- */
-static void
-reserve_status_cb
- (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *json,
- const struct TALER_Amount *balance,
- unsigned int history_length,
- const struct TALER_EXCHANGE_ReserveHistory *history)
-{
- struct StatusState *ss = cls;
- struct TALER_Amount eb;
-
- ss->rsh = NULL;
- if (ss->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected HTTP response code: %d in %s:%u\n",
- http_status,
- __FILE__,
- __LINE__);
- TALER_TESTING_interpreter_fail (ss->is);
- return;
- }
-
- GNUNET_assert (GNUNET_OK == TALER_string_to_amount
- (ss->expected_balance, &eb));
-
- if (0 != TALER_amount_cmp (&eb, balance))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected amount in reserve: %s\n",
- TALER_amount_to_string (balance));
- TALER_TESTING_interpreter_fail (ss->is);
- return;
- }
-
-/**
- * Fixme: need a way to check if reserve history is consistent.
- * Every command which relates to reserve 'x' should be added in
- * a linked list of all commands that relate to the same reserve
- * 'x'.
- *
- * API-wise, any command that relates to a reserve should offer a
- * method called e.g. "compare_with_history" that takes an element
- * of the array returned by "/reserve/status" and checks if that
- * element correspond to itself (= the command exposing the check-
- * method).
- *
- * IDEA: Maybe realize this via another trait, some kind of
- * "reserve history update trait" which returns information about
- * how the command changes the history (provided only by commands
- * that change reserve balances)?
- */
-
- TALER_TESTING_interpreter_next (ss->is);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command being executed.
- * @param is the interpreter state.
- */
-static void
-status_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct StatusState *ss = cls;
- const struct TALER_TESTING_Command *create_reserve;
- const struct TALER_ReservePrivateKeyP *reserve_priv;
- struct TALER_ReservePublicKeyP reserve_pub;
-
- ss->is = is;
- GNUNET_assert (NULL != ss->reserve_reference);
-
- create_reserve
- = TALER_TESTING_interpreter_lookup_command
- (is, ss->reserve_reference);
-
- if (NULL == create_reserve)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- /* NOTE: the following line might generate a ERROR log
- * statements, but it can be ignored. */
- if (GNUNET_OK == TALER_TESTING_get_trait_reserve_priv
- (create_reserve,
- 0,
- &reserve_priv))
- {
- GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
- &reserve_pub.eddsa_pub);
- }
- else
- {
- const char *transfer_subject;
-
- if (GNUNET_OK != TALER_TESTING_get_trait_transfer_subject
- (create_reserve,
- 0,
- &transfer_subject))
- {
- GNUNET_break (0);
- TALER_LOG_ERROR
- ("The reserve has neither a priv nor a subject line..\n");
- TALER_TESTING_interpreter_fail (is);
- return;
-
- }
-
- GNUNET_STRINGS_string_to_data
- (transfer_subject,
- strlen (transfer_subject),
- &reserve_pub.eddsa_pub,
- sizeof (struct TALER_ReservePublicKeyP));
- }
-
- ss->rsh = TALER_EXCHANGE_reserve_status (is->exchange,
- &reserve_pub,
- &reserve_status_cb,
- ss);
-}
-
-
-/**
- * Cleanup the state from a "reserve status" CMD, and possibly
- * cancel a pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-status_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct StatusState *ss = cls;
-
- if (NULL != ss->rsh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- ss->is->ip,
- cmd->label);
- TALER_EXCHANGE_reserve_status_cancel (ss->rsh);
- ss->rsh = NULL;
- }
- GNUNET_free (ss);
-}
-
-
-/**
- * Create a "reserve status" command.
- *
- * @param label the command label.
- * @param reserve_reference reference to the reserve to check.
- * @param expected_balance expected balance for the reserve.
- * @param expected_response_code expected HTTP response code.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_status (const char *label,
- const char *reserve_reference,
- const char *expected_balance,
- unsigned int expected_response_code)
-{
- struct StatusState *ss;
-
- ss = GNUNET_new (struct StatusState);
- ss->reserve_reference = reserve_reference;
- ss->expected_balance = expected_balance;
- ss->expected_response_code = expected_response_code;
-
- struct TALER_TESTING_Command cmd = {
- .cls = ss,
- .label = label,
- .run = &status_run,
- .cleanup = &status_cleanup
- };
-
- return cmd;
-}
diff --git a/src/exchange-lib/testing_api_cmd_track.c b/src/exchange-lib/testing_api_cmd_track.c
deleted file mode 100644
index 4898a097c..000000000
--- a/src/exchange-lib/testing_api_cmd_track.c
+++ /dev/null
@@ -1,810 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange/testing_api_cmd_track.c
- * @brief Implement the testing CMDs for the /track operations.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_testing_lib.h"
-
-/**
- * State for a "track transaction" CMD.
- */
-struct TrackTransactionState
-{
-
- /**
- * If non NULL, will provide a WTID to be compared against
- * the one returned by the "track transaction" operation.
- */
- const char *bank_transfer_reference;
-
- /**
- * The WTID associated by the transaction being tracked.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * Expected HTTP response code.
- */
- unsigned int expected_response_code;
-
- /**
- * Reference to any operation that can provide a transaction.
- * Will be the transaction to track.
- */
- const char *transaction_reference;
-
- /**
- * Index of the coin involved in the transaction. Recall:
- * at the exchange, the tracking is done _per coin_.
- */
- unsigned int coin_index;
-
- /**
- * Handle to the "track transaction" pending operation.
- */
- struct TALER_EXCHANGE_TrackTransactionHandle *tth;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-};
-
-
-/**
- * State for a "track transfer" CMD.
- */
-struct TrackTransferState
-{
-
- /**
- * Expected amount for the WTID being tracked.
- */
- const char *expected_total_amount;
-
- /**
- * Expected fee for this WTID.
- */
- const char *expected_wire_fee;
-
- /**
- * Expected HTTP response code.
- */
- unsigned int expected_response_code;
-
- /**
- * Reference to any operation that can provide a WTID.
- * Will be the WTID to track.
- */
- const char *wtid_reference;
-
- /**
- * Reference to any operation that can provide wire details.
- * Those wire details will then be matched against the credit
- * bank account of the tracked WTID. This way we can test that
- * a wire transfer paid back one particular bank account.
- */
- const char *wire_details_reference;
-
- /**
- * Reference to any operation that can provide an amount.
- * This way we can check that the transferred amount matches
- * our expectations.
- */
- const char *total_amount_reference;
-
- /**
- * Index to the WTID to pick, in case @a wtid_reference has
- * many on offer.
- */
- unsigned int index;
-
- /**
- * Handle to a pending "track transfer" operation.
- */
- struct TALER_EXCHANGE_TrackTransferHandle *tth;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-};
-
-
-/**
- * Checks what is returned by the "track transaction" operation.
- * Checks that the HTTP response code is acceptable, and - if the
- * right reference is non NULL - that the wire transfer subject
- * line matches our expectations.
- *
- * @param cls closure.
- * @param http_status HTTP status code we got.
- * @param ec taler-specific error code.
- * @param json original json reply (may include signatures, those
- * have then been validated already).
- * @param wtid wire transfer identifier, NULL if exchange did not
- * execute the transaction yet.
- * @param execution_time actual or planned execution time for the
- * wire transfer.
- * @param coin_contribution contribution to the @a total_amount of
- * the deposited coin (can be NULL).
- * @param total_amount total amount of the wire transfer, or NULL
- * if the exchange could not provide any @a wtid (set only
- * if @a http_status is #MHD_HTTP_OK).
- */
-static void
-deposit_wtid_cb
- (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- const json_t *json,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- struct GNUNET_TIME_Absolute execution_time,
- const struct TALER_Amount *coin_contribution)
-{
- struct TrackTransactionState *tts = cls;
- struct TALER_TESTING_Interpreter *is = tts->is;
- struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
-
- tts->tth = NULL;
- if (tts->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s in %s:%u\n",
- http_status,
- cmd->label,
- __FILE__,
- __LINE__);
- json_dumpf (json, stderr, 0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- switch (http_status)
- {
- case MHD_HTTP_OK:
- tts->wtid = *wtid;
- if (NULL != tts->bank_transfer_reference)
- {
- const struct TALER_TESTING_Command *bank_transfer_cmd;
- char *ws;
-
- /* _this_ wire transfer subject line. */
- ws = GNUNET_STRINGS_data_to_string_alloc (wtid,
- sizeof (*wtid));
-
- bank_transfer_cmd = TALER_TESTING_interpreter_lookup_command
- (is, tts->bank_transfer_reference);
-
- if (NULL == bank_transfer_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- /* expected wire transfer subject line. */
- const char *transfer_subject;
-
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_transfer_subject
- (bank_transfer_cmd, 0, &transfer_subject))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- /* Compare that expected and gotten subjects match. */
- if (0 != strcmp (ws, transfer_subject))
- {
- GNUNET_break (0);
- GNUNET_free (ws);
- TALER_TESTING_interpreter_fail (tts->is);
- return;
- }
-
- GNUNET_free (ws);
- }
- break;
- case MHD_HTTP_ACCEPTED:
- /* allowed, nothing to check here */
- break;
- case MHD_HTTP_NOT_FOUND:
- /* allowed, nothing to check here */
- break;
- default:
- GNUNET_break (0);
- break;
- }
- TALER_TESTING_interpreter_next (tts->is);
-}
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-track_transaction_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct TrackTransactionState *tts = cls;
- const struct TALER_TESTING_Command *transaction_cmd;
- const struct TALER_CoinSpendPrivateKeyP *coin_priv;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- const json_t *contract_terms;
- const json_t *wire_details;
- struct GNUNET_HashCode h_wire_details;
- struct GNUNET_HashCode h_contract_terms;
- const struct GNUNET_CRYPTO_EddsaPrivateKey *merchant_priv;
-
- tts->is = is;
- transaction_cmd = TALER_TESTING_interpreter_lookup_command
- (tts->is, tts->transaction_reference);
-
- if (NULL == transaction_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (tts->is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
- (transaction_cmd, tts->coin_index, &coin_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (tts->is);
- return;
- }
-
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
- &coin_pub.eddsa_pub);
-
- /* Get the strings.. */
- if (GNUNET_OK != TALER_TESTING_get_trait_wire_details
- (transaction_cmd, 0, &wire_details))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (tts->is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_contract_terms
- (transaction_cmd, 0, &contract_terms))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (tts->is);
- return;
- }
-
- if ((NULL == wire_details) || (NULL == contract_terms))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (tts->is);
- return;
- }
-
- /* Should not fail here, json has been parsed already */
- GNUNET_assert
- ( (GNUNET_OK ==
- TALER_JSON_merchant_wire_signature_hash (wire_details,
- &h_wire_details)) &&
- (GNUNET_OK ==
- TALER_JSON_hash (contract_terms,
- &h_contract_terms)) );
-
- if (GNUNET_OK != TALER_TESTING_get_trait_peer_key
- (transaction_cmd, 0, &merchant_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (tts->is);
- return;
- }
-
- tts->tth = TALER_EXCHANGE_track_transaction
- (is->exchange,
- (struct TALER_MerchantPrivateKeyP *) merchant_priv,
- &h_wire_details,
- &h_contract_terms,
- &coin_pub,
- &deposit_wtid_cb,
- tts);
-
- GNUNET_assert (NULL != tts->tth);
-}
-
-/**
- * Cleanup the state from a "track transaction" CMD, and possibly
- * cancel a operation thereof.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-void
-track_transaction_cleanup
- (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct TrackTransactionState *tts = cls;
-
- if (NULL != tts->tth)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- tts->is->ip,
- cmd->label);
- TALER_EXCHANGE_track_transaction_cancel (tts->tth);
- tts->tth = NULL;
- }
- GNUNET_free (tts);
-}
-
-
-/**
- * Offer internal data from a "track transaction" CMD.
- *
- * @param cls closure.
- * @param ret[out] result (could be anything).
- * @param trait name of the trait.
- * @param index index number of the object to offer.
- *
- * @return #GNUNET_OK on success.
- */
-static int
-track_transaction_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct TrackTransactionState *tts = cls;
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_wtid (0, &tts->wtid),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Create a "track transaction" command.
- *
- * @param label the command label.
- * @param transaction_reference reference to a deposit operation,
- * will be used to get the input data for the track.
- * @param coin_index index of the coin involved in the transaction.
- * @param expected_response_code expected HTTP response code.
- * @param bank_transfer_reference reference to a command that
- * can offer a WTID so as to check that against what WTID
- * the tracked operation has. Set as NULL if not needed.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_track_transaction
- (const char *label,
- const char *transaction_reference,
- unsigned int coin_index,
- unsigned int expected_response_code,
- const char *bank_transfer_reference)
-{
- struct TrackTransactionState *tts;
-
- tts = GNUNET_new (struct TrackTransactionState);
- tts->transaction_reference = transaction_reference;
- tts->expected_response_code = expected_response_code;
- tts->bank_transfer_reference = bank_transfer_reference;
- tts->coin_index = coin_index;
-
- struct TALER_TESTING_Command cmd = {
- .cls = tts,
- .label = label,
- .run = &track_transaction_run,
- .cleanup = &track_transaction_cleanup,
- .traits = &track_transaction_traits
- };
-
- return cmd;
-}
-
-/**
- * Cleanup the state for a "track transfer" CMD, and possibly
- * cancel a pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-void
-track_transfer_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
-
- struct TrackTransferState *tts = cls;
-
- if (NULL != tts->tth)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- tts->is->ip,
- cmd->label);
- TALER_EXCHANGE_track_transfer_cancel (tts->tth);
- tts->tth = NULL;
- }
- GNUNET_free (tts);
-
-}
-
-/**
- * Check whether the HTTP response code from a "track transfer"
- * operation is acceptable, and all other values like total amount,
- * wire fees and hashed wire details as well.
- *
- * @param cls closure.
- * @param http_status HTTP status code we got.
- * @param ec taler-specific error code.
- * @param exchange_pub public key the exchange used for signing
- * the response.
- * @param json original json reply (may include signatures, those
- * have then been validated already).
- * @param h_wire hash of the wire transfer address the transfer
- * went to, or NULL on error.
- * @param execution_time time when the exchange claims to have
- * performed the wire transfer.
- * @param total_amount total amount of the wire transfer, or NULL
- * if the exchange could not provide any @a wtid (set only
- * if @a http_status is "200 OK").
- * @param wire_fee wire fee that was charged by the exchange.
- * @param details_length length of the @a details array.
- * @param details array with details about the combined
- * transactions.
- */
-static void
-track_transfer_cb
- (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- const json_t *json,
- const struct GNUNET_HashCode *h_wire,
- struct GNUNET_TIME_Absolute execution_time,
- const struct TALER_Amount *total_amount,
- const struct TALER_Amount *wire_fee,
- unsigned int details_length,
- const struct TALER_TrackTransferDetails *details)
-{
- struct TrackTransferState *tts = cls;
- struct TALER_TESTING_Interpreter *is = tts->is;
- struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
-
- struct TALER_Amount expected_amount;
-
- tts->tth = NULL;
-
- if (tts->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s in %s:%u\n",
- http_status,
- cmd->label,
- __FILE__,
- __LINE__);
- json_dumpf (json, stderr, 0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if ( (NULL == tts->expected_total_amount) ||
- (NULL == tts->expected_wire_fee) )
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Expected amount and fee not specified, "
- "likely to segfault...\n");
-
- switch (http_status)
- {
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- TALER_string_to_amount (tts->expected_total_amount,
- &expected_amount))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- if (0 != TALER_amount_cmp (total_amount,
- &expected_amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Total amount missmatch to command %s - "
- "%s vs %s\n",
- cmd->label,
- TALER_amount_to_string (total_amount),
- TALER_amount_to_string (&expected_amount));
- json_dumpf (json, stderr, 0);
- fprintf (stderr, "\n");
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (GNUNET_OK !=
- TALER_string_to_amount (tts->expected_wire_fee,
- &expected_amount))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (0 != TALER_amount_cmp (wire_fee,
- &expected_amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire fee missmatch to command %s\n",
- cmd->label);
- json_dumpf (json, stderr, 0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- /**
- * Optionally checking: (1) wire-details for this transfer
- * match the ones from a referenced "deposit" operation -
- * or any operation that could provide wire-details. (2)
- * Total amount for this transfer matches the one from any
- * referenced command that could provide one.
- */
-
- if (NULL != tts->wire_details_reference)
- {
- const struct TALER_TESTING_Command *wire_details_cmd;
- const json_t *wire_details;
- struct GNUNET_HashCode h_wire_details;
-
- if (NULL == (wire_details_cmd
- = TALER_TESTING_interpreter_lookup_command
- (is, tts->wire_details_reference)))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_wire_details (wire_details_cmd,
- 0,
- &wire_details))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_assert
- (GNUNET_OK ==
- TALER_JSON_merchant_wire_signature_hash (wire_details,
- &h_wire_details));
-
- if (0 != memcmp (&h_wire_details,
- h_wire,
- sizeof (struct GNUNET_HashCode)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire hash missmath to command %s\n",
- cmd->label);
- json_dumpf (json, stderr, 0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- }
- if (NULL != tts->total_amount_reference)
- {
- const struct TALER_TESTING_Command *total_amount_cmd;
- const char *total_amount_from_reference_str;
- struct TALER_Amount total_amount_from_reference;
-
- if (NULL == (total_amount_cmd
- = TALER_TESTING_interpreter_lookup_command
- (is, tts->total_amount_reference)))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_amount
- (total_amount_cmd, 0, &total_amount_from_reference_str))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_assert (GNUNET_OK == TALER_string_to_amount
- (total_amount_from_reference_str,
- &total_amount_from_reference));
-
- if (0 != TALER_amount_cmp (total_amount,
- &total_amount_from_reference))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Amount missmath to command %s\n",
- cmd->label);
- json_dumpf (json, stderr, 0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- }
- }
- TALER_TESTING_interpreter_next (is);
-}
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command under execution.
- * @param is the interpreter state.
- */
-void
-track_transfer_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- /* looking for a wtid to track .. */
- struct TrackTransferState *tts = cls;
- struct TALER_WireTransferIdentifierRawP wtid;
- const struct TALER_WireTransferIdentifierRawP *wtid_ptr;
-
- /* If no reference is given, we'll use a all-zeros
- * WTID */
- memset (&wtid, 0, sizeof (wtid));
- wtid_ptr = &wtid;
-
- tts->is = is;
- if (NULL != tts->wtid_reference)
- {
- const struct TALER_TESTING_Command *wtid_cmd;
-
- wtid_cmd = TALER_TESTING_interpreter_lookup_command
- (tts->is, tts->wtid_reference);
-
- if (NULL == wtid_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (tts->is);
- return;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_wtid
- (wtid_cmd, tts->index, &wtid_ptr))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (tts->is);
- return;
- }
- GNUNET_assert (NULL != wtid_ptr);
- }
- tts->tth = TALER_EXCHANGE_track_transfer (is->exchange,
- wtid_ptr,
- &track_transfer_cb,
- tts);
- GNUNET_assert (NULL != tts->tth);
-}
-
-/**
- * Make a "track transfer" CMD where no "expected"-arguments,
- * except the HTTP response code, are given. The best use case
- * is when what matters to check is the HTTP response code, e.g.
- * when a bogus WTID was passed.
- *
- * @param label the command label
- * @param wtid_reference reference to any command which can provide
- * a wtid. If NULL is given, then a all zeroed WTID is
- * used that will at 99.9999% probability NOT match any
- * existing WTID known to the exchange.
- * @param index index number of the WTID to track, in case there
- * are multiple on offer.
- * @param expected_response_code expected HTTP response code.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_track_transfer_empty
- (const char *label,
- const char *wtid_reference,
- unsigned int index,
- unsigned int expected_response_code)
-{
- struct TrackTransferState *tts;
-
- tts = GNUNET_new (struct TrackTransferState);
-
- tts->wtid_reference = wtid_reference;
- tts->index = index;
- tts->expected_response_code = expected_response_code;
-
- struct TALER_TESTING_Command cmd = {
- .cls = tts,
- .label = label,
- .run = &track_transfer_run,
- .cleanup = &track_transfer_cleanup
- };
-
- return cmd;
-}
-
-/**
- * Make a "track transfer" command, specifying which amount and
- * wire fee are expected.
- *
- * @param label the command label.
- * @param wtid_reference reference to any command which can provide
- * a wtid. Will be the one tracked.
- * @param index in case there are multiple WTID offered, this
- * parameter selects a particular one.
- * @param expected_response_code expected HTTP response code.
- * @param expected_amount how much money we expect being moved
- * with this wire-transfer.
- * @param expected_wire_fee expected wire fee.
- *
- * @return the command
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_track_transfer
- (const char *label,
- const char *wtid_reference,
- unsigned int index,
- unsigned int expected_response_code,
- const char *expected_total_amount,
- const char *expected_wire_fee)
-{
- struct TrackTransferState *tts;
-
- tts = GNUNET_new (struct TrackTransferState);
-
- tts->wtid_reference = wtid_reference;
- tts->index = index;
- tts->expected_response_code = expected_response_code;
- tts->expected_total_amount = expected_total_amount;
- tts->expected_wire_fee = expected_wire_fee;
-
- struct TALER_TESTING_Command cmd = {
- .cls = tts,
- .label = label,
- .run = &track_transfer_run,
- .cleanup = &track_transfer_cleanup
- };
-
- return cmd;
-}
-
-/* end of testing_api_cmd_track.c */
diff --git a/src/exchange-lib/testing_api_cmd_wire.c b/src/exchange-lib/testing_api_cmd_wire.c
deleted file mode 100644
index 113545499..000000000
--- a/src/exchange-lib/testing_api_cmd_wire.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_cmd_wire.c
- * @brief command for testing /wire.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_wire_lib.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * State for a "wire" CMD.
- */
-struct WireState
-{
-
- /**
- * Handle to the /wire operation.
- */
- struct TALER_EXCHANGE_WireHandle *wh;
-
- /**
- * Which wire-method we expect is offered by the exchange.
- */
- const char *expected_method;
-
- /**
- * Flag indicating if the expected method is actually
- * offered.
- */
- unsigned int method_found;
-
- /**
- * Fee we expect is charged for this wire-transfer method.
- */
- const char *expected_fee;
-
- /**
- * Expected HTTP response code.
- */
- unsigned int expected_response_code;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-};
-
-
-/**
- * Check whether the HTTP response code is acceptable, that
- * the expected wire method is offered by the exchange, and
- * that the wire fee is acceptable too.
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- * @param accounts_len length of the @a accounts array.
- * @param accounts list of wire accounts of the exchange,
- * NULL on error.
- */
-static void
-wire_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- unsigned int accounts_len,
- const struct TALER_EXCHANGE_WireAccount *accounts)
-{
- struct WireState *ws = cls;
- struct TALER_TESTING_Command *cmd = \
- &ws->is->commands[ws->is->ip];
- struct TALER_Amount expected_fee;
-
- TALER_LOG_DEBUG ("Checking parsed /wire response\n");
- ws->wh = NULL;
- if (ws->expected_response_code != http_status)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (ws->is);
- return;
- }
-
- if (MHD_HTTP_OK == http_status)
- {
- for (unsigned int i=0;i<accounts_len;i++)
- {
- char *method;
-
- method = TALER_WIRE_payto_get_method (accounts[i].url);
- if (0 == strcmp (ws->expected_method,
- method))
- {
- ws->method_found = GNUNET_OK;
- if (NULL != ws->expected_fee)
- {
- GNUNET_assert
- (GNUNET_OK ==
- TALER_string_to_amount (ws->expected_fee,
- &expected_fee));
- const struct TALER_EXCHANGE_WireAggregateFees *waf;
- for (waf = accounts[i].fees;
- NULL != waf;
- waf = waf->next)
- {
- if (0 != TALER_amount_cmp (&waf->wire_fee,
- &expected_fee))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire fee missmatch to command %s\n",
- cmd->label);
- TALER_TESTING_interpreter_fail (ws->is);
- GNUNET_free (method);
- return;
- }
- }
- }
- }
- TALER_LOG_DEBUG ("Freeing method '%s'\n",
- method);
- GNUNET_free (method);
- }
- if (GNUNET_OK != ws->method_found)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "/wire does not offer method '%s'\n",
- ws->expected_method);
- TALER_TESTING_interpreter_fail (ws->is);
- return;
- }
- }
-
- TALER_TESTING_interpreter_next (ws->is);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command to execute.
- * @param is the interpreter state.
- */
-static void
-wire_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct WireState *ws = cls;
- ws->is = is;
- ws->wh = TALER_EXCHANGE_wire (is->exchange,
- &wire_cb,
- ws);
-}
-
-
-/**
- * Cleanup the state of a "wire" CMD, and possibly cancel a
- * pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command which is being cleaned up.
- */
-static void
-wire_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct WireState *ws = cls;
-
- if (NULL != ws->wh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- ws->is->ip,
- cmd->label);
- TALER_EXCHANGE_wire_cancel (ws->wh);
- ws->wh = NULL;
- }
- GNUNET_free (ws);
-}
-
-/**
- * Create a "wire" command.
- *
- * @param label the command label.
- * @param exchange the exchange to connect to.
- * @param expected_method which wire-transfer method is expected
- * to be offered by the exchange.
- * @param expected_fee the fee the exchange should charge.
- * @param expected_response_code the HTTP response the exchange
- * should return.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_wire (const char *label,
- const char *expected_method,
- const char *expected_fee,
- unsigned int expected_response_code)
-{
- struct WireState *ws;
-
- ws = GNUNET_new (struct WireState);
- ws->expected_method = expected_method;
- ws->expected_fee = expected_fee;
- ws->expected_response_code = expected_response_code;
-
- struct TALER_TESTING_Command cmd = {
- .cls = ws,
- .label = label,
- .run = &wire_run,
- .cleanup = &wire_cleanup
- };
-
- return cmd;
-}
diff --git a/src/exchange-lib/testing_api_cmd_withdraw.c b/src/exchange-lib/testing_api_cmd_withdraw.c
deleted file mode 100644
index 7224f65e4..000000000
--- a/src/exchange-lib/testing_api_cmd_withdraw.c
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/testing_api_cmd_withdraw.c
- * @brief main interpreter loop for testcases
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <microhttpd.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-#include "backoff.h"
-
-
-
-/**
- * State for a "withdraw" CMD.
- */
-struct WithdrawState
-{
-
- /**
- * Which reserve should we withdraw from?
- */
- const char *reserve_reference;
-
- /**
- * String describing the denomination value we should withdraw.
- * A corresponding denomination key must exist in the exchange's
- * offerings. Can be NULL if @e pk is set instead.
- */
- struct TALER_Amount amount;
-
- /**
- * If @e amount is NULL, this specifies the denomination key to
- * use. Otherwise, this will be set (by the interpreter) to the
- * denomination PK matching @e amount.
- */
- const struct TALER_EXCHANGE_DenomPublicKey *pk;
-
- /**
- * Exchange base URL. Only used as offered trait.
- */
- char *exchange_url;
-
- /**
- * Interpreter state (during command).
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Set (by the interpreter) to the exchange's signature over the
- * coin's public key.
- */
- struct TALER_DenominationSignature sig;
-
- /**
- * Private key material of the coin, set by the interpreter.
- */
- struct TALER_PlanchetSecretsP ps;
-
- /**
- * Withdraw handle (while operation is running).
- */
- struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
-
- /**
- * Task scheduled to try later.
- */
- struct GNUNET_SCHEDULER_Task *retry_task;
-
- /**
- * How long do we wait until we retry?
- */
- struct GNUNET_TIME_Relative backoff;
-
- /**
- * Expected HTTP response code to the request.
- */
- unsigned int expected_response_code;
-
- /**
- * Was this command modified via
- * #TALER_TESTING_cmd_withdraw_with_retry to
- * enable retries?
- */
- int do_retry;
-};
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the commaind being run.
- * @param is interpreter state.
- */
-static void
-withdraw_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is);
-
-
-/**
- * Task scheduled to re-try #withdraw_run.
- *
- * @param cls a `struct WithdrawState`
- */
-static void
-do_retry (void *cls)
-{
- struct WithdrawState *ws = cls;
-
- ws->retry_task = NULL;
- withdraw_run (ws,
- NULL,
- ws->is);
-}
-
-
-/**
- * "reserve withdraw" operation callback; checks that the
- * response code is expected and store the exchange signature
- * in the state.
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec taler-specific error code.
- * @param sig signature over the coin, NULL on error.
- * @param full_response raw response.
- */
-static void
-reserve_withdraw_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct TALER_DenominationSignature *sig,
- const json_t *full_response)
-{
- struct WithdrawState *ws = cls;
- struct TALER_TESTING_Interpreter *is = ws->is;
-
- ws->wsh = NULL;
- if (ws->expected_response_code != http_status)
- {
- if (GNUNET_YES == ws->do_retry)
- {
- if ( (0 == http_status) ||
- (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec) ||
- (TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS == ec) ||
- (TALER_EC_WITHDRAW_RESERVE_UNKNOWN == ec) ||
- (MHD_HTTP_INTERNAL_SERVER_ERROR == http_status) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Retrying withdraw failed with %u/%d\n",
- http_status,
- (int) ec);
- /* on DB conflicts, do not use backoff */
- if (TALER_EC_DB_COMMIT_FAILED_ON_RETRY == ec)
- ws->backoff = GNUNET_TIME_UNIT_ZERO;
- else
- ws->backoff = EXCHANGE_LIB_BACKOFF (ws->backoff);
- ws->retry_task = GNUNET_SCHEDULER_add_delayed (ws->backoff,
- &do_retry,
- ws);
- return;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d to command %s in %s:%u\n",
- http_status,
- (int) ec,
- TALER_TESTING_interpreter_get_current_label (is),
- __FILE__,
- __LINE__);
- json_dumpf (full_response,
- stderr,
- 0);
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- switch (http_status)
- {
- case MHD_HTTP_OK:
- if (NULL == sig)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- ws->sig.rsa_signature
- = GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
- break;
- case MHD_HTTP_FORBIDDEN:
- /* nothing to check */
- break;
- case MHD_HTTP_NOT_FOUND:
- /* nothing to check */
- break;
- default:
- /* Unsupported status code (by test harness) */
- GNUNET_break (0);
- break;
- }
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Run the command.
- *
- * @param cls closure.
- * @param cmd the command being run, NULL when called from #do_retry()
- * @param is interpreter state.
- */
-static void
-withdraw_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
- struct WithdrawState *ws = cls;
- const struct TALER_ReservePrivateKeyP *rp;
- const struct TALER_TESTING_Command *create_reserve;
-
- (void) cmd;
- create_reserve = TALER_TESTING_interpreter_lookup_command
- (is, ws->reserve_reference);
- if (NULL == create_reserve)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_reserve_priv (create_reserve,
- 0,
- &rp))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
- TALER_planchet_setup_random (&ws->ps);
- ws->is = is;
-
- ws->pk = TALER_TESTING_find_pk
- (TALER_EXCHANGE_get_keys (is->exchange),
- &ws->amount);
- if (NULL == ws->pk)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to determine denomination key at %s\n",
- cmd->label);
- GNUNET_assert (0);
- }
-
- ws->wsh = TALER_EXCHANGE_reserve_withdraw (is->exchange,
- ws->pk,
- rp,
- &ws->ps,
- &reserve_withdraw_cb,
- ws);
- if (NULL == ws->wsh)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-}
-
-
-/**
- * Free the state of a "withdraw" CMD, and possibly cancel
- * a pending operation thereof.
- *
- * @param cls closure.
- * @param cmd the command being freed.
- */
-static void
-withdraw_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct WithdrawState *ws = cls;
-
- if (NULL != ws->wsh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %s did not complete\n",
- cmd->label);
- TALER_EXCHANGE_reserve_withdraw_cancel (ws->wsh);
- ws->wsh = NULL;
- }
- if (NULL != ws->retry_task)
- {
- GNUNET_SCHEDULER_cancel (ws->retry_task);
- ws->retry_task = NULL;
- }
- if (NULL != ws->sig.rsa_signature)
- {
- GNUNET_CRYPTO_rsa_signature_free (ws->sig.rsa_signature);
- ws->sig.rsa_signature = NULL;
- }
- GNUNET_free_non_null (ws->exchange_url);
- GNUNET_free (ws);
-}
-
-
-/**
- * Offer internal data to a "withdraw" CMD state to other
- * commands.
- *
- * @param cls closure
- * @param ret[out] result (could be anything)
- * @param trait name of the trait
- * @param index index number of the object to offer.
- *
- * @return #GNUNET_OK on success
- */
-static int
-withdraw_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct WithdrawState *ws = cls;
- const struct TALER_TESTING_Command *reserve_cmd;
- const struct TALER_ReservePrivateKeyP *reserve_priv;
-
- /* We offer the reserve key where these coins were withdrawn
- * from. */
- reserve_cmd = TALER_TESTING_interpreter_lookup_command
- (ws->is, ws->reserve_reference);
-
- if (NULL == reserve_cmd)
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (ws->is);
- return GNUNET_SYSERR;
- }
-
- if (GNUNET_OK != TALER_TESTING_get_trait_reserve_priv
- (reserve_cmd, 0, &reserve_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (ws->is);
- return GNUNET_SYSERR;
- }
-
- ws->exchange_url = GNUNET_strdup
- (TALER_EXCHANGE_get_base_url (ws->is->exchange));
-
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_coin_priv (0 /* only one coin */,
- &ws->ps.coin_priv),
- TALER_TESTING_make_trait_blinding_key (0 /* only one coin */,
- &ws->ps.blinding_key),
- TALER_TESTING_make_trait_denom_pub (0 /* only one coin */,
- ws->pk),
- TALER_TESTING_make_trait_denom_sig (0 /* only one coin */,
- &ws->sig),
- TALER_TESTING_make_trait_reserve_priv (0,
- reserve_priv),
- TALER_TESTING_make_trait_amount_obj (0,
- &ws->amount),
- TALER_TESTING_make_trait_url (0, ws->exchange_url),
-
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Create a withdraw command, letting the caller specify
- * the desired amount as string.
- *
- * @param label command label.
- * @param amount how much we withdraw.
- * @param expected_response_code which HTTP response code
- * we expect from the exchange.
- *
- * @return the withdraw command to be executed by the interpreter.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_withdraw_amount
- (const char *label,
- const char *reserve_reference,
- const char *amount,
- unsigned int expected_response_code)
-{
- struct WithdrawState *ws;
-
- ws = GNUNET_new (struct WithdrawState);
- ws->reserve_reference = reserve_reference;
-
- if (GNUNET_OK !=
- TALER_string_to_amount (amount,
- &ws->amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %s\n",
- amount,
- label);
- GNUNET_assert (0);
- }
-
- ws->expected_response_code = expected_response_code;
-
- struct TALER_TESTING_Command cmd = {
- .cls = ws,
- .label = label,
- .run = &withdraw_run,
- .cleanup = &withdraw_cleanup,
- .traits = &withdraw_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Create withdraw command, letting the caller specify the
- * amount by a denomination key.
- *
- * @param label command label.
- * @param exchange connection handle to the exchange.
- * @param reserve_reference reference to the reserve to withdraw
- * from; will provide reserve priv to sign the request.
- * @param dk denomination public key.
- * @param expected_response_code expected HTTP response code.
- *
- * @return the command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_withdraw_denomination
- (const char *label,
- const char *reserve_reference,
- const struct TALER_EXCHANGE_DenomPublicKey *dk,
- unsigned int expected_response_code)
-{
- struct WithdrawState *ws;
-
- if (NULL == dk)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Denomination key not specified at %s\n",
- label);
- GNUNET_assert (0);
- }
- ws = GNUNET_new (struct WithdrawState);
- ws->reserve_reference = reserve_reference;
- ws->pk = dk;
- ws->expected_response_code = expected_response_code;
-
- struct TALER_TESTING_Command cmd = {
- .cls = ws,
- .label = label,
- .run = &withdraw_run,
- .cleanup = &withdraw_cleanup,
- .traits = &withdraw_traits
- };
-
- return cmd;
-}
-
-
-/**
- * Modify a withdraw command to enable retries when the
- * reserve is not yet full or we get other transient
- * errors from the exchange.
- *
- * @param cmd a withdraw command
- * @return the command with retries enabled
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_withdraw_with_retry (struct TALER_TESTING_Command cmd)
-{
- struct WithdrawState *ws;
-
- GNUNET_assert (&withdraw_run == cmd.run);
- ws = cmd.cls;
- ws->do_retry = GNUNET_YES;
- return cmd;
-}
-
-
-/* end of testing_api_cmd_withdraw.c */
diff --git a/src/exchange-lib/testing_api_helpers.c b/src/exchange-lib/testing_api_helpers.c
deleted file mode 100644
index e56a57b92..000000000
--- a/src/exchange-lib/testing_api_helpers.c
+++ /dev/null
@@ -1,1050 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_helpers.c
- * @brief helper functions
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * Remove files from previous runs
- *
- * @param config_name configuration filename.
- */
-void
-TALER_TESTING_cleanup_files (const char *config_name)
-{
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_parse_and_run (config_name,
- &TALER_TESTING_cleanup_files_cfg,
- NULL))
- exit (77);
-}
-
-
-/**
- * Remove files from previous runs
- *
- * @param cls NULL
- * @param cfg configuration
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_cleanup_files_cfg (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- char *dir;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- "exchange",
- "keydir",
- &dir))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange",
- "keydir");
- return GNUNET_SYSERR;
- }
- if (GNUNET_YES ==
- GNUNET_DISK_directory_test (dir,
- GNUNET_NO))
- GNUNET_break (GNUNET_OK ==
- GNUNET_DISK_directory_remove (dir));
- GNUNET_free (dir);
- // TODO: auditor-specific clean-up here!
- return GNUNET_OK;
-}
-
-
-/**
- * Run `taler-exchange-keyup`.
- *
- * @param config_filename configuration file to use
- * @param output_filename where to write the output for the auditor
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_run_keyup (const char *config_filename,
- const char *output_filename)
-{
- struct GNUNET_OS_Process *proc;
-
- proc = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-exchange-keyup",
- "taler-exchange-keyup",
- "-c", config_filename,
- "-o", output_filename,
- NULL);
- if (NULL == proc)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to run `taler-exchange-keyup`,"
- " is your PATH correct?\n");
- return GNUNET_SYSERR;
- }
- GNUNET_OS_process_wait (proc);
- GNUNET_OS_process_destroy (proc);
- return GNUNET_OK;
-}
-
-
-/**
- * Run `taler-auditor-sign`.
- *
- * @param config_filename configuration file to use
- * @param exchange_master_pub master public key of the exchange
- * @param auditor_base_url what is the base URL of the auditor
- * @param signdata_in where is the information from taler-exchange-keyup
- * @param signdata_out where to write the output for the exchange
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_run_auditor_sign (const char *config_filename,
- const char *exchange_master_pub,
- const char *auditor_base_url,
- const char *signdata_in,
- const char *signdata_out)
-{
- struct GNUNET_OS_Process *proc;
-
- proc = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-auditor-sign",
- "taler-auditor-sign",
- "-c", config_filename,
- "-u", auditor_base_url,
- "-m", exchange_master_pub,
- "-r", signdata_in,
- "-o", signdata_out,
- NULL);
- if (NULL == proc)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to run `taler-auditor-sign`,"
- " is your PATH correct?\n");
- return GNUNET_SYSERR;
- }
- GNUNET_OS_process_wait (proc);
- GNUNET_OS_process_destroy (proc);
- return GNUNET_OK;
-}
-
-
-/**
- * Run `taler-auditor-exchange`.
- *
- * @param config_filename configuration file to use
- * @param exchange_master_pub master public key of the exchange
- * @param exchange_base_url what is the base URL of the exchange
- * @param do_remove #GNUNET_NO to add exchange, #GNUNET_YES to remove
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_run_auditor_exchange (const char *config_filename,
- const char *exchange_master_pub,
- const char *exchange_base_url,
- int do_remove)
-{
- struct GNUNET_OS_Process *proc;
-
- proc = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-auditor-exchange",
- "taler-auditor-exchange",
- "-c", config_filename,
- "-u", exchange_base_url,
- "-m", exchange_master_pub,
- (GNUNET_YES == do_remove)
- ? "-r"
- : NULL,
- NULL);
- if (NULL == proc)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to run `taler-auditor-exchange`,"
- " is your PATH correct?\n");
- return GNUNET_SYSERR;
- }
- GNUNET_OS_process_wait (proc);
- GNUNET_OS_process_destroy (proc);
- return GNUNET_OK;
-}
-
-
-/**
- * Run `taler-exchange-dbinit -r` (reset exchange database).
- *
- * @param config_filename configuration file to use
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_exchange_db_reset (const char *config_filename)
-{
- struct GNUNET_OS_Process *proc;
- enum GNUNET_OS_ProcessStatusType type;
- unsigned long code;
-
- proc = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-exchange-dbinit",
- "taler-exchange-dbinit",
- "-c", config_filename,
- "-r",
- NULL);
- if (NULL == proc)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to run `taler-exchange-dbinit`,"
- " is your PATH correct?\n");
- return GNUNET_NO;
- }
- if (GNUNET_SYSERR ==
- GNUNET_OS_process_wait_status (proc,
- &type,
- &code))
- {
- GNUNET_break (0);
- GNUNET_OS_process_destroy (proc);
- return GNUNET_SYSERR;
- }
- GNUNET_OS_process_destroy (proc);
- if ( (type == GNUNET_OS_PROCESS_EXITED) &&
- (0 != code) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to setup (exchange) database\n");
- return GNUNET_NO;
- }
- if ( (type != GNUNET_OS_PROCESS_EXITED) ||
- (0 != code) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected error running"
- " `taler-exchange-dbinit'!\n");
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Run `taler-auditor-dbinit -r` (reset auditor database).
- *
- * @param config_filename configuration file to use
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_auditor_db_reset (const char *config_filename)
-{
- struct GNUNET_OS_Process *proc;
- enum GNUNET_OS_ProcessStatusType type;
- unsigned long code;
-
- proc = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-auditor-dbinit",
- "taler-auditor-dbinit",
- "-c", config_filename,
- "-r",
- NULL);
- if (NULL == proc)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to run `taler-auditor-dbinit`,"
- " is your PATH correct?\n");
- return GNUNET_NO;
- }
- if (GNUNET_SYSERR ==
- GNUNET_OS_process_wait_status (proc,
- &type,
- &code))
- {
- GNUNET_break (0);
- GNUNET_OS_process_destroy (proc);
- return GNUNET_SYSERR;
- }
- GNUNET_OS_process_destroy (proc);
- if ( (type == GNUNET_OS_PROCESS_EXITED) &&
- (0 != code) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to setup (auditor) database\n");
- return GNUNET_NO;
- }
- if ( (type != GNUNET_OS_PROCESS_EXITED) ||
- (0 != code) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected error running"
- " `taler-auditor-dbinit'!\n");
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Type of closure for
- * #sign_keys_for_exchange.
- */
-struct SignInfo
-{
- /**
- * Set to the base URL of the exchange. To be free'd
- * by the caller.
- */
- char *exchange_base_url;
-
- /**
- * Set to the auditor's base URL. To be free'd by the caller.
- */
- char *auditor_base_url;
-
- /**
- * Name of the configuration file to use.
- */
- const char *config_filename;
-
- /**
- * Must be set to input file with the data to be signed before
- * calling #TALER_TESTING_sign_keys_for_exchange.
- */
- const char *auditor_sign_input_filename;
-};
-
-
-/**
- * Sign the keys for an exchange given configuration @a cfg.
- * The information to be signed must be in a file "auditor.in".
- *
- * @param cls[in,out] a `struct SignInfo` with
- * further paramters
- * @param cfg configuration to use
- * @return #GNUNET_OK on success
- */
-static int
-sign_keys_for_exchange (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- struct SignInfo *si = cls;
- char *test_home_dir;
- char *signed_keys_out;
- char *exchange_master_pub;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange",
- "BASE_URL",
- &si->exchange_base_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- "exchange",
- "BASE_URL");
- si->exchange_base_url = NULL;
- return GNUNET_NO;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "auditor",
- "BASE_URL",
- &si->auditor_base_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- "auditor",
- "BASE_URL");
- GNUNET_free (si->exchange_base_url);
- si->exchange_base_url = NULL;
- si->auditor_base_url = NULL;
- return GNUNET_SYSERR;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg,
- "paths",
- "TALER_TEST_HOME",
- &test_home_dir))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "paths",
- "TALER_TEST_HOME");
- GNUNET_free (si->exchange_base_url);
- GNUNET_free (si->auditor_base_url);
- si->exchange_base_url = NULL;
- si->auditor_base_url = NULL;
- return GNUNET_SYSERR;
- }
-
- GNUNET_asprintf (&signed_keys_out,
- "%s/.local/share/taler/auditors/auditor.out",
- test_home_dir);
- GNUNET_free (test_home_dir);
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange",
- "MASTER_PUBLIC_KEY",
- &exchange_master_pub))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange",
- "MASTER_PUBLIC_KEY");
- GNUNET_free (si->exchange_base_url);
- GNUNET_free (si->auditor_base_url);
- si->exchange_base_url = NULL;
- si->auditor_base_url = NULL;
- GNUNET_free (signed_keys_out);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_TESTING_run_auditor_exchange (si->config_filename,
- exchange_master_pub,
- si->exchange_base_url,
- GNUNET_NO))
- {
- GNUNET_free (si->exchange_base_url);
- GNUNET_free (si->auditor_base_url);
- si->exchange_base_url = NULL;
- si->auditor_base_url = NULL;
- return GNUNET_NO;
- }
-
- if (GNUNET_OK !=
- TALER_TESTING_run_auditor_sign (si->config_filename,
- exchange_master_pub,
- si->auditor_base_url,
- si->auditor_sign_input_filename,
- signed_keys_out))
- {
- GNUNET_free (si->exchange_base_url);
- GNUNET_free (si->auditor_base_url);
- si->exchange_base_url = NULL;
- si->auditor_base_url = NULL;
- return GNUNET_NO;
- }
- GNUNET_free (signed_keys_out);
- GNUNET_free (exchange_master_pub);
- return GNUNET_OK;
-}
-
-
-/**
- * Prepare launching an exchange. Checks that the configured
- * port is available, runs taler-exchange-keyup,
- * taler-auditor-sign and taler-exchange-dbinit. Does NOT
- * launch the exchange process itself.
- *
- * @param config_filename configuration file to use
- * @param auditor_base_url[out] will be set to the auditor base url,
- * if the config has any; otherwise it will be set to
- * NULL.
- * @param exchange_base_url[out] will be set to the exchange base url,
- * if the config has any; otherwise it will be set to
- * NULL.
- * @return #GNUNET_OK on success, #GNUNET_NO if test should be
- * skipped, #GNUNET_SYSERR on test failure
- */
-int
-TALER_TESTING_prepare_exchange (const char *config_filename,
- char **auditor_base_url,
- char **exchange_base_url)
-{
- struct SignInfo si = {
- .config_filename = config_filename,
- .exchange_base_url = NULL,
- .auditor_base_url = NULL,
- .auditor_sign_input_filename = "auditor.in"
- };
-
- if (GNUNET_OK !=
- TALER_TESTING_run_keyup (config_filename,
- si.auditor_sign_input_filename))
- return GNUNET_NO;
- if (GNUNET_OK !=
- TALER_TESTING_exchange_db_reset (config_filename))
- return GNUNET_NO;
- if (GNUNET_OK !=
- TALER_TESTING_auditor_db_reset (config_filename))
- return GNUNET_NO;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_parse_and_run (config_filename,
- &sign_keys_for_exchange,
- &si))
- return GNUNET_NO;
- *exchange_base_url = si.exchange_base_url;
- *auditor_base_url = si.auditor_base_url;
- return GNUNET_OK;
-}
-
-
-/**
- * Find denomination key matching the given amount.
- *
- * @param keys array of keys to search
- * @param amount coin value to look for
- * @return NULL if no matching key was found
- */
-const struct TALER_EXCHANGE_DenomPublicKey *
-TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys,
- const struct TALER_Amount *amount)
-{
- struct GNUNET_TIME_Absolute now;
- struct TALER_EXCHANGE_DenomPublicKey *pk;
- char *str;
-
- now = GNUNET_TIME_absolute_get ();
- for (unsigned int i=0;i<keys->num_denom_keys;i++)
- {
- pk = &keys->denom_keys[i];
- if ( (0 == TALER_amount_cmp (amount,
- &pk->value)) &&
- (now.abs_value_us >= pk->valid_from.abs_value_us) &&
- (now.abs_value_us <
- pk->withdraw_valid_until.abs_value_us) )
- return pk;
- }
- /* do 2nd pass to check if expiration times are to blame for
- * failure */
- str = TALER_amount_to_string (amount);
- for (unsigned int i=0;i<keys->num_denom_keys;i++)
- {
- pk = &keys->denom_keys[i];
- if ( (0 == TALER_amount_cmp (amount,
- &pk->value)) &&
- ( (now.abs_value_us < pk->valid_from.abs_value_us) ||
- (now.abs_value_us >
- pk->withdraw_valid_until.abs_value_us) ) )
- {
- GNUNET_log
- (GNUNET_ERROR_TYPE_WARNING,
- "Have denomination key for `%s', but with wrong"
- " expiration range %llu vs [%llu,%llu)\n",
- str,
- (unsigned long long) now.abs_value_us,
- (unsigned long long) pk->valid_from.abs_value_us,
- (unsigned long long)
- pk->withdraw_valid_until.abs_value_us);
- GNUNET_free (str);
- return NULL;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "No denomination key for amount %s found\n",
- str);
- GNUNET_free (str);
- return NULL;
-}
-
-
-/**
- * Wait for the exchange to have started. Waits for at
- * most 10s, after that returns 77 to indicate an error.
- *
- * @param base_url what URL should we expect the exchange
- * to be running at
- * @return 0 on success
- */
-int
-TALER_TESTING_wait_exchange_ready (const char *base_url)
-{
- char *wget_cmd;
- unsigned int iter;
-
- GNUNET_asprintf (&wget_cmd,
- "wget -q -t 1 -T 1 %skeys"
- " -o /dev/null -O /dev/null",
- base_url); // make sure ends with '/'
- /* give child time to start and bind against the socket */
- fprintf (stderr,
- "Waiting for `taler-exchange-httpd' to be ready\n");
- iter = 0;
- do
- {
- if (10 == iter)
- {
- fprintf (stderr,
- "Failed to launch `taler-exchange-httpd' (or `wget')\n");
- GNUNET_free (wget_cmd);
- return 77;
- }
- fprintf (stderr, ".\n");
- sleep (1);
- iter++;
- }
- while (0 != system (wget_cmd));
- GNUNET_free (wget_cmd);
- return 0;
-}
-
-
-/**
- * Wait for the auditor to have started. Waits for at
- * most 10s, after that returns 77 to indicate an error.
- *
- * @param base_url what URL should we expect the auditor
- * to be running at
- * @return 0 on success
- */
-int
-TALER_TESTING_wait_auditor_ready (const char *base_url)
-{
- char *wget_cmd;
- unsigned int iter;
-
- GNUNET_asprintf (&wget_cmd,
- "wget -q -t 1 -T 1 %sversion"
- " -o /dev/null -O /dev/null",
- base_url); // make sure ends with '/'
- /* give child time to start and bind against the socket */
- fprintf (stderr,
- "Waiting for `taler-auditor-httpd' to be ready\n");
- iter = 0;
- do
- {
- if (10 == iter)
- {
- fprintf (stderr,
- "Failed to launch `taler-auditor-httpd' (or `wget')\n");
- GNUNET_free (wget_cmd);
- return 77;
- }
- fprintf (stderr, ".\n");
- sleep (1);
- iter++;
- }
- while (0 != system (wget_cmd));
- GNUNET_free (wget_cmd);
- return 0;
-}
-
-
-/**
- * Initialize scheduler loop and curl context for the testcase
- * including starting and stopping the exchange using the given
- * configuration file.
- *
- * @param main_cb routine containing all the commands to run.
- * @param main_cb_cls closure for @a main_cb, typically NULL.
- * @param config_file configuration file for the test-suite.
- *
- * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise.
- * non-#GNUNET_OK codes are #GNUNET_SYSERR most of the
- * time.
- */
-int
-TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb,
- void *main_cb_cls,
- const char *config_filename)
-{
- struct TALER_TESTING_SetupContext setup_ctx = {
- .config_filename = config_filename,
- .main_cb = main_cb,
- .main_cb_cls = main_cb_cls
- };
- int result;
-
- if (GNUNET_OK !=
- (result = GNUNET_CONFIGURATION_parse_and_run (config_filename,
- &TALER_TESTING_setup_with_exchange_cfg,
- &setup_ctx)))
- return result;
- return GNUNET_OK;
-}
-
-
-/**
- * Initialize scheduler loop and curl context for the test case
- * including starting and stopping the exchange using the given
- * configuration file.
- *
- * @param cls must be a `struct TALER_TESTING_SetupContext *`
- * @param cfg configuration to use.
- * @return #GNUNET_OK if no errors occurred.
- */
-int
-TALER_TESTING_setup_with_exchange_cfg (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- const struct TALER_TESTING_SetupContext *setup_ctx = cls;
- struct GNUNET_OS_Process *exchanged;
- unsigned long long port;
- char *serve;
- char *base_url;
- int result;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange",
- "SERVE",
- &serve))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange",
- "SERVE");
- return GNUNET_NO;
- }
-
- if (0 == strcmp ("tcp", serve))
- {
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
- "exchange",
- "PORT",
- &port))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange",
- "PORT");
- GNUNET_free (serve);
- return GNUNET_NO;
- }
-
- if (GNUNET_OK !=
- GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
- (uint16_t) port))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Required port %llu not available, skipping.\n",
- port);
- GNUNET_free (serve);
- return GNUNET_NO;
- }
- }
- GNUNET_free (serve);
- exchanged = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-exchange-httpd",
- "taler-exchange-httpd",
- "-c", setup_ctx->config_filename,
- "-i",
- NULL);
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange",
- "BASE_URL",
- &base_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange",
- "BASE_URL");
- return GNUNET_NO;
- }
-
- if (0 != TALER_TESTING_wait_exchange_ready (base_url))
- {
- GNUNET_free (base_url);
- return 77;
- }
- GNUNET_free (base_url);
-
- /* NOTE: this call blocks. */
- result = TALER_TESTING_setup (setup_ctx->main_cb,
- setup_ctx->main_cb_cls,
- setup_ctx->config_filename,
- exchanged,
- GNUNET_YES);
- GNUNET_break (0 ==
- GNUNET_OS_process_kill (exchanged,
- SIGTERM));
- GNUNET_break (GNUNET_OK ==
- GNUNET_OS_process_wait (exchanged));
- GNUNET_OS_process_destroy (exchanged);
- return result;
-}
-
-
-/**
- * Initialize scheduler loop and curl context for the test case
- * including starting and stopping the auditor and exchange using the
- * given configuration file.
- *
- * @param cls must be a `struct TALER_TESTING_SetupContext *`
- * @param cfg configuration to use.
- * @return #GNUNET_OK if no errors occurred.
- */
-int
-TALER_TESTING_setup_with_auditor_and_exchange_cfg (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- const struct TALER_TESTING_SetupContext *setup_ctx = cls;
- struct GNUNET_OS_Process *auditord;
- unsigned long long port;
- char *serve;
- char *base_url;
- int result;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "auditor",
- "SERVE",
- &serve))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "auditor",
- "SERVE");
- return GNUNET_NO;
- }
-
- if (0 == strcmp ("tcp", serve))
- {
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
- "auditor",
- "PORT",
- &port))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "auditor",
- "PORT");
- GNUNET_free (serve);
- return GNUNET_NO;
- }
-
- if (GNUNET_OK !=
- GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
- (uint16_t) port))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Required port %llu not available, skipping.\n",
- port);
- GNUNET_free (serve);
- return GNUNET_NO;
- }
- }
- GNUNET_free (serve);
- auditord = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-auditor-httpd",
- "taler-auditor-httpd",
- "-c", setup_ctx->config_filename,
- NULL);
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "auditor",
- "BASE_URL",
- &base_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "auditor",
- "BASE_URL");
- return GNUNET_NO;
- }
-
- if (0 != TALER_TESTING_wait_auditor_ready (base_url))
- {
- GNUNET_free (base_url);
- GNUNET_break (0 ==
- GNUNET_OS_process_kill (auditord,
- SIGTERM));
- GNUNET_break (GNUNET_OK ==
- GNUNET_OS_process_wait (auditord));
- GNUNET_OS_process_destroy (auditord);
- return 77;
- }
- GNUNET_free (base_url);
-
- /* NOTE: this call blocks. */
- result = TALER_TESTING_setup_with_exchange_cfg ((void *) setup_ctx,
- cfg);
- GNUNET_break (0 ==
- GNUNET_OS_process_kill (auditord,
- SIGTERM));
- GNUNET_break (GNUNET_OK ==
- GNUNET_OS_process_wait (auditord));
- GNUNET_OS_process_destroy (auditord);
- return result;
-}
-
-
-/**
- * Initialize scheduler loop and curl context for the test case
- * including starting and stopping the auditor and exchange using the
- * given configuration file.
- *
- * @param main_cb main method.
- * @param main_cb_cls main method closure.
- * @param config_filename configuration file name. Is is used
- * by both this function and the exchange itself. In the
- * first case it gives out the exchange port number and
- * the exchange base URL so as to check whether the port
- * is available and the exchange responds when requested
- * at its base URL.
- * @return #GNUNET_OK if no errors occurred.
- */
-int
-TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb,
- void *main_cb_cls,
- const char *config_file)
-{
- struct TALER_TESTING_SetupContext setup_ctx = {
- .config_filename = config_file,
- .main_cb = main_cb,
- .main_cb_cls = main_cb_cls
- };
-
- return GNUNET_CONFIGURATION_parse_and_run (config_file,
- &TALER_TESTING_setup_with_auditor_and_exchange_cfg,
- &setup_ctx);
-}
-
-
-/**
- * Test port in URL string for availability.
- */
-int
-TALER_TESTING_url_port_free (const char *url)
-{
- const char *port;
- long pnum;
-
- port = strrchr (url,
- (unsigned char) ':');
- if (NULL == port)
- pnum = 80;
- else
- pnum = strtol (port + 1, NULL, 10);
- if (GNUNET_OK !=
- GNUNET_NETWORK_test_port_free (IPPROTO_TCP,
- pnum))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Port %u not available.\n",
- (unsigned int) pnum);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Allocate and return a piece of wire-details. Combines
- * the @a account_no and the @a bank_url to a
- * @a payto://-URL and adds some salt to create the JSON.
- *
- * @param account_no account number
- * @param bank_url the bank_url (FIXME/WARNING: shouldn't this be a _hostname_ ??)
- * @return JSON describing the account, including the
- * payto://-URL of the account, must be manually decref'd
- */
-json_t *
-TALER_TESTING_make_wire_details (unsigned long long account_no,
- const char *bank_url)
-{
- char *payto;
- json_t *ret;
-
- GNUNET_asprintf (&payto,
- "payto://x-taler-bank/%s/%llu",
- bank_url,
- account_no);
- ret = json_pack ("{s:s, s:s}",
- "url", payto,
- "salt", "test-salt (must be constant for aggregation tests)");
- GNUNET_free (payto);
- return ret;
-}
-
-
-/**
- * Prepare launching a fakebank. Check that the configuration
- * file has the right option, and that the port is available.
- * If everything is OK, return the configured URL of the fakebank.
- *
- * @param config_filename configuration file to use
- * @param config_section which account to use (must match x-taler-bank)
- * @return NULL on error, fakebank URL otherwise
- */
-char *
-TALER_TESTING_prepare_fakebank (const char *config_filename,
- const char *config_section)
-{
- struct GNUNET_CONFIGURATION_Handle *cfg;
- char *payto_url;
- char *fakebank_url;
- const char *start;
- const char *end;
-
- cfg = GNUNET_CONFIGURATION_create ();
- if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg,
- config_filename))
- return NULL;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- config_section,
- "URL",
- &payto_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
- config_section,
- "URL");
- GNUNET_CONFIGURATION_destroy (cfg);
- return NULL;
- }
- GNUNET_CONFIGURATION_destroy (cfg);
- if (0 != strncasecmp (payto_url,
- "payto://x-taler-bank/",
- strlen ("payto://x-taler-bank/")))
- {
- GNUNET_log_config_invalid
- (GNUNET_ERROR_TYPE_WARNING,
- config_section,
- "URL",
- "expected `x-taler-bank' payto://-URL");
- GNUNET_CONFIGURATION_destroy (cfg);
- GNUNET_free (payto_url);
- return NULL;
- }
- start = &payto_url [strlen ("payto://x-taler-bank/")];
- end = strchr (start,
- (unsigned char) '/');
- if (NULL == end)
- end = &start[strlen (start)];
- fakebank_url = GNUNET_strndup (start,
- end - start);
- GNUNET_free (payto_url);
- if (GNUNET_OK !=
- TALER_TESTING_url_port_free (fakebank_url))
- {
- GNUNET_free (fakebank_url);
- return NULL;
- }
- return fakebank_url;
-}
-
-/* end of testing_api_helpers.c */
diff --git a/src/exchange-lib/testing_api_loop.c b/src/exchange-lib/testing_api_loop.c
deleted file mode 100644
index 3e7e36432..000000000
--- a/src/exchange-lib/testing_api_loop.c
+++ /dev/null
@@ -1,825 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_loop.c
- * @brief main interpreter loop for testcases
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-#include "taler_fakebank_lib.h"
-
-/**
- * Pipe used to communicate child death via signal.
- * Must be global, as used in signal handler!
- */
-static struct GNUNET_DISK_PipeHandle *sigpipe;
-
-/**
- * Lookup command by label.
- *
- * @param is interpreter state to search
- * @param label label to look for
- * @return NULL if command was not found
- */
-const struct TALER_TESTING_Command *
-TALER_TESTING_interpreter_lookup_command
- (struct TALER_TESTING_Interpreter *is,
- const char *label)
-{
- if (NULL == label)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Attempt to lookup command for empty label\n");
- return NULL;
- }
- /* Search backwards as we most likely reference recent commands */
- for (int i=is->ip; i >= 0; i--)
- {
- const struct TALER_TESTING_Command *cmd = &is->commands[i];
-
- /* Give precedence to top-level commands. */
- if ( (NULL != cmd->label) &&
- (0 == strcmp (cmd->label,
- label)) )
- return cmd;
-
- if (TALER_TESTING_cmd_is_batch (cmd))
- {
-#define BATCH_INDEX 1
- struct TALER_TESTING_Command *batch;
-
- GNUNET_assert (GNUNET_OK ==
- TALER_TESTING_get_trait_cmd (cmd,
- BATCH_INDEX,
- &batch));
- for (unsigned int j=0;
- NULL != (cmd = &batch[j])->label;
- j++)
- {
- if ( (NULL != cmd->label) &&
- (0 == strcmp (cmd->label,
- label)) )
- return cmd;
- }
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Command not found: %s\n",
- label);
- return NULL;
-
-}
-
-
-/**
- * Obtain main execution context for the main loop.
- */
-struct GNUNET_CURL_Context *
-TALER_TESTING_interpreter_get_context
- (struct TALER_TESTING_Interpreter *is)
-{
- return is->ctx;
-}
-
-
-struct TALER_FAKEBANK_Handle *
-TALER_TESTING_interpreter_get_fakebank
- (struct TALER_TESTING_Interpreter *is)
-{
- return is->fakebank;
-}
-
-
-/**
- * Run tests starting the "fakebank" first. The "fakebank"
- * is a C minimalist version of the human-oriented Python bank,
- * which is also part of the Taler project.
- *
- * @param is pointer to the interpreter state
- * @param commands the list of commands to execute
- * @param bank_url the url the fakebank is supposed to run on
- */
-void
-TALER_TESTING_run_with_fakebank
- (struct TALER_TESTING_Interpreter *is,
- struct TALER_TESTING_Command *commands,
- const char *bank_url)
-{
- const char *port;
- long pnum;
-
- port = strrchr (bank_url,
- (unsigned char) ':');
- if (NULL == port)
- pnum = 80;
- else
- pnum = strtol (port + 1, NULL, 10);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Starting Fakebank on port %u (%s)\n",
- (unsigned int) pnum,
- bank_url);
- is->fakebank = TALER_FAKEBANK_start ((uint16_t) pnum);
- if (NULL == is->fakebank)
- {
- GNUNET_break (0);
- is->result = GNUNET_SYSERR;
- return;
- }
- TALER_TESTING_run (is,
- commands);
-}
-
-
-/**
- * Run the main interpreter loop that performs exchange operations.
- *
- * @param cls contains the `struct InterpreterState`
- */
-static void
-interpreter_run (void *cls);
-
-
-/**
- * Current command is done, run the next one.
- */
-void
-TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is)
-{
- static unsigned long long ipc;
- static struct GNUNET_TIME_Absolute last_report;
- struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
-
- if (GNUNET_SYSERR == is->result)
- return; /* ignore, we already failled! */
- if (TALER_TESTING_cmd_is_batch (cmd))
- {
-#define CURRENT_BATCH_SUBCMD_INDEX 0
- struct TALER_TESTING_Command *sub_cmd;
-
- GNUNET_assert (GNUNET_OK == TALER_TESTING_get_trait_cmd
- (cmd, CURRENT_BATCH_SUBCMD_INDEX, &sub_cmd));
-
- if (NULL == sub_cmd->label)
- is->ip++;
- }
- else
- is->ip++;
- if (0 == (ipc % 1000))
- {
- if (0 != ipc)
- GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
- "Interpreter executed 1000 instructions in %s\n",
- GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (last_report),
- GNUNET_YES));
- last_report = GNUNET_TIME_absolute_get ();
- }
- ipc++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Current command failed, clean up and fail the test case.
- *
- * @param is interpreter of the test
- */
-void
-TALER_TESTING_interpreter_fail
- (struct TALER_TESTING_Interpreter *is)
-{
- struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
-
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed at command `%s'\n",
- cmd->label);
- while (TALER_TESTING_cmd_is_batch (cmd))
- {
- cmd = TALER_TESTING_cmd_batch_get_current (cmd);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Batch is at command `%s'\n",
- cmd->label);
- }
- is->result = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Create command array terminator.
- *
- * @return a end-command.
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_end (void)
-{
- static struct TALER_TESTING_Command cmd;
- cmd.label = NULL;
-
- return cmd;
-}
-
-
-/**
- * Obtain current label.
- */
-const char *
-TALER_TESTING_interpreter_get_current_label
- (struct TALER_TESTING_Interpreter *is)
-{
- struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
-
- return cmd->label;
-}
-
-
-/**
- * Run the main interpreter loop that performs exchange operations.
- *
- * @param cls contains the `struct TALER_TESTING_Interpreter`
- */
-static void
-interpreter_run (void *cls)
-{
- struct TALER_TESTING_Interpreter *is = cls;
- struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
-
- is->task = NULL;
-
- if (NULL == cmd->label)
- {
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Running command END\n");
- is->result = GNUNET_OK;
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Running command `%s'\n",
- cmd->label);
-
- cmd->run (cmd->cls,
- cmd,
- is);
-}
-
-
-/**
- * Function run when the test terminates (good or bad).
- * Cleans up our state.
- *
- * @param cls the interpreter state.
- */
-static void
-do_shutdown (void *cls)
-{
- struct TALER_TESTING_Interpreter *is = cls;
- struct TALER_TESTING_Command *cmd;
- const char *label;
-
- label = is->commands[is->ip].label;
- if (NULL == label)
- label = "END";
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Executing shutdown at `%s'\n",
- label);
-
- for (unsigned int j=0;NULL != (cmd = &is->commands[j])->label;j++)
- cmd->cleanup (cmd->cls,
- cmd);
- if (NULL != is->exchange)
- {
- TALER_EXCHANGE_disconnect (is->exchange);
- is->exchange = NULL;
- }
- if (NULL != is->task)
- {
- GNUNET_SCHEDULER_cancel (is->task);
- is->task = NULL;
- }
- if (NULL != is->ctx)
- {
- GNUNET_CURL_fini (is->ctx);
- is->ctx = NULL;
- }
- if (NULL != is->rc)
- {
- GNUNET_CURL_gnunet_rc_destroy (is->rc);
- is->rc = NULL;
- }
- if (NULL != is->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (is->timeout_task);
- is->timeout_task = NULL;
- }
- if (NULL != is->child_death_task)
- {
- GNUNET_SCHEDULER_cancel (is->child_death_task);
- is->child_death_task = NULL;
- }
- if (NULL != is->fakebank)
- {
- TALER_FAKEBANK_stop (is->fakebank);
- is->fakebank = NULL;
- }
- GNUNET_free_non_null (is->commands);
-}
-
-
-/**
- * Function run when the test terminates (good or bad) with timeout.
- *
- * @param cls NULL
- */
-static void
-do_timeout (void *cls)
-{
- struct TALER_TESTING_Interpreter *is = cls;
-
- is->timeout_task = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Terminating test due to timeout\n");
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Task triggered whenever we receive a SIGCHLD (child
- * process died).
- *
- * @param cls closure
- */
-static void
-maint_child_death (void *cls)
-{
- struct TALER_TESTING_Interpreter *is = cls;
- struct TALER_TESTING_Command *cmd = &is->commands[is->ip];
- const struct GNUNET_DISK_FileHandle *pr;
-
- struct GNUNET_OS_Process **processp;
- char c[16];
-
- if (TALER_TESTING_cmd_is_batch (cmd))
- {
- struct TALER_TESTING_Command *batch_cmd;
-
- GNUNET_assert
- (GNUNET_OK == TALER_TESTING_get_trait_cmd
- (cmd, 0, &batch_cmd)); /* bad? */
- cmd = batch_cmd;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Got SIGCHLD for `%s'.\n",
- cmd->label);
-
- is->child_death_task = NULL;
- pr = GNUNET_DISK_pipe_handle (sigpipe,
- GNUNET_DISK_PIPE_END_READ);
- GNUNET_break (0 <
- GNUNET_DISK_file_read (pr,
- &c,
- sizeof (c)));
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_process (cmd,
- 0,
- &processp))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (is);
- return;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Got the dead child process handle"
- ", waiting for termination ...\n");
-
- GNUNET_OS_process_wait (*processp);
- GNUNET_OS_process_destroy (*processp);
- *processp = NULL;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "... definitively terminated\n");
-
- if (GNUNET_OK == is->reload_keys)
- {
- if (NULL == is->exchanged)
- {
- GNUNET_break (0);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Triggering key state reload at exchange\n");
- GNUNET_break (0 == GNUNET_OS_process_kill
- (is->exchanged, SIGUSR1));
- sleep (5); /* make sure signal was received and processed */
- }
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Dead child, go on with next command.\n");
- TALER_TESTING_interpreter_next (is);
-}
-
-
-/**
- * Wait until we receive SIGCHLD signal.
- * Then obtain the process trait of the current
- * command, wait on the the zombie and continue
- * with the next command.
- */
-void
-TALER_TESTING_wait_for_sigchld
- (struct TALER_TESTING_Interpreter *is)
-{
- const struct GNUNET_DISK_FileHandle *pr;
-
- GNUNET_assert (NULL == is->child_death_task);
- pr = GNUNET_DISK_pipe_handle (sigpipe,
- GNUNET_DISK_PIPE_END_READ);
- is->child_death_task
- = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
- pr,
- &maint_child_death,
- is);
-}
-
-
-/**
- * Run the testsuite. Note, CMDs are copied into
- * the interpreter state because they are _usually_
- * defined into the "run" method that returns after
- * having scheduled the test interpreter.
- *
- * @param is the interpreter state
- * @param commands the list of command to execute
- * @param timeout how long to wait
- */
-void
-TALER_TESTING_run2 (struct TALER_TESTING_Interpreter *is,
- struct TALER_TESTING_Command *commands,
- struct GNUNET_TIME_Relative timeout)
-{
- unsigned int i;
-
- if (NULL != is->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (is->timeout_task);
- is->timeout_task = NULL;
- }
- /* get the number of commands */
- for (i=0;NULL != commands[i].label;i++) ;
- is->commands = GNUNET_new_array (i + 1,
- struct TALER_TESTING_Command);
- memcpy (is->commands,
- commands,
- sizeof (struct TALER_TESTING_Command) * i);
- is->timeout_task = GNUNET_SCHEDULER_add_delayed
- (timeout,
- &do_timeout,
- is);
- GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is);
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, is);
-}
-
-
-/**
- * Run the testsuite. Note, CMDs are copied into
- * the interpreter state because they are _usually_
- * defined into the "run" method that returns after
- * having scheduled the test interpreter.
- *
- * @param is the interpreter state
- * @param commands the list of command to execute
- */
-void
-TALER_TESTING_run (struct TALER_TESTING_Interpreter *is,
- struct TALER_TESTING_Command *commands)
-{
- TALER_TESTING_run2 (is,
- commands,
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES,
- 5));
-}
-
-
-/**
- * Information used by the wrapper around the main
- * "run" method.
- */
-struct MainContext
-{
- /**
- * Main "run" method.
- */
- TALER_TESTING_Main main_cb;
-
- /**
- * Closure for @e main_cb.
- */
- void *main_cb_cls;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * Configuration filename. The wrapper uses it to fetch
- * the exchange port number; We could have passed the port
- * number here, but having the config filename seems more
- * generic.
- */
- const char *config_filename;
-
- /**
- * URL of the exchange.
- */
- char *exchange_url;
-
-};
-
-
-/**
- * Signal handler called for SIGCHLD. Triggers the
- * respective handler by writing to the trigger pipe.
- */
-static void
-sighandler_child_death ()
-{
- static char c;
- int old_errno = errno; /* back-up errno */
-
- GNUNET_break (1 == GNUNET_DISK_file_write
- (GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_WRITE),
- &c, sizeof (c)));
- errno = old_errno; /* restore errno */
-}
-
-
-/**
- * Called once a connection to the exchange has been
- * established.
- *
- * @param cls closure, typically, the "run" method containing
- * all the commands to be run, and a closure for it.
- * @param keys the exchange's keys.
- * @param compat protocol compatibility information.
- */
-static void
-cert_cb (void *cls,
- const struct TALER_EXCHANGE_Keys *keys,
- enum TALER_EXCHANGE_VersionCompatibility compat)
-{
- struct MainContext *main_ctx = cls;
- struct TALER_TESTING_Interpreter *is = main_ctx->is;
-
- if (NULL == keys)
- {
- if (GNUNET_NO == is->working)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Got NULL response for /keys during startup, retrying!\n");
- TALER_EXCHANGE_disconnect (is->exchange);
- GNUNET_assert (NULL !=
- (is->exchange = TALER_EXCHANGE_connect (is->ctx,
- main_ctx->exchange_url,
- &cert_cb,
- main_ctx,
- TALER_EXCHANGE_OPTION_END)));
- return;
- }
- else
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Got NULL response for /keys during execution!\n");
-
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Got %d DK from /keys\n",
- keys->num_denom_keys);
- }
- is->key_generation++;
- is->keys = keys;
-
- /* /keys has been called for some reason and
- * the interpreter is already running. */
- if (GNUNET_YES == is->working)
- return;
-
- is->working = GNUNET_YES;
-
- /* Very first start of tests, call "run()" */
- if (1 == is->key_generation)
- {
- main_ctx->main_cb (main_ctx->main_cb_cls,
- is);
- return;
- }
-
- /* Tests already started, just trigger the
- * next command. */
- GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Initialize scheduler loop and curl context for the testcase,
- * and responsible to run the "run" method.
- *
- * @param cls closure, typically the "run" method, the
- * interpreter state and a closure for "run".
- */
-static void
-main_wrapper_exchange_agnostic (void *cls)
-{
- struct MainContext *main_ctx = cls;
-
- main_ctx->main_cb (main_ctx->main_cb_cls,
- main_ctx->is);
-}
-
-
-/**
- * Function run when the test is aborted before we launch the actual
- * interpreter. Cleans up our state.
- *
- * @param cls the main context
- */
-static void
-do_abort (void *cls)
-{
- struct MainContext *main_ctx = cls;
- struct TALER_TESTING_Interpreter *is = main_ctx->is;
-
- is->timeout_task = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Executing abort prior to interpreter launch\n");
- if (NULL != is->exchange)
- {
- TALER_EXCHANGE_disconnect (is->exchange);
- is->exchange = NULL;
- }
-}
-
-
-/**
- * Initialize scheduler loop and curl context for the testcase,
- * and responsible to run the "run" method.
- *
- * @param cls a `struct MainContext *`
- * @param cfg configuration to use
- */
-static int
-main_exchange_connect_with_cfg (void *cls,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
- struct MainContext *main_ctx = cls;
- struct TALER_TESTING_Interpreter *is = main_ctx->is;
- char *exchange_url;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- "exchange",
- "BASE_URL",
- &exchange_url))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "exchange",
- "BASE_URL");
- return GNUNET_SYSERR;
- }
- main_ctx->exchange_url = exchange_url;
- is->cfg = cfg;
- is->timeout_task = GNUNET_SCHEDULER_add_shutdown (&do_abort,
- main_ctx);
- GNUNET_break (NULL !=
- (is->exchange = TALER_EXCHANGE_connect (is->ctx,
- exchange_url,
- &cert_cb,
- main_ctx,
- TALER_EXCHANGE_OPTION_END)));
- is->cfg = NULL;
- return GNUNET_OK;
-}
-
-
-/**
- * Initialize scheduler loop and curl context for the testcase,
- * and responsible to run the "run" method.
- *
- * @param cls a `struct MainContext *`
- */
-static void
-main_wrapper_exchange_connect (void *cls)
-{
- struct MainContext *main_ctx = cls;
-
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONFIGURATION_parse_and_run (main_ctx->config_filename,
- &main_exchange_connect_with_cfg,
- main_ctx));
-}
-
-
-/**
- * Install signal handlers plus schedules the main wrapper
- * around the "run" method.
- *
- * @param main_cb the "run" method which contains all the
- * commands.
- * @param main_cb_cls a closure for "run", typically NULL.
- * @param config_filename configuration filename.
- * @param exchanged exchange process handle: will be put in the
- * state as some commands - e.g. revoke - need to send
- * signal to it, for example to let it know to reload the
- * key state.. if NULL, the interpreter will run without
- * trying to connect to the exchange first.
- * @param exchange_connect #GNUNET_YES if the test should connect
- * to the exchange, #GNUNET_NO otherwise
- * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise.
- * non-GNUNET_OK codes are #GNUNET_SYSERR most of the
- * times.
- */
-int
-TALER_TESTING_setup (TALER_TESTING_Main main_cb,
- void *main_cb_cls,
- const char *config_filename,
- struct GNUNET_OS_Process *exchanged,
- int exchange_connect)
-{
- struct TALER_TESTING_Interpreter is;
- struct MainContext main_ctx = {
- .main_cb = main_cb,
- .main_cb_cls = main_cb_cls,
- /* needed to init the curl ctx */
- .is = &is,
- /* needed to read values like exchange port
- * number to construct the exchange url.*/
- .config_filename = config_filename
- };
- struct GNUNET_SIGNAL_Context *shc_chld;
-
- memset (&is,
- 0,
- sizeof (is));
- is.exchanged = exchanged;
- sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO,
- GNUNET_NO, GNUNET_NO);
- GNUNET_assert (NULL != sigpipe);
- shc_chld = GNUNET_SIGNAL_handler_install
- (GNUNET_SIGCHLD,
- &sighandler_child_death);
- is.ctx = GNUNET_CURL_init
- (&GNUNET_CURL_gnunet_scheduler_reschedule,
- &is.rc);
- GNUNET_assert (NULL != is.ctx);
- is.rc = GNUNET_CURL_gnunet_rc_create (is.ctx);
-
- /* Blocking */
-
- if (GNUNET_YES == exchange_connect)
- GNUNET_SCHEDULER_run (&main_wrapper_exchange_connect,
- &main_ctx);
- else
- GNUNET_SCHEDULER_run (&main_wrapper_exchange_agnostic,
- &main_ctx);
- if (NULL != is.final_cleanup_cb)
- is.final_cleanup_cb (is.final_cleanup_cb_cls);
- GNUNET_free_non_null (main_ctx.exchange_url);
- GNUNET_SIGNAL_handler_uninstall (shc_chld);
- GNUNET_DISK_pipe_close (sigpipe);
- sigpipe = NULL;
- return is.result;
-}
-
-/* end of testing_api_loop.c */
diff --git a/src/exchange-lib/testing_api_trait_amount.c b/src/exchange-lib/testing_api_trait_amount.c
deleted file mode 100644
index 8f2b79d45..000000000
--- a/src/exchange-lib/testing_api_trait_amount.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3,
- or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_amount.c
- * @brief offer amounts as traits.
- * @author Marcello Stanisci
- */
-
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_AMOUNT "amount"
-
-/**
- * Obtain an amount from a @a cmd.
- *
- * @param cmd command to extract the amount from.
- * @param index which amount to pick if @a cmd has multiple
- * on offer
- * @param amount[out] set to the amount.
- *
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_amount_obj
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct TALER_Amount **amount)
-{
- return cmd->traits (cmd->cls,
- (const void **) amount,
- TALER_TESTING_TRAIT_AMOUNT,
- index);
-}
-
-
-/**
- * Offer amount.
- *
- * @param index which amount to offer, in case there are
- * multiple available.
- * @param amount the amount to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_amount_obj
- (unsigned int index,
- const struct TALER_Amount *amount)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_AMOUNT,
- .ptr = (const void *) amount
- };
-
- return ret;
-}
-
-
-/* end of testing_api_trait_amount.c */
diff --git a/src/exchange-lib/testing_api_trait_blinding_key.c b/src/exchange-lib/testing_api_trait_blinding_key.c
deleted file mode 100644
index 6e52d1148..000000000
--- a/src/exchange-lib/testing_api_trait_blinding_key.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/testing_api_trait_blinding_key.c
- * @brief offer blinding keys as traits.
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_BLINDING_KEY "blinding-key"
-
-
-/**
- * Obtain a blinding key from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which coin to pick if @a cmd has multiple on offer.
- * @param blinding_key[out] set to the offered blinding key.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_blinding_key
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct TALER_DenominationBlindingKeyP **blinding_key)
-{
- return cmd->traits (cmd->cls,
- (const void **) blinding_key,
- TALER_TESTING_TRAIT_BLINDING_KEY,
- index);
-}
-
-
-
-/**
- * Offer blinding key.
- *
- * @param index index number to associate to the offered key.
- * @param blinding_key blinding key to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_blinding_key
- (unsigned int index,
- const struct TALER_DenominationBlindingKeyP *blinding_key)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_BLINDING_KEY,
- .ptr = (const void *) blinding_key
- };
-
- return ret;
-}
-
-/* end of testing_api_trait_blinding_key.c */
diff --git a/src/exchange-lib/testing_api_trait_cmd.c b/src/exchange-lib/testing_api_trait_cmd.c
deleted file mode 100644
index 61e976568..000000000
--- a/src/exchange-lib/testing_api_trait_cmd.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_cmd.c
- * @brief offers CMDs as traits.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_CMD "cmd"
-
-/**
- * Obtain a command from @a cmd.
- *
- * @param cmd command to extract the command from.
- * @param index always zero. Commands offering this
- * kind of traits do not need this index. For
- * example, a "batch" CMD returns always the
- * CMD currently being executed.
- * @param cmd_[out] where to write the wire details.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_cmd
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- struct TALER_TESTING_Command **_cmd)
-{
- return cmd->traits (cmd->cls,
- (const void **) _cmd,
- TALER_TESTING_TRAIT_CMD,
- index);
-}
-
-
-/**
- * Offer a command in a trait.
- *
- * @param index always zero. Commands offering this
- * kind of traits do not need this index. For
- * example, a "meta" CMD returns always the
- * CMD currently being executed.
- * @param cmd wire details to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_cmd
- (unsigned int index,
- const struct TALER_TESTING_Command *cmd)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_CMD,
- .ptr = (const struct TALER_TESTING_Command *) cmd
- };
- return ret;
-}
-
-/* end of testing_api_trait_cmd.c */
diff --git a/src/exchange-lib/testing_api_trait_coin_priv.c b/src/exchange-lib/testing_api_trait_coin_priv.c
deleted file mode 100644
index b06e4a207..000000000
--- a/src/exchange-lib/testing_api_trait_coin_priv.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_coin_priv.c
- * @brief coin priv traits.
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_COIN_PRIVATE_KEY "coin-private-key"
-
-
-/**
- * Obtain a coin private key from a @a cmd.
- *
- * @param cmd command to extract trait from.
- * @param index index of the coin priv to obtain.
- * @param coin_priv[out] set to the private key of the coin.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_coin_priv
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct TALER_CoinSpendPrivateKeyP **coin_priv)
-{
- return cmd->traits (cmd->cls,
- (const void **) coin_priv,
- TALER_TESTING_TRAIT_COIN_PRIVATE_KEY,
- index);
-}
-
-
-/**
- * Offer coin private key.
- *
- * @param index index number to associate with offered coin priv.
- * @param coin_priv coin private key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_coin_priv
- (unsigned int index,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_COIN_PRIVATE_KEY,
- .ptr = (const void *) coin_priv
- };
-
- return ret;
-}
-
-/* end of testing_api_trait_coin_priv.c */
diff --git a/src/exchange-lib/testing_api_trait_denom_pub.c b/src/exchange-lib/testing_api_trait_denom_pub.c
deleted file mode 100644
index 448a262c8..000000000
--- a/src/exchange-lib/testing_api_trait_denom_pub.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/testing_api_trait_denom_pub.c
- * @brief denom pub traits.
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_DENOM_PUB "denomination-public-key"
-
-
-/**
- * Obtain a denomination public key from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index index number of the denom to obtain.
- * @param denom_pub[out] set to the offered denom pub.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_denom_pub
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct TALER_EXCHANGE_DenomPublicKey **denom_pub)
-{
- return cmd->traits (cmd->cls,
- (const void **) denom_pub,
- TALER_TESTING_TRAIT_DENOM_PUB,
- index);
-}
-
-
-/**
- * Make a trait for a denomination public key.
- *
- * @param index index number to associate to the offered denom pub.
- * @param denom_pub denom pub to offer with this trait.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_denom_pub
- (unsigned int index,
- const struct TALER_EXCHANGE_DenomPublicKey *denom_pub)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_DENOM_PUB,
- .ptr = (const void *) denom_pub
- };
-
- return ret;
-}
-
-/* end of testing_api_trait_denom_pub.c */
diff --git a/src/exchange-lib/testing_api_trait_denom_sig.c b/src/exchange-lib/testing_api_trait_denom_sig.c
deleted file mode 100644
index 03062c835..000000000
--- a/src/exchange-lib/testing_api_trait_denom_sig.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3,
- or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_denom_sig.c
- * @brief offer denomination signatures as traits
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_DENOM_SIG "denomination-signature"
-
-
-/**
- * Obtain a denomination signature from a @a cmd.
- *
- * @param cmd command to extract the denom sig from.
- * @param index index number associated with the denom sig.
- * @param denom_sig[out] set to the offered signature.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_denom_sig
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct TALER_DenominationSignature **denom_sig)
-{
- return cmd->traits (cmd->cls,
- (const void **) denom_sig,
- TALER_TESTING_TRAIT_DENOM_SIG,
- index);
-}
-
-
-/**
- * Offer denom sig.
- *
- * @param index index number to associate to the signature on
- * offer.
- * @param denom_sig the denom sig on offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_denom_sig
- (unsigned int index,
- const struct TALER_DenominationSignature *denom_sig)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_DENOM_SIG,
- .ptr = (const void *) denom_sig
- };
-
- return ret;
-}
-
-
-/* end of testing_api_trait_denom_sig.c */
diff --git a/src/exchange-lib/testing_api_trait_exchange_pub.c b/src/exchange-lib/testing_api_trait_exchange_pub.c
deleted file mode 100644
index e8cdfbb35..000000000
--- a/src/exchange-lib/testing_api_trait_exchange_pub.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/testing_api_trait_exchange_pub.c
- * @brief exchange pub traits.
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_EXCHANGE_PUB "exchange-public-key"
-
-
-/**
- * Obtain a exchange public key from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index index number of the exchange to obtain.
- * @param exchange_pub[out] set to the offered exchange pub.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_exchange_pub
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct TALER_ExchangePublicKeyP **exchange_pub)
-{
- return cmd->traits (cmd->cls,
- (const void **) exchange_pub,
- TALER_TESTING_TRAIT_EXCHANGE_PUB,
- index);
-}
-
-
-/**
- * Make a trait for a exchange public key.
- *
- * @param index index number to associate to the offered exchange pub.
- * @param exchange_pub exchange pub to offer with this trait.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_exchange_pub
- (unsigned int index,
- const struct TALER_ExchangePublicKeyP *exchange_pub)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_EXCHANGE_PUB,
- .ptr = (const void *) exchange_pub
- };
-
- return ret;
-}
-
-/* end of testing_api_trait_exchange_pub.c */
diff --git a/src/exchange-lib/testing_api_trait_exchange_sig.c b/src/exchange-lib/testing_api_trait_exchange_sig.c
deleted file mode 100644
index 97ce2d969..000000000
--- a/src/exchange-lib/testing_api_trait_exchange_sig.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/testing_api_trait_exchange_sig.c
- * @brief exchange pub traits.
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_EXCHANGE_SIG "exchange-online-signature"
-
-
-/**
- * Obtain a exchange signature (online sig) from a @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index index number of the exchange to obtain.
- * @param exchange_sig[out] set to the offered exchange signature.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_exchange_sig
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct TALER_ExchangeSignatureP **exchange_sig)
-{
- return cmd->traits (cmd->cls,
- (const void **) exchange_sig,
- TALER_TESTING_TRAIT_EXCHANGE_SIG,
- index);
-}
-
-
-/**
- * Make a trait for a exchange signature.
- *
- * @param index index number to associate to the offered exchange pub.
- * @param exchange_sig exchange signature to offer with this trait.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_exchange_sig
- (unsigned int index,
- const struct TALER_ExchangeSignatureP *exchange_sig)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_EXCHANGE_SIG,
- .ptr = (const void *) exchange_sig
- };
-
- return ret;
-}
-
-/* end of testing_api_trait_exchange_sig.c */
diff --git a/src/exchange-lib/testing_api_trait_fresh_coin.c b/src/exchange-lib/testing_api_trait_fresh_coin.c
deleted file mode 100644
index 1f6cdac2c..000000000
--- a/src/exchange-lib/testing_api_trait_fresh_coin.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_fresh_coin.c
- * @brief traits to offer fresh conins (after "melt" operations)
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_FRESH_COINS "fresh-coins"
-
-/**
- * Get a array of fresh coins.
- *
- * @param cmd command to extract the fresh coin from.
- * @param index which array to pick if @a cmd has multiple
- * on offer.
- * @param fresh_coins[out] will point to the offered array.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_fresh_coins
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct FreshCoin **fresh_coins)
-{
- return cmd->traits (cmd->cls,
- (const void **) fresh_coins,
- TALER_TESTING_TRAIT_FRESH_COINS,
- index);
-}
-
-
-/**
- * Offer a _array_ of fresh coins.
- *
- * @param index which array of fresh coins to offer,
- * if there are multiple on offer. Tipically passed as
- * zero.
- * @param fresh_coins the array of fresh coins to offer
- *
- * @return the trait,
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_fresh_coins
- (unsigned int index,
- struct FreshCoin *fresh_coins)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_FRESH_COINS,
- .ptr = (const void *) fresh_coins
- };
- return ret;
-}
-
-/* end of testing_api_trait_fresh_coin.c */
diff --git a/src/exchange-lib/testing_api_trait_json.c b/src/exchange-lib/testing_api_trait_json.c
deleted file mode 100644
index 5f6647fbb..000000000
--- a/src/exchange-lib/testing_api_trait_json.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_json.c
- * @brief offers JSON traits.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_WIRE_DETAILS "wire-details"
-#define TALER_TESTING_TRAIT_EXCHANGE_KEYS "exchange-keys"
-
-/**
- * Obtain serialized exchange keys from @a cmd.
- *
- * @param cmd command to extract the keys from.
- * @param index index number associate with the keys on offer.
- * @param keys[out] where to write the serialized keys.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_exchange_keys
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const json_t **keys)
-{
- return cmd->traits (cmd->cls,
- (const void **) keys,
- TALER_TESTING_TRAIT_EXCHANGE_KEYS,
- index);
-}
-
-
-/**
- * Offer serialized keys in a trait.
- *
- * @param index index number associate with the serial keys
- * on offer.
- * @param keys serialized keys to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_exchange_keys
- (unsigned int index,
- const json_t *keys)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_EXCHANGE_KEYS,
- .ptr = (const json_t *) keys
- };
- return ret;
-}
-
-/**
- * Obtain wire details from @a cmd.
- *
- * @param cmd command to extract the wire details from.
- * @param index index number associate with the wire details
- * on offer; usually zero, as one command sticks to
- * one bank account.
- * @param wire_details[out] where to write the wire details.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_wire_details
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const json_t **wire_details)
-{
- return cmd->traits (cmd->cls,
- (const void **) wire_details,
- TALER_TESTING_TRAIT_WIRE_DETAILS,
- index);
-}
-
-
-/**
- * Offer wire details in a trait.
- *
- * @param index index number associate with the wire details
- * on offer; usually zero, as one command sticks to
- * one bank account.
- * @param wire_details wire details to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_wire_details
- (unsigned int index,
- const json_t *wire_details)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_WIRE_DETAILS,
- .ptr = (const json_t *) wire_details
- };
- return ret;
-}
-
-/* end of testing_api_trait_json.c */
diff --git a/src/exchange-lib/testing_api_trait_key_peer.c b/src/exchange-lib/testing_api_trait_key_peer.c
deleted file mode 100644
index d10623d28..000000000
--- a/src/exchange-lib/testing_api_trait_key_peer.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_key_peer.c
- * @brief traits to offer peer's (private) keys
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_KEY_PEER "key-peer"
-#define TALER_TESTING_TRAIT_KEY_PEER_PUB "key-peer-pub"
-
-/**
- * Obtain a private key from a "peer". Used e.g. to obtain
- * a merchant's priv to sign a /track request.
- *
- * @param cmd command that is offering the key.
- * @param index (tipically zero) which key to return if there
- * are multiple on offer.
- * @param priv[out] set to the key coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_peer_key
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct GNUNET_CRYPTO_EddsaPrivateKey **priv)
-{
- return cmd->traits (cmd->cls,
- (const void **) priv,
- TALER_TESTING_TRAIT_KEY_PEER,
- index);
-}
-
-/**
- * Offer private key, typically done when CMD_1 needs it to
- * sign a request.
- *
- * @param index (tipically zero) which key to return if there are
- * multiple on offer.
- * @param priv which object should be offered.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_peer_key
- (unsigned int index,
- const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_KEY_PEER,
- .ptr = (const void *) priv
- };
- return ret;
-}
-
-
-/**
- * Obtain a public key from a "peer". Used e.g. to obtain
- * a merchant's public key to use backend's API.
- *
- * @param cmd command offering the key.
- * @param index (tipically zero) which key to return if there
- * are multiple on offer.
- * @param pub[out] set to the key coming from @a cmd.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_peer_key_pub
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct GNUNET_CRYPTO_EddsaPublicKey **pub)
-{
- return cmd->traits (cmd->cls,
- (const void **) pub,
- TALER_TESTING_TRAIT_KEY_PEER_PUB,
- index);
-}
-
-/**
- * Offer public key.
- *
- * @param index (tipically zero) which key to return if there
- * are multiple on offer. NOTE: if one key is offered, it
- * is mandatory to set this as zero.
- * @param pub which object should be returned.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_peer_key_pub
- (unsigned int index,
- struct GNUNET_CRYPTO_EddsaPublicKey *pub)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_KEY_PEER_PUB,
- .ptr = (const void *) pub
- };
- return ret;
-}
-
-
-/* end of testing_api_trait_key_peer.c */
diff --git a/src/exchange-lib/testing_api_trait_number.c b/src/exchange-lib/testing_api_trait_number.c
deleted file mode 100644
index ee2e76dbb..000000000
--- a/src/exchange-lib/testing_api_trait_number.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_number.c
- * @brief traits to offer numbers
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_UINT "uint"
-#define TALER_TESTING_TRAIT_UINT64 "uint-64"
-
-/**
- * Obtain a number from @a cmd.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param n[out] set to the number coming from @a cmd.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_uint
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const unsigned int **n)
-{
- return cmd->traits (cmd->cls,
- (const void **) n,
- TALER_TESTING_TRAIT_UINT,
- index);
-}
-
-
-/**
- * Offer a number.
- *
- * @param index the number's index number.
- * @param n the number to offer.
- * @return #GNUNET_OK on success.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uint
- (unsigned int index,
- const unsigned int *n)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_UINT,
- .ptr = (const void *) n
- };
- return ret;
-}
-
-/**
- * Obtain a "number" value from @a cmd, 64-bit version.
- *
- * @param cmd command to extract the number from.
- * @param index the number's index number.
- * @param n[out] set to the number coming from @a cmd.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_uint64
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const uint64_t **n)
-{
- return cmd->traits (cmd->cls,
- (const void **) n,
- TALER_TESTING_TRAIT_UINT64,
- index);
-}
-
-/**
- * Offer number trait, 64-bit version.
- *
- * @param index the number's index number.
- * @param n number to offer.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_uint64
- (unsigned int index,
- const uint64_t *n)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_UINT64,
- .ptr = (const void *) n
- };
- return ret;
-}
-
-/* end of testing_api_trait_number.c */
diff --git a/src/exchange-lib/testing_api_trait_process.c b/src/exchange-lib/testing_api_trait_process.c
deleted file mode 100644
index 449b6536f..000000000
--- a/src/exchange-lib/testing_api_trait_process.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3,
- or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty
- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_process.c
- * @brief trait offering process handles.
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_PROCESS "process"
-
-
-/**
- * Obtain location where a command stores a pointer to a process.
- *
- * @param cmd command to extract trait from.
- * @param index which process to pick if @a cmd
- * has multiple on offer.
- * @param coin_priv[out] set to the address of the pointer to the
- * process.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_process
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- struct GNUNET_OS_Process ***processp)
-{
- return cmd->traits (cmd->cls,
- (const void **) processp,
- TALER_TESTING_TRAIT_PROCESS,
- index);
-}
-
-
-/**
- * Offer location where a command stores a pointer to a process.
- *
- * @param index offered location index number, in case there are
- * multiple on offer.
- * @param processp process location to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_process
- (unsigned int index,
- struct GNUNET_OS_Process **processp)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_PROCESS,
- .ptr = (const void *) processp
- };
-
- return ret;
-}
-
-/* end of testing_api_trait_process.c */
diff --git a/src/exchange-lib/testing_api_trait_reserve_priv.c b/src/exchange-lib/testing_api_trait_reserve_priv.c
deleted file mode 100644
index 4a619d07f..000000000
--- a/src/exchange-lib/testing_api_trait_reserve_priv.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/testing_api_trait_reserve_priv.c
- * @brief implements reserve private key trait
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_RESERVE_PRIVATE_KEY \
- "reserve-private-key"
-
-/**
- * Obtain a reserve private key from a @a cmd.
- *
- * @param cmd command to extract the reserve priv from.
- * @param index reserve priv's index number.
- * @param reserve_priv[out] set to the reserve priv.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_reserve_priv
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct TALER_ReservePrivateKeyP **reserve_priv)
-{
- return cmd->traits (cmd->cls,
- (const void **) reserve_priv,
- TALER_TESTING_TRAIT_RESERVE_PRIVATE_KEY,
- index);
-}
-
-
-/**
- * Offer a reserve private key.
- *
- * @param index reserve priv's index number.
- * @param reserve_priv reserve private key to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_reserve_priv
- (unsigned int index,
- const struct TALER_ReservePrivateKeyP *reserve_priv)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_RESERVE_PRIVATE_KEY,
- .ptr = (const void *) reserve_priv
- };
- return ret;
-}
-
-/* end of testing_api_trait_reserve_priv.c */
diff --git a/src/exchange-lib/testing_api_trait_string.c b/src/exchange-lib/testing_api_trait_string.c
deleted file mode 100644
index 8b8f511a7..000000000
--- a/src/exchange-lib/testing_api_trait_string.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_string.c
- * @brief offers strings traits.
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_CONTRACT_TERMS "contract-terms"
-#define TALER_TESTING_TRAIT_TRANSFER_SUBJECT "transfer-subject"
-#define TALER_TESTING_TRAIT_AMOUNT "amount"
-#define TALER_TESTING_TRAIT_URL "url"
-#define TALER_TESTING_TRAIT_ORDER_ID "order-id"
-#define TALER_TESTING_TRAIT_REJECTED "rejected"
-
-/**
- * Obtain contract terms from @a cmd.
- *
- * @param cmd command to extract the contract terms from.
- * @param index contract terms index number.
- * @param contract_terms[out] where to write the contract
- * terms.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_contract_terms
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const json_t **contract_terms)
-{
- return cmd->traits (cmd->cls,
- (const void **) contract_terms,
- TALER_TESTING_TRAIT_CONTRACT_TERMS,
- index);
-}
-
-/**
- * Offer contract terms.
- *
- * @param index contract terms index number.
- * @param contract_terms contract terms to offer.
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_contract_terms
- (unsigned int index,
- const json_t *contract_terms)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_CONTRACT_TERMS,
- .ptr = (const void *) contract_terms
- };
- return ret;
-}
-
-
-/**
- * Obtain a transfer subject from @a cmd.
- *
- * @param cmd command to extract the subject from.
- * @param index index number associated with the transfer
- * subject to offer.
- * @param transfer_subject[out] where to write the offered
- * transfer subject.
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_transfer_subject
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const char **transfer_subject)
-{
- return cmd->traits (cmd->cls,
- (const void **) transfer_subject,
- TALER_TESTING_TRAIT_TRANSFER_SUBJECT,
- index);
-}
-
-/**
- * Offer transfer subject.
- *
- * @param index index number associated with the transfer
- * subject being offered.
- * @param transfer_subject transfer subject to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_transfer_subject
- (unsigned int index,
- const char *transfer_subject)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_TRANSFER_SUBJECT,
- .ptr = (const void *) transfer_subject
- };
- return ret;
-}
-
-
-/**
- * Obtain an amount from @a cmd.
- *
- * @param cmd command to extract the amount from.
- * @param index which amount is to be picked, in case
- * multiple are offered.
- * @param amount[out] where to write the wire details.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_amount
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const char **amount)
-{
- return cmd->traits (cmd->cls,
- (const void **) amount,
- TALER_TESTING_TRAIT_AMOUNT,
- index);
-}
-
-/**
- * Offer amount in a trait.
- *
- * @param index which amount is to be offered,
- * in case multiple are offered.
- * @param amount the amount to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_amount
- (unsigned int index,
- const char *amount)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_AMOUNT,
- .ptr = (const void *) amount
- };
- return ret;
-}
-
-
-/**
- * Obtain a url from @a cmd.
- *
- * @param cmd command to extract the url from.
- * @param index which url is to be picked, in case
- * multiple are offered.
- * @param url[out] where to write the url.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_url
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const char **url)
-{
- return cmd->traits (cmd->cls,
- (const void **) url,
- TALER_TESTING_TRAIT_URL,
- index);
-}
-
-/**
- * Offer url in a trait.
- *
- * @param index which url is to be picked,
- * in case multiple are offered.
- * @param url the url to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_url
- (unsigned int index,
- const char *url)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_URL,
- .ptr = (const void *) url
- };
- return ret;
-}
-
-
-/**
- * Obtain a order id from @a cmd.
- *
- * @param cmd command to extract the order id from.
- * @param index which order id is to be picked, in case
- * multiple are offered.
- * @param order_id[out] where to write the order id.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_order_id
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const char **order_id)
-{
- return cmd->traits (cmd->cls,
- (const void **) order_id,
- TALER_TESTING_TRAIT_ORDER_ID,
- index);
-}
-
-/**
- * Offer order id in a trait.
- *
- * @param index which order id is to be offered,
- * in case multiple are offered.
- * @param order_id the order id to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_order_id
- (unsigned int index,
- const char *order_id)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_ORDER_ID,
- .ptr = (const void *) order_id
- };
- return ret;
-}
-
-/**
- * Obtain the reference to a "reject" CMD. Usually offered
- * by _rejected_ bank transfers.
- *
- * @param cmd command to extract the reference from.
- * @param index which reference is to be picked, in case
- * multiple are offered.
- * @param rejected_reference[out] where to write the reference.
- *
- * @return #GNUNET_OK on success.
- */
-int
-TALER_TESTING_get_trait_rejected
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const char **rejected_reference)
-{
- return cmd->traits (cmd->cls,
- (const void **) rejected_reference,
- TALER_TESTING_TRAIT_REJECTED,
- index);
-}
-
-/**
- * Offer a "reject" CMD reference.
- *
- * @param index which reference is to be offered,
- * in case multiple are offered.
- * @param rejected_reference the reference to offer.
- *
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_rejected
- (unsigned int index,
- const char *rejected)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_REJECTED,
- .ptr = (const void *) rejected
- };
- return ret;
-}
-
-/* end of testing_api_trait_string.c */
diff --git a/src/exchange-lib/testing_api_trait_wtid.c b/src/exchange-lib/testing_api_trait_wtid.c
deleted file mode 100644
index 672329713..000000000
--- a/src/exchange-lib/testing_api_trait_wtid.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file exchange-lib/testing_api_trait_number.c
- * @brief traits to offer numbers
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-#define TALER_TESTING_TRAIT_WTID "wtid"
-
-/**
- * Obtain a WTID value from @a cmd.
- *
- * @param cmd command to extract trait from
- * @param index which WTID to pick if @a cmd has multiple on
- * offer
- * @param wtid[out] set to the wanted WTID.
- * @return #GNUNET_OK on success
- */
-int
-TALER_TESTING_get_trait_wtid
- (const struct TALER_TESTING_Command *cmd,
- unsigned int index,
- const struct TALER_WireTransferIdentifierRawP **wtid)
-{
- return cmd->traits (cmd->cls,
- (const void **) wtid,
- TALER_TESTING_TRAIT_WTID,
- index);
-}
-
-
-/**
- * Offer a WTID.
- *
- * @param index associate the object with this index
- * @param wtid which object should be returned
- * @return the trait.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_make_trait_wtid
- (unsigned int index,
- const struct TALER_WireTransferIdentifierRawP *wtid)
-{
- struct TALER_TESTING_Trait ret = {
- .index = index,
- .trait_name = TALER_TESTING_TRAIT_WTID,
- .ptr = (const void *) wtid
- };
- return ret;
-}
-
-/* end of testing_api_trait_number.c */
diff --git a/src/exchange-lib/testing_api_traits.c b/src/exchange-lib/testing_api_traits.c
deleted file mode 100644
index aa6c79c83..000000000
--- a/src/exchange-lib/testing_api_traits.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2018 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 3, or
- (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public
- License along with TALER; see the file COPYING. If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file exchange-lib/testing_api_traits.c
- * @brief loop for trait resolution
- * @author Christian Grothoff
- * @author Marcello Stanisci
- */
-#include "platform.h"
-#include "taler_json_lib.h"
-#include <gnunet/gnunet_curl_lib.h>
-#include "exchange_api_handle.h"
-#include "taler_signatures.h"
-#include "taler_testing_lib.h"
-
-
-/**
- * End a trait array. Usually, commands offer several traits,
- * and put them in arrays.
- */
-struct TALER_TESTING_Trait
-TALER_TESTING_trait_end ()
-{
- struct TALER_TESTING_Trait end = {
- .index = 0,
- .trait_name = NULL,
- .ptr = NULL
- };
-
- return end;
-}
-
-/**
- * Pick the chosen trait from the traits array.
- *
- * @param traits the traits array.
- * @param ret where to store the result.
- * @param trait type of the trait to extract.
- * @param index index number of the object to extract.
- * @return #GNUNET_OK if no error occurred, #GNUNET_SYSERR otherwise.
- */
-int
-TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- for (unsigned int i=0; NULL != traits[i].trait_name; i++)
- {
- if ( (0 == strcmp (trait, traits[i].trait_name)) &&
- (index == traits[i].index) )
- {
- *ret = (void *) traits[i].ptr;
- return GNUNET_OK;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Trait %s/%u not found.\n",
- trait, index);
-
- return GNUNET_SYSERR;
-}
-
-/* end of testing_api_traits.c */