summaryrefslogtreecommitdiff
path: root/src/mint-lib
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-03-01 15:35:04 +0100
committerChristian Grothoff <christian@grothoff.org>2016-03-01 15:35:04 +0100
commitb5cba3251053c22bf1df46282f1dd0a4c46f6a38 (patch)
treeb7495c3e47c40c57ff81045a4e43aa07a3b6c7b1 /src/mint-lib
parente406833eab7ca0835f9779abebada94592a85a7e (diff)
downloadexchange-b5cba3251053c22bf1df46282f1dd0a4c46f6a38.tar.gz
exchange-b5cba3251053c22bf1df46282f1dd0a4c46f6a38.tar.bz2
exchange-b5cba3251053c22bf1df46282f1dd0a4c46f6a38.zip
renaming mint->exchange
Diffstat (limited to 'src/mint-lib')
-rw-r--r--src/mint-lib/Makefile.am62
-rw-r--r--src/mint-lib/afl-generate.sh34
-rw-r--r--src/mint-lib/baseline/admin_add_incoming.req7
-rw-r--r--src/mint-lib/baseline/deposit.req8
-rw-r--r--src/mint-lib/baseline/keys.req7
-rw-r--r--src/mint-lib/baseline/refresh_link.req5
-rw-r--r--src/mint-lib/baseline/refresh_melt.req8
-rw-r--r--src/mint-lib/baseline/refresh_reveal.req7
-rw-r--r--src/mint-lib/baseline/reserve_status.req4
-rw-r--r--src/mint-lib/baseline/reserve_withdraw.req7
-rw-r--r--src/mint-lib/baseline/wire.req5
-rw-r--r--src/mint-lib/baseline/wire_sepa.req5
-rw-r--r--src/mint-lib/baseline/wire_test.req5
-rw-r--r--src/mint-lib/mint_api_admin.c254
-rw-r--r--src/mint-lib/mint_api_common.c194
-rw-r--r--src/mint-lib/mint_api_common.h41
-rw-r--r--src/mint-lib/mint_api_context.c537
-rw-r--r--src/mint-lib/mint_api_context.h169
-rw-r--r--src/mint-lib/mint_api_deposit.c569
-rw-r--r--src/mint-lib/mint_api_deposit_wtid.c379
-rw-r--r--src/mint-lib/mint_api_handle.c902
-rw-r--r--src/mint-lib/mint_api_handle.h59
-rw-r--r--src/mint-lib/mint_api_json.c525
-rw-r--r--src/mint-lib/mint_api_json.h352
-rw-r--r--src/mint-lib/mint_api_refresh.c2061
-rw-r--r--src/mint-lib/mint_api_refresh_link.c482
-rw-r--r--src/mint-lib/mint_api_reserve.c930
-rw-r--r--src/mint-lib/mint_api_wire.c620
-rw-r--r--src/mint-lib/mint_api_wire_deposits.c284
-rw-r--r--src/mint-lib/test-mint-home/config/mint-common.conf30
-rw-r--r--src/mint-lib/test-mint-home/config/mint-keyup.conf86
-rw-r--r--src/mint-lib/test-mint-home/master.priv1
-rw-r--r--src/mint-lib/test-mint-home/sepa.json6
-rw-r--r--src/mint-lib/test_mint_api.c2599
34 files changed, 0 insertions, 11244 deletions
diff --git a/src/mint-lib/Makefile.am b/src/mint-lib/Makefile.am
deleted file mode 100644
index 171a42464..000000000
--- a/src/mint-lib/Makefile.am
+++ /dev/null
@@ -1,62 +0,0 @@
-# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
-
-if USE_COVERAGE
- AM_CFLAGS = --coverage -O0
- XLIB = -lgcov
-endif
-
-lib_LTLIBRARIES = \
- libtalermint.la
-
-libtalermint_la_LDFLAGS = \
- -version-info 0:0:0 \
- -no-undefined
-
-libtalermint_la_SOURCES = \
- mint_api_common.c mint_api_common.h \
- mint_api_context.c mint_api_context.h \
- mint_api_json.c mint_api_json.h \
- mint_api_handle.c mint_api_handle.h \
- mint_api_admin.c \
- mint_api_deposit.c \
- mint_api_deposit_wtid.c \
- mint_api_refresh.c \
- mint_api_refresh_link.c \
- mint_api_reserve.c \
- mint_api_wire.c \
- mint_api_wire_deposits.c
-
-libtalermint_la_LIBADD = \
- -lgnunetutil \
- -ljansson \
- $(XLIB)
-
-if HAVE_LIBCURL
-libtalermint_la_LIBADD += -lcurl
-else
-if HAVE_LIBGNURL
-libtalermint_la_LIBADD += -lgnurl
-endif
-endif
-
-check_PROGRAMS = \
- test_mint_api
-
-TESTS = \
- $(check_PROGRAMS)
-
-test_mint_api_SOURCES = \
- test_mint_api.c
-test_mint_api_LDADD = \
- libtalermint.la \
- $(LIBGCRYPT_LIBS) \
- $(top_builddir)/src/util/libtalerutil.la \
- -lgnunetutil \
- -ljansson
-
-EXTRA_DIST = \
- test-mint-home/config/mint-common.conf \
- test-mint-home/master.priv \
- test-mint-home/denomkeys/ \
- test-mint-home/signkeys/
diff --git a/src/mint-lib/afl-generate.sh b/src/mint-lib/afl-generate.sh
deleted file mode 100644
index 4b5051869..000000000
--- a/src/mint-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/mint/afl-tests/ to be run during mint-testing.
-#
-# This script uses American Fuzzy Loop (AFL) to fuzz the mint 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-mint-httpd -f /tmp/afl-input -d test-mint-home/ -C
diff --git a/src/mint-lib/baseline/admin_add_incoming.req b/src/mint-lib/baseline/admin_add_incoming.req
deleted file mode 100644
index 677678b5d..000000000
--- a/src/mint-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/mint-lib/baseline/deposit.req b/src/mint-lib/baseline/deposit.req
deleted file mode 100644
index f50d83e40..000000000
--- a/src/mint-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":"1CMEEFQ5S4QJGGAMVYFV07XQRHQA311CR2MTRNC5M9KZV6ETDV1SY00WJFEV2CG9BXQTEQPZAF8A54C2HX32TZCN20VBGPFPS2Z16B0","merchant_pub":"C36TEXQXFW00170C2EJ66ZR0000CX9VPZNZG00109NX020000000","denom_pub":"51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GT58S2K2HJ16H336C9N8CVK4E9N6H1MADHH61330HHM6N1K8E1H8RVKJH256D1M6E1K8RWKJGSH8S2M6DJ170TK2H266GTK8DSS64RKJDJ26D144DJ474SK0GHQ711MAD9G752M2CJ58S1KJDA570SK2E9G8N23GCJ28S146DHH610K2H1Q8CW3GGA16S146H9G68TKACSQ6914CE1H691K2E9N6RWM8H9P8CWM2H9S8GSK0H9P6D1K6H9G6X0M4C2171144HJ46N334H9J692M4H9M8MR4CCJ46GRKEGA46533CDJ38MV4CH9K892MAH1P8S2K6D9K6N246E256H244G9Q6D346GJ56S23JGHJ690KADHJ8H242H2575132CSM6X1M4G9N6RR48E9H8MVM8E9354520818CMG26C1H60R30C935452081918G2J2G0","transaction_id":1,"refund_deadline":"/Date(0)/","coin_sig":"X16E0DP8C2BJNVNX09G24FFC5GA4W7RN2YXZP9WJTAN9BY6B4GMA39QNYR51XNNEZ3H1J7TP0K9G55JZ8V7WS7CZMD7E64HWYBFWM00"} \ No newline at end of file
diff --git a/src/mint-lib/baseline/keys.req b/src/mint-lib/baseline/keys.req
deleted file mode 100644
index a9503a864..000000000
--- a/src/mint-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/mint-lib/baseline/refresh_link.req b/src/mint-lib/baseline/refresh_link.req
deleted file mode 100644
index acf3dff51..000000000
--- a/src/mint-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/mint-lib/baseline/refresh_melt.req b/src/mint-lib/baseline/refresh_melt.req
deleted file mode 100644
index 98b5b6389..000000000
--- a/src/mint-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/mint-lib/baseline/refresh_reveal.req b/src/mint-lib/baseline/refresh_reveal.req
deleted file mode 100644
index 3fb143960..000000000
--- a/src/mint-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/mint-lib/baseline/reserve_status.req b/src/mint-lib/baseline/reserve_status.req
deleted file mode 100644
index 4f988f669..000000000
--- a/src/mint-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/mint-lib/baseline/reserve_withdraw.req b/src/mint-lib/baseline/reserve_withdraw.req
deleted file mode 100644
index 484950250..000000000
--- a/src/mint-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/mint-lib/baseline/wire.req b/src/mint-lib/baseline/wire.req
deleted file mode 100644
index a4f1d0749..000000000
--- a/src/mint-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/mint-lib/baseline/wire_sepa.req b/src/mint-lib/baseline/wire_sepa.req
deleted file mode 100644
index 80d3d4619..000000000
--- a/src/mint-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/mint-lib/baseline/wire_test.req b/src/mint-lib/baseline/wire_test.req
deleted file mode 100644
index 684352c96..000000000
--- a/src/mint-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/mint-lib/mint_api_admin.c b/src/mint-lib/mint_api_admin.c
deleted file mode 100644
index 641e0690f..000000000
--- a/src/mint-lib/mint_api_admin.c
+++ /dev/null
@@ -1,254 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_admin.c
- * @brief Implementation of the /admin/ requests of the mint's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.h"
-
-
-/**
- * @brief An admin/add/incoming Handle
- */
-struct TALER_MINT_AdminAddIncomingHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * HTTP headers for the request.
- */
- struct curl_slist *headers;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_AdminAddIncomingResultCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
-};
-
-
-/**
- * Function called when we're done processing the
- * HTTP /admin/add/incoming request.
- *
- * @param cls the `struct TALER_MINT_AdminAddIncomingHandle`
- * @param eh the curl request handle
- */
-static void
-handle_admin_add_incoming_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_AdminAddIncomingHandle *aai = cls;
- long response_code;
- json_t *json;
-
- aai->job = NULL;
- json = MAC_download_get_result (&aai->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_FORBIDDEN:
- /* Access denied */
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- aai->cb (aai->cb_cls,
- response_code,
- json);
- json_decref (json);
- TALER_MINT_admin_add_incoming_cancel (aai);
-}
-
-
-/**
- * Notify the mint that we have received an incoming transaction
- * which fills a reserve. Note that this API is an administrative
- * API and thus not accessible to typical mint clients, but only
- * to the operators of the mint.
- *
- * @param mint the mint handle; the mint must be ready to operate
- * @param reserve_pub public key of the reserve
- * @param amount amount that was deposited
- * @param execution_date when did we receive the amount
- * @param wire wire details
- * @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 NULL
- * if the inputs are invalid (i.e. invalid amount).
- * In this case, the callback is not called.
- */
-struct TALER_MINT_AdminAddIncomingHandle *
-TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute execution_date,
- const json_t *wire,
- TALER_MINT_AdminAddIncomingResultCallback res_cb,
- void *res_cb_cls)
-{
- struct TALER_MINT_AdminAddIncomingHandle *aai;
- struct TALER_MINT_Context *ctx;
- json_t *admin_obj;
- CURL *eh;
-
- GNUNET_assert (GNUNET_OK ==
- TALER_round_abs_time (&execution_date));
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- GNUNET_break (0);
- return NULL;
- }
- admin_obj = json_pack ("{s:o, s:o," /* reserve_pub/amount */
- " s:o, s:O}", /* execution_Date/wire */
- "reserve_pub", TALER_json_from_data (reserve_pub,
- sizeof (*reserve_pub)),
- "amount", TALER_json_from_amount (amount),
- "execution_date", TALER_json_from_abs (execution_date),
- "wire", wire);
- aai = GNUNET_new (struct TALER_MINT_AdminAddIncomingHandle);
- aai->mint = mint;
- aai->cb = res_cb;
- aai->cb_cls = res_cb_cls;
- aai->url = MAH_path_to_url (mint, "/admin/add/incoming");
-
- eh = curl_easy_init ();
- GNUNET_assert (NULL != (aai->json_enc =
- json_dumps (admin_obj,
- JSON_COMPACT)));
- json_decref (admin_obj);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- aai->url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- aai->json_enc));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDSIZE,
- strlen (aai->json_enc)));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &aai->db));
- ctx = MAH_handle_to_context (mint);
- aai->job = MAC_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_admin_add_incoming_finished,
- aai);
- return aai;
-}
-
-
-/**
- * Cancel an add incoming. This function cannot be used on a request
- * handle if a response is already served for it.
- *
- * @param aai the admin add incoming request handle
- */
-void
-TALER_MINT_admin_add_incoming_cancel (struct TALER_MINT_AdminAddIncomingHandle *aai)
-{
- if (NULL != aai->job)
- {
- MAC_job_cancel (aai->job);
- aai->job = NULL;
- }
- curl_slist_free_all (aai->headers);
- GNUNET_free_non_null (aai->db.buf);
- GNUNET_free (aai->url);
- GNUNET_free (aai->json_enc);
- GNUNET_free (aai);
-}
-
-
-/* end of mint_api_admin.c */
diff --git a/src/mint-lib/mint_api_common.c b/src/mint-lib/mint_api_common.c
deleted file mode 100644
index faba38c74..000000000
--- a/src/mint-lib/mint_api_common.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- 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 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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_common.c
- * @brief common functions for the mint API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "mint_api_common.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.h"
-
-
-/**
- * Verify a coins transaction history as returned by the mint.
- *
- * @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_MINT_verify_coin_history_ (const char *currency,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- json_t *history,
- struct TALER_Amount *total)
-{
- size_t len;
- size_t off;
-
- 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;
- }
- TALER_amount_get_zero (currency,
- total);
- for (off=0;off<len;off++)
- {
- json_t *transaction;
- struct TALER_Amount amount;
- struct TALER_CoinSpendSignatureP sig;
- void *details;
- size_t details_size;
- const char *type;
- struct MAJ_Specification spec[] = {
- MAJ_spec_amount ("amount",
- &amount),
- MAJ_spec_string ("type",
- &type),
- MAJ_spec_fixed_auto ("signature",
- &sig),
- MAJ_spec_varsize ("details",
- &details,
- &details_size),
- MAJ_spec_end
- };
-
- transaction = json_array_get (history,
- off);
- if (GNUNET_OK !=
- MAJ_parse_json (transaction,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (0 == strcasecmp (type,
- "DEPOSIT"))
- {
- const struct TALER_DepositRequestPS *dr;
- struct TALER_Amount dr_amount;
-
- if (details_size != sizeof (struct TALER_DepositRequestPS))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- dr = (const struct TALER_DepositRequestPS *) details;
- if (details_size != ntohl (dr->purpose.size))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- 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);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
-
- // FIXME: check sig!
- TALER_amount_ntoh (&dr_amount,
- &dr->amount_with_fee);
- if (0 != TALER_amount_cmp (&dr_amount,
- &amount))
- {
- GNUNET_break (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- }
- else if (0 == strcasecmp (type,
- "MELT"))
- {
- const struct TALER_RefreshMeltCoinAffirmationPS *rm;
- struct TALER_Amount rm_amount;
-
- if (details_size != sizeof (struct TALER_RefreshMeltCoinAffirmationPS))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- rm = (const struct TALER_RefreshMeltCoinAffirmationPS *) details;
- if (details_size != ntohl (rm->purpose.size))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- 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);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- TALER_amount_ntoh (&rm_amount,
- &rm->amount_with_fee);
- if (0 != TALER_amount_cmp (&rm_amount,
- &amount))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- }
- else
- {
- /* signature not supported, new version on server? */
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_amount_add (total,
- total,
- &amount))
- {
- /* overflow in history already!? inconceivable! Bad mint! */
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- MAJ_parse_free (spec);
- }
- return GNUNET_OK;
-}
-
-
-/* end of mint_api_common.c */
diff --git a/src/mint-lib/mint_api_common.h b/src/mint-lib/mint_api_common.h
deleted file mode 100644
index 10a202146..000000000
--- a/src/mint-lib/mint_api_common.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- 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 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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_common.h
- * @brief common functions for the mint API
- * @author Christian Grothoff
- */
-#include <jansson.h>
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-
-/**
- * Verify a coins transaction history as returned by the mint.
- *
- * @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_MINT_verify_coin_history_ (const char *currency,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- json_t *history,
- struct TALER_Amount *total);
-
-/* end of mint_api_common.h */
diff --git a/src/mint-lib/mint_api_context.c b/src/mint-lib/mint_api_context.c
deleted file mode 100644
index 2767906b5..000000000
--- a/src/mint-lib/mint_api_context.c
+++ /dev/null
@@ -1,537 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_context.c
- * @brief Implementation of the context part of the mint's HTTP API
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include "taler_mint_service.h"
-#include "mint_api_context.h"
-
-
-/**
- * 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\n", \
- function, __FILE__, __LINE__, curl_easy_strerror (code));
-
-/**
- * Print JSON parsing related error information
- */
-#define JSON_WARN(error) \
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
- "JSON parsing failed at %s:%u: %s (%s)\n", \
- __FILE__, __LINE__, error.text, error.source)
-
-
-/**
- * Failsafe flag. Raised if our constructor fails to initialize
- * the Curl library.
- */
-static int TALER_MINT_curl_fail;
-
-
-/**
- * Jobs are CURL requests running within a `struct TALER_MINT_Context`.
- */
-struct MAC_Job
-{
-
- /**
- * We keep jobs in a DLL.
- */
- struct MAC_Job *next;
-
- /**
- * We keep jobs in a DLL.
- */
- struct MAC_Job *prev;
-
- /**
- * Easy handle of the job.
- */
- CURL *easy_handle;
-
- /**
- * Context this job runs in.
- */
- struct TALER_MINT_Context *ctx;
-
- /**
- * Function to call upon completion.
- */
- MAC_JobCompletionCallback jcc;
-
- /**
- * Closure for @e jcc.
- */
- void *jcc_cls;
-
-};
-
-
-/**
- * Context
- */
-struct TALER_MINT_Context
-{
- /**
- * Curl multi handle
- */
- CURLM *multi;
-
- /**
- * Curl share handle
- */
- CURLSH *share;
-
- /**
- * We keep jobs in a DLL.
- */
- struct MAC_Job *jobs_head;
-
- /**
- * We keep jobs in a DLL.
- */
- struct MAC_Job *jobs_tail;
-
- /**
- * HTTP header "application/json", created once and used
- * for all requests that need it.
- */
- struct curl_slist *json_header;
-
-};
-
-
-/**
- * Initialise this library. This function should be called before using any of
- * the following functions.
- *
- * @return library context
- */
-struct TALER_MINT_Context *
-TALER_MINT_init ()
-{
- struct TALER_MINT_Context *ctx;
- CURLM *multi;
- CURLSH *share;
-
- if (TALER_MINT_curl_fail)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Curl was not initialised properly\n");
- return NULL;
- }
- if (NULL == (multi = curl_multi_init ()))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to create a Curl multi handle\n");
- return NULL;
- }
- if (NULL == (share = curl_share_init ()))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to create a Curl share handle\n");
- return NULL;
- }
- ctx = GNUNET_new (struct TALER_MINT_Context);
- ctx->multi = multi;
- ctx->share = share;
- GNUNET_assert (NULL != (ctx->json_header =
- curl_slist_append (NULL,
- "Content-Type: application/json")));
- return ctx;
-}
-
-
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion. Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh. Applications can
- * instead use #MAC_easy_to_closure to extract the @a jcc_cls argument
- * from a valid @a eh afterwards.
- *
- * This function modifies the CURL handle to add the
- * "Content-Type: application/json" header if @a add_json is set.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will
- * be executed AND cleaned up
- * @param add_json add "application/json" content type header
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- */
-struct MAC_Job *
-MAC_job_add (struct TALER_MINT_Context *ctx,
- CURL *eh,
- int add_json,
- MAC_JobCompletionCallback jcc,
- void *jcc_cls)
-{
- struct MAC_Job *job;
-
- if (GNUNET_YES == add_json)
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_HTTPHEADER,
- ctx->json_header));
-
- job = GNUNET_new (struct MAC_Job);
- job->easy_handle = eh;
- job->ctx = ctx;
- job->jcc = jcc;
- job->jcc_cls = jcc_cls;
- GNUNET_CONTAINER_DLL_insert (ctx->jobs_head,
- ctx->jobs_tail,
- job);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_PRIVATE,
- job));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_SHARE,
- ctx->share));
- GNUNET_assert (CURLM_OK ==
- curl_multi_add_handle (ctx->multi,
- eh));
- return job;
-}
-
-
-/**
- * Obtain the `jcc_cls` argument from an `eh` that was
- * given to #MAC_job_add().
- *
- * @param eh easy handle that was used
- * @return the `jcc_cls` that was given to #MAC_job_add().
- */
-void *
-MAC_easy_to_closure (CURL *eh)
-{
- struct MAC_Job *job;
-
- GNUNET_assert (CURLE_OK ==
- curl_easy_getinfo (eh,
- CURLINFO_PRIVATE,
- (char **) &job));
- return job->jcc_cls;
-}
-
-
-/**
- * Cancel a job. Must only be called before the job completion
- * callback is called for the respective job.
- *
- * @param job job to cancel
- */
-void
-MAC_job_cancel (struct MAC_Job *job)
-{
- struct TALER_MINT_Context *ctx = job->ctx;
-
- GNUNET_CONTAINER_DLL_remove (ctx->jobs_head,
- ctx->jobs_tail,
- job);
- GNUNET_assert (CURLM_OK ==
- curl_multi_remove_handle (ctx->multi,
- job->easy_handle));
- curl_easy_cleanup (job->easy_handle);
- GNUNET_free (job);
-}
-
-
-/**
- * Run the main event loop for the Taler interaction.
- *
- * @param ctx the library context
- */
-void
-TALER_MINT_perform (struct TALER_MINT_Context *ctx)
-{
- CURLMsg *cmsg;
- struct MAC_Job *job;
- int n_running;
- int n_completed;
-
- (void) curl_multi_perform (ctx->multi,
- &n_running);
- while (NULL != (cmsg = curl_multi_info_read (ctx->multi,
- &n_completed)))
- {
- /* Only documented return value is CURLMSG_DONE */
- GNUNET_break (CURLMSG_DONE == cmsg->msg);
- GNUNET_assert (CURLE_OK ==
- curl_easy_getinfo (cmsg->easy_handle,
- CURLINFO_PRIVATE,
- (char **) &job));
- GNUNET_assert (job->ctx == ctx);
- job->jcc (job->jcc_cls,
- cmsg->easy_handle);
- MAC_job_cancel (job);
- }
-}
-
-
-/**
- * Obtain the information for a select() call to wait until
- * #TALER_MINT_perform() is ready again. Note that calling
- * any other TALER_MINT-API may also imply that the library
- * is again ready for #TALER_MINT_perform().
- *
- * Basically, a client should use this API to prepare for select(),
- * then block on select(), then call #TALER_MINT_perform() and then
- * start again until the work with the context is done.
- *
- * This function will NOT zero out the sets and assumes that @a max_fd
- * and @a timeout are already set to minimal applicable values. It is
- * safe to give this API FD-sets and @a max_fd and @a timeout that are
- * already initialized to some other descriptors that need to go into
- * the select() call.
- *
- * @param ctx context to get the event loop information for
- * @param read_fd_set will be set for any pending read operations
- * @param write_fd_set will be set for any pending write operations
- * @param except_fd_set is here because curl_multi_fdset() has this argument
- * @param max_fd set to the highest FD included in any set;
- * if the existing sets have no FDs in it, the initial
- * value should be "-1". (Note that `max_fd + 1` will need
- * to be passed to select().)
- * @param timeout set to the timeout in milliseconds (!); -1 means
- * no timeout (NULL, blocking forever is OK), 0 means to
- * proceed immediately with #TALER_MINT_perform().
- */
-void
-TALER_MINT_get_select_info (struct TALER_MINT_Context *ctx,
- fd_set *read_fd_set,
- fd_set *write_fd_set,
- fd_set *except_fd_set,
- int *max_fd,
- long *timeout)
-{
- long to;
- int m;
-
- m = -1;
- GNUNET_assert (CURLM_OK ==
- curl_multi_fdset (ctx->multi,
- read_fd_set,
- write_fd_set,
- except_fd_set,
- &m));
- to = *timeout;
- *max_fd = GNUNET_MAX (m, *max_fd);
- GNUNET_assert (CURLM_OK ==
- curl_multi_timeout (ctx->multi,
- &to));
-
- /* Only if what we got back from curl is smaller than what we
- already had (-1 == infinity!), then update timeout */
- if ( (to < *timeout) &&
- (-1 != to) )
- *timeout = to;
- if ( (-1 == (*timeout)) &&
- (NULL != ctx->jobs_head) )
- *timeout = to;
-}
-
-
-/**
- * Cleanup library initialisation resources. This function should be called
- * after using this library to cleanup the resources occupied during library's
- * initialisation.
- *
- * @param ctx the library context
- */
-void
-TALER_MINT_fini (struct TALER_MINT_Context *ctx)
-{
- /* all jobs must have been cancelled at this time, assert this */
- GNUNET_assert (NULL == ctx->jobs_head);
- curl_share_cleanup (ctx->share);
- curl_multi_cleanup (ctx->multi);
- curl_slist_free_all (ctx->json_header);
- GNUNET_free (ctx);
-}
-
-
-/**
- * Callback used when downloading the reply to an HTTP request.
- * Just appends all of the data to the `buf` in the
- * `struct MAC_DownloadBuffer` for further processing. The size of
- * the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if
- * the download exceeds this size, we abort with an error.
- *
- * @param bufptr data downloaded via HTTP
- * @param size size of an item in @a bufptr
- * @param nitems number of items in @a bufptr
- * @param cls the `struct KeysRequest`
- * @return number of bytes processed from @a bufptr
- */
-size_t
-MAC_download_cb (char *bufptr,
- size_t size,
- size_t nitems,
- void *cls)
-{
- struct MAC_DownloadBuffer *db = cls;
- size_t msize;
- void *buf;
-
- if (0 == size * nitems)
- {
- /* Nothing (left) to do */
- return 0;
- }
- msize = size * nitems;
- if ( (msize + db->buf_size) >= GNUNET_MAX_MALLOC_CHECKED)
- {
- db->eno = ENOMEM;
- return 0; /* signals an error to curl */
- }
- db->buf = GNUNET_realloc (db->buf,
- db->buf_size + msize);
- buf = db->buf + db->buf_size;
- memcpy (buf, bufptr, msize);
- db->buf_size += msize;
- return msize;
-}
-
-
-/**
- * Obtain information about the final result about the
- * HTTP download. If the download was successful, parses
- * the JSON in the @a db and returns it. Also returns
- * the HTTP @a response_code. If the download failed,
- * the return value is NULL. The response code is set
- * in any case, on download errors to zero.
- *
- * Calling this function also cleans up @a db.
- *
- * @param db download buffer
- * @param eh CURL handle (to get the response code)
- * @param[out] response_code set to the HTTP response code
- * (or zero if we aborted the download, i.e.
- * because the response was too big, or if
- * the JSON we received was malformed).
- * @return NULL if downloading a JSON reply failed
- */
-json_t *
-MAC_download_get_result (struct MAC_DownloadBuffer *db,
- CURL *eh,
- long *response_code)
-{
- json_t *json;
- json_error_t error;
- char *ct;
-
- if ( (CURLE_OK !=
- curl_easy_getinfo (eh,
- CURLINFO_CONTENT_TYPE,
- &ct)) ||
- (NULL == ct) ||
- (0 != strcasecmp (ct,
- "application/json")) )
- {
- /* No content type or explicitly not JSON, refuse to parse
- (but keep response code) */
- if (CURLE_OK !=
- curl_easy_getinfo (eh,
- CURLINFO_RESPONSE_CODE,
- response_code))
- {
- /* unexpected error... */
- GNUNET_break (0);
- *response_code = 0;
- }
- return NULL;
- }
-
- json = NULL;
- if (0 == db->eno)
- {
- json = json_loadb (db->buf,
- db->buf_size,
- JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK,
- &error);
- if (NULL == json)
- {
- JSON_WARN (error);
- *response_code = 0;
- }
- }
- GNUNET_free_non_null (db->buf);
- db->buf = NULL;
- db->buf_size = 0;
- if (NULL != json)
- {
- if (CURLE_OK !=
- curl_easy_getinfo (eh,
- CURLINFO_RESPONSE_CODE,
- response_code))
- {
- /* unexpected error... */
- GNUNET_break (0);
- *response_code = 0;
- }
- }
- return json;
-}
-
-
-/**
- * Initial global setup logic, specifically runs the Curl setup.
- */
-__attribute__ ((constructor))
-void
-TALER_MINT_constructor__ (void)
-{
- CURLcode ret;
-
- if (CURLE_OK != (ret = curl_global_init (CURL_GLOBAL_DEFAULT)))
- {
- CURL_STRERROR (GNUNET_ERROR_TYPE_ERROR,
- "curl_global_init",
- ret);
- TALER_MINT_curl_fail = 1;
- }
-}
-
-
-/**
- * Cleans up after us, specifically runs the Curl cleanup.
- */
-__attribute__ ((destructor))
-void
-TALER_MINT_destructor__ (void)
-{
- if (TALER_MINT_curl_fail)
- return;
- curl_global_cleanup ();
-}
-
-/* end of mint_api_context.c */
diff --git a/src/mint-lib/mint_api_context.h b/src/mint-lib/mint_api_context.h
deleted file mode 100644
index 181a4808f..000000000
--- a/src/mint-lib/mint_api_context.h
+++ /dev/null
@@ -1,169 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_context.h
- * @brief Internal interface to the context part of the mint's HTTP API
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "taler_signatures.h"
-
-
-/**
- * Entry in the context's job queue.
- */
-struct MAC_Job;
-
-/**
- * Function to call upon completion of a job.
- *
- * @param cls closure
- * @param eh original easy handle (for inspection)
- */
-typedef void
-(*MAC_JobCompletionCallback)(void *cls,
- CURL *eh);
-
-
-/**
- * Schedule a CURL request to be executed and call the given @a jcc
- * upon its completion. Note that the context will make use of the
- * CURLOPT_PRIVATE facility of the CURL @a eh. Applications can
- * instead use #MAC_easy_to_closure to extract the @a jcc_cls argument
- * from a valid @a eh afterwards.
- *
- * This function modifies the CURL handle to add the
- * "Content-Type: application/json" header if @a add_json is set.
- *
- * @param ctx context to execute the job in
- * @param eh curl easy handle for the request, will
- * be executed AND cleaned up
- * @param add_json add "application/json" content type header
- * @param jcc callback to invoke upon completion
- * @param jcc_cls closure for @a jcc
- */
-struct MAC_Job *
-MAC_job_add (struct TALER_MINT_Context *ctx,
- CURL *eh,
- int add_json,
- MAC_JobCompletionCallback jcc,
- void *jcc_cls);
-
-
-/**
- * Obtain the `jcc_cls` argument from an `eh` that was
- * given to #MAC_job_add().
- *
- * @param eh easy handle that was used
- * @return the `jcc_cls` that was given to #MAC_job_add().
- */
-void *
-MAC_easy_to_closure (CURL *eh);
-
-
-/**
- * Cancel a job. Must only be called before the job completion
- * callback is called for the respective job.
- *
- * @param job job to cancel
- */
-void
-MAC_job_cancel (struct MAC_Job *job);
-
-
-/**
- * @brief Buffer data structure we use to buffer the HTTP download
- * before giving it to the JSON parser.
- */
-struct MAC_DownloadBuffer
-{
-
- /**
- * Download buffer
- */
- void *buf;
-
- /**
- * The size of the download buffer
- */
- size_t buf_size;
-
- /**
- * Error code (based on libc errno) if we failed to download
- * (i.e. response too large).
- */
- int eno;
-
-};
-
-
-/**
- * Callback used when downloading the reply to an HTTP request.
- * Just appends all of the data to the `buf` in the
- * `struct MAC_DownloadBuffer` for further processing. The size of
- * the download is limited to #GNUNET_MAX_MALLOC_CHECKED, if
- * the download exceeds this size, we abort with an error.
- *
- * Should be used by the various routines as the
- * CURLOPT_WRITEFUNCTION. A `struct MAC_DownloadBuffer` needs to be
- * passed to the CURLOPT_WRITEDATA.
- *
- * Afterwards, `eno` needs to be checked to ensure that the download
- * completed correctly.
- *
- * @param bufptr data downloaded via HTTP
- * @param size size of an item in @a bufptr
- * @param nitems number of items in @a bufptr
- * @param cls the `struct KeysRequest`
- * @return number of bytes processed from @a bufptr
- */
-size_t
-MAC_download_cb (char *bufptr,
- size_t size,
- size_t nitems,
- void *cls);
-
-
-/**
- * Obtain information about the final result about the
- * HTTP download. If the download was successful, parses
- * the JSON in the @a db and returns it. Also returns
- * the HTTP @a response_code. If the download failed,
- * the return value is NULL. The response code is set
- * in any case, on download errors to zero.
- *
- * Calling this function also cleans up @a db.
- *
- * @param db download buffer
- * @param eh CURL handle (to get the response code)
- * @param[out] response_code set to the HTTP response code
- * (or zero if we aborted the download, i.e.
- * because the response was too big, or if
- * the JSON we received was malformed).
- * @return NULL if downloading a JSON reply failed
- */
-json_t *
-MAC_download_get_result (struct MAC_DownloadBuffer *db,
- CURL *eh,
- long *response_code);
-
-
-/* end of mint_api_context.h */
diff --git a/src/mint-lib/mint_api_deposit.c b/src/mint-lib/mint_api_deposit.c
deleted file mode 100644
index 400372925..000000000
--- a/src/mint-lib/mint_api_deposit.c
+++ /dev/null
@@ -1,569 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_deposit.c
- * @brief Implementation of the /deposit request of the mint's HTTP API
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "mint_api_common.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.h"
-
-
-/**
- * @brief A Deposit Handle
- */
-struct TALER_MINT_DepositHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_DepositResultCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
- /**
- * Information the mint 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;
-
-};
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * from the mint is valid.
- *
- * @param dh deposit handle
- * @param json json reply with the signature
- * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
- */
-static int
-verify_deposit_signature_ok (const struct TALER_MINT_DepositHandle *dh,
- json_t *json)
-{
- struct TALER_MintSignatureP mint_sig;
- struct TALER_MintPublicKeyP mint_pub;
- const struct TALER_MINT_Keys *key_state;
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("sig", &mint_sig),
- MAJ_spec_fixed_auto ("pub", &mint_pub),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- key_state = TALER_MINT_get_keys (dh->mint);
- if (GNUNET_OK !=
- TALER_MINT_test_signing_key (key_state,
- &mint_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_CONFIRM_DEPOSIT,
- &dh->depconf.purpose,
- &mint_sig.eddsa_signature,
- &mint_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Verify that the signatures on the "403 FORBIDDEN" response from the
- * mint 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_MINT_DepositHandle *dh,
- json_t *json)
-{
- json_t *history;
- struct TALER_Amount total;
-
- history = json_object_get (json,
- "history");
- if (GNUNET_OK !=
- TALER_MINT_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_MINT_DepositHandle`
- * @param eh the curl request handle
- */
-static void
-handle_deposit_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_DepositHandle *dh = cls;
- long response_code;
- json_t *json;
-
- dh->job = NULL;
- json = MAC_download_get_result (&dh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- verify_deposit_signature_ok (dh,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint 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,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- dh->cb (dh->cb_cls,
- response_code,
- json);
- json_decref (json);
- TALER_MINT_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 hash of the contact of the merchant with the customer (further details are never disclosed to the mint)
- * @param coin_pub coin’s public key
- * @param denom_pub denomination key with which the coin is signed
- * @param denom_sig mint’s unblinded signature of the coin
- * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the mint
- * @param transaction_id transaction id for the transaction between merchant and customer
- * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests)
- * @param refund_deadline date until which the merchant can issue a refund to the customer via the mint (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_MINT_DenomPublicKey *dki,
- const struct TALER_Amount *amount,
- const struct GNUNET_HashCode *h_wire,
- const struct GNUNET_HashCode *h_contract,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_DenominationSignature *denom_sig,
- const struct TALER_DenominationPublicKey *denom_pub,
- struct GNUNET_TIME_Absolute timestamp,
- uint64_t transaction_id,
- 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 = *h_contract;
- dr.h_wire = *h_wire;
- dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
- dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
- dr.transaction_id = GNUNET_htonll (transaction_id);
- 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))
- {
- TALER_LOG_WARNING ("Invalid coin signature on /deposit request\n");
- {
- char *s;
- s = TALER_amount_to_string (amount);
- TALER_LOG_DEBUG ("... amount_with_fee was %s\n", s);
- GNUNET_free (s);
- s = TALER_amount_to_string (&dki->fee_deposit);
- TALER_LOG_DEBUG ("... deposit_fee was %s\n", s);
- GNUNET_free (s);
- }
-
- 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))
- {
- TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
- return GNUNET_SYSERR;
- }
- if (0 < TALER_amount_cmp (&dki->fee_deposit,
- amount))
- {
- TALER_LOG_WARNING ("Deposit amount smaller than fee\n");
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Submit a deposit permission to the mint and get the mint'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 mint'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 mint 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 mint and instead return NULL.
- *
- * @param mint the mint handle; the mint must be ready to operate
- * @param amount the amount to be deposited
- * @param wire_deadline date until which the merchant would like the mint to settle the balance (advisory, the mint cannot be
- * forced to settle in the past or upon very short notice, but of course a well-behaved mint will limit aggregation based on the advice received)
- * @param wire_details the merchant’s account details, in a format supported by the mint
- * @param h_contract hash of the contact of the merchant with the customer (further details are never disclosed to the mint)
- * @param coin_pub coin’s public key
- * @param denom_pub denomination key with which the coin is signed
- * @param denom_sig mint’s unblinded signature of the coin
- * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the mint
- * @param transaction_id transaction id for the transaction between merchant and customer
- * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests)
- * @param refund_deadline date until which the merchant can issue a refund to the customer via the mint (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.
- * @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_MINT_DepositHandle *
-TALER_MINT_deposit (struct TALER_MINT_Handle *mint,
- const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute wire_deadline,
- json_t *wire_details,
- const struct GNUNET_HashCode *h_contract,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_DenominationSignature *denom_sig,
- const struct TALER_DenominationPublicKey *denom_pub,
- struct GNUNET_TIME_Absolute timestamp,
- uint64_t transaction_id,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- struct GNUNET_TIME_Absolute refund_deadline,
- const struct TALER_CoinSpendSignatureP *coin_sig,
- TALER_MINT_DepositResultCallback cb,
- void *cb_cls)
-{
- const struct TALER_MINT_Keys *key_state;
- const struct TALER_MINT_DenomPublicKey *dki;
- struct TALER_MINT_DepositHandle *dh;
- struct TALER_MINT_Context *ctx;
- json_t *deposit_obj;
- CURL *eh;
- struct GNUNET_HashCode h_wire;
- struct TALER_Amount amount_without_fee;
-
- (void) TALER_round_abs_time (&wire_deadline);
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- GNUNET_break (0);
- return NULL;
- }
- /* initialize h_wire */
- if (GNUNET_OK !=
- TALER_hash_json (wire_details,
- &h_wire))
- {
- GNUNET_break (0);
- return NULL;
- }
- key_state = TALER_MINT_get_keys (mint);
- dki = TALER_MINT_get_denomination_key (key_state,
- denom_pub);
- if (NULL == dki)
- {
- TALER_LOG_WARNING ("Denomination key unknown to mint\n");
- return NULL;
- }
- if (GNUNET_SYSERR ==
- TALER_amount_subtract (&amount_without_fee,
- amount,
- &dki->fee_deposit))
- {
- GNUNET_break (0);
- return NULL;
- }
-
- if (GNUNET_OK !=
- verify_signatures (dki,
- amount,
- &h_wire,
- h_contract,
- coin_pub,
- denom_sig,
- denom_pub,
- timestamp,
- transaction_id,
- 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 */
- " s:o, s:o," /* coin_pub, denom_pub */
- " s:o, s:o," /* ub_sig, timestamp */
- " s:I, s:o," /* transaction id, merchant_pub */
- " s:o, s:o," /* refund_deadline, wire_deadline */
- " s:o}", /* coin_sig */
- "f", TALER_json_from_amount (amount),
- "wire", wire_details,
- "H_wire", TALER_json_from_data (&h_wire,
- sizeof (h_wire)),
- "H_contract", TALER_json_from_data (h_contract,
- sizeof (struct GNUNET_HashCode)),
- "coin_pub", TALER_json_from_data (coin_pub,
- sizeof (*coin_pub)),
- "denom_pub", TALER_json_from_rsa_public_key (denom_pub->rsa_public_key),
- "ub_sig", TALER_json_from_rsa_signature (denom_sig->rsa_signature),
- "timestamp", TALER_json_from_abs (timestamp),
- "transaction_id", (json_int_t) transaction_id,
- "merchant_pub", TALER_json_from_data (merchant_pub,
- sizeof (*merchant_pub)),
- "refund_deadline", TALER_json_from_abs (refund_deadline),
- "edate", TALER_json_from_abs (wire_deadline),
- "coin_sig", TALER_json_from_data (coin_sig,
- sizeof (*coin_sig))
- );
-
- dh = GNUNET_new (struct TALER_MINT_DepositHandle);
- dh->mint = mint;
- dh->cb = cb;
- dh->cb_cls = cb_cls;
- dh->url = MAH_path_to_url (mint, "/deposit");
- dh->depconf.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
- dh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_DEPOSIT);
- dh->depconf.h_contract = *h_contract;
- dh->depconf.h_wire = h_wire;
- dh->depconf.transaction_id = GNUNET_htonll (transaction_id);
- 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 = curl_easy_init ();
- 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_URL,
- 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)));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &dh->db));
- ctx = MAH_handle_to_context (mint);
- dh->job = MAC_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_MINT_deposit_cancel (struct TALER_MINT_DepositHandle *deposit)
-{
- if (NULL != deposit->job)
- {
- MAC_job_cancel (deposit->job);
- deposit->job = NULL;
- }
- GNUNET_free_non_null (deposit->db.buf);
- GNUNET_free (deposit->url);
- GNUNET_free (deposit->json_enc);
- GNUNET_free (deposit);
-}
-
-
-/* end of mint_api_deposit.c */
diff --git a/src/mint-lib/mint_api_deposit_wtid.c b/src/mint-lib/mint_api_deposit_wtid.c
deleted file mode 100644
index d29f406e3..000000000
--- a/src/mint-lib/mint_api_deposit_wtid.c
+++ /dev/null
@@ -1,379 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_deposit_wtid.c
- * @brief Implementation of the /deposit/wtid request of the mint's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "mint_api_common.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.h"
-
-
-/**
- * @brief A Deposit Wtid Handle
- */
-struct TALER_MINT_DepositWtidHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_DepositWtidCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
- /**
- * Information the mint 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 mint is valid.
- *
- * @param dwh deposit wtid handle
- * @param json json reply with the signature
- * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
- */
-static int
-verify_deposit_wtid_signature_ok (const struct TALER_MINT_DepositWtidHandle *dwh,
- json_t *json)
-{
- struct TALER_MintSignatureP mint_sig;
- struct TALER_MintPublicKeyP mint_pub;
- const struct TALER_MINT_Keys *key_state;
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("mint_sig", &mint_sig),
- MAJ_spec_fixed_auto ("mint_pub", &mint_pub),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- key_state = TALER_MINT_get_keys (dwh->mint);
- if (GNUNET_OK !=
- TALER_MINT_test_signing_key (key_state,
- &mint_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_CONFIRM_WIRE,
- &dwh->depconf.purpose,
- &mint_sig.eddsa_signature,
- &mint_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /deposit/wtid request.
- *
- * @param cls the `struct TALER_MINT_DepositWtidHandle`
- * @param eh the curl request handle
- */
-static void
-handle_deposit_wtid_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_DepositWtidHandle *dwh = cls;
- long response_code;
- json_t *json;
- 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;
-
- dwh->job = NULL;
- json = MAC_download_get_result (&dwh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("wtid", &dwh->depconf.wtid),
- MAJ_spec_absolute_time ("execution_time", &execution_time),
- MAJ_spec_amount ("coin_contribution", &coin_contribution_s),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- 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,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- }
- break;
- case MHD_HTTP_ACCEPTED:
- {
- /* Transaction known, but not executed yet */
- struct MAJ_Specification spec[] = {
- MAJ_spec_absolute_time ("execution_time", &execution_time),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, mint 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:
- /* Mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- dwh->cb (dwh->cb_cls,
- response_code,
- json,
- wtid,
- execution_time,
- coin_contribution);
- json_decref (json);
- TALER_MINT_deposit_wtid_cancel (dwh);
-}
-
-
-/**
- * Obtain wire transfer details about an existing deposit operation.
- *
- * @param mint the mint to query
- * @param merchant_priv the merchant's private key
- * @param h_wire hash of merchant's wire transfer details
- * @param h_contract hash of the contract
- * @param coin_pub public key of the coin
- * @param transaction_id transaction identifier
- * @param cb function to call with the result
- * @param cb_cls closure for @a cb
- * @return handle to abort request
- */
-struct TALER_MINT_DepositWtidHandle *
-TALER_MINT_deposit_wtid (struct TALER_MINT_Handle *mint,
- const struct TALER_MerchantPrivateKeyP *merchant_priv,
- const struct GNUNET_HashCode *h_wire,
- const struct GNUNET_HashCode *h_contract,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- uint64_t transaction_id,
- TALER_MINT_DepositWtidCallback cb,
- void *cb_cls)
-{
- struct TALER_DepositTrackPS dtp;
- struct TALER_MerchantSignatureP merchant_sig;
- struct TALER_MINT_DepositWtidHandle *dwh;
- struct TALER_MINT_Context *ctx;
- json_t *deposit_wtid_obj;
- CURL *eh;
-
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- GNUNET_break (0);
- return NULL;
- }
- dtp.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_DEPOSIT_WTID);
- dtp.purpose.size = htonl (sizeof (dtp));
- dtp.h_contract = *h_contract;
- dtp.h_wire = *h_wire;
- dtp.transaction_id = GNUNET_htonll (transaction_id);
- 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 */
- " s:o, s:I," /* coin_pub, transaction_id */
- " s:o, s:o}", /* merchant_pub, merchant_sig */
- "H_wire", TALER_json_from_data (h_wire,
- sizeof (struct GNUNET_HashCode)),
- "H_contract", TALER_json_from_data (h_contract,
- sizeof (struct GNUNET_HashCode)),
- "coin_pub", TALER_json_from_data (coin_pub,
- sizeof (*coin_pub)),
- "transaction_id", (json_int_t) transaction_id,
- "merchant_pub", TALER_json_from_data (&dtp.merchant,
- sizeof (struct TALER_MerchantPublicKeyP)),
- "merchant_sig", TALER_json_from_data (&merchant_sig,
- sizeof (merchant_sig)));
-
- dwh = GNUNET_new (struct TALER_MINT_DepositWtidHandle);
- dwh->mint = mint;
- dwh->cb = cb;
- dwh->cb_cls = cb_cls;
- dwh->url = MAH_path_to_url (mint, "/deposit/wtid");
- dwh->depconf.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
- dwh->depconf.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_WIRE);
- dwh->depconf.h_wire = *h_wire;
- dwh->depconf.h_contract = *h_contract;
- dwh->depconf.coin_pub = *coin_pub;
- dwh->depconf.transaction_id = GNUNET_htonll (transaction_id);
-
- eh = curl_easy_init ();
- 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_URL,
- dwh->url));
- 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)));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &dwh->db));
- ctx = MAH_handle_to_context (mint);
- dwh->job = MAC_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_MINT_deposit_wtid_cancel (struct TALER_MINT_DepositWtidHandle *dwh)
-{
- if (NULL != dwh->job)
- {
- MAC_job_cancel (dwh->job);
- dwh->job = NULL;
- }
- GNUNET_free_non_null (dwh->db.buf);
- GNUNET_free (dwh->url);
- GNUNET_free (dwh->json_enc);
- GNUNET_free (dwh);
-}
-
-
-/* end of mint_api_deposit_wtid.c */
diff --git a/src/mint-lib/mint_api_handle.c b/src/mint-lib/mint_api_handle.c
deleted file mode 100644
index ef26cd838..000000000
--- a/src/mint-lib/mint_api_handle.c
+++ /dev/null
@@ -1,902 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_handle.c
- * @brief Implementation of the "handle" component of the mint's HTTP API
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <gnunet/gnunet_util_lib.h>
-#include <microhttpd.h>
-#include "taler_mint_service.h"
-#include "taler_signatures.h"
-#include "mint_api_context.h"
-#include "mint_api_json.h"
-#include "mint_api_handle.h"
-
-
-/**
- * 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_MINT_Handle`
- */
-enum MintHandleState
-{
- /**
- * Just allocated.
- */
- MHS_INIT = 0,
-
- /**
- * Obtained the mint'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 mint.
- */
-struct KeysRequest;
-
-
-/**
- * Handle to the mint
- */
-struct TALER_MINT_Handle
-{
- /**
- * The context of this handle
- */
- struct TALER_MINT_Context *ctx;
-
- /**
- * The URL of the mint (i.e. "http://mint.taler.net/")
- */
- char *url;
-
- /**
- * Function to call with the mint's certification data,
- * NULL if this has already been done.
- */
- TALER_MINT_CertificationCallback cert_cb;
-
- /**
- * Closure to pass to @e cert_cb.
- */
- void *cert_cb_cls;
-
- /**
- * Data for the request to get the /keys of a mint,
- * NULL once we are past stage #MHS_INIT.
- */
- struct KeysRequest *kr;
-
- /**
- * Key data of the mint, only valid if
- * @e handshake_complete is past stage #MHS_CERT.
- */
- struct TALER_MINT_Keys key_data;
-
- /**
- * Stage of the mint's initialization routines.
- */
- enum MintHandleState state;
-
-};
-
-
-/* ***************** Internal /keys fetching ************* */
-
-/**
- * Data for the request to get the /keys of a mint.
- */
-struct KeysRequest
-{
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this handle
- */
- char *url;
-
- /**
- * Entry for this request with the `struct TALER_MINT_Context`.
- */
- struct MAC_Job *job;
-
- /**
- * Data structure for the download.
- */
- struct MAC_DownloadBuffer db;
-
-};
-
-
-/**
- * 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_non_null (kr->db.buf);
- GNUNET_free (kr->url);
- GNUNET_free (kr);
-}
-
-
-#define EXITIF(cond) \
- do { \
- if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
- } while (0)
-
-
-/**
- * Parse a mint's signing key encoded in JSON.
- *
- * @param[out] sign_key where to return the result
- * @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_MINT_SigningPublicKey *sign_key,
- json_t *sign_key_obj,
- const struct TALER_MasterPublicKeyP *master_key)
-{
- struct TALER_MintSigningKeyValidityPS sign_key_issue;
- struct GNUNET_CRYPTO_EddsaSignature sig;
- struct GNUNET_TIME_Absolute valid_from;
- struct GNUNET_TIME_Absolute valid_until;
- struct GNUNET_TIME_Absolute valid_legal;
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("master_sig",
- &sig),
- MAJ_spec_fixed_auto ("key",
- &sign_key_issue.signkey_pub),
- MAJ_spec_absolute_time ("stamp_start",
- &valid_from),
- MAJ_spec_absolute_time ("stamp_expire",
- &valid_until),
- MAJ_spec_absolute_time ("stamp_end",
- &valid_legal),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (sign_key_obj,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- sign_key_issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY);
- sign_key_issue.purpose.size =
- htonl (sizeof (struct TALER_MintSigningKeyValidityPS)
- - offsetof (struct TALER_MintSigningKeyValidityPS,
- purpose));
- sign_key_issue.master_public_key = *master_key;
- sign_key_issue.start = GNUNET_TIME_absolute_hton (valid_from);
- sign_key_issue.expire = GNUNET_TIME_absolute_hton (valid_until);
- sign_key_issue.end = GNUNET_TIME_absolute_hton (valid_legal);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY,
- &sign_key_issue.purpose,
- &sig,
- &master_key->eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- sign_key->valid_from = valid_from;
- sign_key->valid_until = valid_until;
- sign_key->key = sign_key_issue.signkey_pub;
- return GNUNET_OK;
-}
-
-
-/**
- * Parse a mint's denomination key encoded in JSON.
- *
- * @param[out] denom_key where to return the result
- * @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_MINT_DenomPublicKey *denom_key,
- json_t *denom_key_obj,
- struct TALER_MasterPublicKeyP *master_key,
- struct GNUNET_HashContext *hash_context)
-{
- struct GNUNET_TIME_Absolute valid_from;
- struct GNUNET_TIME_Absolute withdraw_valid_until;
- struct GNUNET_TIME_Absolute deposit_valid_until;
- struct GNUNET_TIME_Absolute expire_legal;
- struct TALER_Amount value;
- struct TALER_Amount fee_withdraw;
- struct TALER_Amount fee_deposit;
- struct TALER_Amount fee_refresh;
- struct TALER_DenominationKeyValidityPS denom_key_issue;
- struct GNUNET_CRYPTO_rsa_PublicKey *pk;
- struct GNUNET_CRYPTO_EddsaSignature sig;
-
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("master_sig",
- &sig),
- MAJ_spec_absolute_time ("stamp_expire_deposit",
- &deposit_valid_until),
- MAJ_spec_absolute_time ("stamp_expire_withdraw",
- &withdraw_valid_until),
- MAJ_spec_absolute_time ("stamp_start",
- &valid_from),
- MAJ_spec_absolute_time ("stamp_expire_legal",
- &expire_legal),
- MAJ_spec_amount ("value",
- &value),
- MAJ_spec_amount ("fee_withdraw",
- &fee_withdraw),
- MAJ_spec_amount ("fee_deposit",
- &fee_deposit),
- MAJ_spec_amount ("fee_refresh",
- &fee_refresh),
- MAJ_spec_rsa_public_key ("denom_pub",
- &pk),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (denom_key_obj,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- memset (&denom_key_issue, 0, sizeof (denom_key_issue));
- GNUNET_CRYPTO_rsa_public_key_hash (pk,
- &denom_key_issue.denom_hash);
- 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.start = GNUNET_TIME_absolute_hton (valid_from);
- denom_key_issue.expire_withdraw = GNUNET_TIME_absolute_hton (withdraw_valid_until);
- denom_key_issue.expire_spend = GNUNET_TIME_absolute_hton (deposit_valid_until);
- denom_key_issue.expire_legal = GNUNET_TIME_absolute_hton (expire_legal);
- TALER_amount_hton (&denom_key_issue.value,
- &value);
- TALER_amount_hton (&denom_key_issue.fee_withdraw,
- &fee_withdraw);
- TALER_amount_hton (&denom_key_issue.fee_deposit,
- &fee_deposit);
- TALER_amount_hton (&denom_key_issue.fee_refresh,
- &fee_refresh);
- EXITIF (GNUNET_SYSERR ==
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY,
- &denom_key_issue.purpose,
- &sig,
- &master_key->eddsa_pub));
- GNUNET_CRYPTO_hash_context_read (hash_context,
- &denom_key_issue.denom_hash,
- sizeof (struct GNUNET_HashCode));
- denom_key->key.rsa_public_key = pk;
- denom_key->h_key = denom_key_issue.denom_hash;
- denom_key->valid_from = valid_from;
- denom_key->withdraw_valid_until = withdraw_valid_until;
- denom_key->deposit_valid_until = deposit_valid_until;
- denom_key->expire_legal = expire_legal;
- denom_key->value = value;
- denom_key->fee_withdraw = fee_withdraw;
- denom_key->fee_deposit = fee_deposit;
- denom_key->fee_refresh = fee_refresh;
- return GNUNET_OK;
-
- EXITIF_exit:
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Parse a mint's auditor information encoded in JSON.
- *
- * @param[out] auditor where to return the result
- * @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_MINT_AuditorInformation *auditor,
- json_t *auditor_obj,
- const struct TALER_MINT_Keys *key_data)
-{
- json_t *keys;
- json_t *key;
- unsigned int len;
- unsigned int off;
- unsigned int i;
- struct TALER_MintKeyValidityPS kv;
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("auditor_pub",
- &auditor->auditor_pub),
- MAJ_spec_json ("denomination_keys",
- &keys),
- MAJ_spec_end
- };
-
- auditor->auditor_url = NULL; /* #3987 */
- if (GNUNET_OK !=
- MAJ_parse_json (auditor_obj,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- kv.purpose.purpose = htonl (TALER_SIGNATURE_AUDITOR_MINT_KEYS);
- kv.purpose.size = htonl (sizeof (struct TALER_MintKeyValidityPS));
- kv.master = key_data->master_pub;
- len = json_array_size (keys);
- auditor->denom_keys = GNUNET_new_array (len,
- const struct TALER_MINT_DenomPublicKey *);
- i = 0;
- off = 0;
- json_array_foreach (keys, i, key) {
- struct TALER_AuditorSignatureP auditor_sig;
- struct GNUNET_HashCode denom_h;
- const struct TALER_MINT_DenomPublicKey *dk;
- unsigned int j;
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("denom_pub_h",
- &denom_h),
- MAJ_spec_fixed_auto ("auditor_sig",
- &auditor_sig),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (key,
- spec))
- {
- GNUNET_break_op (0);
- continue;
- }
- dk = NULL;
- for (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];
- break;
- }
- }
- if (NULL == dk)
- {
- GNUNET_break_op (0);
- continue;
- }
- kv.start = GNUNET_TIME_absolute_hton (dk->valid_from);
- kv.expire_withdraw = GNUNET_TIME_absolute_hton (dk->withdraw_valid_until);
- kv.expire_spend = GNUNET_TIME_absolute_hton (dk->deposit_valid_until);
- 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);
- kv.denom_hash = dk->h_key;
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_AUDITOR_MINT_KEYS,
- &kv.purpose,
- &auditor_sig.eddsa_sig,
- &auditor->auditor_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- continue;
- }
- auditor->denom_keys[off] = dk;
- off++;
- }
- auditor->num_denom_keys = off;
- 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[out] key_data where to store the results we decoded
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (malformed JSON)
- */
-static int
-decode_keys_json (json_t *resp_obj,
- struct TALER_MINT_Keys *key_data)
-{
- struct GNUNET_TIME_Absolute list_issue_date;
- struct TALER_MintSignatureP sig;
- struct TALER_MintKeySetPS ks;
- struct GNUNET_HashContext *hash_context;
- struct TALER_MintPublicKeyP pub;
-
- if (JSON_OBJECT != json_typeof (resp_obj))
- return GNUNET_SYSERR;
-
- hash_context = GNUNET_CRYPTO_hash_context_start ();
- /* parse the master public key and issue date of the response */
- {
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("master_public_key",
- &key_data->master_pub),
- MAJ_spec_fixed_auto ("eddsa_sig",
- &sig),
- MAJ_spec_fixed_auto ("eddsa_pub",
- &pub),
- MAJ_spec_absolute_time ("list_issue_date",
- &list_issue_date),
- MAJ_spec_end
- };
-
- EXITIF (GNUNET_OK !=
- MAJ_parse_json (resp_obj,
- spec));
- }
-
- /* 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_MINT_SigningPublicKey);
- index = 0;
- json_array_foreach (sign_keys_array, index, sign_key_obj) {
- EXITIF (GNUNET_SYSERR ==
- parse_json_signkey (&key_data->sign_keys[index],
- sign_key_obj,
- &key_data->master_pub));
- }
- }
-
- /* parse the denomination keys */
- {
- 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));
- EXITIF (0 == (key_data->num_denom_keys = json_array_size (denom_keys_array)));
- key_data->denom_keys = GNUNET_new_array (key_data->num_denom_keys,
- struct TALER_MINT_DenomPublicKey);
- index = 0;
- json_array_foreach (denom_keys_array, index, denom_key_obj) {
- EXITIF (GNUNET_SYSERR ==
- parse_json_denomkey (&key_data->denom_keys[index],
- denom_key_obj,
- &key_data->master_pub,
- hash_context));
- }
- }
-
- /* parse the auditor information */
- {
- json_t *auditors_array;
- json_t *auditor_info;
- unsigned int len;
- unsigned int index;
-
- EXITIF (NULL == (auditors_array =
- json_object_get (resp_obj, "auditors")));
- EXITIF (JSON_ARRAY != json_typeof (auditors_array));
- len = json_array_size (auditors_array);
- if (0 != len)
- {
- key_data->auditors = GNUNET_new_array (len,
- struct TALER_MINT_AuditorInformation);
- index = 0;
- json_array_foreach (auditors_array, index, auditor_info) {
- EXITIF (GNUNET_SYSERR ==
- parse_json_auditor (&key_data->auditors[index],
- auditor_info,
- key_data));
- }
- }
- }
-
- /* Validate signature... */
- ks.purpose.size = htonl (sizeof (ks));
- ks.purpose.purpose = htonl (TALER_SIGNATURE_MINT_KEY_SET);
- ks.list_issue_date = GNUNET_TIME_absolute_hton (list_issue_date);
- GNUNET_CRYPTO_hash_context_finish (hash_context,
- &ks.hc);
- hash_context = NULL;
- EXITIF (GNUNET_OK !=
- TALER_MINT_test_signing_key (key_data,
- &pub));
- EXITIF (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_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;
-}
-
-
-/**
- * Callback used when downloading the reply to a /keys request
- * is complete.
- *
- * @param cls the `struct KeysRequest`
- * @param eh easy handle of the original request
- */
-static void
-keys_completed_cb (void *cls,
- CURL *eh)
-{
- struct KeysRequest *kr = cls;
- struct TALER_MINT_Handle *mint = kr->mint;
- json_t *resp_obj;
- long response_code;
- TALER_MINT_CertificationCallback cb;
-
- resp_obj = MAC_download_get_result (&kr->db,
- eh,
- &response_code);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received keys from URL `%s' with status %ld.\n",
- kr->url,
- response_code);
- switch (response_code) {
- case 0:
- break;
- case MHD_HTTP_OK:
- if ( (NULL == resp_obj) ||
- (GNUNET_OK !=
- decode_keys_json (resp_obj,
- &kr->mint->key_data)) )
- response_code = 0;
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- response_code);
- break;
- }
- if (NULL != resp_obj)
- json_decref (resp_obj);
-
- if (MHD_HTTP_OK != response_code)
- {
- mint->kr = NULL;
- free_keys_request (kr);
- mint->state = MHS_FAILED;
- /* notify application that we failed */
- if (NULL != (cb = mint->cert_cb))
- {
- mint->cert_cb = NULL;
- cb (mint->cert_cb_cls,
- NULL);
- }
- return;
- }
- mint->kr = NULL;
- free_keys_request (kr);
- mint->state = MHS_CERT;
- /* notify application about the key information */
- if (NULL != (cb = mint->cert_cb))
- {
- mint->cert_cb = NULL;
- cb (mint->cert_cb_cls,
- &mint->key_data);
- }
-}
-
-
-/* ********************* library internal API ********* */
-
-
-/**
- * Get the context of a mint.
- *
- * @param h the mint handle to query
- * @return ctx context to execute jobs in
- */
-struct TALER_MINT_Context *
-MAH_handle_to_context (struct TALER_MINT_Handle *h)
-{
- return h->ctx;
-}
-
-
-/**
- * Check if the handle is ready to process requests.
- *
- * @param h the mint handle to query
- * @return #GNUNET_YES if we are ready, #GNUNET_NO if not
- */
-int
-MAH_handle_is_ready (struct TALER_MINT_Handle *h)
-{
- return (MHS_CERT == h->state) ? GNUNET_YES : GNUNET_NO;
-}
-
-
-/**
- * Obtain the URL to use for an API request.
- *
- * @param h the mint handle to query
- * @param path Taler API path (i.e. "/reserve/withdraw")
- * @return the full URI to use with cURL
- */
-char *
-MAH_path_to_url (struct TALER_MINT_Handle *h,
- const char *path)
-{
- char *url;
-
- if ( ('/' == path[0]) &&
- (0 < strlen (h->url)) &&
- ('/' == h->url[strlen (h->url) - 1]) )
- path++; /* avoid generating URL with "//" from concat */
- GNUNET_asprintf (&url,
- "%s%s",
- h->url,
- path);
- return url;
-}
-
-
-/* ********************* public API ******************* */
-
-/**
- * Initialise a connection to the mint. Will connect to the
- * mint and obtain information about the mint's master public
- * key and the mint's auditor. The respective information will
- * be passed to the @a cert_cb once available, and all future
- * interactions with the mint will be checked to be signed
- * (where appropriate) by the respective master key.
- *
- * @param ctx the context
- * @param url HTTP base URL for the mint
- * @param cert_cb function to call with the mint's certification information
- * @param cert_cb_cls closure for @a cert_cb
- * @param ... list of additional arguments, terminated by #TALER_MINT_OPTION_END.
- * @return the mint handle; NULL upon error
- */
-struct TALER_MINT_Handle *
-TALER_MINT_connect (struct TALER_MINT_Context *ctx,
- const char *url,
- TALER_MINT_CertificationCallback cert_cb,
- void *cert_cb_cls,
- ...)
-{
- struct TALER_MINT_Handle *mint;
- struct KeysRequest *kr;
- CURL *c;
-
- mint = GNUNET_new (struct TALER_MINT_Handle);
- mint->ctx = ctx;
- mint->url = GNUNET_strdup (url);
- mint->cert_cb = cert_cb;
- mint->cert_cb_cls = cert_cb_cls;
- kr = GNUNET_new (struct KeysRequest);
- kr->mint = mint;
- kr->url = MAH_path_to_url (mint, "/keys");
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Requesting keys with URL `%s'.\n",
- kr->url);
- c = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (c,
- CURLOPT_VERBOSE,
- 0));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (c,
- CURLOPT_STDERR,
- stdout));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (c,
- CURLOPT_URL,
- kr->url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (c,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (c,
- CURLOPT_WRITEDATA,
- &kr->db));
- kr->job = MAC_job_add (mint->ctx,
- c,
- GNUNET_NO,
- &keys_completed_cb,
- kr);
- mint->kr = kr;
- return mint;
-}
-
-
-/**
- * Disconnect from the mint
- *
- * @param mint the mint handle
- */
-void
-TALER_MINT_disconnect (struct TALER_MINT_Handle *mint)
-{
- unsigned int i;
-
- if (NULL != mint->kr)
- {
- MAC_job_cancel (mint->kr->job);
- free_keys_request (mint->kr);
- mint->kr = NULL;
- }
- GNUNET_array_grow (mint->key_data.sign_keys,
- mint->key_data.num_sign_keys,
- 0);
- for (i=0;i<mint->key_data.num_denom_keys;i++)
- GNUNET_CRYPTO_rsa_public_key_free (mint->key_data.denom_keys[i].key.rsa_public_key);
- GNUNET_array_grow (mint->key_data.denom_keys,
- mint->key_data.num_denom_keys,
- 0);
- GNUNET_array_grow (mint->key_data.auditors,
- mint->key_data.num_auditors,
- 0);
- GNUNET_free (mint->url);
- GNUNET_free (mint);
-}
-
-
-/**
- * Test if the given @a pub is a the current signing key from the mint
- * according to @a keys.
- *
- * @param keys the mint's key set
- * @param pub claimed current online signing key for the mint
- * @return #GNUNET_OK if @a pub is (according to /keys) a current signing key
- */
-int
-TALER_MINT_test_signing_key (const struct TALER_MINT_Keys *keys,
- const struct TALER_MintPublicKeyP *pub)
-{
- struct GNUNET_TIME_Absolute now;
- unsigned int i;
-
- /* we will check using a tolerance of 1h for the time */
- now = GNUNET_TIME_absolute_get ();
- for (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_MintPublicKeyP))) )
- return GNUNET_OK;
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Obtain the denomination key details from the mint.
- *
- * @param keys the mint'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_MINT_DenomPublicKey *
-TALER_MINT_get_denomination_key (const struct TALER_MINT_Keys *keys,
- const struct TALER_DenominationPublicKey *pk)
-{
- unsigned int i;
-
- for (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 mint.
- *
- * @param keys the mint'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_MINT_DenomPublicKey *
-TALER_MINT_get_denomination_key_by_hash (const struct TALER_MINT_Keys *keys,
- const struct GNUNET_HashCode *hc)
-{
- unsigned int i;
-
- for (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 mint.
- *
- * @param mint the mint handle
- * @return the mint's key set
- */
-const struct TALER_MINT_Keys *
-TALER_MINT_get_keys (const struct TALER_MINT_Handle *mint)
-{
- return &mint->key_data;
-}
-
-
-/* end of mint_api_handle.c */
diff --git a/src/mint-lib/mint_api_handle.h b/src/mint-lib/mint_api_handle.h
deleted file mode 100644
index 0dae58db6..000000000
--- a/src/mint-lib/mint_api_handle.h
+++ /dev/null
@@ -1,59 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_handle.h
- * @brief Internal interface to the handle part of the mint's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include "taler_mint_service.h"
-
-
-/**
- * Get the context of a mint.
- *
- * @param h the mint handle to query
- * @return ctx context to execute jobs in
- */
-struct TALER_MINT_Context *
-MAH_handle_to_context (struct TALER_MINT_Handle *h);
-
-
-/**
- * Check if the handle is ready to process requests.
- *
- * @param h the mint handle to query
- * @return #GNUNET_YES if we are ready, #GNUNET_NO if not
- */
-int
-MAH_handle_is_ready (struct TALER_MINT_Handle *h);
-
-
-/**
- * Obtain the URL to use for an API request.
- *
- * @param h the mint handle to query
- * @param path Taler API path (i.e. "/reserve/withdraw")
- * @return the full URI to use with cURL
- */
-char *
-MAH_path_to_url (struct TALER_MINT_Handle *h,
- const char *path);
-
-
-/* end of mint_api_handle.h */
diff --git a/src/mint-lib/mint_api_json.c b/src/mint-lib/mint_api_json.c
deleted file mode 100644
index 7de33e5eb..000000000
--- a/src/mint-lib/mint_api_json.c
+++ /dev/null
@@ -1,525 +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 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/>
-*/
-/**
- * @file mint-lib/mint_api_json.c
- * @brief functions to parse incoming requests (JSON snippets)
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "mint_api_json.h"
-
-/**
- * Navigate and parse data in a JSON tree.
- *
- * @param root the JSON node to start the navigation at.
- * @param spec parse specification array
- * @return offset in @a spec where parsing failed, -1 on success (!)
- */
-static int
-parse_json (json_t *root,
- struct MAJ_Specification *spec)
-{
- int i;
- json_t *pos; /* what's our current position? */
-
- pos = root;
- for (i=0;MAJ_CMD_END != spec[i].cmd;i++)
- {
- pos = json_object_get (root,
- spec[i].field);
- if (NULL == pos)
- {
- GNUNET_break_op (0);
- return i;
- }
- switch (spec[i].cmd)
- {
- case MAJ_CMD_END:
- GNUNET_assert (0);
- return i;
- case MAJ_CMD_AMOUNT:
- if (GNUNET_OK !=
- TALER_json_to_amount (pos,
- spec[i].details.amount))
- {
- GNUNET_break_op (0);
- return i;
- }
- break;
- case MAJ_CMD_TIME_ABSOLUTE:
- if (GNUNET_OK !=
- TALER_json_to_abs (pos,
- spec[i].details.abs_time))
- {
- GNUNET_break_op (0);
- return i;
- }
- break;
-
- case MAJ_CMD_STRING:
- {
- const char *str;
-
- str = json_string_value (pos);
- if (NULL == str)
- {
- GNUNET_break_op (0);
- return i;
- }
- *spec[i].details.strptr = str;
- }
- break;
-
- case MAJ_CMD_BINARY_FIXED:
- {
- const char *str;
- int res;
-
- str = json_string_value (pos);
- if (NULL == str)
- {
- GNUNET_break_op (0);
- return i;
- }
- res = GNUNET_STRINGS_string_to_data (str, strlen (str),
- spec[i].details.fixed_data.dest,
- spec[i].details.fixed_data.dest_size);
- if (GNUNET_OK != res)
- {
- GNUNET_break_op (0);
- return i;
- }
- }
- break;
-
- case MAJ_CMD_BINARY_VARIABLE:
- {
- const char *str;
- size_t size;
- void *data;
- int res;
-
- str = json_string_value (pos);
- if (NULL == str)
- {
- GNUNET_break_op (0);
- return i;
- }
- size = (strlen (str) * 5) / 8;
- if (size >= 1024)
- {
- GNUNET_break_op (0);
- return i;
- }
- data = GNUNET_malloc (size);
- res = GNUNET_STRINGS_string_to_data (str,
- strlen (str),
- data,
- size);
- if (GNUNET_OK != res)
- {
- GNUNET_break_op (0);
- GNUNET_free (data);
- return i;
- }
- *spec[i].details.variable_data.dest_p = data;
- *spec[i].details.variable_data.dest_size_p = size;
- }
- break;
-
- case MAJ_CMD_RSA_PUBLIC_KEY:
- {
- size_t size;
- const char *str;
- int res;
- void *buf;
-
- str = json_string_value (pos);
- if (NULL == str)
- {
- GNUNET_break_op (0);
- return i;
- }
- size = (strlen (str) * 5) / 8;
- buf = GNUNET_malloc (size);
- res = GNUNET_STRINGS_string_to_data (str,
- strlen (str),
- buf,
- size);
- if (GNUNET_OK != res)
- {
- GNUNET_free (buf);
- GNUNET_break_op (0);
- return i;
- }
- *spec[i].details.rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_decode (buf,
- size);
- GNUNET_free (buf);
- if (NULL == spec[i].details.rsa_public_key)
- {
- GNUNET_break_op (0);
- return i;
- }
- }
- break;
-
- case MAJ_CMD_RSA_SIGNATURE:
- {
- size_t size;
- const char *str;
- int res;
- void *buf;
-
- str = json_string_value (pos);
- if (NULL == str)
- {
- GNUNET_break_op (0);
- return i;
- }
- size = (strlen (str) * 5) / 8;
- buf = GNUNET_malloc (size);
- res = GNUNET_STRINGS_string_to_data (str,
- strlen (str),
- buf,
- size);
- if (GNUNET_OK != res)
- {
- GNUNET_free (buf);
- GNUNET_break_op (0);
- return i;
- }
- *spec[i].details.rsa_signature
- = GNUNET_CRYPTO_rsa_signature_decode (buf,
- size);
- GNUNET_free (buf);
- if (NULL == spec[i].details.rsa_signature)
- return i;
- }
- break;
-
- case MAJ_CMD_UINT16:
- {
- json_int_t val;
-
- if (! json_is_integer (pos))
- {
- GNUNET_break_op (0);
- return i;
- }
- val = json_integer_value (pos);
- if ( (0 > val) || (val > UINT16_MAX) )
- {
- GNUNET_break_op (0);
- return i;
- }
- *spec[i].details.u16 = (uint16_t) val;
- }
- break;
-
- case MAJ_CMD_UINT64:
- {
- json_int_t val;
-
- if (! json_is_integer (pos))
- {
- GNUNET_break_op (0);
- return i;
- }
- val = json_integer_value (pos);
- *spec[i].details.u64 = (uint64_t) val;
- }
- break;
-
- case MAJ_CMD_JSON_OBJECT:
- {
- if (! (json_is_object (pos) || json_is_array (pos)) )
- {
- GNUNET_break_op (0);
- return i;
- }
- json_incref (pos);
- *spec[i].details.obj = pos;
- }
- break;
-
- default:
- GNUNET_break (0);
- return i;
- }
- }
- return -1; /* all OK! */
-}
-
-
-/**
- * Free all elements allocated during a
- * #MAJ_parse_json() operation.
- *
- * @param spec specification of the parse operation
- * @param end number of elements in @a spec to process
- */
-static void
-parse_free (struct MAJ_Specification *spec,
- int end)
-{
- int i;
-
- for (i=0;i<end;i++)
- {
- switch (spec[i].cmd)
- {
- case MAJ_CMD_END:
- GNUNET_assert (0);
- return;
- case MAJ_CMD_AMOUNT:
- break;
- case MAJ_CMD_TIME_ABSOLUTE:
- break;
- case MAJ_CMD_BINARY_FIXED:
- break;
- case MAJ_CMD_STRING:
- break;
- case MAJ_CMD_BINARY_VARIABLE:
- GNUNET_free (*spec[i].details.variable_data.dest_p);
- *spec[i].details.variable_data.dest_p = NULL;
- *spec[i].details.variable_data.dest_size_p = 0;
- break;
- case MAJ_CMD_RSA_PUBLIC_KEY:
- GNUNET_CRYPTO_rsa_public_key_free (*spec[i].details.rsa_public_key);
- *spec[i].details.rsa_public_key = NULL;
- break;
- case MAJ_CMD_RSA_SIGNATURE:
- GNUNET_CRYPTO_rsa_signature_free (*spec[i].details.rsa_signature);
- *spec[i].details.rsa_signature = NULL;
- break;
- case MAJ_CMD_JSON_OBJECT:
- json_decref (*spec[i].details.obj);
- *spec[i].details.obj = NULL;
- break;
- default:
- GNUNET_break (0);
- break;
- }
- }
-}
-
-
-/**
- * Navigate and parse data in a JSON tree.
- *
- * @param root the JSON node to start the navigation at.
- * @param spec parse specification array
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-int
-MAJ_parse_json (const json_t *root,
- struct MAJ_Specification *spec)
-{
- int ret;
-
- ret = parse_json ((json_t *) root,
- spec);
- if (-1 == ret)
- return GNUNET_OK;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "JSON field `%s` (%d) had unexpected value\n",
- spec[ret].field,
- ret);
- parse_free (spec, ret);
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Free all elements allocated during a
- * #MAJ_parse_json() operation.
- *
- * @param spec specification of the parse operation
- */
-void
-MAJ_parse_free (struct MAJ_Specification *spec)
-{
- int i;
-
- for (i=0;MAJ_CMD_END != spec[i].cmd;i++) ;
- parse_free (spec, i);
-}
-
-
-/**
- * The expected field stores a string.
- *
- * @param name name of the JSON field
- * @param strptr where to store a pointer to the field
- */
-struct MAJ_Specification
-MAJ_spec_string (const char *name,
- const char **strptr)
-{
- struct MAJ_Specification ret =
- {
- .cmd = MAJ_CMD_STRING,
- .field = name,
- .details.strptr = strptr
- };
- return ret;
-}
-
-
-/**
- * Specification for parsing an absolute time value.
- *
- * @param name name of the JSON field
- * @param at where to store the absolute time found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_absolute_time (const char *name,
- struct GNUNET_TIME_Absolute *at)
-{
- struct MAJ_Specification ret =
- {
- .cmd = MAJ_CMD_TIME_ABSOLUTE,
- .field = name,
- .details.abs_time = at
- };
- return ret;
-}
-
-
-/**
- * Specification for parsing an amount value.
- *
- * @param name name of the JSON field
- * @param amount where to store the amount found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_amount (const char *name,
- struct TALER_Amount *amount)
-{
- struct MAJ_Specification ret =
- {
- .cmd = MAJ_CMD_AMOUNT,
- .field = name,
- .details.amount = amount
- };
- return ret;
-}
-
-
-/**
- * 16-bit integer.
- *
- * @param name name of the JSON field
- * @param[out] u16 where to store the integer found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_uint16 (const char *name,
- uint16_t *u16)
-{
- struct MAJ_Specification ret =
- {
- .cmd = MAJ_CMD_UINT16,
- .field = name,
- .details.u16 = u16
- };
- return ret;
-}
-
-
-/**
- * 64-bit integer.
- *
- * @param name name of the JSON field
- * @param[out] u64 where to store the integer found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_uint64 (const char *name,
- uint64_t *u64)
-{
- struct MAJ_Specification ret =
- {
- .cmd = MAJ_CMD_UINT64,
- .field = name,
- .details.u64 = u64
- };
- return ret;
-}
-
-
-/**
- * JSON object.
- *
- * @param name name of the JSON field
- * @param[out] jsonp where to store the JSON found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_json (const char *name,
- json_t **jsonp)
-{
- struct MAJ_Specification ret =
- {
- .cmd = MAJ_CMD_JSON_OBJECT,
- .field = name,
- .details.obj = jsonp
- };
- return ret;
-}
-
-
-/**
- * Specification for parsing an RSA public key.
- *
- * @param name name of the JSON field
- * @param pk where to store the RSA key found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_rsa_public_key (const char *name,
- struct GNUNET_CRYPTO_rsa_PublicKey **pk)
-{
- struct MAJ_Specification ret =
- {
- .cmd = MAJ_CMD_RSA_PUBLIC_KEY,
- .field = name,
- .details.rsa_public_key = pk
- };
- return ret;
-}
-
-
-/**
- * Specification for parsing an RSA signature.
- *
- * @param name name of the JSON field
- * @param sig where to store the RSA signature found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_rsa_signature (const char *name,
- struct GNUNET_CRYPTO_rsa_Signature **sig)
-{
- struct MAJ_Specification ret =
- {
- .cmd = MAJ_CMD_RSA_SIGNATURE,
- .field = name,
- .details.rsa_signature = sig
- };
- return ret;
-}
-
-
-/* end of mint_api_json.c */
diff --git a/src/mint-lib/mint_api_json.h b/src/mint-lib/mint_api_json.h
deleted file mode 100644
index 6bc3a5572..000000000
--- a/src/mint-lib/mint_api_json.h
+++ /dev/null
@@ -1,352 +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 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/>
-*/
-/**
- * @file mint-lib/mint_api_json.h
- * @brief functions to parse incoming requests (JSON snippets)
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_util.h"
-#include <jansson.h>
-
-
-/**
- * Enumeration with the various commands for the
- * #MAJ_parse_json interpreter.
- */
-enum MAJ_Command
-{
-
- /**
- * End of command list.
- */
- MAJ_CMD_END,
-
- /**
- * Parse amount at current position.
- */
- MAJ_CMD_AMOUNT,
-
- /**
- * Parse absolute time at current position.
- */
- MAJ_CMD_TIME_ABSOLUTE,
-
- /**
- * Parse fixed binary value at current position.
- */
- MAJ_CMD_BINARY_FIXED,
-
- /**
- * Parse variable-size binary value at current position.
- */
- MAJ_CMD_BINARY_VARIABLE,
-
- /**
- * Parse RSA public key at current position.
- */
- MAJ_CMD_RSA_PUBLIC_KEY,
-
- /**
- * Parse RSA signature at current position.
- */
- MAJ_CMD_RSA_SIGNATURE,
-
- /**
- * Parse `const char *` JSON string at current position.
- */
- MAJ_CMD_STRING,
-
- /**
- * Parse `uint16_t` integer at the current position.
- */
- MAJ_CMD_UINT16,
-
- /**
- * Parse `uint64_t` integer at the current position.
- */
- MAJ_CMD_UINT64,
-
- /**
- * Parse JSON object at the current position.
- */
- MAJ_CMD_JSON_OBJECT,
-
- /**
- * Parse ??? at current position.
- */
- MAJ_CMD_C
-
-};
-
-
-/**
- * @brief Entry in parser specification for #MAJ_parse_json.
- */
-struct MAJ_Specification
-{
-
- /**
- * Command to execute.
- */
- enum MAJ_Command cmd;
-
- /**
- * Name of the field to access.
- */
- const char *field;
-
- /**
- * Further details for the command.
- */
- union {
-
- /**
- * Where to store amount for #MAJ_CMD_AMOUNT.
- */
- struct TALER_Amount *amount;
-
- /**
- * Where to store time, for #MAJ_CMD_TIME_ABSOLUTE.
- */
- struct GNUNET_TIME_Absolute *abs_time;
-
- /**
- * Where to write binary data, for #MAJ_CMD_BINARY_FIXED.
- */
- struct {
- /**
- * Where to write the data.
- */
- void *dest;
-
- /**
- * How many bytes to write to @e dest.
- */
- size_t dest_size;
-
- } fixed_data;
-
- /**
- * Where to write binary data, for #MAJ_CMD_BINARY_VARIABLE.
- */
- struct {
- /**
- * Where to store the pointer with the data (is allocated).
- */
- void **dest_p;
-
- /**
- * Where to store the number of bytes allocated at `*dest`.
- */
- size_t *dest_size_p;
-
- } variable_data;
-
- /**
- * Where to store the RSA public key for #MAJ_CMD_RSA_PUBLIC_KEY
- */
- struct GNUNET_CRYPTO_rsa_PublicKey **rsa_public_key;
-
- /**
- * Where to store the RSA signature for #MAJ_CMD_RSA_SIGNATURE
- */
- struct GNUNET_CRYPTO_rsa_Signature **rsa_signature;
-
- /**
- * Details for #MAJ_CMD_EDDSA_SIGNATURE
- */
- struct {
-
- /**
- * Where to store the purpose.
- */
- struct GNUNET_CRYPTO_EccSignaturePurpose **purpose_p;
-
- /**
- * Key to verify the signature against.
- */
- const struct GNUNET_CRYPTO_EddsaPublicKey *pub_key;
-
- } eddsa_signature;
-
- /**
- * Where to store a pointer to the string.
- */
- const char **strptr;
-
- /**
- * Where to store 16-bit integer.
- */
- uint16_t *u16;
-
- /**
- * Where to store 64-bit integer.
- */
- uint64_t *u64;
-
- /**
- * Where to store a JSON object.
- */
- json_t **obj;
-
- } details;
-
-};
-
-
-/**
- * Navigate and parse data in a JSON tree.
- *
- * @param root the JSON node to start the navigation at.
- * @param spec parse specification array
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
- */
-int
-MAJ_parse_json (const json_t *root,
- struct MAJ_Specification *spec);
-
-
-/**
- * Free all elements allocated during a
- * #MAJ_parse_json() operation.
- *
- * @param spec specification of the parse operation
- */
-void
-MAJ_parse_free (struct MAJ_Specification *spec);
-
-
-/**
- * End of a parser specification.
- */
-#define MAJ_spec_end { .cmd = MAJ_CMD_END }
-
-/**
- * Fixed size object (in network byte order, encoded using Crockford
- * Base32hex encoding).
- *
- * @param name name of the JSON field
- * @param obj pointer where to write the data (type of `*obj` will determine size)
- */
-#define MAJ_spec_fixed_auto(name,obj) { .cmd = MAJ_CMD_BINARY_FIXED, .field = name, .details.fixed_data.dest = obj, .details.fixed_data.dest_size = sizeof (*obj) }
-
-
-/**
- * Variable size object (in network byte order, encoded using Crockford
- * Base32hex encoding).
- *
- * @param name name of the JSON field
- * @param obj pointer where to write the data (a `void **`)
- * @param size where to store the number of bytes allocated for @a obj (of type `size_t *`
- */
-#define MAJ_spec_varsize(name,obj,size) { .cmd = MAJ_CMD_BINARY_VARIABLE, .field = name, .details.variable_data.dest_p = obj, .details.variable_data.dest_size_p = size }
-
-
-/**
- * The expected field stores a string.
- *
- * @param name name of the JSON field
- * @param strptr where to store a pointer to the field
- */
-struct MAJ_Specification
-MAJ_spec_string (const char *name,
- const char **strptr);
-
-
-/**
- * Absolute time.
- *
- * @param name name of the JSON field
- * @param[out] at where to store the absolute time found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_absolute_time (const char *name,
- struct GNUNET_TIME_Absolute *at);
-
-
-/**
- * 16-bit integer.
- *
- * @param name name of the JSON field
- * @param[out] u16 where to store the integer found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_uint16 (const char *name,
- uint16_t *u16);
-
-
-/**
- * 64-bit integer.
- *
- * @param name name of the JSON field
- * @param[out] u64 where to store the integer found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_uint64 (const char *name,
- uint64_t *u64);
-
-
-/**
- * JSON object.
- *
- * @param name name of the JSON field
- * @param[out] jsonp where to store the JSON found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_json (const char *name,
- json_t **jsonp);
-
-
-/**
- * Specification for parsing an amount value.
- *
- * @param name name of the JSON field
- * @param amount where to store the amount under @a name
- */
-struct MAJ_Specification
-MAJ_spec_amount (const char *name,
- struct TALER_Amount *amount);
-
-
-/**
- * Specification for parsing an RSA public key.
- *
- * @param name name of the JSON field
- * @param pk where to store the RSA key found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_rsa_public_key (const char *name,
- struct GNUNET_CRYPTO_rsa_PublicKey **pk);
-
-
-/**
- * Specification for parsing an RSA signature.
- *
- * @param name name of the JSON field
- * @param sig where to store the RSA signature found under @a name
- */
-struct MAJ_Specification
-MAJ_spec_rsa_signature (const char *name,
- struct GNUNET_CRYPTO_rsa_Signature **sig);
-
-
-
-
-/* end of mint_api_json.h */
diff --git a/src/mint-lib/mint_api_refresh.c b/src/mint-lib/mint_api_refresh.c
deleted file mode 100644
index cea16b153..000000000
--- a/src/mint-lib/mint_api_refresh.c
+++ /dev/null
@@ -1,2061 +0,0 @@
-/*
- 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 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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_refresh.c
- * @brief Implementation of the /refresh/melt+reveal requests of the mint's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "mint_api_common.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.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 deposit_valid_until;
-
- /**
- * 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 for serializations of coin-specific information about the
- * fresh coins we generate during a melt.
- */
-struct FreshCoinP
-{
-
- /**
- * Private key of the coin.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
- /**
- * Size of the encoded blinding key that follows.
- */
- uint32_t bbuf_size;
-
- /* Followed by serialization of:
- - struct TALER_DenominationBlindingKey blinding_key;
- */
-
-};
-
-
-/**
- * Header of serialized data about a melt operation, suitable for
- * persisting it on disk.
- */
-struct MeltDataP
-{
-
- /**
- * Hash over the melting session.
- */
- struct GNUNET_HashCode melt_session_hash;
-
- /**
- * Link secret used to encrypt the @a coin_priv and the blinding
- * key in the linkage data for the respective cut-and-choose dimension.
- */
- struct TALER_LinkSecretP link_secrets[TALER_CNC_KAPPA];
-
- /**
- * 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_MINT_DenomPublicKey fresh_pks[num_fresh_coins];
- 3) TALER_CNC_KAPPA times:
- 3a) struct FreshCoinP 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 deposit_valid_until;
-
- /**
- * Denomination key of the original coin.
- */
- struct TALER_DenominationPublicKey pub_key;
-
- /**
- * Mint's signature over the coin.
- */
- struct TALER_DenominationSignature sig;
-
-};
-
-
-/**
- * Coin-specific information about the fresh coins we generate during
- * a melt.
- */
-struct FreshCoin
-{
-
- /**
- * Private key of the coin.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
- /**
- * Blinding key used for blinding during blind signing.
- */
- struct TALER_DenominationBlindingKey blinding_key;
-
-};
-
-
-/**
- * Melt data in non-serialized format for convenient processing.
- */
-struct MeltData
-{
-
- /**
- * Hash over the melting session.
- */
- struct GNUNET_HashCode melt_session_hash;
-
- /**
- * Link secrets for each cut-and-choose dimension.
- */
- struct TALER_LinkSecretP link_secrets[TALER_CNC_KAPPA];
-
- /**
- * Number of coins we are melting
- */
- uint16_t num_melted_coins;
-
- /**
- * Number of coins we are creating
- */
- uint16_t num_fresh_coins;
-
- /**
- * Information about the melted coins in an array of length @e
- * num_melted_coins.
- */
- struct MeltedCoin *melted_coins;
-
- /**
- * Array of @e num_fresh_coins denomination keys for the coins to be
- * freshly minted.
- */
- 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 FreshCoin *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)
- return;
- 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 fresh coin.
- *
- * @param fc fresh coin to release, the pointer itself is NOT
- * freed (as it is typically not allocated by itself)
- */
-static void
-free_fresh_coin (struct FreshCoin *fc)
-{
- if (NULL == fc)
- return;
- if (NULL != fc->blinding_key.rsa_blinding_key)
- GNUNET_CRYPTO_rsa_blinding_key_free (fc->blinding_key.rsa_blinding_key);
-}
-
-
-/**
- * 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)
-{
- unsigned int i;
- unsigned int j;
-
- if (NULL != md->melted_coins)
- {
- for (i=0;i<md->num_melted_coins;i++)
- free_melted_coin (&md->melted_coins[i]);
- GNUNET_free (md->melted_coins);
- }
- if (NULL != md->fresh_pks)
- {
- for (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 (i=0;i<TALER_CNC_KAPPA;i++)
- {
- for (j=0;j<md->num_fresh_coins;j++)
- free_fresh_coin (&md->fresh_coins[i][j]);
- 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.deposit_valid_until = GNUNET_TIME_absolute_hton (mc->deposit_valid_until);
- 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->deposit_valid_until = GNUNET_TIME_absolute_ntoh (mcp.deposit_valid_until);
- 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 FreshCoin *fc,
- char *buf,
- size_t off)
-{
- struct FreshCoinP fcp;
- char *bbuf;
- size_t bbuf_size;
-
- bbuf_size = GNUNET_CRYPTO_rsa_blinding_key_encode (fc->blinding_key.rsa_blinding_key,
- &bbuf);
- if (NULL == buf)
- {
- GNUNET_free (bbuf);
- return sizeof (struct FreshCoinP) + bbuf_size;
- }
- fcp.coin_priv = fc->coin_priv;
- fcp.bbuf_size = htonl ((uint32_t) bbuf_size);
- memcpy (&buf[off],
- &fcp,
- sizeof (struct FreshCoinP));
- memcpy (&buf[off + sizeof (struct FreshCoinP)],
- bbuf,
- bbuf_size);
- GNUNET_free (bbuf);
- return sizeof (struct FreshCoinP) + bbuf_size;
-}
-
-
-/**
- * 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 FreshCoin *fc,
- const char *buf,
- size_t size,
- int *ok)
-{
- struct FreshCoinP fcp;
- size_t bbuf_size;
-
- if (size < sizeof (struct FreshCoinP))
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
- memcpy (&fcp,
- buf,
- sizeof (struct FreshCoinP));
- bbuf_size = ntohl (fcp.bbuf_size);
- if (size < sizeof (struct FreshCoinP) + bbuf_size)
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
- fc->blinding_key.rsa_blinding_key
- = GNUNET_CRYPTO_rsa_blinding_key_decode (&buf[sizeof (struct FreshCoinP)],
- bbuf_size);
- if (NULL == fc->blinding_key.rsa_blinding_key)
- {
- GNUNET_break (0);
- *ok = GNUNET_NO;
- return 0;
- }
- fc->coin_priv = fcp.coin_priv;
- return sizeof (struct FreshCoinP) + bbuf_size;
-}
-
-
-/**
- * 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;
- unsigned int i;
- unsigned int j;
-
- 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->melt_session_hash = md->melt_session_hash;
- for (i=0;i<TALER_CNC_KAPPA;i++)
- mdp->link_secrets[i] = md->link_secrets[i];
- mdp->num_melted_coins = htons (md->num_melted_coins);
- mdp->num_fresh_coins = htons (md->num_fresh_coins);
- }
- for (i=0;i<md->num_melted_coins;i++)
- size += serialize_melted_coin (&md->melted_coins[i],
- buf,
- size);
- for (i=0;i<md->num_fresh_coins;i++)
- size += serialize_denomination_key (&md->fresh_pks[i],
- buf,
- size);
- for (i=0;i<TALER_CNC_KAPPA;i++)
- for(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;
- unsigned int i;
- unsigned int j;
- 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->melt_session_hash = mdp.melt_session_hash;
- for (i=0;i<TALER_CNC_KAPPA;i++)
- md->link_secrets[i] = mdp.link_secrets[i];
- md->num_melted_coins = ntohs (mdp.num_melted_coins);
- md->num_fresh_coins = ntohs (mdp.num_fresh_coins);
- md->melted_coins = GNUNET_new_array (md->num_melted_coins,
- struct MeltedCoin);
- md->fresh_pks = GNUNET_new_array (md->num_fresh_coins,
- struct TALER_DenominationPublicKey);
- for (i=0;i<TALER_CNC_KAPPA;i++)
- md->fresh_coins[i] = GNUNET_new_array (md->num_fresh_coins,
- struct FreshCoin);
- off = sizeof (struct MeltDataP);
- ok = GNUNET_YES;
- for (i=0;(i<md->num_melted_coins)&&(GNUNET_YES == ok);i++)
- off += deserialize_melted_coin (&md->melted_coins[i],
- &buf[off],
- buf_size - off,
- &ok);
- for (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 (i=0;i<TALER_CNC_KAPPA;i++)
- for(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;
-}
-
-
-/**
- * Setup information for a fresh coin.
- *
- * @param[out] fc value to initialize
- * @param pk denomination information for the fresh coin
- */
-static void
-setup_fresh_coin (struct FreshCoin *fc,
- const struct TALER_MINT_DenomPublicKey *pk)
-{
- struct GNUNET_CRYPTO_EddsaPrivateKey *epk;
- unsigned int len;
-
- epk = GNUNET_CRYPTO_eddsa_key_create ();
- fc->coin_priv.eddsa_priv = *epk;
- GNUNET_free (epk);
- len = GNUNET_CRYPTO_rsa_public_key_len (pk->key.rsa_public_key);
- fc->blinding_key.rsa_blinding_key
- = GNUNET_CRYPTO_rsa_blinding_key_create (len);
-}
-
-
-/**
- * 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_MINT_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 num_melts number of coins that are being melted (typically 1)
- * @param melt_privs array of @a num_melts private keys of the coins to melt
- * @param melt_amounts array of @a num_melts amounts specifying how much
- * each coin will contribute to the melt (including fee)
- * @param melt_sigs array of @a num_melts signatures affirming the
- * validity of the public keys corresponding to the
- * @a melt_privs private keys
- * @param melt_pks array of @a num_melts denomination key information
- * records corresponding to the @a melt_sigs
- * validity of the keys
- * @param check_sigs verify the validity of the signatures of @a melt_sigs
- * @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 mint).
- * Otherwise, pointer to a buffer of @a res_size to store persistently
- * before proceeding to #TALER_MINT_refresh_melt().
- * Non-null results should be freed using #GNUNET_free().
- */
-char *
-TALER_MINT_refresh_prepare (unsigned int num_melts,
- const struct TALER_CoinSpendPrivateKeyP *melt_privs,
- const struct TALER_Amount *melt_amounts,
- const struct TALER_DenominationSignature *melt_sigs,
- const struct TALER_MINT_DenomPublicKey *melt_pks,
- int check_sigs,
- unsigned int fresh_pks_len,
- const struct TALER_MINT_DenomPublicKey *fresh_pks,
- size_t *res_size)
-{
- struct MeltData md;
- char *buf;
- unsigned int i;
- unsigned int j;
- struct GNUNET_HashContext *hash_context;
-
- /* build up melt data structure */
- for (i=0;i<TALER_CNC_KAPPA;i++)
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
- &md.link_secrets[i],
- sizeof (struct TALER_LinkSecretP));
- md.num_melted_coins = num_melts;
- md.num_fresh_coins = fresh_pks_len;
- md.melted_coins = GNUNET_new_array (num_melts,
- struct MeltedCoin);
- for (i=0;i<num_melts;i++)
- {
- md.melted_coins[i].coin_priv = melt_privs[i];
- md.melted_coins[i].melt_amount_with_fee = melt_amounts[i];
- md.melted_coins[i].fee_melt = melt_pks[i].fee_refresh;
- md.melted_coins[i].original_value = melt_pks[i].value;
- for (j=0;j<TALER_CNC_KAPPA;j++)
- {
- struct GNUNET_CRYPTO_EcdhePrivateKey *tpk;
-
- tpk = GNUNET_CRYPTO_ecdhe_key_create ();
- md.melted_coins[i].transfer_priv[j].ecdhe_priv = *tpk;
- GNUNET_free (tpk);
- }
- md.melted_coins[i].deposit_valid_until
- = melt_pks[i].deposit_valid_until;
- md.melted_coins[i].pub_key.rsa_public_key
- = GNUNET_CRYPTO_rsa_public_key_dup (melt_pks[i].key.rsa_public_key);
- md.melted_coins[i].sig.rsa_signature
- = GNUNET_CRYPTO_rsa_signature_dup (melt_sigs[i].rsa_signature);
- }
- md.fresh_pks = GNUNET_new_array (fresh_pks_len,
- struct TALER_DenominationPublicKey);
- for (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);
- for (i=0;i<TALER_CNC_KAPPA;i++)
- {
- md.fresh_coins[i] = GNUNET_new_array (fresh_pks_len,
- struct FreshCoin);
- for (j=0;j<fresh_pks_len;j++)
- setup_fresh_coin (&md.fresh_coins[i][j],
- &fresh_pks[j]);
- }
-
- /* now compute melt session hash */
- hash_context = GNUNET_CRYPTO_hash_context_start ();
- for (i=0;i<fresh_pks_len;i++)
- {
- char *buf;
- size_t buf_size;
-
- buf_size = GNUNET_CRYPTO_rsa_public_key_encode (fresh_pks[i].key.rsa_public_key,
- &buf);
- GNUNET_CRYPTO_hash_context_read (hash_context,
- buf,
- buf_size);
- GNUNET_free (buf);
- }
- for (i=0;i<num_melts;i++)
- {
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_AmountNBO melt_amount;
-
- GNUNET_CRYPTO_eddsa_key_get_public (&melt_privs[i].eddsa_priv,
- &coin_pub.eddsa_pub);
- GNUNET_CRYPTO_hash_context_read (hash_context,
- &coin_pub,
- sizeof (struct TALER_CoinSpendPublicKeyP));
- TALER_amount_hton (&melt_amount,
- &melt_amounts[i]);
- GNUNET_CRYPTO_hash_context_read (hash_context,
- &melt_amount,
- sizeof (struct TALER_AmountNBO));
-
- }
- for (i = 0; i < TALER_CNC_KAPPA; i++)
- {
- for (j = 0; j < fresh_pks_len; j++)
- {
- const struct FreshCoin *fc; /* coin this is about */
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct GNUNET_HashCode coin_hash;
- char *coin_ev; /* blinded message to be signed (in envelope) for each coin */
- size_t coin_ev_size;
- struct TALER_RefreshLinkDecrypted rld;
- struct TALER_RefreshLinkEncrypted *rle;
- char *link_enc; /* encrypted link data */
- size_t link_enc_size;
-
- fc = &md.fresh_coins[i][j];
- 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);
- coin_ev_size = GNUNET_CRYPTO_rsa_blind (&coin_hash,
- fc->blinding_key.rsa_blinding_key,
- md.fresh_pks[j].rsa_public_key,
- &coin_ev);
- GNUNET_CRYPTO_hash_context_read (hash_context,
- coin_ev,
- coin_ev_size);
- GNUNET_free (coin_ev);
-
- rld.coin_priv = fc->coin_priv;
- rld.blinding_key = fc->blinding_key;
- rle = TALER_refresh_encrypt (&rld,
- &md.link_secrets[i]);
- link_enc = TALER_refresh_link_encrypted_encode (rle,
- &link_enc_size);
-
- GNUNET_CRYPTO_hash_context_read (hash_context,
- link_enc,
- link_enc_size);
- GNUNET_free (link_enc);
- }
- }
- for (i = 0; i < TALER_CNC_KAPPA; i++)
- {
- for (j = 0; j < num_melts; j++)
- {
- struct TALER_RefreshCommitLinkP rcl;
- struct TALER_TransferSecretP trans_sec;
-
- GNUNET_CRYPTO_ecdhe_key_get_public (&md.melted_coins[j].transfer_priv[i].ecdhe_priv,
- &rcl.transfer_pub.ecdhe_pub);
- TALER_link_derive_transfer_secret (&melt_privs[j],
- &md.melted_coins[j].transfer_priv[i],
- &trans_sec);
- TALER_transfer_encrypt (&md.link_secrets[i],
- &trans_sec,
- &rcl.shared_secret_enc);
- GNUNET_CRYPTO_hash_context_read (hash_context,
- &rcl,
- sizeof (struct TALER_RefreshCommitLinkP));
- }
- }
-
- GNUNET_CRYPTO_hash_context_finish (hash_context,
- &md.melt_session_hash);
-
- /* finally, serialize everything */
- buf = serialize_melt_data (&md,
- res_size);
- free_melt_data (&md);
- return buf;
-}
-
-
-/* ********************* /refresh/melt ***************************** */
-
-
-/**
- * @brief A /refresh/melt Handle
- */
-struct TALER_MINT_RefreshMeltHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with refresh melt failure results.
- */
- TALER_MINT_RefreshMeltCallback melt_cb;
-
- /**
- * Closure for @e result_cb and @e melt_failure_cb.
- */
- void *melt_cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
- /**
- * Actual information about the melt operation.
- */
- struct MeltData *md;
-};
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * from the mint is valid.
- *
- * @param rmh melt handle
- * @param json json reply with the signature
- * @param[out] noreveal_index set to the noreveal index selected by the mint
- * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not
- */
-static int
-verify_refresh_melt_signature_ok (struct TALER_MINT_RefreshMeltHandle *rmh,
- json_t *json,
- uint16_t *noreveal_index)
-{
- struct TALER_MintSignatureP mint_sig;
- struct TALER_MintPublicKeyP mint_pub;
- const struct TALER_MINT_Keys *key_state;
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("mint_sig", &mint_sig),
- MAJ_spec_fixed_auto ("mint_pub", &mint_pub),
- MAJ_spec_uint16 ("noreveal_index", noreveal_index),
- MAJ_spec_end
- };
- struct TALER_RefreshMeltConfirmationPS confirm;
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* check that mint signing key is permitted */
- key_state = TALER_MINT_get_keys (rmh->mint);
- if (GNUNET_OK !=
- TALER_MINT_test_signing_key (key_state,
- &mint_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 mint */
- confirm.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_MELT);
- confirm.purpose.size = htonl (sizeof (struct TALER_RefreshMeltConfirmationPS));
- confirm.session_hash = rmh->md->melt_session_hash;
- confirm.noreveal_index = htons (*noreveal_index);
- confirm.reserved = htons (0);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_CONFIRM_MELT,
- &confirm.purpose,
- &mint_sig.eddsa_signature,
- &mint_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Verify that the signatures on the "403 FORBIDDEN" response from the
- * mint 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_MINT_RefreshMeltHandle *rmh,
- 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;
- unsigned int i;
- struct MAJ_Specification spec[] = {
- MAJ_spec_json ("history", &history),
- MAJ_spec_fixed_auto ("coin_pub", &coin_pub),
- MAJ_spec_amount ("original_value", &original_value),
- MAJ_spec_amount ("requested_value", &melt_value_with_fee),
- MAJ_spec_end
- };
- const struct MeltedCoin *mc;
-
- /* parse JSON reply */
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* Find out which coin was deemed problematic by the mint */
- mc = NULL;
- for (i=0;i<rmh->md->num_melted_coins;i++)
- {
- if (0 == TALER_amount_cmp (&melt_value_with_fee,
- &rmh->md->melted_coins[i].melt_amount_with_fee))
- {
- struct TALER_CoinSpendPublicKeyP mc_pub;
-
- GNUNET_CRYPTO_eddsa_key_get_public (&rmh->md->melted_coins[i].coin_priv.eddsa_priv,
- &mc_pub.eddsa_pub);
- if (0 == memcmp (&mc_pub,
- &coin_pub,
- sizeof (struct TALER_CoinSpendPublicKeyP)))
- {
- mc = &rmh->md->melted_coins[i];
- break;
- }
- }
- }
- if (NULL == mc)
- {
- /* coin not found in our original request */
- GNUNET_break_op (0);
- json_decref (history);
- return GNUNET_SYSERR;
- }
-
- /* 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_MINT_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_MINT_RefreshMeltHandle`
- * @param eh the curl request handle
- */
-static void
-handle_refresh_melt_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_RefreshMeltHandle *rmh = cls;
- long response_code;
- json_t *json;
- uint16_t noreveal_index = TALER_CNC_KAPPA; /* invalid value */
-
- rmh->job = NULL;
- json = MAC_download_get_result (&rmh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- verify_refresh_melt_signature_ok (rmh,
- json,
- &noreveal_index))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- if (NULL != rmh->melt_cb)
- {
- rmh->melt_cb (rmh->melt_cb_cls,
- response_code,
- noreveal_index,
- json);
- rmh->melt_cb = NULL;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint 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,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- if (NULL != rmh->melt_cb)
- rmh->melt_cb (rmh->melt_cb_cls,
- response_code,
- UINT16_MAX,
- json);
- json_decref (json);
- TALER_MINT_refresh_melt_cancel (rmh);
-}
-
-
-/**
- * Convert a coin to be melted to the respective JSON encoding.
- *
- * @param melt_session_hash session hash to use
- * @param mc coin to be melted
- * @return JSON encoding of the melting request
- */
-static json_t *
-melted_coin_to_json (const struct GNUNET_HashCode *melt_session_hash,
- const struct MeltedCoin *mc)
-{
- struct TALER_CoinSpendSignatureP confirm_sig;
- struct TALER_RefreshMeltCoinAffirmationPS melt;
-
- melt.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
- melt.purpose.size = htonl (sizeof (struct TALER_RefreshMeltCoinAffirmationPS));
- melt.session_hash = *melt_session_hash;
- TALER_amount_hton (&melt.amount_with_fee,
- &mc->melt_amount_with_fee);
- TALER_amount_hton (&melt.melt_fee,
- &mc->fee_melt);
- GNUNET_CRYPTO_eddsa_key_get_public (&mc->coin_priv.eddsa_priv,
- &melt.coin_pub.eddsa_pub);
- GNUNET_CRYPTO_eddsa_sign (&mc->coin_priv.eddsa_priv,
- &melt.purpose,
- &confirm_sig.eddsa_signature);
- return json_pack ("{s:o, s:o, s:o, s:o, s:o}",
- "coin_pub",
- TALER_json_from_data (&melt.coin_pub,
- sizeof (melt.coin_pub)),
- "denom_pub",
- TALER_json_from_rsa_public_key (mc->pub_key.rsa_public_key),
- "denom_sig",
- TALER_json_from_rsa_signature (mc->sig.rsa_signature),
- "confirm_sig",
- TALER_json_from_data (&confirm_sig,
- sizeof (confirm_sig)),
- "value_with_fee",
- TALER_json_from_amount (&mc->melt_amount_with_fee));
-}
-
-
-/**
- * Submit a melt request to the mint and get the mint'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_MINT_refresh_prepare and committed to persistent storage
- * prior to calling this function.
- *
- * @param mint the mint handle; the mint must be ready to operate
- * @param refresh_data_length size of the @a refresh_data (returned
- * in the `res_size` argument from #TALER_MINT_refresh_prepare())
- * @param refresh_data the refresh data as returned from
- #TALER_MINT_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_MINT_RefreshMeltHandle *
-TALER_MINT_refresh_melt (struct TALER_MINT_Handle *mint,
- size_t refresh_data_length,
- const char *refresh_data,
- TALER_MINT_RefreshMeltCallback melt_cb,
- void *melt_cb_cls)
-{
- json_t *melt_obj;
- json_t *new_denoms;
- json_t *melt_coins;
- json_t *coin_evs;
- json_t *transfer_pubs;
- json_t *secret_encs;
- json_t *link_encs;
- json_t *tmp;
- struct TALER_MINT_RefreshMeltHandle *rmh;
- CURL *eh;
- struct TALER_MINT_Context *ctx;
- struct MeltData *md;
- unsigned int i;
- unsigned int j;
-
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- GNUNET_break (0);
- return NULL;
- }
- md = deserialize_melt_data (refresh_data,
- refresh_data_length);
- if (NULL == md)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- /* build JSON request, each of the 6 arrays first */
- new_denoms = json_array ();
- melt_coins = json_array ();
- coin_evs = json_array ();
- transfer_pubs = json_array ();
- secret_encs = json_array ();
- link_encs = json_array ();
- for (i=0;i<md->num_melted_coins;i++)
- {
- const struct MeltedCoin *mc = &md->melted_coins[i];
-
- /* now melt_coins */
- json_array_append (melt_coins,
- melted_coin_to_json (&md->melt_session_hash,
- mc));
- }
-
- /* now transfer_pubs */
- for (j=0;j<TALER_CNC_KAPPA;j++)
- {
- tmp = json_array ();
- for (i=0;i<md->num_melted_coins;i++)
- {
- const struct MeltedCoin *mc = &md->melted_coins[i];
- struct TALER_TransferPublicKeyP transfer_pub;
-
- GNUNET_CRYPTO_ecdhe_key_get_public (&mc->transfer_priv[j].ecdhe_priv,
- &transfer_pub.ecdhe_pub);
- json_array_append (tmp,
- TALER_json_from_data (&transfer_pub,
- sizeof (transfer_pub)));
- }
- json_array_append (transfer_pubs,
- tmp);
- }
-
- /* now secret_encs */
- for (j=0;j<TALER_CNC_KAPPA;j++)
- {
- tmp = json_array ();
- for (i=0;i<md->num_melted_coins;i++)
- {
- const struct MeltedCoin *mc = &md->melted_coins[i];
- struct TALER_EncryptedLinkSecretP els;
- struct TALER_TransferSecretP trans_sec;
-
- TALER_link_derive_transfer_secret (&mc->coin_priv,
- &mc->transfer_priv[j],
- &trans_sec);
- GNUNET_assert (GNUNET_OK ==
- TALER_transfer_encrypt (&md->link_secrets[j],
- &trans_sec,
- &els));
- json_array_append (tmp,
- TALER_json_from_data (&els,
- sizeof (els)));
- }
- json_array_append (secret_encs,
- tmp);
- }
-
- /* now new_denoms */
- for (i=0;i<md->num_fresh_coins;i++)
- {
- json_array_append (new_denoms,
- TALER_json_from_rsa_public_key
- (md->fresh_pks[i].rsa_public_key));
- }
-
- /* now link_encs */
- for (j=0;j<TALER_CNC_KAPPA;j++)
- {
- tmp = json_array ();
- for (i=0;i<md->num_fresh_coins;i++)
- {
- const struct FreshCoin *fc = &md->fresh_coins[j][i];
- struct TALER_RefreshLinkDecrypted rld;
- struct TALER_RefreshLinkEncrypted *rle;
- char *buf;
- size_t buf_len;
-
- rld.coin_priv = fc->coin_priv;
- rld.blinding_key = fc->blinding_key;
- rle = TALER_refresh_encrypt (&rld,
- &md->link_secrets[j]);
- GNUNET_assert (NULL != rle);
- buf = TALER_refresh_link_encrypted_encode (rle,
- &buf_len);
- GNUNET_assert (NULL != buf);
- json_array_append (tmp,
- TALER_json_from_data (buf,
- buf_len));
- GNUNET_free (buf);
- GNUNET_free (rle);
- }
- json_array_append (link_encs,
- tmp);
- }
-
- /* now coin_evs */
- for (j=0;j<TALER_CNC_KAPPA;j++)
- {
- tmp = json_array ();
- for (i=0;i<md->num_fresh_coins;i++)
- {
- const struct FreshCoin *fc = &md->fresh_coins[j][i];
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct GNUNET_HashCode coin_hash;
- char *coin_ev; /* blinded message to be signed (in envelope) for each coin */
- size_t coin_ev_size;
-
- 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);
- coin_ev_size = GNUNET_CRYPTO_rsa_blind (&coin_hash,
- fc->blinding_key.rsa_blinding_key,
- md->fresh_pks[i].rsa_public_key,
- &coin_ev);
- json_array_append (tmp,
- TALER_json_from_data (coin_ev,
- coin_ev_size));
- GNUNET_free (coin_ev);
- }
- json_array_append (coin_evs,
- tmp);
- }
-
- /* finally, assemble main JSON request from constitutent arrays */
- melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}",
- "new_denoms", new_denoms,
- "melt_coins", melt_coins,
- "coin_evs", coin_evs,
- "transfer_pubs", transfer_pubs,
- "secret_encs", secret_encs,
- "link_encs", link_encs);
-
- /* and now we can at last begin the actual request handling */
- rmh = GNUNET_new (struct TALER_MINT_RefreshMeltHandle);
- rmh->mint = mint;
- rmh->melt_cb = melt_cb;
- rmh->melt_cb_cls = melt_cb_cls;
- rmh->md = md;
- rmh->url = MAH_path_to_url (mint,
- "/refresh/melt");
-
- eh = curl_easy_init ();
- 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_URL,
- rmh->url));
- 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)));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &rmh->db));
- ctx = MAH_handle_to_context (mint);
- rmh->job = MAC_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_MINT_refresh_melt_cancel (struct TALER_MINT_RefreshMeltHandle *rmh)
-{
- if (NULL != rmh->job)
- {
- MAC_job_cancel (rmh->job);
- rmh->job = NULL;
- }
- GNUNET_free_non_null (rmh->db.buf);
- 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_MINT_RefreshRevealHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_RefreshRevealCallback reveal_cb;
-
- /**
- * Closure for @e reveal_cb.
- */
- void *reveal_cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
- /**
- * Actual information about the melt operation.
- */
- struct MeltData *md;
-
- /**
- * The index selected by the mint 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 mint 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 mint
- * @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_MINT_RefreshRevealHandle *rrh,
- json_t *json,
- struct TALER_CoinSpendPrivateKeyP *coin_privs,
- struct TALER_DenominationSignature *sigs)
-{
- unsigned int i;
- json_t *jsona;
- struct MAJ_Specification spec[] = {
- MAJ_spec_json ("ev_sigs", &jsona),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (! json_is_array (jsona))
- {
- /* We expected an array of coins */
- GNUNET_break_op (0);
- 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);
- return GNUNET_SYSERR;
- }
- for (i=0;i<rrh->md->num_fresh_coins;i++)
- {
- const struct FreshCoin *fc;
- struct TALER_DenominationPublicKey *pk;
- json_t *jsonai;
- struct GNUNET_CRYPTO_rsa_Signature *blind_sig;
- struct GNUNET_CRYPTO_rsa_Signature *sig;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct GNUNET_HashCode coin_hash;
-
- struct MAJ_Specification spec[] = {
- MAJ_spec_rsa_signature ("ev_sig", &blind_sig),
- MAJ_spec_end
- };
-
- 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 !=
- MAJ_parse_json (jsonai,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* unblind the signature */
- sig = GNUNET_CRYPTO_rsa_unblind (blind_sig,
- fc->blinding_key.rsa_blinding_key,
- pk->rsa_public_key);
- GNUNET_CRYPTO_rsa_signature_free (blind_sig);
-
- /* verify the signature */
- 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 !=
- GNUNET_CRYPTO_rsa_verify (&coin_hash,
- sig,
- pk->rsa_public_key))
- {
- GNUNET_break_op (0);
- GNUNET_CRYPTO_rsa_signature_free (sig);
- return GNUNET_SYSERR;
- }
- coin_privs[i] = fc->coin_priv;
- sigs[i].rsa_signature = sig;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /refresh/reveal request.
- *
- * @param cls the `struct TALER_MINT_RefreshHandle`
- * @param eh the curl request handle
- */
-static void
-handle_refresh_reveal_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_RefreshRevealHandle *rrh = cls;
- long response_code;
- json_t *json;
-
- rrh->job = NULL;
- json = MAC_download_get_result (&rrh->db,
- eh,
- &response_code);
- 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];
- unsigned int i;
- int ret;
-
- memset (sigs, 0, sizeof (sigs));
- ret = refresh_reveal_ok (rrh,
- json,
- coin_privs,
- sigs);
- if (GNUNET_OK != ret)
- {
- response_code = 0;
- }
- else
- {
- rrh->reveal_cb (rrh->reveal_cb_cls,
- MHD_HTTP_OK,
- rrh->md->num_fresh_coins,
- coin_privs,
- sigs,
- json);
- rrh->reveal_cb = NULL;
- }
- for (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 mint is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_CONFLICT:
- /* Nothing really to verify, mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- if (NULL != rrh->reveal_cb)
- rrh->reveal_cb (rrh->reveal_cb_cls,
- response_code,
- 0, NULL, NULL,
- json);
- json_decref (json);
- TALER_MINT_refresh_reveal_cancel (rrh);
-}
-
-
-/**
- * Submit a /refresh/reval request to the mint and get the mint'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 mint the mint handle; the mint must be ready to operate
- * @param refresh_data_length size of the @a refresh_data (returned
- * in the `res_size` argument from #TALER_MINT_refresh_prepare())
- * @param refresh_data the refresh data as returned from
- #TALER_MINT_refresh_prepare())
- * @param noreveal_index response from the mint to the
- * #TALER_MINT_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_MINT_RefreshRevealHandle *
-TALER_MINT_refresh_reveal (struct TALER_MINT_Handle *mint,
- size_t refresh_data_length,
- const char *refresh_data,
- uint16_t noreveal_index,
- TALER_MINT_RefreshRevealCallback reveal_cb,
- void *reveal_cb_cls)
-{
- struct TALER_MINT_RefreshRevealHandle *rrh;
- json_t *transfer_privs;
- json_t *reveal_obj;
- json_t *tmp;
- CURL *eh;
- struct TALER_MINT_Context *ctx;
- struct MeltData *md;
- unsigned int i;
- unsigned int j;
-
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- GNUNET_break (0);
- return NULL;
- }
- 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 mint replied, but maybe
- we had some internal corruption that changed the value... */
- GNUNET_break (0);
- return NULL;
- }
-
- /* build array of transfer private keys */
- transfer_privs = json_array ();
- for (j=0;j<TALER_CNC_KAPPA;j++)
- {
- if (j == noreveal_index)
- {
- /* This is crucial: exclude the transfer key for the
- noreval index! */
- continue;
- }
- tmp = json_array ();
- for (i=0;i<md->num_melted_coins;i++)
- {
- const struct MeltedCoin *mc = &md->melted_coins[i];
-
- json_array_append (tmp,
- TALER_json_from_data (&mc->transfer_priv[j],
- sizeof (struct TALER_TransferPrivateKeyP)));
- }
- json_array_append (transfer_privs,
- tmp);
- }
-
- /* build main JSON request */
- reveal_obj = json_pack ("{s:o, s:o}",
- "session_hash",
- TALER_json_from_data (&md->melt_session_hash,
- sizeof (struct GNUNET_HashCode)),
- "transfer_privs",
- transfer_privs);
-
- /* finally, we can actually issue the request */
- rrh = GNUNET_new (struct TALER_MINT_RefreshRevealHandle);
- rrh->mint = mint;
- rrh->noreveal_index = noreveal_index;
- rrh->reveal_cb = reveal_cb;
- rrh->reveal_cb_cls = reveal_cb_cls;
- rrh->md = md;
- rrh->url = MAH_path_to_url (rrh->mint,
- "/refresh/reveal");
-
- eh = curl_easy_init ();
- 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_URL,
- rrh->url));
- 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)));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &rrh->db));
- ctx = MAH_handle_to_context (rrh->mint);
- rrh->job = MAC_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_MINT_refresh_reveal_cancel (struct TALER_MINT_RefreshRevealHandle *rrh)
-{
- if (NULL != rrh->job)
- {
- MAC_job_cancel (rrh->job);
- rrh->job = NULL;
- }
- GNUNET_free_non_null (rrh->db.buf);
- 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 mint_api_refresh.c */
diff --git a/src/mint-lib/mint_api_refresh_link.c b/src/mint-lib/mint_api_refresh_link.c
deleted file mode 100644
index dcd2326ca..000000000
--- a/src/mint-lib/mint_api_refresh_link.c
+++ /dev/null
@@ -1,482 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_refresh_link.c
- * @brief Implementation of the /refresh/link request of the mint's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.h"
-
-
-/**
- * @brief A /refresh/link Handle
- */
-struct TALER_MINT_RefreshLinkHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_RefreshLinkCallback link_cb;
-
- /**
- * Closure for @e cb.
- */
- void *link_cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
- /**
- * 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 trans_pub our transfer public key
- * @param secret_enc encrypted key to decrypt link data
- * @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_MINT_RefreshLinkHandle *rlh,
- json_t *json,
- const struct TALER_TransferPublicKeyP *trans_pub,
- const struct TALER_EncryptedLinkSecretP *secret_enc,
- struct TALER_CoinSpendPrivateKeyP *coin_priv,
- struct TALER_DenominationSignature *sig,
- struct TALER_DenominationPublicKey *pub)
-{
- void *link_enc;
- size_t link_enc_size;
- struct GNUNET_CRYPTO_rsa_Signature *bsig;
- struct GNUNET_CRYPTO_rsa_PublicKey *rpub;
- struct MAJ_Specification spec[] = {
- MAJ_spec_varsize ("link_enc", &link_enc, &link_enc_size),
- MAJ_spec_rsa_public_key ("denom_pub", &rpub),
- MAJ_spec_rsa_signature ("ev_sig", &bsig),
- MAJ_spec_end
- };
- struct TALER_RefreshLinkEncrypted *rle;
- struct TALER_RefreshLinkDecrypted *rld;
- struct TALER_LinkSecretP secret;
-
- /* parse reply */
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* decode and decrypt link data */
- rle = TALER_refresh_link_encrypted_decode (link_enc,
- link_enc_size);
- if (NULL == rle)
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_link_decrypt_secret2 (secret_enc,
- trans_pub,
- &rlh->coin_priv,
- &secret))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- rld = TALER_refresh_decrypt (rle,
- &secret);
- if (NULL == rld)
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
-
- /* extract coin and signature */
- *coin_priv = rld->coin_priv;
- sig->rsa_signature
- = GNUNET_CRYPTO_rsa_unblind (bsig,
- rld->blinding_key.rsa_blinding_key,
- rpub);
-
- /* clean up */
- GNUNET_free (rld);
- pub->rsa_public_key = GNUNET_CRYPTO_rsa_public_key_dup (rpub);
- MAJ_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_MINT_RefreshLinkHandle *rlh,
- 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 MAJ_Specification spec[] = {
- MAJ_spec_json ("new_coins", &jsona),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json_array_get (json,
- session),
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (! json_is_array (jsona))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
-
- /* count all coins over all sessions */
- num_coins += json_array_size (jsona);
- MAJ_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 TALER_EncryptedLinkSecretP secret_enc;
- struct MAJ_Specification spec[] = {
- MAJ_spec_json ("new_coins", &jsona),
- MAJ_spec_fixed_auto ("transfer_pub", &trans_pub),
- MAJ_spec_fixed_auto ("secret_enc", &secret_enc),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json_array_get (json,
- session),
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (! json_is_array (jsona))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
-
- /* decode all coins */
- for (i=0;i<json_array_size (jsona);i++)
- {
- if (GNUNET_OK !=
- parse_refresh_link_coin (rlh,
- json_array_get (jsona,
- i),
- &trans_pub,
- &secret_enc,
- &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;
- MAJ_parse_free (spec);
- break;
- }
- MAJ_parse_free (spec);
- } /* end of for (session) */
-
- if (off_coin == num_coins)
- {
- rlh->link_cb (rlh->link_cb_cls,
- MHD_HTTP_OK,
- num_coins,
- coin_privs,
- sigs,
- pubs,
- json);
- rlh->link_cb = NULL;
- ret = GNUNET_OK;
- }
- else
- {
- GNUNET_break_op (0);
- ret = GNUNET_SYSERR;
- }
-
- /* clean up */
- 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_MINT_RefreshLinkHandle`
- * @param eh the curl request handle
- */
-static void
-handle_refresh_link_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_RefreshLinkHandle *rlh = cls;
- long response_code;
- json_t *json;
-
- rlh->job = NULL;
- json = MAC_download_get_result (&rlh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- parse_refresh_link_ok (rlh,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_NOT_FOUND:
- /* Nothing really to verify, mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- if (NULL != rlh->link_cb)
- rlh->link_cb (rlh->link_cb_cls,
- response_code,
- 0, NULL, NULL, NULL,
- json);
- json_decref (json);
- TALER_MINT_refresh_link_cancel (rlh);
-}
-
-
-/**
- * Submit a link request to the mint and get the mint'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 mint the mint handle; the mint 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_MINT_RefreshLinkHandle *
-TALER_MINT_refresh_link (struct TALER_MINT_Handle *mint,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- TALER_MINT_RefreshLinkCallback link_cb,
- void *link_cb_cls)
-{
- struct TALER_MINT_RefreshLinkHandle *rlh;
- CURL *eh;
- struct TALER_MINT_Context *ctx;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- char *pub_str;
- char *arg_str;
-
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- 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_MINT_RefreshLinkHandle);
- rlh->mint = mint;
- rlh->link_cb = link_cb;
- rlh->link_cb_cls = link_cb_cls;
- rlh->coin_priv = *coin_priv;
- rlh->url = MAH_path_to_url (mint, arg_str);
- GNUNET_free (arg_str);
-
- eh = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- rlh->url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &rlh->db));
- ctx = MAH_handle_to_context (mint);
- rlh->job = MAC_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_MINT_refresh_link_cancel (struct TALER_MINT_RefreshLinkHandle *rlh)
-{
- if (NULL != rlh->job)
- {
- MAC_job_cancel (rlh->job);
- rlh->job = NULL;
- }
- GNUNET_free_non_null (rlh->db.buf);
- GNUNET_free (rlh->url);
- GNUNET_free (rlh);
-}
-
-
-/* end of mint_api_refresh_link.c */
diff --git a/src/mint-lib/mint_api_reserve.c b/src/mint-lib/mint_api_reserve.c
deleted file mode 100644
index 1f8140cff..000000000
--- a/src/mint-lib/mint_api_reserve.c
+++ /dev/null
@@ -1,930 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_reserve.c
- * @brief Implementation of the /reserve requests of the mint's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.h"
-
-
-/* ********************** /reserve/status ********************** */
-
-/**
- * @brief A Withdraw Status Handle
- */
-struct TALER_MINT_ReserveStatusHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_ReserveStatusResultCallback cb;
-
- /**
- * Public key of the reserve we are querying.
- */
- struct TALER_ReservePublicKeyP reserve_pub;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
-};
-
-
-/**
- * Parse history given in JSON format and return it in binary
- * format.
- *
- * @param[in] 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 (json_t *history,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const char *currency,
- struct TALER_Amount *balance,
- unsigned int history_length,
- struct TALER_MINT_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;
-
- TALER_amount_get_zero (currency,
- &total_in);
- 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 MAJ_Specification hist_spec[] = {
- MAJ_spec_string ("type", &type),
- MAJ_spec_amount ("amount",
- &amount),
- /* 'wire' and 'signature' are optional depending on 'type'! */
- MAJ_spec_end
- };
-
- transaction = json_array_get (history,
- off);
- if (GNUNET_OK !=
- MAJ_parse_json (transaction,
- hist_spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rhistory[off].amount = amount;
-
- if (0 == strcasecmp (type,
- "DEPOSIT"))
- {
- json_t *wire;
-
- rhistory[off].type = TALER_MINT_RTT_DEPOSIT;
- if (GNUNET_OK !=
- TALER_amount_add (&total_in,
- &total_in,
- &amount))
- {
- /* overflow in history already!? inconceivable! Bad mint! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- wire = json_object_get (transaction,
- "wire");
- /* check 'wire' is a JSON object (no need to check wireformat,
- but we do at least expect "some" JSON object here) */
- if ( (NULL == wire) ||
- (! json_is_object (wire)) )
- {
- /* not even a JSON 'wire' specification, not acceptable */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rhistory[off].details.wire_in_details = wire;
- /* end type==DEPOSIT */
- }
- else if (0 == strcasecmp (type,
- "WITHDRAW"))
- {
- struct TALER_ReserveSignatureP sig;
- struct TALER_WithdrawRequestPS withdraw_purpose;
- struct TALER_Amount amount_from_purpose;
- struct MAJ_Specification withdraw_spec[] = {
- MAJ_spec_fixed_auto ("signature",
- &sig),
- MAJ_spec_fixed_auto ("details",
- &withdraw_purpose),
- MAJ_spec_end
- };
- unsigned int i;
-
- rhistory[off].type = TALER_MINT_RTT_WITHDRAWAL;
- if (GNUNET_OK !=
- MAJ_parse_json (transaction,
- withdraw_spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* 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);
- MAJ_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- TALER_amount_ntoh (&amount_from_purpose,
- &withdraw_purpose.amount_with_fee);
- if (0 != TALER_amount_cmp (&amount,
- &amount_from_purpose))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- rhistory[off].details.out_authorization_sig = json_object_get (transaction,
- "signature");
- /* Check check that the same withdraw transaction
- isn't listed twice by the mint. 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);
- MAJ_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 mint! */
- GNUNET_break_op (0);
- MAJ_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- /* end type==WITHDRAW */
- }
- 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 mint ever allow this!? */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /reserve/status request.
- *
- * @param cls the `struct TALER_MINT_ReserveStatusHandle`
- * @param eh curl handle of the request that finished
- */
-static void
-handle_reserve_status_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_ReserveStatusHandle *wsh = cls;
- long response_code;
- json_t *json;
-
- wsh->job = NULL;
- json = MAC_download_get_result (&wsh->db,
- eh,
- &response_code);
- 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 MAJ_Specification spec[] = {
- MAJ_spec_amount ("balance", &balance),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- history = json_object_get (json,
- "history");
- if (NULL == history)
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- len = json_array_size (history);
- {
- struct TALER_MINT_ReserveHistory rhistory[len];
-
- if (GNUNET_OK !=
- parse_reserve_history (history,
- &wsh->reserve_pub,
- balance.currency,
- &balance_from_history,
- len,
- rhistory))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- if (0 !=
- TALER_amount_cmp (&balance_from_history,
- &balance))
- {
- /* mint cannot add up balances!? */
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- wsh->cb (wsh->cb_cls,
- response_code,
- json,
- &balance,
- len,
- rhistory);
- wsh->cb = NULL;
- }
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- if (NULL != wsh->cb)
- wsh->cb (wsh->cb_cls,
- response_code,
- json,
- NULL,
- 0, NULL);
- json_decref (json);
- TALER_MINT_reserve_status_cancel (wsh);
-}
-
-
-/**
- * Submit a request to obtain the transaction history of a reserve
- * from the mint. 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 mint's
- * reply is not well-formed, we return an HTTP status code of zero to
- * @a cb.
- *
- * @param mint the mint handle; the mint 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_MINT_ReserveStatusHandle *
-TALER_MINT_reserve_status (struct TALER_MINT_Handle *mint,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- TALER_MINT_ReserveStatusResultCallback cb,
- void *cb_cls)
-{
- struct TALER_MINT_ReserveStatusHandle *wsh;
- struct TALER_MINT_Context *ctx;
- CURL *eh;
- char *pub_str;
- char *arg_str;
-
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- 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);
- wsh = GNUNET_new (struct TALER_MINT_ReserveStatusHandle);
- wsh->mint = mint;
- wsh->cb = cb;
- wsh->cb_cls = cb_cls;
- wsh->reserve_pub = *reserve_pub;
- wsh->url = MAH_path_to_url (mint,
- arg_str);
- GNUNET_free (arg_str);
-
- eh = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- wsh->url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &wsh->db));
- ctx = MAH_handle_to_context (mint);
- wsh->job = MAC_job_add (ctx,
- eh,
- GNUNET_NO,
- &handle_reserve_status_finished,
- wsh);
- 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 wsh the withdraw status request handle
- */
-void
-TALER_MINT_reserve_status_cancel (struct TALER_MINT_ReserveStatusHandle *wsh)
-{
- if (NULL != wsh->job)
- {
- MAC_job_cancel (wsh->job);
- wsh->job = NULL;
- }
- GNUNET_free_non_null (wsh->db.buf);
- GNUNET_free (wsh->url);
- GNUNET_free (wsh);
-}
-
-
-/* ********************** /reserve/withdraw ********************** */
-
-/**
- * @brief A Withdraw Sign Handle
- */
-struct TALER_MINT_ReserveWithdrawHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * JSON encoding of the request to POST.
- */
- char *json_enc;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_ReserveWithdrawResultCallback cb;
-
- /**
- * Key used to blind the value.
- */
- const struct TALER_DenominationBlindingKey *blinding_key;
-
- /**
- * Denomination key we are withdrawing.
- */
- const struct TALER_MINT_DenomPublicKey *pk;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
- /**
- * 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 mint 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 mint
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static int
-reserve_withdraw_ok (struct TALER_MINT_ReserveWithdrawHandle *wsh,
- json_t *json)
-{
- struct GNUNET_CRYPTO_rsa_Signature *blind_sig;
- struct GNUNET_CRYPTO_rsa_Signature *sig;
- struct TALER_DenominationSignature dsig;
- struct MAJ_Specification spec[] = {
- MAJ_spec_rsa_signature ("ev_sig", &blind_sig),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- sig = GNUNET_CRYPTO_rsa_unblind (blind_sig,
- wsh->blinding_key->rsa_blinding_key,
- wsh->pk->key.rsa_public_key);
- GNUNET_CRYPTO_rsa_signature_free (blind_sig);
- if (GNUNET_OK !=
- GNUNET_CRYPTO_rsa_verify (&wsh->c_hash,
- sig,
- wsh->pk->key.rsa_public_key))
- {
- GNUNET_break_op (0);
- GNUNET_CRYPTO_rsa_signature_free (sig);
- return GNUNET_SYSERR;
- }
- /* signature is valid, return it to the application */
- dsig.rsa_signature = sig;
- wsh->cb (wsh->cb_cls,
- MHD_HTTP_OK,
- &dsig,
- json);
- /* make sure callback isn't called again after return */
- wsh->cb = NULL;
- GNUNET_CRYPTO_rsa_signature_free (sig);
- return GNUNET_OK;
-}
-
-
-/**
- * We got a 402 PAYMENT REQUIRED 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 mint 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 mint
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static int
-reserve_withdraw_payment_required (struct TALER_MINT_ReserveWithdrawHandle *wsh,
- 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 MAJ_Specification spec[] = {
- MAJ_spec_amount ("balance", &balance),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- 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_MINT_ReserveHistory rhistory[len];
-
- if (GNUNET_OK !=
- parse_reserve_history (history,
- &wsh->reserve_pub,
- balance.currency,
- &balance_from_history,
- len,
- rhistory))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
-
- if (0 !=
- TALER_amount_cmp (&balance_from_history,
- &balance))
- {
- /* mint 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_MINT_ReserveWithdrawHandle`
- * @param eh curl handle of the request that finished
- */
-static void
-handle_reserve_withdraw_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_ReserveWithdrawHandle *wsh = cls;
- long response_code;
- json_t *json;
-
- wsh->job = NULL;
- json = MAC_download_get_result (&wsh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- reserve_withdraw_ok (wsh,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_PAYMENT_REQUIRED:
- /* The mint says that the reserve has insufficient funds;
- check the signatures in the history... */
- if (GNUNET_OK !=
- reserve_withdraw_payment_required (wsh,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- }
- break;
- case MHD_HTTP_UNAUTHORIZED:
- GNUNET_break (0);
- /* Nothing really to verify, mint 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 mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- if (NULL != wsh->cb)
- wsh->cb (wsh->cb_cls,
- response_code,
- NULL,
- json);
- json_decref (json);
- TALER_MINT_reserve_withdraw_cancel (wsh);
-}
-
-
-/**
- * Withdraw a coin from the mint 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 mint the mint handle; the mint must be ready to operate
- * @param pk kind of coin to create
- * @param reserve_priv private key of the reserve to withdraw from
- * @param coin_priv where to store the coin's private key,
- * caller must have committed this value to disk before the call (with @a pk)
- * @param blinding_key where to store the coin's blinding key
- * 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 #GNUNET_OK on success, #GNUNET_SYSERR
- * if the inputs are invalid (i.e. denomination key not with this mint).
- * In this case, the callback is not called.
- */
-struct TALER_MINT_ReserveWithdrawHandle *
-TALER_MINT_reserve_withdraw (struct TALER_MINT_Handle *mint,
- const struct TALER_MINT_DenomPublicKey *pk,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- const struct TALER_DenominationBlindingKey *blinding_key,
- TALER_MINT_ReserveWithdrawResultCallback res_cb,
- void *res_cb_cls)
-{
- struct TALER_MINT_ReserveWithdrawHandle *wsh;
- struct TALER_WithdrawRequestPS req;
- struct TALER_ReserveSignatureP reserve_sig;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_MINT_Context *ctx;
- struct TALER_Amount amount_with_fee;
- char *coin_ev;
- size_t coin_ev_size;
- json_t *withdraw_obj;
- CURL *eh;
-
- wsh = GNUNET_new (struct TALER_MINT_ReserveWithdrawHandle);
- wsh->mint = mint;
- wsh->cb = res_cb;
- wsh->cb_cls = res_cb_cls;
- wsh->pk = pk;
-
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
- &coin_pub.eddsa_pub);
- GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
- &wsh->c_hash);
- coin_ev_size = GNUNET_CRYPTO_rsa_blind (&wsh->c_hash,
- blinding_key->rsa_blinding_key,
- pk->key.rsa_public_key,
- &coin_ev);
- GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
- &wsh->reserve_pub.eddsa_pub);
- req.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
- req.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
- req.reserve_pub = wsh->reserve_pub;
- if (GNUNET_OK !=
- TALER_amount_add (&amount_with_fee,
- &pk->fee_withdraw,
- &pk->value))
- {
- /* mint gave us denomination keys that overflow like this!? */
- GNUNET_break_op (0);
- GNUNET_free (coin_ev);
- GNUNET_free (wsh);
- return NULL;
- }
- TALER_amount_hton (&req.amount_with_fee,
- &amount_with_fee);
- TALER_amount_hton (&req.withdraw_fee,
- &pk->fee_withdraw);
- GNUNET_CRYPTO_rsa_public_key_hash (pk->key.rsa_public_key,
- &req.h_denomination_pub);
- GNUNET_CRYPTO_hash (coin_ev,
- 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));
- withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub and coin_ev */
- " s:o, s:o}",/* reserve_pub and reserve_sig */
- "denom_pub", TALER_json_from_rsa_public_key (pk->key.rsa_public_key),
- "coin_ev", TALER_json_from_data (coin_ev,
- coin_ev_size),
- "reserve_pub", TALER_json_from_data (&wsh->reserve_pub,
- sizeof (struct TALER_ReservePublicKeyP)),
- "reserve_sig", TALER_json_from_data (&reserve_sig,
- sizeof (reserve_sig)));
- GNUNET_free (coin_ev);
-
- wsh->blinding_key = blinding_key;
- wsh->url = MAH_path_to_url (mint, "/reserve/withdraw");
-
- eh = curl_easy_init ();
- 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_URL,
- wsh->url));
- 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)));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &wsh->db));
- ctx = MAH_handle_to_context (mint);
- wsh->job = MAC_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_reserve_withdraw_finished,
- wsh);
- 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_MINT_reserve_withdraw_cancel (struct TALER_MINT_ReserveWithdrawHandle *sign)
-{
- if (NULL != sign->job)
- {
- MAC_job_cancel (sign->job);
- sign->job = NULL;
- }
- GNUNET_free_non_null (sign->db.buf);
- GNUNET_free (sign->url);
- GNUNET_free (sign->json_enc);
- GNUNET_free (sign);
-}
-
-
-/* end of mint_api_reserve.c */
diff --git a/src/mint-lib/mint_api_wire.c b/src/mint-lib/mint_api_wire.c
deleted file mode 100644
index 0947354ad..000000000
--- a/src/mint-lib/mint_api_wire.c
+++ /dev/null
@@ -1,620 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_wire.c
- * @brief Implementation of the /wire request of the mint's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "mint_api_common.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.h"
-
-
-/**
- * @brief A Wire Handle
- */
-struct TALER_MINT_WireHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_WireResultCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
- /**
- * Set to the "methods" JSON array returned by the
- * /wire request.
- */
- json_t *methods;
-
- /**
- * Current iteration offset in the @e methods array.
- */
- unsigned int methods_off;
-
-};
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * for /wire/sepa from the mint is valid.
- *
- * @param wh wire handle
- * @param json json reply with the signature
- * @return #GNUNET_SYSERR if @a json is invalid,
- * #GNUNET_NO if the method is unknown,
- * #GNUNET_OK if the json is valid
- */
-static int
-verify_wire_sepa_signature_ok (const struct TALER_MINT_WireHandle *wh,
- json_t *json)
-{
- struct TALER_MasterSignatureP mint_sig;
- struct TALER_MasterWireSepaDetailsPS mp;
- const char *receiver_name;
- const char *iban;
- const char *bic;
- const struct TALER_MINT_Keys *key_state;
- struct GNUNET_HashContext *hc;
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("sig", &mint_sig),
- MAJ_spec_string ("receiver_name", &receiver_name),
- MAJ_spec_string ("iban", &iban),
- MAJ_spec_string ("bic", &bic),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- key_state = TALER_MINT_get_keys (wh->mint);
- mp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SEPA_DETAILS);
- mp.purpose.size = htonl (sizeof (struct TALER_MasterWireSepaDetailsPS));
- hc = GNUNET_CRYPTO_hash_context_start ();
- GNUNET_CRYPTO_hash_context_read (hc,
- receiver_name,
- strlen (receiver_name) + 1);
- GNUNET_CRYPTO_hash_context_read (hc,
- iban,
- strlen (iban) + 1);
- GNUNET_CRYPTO_hash_context_read (hc,
- bic,
- strlen (bic) + 1);
- GNUNET_CRYPTO_hash_context_finish (hc,
- &mp.h_sepa_details);
-
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SEPA_DETAILS,
- &mp.purpose,
- &mint_sig.eddsa_signature,
- &key_state->master_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return GNUNET_SYSERR;
- }
- MAJ_parse_free (spec);
- return GNUNET_OK;
-}
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * for /wire/METHOD from the mint is valid.
- *
- * @param wh wire handle with key material
- * @param method method to verify the reply for
- * @param json json reply with the signature
- * @return #GNUNET_SYSERR if @a json is invalid,
- * #GNUNET_NO if the method is unknown,
- * #GNUNET_OK if the json is valid
- */
-static int
-verify_wire_method_signature_ok (const struct TALER_MINT_WireHandle *wh,
- const char *method,
- json_t *json)
-{
- struct
- {
- /**
- * Name fo the method.
- */
- const char *method;
-
- /**
- * Handler to invoke to verify signature.
- *
- * @param wh wire handle with key material
- * @param json json reply with signature to verify
- */
- int (*handler)(const struct TALER_MINT_WireHandle *wh,
- json_t *json);
- } handlers[] = {
- { "sepa", &verify_wire_sepa_signature_ok },
- { NULL, NULL }
- };
- unsigned int i;
-
- for (i=0;NULL != handlers[i].method; i++)
- if (0 == strcasecmp (handlers[i].method,
- method))
- return handlers[i].handler (wh,
- json);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Wire transfer method `%s' not supported\n",
- method);
- return GNUNET_NO;
-}
-
-
-/**
- * Perform the next /wire/method request or signal
- * the end of the iteration.
- *
- * @param wh the wire handle
- * @return a handle for this request
- */
-static void
-request_wire_method (struct TALER_MINT_WireHandle *wh);
-
-
-/**
- * Function called when we're done processing the
- * HTTP /wire/METHOD request.
- *
- * @param cls the `struct TALER_MINT_WireHandle`
- * @param eh the curl request handle
- */
-static void
-handle_wire_method_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_WireHandle *wh = cls;
- long response_code;
- json_t *json;
-
- wh->job = NULL;
- json = MAC_download_get_result (&wh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- const char *method;
-
- method = json_string_value (json_array_get (wh->methods,
- wh->methods_off - 1));
- if (GNUNET_OK !=
- verify_wire_method_signature_ok (wh,
- method,
- json))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- break;
- }
- case MHD_HTTP_FOUND:
- /* /wire/test returns a 302 redirect, we should just give
- this information back to the callback below */
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- if (0 == response_code)
- {
- /* signal end of iteration */
- wh->cb (wh->cb_cls,
- 0,
- NULL,
- NULL);
- json_decref (json);
- TALER_MINT_wire_cancel (wh);
- return;
- }
- /* pass on successful reply */
- wh->cb (wh->cb_cls,
- response_code,
- json_string_value (json_array_get (wh->methods,
- wh->methods_off-1)),
- json);
- /* trigger request for the next /wire/method */
- request_wire_method (wh);
-}
-
-
-/**
- * Perform the next /wire/method request or signal
- * the end of the iteration.
- *
- * @param wh the wire handle
- * @return a handle for this request
- */
-static void
-request_wire_method (struct TALER_MINT_WireHandle *wh)
-{
- struct TALER_MINT_Context *ctx;
- CURL *eh;
- char *path;
-
- if (json_array_size (wh->methods) <= wh->methods_off)
- {
- /* we are done, signal end of iteration */
- wh->cb (wh->cb_cls,
- 0,
- NULL,
- NULL);
- TALER_MINT_wire_cancel (wh);
- return;
- }
- GNUNET_free_non_null (wh->db.buf);
- wh->db.buf = NULL;
- wh->db.buf_size = 0;
- wh->db.eno = 0;
- GNUNET_free_non_null (wh->url);
- GNUNET_asprintf (&path,
- "/wire/%s",
- json_string_value (json_array_get (wh->methods,
- wh->methods_off++)));
- wh->url = MAH_path_to_url (wh->mint,
- path);
- GNUNET_free (path);
-
- eh = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- wh->url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &wh->db));
- /* The default is 'disabled', but let's be sure */
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_FOLLOWLOCATION,
- (long) 0));
- ctx = MAH_handle_to_context (wh->mint);
- wh->job = MAC_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_wire_method_finished,
- wh);
- TALER_MINT_perform (ctx);
-}
-
-
-/**
- * Verify that the signature on the "200 OK" response
- * for /wire from the mint is valid.
- *
- * @param wh wire handle
- * @param json json reply with the signature
- * @return NULL if @a json is invalid, otherwise the
- * "methods" array (with an RC of 1)
- */
-static json_t *
-verify_wire_signature_ok (const struct TALER_MINT_WireHandle *wh,
- json_t *json)
-{
- struct TALER_MintSignatureP mint_sig;
- struct TALER_MintPublicKeyP mint_pub;
- struct TALER_MintWireSupportMethodsPS mp;
- json_t *methods;
- const struct TALER_MINT_Keys *key_state;
- struct GNUNET_HashContext *hc;
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("sig", &mint_sig),
- MAJ_spec_fixed_auto ("pub", &mint_pub),
- MAJ_spec_json ("methods", &methods),
- MAJ_spec_end
- };
- unsigned int i;
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- return NULL;
- }
- if (! json_is_array (methods))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return NULL;
- }
-
- key_state = TALER_MINT_get_keys (wh->mint);
- if (GNUNET_OK !=
- TALER_MINT_test_signing_key (key_state,
- &mint_pub))
- {
- GNUNET_break_op (0);
- return NULL;
- }
- hc = GNUNET_CRYPTO_hash_context_start ();
- for (i=0;i<json_array_size (methods);i++)
- {
- const json_t *element = json_array_get (methods, i);
- const char *method;
-
- if (! json_is_string (element))
- {
- GNUNET_CRYPTO_hash_context_abort (hc);
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return NULL;
- }
- method = json_string_value (element);
- GNUNET_CRYPTO_hash_context_read (hc,
- method,
- strlen (method) + 1);
- }
- mp.purpose.purpose = htonl (TALER_SIGNATURE_MINT_WIRE_TYPES);
- mp.purpose.size = htonl (sizeof (struct TALER_MintWireSupportMethodsPS));
- GNUNET_CRYPTO_hash_context_finish (hc,
- &mp.h_wire_types);
-
- if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_WIRE_TYPES,
- &mp.purpose,
- &mint_sig.eddsa_signature,
- &mint_pub.eddsa_pub))
- {
- GNUNET_break_op (0);
- MAJ_parse_free (spec);
- return NULL;
- }
- return methods;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /wire request.
- *
- * @param cls the `struct TALER_MINT_WireHandle`
- * @param eh the curl request handle
- */
-static void
-handle_wire_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_WireHandle *wh = cls;
- long response_code;
- json_t *json;
-
- wh->job = NULL;
- json = MAC_download_get_result (&wh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- json_t *methods;
-
- if (NULL ==
- (methods = verify_wire_signature_ok (wh,
- json)))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- wh->methods = methods;
- request_wire_method (wh);
- return;
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- if (0 != response_code)
- {
- /* pass on successful reply */
- wh->cb (wh->cb_cls,
- response_code,
- NULL,
- json);
- }
- /* signal end of iteration */
- wh->cb (wh->cb_cls,
- 0,
- NULL,
- NULL);
- if (NULL != json)
- json_decref (json);
- TALER_MINT_wire_cancel (wh);
-}
-
-
-/**
- * Obtain information about a mint's wire instructions.
- * A mint may provide wire instructions for creating
- * a reserve. The wire instructions also indicate
- * which wire formats merchants may use with the mint.
- * 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 mint's reply is not well-formed,
- * we return an HTTP status code of zero to @a cb.
- *
- * @param mint the mint handle; the mint 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_MINT_WireHandle *
-TALER_MINT_wire (struct TALER_MINT_Handle *mint,
- TALER_MINT_WireResultCallback wire_cb,
- void *wire_cb_cls)
-{
- struct TALER_MINT_WireHandle *wh;
- struct TALER_MINT_Context *ctx;
- CURL *eh;
-
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- GNUNET_break (0);
- return NULL;
- }
- wh = GNUNET_new (struct TALER_MINT_WireHandle);
- wh->mint = mint;
- wh->cb = wire_cb;
- wh->cb_cls = wire_cb_cls;
- wh->url = MAH_path_to_url (mint, "/wire");
-
- eh = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- wh->url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &wh->db));
- ctx = MAH_handle_to_context (mint);
- wh->job = MAC_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_MINT_wire_cancel (struct TALER_MINT_WireHandle *wh)
-{
- if (NULL != wh->job)
- {
- MAC_job_cancel (wh->job);
- wh->job = NULL;
- }
- if (NULL != wh->methods)
- {
- json_decref (wh->methods);
- wh->methods = NULL;
- }
- GNUNET_free_non_null (wh->db.buf);
- GNUNET_free (wh->url);
- GNUNET_free (wh);
-}
-
-
-/* end of mint_api_wire.c */
diff --git a/src/mint-lib/mint_api_wire_deposits.c b/src/mint-lib/mint_api_wire_deposits.c
deleted file mode 100644
index f71c5b696..000000000
--- a/src/mint-lib/mint_api_wire_deposits.c
+++ /dev/null
@@ -1,284 +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, If not, see
- <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint-lib/mint_api_wire_deposits.c
- * @brief Implementation of the /wire/deposits request of the mint's HTTP API
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <curl/curl.h>
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include "taler_mint_service.h"
-#include "mint_api_common.h"
-#include "mint_api_json.h"
-#include "mint_api_context.h"
-#include "mint_api_handle.h"
-#include "taler_signatures.h"
-
-
-/**
- * @brief A /wire/deposits Handle
- */
-struct TALER_MINT_WireDepositsHandle
-{
-
- /**
- * The connection to mint this request handle will use
- */
- struct TALER_MINT_Handle *mint;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct MAC_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MINT_WireDepositsCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Download buffer
- */
- struct MAC_DownloadBuffer db;
-
-};
-
-
-/**
- * Function called when we're done processing the
- * HTTP /wire/deposits request.
- *
- * @param cls the `struct TALER_MINT_WireDepositsHandle`
- * @param eh the curl request handle
- */
-static void
-handle_wire_deposits_finished (void *cls,
- CURL *eh)
-{
- struct TALER_MINT_WireDepositsHandle *wdh = cls;
- long response_code;
- json_t *json;
-
- wdh->job = NULL;
- json = MAC_download_get_result (&wdh->db,
- eh,
- &response_code);
- switch (response_code)
- {
- case 0:
- break;
- case MHD_HTTP_OK:
- {
- json_t *details_j;
- struct GNUNET_HashCode h_wire;
- struct TALER_Amount total_amount;
- struct TALER_MerchantPublicKeyP merchant_pub;
- unsigned int num_details;
- struct MAJ_Specification spec[] = {
- MAJ_spec_fixed_auto ("H_wire", &h_wire),
- MAJ_spec_fixed_auto ("merchant_pub", &merchant_pub),
- MAJ_spec_amount ("total_amount", &total_amount),
- MAJ_spec_json ("details", &details_j),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (json,
- spec))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- num_details = json_array_size (details_j);
- {
- struct TALER_WireDepositDetails details[num_details];
- unsigned int i;
-
- for (i=0;i<num_details;i++)
- {
- struct TALER_WireDepositDetails *detail = &details[i];
- struct json_t *detail_j = json_array_get (details_j, i);
- struct MAJ_Specification spec_detail[] = {
- MAJ_spec_fixed_auto ("H_contract", &detail->h_contract),
- MAJ_spec_amount ("deposit_value", &detail->coin_value),
- MAJ_spec_amount ("deposit_fee", &detail->coin_fee),
- MAJ_spec_uint64 ("transaction_id", &detail->transaction_id),
- MAJ_spec_fixed_auto ("coin_pub", &detail->coin_pub),
- MAJ_spec_end
- };
-
- if (GNUNET_OK !=
- MAJ_parse_json (detail_j,
- spec_detail))
- {
- GNUNET_break_op (0);
- response_code = 0;
- break;
- }
- }
- if (0 == response_code)
- break;
- wdh->cb (wdh->cb_cls,
- response_code,
- json,
- &h_wire,
- &total_amount,
- num_details,
- details);
- json_decref (json);
- TALER_MINT_wire_deposits_cancel (wdh);
- return;
- }
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the mint is buggy
- (or API version conflict); just pass JSON reply to the application */
- break;
- case MHD_HTTP_UNAUTHORIZED:
- /* Nothing really to verify, mint 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:
- /* Mint 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",
- response_code);
- GNUNET_break (0);
- response_code = 0;
- break;
- }
- wdh->cb (wdh->cb_cls,
- response_code,
- json,
- NULL, NULL, 0, NULL);
- json_decref (json);
- TALER_MINT_wire_deposits_cancel (wdh);
-}
-
-
-/**
- * Query the mint about which transactions were combined
- * to create a wire transfer.
- *
- * @param mint mint 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_MINT_WireDepositsHandle *
-TALER_MINT_wire_deposits (struct TALER_MINT_Handle *mint,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- TALER_MINT_WireDepositsCallback cb,
- void *cb_cls)
-{
- struct TALER_MINT_WireDepositsHandle *wdh;
- struct TALER_MINT_Context *ctx;
- char *buf;
- char *path;
- CURL *eh;
-
- if (GNUNET_YES !=
- MAH_handle_is_ready (mint))
- {
- GNUNET_break (0);
- return NULL;
- }
-
- wdh = GNUNET_new (struct TALER_MINT_WireDepositsHandle);
- wdh->mint = mint;
- wdh->cb = cb;
- wdh->cb_cls = cb_cls;
-
- buf = GNUNET_STRINGS_data_to_string_alloc (wtid,
- sizeof (struct TALER_WireTransferIdentifierRawP));
- GNUNET_asprintf (&path,
- "/wire/deposits?wtid=%s",
- buf);
- wdh->url = MAH_path_to_url (wdh->mint,
- path);
- GNUNET_free (buf);
- GNUNET_free (path);
-
- eh = curl_easy_init ();
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- wdh->url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEFUNCTION,
- &MAC_download_cb));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_WRITEDATA,
- &wdh->db));
- ctx = MAH_handle_to_context (mint);
- wdh->job = MAC_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_wire_deposits_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_MINT_wire_deposits_cancel (struct TALER_MINT_WireDepositsHandle *wdh)
-{
- if (NULL != wdh->job)
- {
- MAC_job_cancel (wdh->job);
- wdh->job = NULL;
- }
- GNUNET_free_non_null (wdh->db.buf);
- GNUNET_free (wdh->url);
- GNUNET_free (wdh);
-}
-
-
-/* end of mint_api_wire_deposits.c */
diff --git a/src/mint-lib/test-mint-home/config/mint-common.conf b/src/mint-lib/test-mint-home/config/mint-common.conf
deleted file mode 100644
index b2b948268..000000000
--- a/src/mint-lib/test-mint-home/config/mint-common.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-[mint]
-# Currency supported by the mint (can only be one)
-CURRENCY = EUR
-
-# Wire format supported by the mint
-# We use 'test' for testing of the actual
-# coin operations, and 'sepa' to test SEPA-specific routines.
-WIREFORMAT = test sepa
-
-# HTTP port the mint listens to
-PORT = 8081
-
-# Master public key used to sign the mint's various keys
-MASTER_PUBLIC_KEY = 98NJW3CQHZQGQXTY3K85K531XKPAPAVV4Q5V8PYYRR00NJGZWNVG
-
-# How to access our database
-DB = postgres
-
-# Is this is a testcase, use transient DB actions?
-TESTRUN = YES
-
-[mintdb-postgres]
-
-DB_CONN_STR = "postgres:///talercheck"
-
-[mint-wire-sepa]
-SEPA_RESPONSE_FILE = "test-mint-home/sepa.json"
-
-[mint-wire-test]
-REDIRECT_URL = "http://www.taler.net/"
diff --git a/src/mint-lib/test-mint-home/config/mint-keyup.conf b/src/mint-lib/test-mint-home/config/mint-keyup.conf
deleted file mode 100644
index 8ad1f3bb2..000000000
--- a/src/mint-lib/test-mint-home/config/mint-keyup.conf
+++ /dev/null
@@ -1,86 +0,0 @@
-[mint_keys]
-
-# 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 generate denomination and signing keys
-# ahead of time?
-lookahead_sign = 32 weeks 1 day
-
-# how long do we provide to clients denomination and signing keys
-# ahead of time?
-lookahead_provide = 4 weeks 1 day
-
-
-# Coin definitions are detected because the section
-# name begins with "coin_". The rest of the
-# name is free, but of course following the convention
-# of "coin_$CURRENCY[_$SUBUNIT]_$VALUE" make sense.
-[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
-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
-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
-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
-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
-rsa_keysize = 1024
-
-[coin_eur_1000]
-value = EUR:1000
-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
-rsa_keysize = 2048
diff --git a/src/mint-lib/test-mint-home/master.priv b/src/mint-lib/test-mint-home/master.priv
deleted file mode 100644
index 394926938..000000000
--- a/src/mint-lib/test-mint-home/master.priv
+++ /dev/null
@@ -1 +0,0 @@
-pÚ^ó-Ú33ˆ€XXÁ!ˆ\0qúýµmUþ_‰ˆ \ No newline at end of file
diff --git a/src/mint-lib/test-mint-home/sepa.json b/src/mint-lib/test-mint-home/sepa.json
deleted file mode 100644
index 36d12f661..000000000
--- a/src/mint-lib/test-mint-home/sepa.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "receiver_name": "Max Mustermann",
- "iban": "DE89370400440532013000",
- "bic": "COBADEFF370",
- "sig": "8M5YJXM68PRAXKH76HYEBCJW657B23JA0RFGNDMZK2379YZMT626H1BN89KC0M1KJBWGYEN5Z763Q0Y7MCTZQ6BPPT7D9KFCTW60C10"
-} \ No newline at end of file
diff --git a/src/mint-lib/test_mint_api.c b/src/mint-lib/test_mint_api.c
deleted file mode 100644
index b243cc2cf..000000000
--- a/src/mint-lib/test_mint_api.c
+++ /dev/null
@@ -1,2599 +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, If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file mint/test_mint_api.c
- * @brief testcase to test mint's HTTP API interface
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "taler_util.h"
-#include "taler_signatures.h"
-#include "taler_mint_service.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <microhttpd.h>
-
-/**
- * Is the configuration file is set to include wire format 'test'?
- */
-#define WIRE_TEST 1
-
-/**
- * Is the configuration file is set to include wire format 'sepa'?
- */
-#define WIRE_SEPA 1
-
-/**
- * Main execution context for the main loop.
- */
-static struct TALER_MINT_Context *ctx;
-
-/**
- * Handle to access the mint.
- */
-static struct TALER_MINT_Handle *mint;
-
-/**
- * Task run on shutdown.
- */
-static struct GNUNET_SCHEDULER_Task *shutdown_task;
-
-/**
- * Task that runs the main event loop.
- */
-static struct GNUNET_SCHEDULER_Task *ctx_task;
-
-/**
- * Result of the testcases, #GNUNET_OK on success
- */
-static int result;
-
-
-/**
- * Opcodes for the interpreter.
- */
-enum OpCode
-{
- /**
- * Termination code, stops the interpreter loop (with success).
- */
- OC_END = 0,
-
- /**
- * Add funds to a reserve by (faking) incoming wire transfer.
- */
- OC_ADMIN_ADD_INCOMING,
-
- /**
- * Check status of a reserve.
- */
- OC_WITHDRAW_STATUS,
-
- /**
- * Withdraw a coin from a reserve.
- */
- OC_WITHDRAW_SIGN,
-
- /**
- * Deposit a coin (pay with it).
- */
- OC_DEPOSIT,
-
- /**
- * Melt a (set of) coins.
- */
- OC_REFRESH_MELT,
-
- /**
- * Complete melting session by withdrawing melted coins.
- */
- OC_REFRESH_REVEAL,
-
- /**
- * Verify mint's /refresh/link by linking original private key to
- * results from #OC_REFRESH_REVEAL step.
- */
- OC_REFRESH_LINK,
-
- /**
- * Verify the mint's /wire-method.
- */
- OC_WIRE,
-
- /**
- * Verify mint's /wire/deposits method.
- */
- OC_WIRE_DEPOSITS,
-
- /**
- * Verify mint's /deposit/wtid method.
- */
- OC_DEPOSIT_WTID
-
-};
-
-
-/**
- * Structure specifying details about a coin to be melted.
- * Used in a NULL-terminated array as part of command
- * specification.
- */
-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_ref;
-
-};
-
-
-/**
- * Information about a fresh coin generated by the refresh operation.
- */
-struct FreshCoin
-{
-
- /**
- * 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_MINT_DenomPublicKey *pk;
-
- /**
- * Set (by the interpreter) to the mint's signature over the
- * coin's public key.
- */
- struct TALER_DenominationSignature sig;
-
- /**
- * Set (by the interpreter) to the coin's private key.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
-};
-
-
-/**
- * Details for a mint operation to execute.
- */
-struct Command
-{
- /**
- * Opcode of the command.
- */
- enum OpCode oc;
-
- /**
- * Label for the command, can be NULL.
- */
- const char *label;
-
- /**
- * Which response code do we expect for this command?
- */
- unsigned int expected_response_code;
-
- /**
- * Details about the command.
- */
- union
- {
-
- /**
- * Information for a #OC_ADMIN_ADD_INCOMING command.
- */
- struct
- {
-
- /**
- * Label to another admin_add_incoming command if we
- * should deposit into an existing reserve, NULL if
- * a fresh reserve should be created.
- */
- const char *reserve_reference;
-
- /**
- * String describing the amount to add to the reserve.
- */
- const char *amount;
-
- /**
- * Wire details (JSON).
- */
- const char *wire;
-
- /**
- * Set (by the interpreter) to the reserve's private key
- * we used to fill the reserve.
- */
- struct TALER_ReservePrivateKeyP reserve_priv;
-
- /**
- * Set to the API's handle during the operation.
- */
- struct TALER_MINT_AdminAddIncomingHandle *aih;
-
- } admin_add_incoming;
-
- /**
- * Information for a #OC_WITHDRAW_STATUS command.
- */
- struct
- {
-
- /**
- * Label to the #OC_ADMIN_ADD_INCOMING command which
- * created the reserve.
- */
- const char *reserve_reference;
-
- /**
- * Set to the API's handle during the operation.
- */
- struct TALER_MINT_ReserveStatusHandle *wsh;
-
- /**
- * Expected reserve balance.
- */
- const char *expected_balance;
-
- } reserve_status;
-
- /**
- * Information for a #OC_WITHDRAW_SIGN command.
- */
- struct
- {
-
- /**
- * 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 mint's
- * offerings. Can be NULL if @e pk is set instead.
- */
- const char *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_MINT_DenomPublicKey *pk;
-
- /**
- * Set (by the interpreter) to the mint's signature over the
- * coin's public key.
- */
- struct TALER_DenominationSignature sig;
-
- /**
- * Set (by the interpreter) to the coin's private key.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
- /**
- * Blinding key used for the operation.
- */
- struct TALER_DenominationBlindingKey blinding_key;
-
- /**
- * Withdraw handle (while operation is running).
- */
- struct TALER_MINT_ReserveWithdrawHandle *wsh;
-
- } reserve_withdraw;
-
- /**
- * Information for a #OC_DEPOSIT command.
- */
- struct
- {
-
- /**
- * Amount to deposit.
- */
- const char *amount;
-
- /**
- * Reference to a reserve_withdraw operation for a coin to
- * be used for the /deposit operation.
- */
- const char *coin_ref;
-
- /**
- * If this @e coin_ref refers to an operation that generated
- * an array of coins, this value determines which coin to use.
- */
- unsigned int coin_idx;
-
- /**
- * JSON string describing the merchant's "wire details".
- */
- const char *wire_details;
-
- /**
- * JSON string describing the contract between the two parties.
- */
- const char *contract;
-
- /**
- * Transaction ID to use.
- */
- uint64_t transaction_id;
-
- /**
- * 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 of the merchant,
- * if @e refund_deadline is non-zero.
- */
- struct TALER_MerchantPrivateKeyP merchant_priv;
-
- /**
- * Deposit handle while operation is running.
- */
- struct TALER_MINT_DepositHandle *dh;
-
- } deposit;
-
- /**
- * Information for a #OC_REFRESH_MELT command.
- */
- struct
- {
-
- /**
- * Information about coins to be melted.
- */
- struct MeltDetails *melted_coins;
-
- /**
- * Denominations of the fresh coins to withdraw.
- */
- const char **fresh_amounts;
-
- /**
- * Array of the public keys corresponding to
- * the @e fresh_amounts, set by the interpreter.
- */
- const struct TALER_MINT_DenomPublicKey **fresh_pks;
-
- /**
- * Melt handle while operation is running.
- */
- struct TALER_MINT_RefreshMeltHandle *rmh;
-
- /**
- * Data used in the refresh operation, set by the interpreter.
- */
- char *refresh_data;
-
- /**
- * Number of bytes in @e refresh_data, set by the interpreter.
- */
- size_t refresh_data_length;
-
- /**
- * Set by the interpreter (upon completion) to the noreveal
- * index selected by the mint.
- */
- uint16_t noreveal_index;
-
- } refresh_melt;
-
- /**
- * Information for a #OC_REFRESH_REVEAL command.
- */
- struct
- {
-
- /**
- * Melt operation this is the matching reveal for.
- */
- const char *melt_ref;
-
- /**
- * Reveal handle while operation is running.
- */
- struct TALER_MINT_RefreshRevealHandle *rrh;
-
- /**
- * Number of fresh coins withdrawn, set by the interpreter.
- * Length of the @e fresh_coins array.
- */
- unsigned int num_fresh_coins;
-
- /**
- * Information about coins withdrawn, set by the interpreter.
- */
- struct FreshCoin *fresh_coins;
-
- } refresh_reveal;
-
- /**
- * Information for a #OC_REFRESH_LINK command.
- */
- struct
- {
-
- /**
- * Reveal operation this is the matching link for.
- */
- const char *reveal_ref;
-
- /**
- * Link handle while operation is running.
- */
- struct TALER_MINT_RefreshLinkHandle *rlh;
-
- /**
- * Which of the melted coins should be used for the linkage?
- */
- unsigned int coin_idx;
-
- } refresh_link;
-
- /**
- * Information for the /wire command.
- */
- struct {
-
- /**
- * Handle to the wire request.
- */
- struct TALER_MINT_WireHandle *wh;
-
- /**
- * Format we expect to see, others will be *ignored*.
- */
- const char *format;
-
- } wire;
-
- /**
- * Information for the /wire/deposits's command.
- */
- struct {
-
- /**
- * Handle to the wire deposits request.
- */
- struct TALER_MINT_WireDepositsHandle *wdh;
-
- /**
- * Reference to a /deposit/wtid command. If set, we use the
- * WTID from that command.
- */
- const char *wtid_ref;
-
- /**
- * WTID to use (used if @e wtid_ref is NULL).
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /* TODO: may want to add list of deposits we expected
- to see aggregated here in the future. */
-
- } wire_deposits;
-
- /**
- * Information for the /deposit/wtid command.
- */
- struct {
-
- /**
- * Handle to the deposit wtid request.
- */
- struct TALER_MINT_DepositWtidHandle *dwh;
-
- /**
- * Which /deposit operation should we obtain WTID data for?
- */
- const char *deposit_ref;
-
- /**
- * What is the expected total amount? Only used if
- * @e expected_response_code was #MHD_HTTP_OK.
- */
- struct TALER_Amount total_amount_expected;
-
- /**
- * Wire transfer identifier, set if #MHD_HTTP_OK was the response code.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- } deposit_wtid;
-
- } details;
-
-};
-
-
-/**
- * State of the interpreter loop.
- */
-struct InterpreterState
-{
- /**
- * Keys from the mint.
- */
- const struct TALER_MINT_Keys *keys;
-
- /**
- * Commands the interpreter will run.
- */
- struct Command *commands;
-
- /**
- * Interpreter task (if one is scheduled).
- */
- struct GNUNET_SCHEDULER_Task *task;
-
- /**
- * Instruction pointer. Tells #interpreter_run() which
- * instruction to run next.
- */
- unsigned int ip;
-
-};
-
-
-/**
- * Task that runs the context's event loop with the GNUnet scheduler.
- *
- * @param cls unused
- * @param tc scheduler context (unused)
- */
-static void
-context_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Run the context task, the working set has changed.
- */
-static void
-trigger_context_task ()
-{
- GNUNET_SCHEDULER_cancel (ctx_task);
- ctx_task = GNUNET_SCHEDULER_add_now (&context_task,
- NULL);
-}
-
-
-/**
- * The testcase failed, return with an error code.
- *
- * @param is interpreter state to clean up
- */
-static void
-fail (struct InterpreterState *is)
-{
- result = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Find a command by label.
- *
- * @param is interpreter state to search
- * @param label label to look for
- * @return NULL if command was not found
- */
-static const struct Command *
-find_command (const struct InterpreterState *is,
- const char *label)
-{
- unsigned int i;
- const struct Command *cmd;
-
- if (NULL == label)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Attempt to lookup command for empty label\n");
- return NULL;
- }
- for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++)
- if ( (NULL != cmd->label) &&
- (0 == strcmp (cmd->label,
- label)) )
- return cmd;
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command not found: %s\n",
- label);
- return NULL;
-}
-
-
-/**
- * Run the main interpreter loop that performs mint operations.
- *
- * @param cls contains the `struct InterpreterState`
- * @param tc scheduler context
- */
-static void
-interpreter_run (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Function called upon completion of our /admin/add/incoming request.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
- * 0 if the mint's reply is bogus (fails to follow the protocol)
- * @param full_response full response from the mint (for logging, in case of errors)
- */
-static void
-add_incoming_cb (void *cls,
- unsigned int http_status,
- json_t *full_response)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
-
- cmd->details.admin_add_incoming.aih = NULL;
- if (MHD_HTTP_OK != http_status)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Check if the given historic event @a h corresponds to the given
- * command @a cmd.
- *
- * @param h event in history
- * @param cmd an #OC_ADMIN_ADD_INCOMING command
- * @return #GNUNET_OK if they match, #GNUNET_SYSERR if not
- */
-static int
-compare_admin_add_incoming_history (const struct TALER_MINT_ReserveHistory *h,
- const struct Command *cmd)
-{
- struct TALER_Amount amount;
-
- if (TALER_MINT_RTT_DEPOSIT != h->type)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount (cmd->details.admin_add_incoming.amount,
- &amount));
- if (0 != TALER_amount_cmp (&amount,
- &h->amount))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Check if the given historic event @a h corresponds to the given
- * command @a cmd.
- *
- * @param h event in history
- * @param cmd an #OC_WITHDRAW_SIGN command
- * @return #GNUNET_OK if they match, #GNUNET_SYSERR if not
- */
-static int
-compare_reserve_withdraw_history (const struct TALER_MINT_ReserveHistory *h,
- const struct Command *cmd)
-{
- struct TALER_Amount amount;
- struct TALER_Amount amount_with_fee;
-
- if (TALER_MINT_RTT_WITHDRAWAL != h->type)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount (cmd->details.reserve_withdraw.amount,
- &amount));
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_add (&amount_with_fee,
- &amount,
- &cmd->details.reserve_withdraw.pk->fee_withdraw));
- if (0 != TALER_amount_cmp (&amount_with_fee,
- &h->amount))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called with the result of a /reserve/status request.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
- * 0 if the mint's reply is bogus (fails to follow the protocol)
- * @param[in] json original response in JSON format (useful only for diagnostics)
- * @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,
- json_t *json,
- const struct TALER_Amount *balance,
- unsigned int history_length,
- const struct TALER_MINT_ReserveHistory *history)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
- struct Command *rel;
- unsigned int i;
- unsigned int j;
- struct TALER_Amount amount;
-
- cmd->details.reserve_status.wsh = NULL;
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s\n",
- http_status,
- cmd->label);
- GNUNET_break (0);
- json_dumpf (json, stderr, 0);
- fail (is);
- return;
- }
- switch (http_status)
- {
- case MHD_HTTP_OK:
- /* FIXME: note that history events may come in a different
- order than the commands. However, for now this works... */
- j = 0;
- for (i=0;i<is->ip;i++)
- {
- switch ((rel = &is->commands[i])->oc)
- {
- case OC_ADMIN_ADD_INCOMING:
- if ( ( (NULL != rel->label) &&
- (0 == strcmp (cmd->details.reserve_status.reserve_reference,
- rel->label) ) ) ||
- ( (NULL != rel->details.admin_add_incoming.reserve_reference) &&
- (0 == strcmp (cmd->details.reserve_status.reserve_reference,
- rel->details.admin_add_incoming.reserve_reference) ) ) )
- {
- if (GNUNET_OK !=
- compare_admin_add_incoming_history (&history[j],
- rel))
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- j++;
- }
- break;
- case OC_WITHDRAW_SIGN:
- if (0 == strcmp (cmd->details.reserve_status.reserve_reference,
- rel->details.reserve_withdraw.reserve_reference))
- {
- if (GNUNET_OK !=
- compare_reserve_withdraw_history (&history[j],
- rel))
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- j++;
- }
- break;
- default:
- /* unreleated, just skip */
- break;
- }
- }
- if (j != history_length)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- if (NULL != cmd->details.reserve_status.expected_balance)
- {
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount (cmd->details.reserve_status.expected_balance,
- &amount));
- if (0 != TALER_amount_cmp (&amount,
- balance))
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- }
- break;
- default:
- /* Unsupported status code (by test harness) */
- GNUNET_break (0);
- break;
- }
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Function called upon completion of our /reserve/withdraw request.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
- * 0 if the mint's reply is bogus (fails to follow the protocol)
- * @param sig signature over the coin, NULL on error
- * @param full_response full response from the mint (for logging, in case of errors)
- */
-static void
-reserve_withdraw_cb (void *cls,
- unsigned int http_status,
- const struct TALER_DenominationSignature *sig,
- json_t *full_response)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
-
- cmd->details.reserve_withdraw.wsh = NULL;
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s\n",
- http_status,
- cmd->label);
- json_dumpf (full_response, stderr, 0);
- GNUNET_break (0);
- fail (is);
- return;
- }
- switch (http_status)
- {
- case MHD_HTTP_OK:
- if (NULL == sig)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- cmd->details.reserve_withdraw.sig.rsa_signature
- = GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
- break;
- case MHD_HTTP_PAYMENT_REQUIRED:
- /* nothing to check */
- break;
- default:
- /* Unsupported status code (by test harness) */
- GNUNET_break (0);
- break;
- }
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Function called with the result of a /deposit operation.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful deposit;
- * 0 if the mint's reply is bogus (fails to follow the protocol)
- * @param obj the received JSON reply, should be kept as proof (and, in case of errors,
- * be forwarded to the customer)
- */
-static void
-deposit_cb (void *cls,
- unsigned int http_status,
- json_t *obj)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
-
- cmd->details.deposit.dh = NULL;
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s\n",
- http_status,
- cmd->label);
- json_dumpf (obj, stderr, 0);
- fail (is);
- return;
- }
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Function called with the result of the /refresh/melt operation.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, never #MHD_HTTP_OK (200) as for successful intermediate response this callback is skipped.
- * 0 if the mint's reply is bogus (fails to follow the protocol)
- * @param noreveal_index choice by the mint in the cut-and-choose protocol,
- * UINT16_MAX on error
- * @param full_response full response from the mint (for logging, in case of errors)
- */
-static void
-melt_cb (void *cls,
- unsigned int http_status,
- uint16_t noreveal_index,
- json_t *full_response)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
-
- cmd->details.refresh_melt.rmh = NULL;
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s\n",
- http_status,
- cmd->label);
- json_dumpf (full_response, stderr, 0);
- fail (is);
- return;
- }
- cmd->details.refresh_melt.noreveal_index = noreveal_index;
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Function called with the result of the /refresh/reveal operation.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
- * 0 if the mint's reply is bogus (fails to follow the protocol)
- * @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 full response from the mint (for logging, in case of errors)
- */
-static void
-reveal_cb (void *cls,
- unsigned int http_status,
- unsigned int num_coins,
- const struct TALER_CoinSpendPrivateKeyP *coin_privs,
- const struct TALER_DenominationSignature *sigs,
- json_t *full_response)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
- const struct Command *ref;
- unsigned int i;
-
- cmd->details.refresh_reveal.rrh = NULL;
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s\n",
- http_status,
- cmd->label);
- json_dumpf (full_response, stderr, 0);
- fail (is);
- return;
- }
- ref = find_command (is,
- cmd->details.refresh_reveal.melt_ref);
- cmd->details.refresh_reveal.num_fresh_coins = num_coins;
- switch (http_status)
- {
- case MHD_HTTP_OK:
- cmd->details.refresh_reveal.fresh_coins
- = GNUNET_new_array (num_coins,
- struct FreshCoin);
- for (i=0;i<num_coins;i++)
- {
- struct FreshCoin *fc = &cmd->details.refresh_reveal.fresh_coins[i];
-
- fc->pk = ref->details.refresh_melt.fresh_pks[i];
- fc->coin_priv = coin_privs[i];
- fc->sig.rsa_signature
- = GNUNET_CRYPTO_rsa_signature_dup (sigs[i].rsa_signature);
- }
- break;
- default:
- break;
- }
-
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Function called with the result of a /refresh/link operation.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
- * 0 if the mint's reply is bogus (fails to follow the protocol)
- * @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 full response from the mint (for logging, in case of errors)
- */
-static void
-link_cb (void *cls,
- unsigned int http_status,
- unsigned int num_coins,
- const struct TALER_CoinSpendPrivateKeyP *coin_privs,
- const struct TALER_DenominationSignature *sigs,
- const struct TALER_DenominationPublicKey *pubs,
- json_t *full_response)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
- const struct Command *ref;
- unsigned int i;
- unsigned int j;
- unsigned int found;
-
- cmd->details.refresh_link.rlh = NULL;
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s\n",
- http_status,
- cmd->label);
- json_dumpf (full_response, stderr, 0);
- fail (is);
- return;
- }
- ref = find_command (is,
- cmd->details.refresh_link.reveal_ref);
- switch (http_status)
- {
- case MHD_HTTP_OK:
- /* check that number of coins returned matches */
- if (num_coins != ref->details.refresh_reveal.num_fresh_coins)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- /* check that the coins match */
- for (i=0;i<num_coins;i++)
- for (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;
- for (i=0;i<num_coins;i++)
- for (j=0;j<num_coins;j++)
- {
- const struct FreshCoin *fc;
-
- fc = &ref->details.refresh_reveal.fresh_coins[j];
- if ( (0 == memcmp (&coin_privs[i],
- &fc->coin_priv,
- sizeof (struct TALER_CoinSpendPrivateKeyP))) &&
- (0 == GNUNET_CRYPTO_rsa_signature_cmp (fc->sig.rsa_signature,
- sigs[i].rsa_signature)) &&
- (0 == GNUNET_CRYPTO_rsa_public_key_cmp (fc->pk->key.rsa_public_key,
- pubs[i].rsa_public_key)) )
- {
- found++;
- break;
- }
- }
- if (found != num_coins)
- {
- fprintf (stderr,
- "Only %u/%u coins match expectations\n",
- found,
- num_coins);
- GNUNET_break (0);
- fail (is);
- return;
- }
- break;
- default:
- break;
- }
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * 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
- */
-static const struct TALER_MINT_DenomPublicKey *
-find_pk (const struct TALER_MINT_Keys *keys,
- const struct TALER_Amount *amount)
-{
- unsigned int i;
- struct GNUNET_TIME_Absolute now;
- struct TALER_MINT_DenomPublicKey *pk;
- char *str;
-
- now = GNUNET_TIME_absolute_get ();
- for (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 (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,
- now.abs_value_us,
- pk->valid_from.abs_value_us,
- 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;
-}
-
-
-/**
- * Callbacks called with the result(s) of a
- * wire format inquiry request to the mint.
- *
- * The callback is invoked multiple times, once for each supported @a
- * method. Finally, it is invoked one more time with cls/0/NULL/NULL
- * to indicate the end of the iteration. If any request fails to
- * generate a valid response from the mint, @a http_status will also
- * be zero and the iteration will also end. Thus, the iteration
- * always ends with a final call with an @a http_status of 0. If the
- * @a http_status is already 0 on the first call, then the response to
- * the /wire request was invalid. Later, clients can tell the
- * difference between @a http_status of 0 indicating a failed
- * /wire/method request and a regular end of the iteration by @a
- * method being non-NULL. If the mint simply correctly asserts that
- * it does not support any methods, @a method will be NULL but the @a
- * http_status will be #MHD_HTTP_OK for the first call (followed by a
- * cls/0/NULL/NULL call to signal the end of the iteration).
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful request;
- * 0 if the mint's reply is bogus (fails to follow the protocol)
- * @param method wire format method supported, i.e. "test" or "sepa", or NULL
- * if already the /wire request failed.
- * @param obj the received JSON reply, if successful this should be the wire
- * format details as provided by /wire/METHOD/, or NULL if the
- * reply was not in JSON format (in this case, the client might
- * want to do an HTTP request to /wire/METHOD/ with a browser to
- * provide more information to the user about the @a method).
- */
-static void
-wire_cb (void *cls,
- unsigned int http_status,
- const char *method,
- json_t *obj)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
-
- if (0 == http_status)
- {
- /* 0 always signals the end of the iteration */
- cmd->details.wire.wh = NULL;
- }
- else if ( (NULL != method) &&
- (0 != strcasecmp (method,
- cmd->details.wire.format)) )
- {
- /* not the method we care about, skip */
- return;
- }
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s/%s\n",
- http_status,
- cmd->label,
- method);
- json_dumpf (obj, stderr, 0);
- fail (is);
- return;
- }
- if (0 == http_status)
- {
- /* end of iteration, move to next command */
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
- return;
- }
- /* For now, we only support to be called only once
- with a "positive" result; so we switch to an
- expected value of 0 for the 2nd iteration */
- cmd->expected_response_code = 0;
-}
-
-
-/**
- * Function called with detailed wire transfer data, including all
- * of the coin transactions that were combined into the wire transfer.
- *
- * @param cls closure
- * @param http_status HTTP status code we got, 0 on mint protocol violation
- * @param json original json reply (may include signatures, those have then been
- * validated already)
- * @param wtid extracted wire transfer identifier, or NULL if the mint could
- * not provide any (set only if @a http_status is #MHD_HTTP_OK)
- * @param total_amount total amount of the wire transfer, or NULL if the mint could
- * not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK)
- * @param details_length length of the @a details array
- * @param details array with details about the combined transactions
- */
-static void
-wire_deposits_cb (void *cls,
- unsigned int http_status,
- json_t *json,
- const struct GNUNET_HashCode *h_wire,
- const struct TALER_Amount *total_amount,
- unsigned int details_length,
- const struct TALER_WireDepositDetails *details)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
- const struct Command *ref;
-
- cmd->details.wire_deposits.wdh = NULL;
- ref = find_command (is,
- cmd->details.wire_deposits.wtid_ref);
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s\n",
- http_status,
- cmd->label);
- json_dumpf (json, stderr, 0);
- fail (is);
- return;
- }
- switch (http_status)
- {
- case MHD_HTTP_OK:
- if (0 != TALER_amount_cmp (total_amount,
- &ref->details.deposit_wtid.total_amount_expected))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Total amount missmatch to command %s\n",
- http_status,
- cmd->label);
- json_dumpf (json, stderr, 0);
- fail (is);
- return;
- }
- if (NULL != ref->details.deposit_wtid.deposit_ref)
- {
- const struct Command *dep;
- struct GNUNET_HashCode hw;
-
- dep = find_command (is,
- ref->details.deposit_wtid.deposit_ref);
- GNUNET_CRYPTO_hash (dep->details.deposit.wire_details,
- strlen (dep->details.deposit.wire_details),
- &hw);
- if (0 != memcmp (&hw,
- h_wire,
- sizeof (struct GNUNET_HashCode)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Wire hash missmatch to command %s\n",
- cmd->label);
- json_dumpf (json, stderr, 0);
- fail (is);
- return;
- }
- }
- break;
- default:
- break;
- }
-
- /* move to next command */
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Function called with detailed wire transfer data.
- *
- * @param cls closure
- * @param http_status HTTP status code we got, 0 on mint protocol violation
- * @param json original json reply (may include signatures, those have then been
- * validated already)
- * @param wtid wire transfer identifier used by the mint, NULL if mint did not
- * yet execute the transaction
- * @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 (may be NULL)
- * @param total_amount total amount of the wire transfer, or NULL if the mint 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,
- json_t *json,
- const struct TALER_WireTransferIdentifierRawP *wtid,
- struct GNUNET_TIME_Absolute execution_time,
- const struct TALER_Amount *coin_contribution)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
-
- cmd->details.deposit_wtid.dwh = NULL;
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u to command %s\n",
- http_status,
- cmd->label);
- json_dumpf (json, stderr, 0);
- fail (is);
- return;
- }
- switch (http_status)
- {
- case MHD_HTTP_OK:
- cmd->details.deposit_wtid.wtid = *wtid;
- break;
- default:
- break;
- }
-
- /* move to next command */
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Run the main interpreter loop that performs mint operations.
- *
- * @param cls contains the `struct InterpreterState`
- * @param tc scheduler context
- */
-static void
-interpreter_run (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
- const struct Command *ref;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct TALER_Amount amount;
- struct GNUNET_TIME_Absolute execution_date;
- json_t *wire;
-
- is->task = NULL;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- {
- fprintf (stderr,
- "Test aborted by shutdown request\n");
- fail (is);
- return;
- }
- switch (cmd->oc)
- {
- case OC_END:
- result = GNUNET_OK;
- GNUNET_SCHEDULER_shutdown ();
- return;
- case OC_ADMIN_ADD_INCOMING:
- if (NULL !=
- cmd->details.admin_add_incoming.reserve_reference)
- {
- ref = find_command (is,
- cmd->details.admin_add_incoming.reserve_reference);
- GNUNET_assert (NULL != ref);
- GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
- cmd->details.admin_add_incoming.reserve_priv
- = ref->details.admin_add_incoming.reserve_priv;
- }
- else
- {
- struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
-
- priv = GNUNET_CRYPTO_eddsa_key_create ();
- cmd->details.admin_add_incoming.reserve_priv.eddsa_priv = *priv;
- GNUNET_free (priv);
- }
- GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.admin_add_incoming.reserve_priv.eddsa_priv,
- &reserve_pub.eddsa_pub);
- if (GNUNET_OK !=
- TALER_string_to_amount (cmd->details.admin_add_incoming.amount,
- &amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u\n",
- cmd->details.admin_add_incoming.amount,
- is->ip);
- fail (is);
- return;
- }
- wire = json_loads (cmd->details.admin_add_incoming.wire,
- JSON_REJECT_DUPLICATES,
- NULL);
- if (NULL == wire)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse wire details `%s' at %u\n",
- cmd->details.admin_add_incoming.wire,
- is->ip);
- fail (is);
- return;
- }
- execution_date = GNUNET_TIME_absolute_get ();
- TALER_round_abs_time (&execution_date);
- cmd->details.admin_add_incoming.aih
- = TALER_MINT_admin_add_incoming (mint,
- &reserve_pub,
- &amount,
- execution_date,
- wire,
- &add_incoming_cb,
- is);
- if (NULL == cmd->details.admin_add_incoming.aih)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- trigger_context_task ();
- return;
- case OC_WITHDRAW_STATUS:
- GNUNET_assert (NULL !=
- cmd->details.reserve_status.reserve_reference);
- ref = find_command (is,
- cmd->details.reserve_status.reserve_reference);
- GNUNET_assert (NULL != ref);
- GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
- GNUNET_CRYPTO_eddsa_key_get_public (&ref->details.admin_add_incoming.reserve_priv.eddsa_priv,
- &reserve_pub.eddsa_pub);
- cmd->details.reserve_status.wsh
- = TALER_MINT_reserve_status (mint,
- &reserve_pub,
- &reserve_status_cb,
- is);
- trigger_context_task ();
- return;
- case OC_WITHDRAW_SIGN:
- GNUNET_assert (NULL !=
- cmd->details.reserve_withdraw.reserve_reference);
- ref = find_command (is,
- cmd->details.reserve_withdraw.reserve_reference);
- GNUNET_assert (NULL != ref);
- GNUNET_assert (OC_ADMIN_ADD_INCOMING == ref->oc);
- if (NULL != cmd->details.reserve_withdraw.amount)
- {
- if (GNUNET_OK !=
- TALER_string_to_amount (cmd->details.reserve_withdraw.amount,
- &amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u\n",
- cmd->details.reserve_withdraw.amount,
- is->ip);
- fail (is);
- return;
- }
- cmd->details.reserve_withdraw.pk = find_pk (is->keys,
- &amount);
- }
- if (NULL == cmd->details.reserve_withdraw.pk)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to determine denomination key at %u\n",
- is->ip);
- fail (is);
- return;
- }
-
- /* create coin's private key */
- {
- struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
-
- priv = GNUNET_CRYPTO_eddsa_key_create ();
- cmd->details.reserve_withdraw.coin_priv.eddsa_priv = *priv;
- GNUNET_free (priv);
- }
- GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.reserve_withdraw.coin_priv.eddsa_priv,
- &coin_pub.eddsa_pub);
- cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key
- = GNUNET_CRYPTO_rsa_blinding_key_create (GNUNET_CRYPTO_rsa_public_key_len (cmd->details.reserve_withdraw.pk->key.rsa_public_key));
- cmd->details.reserve_withdraw.wsh
- = TALER_MINT_reserve_withdraw (mint,
- cmd->details.reserve_withdraw.pk,
- &ref->details.admin_add_incoming.reserve_priv,
- &cmd->details.reserve_withdraw.coin_priv,
- &cmd->details.reserve_withdraw.blinding_key,
- &reserve_withdraw_cb,
- is);
- if (NULL == cmd->details.reserve_withdraw.wsh)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- trigger_context_task ();
- return;
- case OC_DEPOSIT:
- {
- struct GNUNET_HashCode h_contract;
- const struct TALER_CoinSpendPrivateKeyP *coin_priv;
- const struct TALER_MINT_DenomPublicKey *coin_pk;
- const struct TALER_DenominationSignature *coin_pk_sig;
- struct TALER_CoinSpendPublicKeyP coin_pub;
- 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 *priv;
- struct TALER_MerchantPublicKeyP merchant_pub;
- json_t *contract;
- json_t *wire;
-
- GNUNET_assert (NULL !=
- cmd->details.deposit.coin_ref);
- ref = find_command (is,
- cmd->details.deposit.coin_ref);
- GNUNET_assert (NULL != ref);
- switch (ref->oc)
- {
- case OC_WITHDRAW_SIGN:
- coin_priv = &ref->details.reserve_withdraw.coin_priv;
- coin_pk = ref->details.reserve_withdraw.pk;
- coin_pk_sig = &ref->details.reserve_withdraw.sig;
- break;
- case OC_REFRESH_REVEAL:
- {
- const struct FreshCoin *fc;
- unsigned int idx;
-
- idx = cmd->details.deposit.coin_idx;
- GNUNET_assert (idx < ref->details.refresh_reveal.num_fresh_coins);
- fc = &ref->details.refresh_reveal.fresh_coins[idx];
-
- coin_priv = &fc->coin_priv;
- coin_pk = fc->pk;
- coin_pk_sig = &fc->sig;
- }
- break;
- default:
- GNUNET_assert (0);
- }
- if (GNUNET_OK !=
- TALER_string_to_amount (cmd->details.deposit.amount,
- &amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u\n",
- cmd->details.deposit.amount,
- is->ip);
- fail (is);
- return;
- }
- contract = json_loads (cmd->details.deposit.contract,
- JSON_REJECT_DUPLICATES,
- NULL);
- if (NULL == contract)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse contract details `%s' at %u/%s\n",
- cmd->details.deposit.contract,
- is->ip,
- cmd->label);
- fail (is);
- return;
- }
- TALER_hash_json (contract,
- &h_contract);
- wire = json_loads (cmd->details.deposit.wire_details,
- JSON_REJECT_DUPLICATES,
- NULL);
- if (NULL == wire)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse wire details `%s' at %u/%s\n",
- cmd->details.deposit.wire_details,
- is->ip,
- cmd->label);
- fail (is);
- return;
- }
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
- &coin_pub.eddsa_pub);
-
- priv = GNUNET_CRYPTO_eddsa_key_create ();
- cmd->details.deposit.merchant_priv.eddsa_priv = *priv;
- GNUNET_free (priv);
- if (0 != cmd->details.deposit.refund_deadline.rel_value_us)
- {
- refund_deadline = GNUNET_TIME_relative_to_absolute (cmd->details.deposit.refund_deadline);
- }
- else
- {
- refund_deadline = GNUNET_TIME_UNIT_ZERO_ABS;
- }
- GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.deposit.merchant_priv.eddsa_priv,
- &merchant_pub.eddsa_pub);
-
- wire_deadline = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS);
- timestamp = GNUNET_TIME_absolute_get ();
- TALER_round_abs_time (&timestamp);
- {
- 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 = h_contract;
- TALER_hash_json (wire,
- &dr.h_wire);
- dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
- dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
- dr.transaction_id = GNUNET_htonll (cmd->details.deposit.transaction_id);
- TALER_amount_hton (&dr.amount_with_fee,
- &amount);
- TALER_amount_hton (&dr.deposit_fee,
- &coin_pk->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));
- }
- cmd->details.deposit.dh
- = TALER_MINT_deposit (mint,
- &amount,
- wire_deadline,
- wire,
- &h_contract,
- &coin_pub,
- coin_pk_sig,
- &coin_pk->key,
- timestamp,
- cmd->details.deposit.transaction_id,
- &merchant_pub,
- refund_deadline,
- &coin_sig,
- &deposit_cb,
- is);
- if (NULL == cmd->details.deposit.dh)
- {
- GNUNET_break (0);
- json_decref (wire);
- fail (is);
- return;
- }
- json_decref (wire);
- trigger_context_task ();
- return;
- }
- case OC_REFRESH_MELT:
- {
- unsigned int num_melted_coins;
- unsigned int num_fresh_coins;
-
- cmd->details.refresh_melt.noreveal_index = UINT16_MAX;
- for (num_melted_coins=0;
- NULL != cmd->details.refresh_melt.melted_coins[num_melted_coins].amount;
- num_melted_coins++) ;
- for (num_fresh_coins=0;
- NULL != cmd->details.refresh_melt.fresh_amounts[num_fresh_coins];
- num_fresh_coins++) ;
-
- cmd->details.refresh_melt.fresh_pks
- = GNUNET_new_array (num_fresh_coins,
- const struct TALER_MINT_DenomPublicKey *);
- {
- struct TALER_CoinSpendPrivateKeyP melt_privs[num_melted_coins];
- struct TALER_Amount melt_amounts[num_melted_coins];
- struct TALER_DenominationSignature melt_sigs[num_melted_coins];
- struct TALER_MINT_DenomPublicKey melt_pks[num_melted_coins];
- struct TALER_MINT_DenomPublicKey fresh_pks[num_fresh_coins];
- unsigned int i;
-
- for (i=0;i<num_melted_coins;i++)
- {
- const struct MeltDetails *md = &cmd->details.refresh_melt.melted_coins[i];
- ref = find_command (is,
- md->coin_ref);
- GNUNET_assert (NULL != ref);
- GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
-
- melt_privs[i] = ref->details.reserve_withdraw.coin_priv;
- if (GNUNET_OK !=
- TALER_string_to_amount (md->amount,
- &melt_amounts[i]))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u\n",
- md->amount,
- is->ip);
- fail (is);
- return;
- }
- melt_sigs[i] = ref->details.reserve_withdraw.sig;
- melt_pks[i] = *ref->details.reserve_withdraw.pk;
- }
- for (i=0;i<num_fresh_coins;i++)
- {
- if (GNUNET_OK !=
- TALER_string_to_amount (cmd->details.refresh_melt.fresh_amounts[i],
- &amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u\n",
- cmd->details.reserve_withdraw.amount,
- is->ip);
- fail (is);
- return;
- }
- cmd->details.refresh_melt.fresh_pks[i]
- = find_pk (is->keys,
- &amount);
- fresh_pks[i] = *cmd->details.refresh_melt.fresh_pks[i];
- }
- cmd->details.refresh_melt.refresh_data
- = TALER_MINT_refresh_prepare (num_melted_coins,
- melt_privs,
- melt_amounts,
- melt_sigs,
- melt_pks,
- GNUNET_YES,
- num_fresh_coins,
- fresh_pks,
- &cmd->details.refresh_melt.refresh_data_length);
- if (NULL == cmd->details.refresh_melt.refresh_data)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- cmd->details.refresh_melt.rmh
- = TALER_MINT_refresh_melt (mint,
- cmd->details.refresh_melt.refresh_data_length,
- cmd->details.refresh_melt.refresh_data,
- &melt_cb,
- is);
- if (NULL == cmd->details.refresh_melt.rmh)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- }
- }
- trigger_context_task ();
- return;
- case OC_REFRESH_REVEAL:
- ref = find_command (is,
- cmd->details.refresh_reveal.melt_ref);
- cmd->details.refresh_reveal.rrh
- = TALER_MINT_refresh_reveal (mint,
- ref->details.refresh_melt.refresh_data_length,
- ref->details.refresh_melt.refresh_data,
- ref->details.refresh_melt.noreveal_index,
- &reveal_cb,
- is);
- if (NULL == cmd->details.refresh_reveal.rrh)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- trigger_context_task ();
- return;
- case OC_REFRESH_LINK:
- /* find reveal command */
- ref = find_command (is,
- cmd->details.refresh_link.reveal_ref);
- /* find melt command */
- ref = find_command (is,
- ref->details.refresh_reveal.melt_ref);
- /* find reserve_withdraw command */
- {
- unsigned int idx;
- const struct MeltDetails *md;
- unsigned int num_melted_coins;
-
- for (num_melted_coins=0;
- NULL != ref->details.refresh_melt.melted_coins[num_melted_coins].amount;
- num_melted_coins++) ;
- idx = cmd->details.refresh_link.coin_idx;
- GNUNET_assert (idx < num_melted_coins);
- md = &ref->details.refresh_melt.melted_coins[idx];
- ref = find_command (is,
- md->coin_ref);
- }
- GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
- /* finally, use private key from withdraw sign command */
- cmd->details.refresh_link.rlh
- = TALER_MINT_refresh_link (mint,
- &ref->details.reserve_withdraw.coin_priv,
- &link_cb,
- is);
- if (NULL == cmd->details.refresh_link.rlh)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- trigger_context_task ();
- return;
- case OC_WIRE:
- cmd->details.wire.wh = TALER_MINT_wire (mint,
- &wire_cb,
- is);
- trigger_context_task ();
- return;
- case OC_WIRE_DEPOSITS:
- if (NULL != cmd->details.wire_deposits.wtid_ref)
- {
- ref = find_command (is,
- cmd->details.wire_deposits.wtid_ref);
- GNUNET_assert (NULL != ref);
- cmd->details.wire_deposits.wtid = ref->details.deposit_wtid.wtid;
- }
- cmd->details.wire_deposits.wdh
- = TALER_MINT_wire_deposits (mint,
- &cmd->details.wire_deposits.wtid,
- &wire_deposits_cb,
- is);
- trigger_context_task ();
- return;
- case OC_DEPOSIT_WTID:
- {
- struct GNUNET_HashCode h_wire;
- struct GNUNET_HashCode h_contract;
- json_t *wire;
- json_t *contract;
- const struct Command *coin;
- struct TALER_CoinSpendPublicKeyP coin_pub;
-
- ref = find_command (is,
- cmd->details.deposit_wtid.deposit_ref);
- GNUNET_assert (NULL != ref);
- coin = find_command (is,
- ref->details.deposit.coin_ref);
- GNUNET_assert (NULL != coin);
- switch (coin->oc)
- {
- case OC_WITHDRAW_SIGN:
- GNUNET_CRYPTO_eddsa_key_get_public (&coin->details.reserve_withdraw.coin_priv.eddsa_priv,
- &coin_pub.eddsa_pub);
- break;
- case OC_REFRESH_REVEAL:
- {
- const struct FreshCoin *fc;
- unsigned int idx;
-
- idx = ref->details.deposit.coin_idx;
- GNUNET_assert (idx < coin->details.refresh_reveal.num_fresh_coins);
- fc = &coin->details.refresh_reveal.fresh_coins[idx];
-
- GNUNET_CRYPTO_eddsa_key_get_public (&fc->coin_priv.eddsa_priv,
- &coin_pub.eddsa_pub);
- }
- break;
- default:
- GNUNET_assert (0);
- }
-
- wire = json_loads (ref->details.deposit.wire_details,
- JSON_REJECT_DUPLICATES,
- NULL);
- GNUNET_assert (NULL != wire);
- TALER_hash_json (wire,
- &h_wire);
- json_decref (wire);
- contract = json_loads (ref->details.deposit.contract,
- JSON_REJECT_DUPLICATES,
- NULL);
- GNUNET_assert (NULL != contract);
- TALER_hash_json (contract,
- &h_contract);
- json_decref (contract);
- cmd->details.deposit_wtid.dwh
- = TALER_MINT_deposit_wtid (mint,
- &ref->details.deposit.merchant_priv,
- &h_wire,
- &h_contract,
- &coin_pub,
- ref->details.deposit.transaction_id,
- &deposit_wtid_cb,
- is);
- trigger_context_task ();
- }
- return;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown instruction %d at %u (%s)\n",
- cmd->oc,
- is->ip,
- cmd->label);
- fail (is);
- return;
- }
-}
-
-
-/**
- * Function run when the test terminates (good or bad).
- * Cleans up our state.
- *
- * @param cls the interpreter state.
- * @param tc unused
- */
-static void
-do_shutdown (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd;
- unsigned int i;
-
- shutdown_task = NULL;
- for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++)
- {
- switch (cmd->oc)
- {
- case OC_END:
- GNUNET_assert (0);
- break;
- case OC_ADMIN_ADD_INCOMING:
- if (NULL != cmd->details.admin_add_incoming.aih)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_admin_add_incoming_cancel (cmd->details.admin_add_incoming.aih);
- cmd->details.admin_add_incoming.aih = NULL;
- }
- break;
- case OC_WITHDRAW_STATUS:
- if (NULL != cmd->details.reserve_status.wsh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_reserve_status_cancel (cmd->details.reserve_status.wsh);
- cmd->details.reserve_status.wsh = NULL;
- }
- break;
- case OC_WITHDRAW_SIGN:
- if (NULL != cmd->details.reserve_withdraw.wsh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_reserve_withdraw_cancel (cmd->details.reserve_withdraw.wsh);
- cmd->details.reserve_withdraw.wsh = NULL;
- }
- if (NULL != cmd->details.reserve_withdraw.sig.rsa_signature)
- {
- GNUNET_CRYPTO_rsa_signature_free (cmd->details.reserve_withdraw.sig.rsa_signature);
- cmd->details.reserve_withdraw.sig.rsa_signature = NULL;
- }
- if (NULL != cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key)
- {
- GNUNET_CRYPTO_rsa_blinding_key_free (cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key);
- cmd->details.reserve_withdraw.blinding_key.rsa_blinding_key = NULL;
- }
- break;
- case OC_DEPOSIT:
- if (NULL != cmd->details.deposit.dh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_deposit_cancel (cmd->details.deposit.dh);
- cmd->details.deposit.dh = NULL;
- }
- break;
- case OC_REFRESH_MELT:
- if (NULL != cmd->details.refresh_melt.rmh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_refresh_melt_cancel (cmd->details.refresh_melt.rmh);
- cmd->details.refresh_melt.rmh = NULL;
- }
- GNUNET_free_non_null (cmd->details.refresh_melt.fresh_pks);
- cmd->details.refresh_melt.fresh_pks = NULL;
- GNUNET_free_non_null (cmd->details.refresh_melt.refresh_data);
- cmd->details.refresh_melt.refresh_data = NULL;
- cmd->details.refresh_melt.refresh_data_length = 0;
- break;
- case OC_REFRESH_REVEAL:
- if (NULL != cmd->details.refresh_reveal.rrh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_refresh_reveal_cancel (cmd->details.refresh_reveal.rrh);
- cmd->details.refresh_reveal.rrh = NULL;
- }
- {
- unsigned int j;
- struct FreshCoin *fresh_coins;
-
- fresh_coins = cmd->details.refresh_reveal.fresh_coins;
- for (j=0;j<cmd->details.refresh_reveal.num_fresh_coins;j++)
- GNUNET_CRYPTO_rsa_signature_free (fresh_coins[j].sig.rsa_signature);
- }
- GNUNET_free_non_null (cmd->details.refresh_reveal.fresh_coins);
- cmd->details.refresh_reveal.fresh_coins = NULL;
- cmd->details.refresh_reveal.num_fresh_coins = 0;
- break;
- case OC_REFRESH_LINK:
- if (NULL != cmd->details.refresh_link.rlh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_refresh_link_cancel (cmd->details.refresh_link.rlh);
- cmd->details.refresh_link.rlh = NULL;
- }
- break;
- case OC_WIRE:
- if (NULL != cmd->details.wire.wh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_wire_cancel (cmd->details.wire.wh);
- cmd->details.wire.wh = NULL;
- }
- break;
- case OC_WIRE_DEPOSITS:
- if (NULL != cmd->details.wire_deposits.wdh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_wire_deposits_cancel (cmd->details.wire_deposits.wdh);
- cmd->details.wire_deposits.wdh = NULL;
- }
- break;
- case OC_DEPOSIT_WTID:
- if (NULL != cmd->details.deposit_wtid.dwh)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_MINT_deposit_wtid_cancel (cmd->details.deposit_wtid.dwh);
- cmd->details.deposit_wtid.dwh = NULL;
- }
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown instruction %d at %u (%s)\n",
- cmd->oc,
- i,
- cmd->label);
- break;
- }
- }
- if (NULL != is->task)
- {
- GNUNET_SCHEDULER_cancel (is->task);
- is->task = NULL;
- }
- GNUNET_free (is);
- if (NULL != ctx_task)
- {
- GNUNET_SCHEDULER_cancel (ctx_task);
- ctx_task = NULL;
- }
- if (NULL != mint)
- {
- TALER_MINT_disconnect (mint);
- mint = NULL;
- }
- if (NULL != ctx)
- {
- TALER_MINT_fini (ctx);
- ctx = NULL;
- }
-}
-
-
-/**
- * Functions of this type are called to provide the retrieved signing and
- * denomination keys of the mint. No TALER_MINT_*() functions should be called
- * in this callback.
- *
- * @param cls closure
- * @param keys information about keys of the mint
- */
-static void
-cert_cb (void *cls,
- const struct TALER_MINT_Keys *keys)
-{
- struct InterpreterState *is = cls;
-
- /* check that keys is OK */
-#define ERR(cond) do { if(!(cond)) break; GNUNET_break (0); GNUNET_SCHEDULER_shutdown(); return; } while (0)
- ERR (NULL == keys);
- ERR (0 == keys->num_sign_keys);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Read %u signing keys\n",
- keys->num_sign_keys);
- ERR (0 == keys->num_denom_keys);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Read %u denomination keys\n",
- keys->num_denom_keys);
-#undef ERR
-
- /* run actual tests via interpreter-loop */
- is->keys = keys;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Task that runs the context's event loop with the GNUnet scheduler.
- *
- * @param cls unused
- * @param tc scheduler context (unused)
- */
-static void
-context_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- long timeout;
- int max_fd;
- fd_set read_fd_set;
- fd_set write_fd_set;
- fd_set except_fd_set;
- struct GNUNET_NETWORK_FDSet *rs;
- struct GNUNET_NETWORK_FDSet *ws;
- struct GNUNET_TIME_Relative delay;
-
- ctx_task = NULL;
- TALER_MINT_perform (ctx);
- max_fd = -1;
- timeout = -1;
- FD_ZERO (&read_fd_set);
- FD_ZERO (&write_fd_set);
- FD_ZERO (&except_fd_set);
- TALER_MINT_get_select_info (ctx,
- &read_fd_set,
- &write_fd_set,
- &except_fd_set,
- &max_fd,
- &timeout);
- if (timeout >= 0)
- delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
- timeout);
- else
- delay = GNUNET_TIME_UNIT_FOREVER_REL;
- rs = GNUNET_NETWORK_fdset_create ();
- GNUNET_NETWORK_fdset_copy_native (rs,
- &read_fd_set,
- max_fd + 1);
- ws = GNUNET_NETWORK_fdset_create ();
- GNUNET_NETWORK_fdset_copy_native (ws,
- &write_fd_set,
- max_fd + 1);
- ctx_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- delay,
- rs,
- ws,
- &context_task,
- cls);
- GNUNET_NETWORK_fdset_destroy (rs);
- GNUNET_NETWORK_fdset_destroy (ws);
-}
-
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL!)
- * @param config configuration
- */
-static void
-run (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct InterpreterState *is;
- static struct MeltDetails melt_coins_1[] = {
- { .amount = "EUR:4",
- .coin_ref = "refresh-withdraw-coin-1" },
- { NULL, NULL }
- };
- static const char *melt_fresh_amounts_1[] = {
- "EUR:1",
- "EUR:1",
- "EUR:1",
- "EUR:0.1",
- "EUR:0.1",
- "EUR:0.1",
- "EUR:0.1",
- "EUR:0.1",
- "EUR:0.1",
- "EUR:0.1",
- "EUR:0.1",
- "EUR:0.01",
- "EUR:0.01",
- "EUR:0.01",
- "EUR:0.01",
- "EUR:0.01",
- "EUR:0.01",
- /* with 0.01 withdraw fees (except for 1ct coins),
- this totals up to exactly EUR:3.97, and with
- the 0.03 refresh fee, to EUR:4.0*/
- NULL
- };
- static struct Command commands[] =
- {
- /* *************** start of /wire testing ************** */
-
-#if WIRE_TEST
- { .oc = OC_WIRE,
- .label = "wire-test",
- /* /wire/test replies with a 302 redirect */
- .expected_response_code = MHD_HTTP_FOUND,
- .details.wire.format = "test" },
-#endif
-#if WIRE_SEPA
- { .oc = OC_WIRE,
- .label = "wire-sepa",
- /* /wire/sepa replies with a 200 redirect */
- .expected_response_code = MHD_HTTP_OK,
- .details.wire.format = "sepa" },
-#endif
- /* *************** end of /wire testing ************** */
-
-#if WIRE_TEST
- /* None of this works if 'test' is not allowed as we do
- /admin/add/incoming with format 'test' */
-
- /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
- { .oc = OC_ADMIN_ADD_INCOMING,
- .label = "create-reserve-1",
- .expected_response_code = MHD_HTTP_OK,
- .details.admin_add_incoming.wire = "{ \"type\":\"TEST\", \"bank\":\"source bank\", \"account\":42 }",
- .details.admin_add_incoming.amount = "EUR:5.01" },
- /* Withdraw a 5 EUR coin, at fee of 1 ct */
- { .oc = OC_WITHDRAW_SIGN,
- .label = "withdraw-coin-1",
- .expected_response_code = MHD_HTTP_OK,
- .details.reserve_withdraw.reserve_reference = "create-reserve-1",
- .details.reserve_withdraw.amount = "EUR:5" },
- /* Check that deposit and withdraw operation are in history, and
- that the balance is now at zero */
- { .oc = OC_WITHDRAW_STATUS,
- .label = "withdraw-status-1",
- .expected_response_code = MHD_HTTP_OK,
- .details.reserve_status.reserve_reference = "create-reserve-1",
- .details.reserve_status.expected_balance = "EUR:0" },
- /* Try to deposit the 5 EUR coin (in full) */
- { .oc = OC_DEPOSIT,
- .label = "deposit-simple",
- .expected_response_code = MHD_HTTP_OK,
- .details.deposit.amount = "EUR:5",
- .details.deposit.coin_ref = "withdraw-coin-1",
- .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
- .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }",
- .details.deposit.transaction_id = 1 },
-
- /* Try to overdraw funds ... */
- { .oc = OC_WITHDRAW_SIGN,
- .label = "withdraw-coin-2",
- .expected_response_code = MHD_HTTP_PAYMENT_REQUIRED,
- .details.reserve_withdraw.reserve_reference = "create-reserve-1",
- .details.reserve_withdraw.amount = "EUR:5" },
-
- /* Try to double-spend the 5 EUR coin with different wire details */
- { .oc = OC_DEPOSIT,
- .label = "deposit-double-1",
- .expected_response_code = MHD_HTTP_FORBIDDEN,
- .details.deposit.amount = "EUR:5",
- .details.deposit.coin_ref = "withdraw-coin-1",
- .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":43 }",
- .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }",
- .details.deposit.transaction_id = 1 },
- /* Try to double-spend the 5 EUR coin at the same merchant (but different
- transaction ID) */
- { .oc = OC_DEPOSIT,
- .label = "deposit-double-2",
- .expected_response_code = MHD_HTTP_FORBIDDEN,
- .details.deposit.amount = "EUR:5",
- .details.deposit.coin_ref = "withdraw-coin-1",
- .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
- .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":1 } ] }",
- .details.deposit.transaction_id = 2 },
- /* Try to double-spend the 5 EUR coin at the same merchant (but different
- contract) */
- { .oc = OC_DEPOSIT,
- .label = "deposit-double-3",
- .expected_response_code = MHD_HTTP_FORBIDDEN,
- .details.deposit.amount = "EUR:5",
- .details.deposit.coin_ref = "withdraw-coin-1",
- .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
- .details.deposit.contract = "{ \"items\":[{ \"name\":\"ice cream\", \"value\":2 } ] }",
- .details.deposit.transaction_id = 1 },
-
- /* ***************** /refresh testing ******************** */
-
- /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct */
- { .oc = OC_ADMIN_ADD_INCOMING,
- .label = "refresh-create-reserve-1",
- .expected_response_code = MHD_HTTP_OK,
- .details.admin_add_incoming.wire = "{ \"type\":\"TEST\", \"bank\":\"source bank\", \"account\":424 }",
- .details.admin_add_incoming.amount = "EUR:5.01" },
- /* Withdraw a 5 EUR coin, at fee of 1 ct */
- { .oc = OC_WITHDRAW_SIGN,
- .label = "refresh-withdraw-coin-1",
- .expected_response_code = MHD_HTTP_OK,
- .details.reserve_withdraw.reserve_reference = "refresh-create-reserve-1",
- .details.reserve_withdraw.amount = "EUR:5" },
- /* 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) */
- { .oc = OC_DEPOSIT,
- .label = "refresh-deposit-partial",
- .expected_response_code = MHD_HTTP_OK,
- .details.deposit.amount = "EUR:1",
- .details.deposit.coin_ref = "refresh-withdraw-coin-1",
- .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
- .details.deposit.contract = "{ \"items\" : [ { \"name\":\"ice cream\", \"value\":\"EUR:1\" } ] }",
- .details.deposit.transaction_id = 42421 },
-
- /* Melt the rest of the coin's value (EUR:4.00 = 3x EUR:1.03 + 7x EUR:0.13) */
-
- { .oc = OC_REFRESH_MELT,
- .label = "refresh-melt-1",
- .expected_response_code = MHD_HTTP_OK,
- .details.refresh_melt.melted_coins = melt_coins_1,
- .details.refresh_melt.fresh_amounts = melt_fresh_amounts_1 },
-
-
- /* Complete (successful) melt operation, and withdraw the coins */
- { .oc = OC_REFRESH_REVEAL,
- .label = "refresh-reveal-1",
- .expected_response_code = MHD_HTTP_OK,
- .details.refresh_reveal.melt_ref = "refresh-melt-1" },
-
- /* Test that /refresh/link works */
- { .oc = OC_REFRESH_LINK,
- .label = "refresh-link-1",
- .expected_response_code = MHD_HTTP_OK,
- .details.refresh_link.reveal_ref = "refresh-reveal-1" },
-
-
- /* Test successfully spending coins from the refresh operation:
- first EUR:1 */
- { .oc = OC_DEPOSIT,
- .label = "refresh-deposit-refreshed-1a",
- .expected_response_code = MHD_HTTP_OK,
- .details.deposit.amount = "EUR:1",
- .details.deposit.coin_ref = "refresh-reveal-1",
- .details.deposit.coin_idx = 0,
- .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
- .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }",
- .details.deposit.transaction_id = 2 },
-
- /* Test successfully spending coins from the refresh operation:
- finally EUR:0.1 */
- { .oc = OC_DEPOSIT,
- .label = "refresh-deposit-refreshed-1b",
- .expected_response_code = MHD_HTTP_OK,
- .details.deposit.amount = "EUR:0.1",
- .details.deposit.coin_ref = "refresh-reveal-1",
- .details.deposit.coin_idx = 4,
- .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
- .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }",
- .details.deposit.transaction_id = 2 },
-
- /* Test running a failing melt operation (same operation again must fail) */
- { .oc = OC_REFRESH_MELT,
- .label = "refresh-melt-failing",
- .expected_response_code = MHD_HTTP_FORBIDDEN,
- .details.refresh_melt.melted_coins = melt_coins_1,
- .details.refresh_melt.fresh_amounts = melt_fresh_amounts_1 },
-
- // FIXME: also test with coin that was already melted
- // (signature differs from coin that was deposited...)
- /* *************** end of /refresh testing ************** */
-
- /* ************** Test tracking API ******************** */
- /* Try resolving a deposit's WTID, as we never triggered
- execution of transactions, the answer should be that
- the mint knows about the deposit, but has no WTID yet. */
- { .oc = OC_DEPOSIT_WTID,
- .label = "deposit-wtid-found",
- .expected_response_code = MHD_HTTP_ACCEPTED,
- .details.deposit_wtid.deposit_ref = "deposit-simple" },
- /* Try resolving a deposit's WTID for a failed deposit.
- As the deposit failed, the answer should be that
- the mint does NOT know about the deposit. */
- { .oc = OC_DEPOSIT_WTID,
- .label = "deposit-wtid-failing",
- .expected_response_code = MHD_HTTP_NOT_FOUND,
- .details.deposit_wtid.deposit_ref = "deposit-double-2" },
- /* Try resolving an undefined (all zeros) WTID; this
- should fail as obviously the mint didn't use that
- WTID value for any transaction. */
- { .oc = OC_WIRE_DEPOSITS,
- .label = "wire-deposit-failing",
- .expected_response_code = MHD_HTTP_NOT_FOUND },
-
- /* TODO: trigger aggregation logic and then check the
- cases where tracking succeeds! */
-
- /* ************** End of tracking API testing************* */
-
-
-#endif
-
- { .oc = OC_END }
- };
-
- is = GNUNET_new (struct InterpreterState);
- is->commands = commands;
-
- ctx = TALER_MINT_init ();
- GNUNET_assert (NULL != ctx);
- ctx_task = GNUNET_SCHEDULER_add_now (&context_task,
- ctx);
- mint = TALER_MINT_connect (ctx,
- "http://localhost:8081",
- &cert_cb, is,
- TALER_MINT_OPTION_END);
- GNUNET_assert (NULL != mint);
- shutdown_task
- = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 150),
- &do_shutdown, is);
-}
-
-
-/**
- * Main function for the testcase for the mint API.
- *
- * @param argc expected to be 1
- * @param argv expected to only contain the program name
- */
-int
-main (int argc,
- char * const *argv)
-{
- struct GNUNET_OS_Process *proc;
- struct GNUNET_OS_Process *mintd;
-
- GNUNET_log_setup ("test-mint-api",
- "WARNING",
- NULL);
- proc = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-mint-keyup",
- "taler-mint-keyup",
- "-d", "test-mint-home",
- "-m", "test-mint-home/master.priv",
- NULL);
- GNUNET_OS_process_wait (proc);
- GNUNET_OS_process_destroy (proc);
- mintd = GNUNET_OS_start_process (GNUNET_NO,
- GNUNET_OS_INHERIT_STD_ALL,
- NULL, NULL, NULL,
- "taler-mint-httpd",
- "taler-mint-httpd",
- "-d", "test-mint-home",
- NULL);
- /* give child time to start and bind against the socket */
- fprintf (stderr, "Waiting for taler-mint-httpd to be ready");
- do
- {
- fprintf (stderr, ".");
- sleep (1);
- }
- while (0 != system ("wget -q -t 1 -T 1 http://127.0.0.1:8081/keys -o /dev/null -O /dev/null"));
- fprintf (stderr, "\n");
- result = GNUNET_SYSERR;
- GNUNET_SCHEDULER_run (&run, NULL);
- GNUNET_OS_process_kill (mintd,
- SIGTERM);
- GNUNET_OS_process_wait (mintd);
- GNUNET_OS_process_destroy (mintd);
- return (GNUNET_OK == result) ? 0 : 1;
-}
-
-/* end of test_mint_api.c */