Compare commits
378 Commits
7624db4efd
...
8638446f94
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8638446f94 | ||
![]() |
ca61b64149 | ||
![]() |
a63e706cd7 | ||
![]() |
debc6ed983 | ||
![]() |
09c9054bae | ||
c165ef31fe | |||
![]() |
bdd81674cf | ||
![]() |
eed3cda48c | ||
![]() |
3fe94eb144 | ||
![]() |
3d66034093 | ||
![]() |
360382192f | ||
![]() |
ec2d596b46 | ||
![]() |
007e4bc954 | ||
![]() |
bad572a010 | ||
![]() |
8da74a6ca7 | ||
![]() |
f6a7d4a1ed | ||
![]() |
eccf37e450 | ||
![]() |
83be3173d4 | ||
![]() |
568d27abe5 | ||
![]() |
963477e064 | ||
![]() |
58a0882909 | ||
![]() |
70a5ceecc1 | ||
![]() |
3c4d6f1ba2 | ||
![]() |
007cc7abe8 | ||
![]() |
7876bc0600 | ||
![]() |
03cfd2b1e5 | ||
![]() |
6d16958a5c | ||
![]() |
71a42d2be8 | ||
![]() |
393ae7f9a3 | ||
![]() |
e71782ea77 | ||
![]() |
0e32eacdb0 | ||
![]() |
eaea32b319 | ||
![]() |
f3ceeb00ea | ||
![]() |
7700f6ff88 | ||
![]() |
f2e2c5c9d8 | ||
![]() |
937524940a | ||
![]() |
982b60c93c | ||
![]() |
446761b602 | ||
![]() |
f0bcbf6586 | ||
![]() |
b9a30d29cb | ||
![]() |
013942ba91 | ||
![]() |
070e6de61e | ||
![]() |
f8e77a27c0 | ||
![]() |
555cc06220 | ||
![]() |
bdbd2a464d | ||
60f609135d | |||
![]() |
b9963f7525 | ||
![]() |
6c81796d6f | ||
![]() |
f4eb53f2a4 | ||
![]() |
8e0b998217 | ||
![]() |
21a1c715ee | ||
![]() |
efa0ca4ec1 | ||
![]() |
a17781ba8d | ||
![]() |
6512456dc2 | ||
![]() |
baf00c0262 | ||
![]() |
93943bdb5b | ||
![]() |
3e99c50c0f | ||
![]() |
d04769b729 | ||
![]() |
04c32eafb9 | ||
![]() |
5dd03fe359 | ||
![]() |
65ce2eede6 | ||
![]() |
00c68e0a04 | ||
![]() |
f86eead6d6 | ||
![]() |
7193261e52 | ||
![]() |
361f534dbb | ||
![]() |
300194f42a | ||
![]() |
d55b093de8 | ||
![]() |
ab4aa4dcfd | ||
![]() |
7b25787a4b | ||
![]() |
7f902c0fc9 | ||
![]() |
d40da21e90 | ||
![]() |
6d2ee2c88a | ||
![]() |
d77354b11a | ||
![]() |
8e71a7e4de | ||
![]() |
92e04e0a3f | ||
![]() |
daddc69dc9 | ||
![]() |
1d84c284ad | ||
![]() |
054f2ab51c | ||
![]() |
656b521a83 | ||
![]() |
6ee4558b6f | ||
![]() |
2e80f51e25 | ||
![]() |
76b8a2a8de | ||
![]() |
a509a91f92 | ||
![]() |
cdd2930a99 | ||
![]() |
2035294adb | ||
![]() |
f1a58b0fd8 | ||
![]() |
b3844e4923 | ||
![]() |
fcaf508647 | ||
![]() |
3ee8879ada | ||
![]() |
3599ac0ac2 | ||
![]() |
67535ebf65 | ||
![]() |
40daa209fb | ||
![]() |
8658ae03ca | ||
![]() |
4a5d71cca2 | ||
![]() |
96fb11bed0 | ||
![]() |
21bcc5fa0b | ||
![]() |
3233195d2d | ||
![]() |
b1b943aa3e | ||
![]() |
737937291c | ||
![]() |
a6494f9905 | ||
![]() |
9e0df07a16 | ||
![]() |
c471ae447b | ||
![]() |
81ad77b8dc | ||
![]() |
421f59749e | ||
![]() |
68b155aab5 | ||
![]() |
344c53c51d | ||
![]() |
492d501570 | ||
![]() |
a6b2108009 | ||
![]() |
a6a1fa9fde | ||
![]() |
5e06f842dd | ||
![]() |
b9d0b1aae4 | ||
![]() |
7bd1828482 | ||
![]() |
ccc7743fdd | ||
![]() |
3b5d9daca9 | ||
![]() |
d8f1f7b761 | ||
![]() |
802649c270 | ||
![]() |
f089bbe536 | ||
![]() |
8690892cac | ||
![]() |
02716c4084 | ||
![]() |
d803d86bf9 | ||
![]() |
3db8f0f22d | ||
![]() |
fac01f140f | ||
![]() |
439c872af4 | ||
![]() |
10a97996f7 | ||
![]() |
84b8886b12 | ||
![]() |
6150713fc4 | ||
![]() |
2d0d8e7e8e | ||
![]() |
42f3f83b7d | ||
![]() |
d6c161a72e | ||
![]() |
db320d3e8e | ||
![]() |
7689c71cea | ||
![]() |
6518cc20dd | ||
![]() |
d0a0bd9725 | ||
![]() |
75d9584e28 | ||
![]() |
33312e5abf | ||
![]() |
6cf4a068ad | ||
![]() |
35b4a51e14 | ||
![]() |
93eb88a8c9 | ||
![]() |
81732d49cc | ||
![]() |
842e04b13c | ||
![]() |
99a844e52e | ||
![]() |
06bfbd9150 | ||
![]() |
60c08dccec | ||
![]() |
02eb80e0b2 | ||
![]() |
d3a6388199 | ||
![]() |
6b8e732bf8 | ||
![]() |
5f6d5bc3fc | ||
![]() |
415c922c92 | ||
![]() |
2d84d7f6dd | ||
![]() |
4199e4438d | ||
![]() |
8c9d5d6135 | ||
![]() |
370ee3a417 | ||
![]() |
65943dcb13 | ||
![]() |
31e554ad46 | ||
![]() |
7ebdac0a8b | ||
![]() |
0a7b75b2cf | ||
![]() |
40440604dd | ||
![]() |
1173502189 | ||
![]() |
72ae759fa0 | ||
![]() |
a4ede7caec | ||
![]() |
3d80b20459 | ||
![]() |
7718cd4153 | ||
![]() |
f99fb9ad4b | ||
![]() |
fed8353c67 | ||
![]() |
fb8349a7e3 | ||
![]() |
8e4969eb66 | ||
![]() |
c48b51be6f | ||
1bb992d777 | |||
![]() |
3e8c797bb7 | ||
![]() |
d623cab1a3 | ||
![]() |
1396afc136 | ||
![]() |
521e0bbcb5 | ||
9a05781ab3 | |||
17a00ef22d | |||
47e276e11a | |||
be536de23c | |||
![]() |
336f2d8991 | ||
![]() |
25aa208d12 | ||
![]() |
932cef3d8c | ||
![]() |
efb8c8037b | ||
a92d3aae7b | |||
f24fc18564 | |||
38fcca16c8 | |||
![]() |
505989a507 | ||
![]() |
5c0cbba761 | ||
![]() |
94038bfcfd | ||
![]() |
b4965db0d2 | ||
![]() |
b671d6b25d | ||
![]() |
aedd2014ec | ||
![]() |
36c568ab8d | ||
![]() |
345c141bad | ||
![]() |
b7a4fd401e | ||
![]() |
a1825d38b3 | ||
![]() |
e270bc32cc | ||
![]() |
b054c969cb | ||
![]() |
cf358f9546 | ||
![]() |
e731739396 | ||
![]() |
cf11b3f0b2 | ||
![]() |
132359a444 | ||
![]() |
a72337a5f3 | ||
![]() |
e40a16aa8e | ||
![]() |
c30c7cde4d | ||
![]() |
8ef3997160 | ||
![]() |
ae2f1ced8b | ||
![]() |
1002ac13e4 | ||
31c545b9e8 | |||
![]() |
eea35ffb01 | ||
![]() |
53cde04c4e | ||
![]() |
582acc3cf3 | ||
![]() |
c3e67dfc6b | ||
![]() |
f5eef0c816 | ||
061c4f72bd | |||
b84c88fc04 | |||
137bd97154 | |||
![]() |
4af1772f12 | ||
![]() |
1e0789eda3 | ||
![]() |
8776f16b06 | ||
14b57d3e13 | |||
![]() |
509657bfef | ||
![]() |
a7ad5a07e2 | ||
![]() |
ba69c32712 | ||
![]() |
f32b183143 | ||
![]() |
b496b8fed5 | ||
![]() |
fc1383ebd1 | ||
![]() |
001f406ad6 | ||
![]() |
a2604f7967 | ||
![]() |
a13f90a15e | ||
![]() |
5882e6b56b | ||
![]() |
00928aba0a | ||
![]() |
2299b8b193 | ||
![]() |
3893afa49c | ||
![]() |
cacb019501 | ||
![]() |
b91a406525 | ||
![]() |
78cf27aaac | ||
![]() |
6aad1fa351 | ||
![]() |
7a1dcc52ca | ||
![]() |
c8c1005297 | ||
![]() |
d30b7f8eeb | ||
![]() |
bd09b2302a | ||
![]() |
72dd9514aa | ||
![]() |
f9971faa7a | ||
![]() |
fe2a15c558 | ||
![]() |
89431a41b7 | ||
![]() |
0a10644b81 | ||
![]() |
22cfc59d90 | ||
![]() |
adb999ce2c | ||
![]() |
f3a4b00907 | ||
![]() |
7191641406 | ||
![]() |
df8ff01f29 | ||
![]() |
914a77b5a7 | ||
![]() |
970225516e | ||
![]() |
8c3e263b76 | ||
![]() |
5147c8b788 | ||
![]() |
831e32b7ad | ||
![]() |
393cea46d1 | ||
![]() |
7ba135362e | ||
![]() |
ae75ff2cb4 | ||
![]() |
6f027fc130 | ||
![]() |
caabee9e94 | ||
![]() |
86ee587b03 | ||
![]() |
ca536c0379 | ||
![]() |
5880a8ec4f | ||
![]() |
f596b27a97 | ||
![]() |
82718aecf8 | ||
![]() |
1b76ba5e9a | ||
![]() |
0ba219fe5b | ||
![]() |
6c66f6f5cf | ||
![]() |
caf66486e7 | ||
![]() |
45916b992b | ||
![]() |
75c1e10a67 | ||
![]() |
0cf9a9984c | ||
![]() |
747ae5ef09 | ||
![]() |
eadee56dcf | ||
![]() |
6040c9ff0f | ||
![]() |
e5b65aa443 | ||
![]() |
adc9dae4cc | ||
![]() |
074ea7502e | ||
![]() |
3249687b2a | ||
![]() |
b25c9398b7 | ||
![]() |
a227ee6d1b | ||
![]() |
ee4077ef80 | ||
30985c0975 | |||
ccf2d69dfb | |||
488d217381 | |||
a2386abadb | |||
![]() |
d61a19c275 | ||
![]() |
1f1d675f3d | ||
![]() |
b9a9af3a59 | ||
![]() |
d0a69da895 | ||
![]() |
646c9ad061 | ||
![]() |
098d572471 | ||
![]() |
783e2ae424 | ||
![]() |
238761c87d | ||
![]() |
b856d56d95 | ||
![]() |
c782dfe2aa | ||
![]() |
6ffc2c68a3 | ||
b0cf653b83 | |||
e336c02d14 | |||
![]() |
f091808425 | ||
![]() |
7d2a009e1b | ||
![]() |
41399bc224 | ||
![]() |
9b7716f9f2 | ||
![]() |
6505f69869 | ||
![]() |
6868b78692 | ||
![]() |
cce049a0b5 | ||
![]() |
734b68d45e | ||
![]() |
e200e86032 | ||
![]() |
bdc797a583 | ||
![]() |
c7e2d206ba | ||
![]() |
1f86b02ffa | ||
![]() |
f5f15e6531 | ||
![]() |
b560527ee3 | ||
![]() |
65808106c7 | ||
![]() |
532fabf20a | ||
![]() |
28203913e2 | ||
![]() |
e7fa97cc87 | ||
![]() |
427417b835 | ||
![]() |
dee45bf022 | ||
![]() |
1bb5a77c8d | ||
![]() |
c83892ba29 | ||
![]() |
69927847cc | ||
![]() |
5406d564fb | ||
![]() |
938db9ac56 | ||
![]() |
c4690a44bc | ||
![]() |
685837ad28 | ||
![]() |
f5e5f4b843 | ||
![]() |
f22125ce0f | ||
![]() |
b4f7231d17 | ||
![]() |
98c21a5116 | ||
![]() |
52a8b8f888 | ||
![]() |
280f94c3a6 | ||
![]() |
f0a95037ef | ||
![]() |
badfde8962 | ||
e909f5701b | |||
![]() |
142a369e43 | ||
![]() |
23af6c3c41 | ||
![]() |
a59d39f699 | ||
![]() |
eac8b8c0da | ||
![]() |
bab36a2ac8 | ||
![]() |
12809b28ec | ||
![]() |
63879d9d20 | ||
![]() |
fe94405554 | ||
![]() |
7529939a0f | ||
![]() |
687f0cab82 | ||
![]() |
a8d80d519d | ||
![]() |
7a74cde9c7 | ||
![]() |
9a3d993d07 | ||
![]() |
e1e68cebb8 | ||
![]() |
92c594774e | ||
2fe5223c72 | |||
cd5ee2338c | |||
![]() |
ab3868f83b | ||
![]() |
54106e63dc | ||
![]() |
a080f11890 | ||
![]() |
57470e4c08 | ||
![]() |
5fa977cc05 | ||
![]() |
841e56bafd | ||
![]() |
7ff58c3d8f | ||
8a906bf96c | |||
![]() |
43f8ab6b48 | ||
![]() |
4835ddf60b | ||
![]() |
3a1f418603 | ||
d0b27833b2 | |||
![]() |
f5e1cf5e6d | ||
![]() |
f9a2808ed0 | ||
![]() |
1643b745af | ||
![]() |
f951cdef8c | ||
4c53d42e44 | |||
![]() |
476ae53808 | ||
![]() |
80fc8231ad | ||
![]() |
57e3864c09 | ||
![]() |
79d123d1b4 | ||
![]() |
7f30609ff0 | ||
![]() |
548613c617 | ||
![]() |
41a9a73eb8 | ||
10d7d93ad8 | |||
![]() |
cab654237f | ||
![]() |
2abe9bf6d7 |
7
.gitignore
vendored
7
.gitignore
vendored
@ -88,6 +88,7 @@ src/wire-plugins/test_wire_plugin
|
||||
src/wire-plugins/test_wire_plugin_transactions_taler_bank
|
||||
src/pq/test_pq
|
||||
src/sq/test_sq
|
||||
src/util/test_age_restriction
|
||||
src/util/test_amount
|
||||
src/util/test_crypto
|
||||
src/util/test_json
|
||||
@ -133,6 +134,12 @@ src/testing/test_auditor_api_rsa
|
||||
src/testing/test_exchange_api_overlapping_keys_bug_cs
|
||||
src/testing/test_exchange_api_overlapping_keys_bug_rsa
|
||||
src/testing/test_exchange_api_home/.local/share/taler/exchange/revocations/
|
||||
src/testing/test_auditor_api
|
||||
src/testing/test_auditor_api_version
|
||||
src/testing/test_exchange_api_keys_cherry_picking
|
||||
src/testing/test_exchange_api_overlapping_keys_bug
|
||||
src/testing/test_exchange_api_revocation
|
||||
src/testing/test_exchange_management_api
|
||||
src/wire-plugins/test_wire_plugin_legacy_taler_bank
|
||||
uncrustify.cfg
|
||||
vgcore.*
|
||||
|
@ -15,11 +15,6 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
BUILT_SOURCES = src/include/taler_error_codes.h
|
||||
|
||||
src/include/taler_error_codes.h: contrib/gana/gnu-taler-error-codes/registry.rec
|
||||
contrib/gana-update.sh
|
||||
|
||||
@DX_RULES@
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
10
configure.ac
10
configure.ac
@ -291,7 +291,6 @@ AC_CHECK_HEADERS([gnunet/gnunet_sq_lib.h],
|
||||
|
||||
|
||||
# check for libmicrohttpd
|
||||
microhttpd=0
|
||||
AC_MSG_CHECKING([for microhttpd])
|
||||
AC_ARG_WITH([microhttpd],
|
||||
[AS_HELP_STRING([--with-microhttpd=PFX], [base of microhttpd installation])],
|
||||
@ -303,14 +302,7 @@ AS_CASE([$with_microhttpd],
|
||||
[no], [AC_MSG_ERROR([--with-microhttpd is required])],
|
||||
[LDFLAGS="-L$with_microhttpd/lib $LDFLAGS"
|
||||
CPPFLAGS="-I$with_microhttpd/include $CPPFLAGS"])
|
||||
AC_CHECK_LIB(microhttpd,MHD_start_daemon,
|
||||
[AC_CHECK_HEADER([microhttpd.h],[microhttpd=1])])
|
||||
AC_CHECK_DECL([MHD_DAEMON_INFO_CURRENT_CONNECTIONS],,[microhttpd=0],[[#include <microhttpd.h>]])
|
||||
AS_IF([test $microhttpd = 0],
|
||||
[AC_MSG_ERROR([[
|
||||
***
|
||||
*** You need libmicrohttpd >= 0.9.39 to build this program.
|
||||
*** ]])])
|
||||
MHD_VERSION_AT_LEAST([0.9.71])
|
||||
|
||||
# check for libjansson (Jansson JSON library)
|
||||
jansson=0
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 24eb905bac48869b4184801571c0728c772b299c
|
||||
Subproject commit 75c838e74c41bf9a6c02cdfe8109a444056bf26d
|
@ -3,32 +3,36 @@
|
||||
# Run from exchange/ main directory.
|
||||
set -eu
|
||||
|
||||
# Generate taler-error-codes.h in gana and copy it to
|
||||
# src/include/taler_error_codes.h
|
||||
cd contrib/gana/gnu-taler-error-codes
|
||||
make
|
||||
cd ../../..
|
||||
for n in taler_error_codes.c
|
||||
do
|
||||
if ! diff contrib/gana/gnu-taler-error-codes/${n} src/util/${n} > /dev/null
|
||||
domake ()
|
||||
{
|
||||
# $1 -- dir under contrib/
|
||||
dir="contrib/$1"
|
||||
|
||||
make -C $dir
|
||||
}
|
||||
|
||||
ensure ()
|
||||
{
|
||||
# $1 -- filename
|
||||
# $2 -- src dir under contrib/
|
||||
# $3 -- dst dir under ./
|
||||
fn="$1"
|
||||
src="contrib/$2"
|
||||
dst="./$3"
|
||||
|
||||
if ! diff $src/$fn $dst/$fn > /dev/null
|
||||
then
|
||||
cp contrib/gana/gnu-taler-error-codes/$n src/util/$n
|
||||
cp $src/$fn $dst/$fn
|
||||
chmod -w $dst/$fn
|
||||
fi
|
||||
done
|
||||
for n in taler_error_codes.h
|
||||
do
|
||||
if ! diff contrib/gana/gnu-taler-error-codes/${n} src/include/${n} > /dev/null
|
||||
then
|
||||
cp contrib/gana/gnu-taler-error-codes/$n src/include/$n
|
||||
fi
|
||||
done
|
||||
cd contrib/gana/gnu-taler-db-events
|
||||
make
|
||||
cd ../../..
|
||||
for n in taler_dbevents.h
|
||||
do
|
||||
if ! diff contrib/gana/gnu-taler-db-events/${n} src/include/${n} > /dev/null
|
||||
then
|
||||
cp contrib/gana/gnu-taler-db-events/$n src/include/$n
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
domake gana/gnu-taler-error-codes
|
||||
ensure taler_error_codes.c gana/gnu-taler-error-codes src/util
|
||||
ensure taler_error_codes.h gana/gnu-taler-error-codes src/include
|
||||
|
||||
domake gana/gnu-taler-db-events
|
||||
ensure taler_dbevents.h gana/gnu-taler-db-events src/include
|
||||
|
||||
domake sigp
|
||||
ensure taler_signatures.h sigp src/include
|
||||
|
@ -9,7 +9,7 @@ Generating a new Privacy Policy requires Sphinx, LaTeX with babel
|
||||
packages for all supported languages. On Debian, you should
|
||||
at least install:
|
||||
|
||||
$ apt install python3-sphinx sphinx-intl texlive-lang-german texlive-lang-english
|
||||
$ apt install python3-sphinx sphinx-intl texlive-lang-german texlive-lang-english latexmk texlive-latex-recommended texlive-latex-extra
|
||||
|
||||
(NOTE: List may be incomplete.)
|
||||
|
||||
|
3
contrib/sigp/.gitignore
vendored
Normal file
3
contrib/sigp/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/registry.rec
|
||||
/taler_signatures.h
|
||||
/taler_signatures.h.tmp
|
21
contrib/sigp/Makefile
Normal file
21
contrib/sigp/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
FILES = taler_signatures.h
|
||||
|
||||
gana = ../gana
|
||||
|
||||
|
||||
all: check $(FILES)
|
||||
check: registry.rec
|
||||
recfix --check registry.rec
|
||||
registry.rec:
|
||||
ln -s $(gana)/gnunet-signatures/registry.rec
|
||||
distclean:
|
||||
rm -f *.tmp
|
||||
clean:
|
||||
rm -f $(FILES) *.tmp registry.rec
|
||||
taler_signatures.h.tmp: registry.rec h.template
|
||||
$(gana)/format.sh h.template 'Package = "GNU Taler"' < registry.rec > $@
|
||||
|
||||
taler_signatures.h: h.header taler_signatures.h.tmp h.footer
|
||||
cat h.header taler_signatures.h.tmp h.footer > $@
|
||||
|
||||
.PHONY: check clean distclean
|
10
contrib/sigp/README
Normal file
10
contrib/sigp/README
Normal file
@ -0,0 +1,10 @@
|
||||
This directory contains bootstrap code to extract info from the
|
||||
Signature Purposes database (registry) and format it in various ways.
|
||||
It is a peer of ${top_srcdir}/contrib/gana/ (q.v.).
|
||||
|
||||
NB: New database entries MUST have field "Package: GNU Taler" if
|
||||
you want them to be visible to the Makefile in this directory.
|
||||
|
||||
Don't make changes to registry.rec here (it is a symlink, after all).
|
||||
Instead, make them in ../gana/gnunet-signatures/ or from a separate
|
||||
checkout of the GANA Git repo (commit from there, too).
|
3
contrib/sigp/h.footer
Normal file
3
contrib/sigp/h.footer
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
#endif
|
32
contrib/sigp/h.header
Normal file
32
contrib/sigp/h.header
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file taler_signatures.h
|
||||
* @brief message formats and signature constants used to define
|
||||
* the binary formats of signatures in Taler
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
*
|
||||
* This file should define the constants and C structs that one needs
|
||||
* to know to implement Taler clients (wallets or merchants or
|
||||
* auditor) that need to produce or verify Taler signatures.
|
||||
*/
|
||||
#ifndef TALER_SIGNATURES_H
|
||||
#define TALER_SIGNATURES_H
|
||||
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include "taler_amount_lib.h"
|
||||
#include "taler_crypto_lib.h"
|
6
contrib/sigp/h.template
Normal file
6
contrib/sigp/h.template
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
/**
|
||||
* {{Comment}}
|
||||
*/
|
||||
#define TALER_SIGNATURE_{{Name}} {{Number}}
|
@ -9,7 +9,7 @@ Generating new Terms of Service requires Sphinx, LaTeX with babel
|
||||
packages for all supported languages. On Debian, you should
|
||||
at least install:
|
||||
|
||||
$ apt install python3-sphinx sphinx-intl texlive-lang-german texlive-lang-english
|
||||
$ apt install python3-sphinx sphinx-intl texlive-lang-german texlive-lang-english latexmk texlive-latex-recommended texlive-latex-extra
|
||||
|
||||
(NOTE: List may be incomplete.)
|
||||
|
||||
|
310
contrib/tos/bfh.rst
Normal file
310
contrib/tos/bfh.rst
Normal file
@ -0,0 +1,310 @@
|
||||
Terms Of Service
|
||||
================
|
||||
|
||||
Last Updated: 09.06.2022
|
||||
|
||||
Welcome! The ICE research center of the Bern University of Applied Sciences
|
||||
in Switzerland (“we,” “our,” or “us”) provides an experimental payment service
|
||||
through our Internet presence (collectively the “Services”). Before using our
|
||||
Services, please read the Terms of Service (the “Terms” or the “Agreement”)
|
||||
carefully.
|
||||
|
||||
This is research
|
||||
----------------
|
||||
|
||||
This is a research experiment. Any funds wired to our Bitcoin address are
|
||||
considered a donation to our research group. We may use them to enable
|
||||
payments following the GNU Taler protocol, or simply keep them at our
|
||||
discretion. The service is experimental and may also be discontinued at
|
||||
any time, in which case all remaining funds will definitively be kept by
|
||||
the research group.
|
||||
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
This section provides a brief summary of the highlights of this
|
||||
Agreement. Please note that when you accept this Agreement, you are accepting
|
||||
all of the terms and conditions and not just this section. We and possibly
|
||||
other third parties provide Internet services which interact with the Taler
|
||||
Wallet’s self-hosted personal payment application. When using the Taler Wallet
|
||||
to interact with our Services, you are agreeing to our Terms, so please read
|
||||
carefully.
|
||||
|
||||
Highlights:
|
||||
~~~~~~~~~~~
|
||||
|
||||
• You are responsible for keeping the data in your Taler Wallet at all times
|
||||
under your control. Any losses arising from you not being in control of
|
||||
your private information are your problem.
|
||||
• We may transfer funds we receive from our users to any legal
|
||||
recipient to the best of our ability within the limitations of the law and
|
||||
our implementation. However, the Services offered today are highly
|
||||
experimental and the set of recipients of funds is severely restricted.
|
||||
Again, we stress this is a research experiment and technically all funds
|
||||
held by the exchange are owned by the research group of the university.
|
||||
• For our Services, we may charge transaction fees. The specific fee structure
|
||||
is provided based on the Taler protocol and should be shown to you when you
|
||||
withdraw electronic coins using a Taler Wallet. You agree and understand
|
||||
that the Taler protocol allows for the fee structure to change.
|
||||
• You agree to not intentionally overwhelm our systems with requests and
|
||||
follow responsible disclosure if you find security issues in our services.
|
||||
• We cannot be held accountable for our Services not being available due to
|
||||
any circumstances. If we modify or terminate our services,
|
||||
we may give you the opportunity to recover your funds. However,
|
||||
given the experimental state of the Services today, this may not be
|
||||
possible. You are strongly advised to limit your use of the Service
|
||||
to small-scale experiments expecting total loss of all funds.
|
||||
|
||||
These terms outline approved uses of our Services. The Services and these
|
||||
Terms are still at an experimental stage. If you have any questions or
|
||||
comments related to this Agreement, please send us a message to
|
||||
ice@bfh.ch. If you do not agree to this Agreement, you must not
|
||||
use our Services.
|
||||
|
||||
How you accept this policy
|
||||
--------------------------
|
||||
|
||||
By sending funds to us (to top-up your Taler Wallet), you acknowledge that you
|
||||
have read, understood, and agreed to these Terms. We reserve the right to
|
||||
change these Terms at any time. If you disagree with the change, we may in the
|
||||
future offer you with an easy option to recover your unspent funds. However,
|
||||
in the current experimental period you acknowledge that this feature is not
|
||||
yet available, resulting in your funds being lost unless you accept the new
|
||||
Terms. If you continue to use our Services other than to recover your unspent
|
||||
funds, your continued use of our Services following any such change will
|
||||
signify your acceptance to be bound by the then current Terms. Please check
|
||||
the effective date above to determine if there have been any changes since you
|
||||
have last reviewed these Terms.
|
||||
|
||||
Services
|
||||
--------
|
||||
|
||||
We will try to transfer funds that we receive from users to any legal
|
||||
recipient to the best of our ability and within the limitations of the
|
||||
law. However, the Services offered today are highly experimental and the set
|
||||
of recipients of funds is severely restricted. The Taler Wallet can be loaded
|
||||
by exchanging fiat or cryptocurrencies against electronic coins. We are
|
||||
providing this exchange service. Once your Taler Wallet is loaded with
|
||||
electronic coins they can be spent for purchases if the seller is accepting
|
||||
Taler as a means of payment. We are not guaranteeing that any seller is
|
||||
accepting Taler at all or a particular seller. The seller or recipient of
|
||||
deposits of electronic coins must specify the target account, as per the
|
||||
design of the Taler protocol. They are responsible for following the protocol
|
||||
and specifying the correct bank account, and are solely liable for any losses
|
||||
that may arise from specifying the wrong account. We may allow the government
|
||||
to link wire transfers to the underlying contract hash. It is the
|
||||
responsibility of recipients to preserve the full contracts and to pay
|
||||
whatever taxes and charges may be applicable. Technical issues may lead to
|
||||
situations where we are unable to make transfers at all or lead to incorrect
|
||||
transfers that cannot be reversed. We may refuse to execute transfers if the
|
||||
transfers are prohibited by a competent legal authority and we are ordered to
|
||||
do so.
|
||||
|
||||
When using our Services, you agree to not take any action that intentionally
|
||||
imposes an unreasonable load on our infrastructure. If you find security
|
||||
problems in our Services, you agree to first report them to
|
||||
security@taler-systems.com and grant us the right to publish your report. We
|
||||
warrant that we will ourselves publicly disclose any issues reported within 3
|
||||
months, and that we will not prosecute anyone reporting security issues if
|
||||
they did not exploit the issue beyond a proof-of-concept, and followed the
|
||||
above responsible disclosure practice.
|
||||
|
||||
|
||||
Fees
|
||||
----
|
||||
|
||||
You agree to pay the fees for exchanges and withdrawals completed via the
|
||||
Taler Wallet ("Fees") as defined by us, which we may change from time to
|
||||
time. With the exception of wire transfer fees, Taler transaction fees are set
|
||||
for any electronic coin at the time of withdrawal and fixed throughout the
|
||||
validity period of the respective electronic coin. Your wallet should obtain
|
||||
and display applicable fees when withdrawing funds. Fees for coins obtained as
|
||||
change may differ from the fees applicable to the original coin. Wire transfer
|
||||
fees that are independent from electronic coins may change annually. You
|
||||
authorize us to charge or deduct applicable fees owed in connection with
|
||||
deposits, exchanges and withdrawals following the rules of the Taler protocol.
|
||||
We reserve the right to provide different types of rewards to users either in
|
||||
the form of discount for our Services or in any other form at our discretion
|
||||
and without prior notice to you.
|
||||
|
||||
Eligibility and Financial self-responsibility
|
||||
---------------------------------------------
|
||||
|
||||
To be eligible to use our Services, you must be able to form legally binding
|
||||
contracts or have the permission of your legal guardian. By using our
|
||||
Services, you represent and warrant that you meet all eligibility requirements
|
||||
that we outline in these Terms.
|
||||
|
||||
You will be responsible for maintaining the availability, integrity and
|
||||
confidentiality of the data stored in your wallet. When you setup a Taler
|
||||
Wallet, you are strongly advised to follow the precautionary measures offered
|
||||
by the software to minimize the chances to losse access to or control over
|
||||
your Wallet data. We will not be liable for any loss or damage arising from
|
||||
your failure to comply with this paragraph.
|
||||
|
||||
Copyrights and trademarks
|
||||
-------------------------
|
||||
|
||||
The Taler Wallet is released under the terms of the GNU General Public License
|
||||
(GNU GPL). You have the right to access, use, and share the Taler Wallet, in
|
||||
modified or unmodified form. However, the GPL is a strong copyleft license,
|
||||
which means that any derivative works must be distributed under the same
|
||||
license terms as the original software. If you have any questions, you should
|
||||
review the GNU GPL’s full terms and conditions at
|
||||
https://www.gnu.org/licenses/gpl-3.0.en.html. “Taler” itself is a trademark
|
||||
of Taler Systems SA. You are welcome to use the name in relation to processing
|
||||
payments using the Taler protocol, assuming your use is compatible with an
|
||||
official release from the GNU Project that is not older than two years.
|
||||
|
||||
|
||||
Limitation of liability & disclaimer of warranties
|
||||
--------------------------------------------------
|
||||
|
||||
You understand and agree that we have no control over, and no duty to take any
|
||||
action regarding: Failures, disruptions, errors, or delays in processing that
|
||||
you may experience while using our Services; The risk of failure of hardware,
|
||||
software, and Internet connections; The risk of malicious software being
|
||||
introduced or found in the software underlying the Taler Wallet; The risk that
|
||||
third parties may obtain unauthorized access to information stored within your
|
||||
Taler Wallet, including, but not limited to your Taler Wallet coins or backup
|
||||
encryption keys. You release us from all liability related to any losses,
|
||||
damages, or claims arising from:
|
||||
|
||||
(a) user error such as forgotten passwords, incorrectly constructed
|
||||
transactions;
|
||||
(b) server failure or data loss;
|
||||
(c) unauthorized access to the Taler Wallet application;
|
||||
(d) bugs or other errors in the Taler Wallet software; and
|
||||
(e) any unauthorized third party activities, including, but not limited to,
|
||||
the use of viruses, phishing, brute forcing, or other means of attack
|
||||
against the Taler Wallet. We make no representations concerning any
|
||||
Third Party Content contained in or accessed through our Services.
|
||||
|
||||
Any other terms, conditions, warranties, or representations associated with
|
||||
such content, are solely between you and such organizations and/or
|
||||
individuals.
|
||||
|
||||
To the fullest extent permitted by applicable law, in no event will we or any
|
||||
of our officers, directors, representatives, agents, servants, counsel,
|
||||
employees, consultants, lawyers, and other personnel authorized to act,
|
||||
acting, or purporting to act on our behalf (collectively the “Taler Parties”)
|
||||
be liable to you under contract, tort, strict liability, negligence, or any
|
||||
other legal or equitable theory, for:
|
||||
|
||||
(a) any lost profits, data loss, cost of procurement of substitute goods or
|
||||
services, or direct, indirect, incidental, special, punitive, compensatory,
|
||||
or consequential damages of any kind whatsoever resulting from:
|
||||
|
||||
(i) your use of, or conduct in connection with, our services;
|
||||
(ii) any unauthorized use of your wallet and/or private key due to your
|
||||
failure to maintain the confidentiality of your wallet;
|
||||
(iii) any interruption or cessation of transmission to or from the services; or
|
||||
(iv) any bugs, viruses, trojan horses, or the like that are found in the Taler
|
||||
Wallet software or that may be transmitted to or through our services by
|
||||
any third party (regardless of the source of origination), or
|
||||
|
||||
(b) any direct damages.
|
||||
|
||||
These limitations apply regardless of legal theory, whether based on tort,
|
||||
strict liability, breach of contract, breach of warranty, or any other legal
|
||||
theory, and whether or not we were advised of the possibility of such
|
||||
damages. Some jurisdictions do not allow the exclusion or limitation of
|
||||
liability for consequential or incidental damages, so the above limitation may
|
||||
not apply to you.
|
||||
|
||||
Our services are provided "as is" and without warranty of any kind. To the
|
||||
maximum extent permitted by law, we disclaim all representations and
|
||||
warranties, express or implied, relating to the services and underlying
|
||||
software or any content on the services, whether provided or owned by us or by
|
||||
any third party, including without limitation, warranties of merchantability,
|
||||
fitness for a particular purpose, title, non-infringement, freedom from
|
||||
computer virus, and any implied warranties arising from course of dealing,
|
||||
course of performance, or usage in trade, all of which are expressly
|
||||
disclaimed. In addition, we do not represent or warrant that the content
|
||||
accessible via the services is accurate, complete, available, current, free of
|
||||
viruses or other harmful components, or that the results of using the services
|
||||
will meet your requirements. Some states do not allow the disclaimer of
|
||||
implied warranties, so the foregoing disclaimers may not apply to you. This
|
||||
paragraph gives you specific legal rights and you may also have other legal
|
||||
rights that vary from state to state.
|
||||
|
||||
Indemnity and Time limitation on claims and Termination
|
||||
-------------------------------------------------------
|
||||
|
||||
To the extent permitted by applicable law, you agree to defend, indemnify, and
|
||||
hold harmless the Taler Parties from and against any and all claims, damages,
|
||||
obligations, losses, liabilities, costs or debt, and expenses (including, but
|
||||
not limited to, attorney’s fees) arising from: (a) your use of and access to
|
||||
the Services; (b) any feedback or submissions you provide to us concerning the
|
||||
Taler Wallet; (c) your violation of any term of this Agreement; or (d) your
|
||||
violation of any law, rule, or regulation, or the rights of any third party.
|
||||
|
||||
You agree that any claim you may have arising out of or related to your
|
||||
relationship with us must be filed within one year after such claim arises,
|
||||
otherwise, your claim in permanently barred.
|
||||
|
||||
In the event of termination concerning your use of our Services, your
|
||||
obligations under this Agreement will still continue.
|
||||
|
||||
|
||||
Discontinuance of services and Force majeure
|
||||
--------------------------------------------
|
||||
|
||||
We may, in our sole discretion and without cost to you, with or without prior
|
||||
notice, and at any time, modify or discontinue, temporarily or permanently,
|
||||
any portion of our Services. We will use the Taler protocol’s provisions to
|
||||
notify Wallets if our Services are to be discontinued. It is your
|
||||
responsibility to ensure that the Taler Wallet is online at least once every
|
||||
three months to observe these notifications. We shall not be held responsible
|
||||
or liable for any loss of funds in the event that we discontinue or depreciate
|
||||
the Services and your Taler Wallet fails to transfer out the coins within a
|
||||
three months notification period.
|
||||
|
||||
We shall not be held liable for any delays, failure in performance, or
|
||||
interruptions of service which result directly or indirectly from any cause or
|
||||
condition beyond our reasonable control, including but not limited to: any
|
||||
delay or failure due to any act of God, act of civil or military authorities,
|
||||
act of terrorism, civil disturbance, war, strike or other labor dispute, fire,
|
||||
interruption in telecommunications or Internet services or network provider
|
||||
services, failure of equipment and/or software, other catastrophe, or any
|
||||
other occurrence which is beyond our reasonable control and shall not affect
|
||||
the validity and enforceability of any remaining provisions.
|
||||
|
||||
|
||||
Governing law, Waivers, Severability and Assignment
|
||||
---------------------------------------------------
|
||||
|
||||
No matter where you’re located, the laws of Switzerland will govern these
|
||||
Terms. If any provisions of these Terms are inconsistent with any applicable
|
||||
law, those provisions will be superseded or modified only to the extent such
|
||||
provisions are inconsistent. The parties agree to submit to the ordinary
|
||||
courts in Bern, Switzerland for exclusive jurisdiction of any dispute
|
||||
arising out of or related to your use of the Services or your breach of these
|
||||
Terms.
|
||||
|
||||
Our failure to exercise or delay in exercising any right, power, or privilege
|
||||
under this Agreement shall not operate as a waiver; nor shall any single or
|
||||
partial exercise of any right, power, or privilege preclude any other or
|
||||
further exercise thereof.
|
||||
|
||||
You agree that we may assign any of our rights and/or transfer, sub-contract,
|
||||
or delegate any of our obligations under these Terms.
|
||||
|
||||
If it turns out that any part of this Agreement is invalid, void, or for any
|
||||
reason unenforceable, that term will be deemed severable and limited or
|
||||
eliminated to the minimum extent necessary.
|
||||
|
||||
This Agreement sets forth the entire understanding and agreement as to the
|
||||
subject matter hereof and supersedes any and all prior discussions,
|
||||
agreements, and understandings of any kind (including, without limitation, any
|
||||
prior versions of this Agreement) and every nature between us. Except as
|
||||
provided for above, any modification to this Agreement must be in writing and
|
||||
must be signed by both parties.
|
||||
|
||||
|
||||
Questions or comments
|
||||
---------------------
|
||||
|
||||
We welcome comments, questions, concerns, or suggestions. Please send us a
|
||||
message on our contact page at legal@taler-systems.com.
|
Binary file not shown.
@ -20,11 +20,21 @@
|
||||
|
||||
<div class="section" id="terms-of-service">
|
||||
<h1>Terms Of Service<a class="headerlink" href="#terms-of-service" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Last Updated: 12.4.2019</p>
|
||||
<p>Welcome! Taler Systems SA (“we,” “our,” or “us”) provides a payment service
|
||||
<p>Last Updated: 09.06.2022</p>
|
||||
<p>Welcome! The ICE research center of the Bern University of Applied Sciences
|
||||
in Switzerland (“we,” “our,” or “us”) provides an experimental payment service
|
||||
through our Internet presence (collectively the “Services”). Before using our
|
||||
Services, please read the Terms of Service (the “Terms” or the “Agreement”)
|
||||
carefully.</p>
|
||||
<div class="section" id="this-is-research">
|
||||
<h2>This is research<a class="headerlink" href="#this-is-research" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This is a research experiment. Any funds wired to our Bitcoin address are
|
||||
considered a donation to our research group. We may use them to enable
|
||||
payments following the GNU Taler protocol, or simply keep them at our
|
||||
discretion. The service is experimental and may also be discontinued at
|
||||
any time, in which case all remaining funds will definitively be kept by
|
||||
the research group.</p>
|
||||
</div>
|
||||
<div class="section" id="overview">
|
||||
<h2>Overview<a class="headerlink" href="#overview" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This section provides a brief summary of the highlights of this
|
||||
@ -41,10 +51,12 @@ carefully.</p>
|
||||
<li><p>You are responsible for keeping the data in your Taler Wallet at all times
|
||||
under your control. Any losses arising from you not being in control of
|
||||
your private information are your problem.</p></li>
|
||||
<li><p>We will try to transfer funds we hold in escrow for our users to any legal
|
||||
<li><p>We may transfer funds we receive from our users to any legal
|
||||
recipient to the best of our ability within the limitations of the law and
|
||||
our implementation. However, the Services offered today are highly
|
||||
experimental and the set of recipients of funds is severely restricted.</p></li>
|
||||
experimental and the set of recipients of funds is severely restricted.
|
||||
Again, we stress this is a research experiment and technically all funds
|
||||
held by the exchange are owned by the research group of the university.</p></li>
|
||||
<li><p>For our Services, we may charge transaction fees. The specific fee structure
|
||||
is provided based on the Taler protocol and should be shown to you when you
|
||||
withdraw electronic coins using a Taler Wallet. You agree and understand
|
||||
@ -52,8 +64,8 @@ that the Taler protocol allows for the fee structure to change.</p></li>
|
||||
<li><p>You agree to not intentionally overwhelm our systems with requests and
|
||||
follow responsible disclosure if you find security issues in our services.</p></li>
|
||||
<li><p>We cannot be held accountable for our Services not being available due to
|
||||
circumstances beyond our control. If we modify or terminate our services,
|
||||
we will try to give you the opportunity to recover your funds. However,
|
||||
any circumstances. If we modify or terminate our services,
|
||||
we may give you the opportunity to recover your funds. However,
|
||||
given the experimental state of the Services today, this may not be
|
||||
possible. You are strongly advised to limit your use of the Service
|
||||
to small-scale experiments expecting total loss of all funds.</p></li>
|
||||
@ -62,7 +74,7 @@ to small-scale experiments expecting total loss of all funds.</p></li>
|
||||
<p>These terms outline approved uses of our Services. The Services and these
|
||||
Terms are still at an experimental stage. If you have any questions or
|
||||
comments related to this Agreement, please send us a message to
|
||||
<a class="reference external" href="mailto:legal%40taler-systems.com">legal<span>@</span>taler-systems<span>.</span>com</a>. If you do not agree to this Agreement, you must not
|
||||
<a class="reference external" href="mailto:ice%40bfh.ch">ice<span>@</span>bfh<span>.</span>ch</a>. If you do not agree to this Agreement, you must not
|
||||
use our Services.</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -82,26 +94,26 @@ have last reviewed these Terms.</p>
|
||||
</div>
|
||||
<div class="section" id="services">
|
||||
<h2>Services<a class="headerlink" href="#services" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We will try to transfer funds that we hold in escrow for our users to any
|
||||
legal recipient to the best of our ability and within the limitations of the
|
||||
law and our implementation. However, the Services offered today are highly
|
||||
experimental and the set of recipients of funds is severely restricted. The
|
||||
Taler Wallet can be loaded by exchanging fiat currencies against electronic
|
||||
coins. We are providing this exchange service. Once your Taler Wallet is
|
||||
loaded with electronic coins they can be spent for purchases if the seller is
|
||||
accepting Taler as a means of payment. We are not guaranteeing that any seller
|
||||
is accepting Taler at all or a particular seller. The seller or recipient of
|
||||
<p>We will try to transfer funds that we receive from users to any legal
|
||||
recipient to the best of our ability and within the limitations of the
|
||||
law. However, the Services offered today are highly experimental and the set
|
||||
of recipients of funds is severely restricted. The Taler Wallet can be loaded
|
||||
by exchanging fiat or cryptocurrencies against electronic coins. We are
|
||||
providing this exchange service. Once your Taler Wallet is loaded with
|
||||
electronic coins they can be spent for purchases if the seller is accepting
|
||||
Taler as a means of payment. We are not guaranteeing that any seller is
|
||||
accepting Taler at all or a particular seller. The seller or recipient of
|
||||
deposits of electronic coins must specify the target account, as per the
|
||||
design of the Taler protocol. They are responsible for following the protocol
|
||||
and specifying the correct bank account, and are solely liable for any losses
|
||||
that may arise from specifying the wrong account. We will allow the government
|
||||
that may arise from specifying the wrong account. We may allow the government
|
||||
to link wire transfers to the underlying contract hash. It is the
|
||||
responsibility of recipients to preserve the full contracts and to pay
|
||||
whatever taxes and charges may be applicable. Technical issues may lead to
|
||||
situations where we are unable to make transfers at all or lead to incorrect
|
||||
transfers that cannot be reversed. We will only refuse to execute transfers if
|
||||
the transfers are prohibited by a competent legal authority and we are ordered
|
||||
to do so.</p>
|
||||
transfers that cannot be reversed. We may refuse to execute transfers if the
|
||||
transfers are prohibited by a competent legal authority and we are ordered to
|
||||
do so.</p>
|
||||
<p>When using our Services, you agree to not take any action that intentionally
|
||||
imposes an unreasonable load on our infrastructure. If you find security
|
||||
problems in our Services, you agree to first report them to
|
||||
@ -267,7 +279,7 @@ the validity and enforceability of any remaining provisions.</p>
|
||||
Terms. If any provisions of these Terms are inconsistent with any applicable
|
||||
law, those provisions will be superseded or modified only to the extent such
|
||||
provisions are inconsistent. The parties agree to submit to the ordinary
|
||||
courts in Zurich, Switzerland for exclusive jurisdiction of any dispute
|
||||
courts in Bern, Switzerland for exclusive jurisdiction of any dispute
|
||||
arising out of or related to your use of the Services or your breach of these
|
||||
Terms.</p>
|
||||
<p>Our failure to exercise or delay in exercising any right, power, or privilege
|
||||
|
Binary file not shown.
@ -1,12 +1,24 @@
|
||||
Terms Of Service
|
||||
****************
|
||||
|
||||
Last Updated: 12.4.2019
|
||||
Last Updated: 09.06.2022
|
||||
|
||||
Welcome! Taler Systems SA (“we,” “our,” or “us”) provides a payment
|
||||
service through our Internet presence (collectively the “Services”).
|
||||
Before using our Services, please read the Terms of Service (the
|
||||
“Terms” or the “Agreement”) carefully.
|
||||
Welcome! The ICE research center of the Bern University of Applied
|
||||
Sciences in Switzerland (“we,” “our,” or “us”) provides an
|
||||
experimental payment service through our Internet presence
|
||||
(collectively the “Services”). Before using our Services, please read
|
||||
the Terms of Service (the “Terms” or the “Agreement”) carefully.
|
||||
|
||||
|
||||
This is research
|
||||
================
|
||||
|
||||
This is a research experiment. Any funds wired to our Bitcoin address
|
||||
are considered a donation to our research group. We may use them to
|
||||
enable payments following the GNU Taler protocol, or simply keep them
|
||||
at our discretion. The service is experimental and may also be
|
||||
discontinued at any time, in which case all remaining funds will
|
||||
definitively be kept by the research group.
|
||||
|
||||
|
||||
Overview
|
||||
@ -28,11 +40,13 @@ Highlights:
|
||||
all times under your control. Any losses arising from you not
|
||||
being in control of your private information are your problem.
|
||||
|
||||
* We will try to transfer funds we hold in escrow for our users to
|
||||
any legal recipient to the best of our ability within the
|
||||
limitations of the law and our implementation. However, the
|
||||
Services offered today are highly experimental and the set of
|
||||
recipients of funds is severely restricted.
|
||||
* We may transfer funds we receive from our users to any legal
|
||||
recipient to the best of our ability within the limitations of
|
||||
the law and our implementation. However, the Services offered
|
||||
today are highly experimental and the set of recipients of funds
|
||||
is severely restricted. Again, we stress this is a research
|
||||
experiment and technically all funds held by the exchange are
|
||||
owned by the research group of the university.
|
||||
|
||||
* For our Services, we may charge transaction fees. The specific
|
||||
fee structure is provided based on the Taler protocol and should
|
||||
@ -45,19 +59,18 @@ Highlights:
|
||||
issues in our services.
|
||||
|
||||
* We cannot be held accountable for our Services not being
|
||||
available due to circumstances beyond our control. If we modify
|
||||
or terminate our services, we will try to give you the
|
||||
opportunity to recover your funds. However, given the
|
||||
experimental state of the Services today, this may not be
|
||||
possible. You are strongly advised to limit your use of the
|
||||
Service to small-scale experiments expecting total loss of all
|
||||
funds.
|
||||
available due to any circumstances. If we modify or terminate our
|
||||
services, we may give you the opportunity to recover your funds.
|
||||
However, given the experimental state of the Services today, this
|
||||
may not be possible. You are strongly advised to limit your use
|
||||
of the Service to small-scale experiments expecting total loss of
|
||||
all funds.
|
||||
|
||||
These terms outline approved uses of our Services. The Services and
|
||||
these Terms are still at an experimental stage. If you have any
|
||||
questions or comments related to this Agreement, please send us a
|
||||
message to legal@taler-systems.com. If you do not agree to this
|
||||
Agreement, you must not use our Services.
|
||||
message to ice@bfh.ch. If you do not agree to this Agreement, you must
|
||||
not use our Services.
|
||||
|
||||
|
||||
How you accept this policy
|
||||
@ -80,26 +93,25 @@ since you have last reviewed these Terms.
|
||||
Services
|
||||
========
|
||||
|
||||
We will try to transfer funds that we hold in escrow for our users to
|
||||
any legal recipient to the best of our ability and within the
|
||||
limitations of the law and our implementation. However, the Services
|
||||
offered today are highly experimental and the set of recipients of
|
||||
funds is severely restricted. The Taler Wallet can be loaded by
|
||||
exchanging fiat currencies against electronic coins. We are providing
|
||||
this exchange service. Once your Taler Wallet is loaded with
|
||||
electronic coins they can be spent for purchases if the seller is
|
||||
accepting Taler as a means of payment. We are not guaranteeing that
|
||||
any seller is accepting Taler at all or a particular seller. The
|
||||
seller or recipient of deposits of electronic coins must specify the
|
||||
target account, as per the design of the Taler protocol. They are
|
||||
responsible for following the protocol and specifying the correct bank
|
||||
account, and are solely liable for any losses that may arise from
|
||||
specifying the wrong account. We will allow the government to link
|
||||
wire transfers to the underlying contract hash. It is the
|
||||
responsibility of recipients to preserve the full contracts and to pay
|
||||
whatever taxes and charges may be applicable. Technical issues may
|
||||
lead to situations where we are unable to make transfers at all or
|
||||
lead to incorrect transfers that cannot be reversed. We will only
|
||||
We will try to transfer funds that we receive from users to any legal
|
||||
recipient to the best of our ability and within the limitations of the
|
||||
law. However, the Services offered today are highly experimental and
|
||||
the set of recipients of funds is severely restricted. The Taler
|
||||
Wallet can be loaded by exchanging fiat or cryptocurrencies against
|
||||
electronic coins. We are providing this exchange service. Once your
|
||||
Taler Wallet is loaded with electronic coins they can be spent for
|
||||
purchases if the seller is accepting Taler as a means of payment. We
|
||||
are not guaranteeing that any seller is accepting Taler at all or a
|
||||
particular seller. The seller or recipient of deposits of electronic
|
||||
coins must specify the target account, as per the design of the Taler
|
||||
protocol. They are responsible for following the protocol and
|
||||
specifying the correct bank account, and are solely liable for any
|
||||
losses that may arise from specifying the wrong account. We may allow
|
||||
the government to link wire transfers to the underlying contract hash.
|
||||
It is the responsibility of recipients to preserve the full contracts
|
||||
and to pay whatever taxes and charges may be applicable. Technical
|
||||
issues may lead to situations where we are unable to make transfers at
|
||||
all or lead to incorrect transfers that cannot be reversed. We may
|
||||
refuse to execute transfers if the transfers are prohibited by a
|
||||
competent legal authority and we are ordered to do so.
|
||||
|
||||
@ -306,7 +318,7 @@ No matter where you’re located, the laws of Switzerland will govern
|
||||
these Terms. If any provisions of these Terms are inconsistent with
|
||||
any applicable law, those provisions will be superseded or modified
|
||||
only to the extent such provisions are inconsistent. The parties agree
|
||||
to submit to the ordinary courts in Zurich, Switzerland for exclusive
|
||||
to submit to the ordinary courts in Bern, Switzerland for exclusive
|
||||
jurisdiction of any dispute arising out of or related to your use of
|
||||
the Services or your breach of these Terms.
|
||||
|
||||
|
@ -1,14 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE document PUBLIC "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML" "http://docutils.sourceforge.net/docs/ref/docutils.dtd">
|
||||
<!-- Generated by Docutils 0.16 -->
|
||||
<document source="/research/taler/exchange/contrib/tos/tos.rst">
|
||||
<document source="/home/grothoff/research/taler/exchange/contrib/tos/tos.rst">
|
||||
<section ids="terms-of-service" names="terms\ of\ service">
|
||||
<title>Terms Of Service</title>
|
||||
<paragraph>Last Updated: 12.4.2019</paragraph>
|
||||
<paragraph>Welcome! Taler Systems SA (“we,” “our,” or “us”) provides a payment service
|
||||
<paragraph>Last Updated: 09.06.2022</paragraph>
|
||||
<paragraph>Welcome! The ICE research center of the Bern University of Applied Sciences
|
||||
in Switzerland (“we,” “our,” or “us”) provides an experimental payment service
|
||||
through our Internet presence (collectively the “Services”). Before using our
|
||||
Services, please read the Terms of Service (the “Terms” or the “Agreement”)
|
||||
carefully.</paragraph>
|
||||
<section ids="this-is-research" names="this\ is\ research">
|
||||
<title>This is research</title>
|
||||
<paragraph>This is a research experiment. Any funds wired to our Bitcoin address are
|
||||
considered a donation to our research group. We may use them to enable
|
||||
payments following the GNU Taler protocol, or simply keep them at our
|
||||
discretion. The service is experimental and may also be discontinued at
|
||||
any time, in which case all remaining funds will definitively be kept by
|
||||
the research group.</paragraph>
|
||||
</section>
|
||||
<section ids="overview" names="overview">
|
||||
<title>Overview</title>
|
||||
<paragraph>This section provides a brief summary of the highlights of this
|
||||
@ -28,10 +38,12 @@
|
||||
your private information are your problem.</paragraph>
|
||||
</list_item>
|
||||
<list_item>
|
||||
<paragraph>We will try to transfer funds we hold in escrow for our users to any legal
|
||||
<paragraph>We may transfer funds we receive from our users to any legal
|
||||
recipient to the best of our ability within the limitations of the law and
|
||||
our implementation. However, the Services offered today are highly
|
||||
experimental and the set of recipients of funds is severely restricted.</paragraph>
|
||||
experimental and the set of recipients of funds is severely restricted.
|
||||
Again, we stress this is a research experiment and technically all funds
|
||||
held by the exchange are owned by the research group of the university.</paragraph>
|
||||
</list_item>
|
||||
<list_item>
|
||||
<paragraph>For our Services, we may charge transaction fees. The specific fee structure
|
||||
@ -45,8 +57,8 @@
|
||||
</list_item>
|
||||
<list_item>
|
||||
<paragraph>We cannot be held accountable for our Services not being available due to
|
||||
circumstances beyond our control. If we modify or terminate our services,
|
||||
we will try to give you the opportunity to recover your funds. However,
|
||||
any circumstances. If we modify or terminate our services,
|
||||
we may give you the opportunity to recover your funds. However,
|
||||
given the experimental state of the Services today, this may not be
|
||||
possible. You are strongly advised to limit your use of the Service
|
||||
to small-scale experiments expecting total loss of all funds.</paragraph>
|
||||
@ -56,7 +68,7 @@
|
||||
<paragraph>These terms outline approved uses of our Services. The Services and these
|
||||
Terms are still at an experimental stage. If you have any questions or
|
||||
comments related to this Agreement, please send us a message to
|
||||
<reference refuri="mailto:legal@taler-systems.com">legal@taler-systems.com</reference>. If you do not agree to this Agreement, you must not
|
||||
<reference refuri="mailto:ice@bfh.ch">ice@bfh.ch</reference>. If you do not agree to this Agreement, you must not
|
||||
use our Services.</paragraph>
|
||||
</section>
|
||||
</section>
|
||||
@ -76,26 +88,26 @@
|
||||
</section>
|
||||
<section ids="services" names="services">
|
||||
<title>Services</title>
|
||||
<paragraph>We will try to transfer funds that we hold in escrow for our users to any
|
||||
legal recipient to the best of our ability and within the limitations of the
|
||||
law and our implementation. However, the Services offered today are highly
|
||||
experimental and the set of recipients of funds is severely restricted. The
|
||||
Taler Wallet can be loaded by exchanging fiat currencies against electronic
|
||||
coins. We are providing this exchange service. Once your Taler Wallet is
|
||||
loaded with electronic coins they can be spent for purchases if the seller is
|
||||
accepting Taler as a means of payment. We are not guaranteeing that any seller
|
||||
is accepting Taler at all or a particular seller. The seller or recipient of
|
||||
<paragraph>We will try to transfer funds that we receive from users to any legal
|
||||
recipient to the best of our ability and within the limitations of the
|
||||
law. However, the Services offered today are highly experimental and the set
|
||||
of recipients of funds is severely restricted. The Taler Wallet can be loaded
|
||||
by exchanging fiat or cryptocurrencies against electronic coins. We are
|
||||
providing this exchange service. Once your Taler Wallet is loaded with
|
||||
electronic coins they can be spent for purchases if the seller is accepting
|
||||
Taler as a means of payment. We are not guaranteeing that any seller is
|
||||
accepting Taler at all or a particular seller. The seller or recipient of
|
||||
deposits of electronic coins must specify the target account, as per the
|
||||
design of the Taler protocol. They are responsible for following the protocol
|
||||
and specifying the correct bank account, and are solely liable for any losses
|
||||
that may arise from specifying the wrong account. We will allow the government
|
||||
that may arise from specifying the wrong account. We may allow the government
|
||||
to link wire transfers to the underlying contract hash. It is the
|
||||
responsibility of recipients to preserve the full contracts and to pay
|
||||
whatever taxes and charges may be applicable. Technical issues may lead to
|
||||
situations where we are unable to make transfers at all or lead to incorrect
|
||||
transfers that cannot be reversed. We will only refuse to execute transfers if
|
||||
the transfers are prohibited by a competent legal authority and we are ordered
|
||||
to do so.</paragraph>
|
||||
transfers that cannot be reversed. We may refuse to execute transfers if the
|
||||
transfers are prohibited by a competent legal authority and we are ordered to
|
||||
do so.</paragraph>
|
||||
<paragraph>When using our Services, you agree to not take any action that intentionally
|
||||
imposes an unreasonable load on our infrastructure. If you find security
|
||||
problems in our Services, you agree to first report them to
|
||||
@ -283,7 +295,7 @@
|
||||
Terms. If any provisions of these Terms are inconsistent with any applicable
|
||||
law, those provisions will be superseded or modified only to the extent such
|
||||
provisions are inconsistent. The parties agree to submit to the ordinary
|
||||
courts in Zurich, Switzerland for exclusive jurisdiction of any dispute
|
||||
courts in Bern, Switzerland for exclusive jurisdiction of any dispute
|
||||
arising out of or related to your use of the Services or your breach of these
|
||||
Terms.</paragraph>
|
||||
<paragraph>Our failure to exercise or delay in exercising any right, power, or privilege
|
||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
||||
taler-exchange (0.8.99-1) unstable; urgency=low
|
||||
|
||||
* Updating to latest pre-release from Git.
|
||||
|
||||
-- Christian Grothoff <grothoff@taler.net> Mon, 20 Jun 2022 13:12:58 +0200
|
||||
|
||||
taler-exchange (0.8.5-3) unstable; urgency=low
|
||||
|
||||
* Updating to latest Git with minor bugfixes and improvements.
|
||||
|
22
debian/control
vendored
22
debian/control
vendored
@ -9,27 +9,22 @@ Build-Depends:
|
||||
bash,
|
||||
debhelper-compat (= 12),
|
||||
gettext,
|
||||
libgnunet-dev (>=0.15.3),
|
||||
libgnunet-dev (>=0.17.1),
|
||||
libcurl4-gnutls-dev (>=7.35.0) | libcurl4-openssl-dev (>= 7.35.0),
|
||||
libgcrypt20-dev (>=1.6),
|
||||
libgcrypt20-dev (>=1.8),
|
||||
libgnutls28-dev (>=3.2.12),
|
||||
libidn2-dev,
|
||||
libjansson-dev,
|
||||
libltdl-dev (>=2.2),
|
||||
libmicrohttpd-dev (>=0.9.63),
|
||||
libpq-dev (>=9.5),
|
||||
libmicrohttpd-dev (>=0.9.71),
|
||||
libpq-dev (>=13),
|
||||
libsodium-dev (>=1.0.11),
|
||||
libsqlite3-dev (>=3.8),
|
||||
libunistring-dev (>=0.9.2),
|
||||
python3-jinja2,
|
||||
net-tools,
|
||||
po-debconf,
|
||||
python3-dev,
|
||||
texinfo (>=5.2),
|
||||
zlib1g-dev
|
||||
Build-Conflicts:
|
||||
autoconf2.13,
|
||||
automake1.4
|
||||
Standards-Version: 4.5.0
|
||||
Vcs-Git: https://salsa.debian.org/debian/taler-exchange.git
|
||||
Vcs-browser: https://salsa.debian.org/debian/taler-exchange
|
||||
@ -72,7 +67,8 @@ Depends:
|
||||
${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Recommends:
|
||||
taler-exchange-offline (= ${binary:Version})
|
||||
taler-exchange-offline (= ${binary:Version}),
|
||||
postgresql (>=13.0)
|
||||
Description: GNU's payment system operator
|
||||
|
||||
Package: taler-exchange-offline
|
||||
@ -109,9 +105,9 @@ Section: libdevel
|
||||
Architecture: any
|
||||
Depends:
|
||||
libtalerexchange (= ${binary:Version}),
|
||||
libgnunet-dev (>=0.15.3),
|
||||
libgcrypt20-dev (>=1.6),
|
||||
libmicrohttpd-dev (>=0.9.33),
|
||||
libgnunet-dev (>=0.17.1),
|
||||
libgcrypt20-dev (>=1.8),
|
||||
libmicrohttpd-dev (>=0.9.71),
|
||||
${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Description: libraries to talk to a GNU Taler exchange (development)
|
||||
|
1
debian/libtalerexchange.install
vendored
1
debian/libtalerexchange.install
vendored
@ -5,5 +5,6 @@ usr/share/taler/config.d/paths.conf
|
||||
usr/share/taler/config.d/taler.conf
|
||||
debian/etc-libtalerexchange/* etc/
|
||||
usr/bin/taler-config
|
||||
usr/bin/taler-crypto-worker
|
||||
usr/share/man/man5/taler.conf.5
|
||||
usr/share/man/man1/taler-config*
|
||||
|
1
debian/rules
vendored
1
debian/rules
vendored
@ -37,6 +37,7 @@ override_dh_installsystemd:
|
||||
dh_installsystemd -ptaler-exchange --name=taler-exchange-aggregator --no-start --no-enable
|
||||
dh_installsystemd -ptaler-exchange --name=taler-exchange-transfer --no-start --no-enable
|
||||
dh_installsystemd -ptaler-exchange --name=taler-exchange-wirewatch --no-start --no-enable
|
||||
dh_installsystemd -ptaler-exchange --name=taler-exchange-secmod-cs --no-start --no-enable
|
||||
dh_installsystemd -ptaler-exchange --name=taler-exchange-secmod-eddsa --no-start --no-enable
|
||||
dh_installsystemd -ptaler-exchange --name=taler-exchange-secmod-rsa --no-start --no-enable
|
||||
dh_installsystemd -ptaler-exchange --name=taler-exchange-closer --no-start --no-enable
|
||||
|
4
debian/taler-exchange.install
vendored
4
debian/taler-exchange.install
vendored
@ -1,7 +1,9 @@
|
||||
usr/bin/taler-exchange-aggregator
|
||||
usr/bin/taler-exchange-closer
|
||||
usr/bin/taler-exchange-dbinit
|
||||
usr/bin/taler-exchange-expire
|
||||
usr/bin/taler-exchange-httpd
|
||||
usr/bin/taler-exchange-router
|
||||
usr/bin/taler-exchange-secmod-cs
|
||||
usr/bin/taler-exchange-secmod-eddsa
|
||||
usr/bin/taler-exchange-secmod-rsa
|
||||
@ -11,7 +13,9 @@ usr/bin/taler-exchange-wire-gateway-client
|
||||
usr/share/man/man1/taler-exchange-aggregator*
|
||||
usr/share/man/man1/taler-exchange-closer*
|
||||
usr/share/man/man1/taler-exchange-dbinit*
|
||||
usr/share/man/man1/taler-exchange-expire*
|
||||
usr/share/man/man1/taler-exchange-httpd*
|
||||
usr/share/man/man1/taler-exchange-router*
|
||||
usr/share/man/man1/taler-exchange-secmod-eddsa*
|
||||
usr/share/man/man1/taler-exchange-secmod-rsa*
|
||||
usr/share/man/man1/taler-exchange-secmod-cs*
|
||||
|
15
debian/taler-exchange.taler-exchange-expire.service
vendored
Normal file
15
debian/taler-exchange.taler-exchange-expire.service
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=GNU Taler payment system exchange expire service
|
||||
PartOf=taler-exchange.target
|
||||
|
||||
[Service]
|
||||
User=taler-exchange-expire
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=100ms
|
||||
ExecStart=/usr/bin/taler-exchange-expire -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
ProtectSystem=full
|
1
debian/taler-exchange.taler-exchange.target
vendored
1
debian/taler-exchange.taler-exchange.target
vendored
@ -6,6 +6,7 @@ Wants=taler-exchange-httpd.service
|
||||
Wants=taler-exchange-wirewatch.service
|
||||
Wants=taler-exchange-aggregator.service
|
||||
Wants=taler-exchange-closer.service
|
||||
Wants=taler-exchange-expire.service
|
||||
Wants=taler-exchange-transfer.service
|
||||
|
||||
[Install]
|
||||
|
4
doc/.gitignore
vendored
4
doc/.gitignore
vendored
@ -1,7 +1,6 @@
|
||||
*.aux
|
||||
*.dvi
|
||||
*.log
|
||||
*.pdf
|
||||
*.out
|
||||
*.snm
|
||||
*.toc
|
||||
@ -25,3 +24,6 @@ taler-exchange.html
|
||||
taler-exchange.fn
|
||||
taler-exchange.cp
|
||||
taler-exchange.auxtaler-exchange.cps
|
||||
cbdc-es/cbdc-es.pdf
|
||||
cbdc-it/cbdc-it.pdf
|
||||
audit/response-202109.pdf
|
||||
|
@ -21,10 +21,13 @@ man_MANS = \
|
||||
prebuilt/man/taler-exchange-benchmark.1 \
|
||||
prebuilt/man/taler-exchange-closer.1 \
|
||||
prebuilt/man/taler-exchange-dbinit.1 \
|
||||
prebuilt/man/taler-exchange-expire.1 \
|
||||
prebuilt/man/taler-exchange-httpd.1 \
|
||||
prebuilt/man/taler-exchange-offline.1 \
|
||||
prebuilt/man/taler-exchange-secmod-cs.1\
|
||||
prebuilt/man/taler-exchange-secmod-eddsa.1\
|
||||
prebuilt/man/taler-exchange-secmod-rsa.1 \
|
||||
prebuilt/man/taler-exchange-router.1\
|
||||
prebuilt/man/taler-exchange-transfer.1\
|
||||
prebuilt/man/taler-exchange-wirewatch.1 \
|
||||
prebuilt/man/taler-exchange-wire-gateway-client.1\
|
||||
|
@ -43,14 +43,14 @@ migliorate per tutelare la privacy nelle transazioni, soddisfare i
|
||||
requisiti normativi in modo efficace e offrire un livello di protezione
|
||||
resistente ai computer quantistici contro il rischio sistemico per
|
||||
la privacy. Né la politica monetaria né la stabilità del sistema
|
||||
finanziario sarebbero realmente interessate da questo sistema dal
|
||||
finanziario sarebbero realmente interessate da questo sistema, dal
|
||||
momento che una moneta emessa in questo modo replicherebbe il contante
|
||||
fisico anziché i depositi bancari. \\
|
||||
|
||||
JEL: E42, E51, E52, E58, G2
|
||||
\\
|
||||
|
||||
Parole chiave: monete digitali, banca centrale, CBDC, firma cieca,
|
||||
Parole chiave: monete digitali, banca centrale, CBDC, firma cieca (\textit{blind signatures}),
|
||||
criptovalute stabili, \textit{stablecoins}
|
||||
\end{abstract}
|
||||
|
||||
@ -91,7 +91,7 @@ CoinMarketCap elenca oltre 5.000 criptovalute. Recentemente le banche
|
||||
centrali hanno iniziato a considerare, o almeno a studiare,
|
||||
l'emissione di monete digitali~\cite[vedi][]{AuerBoehme,AuerCornelli,Boar,Kiff,Mancini-Griffoli}.
|
||||
|
||||
Attualmente le banche centrali emettono due tipi di moneta: (i)
|
||||
Attualmente, le banche centrali emettono due tipi di moneta: (i)
|
||||
riserve sotto forma di conti di regolamento presso le banche centrali,
|
||||
destinate solo agli operatori dei mercati finanziari, e (ii) divisa
|
||||
disponibile per tutti sotto forma di banconote. Di conseguenza, la
|
||||
@ -1088,13 +1088,14 @@ possono supportare milioni di transazioni al secondo.
|
||||
% una discussione a riguardo:
|
||||
% https://italian.stackexchange.com/questions/3653/probabilmente-indicativo-o-congiuntivo
|
||||
% Not incorrect but FIXED anyway.
|
||||
Infine, il costo totale del sistema è basso. Probabilmente il costo
|
||||
principale è rappresentato dall'archiviazione sicura per
|
||||
molti anni di 1–10 kilobyte per transazione. Gli esperimenti su un
|
||||
prototipo di GNU Taler che utilizzava i prezzi di \textit{Amazon Web Service}
|
||||
hanno stabilito che il costo del sistema (archiviazione, larghezza di
|
||||
banda e capacità di calcolo) su larga scala sarebbe inferiore a
|
||||
0,0001 USD per transazione~\cite[per i dettagli sui dati, si veda][]{Dold}.
|
||||
|
||||
Infine, il costo totale del sistema è basso. Il costo principale è
|
||||
rappresentato dall'archiviazione a lungo termine di 1–10 kilobyte
|
||||
per transazione. Gli esperimenti su un prototipo di GNU Taler che
|
||||
utilizzava i prezzi di \textit{Amazon Web Service} hanno stabilito
|
||||
che il costo del sistema (archiviazione, larghezza di banda e capacità
|
||||
di calcolo) su larga scala sarebbe inferiore a 0,0001 USD per
|
||||
transazione~\cite[per i dettagli sui dati, si veda][]{Dold}.
|
||||
|
||||
\section{Considerazioni normative e politiche}
|
||||
\label{5.-considerazioni-normative-e-politiche}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 74d9c44ebc257a3d8b9c2c0a806508bd0cc5269a
|
||||
Subproject commit 1ed97b23f19c80fa84b21a5eb0c686d5491e8ec6
|
2
doc/system/.gitignore
vendored
2
doc/system/.gitignore
vendored
@ -1,5 +1,7 @@
|
||||
thesis.pdf
|
||||
thesis-*.pdf
|
||||
system.pdf
|
||||
system-*.pdf
|
||||
thesis.out
|
||||
summary/summary-english.pdf
|
||||
*-converted-to.pdf
|
||||
|
BIN
doc/system/plots/cpu.pdf
Normal file
BIN
doc/system/plots/cpu.pdf
Normal file
Binary file not shown.
BIN
doc/system/plots/latencies.pdf
Normal file
BIN
doc/system/plots/latencies.pdf
Normal file
Binary file not shown.
7
doc/system/plots/latency-summary-0.data
Normal file
7
doc/system/plots/latency-summary-0.data
Normal file
@ -0,0 +1,7 @@
|
||||
http://192.168.42.1:8081/deposit 22.3593
|
||||
http://192.168.42.1:8081/keys 1.139
|
||||
http://192.168.42.1:8081/reserve/withdraw 22.675
|
||||
http://192.168.42.1:8081/refresh/link 7.12287
|
||||
http://192.168.42.1:8081/refresh/reveal 63.6377
|
||||
http://192.168.42.1:8081/refresh/melt 20.7065
|
||||
http://192.168.42.2:8081/admin/add/incoming 0.501
|
7
doc/system/plots/latency-summary-100.data
Normal file
7
doc/system/plots/latency-summary-100.data
Normal file
@ -0,0 +1,7 @@
|
||||
http://192.168.42.1:8081/deposit 223.217
|
||||
http://192.168.42.1:8081/keys 201.251
|
||||
http://192.168.42.1:8081/reserve/withdraw 222.458
|
||||
http://192.168.42.1:8081/refresh/link 205.331
|
||||
http://192.168.42.1:8081/refresh/reveal 466.303
|
||||
http://192.168.42.1:8081/refresh/melt 223.9
|
||||
http://192.168.42.2:8081/admin/add/incoming 0.485
|
7
doc/system/plots/req-received.data
Normal file
7
doc/system/plots/req-received.data
Normal file
@ -0,0 +1,7 @@
|
||||
http://192.168.42.1:8081/deposit 0.339055
|
||||
http://192.168.42.1:8081/keys 3.748
|
||||
http://192.168.42.1:8081/reserve/withdraw 0.722583
|
||||
http://192.168.42.1:8081/refresh/link 3.15716
|
||||
http://192.168.42.1:8081/refresh/reveal 2.10851
|
||||
http://192.168.42.1:8081/refresh/melt 0.35252
|
||||
http://192.168.42.2:8081/admin/add/incoming 0.177
|
7
doc/system/plots/req-sent.data
Normal file
7
doc/system/plots/req-sent.data
Normal file
@ -0,0 +1,7 @@
|
||||
http://192.168.42.1:8081/deposit 1.36432
|
||||
http://192.168.42.1:8081/keys 0.145
|
||||
http://192.168.42.1:8081/reserve/withdraw 0.711581
|
||||
http://192.168.42.1:8081/refresh/link 0.215
|
||||
http://192.168.42.1:8081/refresh/reveal 1.42
|
||||
http://192.168.42.1:8081/refresh/melt 1.06365
|
||||
http://192.168.42.2:8081/admin/add/incoming 0.386
|
BIN
doc/system/plots/speed.pdf
Normal file
BIN
doc/system/plots/speed.pdf
Normal file
Binary file not shown.
@ -66,7 +66,7 @@
|
||||
|
||||
\usepackage{pdfpages}
|
||||
|
||||
\author{Florian Dold \and the GNU Taler Developers}
|
||||
\author{Florian Dold \and The GNU Taler Developers}
|
||||
\title{The GNU Taler System}
|
||||
|
||||
\begin{document}
|
||||
@ -79,6 +79,7 @@
|
||||
\let\thefootnote=\oldthefootnote%
|
||||
}
|
||||
|
||||
\maketitle
|
||||
\frontmatter
|
||||
\include{abstract}
|
||||
\include{acknowledgements}
|
||||
|
BIN
doc/system/taler-arch-full.pdf
Normal file
BIN
doc/system/taler-arch-full.pdf
Normal file
Binary file not shown.
49
m4/mhd.m4
Normal file
49
m4/mhd.m4
Normal file
@ -0,0 +1,49 @@
|
||||
# mhd.m4
|
||||
|
||||
# This file is part of TALER
|
||||
# Copyright (C) 2022 Taler Systems SA
|
||||
#
|
||||
# TALER is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 3, or (at your option) any later version.
|
||||
#
|
||||
# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/license>
|
||||
|
||||
# serial 1
|
||||
|
||||
dnl MHD_VERSION_AT_LEAST([VERSION])
|
||||
dnl
|
||||
dnl Check that microhttpd.h can be used to build a program that prints out
|
||||
dnl the MHD_VERSION tuple in X.Y.Z format, and that X.Y.Z is greater or equal
|
||||
dnl to VERSION. If not, display message and cause the configure script to
|
||||
dnl exit failurefully.
|
||||
dnl
|
||||
dnl This uses AX_COMPARE_VERSION to do the job.
|
||||
dnl It sets shell var mhd_cv_version, as well.
|
||||
dnl
|
||||
AC_DEFUN([MHD_VERSION_AT_LEAST],
|
||||
[AC_CACHE_CHECK([libmicrohttpd version],[mhd_cv_version],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdio.h>
|
||||
#include <microhttpd.h>
|
||||
]],[[
|
||||
int v = MHD_VERSION;
|
||||
printf ("%x.%x.%x\n",
|
||||
(v >> 24) & 0xff,
|
||||
(v >> 16) & 0xff,
|
||||
(v >> 8) & 0xff);
|
||||
]])],
|
||||
[mhd_cv_version=$(./conftest)],
|
||||
[mhd_cv_version=0])])
|
||||
AX_COMPARE_VERSION([$mhd_cv_version],[ge],[$1],,
|
||||
[AC_MSG_ERROR([[
|
||||
***
|
||||
*** You need libmicrohttpd >= $1 to build this program.
|
||||
*** ]])])])
|
||||
|
||||
# mhd.m4 ends here
|
@ -194,10 +194,7 @@ check_SCRIPTS = \
|
||||
|
||||
.NOTPARALLEL:
|
||||
# revocation test disabled for now: need working wallet first!
|
||||
# TESTS = $(check_SCRIPTS)
|
||||
TESTS = \
|
||||
test-auditor.sh \
|
||||
test-sync.sh
|
||||
TESTS = $(check_SCRIPTS)
|
||||
|
||||
EXTRA_DIST = \
|
||||
taler-auditor.in \
|
||||
|
@ -1 +1 @@
|
||||
1646042841
|
||||
1655640402
|
||||
|
@ -113,7 +113,7 @@ currency = TESTKUDOS
|
||||
[merchant-exchange-default]
|
||||
CURRENCY = TESTKUDOS
|
||||
EXCHANGE_BASE_URL = http://localhost:8081/
|
||||
MASTER_KEY = TMQ09D9G18Z8TFEABD833SDJ6JQWRYKFHPTWT6DMPQS54ZC66RDG
|
||||
MASTER_KEY = JM0NJXHM6Y6HYAPK2WDFH3HDJ2E9KZWGKM3E0FYRV2V3HCTB3DQ0
|
||||
|
||||
[merchant-account-merchant]
|
||||
ACTIVE_default = YES
|
||||
@ -157,7 +157,7 @@ CONFIG = postgres:///auditor-basedb
|
||||
[exchange]
|
||||
LOOKAHEAD_SIGN = 32 weeks 1 day
|
||||
SIGNKEY_DURATION = 4 weeks
|
||||
MASTER_PUBLIC_KEY = TMQ09D9G18Z8TFEABD833SDJ6JQWRYKFHPTWT6DMPQS54ZC66RDG
|
||||
MASTER_PUBLIC_KEY = JM0NJXHM6Y6HYAPK2WDFH3HDJ2E9KZWGKM3E0FYRV2V3HCTB3DQ0
|
||||
SIGNKEY_LEGAL_DURATION = 4 weeks
|
||||
UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http
|
||||
|
||||
@ -169,13 +169,13 @@ SUGGESTED_EXCHANGE = http://localhost:8081/
|
||||
HTTP_PORT = 8082
|
||||
MAX_DEBT_BANK = TESTKUDOS:100000.0
|
||||
MAX_DEBT = TESTKUDOS:50.0
|
||||
DATABASE = postgres:///taler-auditor-basedb
|
||||
DATABASE = postgres:///auditor-basedb
|
||||
|
||||
[auditordb-postgres]
|
||||
CONFIG = postgres:///taler-auditor-basedb
|
||||
CONFIG = postgres:///auditor-basedb
|
||||
|
||||
[auditor]
|
||||
PUBLIC_KEY = 95FVPHMW4110HTPVSGMT2YMDE2BSGXZEV5WSV0TD1DXMF2RQ5HN0
|
||||
PUBLIC_KEY = 73NJKBP4MHJF8274K88F4WFWKNYMK8T6MTSE6HHYS6WC01H9YH7G
|
||||
TINY_AMOUNT = TESTKUDOS:0.01
|
||||
BASE_URL = http://localhost:8083/
|
||||
|
||||
@ -184,3 +184,4 @@ TALER_CACHE_HOME = $TALER_HOME/.cache/taler/
|
||||
TALER_CONFIG_HOME = $TALER_HOME/.config/taler/
|
||||
TALER_DATA_HOME = $TALER_HOME/.local/share/taler/
|
||||
TALER_HOME = ${PWD}/generate_auditordb_home/
|
||||
|
||||
|
@ -1 +1 @@
|
||||
TMQ09D9G18Z8TFEABD833SDJ6JQWRYKFHPTWT6DMPQS54ZC66RDG
|
||||
JM0NJXHM6Y6HYAPK2WDFH3HDJ2E9KZWGKM3E0FYRV2V3HCTB3DQ0
|
||||
|
File diff suppressed because it is too large
Load Diff
186
src/auditor/batch.conf
Normal file
186
src/auditor/batch.conf
Normal file
@ -0,0 +1,186 @@
|
||||
[arm]
|
||||
CONFIG = /research/taler/exchange/src/auditor/batch.conf
|
||||
|
||||
[benchmark]
|
||||
MERCHANT_DETAILS = merchant_details.json
|
||||
BANK_DETAILS = bank_details.json
|
||||
|
||||
[coin_kudos_10]
|
||||
rsa_keysize = 1024
|
||||
CIPHER = RSA
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_withdraw = TESTKUDOS:0.01
|
||||
duration_legal = 3 years
|
||||
duration_spend = 2 years
|
||||
duration_withdraw = 7 days
|
||||
value = TESTKUDOS:10
|
||||
|
||||
[coin_kudos_8]
|
||||
rsa_keysize = 1024
|
||||
CIPHER = RSA
|
||||
fee_refund = TESTKUDOS:0.04
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_deposit = TESTKUDOS:0.02
|
||||
fee_withdraw = TESTKUDOS:0.05
|
||||
duration_legal = 3 years
|
||||
duration_spend = 2 years
|
||||
duration_withdraw = 7 days
|
||||
value = TESTKUDOS:8
|
||||
|
||||
[coin_kudos_5]
|
||||
rsa_keysize = 1024
|
||||
CIPHER = RSA
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_withdraw = TESTKUDOS:0.01
|
||||
duration_legal = 3 years
|
||||
duration_spend = 2 years
|
||||
duration_withdraw = 7 days
|
||||
value = TESTKUDOS:5
|
||||
|
||||
[coin_kudos_4]
|
||||
rsa_keysize = 1024
|
||||
CIPHER = RSA
|
||||
fee_refund = TESTKUDOS:0.02
|
||||
fee_refresh = TESTKUDOS:0.04
|
||||
fee_deposit = TESTKUDOS:0.03
|
||||
fee_withdraw = TESTKUDOS:0.03
|
||||
duration_legal = 3 years
|
||||
duration_spend = 2 years
|
||||
duration_withdraw = 7 days
|
||||
value = TESTKUDOS:4
|
||||
|
||||
[coin_kudos_2]
|
||||
rsa_keysize = 1024
|
||||
CIPHER = RSA
|
||||
fee_refund = TESTKUDOS:0.02
|
||||
fee_refresh = TESTKUDOS:0.04
|
||||
fee_deposit = TESTKUDOS:0.03
|
||||
fee_withdraw = TESTKUDOS:0.03
|
||||
duration_legal = 3 years
|
||||
duration_spend = 2 years
|
||||
duration_withdraw = 7 days
|
||||
value = TESTKUDOS:2
|
||||
|
||||
[coin_kudos_1]
|
||||
rsa_keysize = 1024
|
||||
CIPHER = RSA
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_deposit = TESTKUDOS:0.02
|
||||
fee_withdraw = TESTKUDOS:0.02
|
||||
duration_legal = 3 years
|
||||
duration_spend = 2 years
|
||||
duration_withdraw = 7 days
|
||||
value = TESTKUDOS:1
|
||||
|
||||
[coin_kudos_ct_10]
|
||||
rsa_keysize = 1024
|
||||
CIPHER = RSA
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.03
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_withdraw = TESTKUDOS:0.01
|
||||
duration_legal = 3 years
|
||||
duration_spend = 2 years
|
||||
duration_withdraw = 7 days
|
||||
value = TESTKUDOS:0.10
|
||||
|
||||
[coin_kudos_ct_1]
|
||||
rsa_keysize = 1024
|
||||
CIPHER = RSA
|
||||
fee_refund = TESTKUDOS:0.01
|
||||
fee_refresh = TESTKUDOS:0.01
|
||||
fee_deposit = TESTKUDOS:0.01
|
||||
fee_withdraw = TESTKUDOS:0.01
|
||||
duration_legal = 3 years
|
||||
duration_spend = 2 years
|
||||
duration_withdraw = 7 days
|
||||
value = TESTKUDOS:0.01
|
||||
|
||||
[payments-generator]
|
||||
exchange = http://localhost:8081/
|
||||
exchange-admin = http://localhost:18080/
|
||||
exchange_admin = http://localhost:18080/
|
||||
merchant = http://localhost:9966/
|
||||
bank = http://localhost:8082/
|
||||
instance = default
|
||||
currency = TESTKUDOS
|
||||
|
||||
[merchant-exchange-default]
|
||||
CURRENCY = TESTKUDOS
|
||||
EXCHANGE_BASE_URL = http://localhost:8081/
|
||||
MASTER_KEY = 2XPQZ7B7EERWT7GR0MF30HPFG4TA1J0CWCQ3XBD48PA4K7GVDBK0
|
||||
|
||||
[merchant-account-merchant]
|
||||
ACTIVE_default = YES
|
||||
HONOR_default = YES
|
||||
PAYTO_URI = payto://x-taler-bank/localhost/42
|
||||
|
||||
[exchange-accountcredentials-1]
|
||||
PASSWORD = x
|
||||
USERNAME = Exchange
|
||||
WIRE_GATEWAY_AUTH_METHOD = basic
|
||||
WIRE_GATEWAY_URL = http://localhost:8082/taler-wire-gateway/Exchange/
|
||||
|
||||
[exchange-account-1]
|
||||
enable_credit = yes
|
||||
enable_debit = yes
|
||||
PAYTO_URI = payto://x-taler-bank/localhost/Exchange
|
||||
|
||||
[instance-default]
|
||||
NAME = Merchant Inc.
|
||||
KEYFILE = ${TALER_DATA_HOME}/merchant/default.priv
|
||||
|
||||
[taler]
|
||||
CURRENCY_ROUND_UNIT = TESTKUDOS:0.01
|
||||
CURRENCY = TESTKUDOS
|
||||
|
||||
[merchantdb-postgres]
|
||||
CONFIG = postgres:///batch
|
||||
|
||||
[merchant]
|
||||
DEFAULT_MAX_WIRE_FEE = TESTKUDOS:0.10
|
||||
KEYFILE = ${TALER_DATA_HOME}/merchant/merchant.priv
|
||||
DEFAULT_MAX_DEPOSIT_FEE = TESTKUDOS:0.1
|
||||
WIREFORMAT = default
|
||||
WIRE_TRANSFER_DELAY = 1 minute
|
||||
FORCE_AUDIT = YES
|
||||
UNIXPATH = ${TALER_RUNTIME_DIR}/merchant.http
|
||||
|
||||
[exchangedb-postgres]
|
||||
CONFIG = postgres:///batch
|
||||
|
||||
[exchange]
|
||||
LOOKAHEAD_SIGN = 32 weeks 1 day
|
||||
SIGNKEY_DURATION = 4 weeks
|
||||
MASTER_PUBLIC_KEY = 2XPQZ7B7EERWT7GR0MF30HPFG4TA1J0CWCQ3XBD48PA4K7GVDBK0
|
||||
SIGNKEY_LEGAL_DURATION = 4 weeks
|
||||
UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http
|
||||
|
||||
[bank]
|
||||
SERVE = http
|
||||
ALLOW_REGISTRATIONS = YES
|
||||
SUGGESTED_EXCHANGE_PAYTO = payto://x-taler-bank/localhost:8082/2
|
||||
SUGGESTED_EXCHANGE = http://localhost:8081/
|
||||
HTTP_PORT = 8082
|
||||
MAX_DEBT_BANK = TESTKUDOS:100000.0
|
||||
MAX_DEBT = TESTKUDOS:50.0
|
||||
DATABASE = postgres:///batch
|
||||
|
||||
[auditordb-postgres]
|
||||
CONFIG = postgres:///batch
|
||||
|
||||
[auditor]
|
||||
PUBLIC_KEY = JG9QFRG7R7BH9701420BD6M38NZW21MV9AR3QHYJEAHZ4S26B3HG
|
||||
TINY_AMOUNT = TESTKUDOS:0.01
|
||||
BASE_URL = http://localhost:8083/
|
||||
|
||||
[PATHS]
|
||||
TALER_CACHE_HOME = $TALER_HOME/.cache/taler/
|
||||
TALER_CONFIG_HOME = $TALER_HOME/.config/taler/
|
||||
TALER_DATA_HOME = $TALER_HOME/.local/share/taler/
|
||||
TALER_HOME = ${PWD}/generate_auditordb_home/
|
235
src/auditor/batch.sh
Executable file
235
src/auditor/batch.sh
Executable file
@ -0,0 +1,235 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
# Cleanup to run whenever we exit
|
||||
function cleanup()
|
||||
{
|
||||
for n in `jobs -p`
|
||||
do
|
||||
kill $n 2> /dev/null || true
|
||||
done
|
||||
wait
|
||||
}
|
||||
|
||||
# Install cleanup handler (except for kill -9)
|
||||
trap cleanup EXIT
|
||||
|
||||
|
||||
# Exit, with status code "skip" (no 'real' failure)
|
||||
function exit_skip() {
|
||||
echo $1
|
||||
exit 77
|
||||
}
|
||||
|
||||
# Where do we write the result?
|
||||
BASEDB=${1:-"batch"}
|
||||
|
||||
# Name of the Postgres database we will use for the script.
|
||||
# Will be dropped, do NOT use anything that might be used
|
||||
# elsewhere
|
||||
export TARGET_DB=`basename ${BASEDB}`
|
||||
|
||||
export WALLET_DB=${BASEDB:-"wallet"}.wdb
|
||||
|
||||
# delete existing wallet database
|
||||
rm -f $WALLET_DB
|
||||
|
||||
|
||||
# Configuration file will be edited, so we create one
|
||||
# from the template.
|
||||
CONF=${BASEDB}.conf
|
||||
cp generate-auditor-basedb.conf $CONF
|
||||
|
||||
|
||||
echo -n "Testing for taler-fakebank-run"
|
||||
taler-fakebank-run -h >/dev/null </dev/null || exit_skip " MISSING"
|
||||
echo " FOUND"
|
||||
echo -n "Testing for taler-wallet-cli"
|
||||
taler-wallet-cli -v >/dev/null </dev/null || exit_skip " MISSING"
|
||||
echo " FOUND"
|
||||
echo -n "Testing for curl"
|
||||
curl --help >/dev/null </dev/null || exit_skip " MISSING"
|
||||
echo " FOUND"
|
||||
|
||||
|
||||
pwd
|
||||
# Clean up
|
||||
|
||||
DATA_DIR=`taler-config -f -c $CONF -s PATHS -o TALER_HOME`
|
||||
rm -rf $DATA_DIR || true
|
||||
|
||||
# reset database
|
||||
dropdb $TARGET_DB >/dev/null 2>/dev/null || true
|
||||
createdb $TARGET_DB || exit_skip "Could not create database $TARGET_DB"
|
||||
|
||||
|
||||
# obtain key configuration data
|
||||
MASTER_PRIV_FILE=`taler-config -f -c $CONF -s exchange-offline -o MASTER_PRIV_FILE`
|
||||
MASTER_PRIV_DIR=`dirname $MASTER_PRIV_FILE`
|
||||
mkdir -p $MASTER_PRIV_DIR
|
||||
gnunet-ecc -g1 $MASTER_PRIV_FILE > /dev/null
|
||||
MASTER_PUB=`gnunet-ecc -p $MASTER_PRIV_FILE`
|
||||
EXCHANGE_URL=`taler-config -c $CONF -s EXCHANGE -o BASE_URL`
|
||||
MERCHANT_PORT=`taler-config -c $CONF -s MERCHANT -o PORT`
|
||||
MERCHANT_URL=http://localhost:${MERCHANT_PORT}/
|
||||
BANK_PORT=`taler-config -c $CONF -s BANK -o HTTP_PORT`
|
||||
BANK_URL=http://localhost:${BANK_PORT}/
|
||||
AUDITOR_URL=http://localhost:8083/
|
||||
AUDITOR_PRIV_FILE=`taler-config -f -c $CONF -s AUDITOR -o AUDITOR_PRIV_FILE`
|
||||
AUDITOR_PRIV_DIR=`dirname $AUDITOR_PRIV_FILE`
|
||||
mkdir -p $AUDITOR_PRIV_DIR
|
||||
gnunet-ecc -g1 $AUDITOR_PRIV_FILE > /dev/null
|
||||
AUDITOR_PUB=`gnunet-ecc -p $AUDITOR_PRIV_FILE`
|
||||
|
||||
echo "AUDITOR PUB is $AUDITOR_PUB using file $AUDITOR_PRIV_FILE"
|
||||
|
||||
# patch configuration
|
||||
taler-config -c $CONF -s exchange -o MASTER_PUBLIC_KEY -V $MASTER_PUB
|
||||
taler-config -c $CONF -s auditor -o PUBLIC_KEY -V $AUDITOR_PUB
|
||||
taler-config -c $CONF -s merchant-exchange-default -o MASTER_KEY -V $MASTER_PUB
|
||||
taler-config -c $CONF -s exchangedb-postgres -o CONFIG -V postgres:///$TARGET_DB
|
||||
taler-config -c $CONF -s auditordb-postgres -o CONFIG -V postgres:///$TARGET_DB
|
||||
taler-config -c $CONF -s merchantdb-postgres -o CONFIG -V postgres:///$TARGET_DB
|
||||
taler-config -c $CONF -s bank -o database -V postgres:///$TARGET_DB
|
||||
|
||||
# setup exchange
|
||||
echo "Setting up exchange"
|
||||
taler-exchange-dbinit -c $CONF
|
||||
|
||||
echo "Setting up merchant"
|
||||
taler-merchant-dbinit -c $CONF
|
||||
|
||||
# setup auditor
|
||||
echo "Setting up auditor"
|
||||
taler-auditor-dbinit -c $CONF || exit_skip "Failed to initialize auditor DB"
|
||||
taler-auditor-exchange -c $CONF -m $MASTER_PUB -u $EXCHANGE_URL || exit_skip "Failed to add exchange to auditor"
|
||||
|
||||
# Launch services
|
||||
echo "Launching services"
|
||||
taler-fakebank-run -c $CONF &> taler-bank.log &
|
||||
TFN=`which taler-exchange-httpd`
|
||||
TBINPFX=`dirname $TFN`
|
||||
TLIBEXEC=${TBINPFX}/../lib/taler/libexec/
|
||||
taler-exchange-secmod-eddsa -c $CONF 2> taler-exchange-secmod-eddsa.log &
|
||||
taler-exchange-secmod-rsa -c $CONF 2> taler-exchange-secmod-rsa.log &
|
||||
taler-exchange-secmod-cs -c $CONF 2> taler-exchange-secmod-cs.log &
|
||||
taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log &
|
||||
taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log &
|
||||
taler-exchange-wirewatch -c $CONF 2> taler-exchange-wirewatch.log &
|
||||
taler-auditor-httpd -L INFO -c $CONF 2> taler-auditor-httpd.log &
|
||||
|
||||
# Wait for all bank to be available (usually the slowest)
|
||||
for n in `seq 1 50`
|
||||
do
|
||||
echo -n "."
|
||||
sleep 0.2
|
||||
OK=0
|
||||
# bank
|
||||
wget http://localhost:8082/ -o /dev/null -O /dev/null >/dev/null || continue
|
||||
OK=1
|
||||
break
|
||||
done
|
||||
|
||||
if [ 1 != $OK ]
|
||||
then
|
||||
exit_skip "Failed to launch services"
|
||||
fi
|
||||
|
||||
# Wait for all services to be available
|
||||
for n in `seq 1 50`
|
||||
do
|
||||
echo -n "."
|
||||
sleep 0.1
|
||||
OK=0
|
||||
# exchange
|
||||
wget http://localhost:8081/seed -o /dev/null -O /dev/null >/dev/null || continue
|
||||
# merchant
|
||||
wget http://localhost:9966/ -o /dev/null -O /dev/null >/dev/null || continue
|
||||
# Auditor
|
||||
wget http://localhost:8083/ -o /dev/null -O /dev/null >/dev/null || continue
|
||||
OK=1
|
||||
break
|
||||
done
|
||||
|
||||
if [ 1 != $OK ]
|
||||
then
|
||||
exit_skip "Failed to launch services"
|
||||
fi
|
||||
echo " DONE"
|
||||
|
||||
echo -n "Setting up keys"
|
||||
taler-exchange-offline -c $CONF \
|
||||
download sign \
|
||||
enable-account payto://x-taler-bank/localhost/Exchange \
|
||||
enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \
|
||||
wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 \
|
||||
global-fee now TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 1h 1h 1year 5 \
|
||||
upload &> taler-exchange-offline.log
|
||||
|
||||
echo -n "."
|
||||
|
||||
for n in `seq 1 2`
|
||||
do
|
||||
echo -n "."
|
||||
OK=0
|
||||
wget --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue
|
||||
OK=1
|
||||
break
|
||||
done
|
||||
|
||||
if [ 1 != $OK ]
|
||||
then
|
||||
exit_skip "Failed to setup keys"
|
||||
fi
|
||||
|
||||
echo " DONE"
|
||||
echo -n "Adding auditor signatures ..."
|
||||
|
||||
taler-auditor-offline -c $CONF \
|
||||
download sign upload &> taler-auditor-offline.log
|
||||
|
||||
echo " DONE"
|
||||
# Setup merchant
|
||||
|
||||
echo -n "Setting up merchant"
|
||||
|
||||
curl -H "Content-Type: application/json" -X POST -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_ms" : 3600000},"default_pay_delay":{"d_ms": 3600000}}' http://localhost:9966/management/instances
|
||||
|
||||
|
||||
echo " DONE"
|
||||
|
||||
# run wallet CLI
|
||||
echo "Ready to run wallet"
|
||||
export WALLET_DB
|
||||
export EXCHANGE_URL
|
||||
export MERCHANT_URL
|
||||
export BANK_URL
|
||||
unset TALER_WALLET_INSECURE_TRUST_EXCHANGE
|
||||
export TALER_WALLET_BATCH_WITHDRAWAL=1
|
||||
echo 'taler-wallet-cli --wallet-db=$WALLET_DB -L TRACE advanced bench1 --config-json "{ \"exchange\": \"$EXCHANGE_URL\", \"bank\": \"${BANK_URL}\", \"currency\": \"TESTKUDOS\", \"payto\": \"payto://x-taler-bank/localhost/foo\", \"iterations\": 100000, \"deposits\": 10, \"restartAfter\": 2 }"'
|
||||
bash
|
||||
|
||||
#taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api 'runIntegrationTest' \
|
||||
# "$(jq -n '
|
||||
# {
|
||||
# amountToSpend: "TESTKUDOS:4",
|
||||
# amountToWithdraw: "TESTKUDOS:10",
|
||||
# bankBaseUrl: $BANK_URL,
|
||||
# exchangeBaseUrl: $EXCHANGE_URL,
|
||||
# merchantBaseUrl: $MERCHANT_URL,
|
||||
# }' \
|
||||
# --arg MERCHANT_URL "$MERCHANT_URL" \
|
||||
# --arg EXCHANGE_URL "$EXCHANGE_URL" \
|
||||
# --arg BANK_URL "$BANK_URL"
|
||||
# )" &> taler-wallet-cli.log
|
||||
|
||||
|
||||
echo "Shutting down services"
|
||||
cleanup
|
||||
|
||||
# clean up
|
||||
echo "Final clean up"
|
||||
dropdb $TARGET_DB
|
||||
|
||||
rm -rf $DATA_DIR || true
|
||||
exit 0
|
@ -41,7 +41,7 @@ BASEDB=${1:-"auditor-basedb"}
|
||||
# Name of the Postgres database we will use for the script.
|
||||
# Will be dropped, do NOT use anything that might be used
|
||||
# elsewhere
|
||||
export TARGET_DB=${BASEDB}
|
||||
export TARGET_DB=`basename ${BASEDB}`
|
||||
|
||||
export WALLET_DB=${BASEDB:-"wallet"}.wdb
|
||||
|
||||
@ -52,7 +52,7 @@ rm -f $WALLET_DB
|
||||
# Configuration file will be edited, so we create one
|
||||
# from the template.
|
||||
CONF=${BASEDB}.conf
|
||||
cp generate-auditor-basedb-template.conf $CONF
|
||||
cp generate-auditor-basedb.conf $CONF
|
||||
|
||||
|
||||
echo -n "Testing for taler-bank-manage"
|
||||
@ -61,9 +61,12 @@ echo " FOUND"
|
||||
echo -n "Testing for taler-wallet-cli"
|
||||
taler-wallet-cli -v >/dev/null </dev/null || exit_skip " MISSING"
|
||||
echo " FOUND"
|
||||
echo -n "Testing for curl"
|
||||
curl --help >/dev/null </dev/null || exit_skip " MISSING"
|
||||
echo " FOUND"
|
||||
|
||||
|
||||
|
||||
pwd
|
||||
# Clean up
|
||||
|
||||
DATA_DIR=`taler-config -f -c $CONF -s PATHS -o TALER_HOME`
|
||||
@ -173,7 +176,8 @@ taler-exchange-offline -c $CONF \
|
||||
download sign \
|
||||
enable-account payto://x-taler-bank/localhost/Exchange \
|
||||
enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \
|
||||
wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 \
|
||||
wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 \
|
||||
global-fee now TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 1h 1h 1year 5 \
|
||||
upload &> taler-exchange-offline.log
|
||||
|
||||
echo -n "."
|
||||
@ -182,7 +186,6 @@ for n in `seq 1 2`
|
||||
do
|
||||
echo -n "."
|
||||
OK=0
|
||||
# bank
|
||||
wget --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue
|
||||
OK=1
|
||||
break
|
||||
@ -193,6 +196,9 @@ then
|
||||
exit_skip "Failed to setup keys"
|
||||
fi
|
||||
|
||||
echo " DONE"
|
||||
echo -n "Adding auditor signatures ..."
|
||||
|
||||
taler-auditor-offline -c $CONF \
|
||||
download sign upload &> taler-auditor-offline.log
|
||||
|
||||
|
@ -32,7 +32,7 @@ export BASEDB=${1:-"revoke-basedb"}
|
||||
# Name of the Postgres database we will use for the script.
|
||||
# Will be dropped, do NOT use anything that might be used
|
||||
# elsewhere
|
||||
export TARGET_DB=${BASEDB}
|
||||
export TARGET_DB=`basename ${BASEDB}`
|
||||
TMP_DIR=`mktemp -d revocation-tmp-XXXXXX`
|
||||
export WALLET_DB=wallet-revocation.json
|
||||
rm -f $WALLET_DB
|
||||
@ -40,7 +40,7 @@ rm -f $WALLET_DB
|
||||
# Configuration file will be edited, so we create one
|
||||
# from the template.
|
||||
export CONF=generate-auditor-basedb-revocation.conf
|
||||
cp generate-auditor-basedb-template.conf $CONF
|
||||
cp generate-auditor-basedb.conf $CONF
|
||||
|
||||
|
||||
echo -n "Testing for taler-bank-manage"
|
||||
@ -49,6 +49,9 @@ echo " FOUND"
|
||||
echo -n "Testing for taler-wallet-cli"
|
||||
taler-wallet-cli -v >/dev/null </dev/null || exit_skip " MISSING"
|
||||
echo " FOUND"
|
||||
echo -n "Testing for curl"
|
||||
curl --help >/dev/null </dev/null || exit_skip " MISSING"
|
||||
echo " FOUND"
|
||||
|
||||
|
||||
|
||||
@ -133,7 +136,7 @@ done
|
||||
|
||||
if [ 1 != $OK ]
|
||||
then
|
||||
exit_skip "Failed to launch services"
|
||||
exit_skip "Failed to launch Bank services"
|
||||
fi
|
||||
|
||||
# Wait for all other services to be available
|
||||
@ -155,7 +158,7 @@ done
|
||||
if [ 1 != $OK ]
|
||||
then
|
||||
cleanup
|
||||
exit_skip "Failed to launch services"
|
||||
exit_skip "Failed to launch Taler services"
|
||||
fi
|
||||
echo " DONE"
|
||||
|
||||
@ -165,7 +168,8 @@ taler-exchange-offline -c $CONF \
|
||||
download sign \
|
||||
enable-account payto://x-taler-bank/localhost/Exchange \
|
||||
enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \
|
||||
wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 \
|
||||
wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 \
|
||||
global-fee now TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 TESTKUDOS:0.01 1h 1h 1year 5 \
|
||||
upload &> taler-exchange-offline.log
|
||||
|
||||
echo -n "."
|
||||
|
@ -61,6 +61,11 @@ struct TALER_AuditorPublicKeyP TALER_ARL_auditor_pub;
|
||||
*/
|
||||
char *TALER_ARL_auditor_url;
|
||||
|
||||
/**
|
||||
* REST API endpoint of the exchange.
|
||||
*/
|
||||
char *TALER_ARL_exchange_url;
|
||||
|
||||
/**
|
||||
* At what time did the auditor process start?
|
||||
*/
|
||||
@ -68,7 +73,7 @@ struct GNUNET_TIME_Absolute start_time;
|
||||
|
||||
/**
|
||||
* Results about denominations, cached per-transaction, maps denomination pub hashes
|
||||
* to `struct TALER_DenominationKeyValidityPS`.
|
||||
* to `const struct TALER_EXCHANGEDB_DenominationKeyInformation`.
|
||||
*/
|
||||
static struct GNUNET_CONTAINER_MultiHashMap *denominations;
|
||||
|
||||
@ -114,16 +119,14 @@ TALER_ARL_report (json_t *array,
|
||||
*
|
||||
* @param cls closure, NULL
|
||||
* @param denom_pub public key, sometimes NULL (!)
|
||||
* @param validity issuing information with value, fees and other info about the denomination.
|
||||
* @param issue issuing information with value, fees and other info about the denomination.
|
||||
*/
|
||||
static void
|
||||
add_denomination (
|
||||
void *cls,
|
||||
const struct TALER_DenominationPublicKey *denom_pub,
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformationP *validity)
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue)
|
||||
{
|
||||
const struct TALER_DenominationKeyValidityPS *issue = &validity->properties;
|
||||
|
||||
(void) cls;
|
||||
(void) denom_pub;
|
||||
if (NULL !=
|
||||
@ -132,35 +135,26 @@ add_denomination (
|
||||
return; /* value already known */
|
||||
#if GNUNET_EXTRA_LOGGING >= 1
|
||||
{
|
||||
struct TALER_Amount value;
|
||||
|
||||
TALER_amount_ntoh (&value,
|
||||
&issue->value);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Tracking denomination `%s' (%s)\n",
|
||||
GNUNET_h2s (&issue->denom_hash.hash),
|
||||
TALER_amount2s (&value));
|
||||
TALER_amount_ntoh (&value,
|
||||
&issue->fees.withdraw);
|
||||
TALER_amount2s (&issue->value));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Withdraw fee is %s\n",
|
||||
TALER_amount2s (&value));
|
||||
TALER_amount2s (&issue->fees.withdraw));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Start time is %s\n",
|
||||
GNUNET_TIME_timestamp2s
|
||||
(GNUNET_TIME_timestamp_ntoh (issue->start)));
|
||||
GNUNET_TIME_timestamp2s (issue->start));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Expire deposit time is %s\n",
|
||||
GNUNET_TIME_timestamp2s
|
||||
(GNUNET_TIME_timestamp_ntoh (issue->expire_deposit)));
|
||||
GNUNET_TIME_timestamp2s (issue->expire_deposit));
|
||||
}
|
||||
#endif
|
||||
{
|
||||
struct TALER_DenominationKeyValidityPS *i;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
|
||||
|
||||
i = GNUNET_new (struct TALER_DenominationKeyValidityPS);
|
||||
i = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyInformation);
|
||||
*i = *issue;
|
||||
i->master = TALER_ARL_master_pub;
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_CONTAINER_multihashmap_put (denominations,
|
||||
&issue->denom_hash.hash,
|
||||
@ -173,7 +167,7 @@ add_denomination (
|
||||
enum GNUNET_DB_QueryStatus
|
||||
TALER_ARL_get_denomination_info_by_hash (
|
||||
const struct TALER_DenominationHashP *dh,
|
||||
const struct TALER_DenominationKeyValidityPS **issue)
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation **issue)
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
@ -192,7 +186,7 @@ TALER_ARL_get_denomination_info_by_hash (
|
||||
}
|
||||
}
|
||||
{
|
||||
const struct TALER_DenominationKeyValidityPS *i;
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
|
||||
|
||||
i = GNUNET_CONTAINER_multihashmap_get (denominations,
|
||||
&dh->hash);
|
||||
@ -205,7 +199,7 @@ TALER_ARL_get_denomination_info_by_hash (
|
||||
}
|
||||
/* maybe database changed since we last iterated, give it one more shot */
|
||||
{
|
||||
struct TALER_EXCHANGEDB_DenominationKeyInformationP issue;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
|
||||
|
||||
qs = TALER_ARL_edb->get_denomination_info (TALER_ARL_edb->cls,
|
||||
dh,
|
||||
@ -224,7 +218,7 @@ TALER_ARL_get_denomination_info_by_hash (
|
||||
&issue);
|
||||
}
|
||||
{
|
||||
const struct TALER_DenominationKeyValidityPS *i;
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation *i;
|
||||
|
||||
i = GNUNET_CONTAINER_multihashmap_get (denominations,
|
||||
&dh->hash);
|
||||
@ -246,7 +240,7 @@ TALER_ARL_get_denomination_info_by_hash (
|
||||
enum GNUNET_DB_QueryStatus
|
||||
TALER_ARL_get_denomination_info (
|
||||
const struct TALER_DenominationPublicKey *denom_pub,
|
||||
const struct TALER_DenominationKeyValidityPS **issue,
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation **issue,
|
||||
struct TALER_DenominationHashP *dh)
|
||||
{
|
||||
struct TALER_DenominationHashP hc;
|
||||
@ -382,10 +376,13 @@ test_master_present (void *cls,
|
||||
{
|
||||
int *found = cls;
|
||||
|
||||
(void) exchange_url;
|
||||
if (0 == GNUNET_memcmp (mpub,
|
||||
&TALER_ARL_master_pub))
|
||||
{
|
||||
*found = GNUNET_YES;
|
||||
GNUNET_free (TALER_ARL_exchange_url);
|
||||
TALER_ARL_exchange_url = GNUNET_strdup (exchange_url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -776,6 +773,7 @@ TALER_ARL_done (json_t *report)
|
||||
JSON_INDENT (2));
|
||||
json_decref (report);
|
||||
}
|
||||
GNUNET_free (TALER_ARL_exchange_url);
|
||||
GNUNET_free (TALER_ARL_auditor_url);
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,11 @@ extern struct TALER_AuditorPublicKeyP TALER_ARL_auditor_pub;
|
||||
*/
|
||||
extern char *TALER_ARL_auditor_url;
|
||||
|
||||
/**
|
||||
* REST API endpoint of the exchange.
|
||||
*/
|
||||
extern char *TALER_ARL_exchange_url;
|
||||
|
||||
/**
|
||||
* At what time did the auditor process start?
|
||||
*/
|
||||
@ -102,7 +107,7 @@ TALER_ARL_report (json_t *array,
|
||||
enum GNUNET_DB_QueryStatus
|
||||
TALER_ARL_get_denomination_info_by_hash (
|
||||
const struct TALER_DenominationHashP *dh,
|
||||
const struct TALER_DenominationKeyValidityPS **issue);
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation **issue);
|
||||
|
||||
|
||||
/**
|
||||
@ -117,7 +122,7 @@ TALER_ARL_get_denomination_info_by_hash (
|
||||
enum GNUNET_DB_QueryStatus
|
||||
TALER_ARL_get_denomination_info (
|
||||
const struct TALER_DenominationPublicKey *denom_pub,
|
||||
const struct TALER_DenominationKeyValidityPS **issue,
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation **issue,
|
||||
struct TALER_DenominationHashP *dh);
|
||||
|
||||
|
||||
|
@ -1 +1 @@
|
||||
1638367019
|
||||
1655640625
|
||||
|
@ -1 +1 @@
|
||||
93PR4M9WR54W046A4DWR58V28T2G94DJCWHY0NMBW2S8N6W60AT0
|
||||
MREDG0XYVSX4RPYSA6JNQZ93P2DDBG45F3M6RBZXRS49M0JTVN40
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,6 +32,50 @@
|
||||
#include "taler-auditor-httpd_deposit-confirmation.h"
|
||||
|
||||
|
||||
GNUNET_NETWORK_STRUCT_BEGIN
|
||||
|
||||
/**
|
||||
* @brief Information about a signing key of the exchange. Signing keys are used
|
||||
* to sign exchange messages other than coins, i.e. to confirm that a
|
||||
* deposit was successful or that a refresh was accepted.
|
||||
*/
|
||||
struct ExchangeSigningKeyDataP
|
||||
{
|
||||
|
||||
/**
|
||||
* When does this signing key begin to be valid?
|
||||
*/
|
||||
struct GNUNET_TIME_TimestampNBO start;
|
||||
|
||||
/**
|
||||
* When does this signing key expire? Note: This is currently when
|
||||
* the Exchange will definitively stop using it. Signatures made with
|
||||
* the key remain valid until @e end. When checking validity periods,
|
||||
* clients should allow for some overlap between keys and tolerate
|
||||
* the use of either key during the overlap time (due to the
|
||||
* possibility of clock skew).
|
||||
*/
|
||||
struct GNUNET_TIME_TimestampNBO expire;
|
||||
|
||||
/**
|
||||
* When do signatures with this signing key become invalid? After
|
||||
* this point, these signatures cannot be used in (legal) disputes
|
||||
* anymore, as the Exchange is then allowed to destroy its side of the
|
||||
* evidence. @e end is expected to be significantly larger than @e
|
||||
* expire (by a year or more).
|
||||
*/
|
||||
struct GNUNET_TIME_TimestampNBO end;
|
||||
|
||||
/**
|
||||
* The public online signing key that the exchange will use
|
||||
* between @e start and @e expire.
|
||||
*/
|
||||
struct TALER_ExchangePublicKeyP signkey_pub;
|
||||
};
|
||||
|
||||
GNUNET_NETWORK_STRUCT_END
|
||||
|
||||
|
||||
/**
|
||||
* Cache of already verified exchange signing keys. Maps the hash of the
|
||||
* `struct TALER_ExchangeSigningKeyValidityPS` to the (static) string
|
||||
@ -65,9 +109,7 @@ verify_and_execute_deposit_confirmation (
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct GNUNET_HashCode h;
|
||||
const char *cached;
|
||||
struct TALER_ExchangeSigningKeyValidityPS skv = {
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY),
|
||||
.purpose.size = htonl (sizeof (struct TALER_ExchangeSigningKeyValidityPS)),
|
||||
struct ExchangeSigningKeyDataP skv = {
|
||||
.start = GNUNET_TIME_timestamp_hton (es->ep_start),
|
||||
.expire = GNUNET_TIME_timestamp_hton (es->ep_expire),
|
||||
.end = GNUNET_TIME_timestamp_hton (es->ep_end),
|
||||
@ -182,17 +224,18 @@ verify_and_execute_deposit_confirmation (
|
||||
|
||||
/* check deposit confirmation signature */
|
||||
if (GNUNET_OK !=
|
||||
TALER_exchange_deposit_confirm_verify (&dc->h_contract_terms,
|
||||
&dc->h_wire,
|
||||
NULL /* h_extensions! */,
|
||||
dc->exchange_timestamp,
|
||||
dc->wire_deadline,
|
||||
dc->refund_deadline,
|
||||
&dc->amount_without_fee,
|
||||
&dc->coin_pub,
|
||||
&dc->merchant,
|
||||
&dc->exchange_pub,
|
||||
&dc->exchange_sig))
|
||||
TALER_exchange_online_deposit_confirmation_verify (
|
||||
&dc->h_contract_terms,
|
||||
&dc->h_wire,
|
||||
NULL /* h_extensions! */,
|
||||
dc->exchange_timestamp,
|
||||
dc->wire_deadline,
|
||||
dc->refund_deadline,
|
||||
&dc->amount_without_fee,
|
||||
&dc->coin_pub,
|
||||
&dc->merchant,
|
||||
&dc->exchange_pub,
|
||||
&dc->exchange_sig))
|
||||
{
|
||||
TALER_LOG_WARNING (
|
||||
"Invalid signature on /deposit-confirmation request\n");
|
||||
|
@ -109,8 +109,22 @@ static struct Table tables[] = {
|
||||
{ .rt = TALER_EXCHANGEDB_RT_WIRE_OUT},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_WIRE_FEE},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_GLOBAL_FEE},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_RECOUP},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_RECOUP_REFRESH },
|
||||
{ .rt = TALER_EXCHANGEDB_RT_EXTENSIONS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_EXTENSION_DETAILS },
|
||||
{ .rt = TALER_EXCHANGEDB_RT_PURSE_REQUESTS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_PURSE_REFUNDS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_PURSE_MERGES},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_PURSE_DEPOSITS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_ACCOUNT_MERGES},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_HISTORY_REQUESTS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_CLOSE_REQUESTS},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_WADS_OUT},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_WADS_IN},
|
||||
{ .rt = TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES},
|
||||
{ .end = true }
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,7 @@ Arguments mandatory for long options are also mandatory for short options.
|
||||
-h, --help print this help
|
||||
-i, --internal perform checks only applicable for
|
||||
exchange-internal audits
|
||||
-I, --ignore-not-found ignore problems with the exchange bank account not existing
|
||||
-L, --log=LOGLEVEL configure logging to use LOGLEVEL
|
||||
-l, --logfile=FILENAME configure logging to write logs to FILENAME
|
||||
-m, --exchange-key=KEY public key of the exchange (Crockford base32
|
||||
@ -28,7 +29,7 @@ EOF
|
||||
|
||||
function optcheck {
|
||||
|
||||
TEMP=`getopt -o c:hiL:l:m:T:v --long config:,help,internal,log:,logfile:exchange-key:,timetravel:,version -n 'taler-auditor' -- "$@"`
|
||||
TEMP=`getopt -o c:hiIL:l:m:T:v --long config:,help,internal,ignore-not-found,log:,logfile:exchange-key:,timetravel:,version -n 'taler-auditor' -- "$@"`
|
||||
|
||||
if [ $? != 0 ] ;
|
||||
then
|
||||
@ -43,6 +44,7 @@ DEBUG=false
|
||||
MEMORY=
|
||||
DEBUGFILE=
|
||||
JAVA_MISC_OPT=
|
||||
INF=
|
||||
while true; do
|
||||
case "$1" in
|
||||
-c | --config ) shift 2 ;;
|
||||
@ -51,6 +53,7 @@ while true; do
|
||||
exit 0
|
||||
;;
|
||||
-i | --internal ) shift ;;
|
||||
-I | --ignore-not-found ) INF="-I"; shift ;;
|
||||
-L | --log ) shift 2;;
|
||||
-l | --logfile ) shift ;;
|
||||
-m | --exchange-key ) shift 2 ;;
|
||||
@ -74,16 +77,20 @@ done
|
||||
}
|
||||
# End of function 'optcheck'
|
||||
|
||||
|
||||
optcheck "$@"
|
||||
|
||||
# Remove "-I" from $@ if present, store result in $ARGS.
|
||||
ARGS=("$@")
|
||||
ARGS=(${ARGS[@]/$INF})
|
||||
|
||||
DIR=`mktemp -d reportXXXXXX`
|
||||
for n in aggregation coins deposits reserves wire
|
||||
for n in aggregation coins deposits reserves
|
||||
do
|
||||
taler-helper-auditor-$n "$@" > ${DIR}/$n.json
|
||||
taler-helper-auditor-$n ${ARGS[*]} > ${DIR}/$n.json
|
||||
done
|
||||
|
||||
taler-helper-auditor-wire $INF ${ARGS[*]} > ${DIR}/wire.json
|
||||
|
||||
taler-helper-auditor-render.py \
|
||||
${DIR}/aggregation.json \
|
||||
${DIR}/coins.json \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2016-2021 Taler Systems SA
|
||||
Copyright (C) 2016-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero Public License as published by the Free Software
|
||||
@ -305,14 +305,9 @@ struct WireFeeInfo
|
||||
struct GNUNET_TIME_Timestamp end_date;
|
||||
|
||||
/**
|
||||
* How high is the wire fee.
|
||||
* How high are the wire fees.
|
||||
*/
|
||||
struct TALER_Amount wire_fee;
|
||||
|
||||
/**
|
||||
* How high is the closing fee.
|
||||
*/
|
||||
struct TALER_Amount closing_fee;
|
||||
struct TALER_WireFeeSet fees;
|
||||
|
||||
};
|
||||
|
||||
@ -395,7 +390,7 @@ check_transaction_history_for_deposit (
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const struct TALER_DenominationKeyValidityPS *issue,
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue,
|
||||
const struct TALER_EXCHANGEDB_TransactionList *tl_head,
|
||||
struct TALER_Amount *merchant_gain,
|
||||
struct TALER_Amount *deposit_gain)
|
||||
@ -405,7 +400,7 @@ check_transaction_history_for_deposit (
|
||||
struct TALER_Amount spent;
|
||||
struct TALER_Amount merchant_loss;
|
||||
const struct TALER_Amount *deposit_fee;
|
||||
int refund_deposit_fee;
|
||||
bool refund_deposit_fee;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Checking transaction history of coin %s\n",
|
||||
@ -426,8 +421,8 @@ check_transaction_history_for_deposit (
|
||||
to reconstruct the order of the events, so instead of subtracting we
|
||||
compute positive (deposit, melt) and negative (refund) values separately
|
||||
here, and then subtract the negative from the positive at the end (after
|
||||
the loops). *///
|
||||
refund_deposit_fee = GNUNET_NO;
|
||||
the loops). */
|
||||
refund_deposit_fee = false;
|
||||
deposit_fee = NULL;
|
||||
for (const struct TALER_EXCHANGEDB_TransactionList *tl = tl_head;
|
||||
NULL != tl;
|
||||
@ -466,23 +461,16 @@ check_transaction_history_for_deposit (
|
||||
deposit_fee = fee_claimed; /* We had a deposit, remember the fee, we may need it */
|
||||
}
|
||||
/* Check that the fees given in the transaction list and in dki match */
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&issue->fees.deposit,
|
||||
fee_claimed))
|
||||
{
|
||||
struct TALER_Amount fee_expected;
|
||||
|
||||
/* Fee according to denomination data of auditor */
|
||||
TALER_amount_ntoh (&fee_expected,
|
||||
&issue->fees.deposit);
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&fee_expected,
|
||||
fee_claimed))
|
||||
{
|
||||
/* Disagreement in fee structure between auditor and exchange DB! */
|
||||
report_amount_arithmetic_inconsistency ("deposit fee",
|
||||
0,
|
||||
fee_claimed,
|
||||
&fee_expected,
|
||||
1);
|
||||
}
|
||||
/* Disagreement in fee structure between auditor and exchange DB! */
|
||||
report_amount_arithmetic_inconsistency ("deposit fee",
|
||||
0,
|
||||
fee_claimed,
|
||||
&issue->fees.deposit,
|
||||
1);
|
||||
}
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_MELT:
|
||||
@ -492,22 +480,16 @@ check_transaction_history_for_deposit (
|
||||
&expenditures,
|
||||
amount_with_fee);
|
||||
/* Check that the fees given in the transaction list and in dki match */
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&issue->fees.refresh,
|
||||
fee_claimed))
|
||||
{
|
||||
struct TALER_Amount fee_expected;
|
||||
|
||||
TALER_amount_ntoh (&fee_expected,
|
||||
&issue->fees.refresh);
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&fee_expected,
|
||||
fee_claimed))
|
||||
{
|
||||
/* Disagreement in fee structure between exchange and auditor */
|
||||
report_amount_arithmetic_inconsistency ("melt fee",
|
||||
0,
|
||||
fee_claimed,
|
||||
&fee_expected,
|
||||
1);
|
||||
}
|
||||
/* Disagreement in fee structure between exchange and auditor */
|
||||
report_amount_arithmetic_inconsistency ("melt fee",
|
||||
0,
|
||||
fee_claimed,
|
||||
&issue->fees.refresh,
|
||||
1);
|
||||
}
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_REFUND:
|
||||
@ -533,25 +515,21 @@ check_transaction_history_for_deposit (
|
||||
&merchant_loss,
|
||||
amount_with_fee);
|
||||
/* If there is a refund, we give back the deposit fee */
|
||||
refund_deposit_fee = GNUNET_YES;
|
||||
/* FIXME: wrong: only if this is a FULL
|
||||
refund we refund the deposit fee! */
|
||||
refund_deposit_fee = true;
|
||||
}
|
||||
/* Check that the fees given in the transaction list and in dki match */
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&issue->fees.refund,
|
||||
fee_claimed))
|
||||
{
|
||||
struct TALER_Amount fee_expected;
|
||||
|
||||
TALER_amount_ntoh (&fee_expected,
|
||||
&issue->fees.refund);
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&fee_expected,
|
||||
fee_claimed))
|
||||
{
|
||||
/* Disagreement in fee structure between exchange and auditor! */
|
||||
report_amount_arithmetic_inconsistency ("refund fee",
|
||||
0,
|
||||
fee_claimed,
|
||||
&fee_expected,
|
||||
1);
|
||||
}
|
||||
/* Disagreement in fee structure between exchange and auditor! */
|
||||
report_amount_arithmetic_inconsistency ("refund fee",
|
||||
0,
|
||||
fee_claimed,
|
||||
&issue->fees.refund,
|
||||
1);
|
||||
}
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP:
|
||||
@ -579,6 +557,13 @@ check_transaction_history_for_deposit (
|
||||
&expenditures,
|
||||
amount_with_fee);
|
||||
break;
|
||||
case TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
|
||||
amount_with_fee = &tl->details.purse_deposit->amount;
|
||||
if (! tl->details.purse_deposit->refunded)
|
||||
TALER_ARL_amount_add (&expenditures,
|
||||
&expenditures,
|
||||
amount_with_fee);
|
||||
break;
|
||||
}
|
||||
} /* for 'tl' */
|
||||
|
||||
@ -589,11 +574,14 @@ check_transaction_history_for_deposit (
|
||||
"Aggregation loss due to refunds is %s\n",
|
||||
TALER_amount2s (&merchant_loss));
|
||||
*deposit_gain = *merchant_gain;
|
||||
if ( (GNUNET_YES == refund_deposit_fee) &&
|
||||
if ( (refund_deposit_fee) &&
|
||||
(NULL != deposit_fee) )
|
||||
{
|
||||
/* We had a /deposit operation AND a /refund operation,
|
||||
and should thus not charge the merchant the /deposit fee */
|
||||
/* FIXME: this is wrong, the merchant never pays either
|
||||
fee, the deposit fee is simply not charged to the coin
|
||||
IF there is a full refund. */
|
||||
TALER_ARL_amount_add (merchant_gain,
|
||||
merchant_gain,
|
||||
deposit_fee);
|
||||
@ -646,18 +634,14 @@ check_transaction_history_for_deposit (
|
||||
else
|
||||
{
|
||||
/* Now check that 'spent' is less or equal than the total coin value */
|
||||
struct TALER_Amount value;
|
||||
|
||||
TALER_amount_ntoh (&value,
|
||||
&issue->value);
|
||||
if (1 == TALER_amount_cmp (&spent,
|
||||
&value))
|
||||
&issue->value))
|
||||
{
|
||||
/* spent > value */
|
||||
report_coin_arithmetic_inconsistency ("spend",
|
||||
coin_pub,
|
||||
&spent,
|
||||
&value,
|
||||
&issue->value,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
@ -708,7 +692,7 @@ wire_transfer_information_cb (
|
||||
const struct TALER_Amount *deposit_fee)
|
||||
{
|
||||
struct WireCheckContext *wcc = cls;
|
||||
const struct TALER_DenominationKeyValidityPS *issue;
|
||||
const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
|
||||
struct TALER_Amount computed_value;
|
||||
struct TALER_Amount total_deposit_without_refunds;
|
||||
struct TALER_EXCHANGEDB_TransactionList *tl;
|
||||
@ -911,7 +895,7 @@ get_wire_fee (struct AggregationContext *ac,
|
||||
GNUNET_TIME_timestamp_cmp (pos->end_date,
|
||||
>,
|
||||
timestamp) )
|
||||
return &pos->wire_fee;
|
||||
return &pos->fees.wire;
|
||||
if (GNUNET_TIME_timestamp_cmp (pos->start_date,
|
||||
>,
|
||||
timestamp))
|
||||
@ -926,8 +910,7 @@ get_wire_fee (struct AggregationContext *ac,
|
||||
timestamp,
|
||||
&wfi->start_date,
|
||||
&wfi->end_date,
|
||||
&wfi->wire_fee,
|
||||
&wfi->closing_fee,
|
||||
&wfi->fees,
|
||||
&master_sig))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
@ -944,8 +927,7 @@ get_wire_fee (struct AggregationContext *ac,
|
||||
method,
|
||||
wfi->start_date,
|
||||
wfi->end_date,
|
||||
&wfi->wire_fee,
|
||||
&wfi->closing_fee,
|
||||
&wfi->fees,
|
||||
&TALER_ARL_master_pub,
|
||||
&master_sig))
|
||||
{
|
||||
@ -958,7 +940,7 @@ get_wire_fee (struct AggregationContext *ac,
|
||||
/* Established fee, keep in sorted list */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Wire fee is %s starting at %s\n",
|
||||
TALER_amount2s (&wfi->wire_fee),
|
||||
TALER_amount2s (&wfi->fees.wire),
|
||||
GNUNET_TIME_timestamp2s (wfi->start_date));
|
||||
if ( (NULL == pos) ||
|
||||
(NULL == pos->prev) )
|
||||
@ -999,7 +981,7 @@ get_wire_fee (struct AggregationContext *ac,
|
||||
TALER_JSON_pack_time_abs_human ("time",
|
||||
wfi->end_date.abs_time)));
|
||||
}
|
||||
return &wfi->wire_fee;
|
||||
return &wfi->fees.wire;
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -304,6 +304,12 @@ static struct GNUNET_CURL_RescheduleContext *rc;
|
||||
*/
|
||||
static int internal_checks;
|
||||
|
||||
/**
|
||||
* Should we ignore if the bank does not know our bank
|
||||
* account?
|
||||
*/
|
||||
static int ignore_account_404;
|
||||
|
||||
/* ***************************** Shutdown **************************** */
|
||||
|
||||
/**
|
||||
@ -778,8 +784,6 @@ commit (enum GNUNET_DB_QueryStatus qs)
|
||||
* @param amount value of the deposit, including fee
|
||||
* @param payto_uri where should the funds be wired
|
||||
* @param deadline what was the requested wire transfer deadline
|
||||
* @param tiny did the exchange defer this transfer because it is too small?
|
||||
* NOTE: only valid in internal audit mode!
|
||||
* @param done did the exchange claim that it made a transfer?
|
||||
* NOTE: only valid in internal audit mode!
|
||||
*/
|
||||
@ -790,7 +794,6 @@ wire_missing_cb (void *cls,
|
||||
const struct TALER_Amount *amount,
|
||||
const char *payto_uri,
|
||||
struct GNUNET_TIME_Timestamp deadline,
|
||||
bool tiny,
|
||||
bool done)
|
||||
{
|
||||
json_t *rep;
|
||||
@ -799,23 +802,11 @@ wire_missing_cb (void *cls,
|
||||
TALER_ARL_amount_add (&total_amount_lag,
|
||||
&total_amount_lag,
|
||||
amount);
|
||||
if (internal_checks)
|
||||
{
|
||||
/* In internal mode, we insist that the entry was
|
||||
actually marked as tiny. */
|
||||
if (tiny &&
|
||||
(0 > TALER_amount_cmp (amount,
|
||||
&tiny_amount)) )
|
||||
return; /* acceptable, amount was tiny */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* External auditors do not replicate tiny, so they
|
||||
only check that the amount is tiny */
|
||||
if (0 > TALER_amount_cmp (amount,
|
||||
&tiny_amount))
|
||||
return; /* acceptable, amount was tiny */
|
||||
}
|
||||
/* For now, we simplify and only check that the
|
||||
amount was tiny */
|
||||
if (0 > TALER_amount_cmp (amount,
|
||||
&tiny_amount))
|
||||
return; /* acceptable, amount was tiny */
|
||||
rep = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("row",
|
||||
rowid),
|
||||
@ -1181,7 +1172,7 @@ check_rc_matches (void *cls,
|
||||
* @param value the `struct ReserveOutInfo` to report
|
||||
* @return #GNUNET_OK
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
complain_out_not_found (void *cls,
|
||||
const struct GNUNET_HashCode *key,
|
||||
void *value)
|
||||
@ -1290,7 +1281,7 @@ check_exchange_wire_out (struct WireAccount *wa)
|
||||
* @param json original response in JSON format
|
||||
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
history_debit_cb (void *cls,
|
||||
unsigned int http_status_code,
|
||||
enum TALER_ErrorCode ec,
|
||||
@ -1306,7 +1297,9 @@ history_debit_cb (void *cls,
|
||||
if (NULL == details)
|
||||
{
|
||||
wa->dhh = NULL;
|
||||
if (TALER_EC_NONE != ec)
|
||||
if ( (TALER_EC_NONE != ec) &&
|
||||
( (! ignore_account_404) ||
|
||||
(MHD_HTTP_NOT_FOUND != http_status_code) ) )
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Error fetching debit history of account %s: %u/%u!\n",
|
||||
@ -1583,7 +1576,7 @@ process_credits (void *cls);
|
||||
* @param json raw response
|
||||
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
history_credit_cb (void *cls,
|
||||
unsigned int http_status,
|
||||
enum TALER_ErrorCode ec,
|
||||
@ -1599,7 +1592,9 @@ history_credit_cb (void *cls,
|
||||
if (NULL == details)
|
||||
{
|
||||
wa->chh = NULL;
|
||||
if (TALER_EC_NONE != ec)
|
||||
if ( (TALER_EC_NONE != ec) &&
|
||||
( (! ignore_account_404) ||
|
||||
(MHD_HTTP_NOT_FOUND != http_status) ) )
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Error fetching credit history of account %s: %u/%s!\n",
|
||||
@ -2192,6 +2187,10 @@ main (int argc,
|
||||
"internal",
|
||||
"perform checks only applicable for exchange-internal audits",
|
||||
&internal_checks),
|
||||
GNUNET_GETOPT_option_flag ('I',
|
||||
"ignore-not-found",
|
||||
"continue, even if the bank account of the exchange was not found",
|
||||
&ignore_account_404),
|
||||
GNUNET_GETOPT_option_base32_auto ('m',
|
||||
"exchange-key",
|
||||
"KEY",
|
||||
|
@ -6,7 +6,7 @@
|
||||
#
|
||||
# Requires 'jq' tool and Postgres superuser rights!
|
||||
set -eu
|
||||
set -x
|
||||
#set -x
|
||||
|
||||
# Set of numbers for all the testcases.
|
||||
# When adding new tests, increase the last number:
|
||||
@ -472,11 +472,9 @@ function test_4() {
|
||||
echo "===========4: deposit wire target wrong================="
|
||||
# Original target bank account was 43, changing to 44
|
||||
SERIAL=`echo "SELECT deposit_serial_id FROM deposits WHERE amount_with_fee_val=3 AND amount_with_fee_frac=0 ORDER BY deposit_serial_id LIMIT 1" | psql $DB -Aqt`
|
||||
OLD_WIRE_ID=`echo "SELECT w.wire_target_serial_id FROM deposits d, wire_targets w WHERE d.wire_target_serial_id = w.wire_target_serial_id AND deposit_serial_id=${SERIAL};" | psql $DB -Aqt`
|
||||
NEW_WIRE_ID=`echo "INSERT INTO wire_targets (wire_target_serial_id, payto_uri, h_payto, kyc_ok) VALUES (DEFAULT, 'payto://x-taler-bank/localhost/testuser-xxlargtp', '\xe67a8933f7521572236301d7ff63e217245f777ed4b4d7e8df1b989900743658f4c10042ff9e5ce517bff4e5387b27877780673d85393f289aea5ee1946021c3', false) RETURNING wire_target_serial_id;" | psql $DB -Aqt`
|
||||
echo OLD_WIRE_ID=$OLD_WIRE_ID
|
||||
echo NEW_WIRE_ID=$NEW_WIRE_ID
|
||||
echo "UPDATE deposits SET wire_target_serial_id=$NEW_WIRE_ID WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB
|
||||
OLD_WIRE_ID=`echo "SELECT wire_target_h_payto FROM deposits WHERE deposit_serial_id=${SERIAL};" | psql $DB -Aqt`
|
||||
NEW_WIRE_ID=`echo "INSERT INTO wire_targets (payto_uri, wire_target_h_payto, kyc_ok) VALUES ('payto://x-taler-bank/localhost/testuser-xxlargtp', '\x1e8f31936b3cee8f8afd3aac9e38b5db42d45b721ffc4eb1e5b9ddaf1565660b', false);" | psql $DB -Aqt`
|
||||
echo "UPDATE deposits SET wire_target_h_payto='\x1e8f31936b3cee8f8afd3aac9e38b5db42d45b721ffc4eb1e5b9ddaf1565660b' WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB
|
||||
|
||||
run_audit
|
||||
|
||||
@ -510,7 +508,7 @@ fi
|
||||
|
||||
echo PASS
|
||||
# Undo:
|
||||
echo "UPDATE deposits SET wire_target_serial_id=$OLD_WIRE_ID WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB
|
||||
echo "UPDATE deposits SET wire_target_h_payto='$OLD_WIRE_ID' WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB
|
||||
|
||||
}
|
||||
|
||||
@ -867,7 +865,7 @@ function test_13() {
|
||||
echo "===========13: wrong melt signature ==========="
|
||||
# Modify denom_sig, so it is wrong
|
||||
COIN_PUB=`echo "SELECT old_coin_pub FROM refresh_commitments LIMIT 1;" | psql $DB -Aqt`
|
||||
OLD_SIG=`echo "SELECT old_coin_sig FROM refresh_commitments WHERE old_known_pub='$COIN_PUB';" | psql $DB -Aqt`
|
||||
OLD_SIG=`echo "SELECT old_coin_sig FROM refresh_commitments WHERE old_coin_pub='$COIN_PUB';" | psql $DB -Aqt`
|
||||
NEW_SIG="\xba588af7c13c477dca1ac458f65cc484db8fba53b969b873f4353ecbd815e6b4c03f42c0cb63a2b609c2d726e612fd8e0c084906a41f409b6a23a08a83c89a02"
|
||||
echo "UPDATE refresh_commitments SET old_coin_sig='$NEW_SIG' WHERE old_coin_pub='$COIN_PUB'" | psql -Aqt $DB
|
||||
|
||||
@ -1487,11 +1485,11 @@ function test_26() {
|
||||
echo "===========26: deposit wire target malformed ================="
|
||||
# Expects 'payto_uri', not 'url' (also breaks signature, but we cannot even check that).
|
||||
SERIAL=`echo "SELECT deposit_serial_id FROM deposits WHERE amount_with_fee_val=3 AND amount_with_fee_frac=0 ORDER BY deposit_serial_id LIMIT 1" | psql $DB -Aqt`
|
||||
OLD_WIRE_ID=`echo "SELECT w.wire_target_serial_id FROM deposits d, wire_targets w WHERE d.wire_target_serial_id = w.wire_target_serial_id AND deposit_serial_id=${SERIAL};" | psql $DB -Aqt`
|
||||
NEW_WIRE_ID=`echo "INSERT INTO wire_targets (wire_target_serial_id, payto_uri, h_payto, kyc_ok) VALUES (DEFAULT, 'payto://x-taler-bank/localhost/testuser-xxlargtp', '\xe67a8933f7521572236301d7ff63e217245f777ed4b4d7e8df1b989900743658f4c10042ff9e5ce517bff4e5387b27877780673d85393f289aea5ee1946021c3', false) RETURNING wire_target_serial_id;" | psql $DB -Aqt`
|
||||
OLD_WIRE_ID=`echo "SELECT wire_target_h_payto FROM deposits WHERE deposit_serial_id=${SERIAL};" | psql $DB -Aqt`
|
||||
NEW_WIRE_ID=`echo "INSERT INTO wire_targets (payto_uri, wire_target_h_payto, kyc_ok) VALUES ('payto://x-taler-bank/localhost/testuser-xxlargtp', '\x1e8f31936b3cee8f8afd3aac9e38b5db42d45b721ffc4eb1e5b9ddaf1565660b', false);" | psql $DB -Aqt`
|
||||
echo OLD_WIRE_ID=$OLD_WIRE_ID
|
||||
echo NEW_WIRE_ID=$NEW_WIRE_ID
|
||||
echo "UPDATE deposits SET wire_target_serial_id=$NEW_WIRE_ID WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB
|
||||
echo "UPDATE deposits SET wire_target_h_payto='\x1e8f31936b3cee8f8afd3aac9e38b5db42d45b721ffc4eb1e5b9ddaf1565660b' WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB
|
||||
|
||||
run_audit
|
||||
|
||||
@ -1525,7 +1523,7 @@ fi
|
||||
|
||||
echo PASS
|
||||
# Undo:
|
||||
echo "UPDATE deposits SET wire_target_serial_id=$OLD_WIRE_ID WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB
|
||||
echo "UPDATE deposits SET wire_target_h_payto='$OLD_WIRE_ID' WHERE deposit_serial_id=${SERIAL}" | psql -Aqt $DB
|
||||
|
||||
}
|
||||
|
||||
@ -1597,12 +1595,6 @@ then
|
||||
run_audit aggregator
|
||||
|
||||
echo -n "Testing inconsistency detection... "
|
||||
ROW=`jq -e .bad_sig_losses[0].row < test-audit-aggregation.json`
|
||||
if test $ROW != "1"
|
||||
then
|
||||
exit_fail "Row wrong, got $ROW"
|
||||
fi
|
||||
|
||||
LOSS=`jq -r .bad_sig_losses[0].loss < test-audit-aggregation.json`
|
||||
if test $LOSS == "TESTKUDOS:0"
|
||||
then
|
||||
@ -1891,6 +1883,7 @@ else
|
||||
then
|
||||
MYDIR=`mktemp -d /tmp/taler-auditor-basedbXXXXXX`
|
||||
echo " FOUND. Generating fresh database at $MYDIR"
|
||||
pwd
|
||||
if ./generate-auditor-basedb.sh $MYDIR/basedb
|
||||
then
|
||||
check_with_database $MYDIR/basedb
|
||||
|
@ -74,8 +74,9 @@ function pre_audit () {
|
||||
|
||||
if test ${1:-no} = "aggregator"
|
||||
then
|
||||
export CONF
|
||||
echo -n "Running exchange aggregator ..."
|
||||
taler-exchange-aggregator -L INFO -t -c $CONF 2> aggregator.log || exit_fail "FAIL"
|
||||
taler-exchange-aggregator -L INFO -t -c $CONF -y 2> aggregator.log || exit_fail "FAIL"
|
||||
echo " DONE"
|
||||
echo -n "Running exchange closer ..."
|
||||
taler-exchange-closer -L INFO -t -c $CONF 2> closer.log || exit_fail "FAIL"
|
||||
|
@ -16,7 +16,7 @@ echo -n "."
|
||||
psql talercheck-in < auditor-basedb.sql >/dev/null 2> /dev/null
|
||||
|
||||
echo -n "."
|
||||
~/bin/taler-auditor-sync -s test-sync-in.conf -d test-sync-out.conf -t
|
||||
taler-auditor-sync -s test-sync-in.conf -d test-sync-out.conf -t
|
||||
|
||||
# cs_nonce_locks excluded: no point
|
||||
for table in denominations denomination_revocations wire_targets reserves reserves_in reserves_close reserves_out auditors auditor_denom_sigs exchange_sign_keys signkey_revocations extensions extension_details known_coins refresh_commitments refresh_revealed_coins refresh_transfer_keys deposits refunds wire_out aggregation_tracking wire_fee recoup recoup_refresh
|
||||
|
@ -47,6 +47,11 @@ CREATE TABLE IF NOT EXISTS auditor_progress_reserve
|
||||
,last_reserve_out_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_reserve_recoup_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_reserve_close_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_purse_merges_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_purse_deposits_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_account_merges_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_history_requests_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_close_requests_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,PRIMARY KEY (master_pub)
|
||||
);
|
||||
COMMENT ON TABLE auditor_progress_reserve
|
||||
@ -82,6 +87,8 @@ CREATE TABLE IF NOT EXISTS auditor_progress_coin
|
||||
,last_refund_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_recoup_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_recoup_refresh_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_purse_deposits_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,last_purse_refunds_serial_id INT8 NOT NULL DEFAULT 0
|
||||
,PRIMARY KEY (master_pub)
|
||||
);
|
||||
COMMENT ON TABLE auditor_progress_coin
|
||||
@ -136,6 +143,10 @@ CREATE TABLE IF NOT EXISTS auditor_reserve_balance
|
||||
,reserve_balance_frac INT4 NOT NULL
|
||||
,withdraw_fee_balance_val INT8 NOT NULL
|
||||
,withdraw_fee_balance_frac INT4 NOT NULL
|
||||
,purse_fee_balance_val INT8 NOT NULL
|
||||
,purse_fee_balance_frac INT4 NOT NULL
|
||||
,history_fee_balance_val INT8 NOT NULL
|
||||
,history_fee_balance_frac INT4 NOT NULL
|
||||
);
|
||||
COMMENT ON TABLE auditor_reserve_balance
|
||||
IS 'sum of the balances of all customer reserves (by exchange master public key)';
|
||||
|
@ -230,8 +230,13 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",last_reserve_out_serial_id=$2"
|
||||
",last_reserve_recoup_serial_id=$3"
|
||||
",last_reserve_close_serial_id=$4"
|
||||
" WHERE master_pub=$5",
|
||||
5),
|
||||
",last_purse_merges_serial_id=$5"
|
||||
",last_purse_deposits_serial_id=$6"
|
||||
",last_account_merges_serial_id=$7"
|
||||
",last_history_requests_serial_id=$8"
|
||||
",last_close_requests_serial_id=$9"
|
||||
" WHERE master_pub=$10",
|
||||
10),
|
||||
/* Used in #postgres_get_auditor_progress_reserve() */
|
||||
GNUNET_PQ_make_prepare ("auditor_progress_select_reserve",
|
||||
"SELECT"
|
||||
@ -239,6 +244,11 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",last_reserve_out_serial_id"
|
||||
",last_reserve_recoup_serial_id"
|
||||
",last_reserve_close_serial_id"
|
||||
",last_purse_merges_serial_id"
|
||||
",last_purse_deposits_serial_id"
|
||||
",last_account_merges_serial_id"
|
||||
",last_history_requests_serial_id"
|
||||
",last_close_requests_serial_id"
|
||||
" FROM auditor_progress_reserve"
|
||||
" WHERE master_pub=$1;",
|
||||
1),
|
||||
@ -250,8 +260,13 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",last_reserve_out_serial_id"
|
||||
",last_reserve_recoup_serial_id"
|
||||
",last_reserve_close_serial_id"
|
||||
") VALUES ($1,$2,$3,$4,$5);",
|
||||
5),
|
||||
",last_purse_merges_serial_id"
|
||||
",last_purse_deposits_serial_id"
|
||||
",last_account_merges_serial_id"
|
||||
",last_history_requests_serial_id"
|
||||
",last_close_requests_serial_id"
|
||||
") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);",
|
||||
10),
|
||||
/* Used in #postgres_update_auditor_progress_aggregation() */
|
||||
GNUNET_PQ_make_prepare ("auditor_progress_update_aggregation",
|
||||
"UPDATE auditor_progress_aggregation SET "
|
||||
@ -301,8 +316,10 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",last_refund_serial_id=$4"
|
||||
",last_recoup_serial_id=$5"
|
||||
",last_recoup_refresh_serial_id=$6"
|
||||
" WHERE master_pub=$7",
|
||||
7),
|
||||
",last_purse_deposits_serial_id=$7"
|
||||
",last_purse_refunds_serial_id=$8"
|
||||
" WHERE master_pub=$9",
|
||||
9),
|
||||
/* Used in #postgres_get_auditor_progress_coin() */
|
||||
GNUNET_PQ_make_prepare ("auditor_progress_select_coin",
|
||||
"SELECT"
|
||||
@ -312,6 +329,8 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",last_refund_serial_id"
|
||||
",last_recoup_serial_id"
|
||||
",last_recoup_refresh_serial_id"
|
||||
",last_purse_deposits_serial_id"
|
||||
",last_purse_refunds_serial_id"
|
||||
" FROM auditor_progress_coin"
|
||||
" WHERE master_pub=$1;",
|
||||
1),
|
||||
@ -325,8 +344,10 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",last_refund_serial_id"
|
||||
",last_recoup_serial_id"
|
||||
",last_recoup_refresh_serial_id"
|
||||
") VALUES ($1,$2,$3,$4,$5,$6,$7);",
|
||||
7),
|
||||
",last_purse_deposits_serial_id"
|
||||
",last_purse_refunds_serial_id"
|
||||
") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9);",
|
||||
9),
|
||||
/* Used in #postgres_insert_wire_auditor_account_progress() */
|
||||
GNUNET_PQ_make_prepare ("wire_auditor_account_progress_insert",
|
||||
"INSERT INTO wire_auditor_account_progress "
|
||||
@ -430,8 +451,12 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",reserve_balance_frac"
|
||||
",withdraw_fee_balance_val"
|
||||
",withdraw_fee_balance_frac"
|
||||
") VALUES ($1,$2,$3,$4,$5)",
|
||||
5),
|
||||
",purse_fee_balance_val"
|
||||
",purse_fee_balance_frac"
|
||||
",history_fee_balance_val"
|
||||
",history_fee_balance_frac"
|
||||
") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)",
|
||||
9),
|
||||
/* Used in #postgres_update_reserve_summary() */
|
||||
GNUNET_PQ_make_prepare ("auditor_reserve_balance_update",
|
||||
"UPDATE auditor_reserve_balance SET"
|
||||
@ -439,8 +464,12 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",reserve_balance_frac=$2"
|
||||
",withdraw_fee_balance_val=$3"
|
||||
",withdraw_fee_balance_frac=$4"
|
||||
" WHERE master_pub=$5;",
|
||||
5),
|
||||
",purse_fee_balance_val=$5"
|
||||
",purse_fee_balance_frac=$6"
|
||||
",history_fee_balance_val=$7"
|
||||
",history_fee_balance_frac=$8"
|
||||
" WHERE master_pub=$9;",
|
||||
9),
|
||||
/* Used in #postgres_get_reserve_summary() */
|
||||
GNUNET_PQ_make_prepare ("auditor_reserve_balance_select",
|
||||
"SELECT"
|
||||
@ -448,6 +477,10 @@ setup_connection (struct PostgresClosure *pg)
|
||||
",reserve_balance_frac"
|
||||
",withdraw_fee_balance_val"
|
||||
",withdraw_fee_balance_frac"
|
||||
",purse_fee_balance_val"
|
||||
",purse_fee_balance_frac"
|
||||
",history_fee_balance_val"
|
||||
",history_fee_balance_frac"
|
||||
" FROM auditor_reserve_balance"
|
||||
" WHERE master_pub=$1;",
|
||||
1),
|
||||
@ -1225,6 +1258,11 @@ postgres_insert_auditor_progress_reserve (
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_out_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_recoup_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_close_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_purse_merges_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_purse_deposits_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_account_merges_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_history_requests_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_close_requests_serial_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
@ -1255,6 +1293,11 @@ postgres_update_auditor_progress_reserve (
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_out_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_recoup_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_reserve_close_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_purse_merges_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_purse_deposits_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_account_merges_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_history_requests_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppr->last_close_requests_serial_id),
|
||||
GNUNET_PQ_query_param_auto_from_type (master_pub),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
@ -1293,6 +1336,16 @@ postgres_get_auditor_progress_reserve (
|
||||
&ppr->last_reserve_recoup_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_reserve_close_serial_id",
|
||||
&ppr->last_reserve_close_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_purse_merges_serial_id",
|
||||
&ppr->last_purse_merges_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_purse_deposits_serial_id",
|
||||
&ppr->last_purse_deposits_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_account_merges_serial_id",
|
||||
&ppr->last_account_merges_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_history_requests_serial_id",
|
||||
&ppr->last_history_requests_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_close_requests_serial_id",
|
||||
&ppr->last_close_requests_serial_id),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
@ -1503,6 +1556,8 @@ postgres_insert_auditor_progress_coin (
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_refund_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_refresh_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_purse_deposits_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_purse_refunds_serial_id),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
@ -1535,6 +1590,8 @@ postgres_update_auditor_progress_coin (
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_refund_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_recoup_refresh_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_purse_deposits_serial_id),
|
||||
GNUNET_PQ_query_param_uint64 (&ppc->last_purse_refunds_serial_id),
|
||||
GNUNET_PQ_query_param_auto_from_type (master_pub),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
@ -1577,6 +1634,10 @@ postgres_get_auditor_progress_coin (
|
||||
&ppc->last_recoup_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_recoup_refresh_serial_id",
|
||||
&ppc->last_recoup_refresh_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_purse_deposits_serial_id",
|
||||
&ppc->last_purse_deposits_serial_id),
|
||||
GNUNET_PQ_result_spec_uint64 ("last_purse_refunds_serial_id",
|
||||
&ppc->last_purse_refunds_serial_id),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
@ -1965,7 +2026,8 @@ postgres_get_reserve_info (void *cls,
|
||||
* @param master_pub master public key of the exchange
|
||||
* @param reserve_balance amount stored in the reserve
|
||||
* @param withdraw_fee_balance amount the exchange gained in withdraw fees
|
||||
* due to withdrawals from this reserve
|
||||
* @param purse_fee_balance amount the exchange gained in purse fees
|
||||
* @param history_fee_balance amount the exchange gained in history fees
|
||||
* @return transaction status code
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
@ -1973,13 +2035,17 @@ postgres_insert_reserve_summary (
|
||||
void *cls,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
const struct TALER_Amount *reserve_balance,
|
||||
const struct TALER_Amount *withdraw_fee_balance)
|
||||
const struct TALER_Amount *withdraw_fee_balance,
|
||||
const struct TALER_Amount *purse_fee_balance,
|
||||
const struct TALER_Amount *history_fee_balance)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
GNUNET_PQ_query_param_auto_from_type (master_pub),
|
||||
TALER_PQ_query_param_amount (reserve_balance),
|
||||
TALER_PQ_query_param_amount (withdraw_fee_balance),
|
||||
TALER_PQ_query_param_amount (purse_fee_balance),
|
||||
TALER_PQ_query_param_amount (history_fee_balance),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
|
||||
@ -2009,12 +2075,16 @@ postgres_update_reserve_summary (
|
||||
void *cls,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
const struct TALER_Amount *reserve_balance,
|
||||
const struct TALER_Amount *withdraw_fee_balance)
|
||||
const struct TALER_Amount *withdraw_fee_balance,
|
||||
const struct TALER_Amount *purse_fee_balance,
|
||||
const struct TALER_Amount *history_fee_balance)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
TALER_PQ_query_param_amount (reserve_balance),
|
||||
TALER_PQ_query_param_amount (withdraw_fee_balance),
|
||||
TALER_PQ_query_param_amount (purse_fee_balance),
|
||||
TALER_PQ_query_param_amount (history_fee_balance),
|
||||
GNUNET_PQ_query_param_auto_from_type (master_pub),
|
||||
GNUNET_PQ_query_param_end
|
||||
};
|
||||
@ -2030,16 +2100,19 @@ postgres_update_reserve_summary (
|
||||
*
|
||||
* @param cls the @e cls of this struct with the plugin-specific state
|
||||
* @param master_pub master public key of the exchange
|
||||
* @param[out] reserve_balance amount stored in the reserve
|
||||
* @param[out] reserve_balance amount stored in reserves
|
||||
* @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees
|
||||
* due to withdrawals from this reserve
|
||||
* @param[out] purse_fee_balance amount the exchange gained in purse fees
|
||||
* @param[out] history_fee_balance amount the exchange gained in history fees
|
||||
* @return transaction status code
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
postgres_get_reserve_summary (void *cls,
|
||||
const struct TALER_MasterPublicKeyP *master_pub,
|
||||
struct TALER_Amount *reserve_balance,
|
||||
struct TALER_Amount *withdraw_fee_balance)
|
||||
struct TALER_Amount *withdraw_fee_balance,
|
||||
struct TALER_Amount *purse_fee_balance,
|
||||
struct TALER_Amount *history_fee_balance)
|
||||
{
|
||||
struct PostgresClosure *pg = cls;
|
||||
struct GNUNET_PQ_QueryParam params[] = {
|
||||
@ -2049,7 +2122,8 @@ postgres_get_reserve_summary (void *cls,
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("reserve_balance", reserve_balance),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("withdraw_fee_balance", withdraw_fee_balance),
|
||||
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("purse_fee_balance", purse_fee_balance),
|
||||
TALER_PQ_RESULT_SPEC_AMOUNT ("history_fee_balance", history_fee_balance),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
|
@ -220,8 +220,14 @@ run (void *cls)
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_reserve_info\n");
|
||||
|
||||
struct TALER_Amount reserve_balance, withdraw_fee_balance;
|
||||
struct TALER_Amount reserve_balance2 = {}, withdraw_fee_balance2 = {};
|
||||
struct TALER_Amount reserve_balance;
|
||||
struct TALER_Amount withdraw_fee_balance;
|
||||
struct TALER_Amount purse_fee_balance;
|
||||
struct TALER_Amount history_fee_balance;
|
||||
struct TALER_Amount reserve_balance2 = {};
|
||||
struct TALER_Amount withdraw_fee_balance2 = {};
|
||||
struct TALER_Amount purse_fee_balance2 = {};
|
||||
struct TALER_Amount history_fee_balance2 = {};
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":12.345678",
|
||||
@ -229,6 +235,12 @@ run (void *cls)
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":23.456789",
|
||||
&withdraw_fee_balance));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":23.456789",
|
||||
&purse_fee_balance));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount (CURRENCY ":23.456789",
|
||||
&history_fee_balance));
|
||||
|
||||
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
@ -268,10 +280,12 @@ run (void *cls)
|
||||
FAILIF (0 != strcmp (payto,
|
||||
"payto://bla/blub"));
|
||||
GNUNET_free (payto);
|
||||
FAILIF (0 != GNUNET_memcmp (&date, &future)
|
||||
|| 0 != GNUNET_memcmp (&reserve_balance2, &reserve_balance)
|
||||
|| 0 != GNUNET_memcmp (&withdraw_fee_balance2,
|
||||
&withdraw_fee_balance));
|
||||
FAILIF (0 != GNUNET_memcmp (&date,
|
||||
&future)
|
||||
|| 0 != TALER_amount_cmp (&reserve_balance2,
|
||||
&reserve_balance)
|
||||
|| 0 != TALER_amount_cmp (&withdraw_fee_balance2,
|
||||
&withdraw_fee_balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_reserve_summary\n");
|
||||
@ -279,8 +293,10 @@ run (void *cls)
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->insert_reserve_summary (plugin->cls,
|
||||
&master_pub,
|
||||
&reserve_balance,
|
||||
&withdraw_fee_balance,
|
||||
&reserve_balance));
|
||||
&purse_fee_balance,
|
||||
&history_fee_balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: update_reserve_summary\n");
|
||||
@ -289,25 +305,34 @@ run (void *cls)
|
||||
plugin->update_reserve_summary (plugin->cls,
|
||||
&master_pub,
|
||||
&reserve_balance,
|
||||
&withdraw_fee_balance));
|
||||
&withdraw_fee_balance,
|
||||
&purse_fee_balance,
|
||||
&history_fee_balance));
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: get_reserve_summary\n");
|
||||
|
||||
ZR_BLK (&reserve_balance2);
|
||||
ZR_BLK (&withdraw_fee_balance2);
|
||||
ZR_BLK (&purse_fee_balance2);
|
||||
ZR_BLK (&history_fee_balance2);
|
||||
|
||||
FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
plugin->get_reserve_summary (plugin->cls,
|
||||
&master_pub,
|
||||
&reserve_balance2,
|
||||
&withdraw_fee_balance2));
|
||||
|
||||
FAILIF ( (0 != GNUNET_memcmp (&reserve_balance2,
|
||||
&reserve_balance) ||
|
||||
(0 != GNUNET_memcmp (&withdraw_fee_balance2,
|
||||
&withdraw_fee_balance)) ) );
|
||||
&withdraw_fee_balance2,
|
||||
&purse_fee_balance2,
|
||||
&history_fee_balance2));
|
||||
|
||||
FAILIF ( (0 != TALER_amount_cmp (&reserve_balance2,
|
||||
&reserve_balance) ||
|
||||
(0 != TALER_amount_cmp (&withdraw_fee_balance2,
|
||||
&withdraw_fee_balance)) ||
|
||||
(0 != TALER_amount_cmp (&purse_fee_balance2,
|
||||
&purse_fee_balance)) ||
|
||||
(0 != TALER_amount_cmp (&history_fee_balance2,
|
||||
&history_fee_balance))));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Test: insert_denomination_balance\n");
|
||||
|
||||
|
@ -159,6 +159,11 @@ struct Account
|
||||
*/
|
||||
char *account_name;
|
||||
|
||||
/**
|
||||
* Receiver name for payto:// URIs.
|
||||
*/
|
||||
char *receiver_name;
|
||||
|
||||
/**
|
||||
* Current account balance.
|
||||
*/
|
||||
@ -497,9 +502,10 @@ lp_trigger (struct LongPoller *lp,
|
||||
GNUNET_free (lp);
|
||||
h->mhd_again = true;
|
||||
#ifdef __linux__
|
||||
if (-1 != h->lp_event)
|
||||
if (-1 == h->lp_event)
|
||||
#else
|
||||
if (-1 != h->lp_event_in && -1 != h->lp_event_out)
|
||||
if ( (-1 == h->lp_event_in) &&
|
||||
(-1 == h->lp_event_out) )
|
||||
#endif
|
||||
{
|
||||
if (NULL != h->mhd_task)
|
||||
@ -617,11 +623,14 @@ lp_expiration_thread (void *cls)
|
||||
*
|
||||
* @param[in,out] h bank to lookup account at
|
||||
* @param name account name to resolve
|
||||
* @return account handle (never NULL)
|
||||
* @param receiver_name receiver name in payto:// URI,
|
||||
* NULL if the account must already exist
|
||||
* @return account handle, NULL if account does not yet exist
|
||||
*/
|
||||
static struct Account *
|
||||
lookup_account (struct TALER_FAKEBANK_Handle *h,
|
||||
const char *name)
|
||||
const char *name,
|
||||
const char *receiver_name)
|
||||
{
|
||||
struct GNUNET_HashCode hc;
|
||||
size_t slen;
|
||||
@ -640,8 +649,15 @@ lookup_account (struct TALER_FAKEBANK_Handle *h,
|
||||
&hc);
|
||||
if (NULL == account)
|
||||
{
|
||||
if (NULL == receiver_name)
|
||||
{
|
||||
GNUNET_assert (0 ==
|
||||
pthread_mutex_unlock (&h->accounts_lock));
|
||||
return NULL;
|
||||
}
|
||||
account = GNUNET_new (struct Account);
|
||||
account->account_name = GNUNET_strdup (name);
|
||||
account->receiver_name = GNUNET_strdup (receiver_name);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_set_zero (h->currency,
|
||||
&account->balance));
|
||||
@ -723,9 +739,31 @@ TALER_FAKEBANK_check_debit (struct TALER_FAKEBANK_Handle *h,
|
||||
strcasecmp (want_amount->currency,
|
||||
h->currency));
|
||||
debit_account = lookup_account (h,
|
||||
want_debit);
|
||||
want_debit,
|
||||
NULL);
|
||||
credit_account = lookup_account (h,
|
||||
want_credit);
|
||||
want_credit,
|
||||
NULL);
|
||||
if (NULL == debit_account)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"I wanted: %s->%s (%s) from exchange %s (DEBIT), but debit account does not even exist!\n",
|
||||
want_debit,
|
||||
want_credit,
|
||||
TALER_amount2s (want_amount),
|
||||
exchange_base_url);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (NULL == credit_account)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"I wanted: %s->%s (%s) from exchange %s (DEBIT), but credit account does not even exist!\n",
|
||||
want_debit,
|
||||
want_credit,
|
||||
TALER_amount2s (want_amount),
|
||||
exchange_base_url);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
for (struct Transaction *t = debit_account->out_tail;
|
||||
NULL != t;
|
||||
t = t->prev_out)
|
||||
@ -769,9 +807,31 @@ TALER_FAKEBANK_check_credit (struct TALER_FAKEBANK_Handle *h,
|
||||
GNUNET_assert (0 == strcasecmp (want_amount->currency,
|
||||
h->currency));
|
||||
debit_account = lookup_account (h,
|
||||
want_debit);
|
||||
want_debit,
|
||||
NULL);
|
||||
credit_account = lookup_account (h,
|
||||
want_credit);
|
||||
want_credit,
|
||||
NULL);
|
||||
if (NULL == debit_account)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"I wanted:\n%s -> %s (%s) with subject %s (CREDIT) but debit account is unknown.\n",
|
||||
want_debit,
|
||||
want_credit,
|
||||
TALER_amount2s (want_amount),
|
||||
TALER_B2S (reserve_pub));
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (NULL == credit_account)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"I wanted:\n%s -> %s (%s) with subject %s (CREDIT) but credit account is unknown.\n",
|
||||
want_debit,
|
||||
want_credit,
|
||||
TALER_amount2s (want_amount),
|
||||
TALER_B2S (reserve_pub));
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
for (struct Transaction *t = credit_account->in_tail;
|
||||
NULL != t;
|
||||
t = t->prev_in)
|
||||
@ -1011,8 +1071,10 @@ make_transfer (
|
||||
url_len = strlen (exchange_base_url);
|
||||
GNUNET_assert (url_len < MAX_URL_LEN);
|
||||
debit_acc = lookup_account (h,
|
||||
debit_account,
|
||||
debit_account);
|
||||
credit_acc = lookup_account (h,
|
||||
credit_account,
|
||||
credit_account);
|
||||
if (NULL != request_uid)
|
||||
{
|
||||
@ -1131,10 +1193,11 @@ make_admin_transfer (
|
||||
credit_account,
|
||||
strlen ("payto://")));
|
||||
debit_acc = lookup_account (h,
|
||||
debit_account,
|
||||
debit_account);
|
||||
credit_acc = lookup_account (h,
|
||||
credit_account,
|
||||
credit_account);
|
||||
|
||||
GNUNET_assert (0 ==
|
||||
pthread_mutex_lock (&h->rpubs_lock));
|
||||
t = GNUNET_CONTAINER_multipeermap_get (h->rpubs,
|
||||
@ -1216,6 +1279,7 @@ free_account (void *cls,
|
||||
(void) key;
|
||||
GNUNET_assert (NULL == account->lp_head);
|
||||
GNUNET_free (account->account_name);
|
||||
GNUNET_free (account->receiver_name);
|
||||
GNUNET_free (account);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
@ -1440,6 +1504,15 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
|
||||
NULL);
|
||||
}
|
||||
debit = TALER_xtalerbank_account_from_payto (debit_account);
|
||||
if (NULL == debit)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
|
||||
debit_account);
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Receiving incoming wire transfer: %s->%s, subject: %s, amount: %s\n",
|
||||
debit,
|
||||
@ -1557,9 +1630,18 @@ handle_transfer (struct TALER_FAKEBANK_Handle *h,
|
||||
return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
|
||||
}
|
||||
{
|
||||
int ret;
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
credit = TALER_xtalerbank_account_from_payto (credit_account);
|
||||
if (NULL == credit)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (
|
||||
connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
|
||||
credit_account);
|
||||
}
|
||||
ret = make_transfer (h,
|
||||
account,
|
||||
credit,
|
||||
@ -1649,7 +1731,7 @@ struct HistoryArgs
|
||||
uint64_t account_number;
|
||||
|
||||
/**
|
||||
* Index of the starting transaction.
|
||||
* Index of the starting transaction, exclusive (!).
|
||||
*/
|
||||
uint64_t start_idx;
|
||||
|
||||
@ -1942,10 +2024,19 @@ handle_debit_history (struct TALER_FAKEBANK_Handle *h,
|
||||
if (&special_ptr == *con_cls)
|
||||
ha.lp_timeout = GNUNET_TIME_UNIT_ZERO;
|
||||
acc = lookup_account (h,
|
||||
account);
|
||||
account,
|
||||
NULL);
|
||||
if (NULL == acc)
|
||||
{
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
TALER_EC_BANK_UNKNOWN_ACCOUNT,
|
||||
account);
|
||||
}
|
||||
GNUNET_asprintf (&debit_payto,
|
||||
"payto://x-taler-bank/localhost/%s",
|
||||
account);
|
||||
"payto://x-taler-bank/localhost/%s?receiver-name=%s",
|
||||
account,
|
||||
acc->receiver_name);
|
||||
history = json_array ();
|
||||
if (NULL == history)
|
||||
{
|
||||
@ -1991,6 +2082,11 @@ handle_debit_history (struct TALER_FAKEBANK_Handle *h,
|
||||
{
|
||||
GNUNET_assert (0 ==
|
||||
pthread_mutex_unlock (&h->big_lock));
|
||||
if (overflow)
|
||||
return TALER_MHD_reply_with_ec (
|
||||
connection,
|
||||
TALER_EC_BANK_ANCIENT_TRANSACTION_GONE,
|
||||
NULL);
|
||||
return TALER_MHD_REPLY_JSON_PACK (
|
||||
connection,
|
||||
MHD_HTTP_OK,
|
||||
@ -2061,8 +2157,10 @@ handle_debit_history (struct TALER_FAKEBANK_Handle *h,
|
||||
continue;
|
||||
}
|
||||
GNUNET_asprintf (&credit_payto,
|
||||
"payto://x-taler-bank/localhost/%s",
|
||||
pos->credit_account->account_name);
|
||||
"payto://x-taler-bank/localhost/%s?receiver-name=%s",
|
||||
pos->credit_account->account_name,
|
||||
pos->credit_account->receiver_name);
|
||||
|
||||
trans = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("row_id",
|
||||
pos->row_id),
|
||||
@ -2156,12 +2254,22 @@ handle_credit_history (struct TALER_FAKEBANK_Handle *h,
|
||||
ha.lp_timeout = GNUNET_TIME_UNIT_ZERO;
|
||||
*con_cls = &special_ptr;
|
||||
acc = lookup_account (h,
|
||||
account);
|
||||
account,
|
||||
NULL);
|
||||
if (NULL == acc)
|
||||
{
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
TALER_EC_BANK_UNKNOWN_ACCOUNT,
|
||||
account);
|
||||
}
|
||||
history = json_array ();
|
||||
GNUNET_assert (NULL != history);
|
||||
GNUNET_asprintf (&credit_payto,
|
||||
"payto://x-taler-bank/localhost/%s",
|
||||
account);
|
||||
"payto://x-taler-bank/localhost/%s?receiver-name=%s",
|
||||
account,
|
||||
acc->receiver_name);
|
||||
|
||||
GNUNET_assert (0 ==
|
||||
pthread_mutex_lock (&h->big_lock));
|
||||
if (! ha.have_start)
|
||||
@ -2194,14 +2302,19 @@ handle_credit_history (struct TALER_FAKEBANK_Handle *h,
|
||||
if ( (NULL == t) ||
|
||||
overflow)
|
||||
{
|
||||
GNUNET_free (credit_payto);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"No transactions available, suspending request\n");
|
||||
GNUNET_free (credit_payto);
|
||||
if (GNUNET_TIME_relative_is_zero (ha.lp_timeout) &&
|
||||
(0 < ha.delta))
|
||||
{
|
||||
GNUNET_assert (0 ==
|
||||
pthread_mutex_unlock (&h->big_lock));
|
||||
if (overflow)
|
||||
return TALER_MHD_reply_with_ec (
|
||||
connection,
|
||||
TALER_EC_BANK_ANCIENT_TRANSACTION_GONE,
|
||||
NULL);
|
||||
return TALER_MHD_REPLY_JSON_PACK (connection,
|
||||
MHD_HTTP_OK,
|
||||
GNUNET_JSON_pack_array_steal (
|
||||
@ -2260,8 +2373,9 @@ handle_credit_history (struct TALER_FAKEBANK_Handle *h,
|
||||
continue;
|
||||
}
|
||||
GNUNET_asprintf (&debit_payto,
|
||||
"payto://x-taler-bank/localhost/%s",
|
||||
pos->debit_account->account_name);
|
||||
"payto://x-taler-bank/localhost/%s?receiver-name=%s",
|
||||
pos->debit_account->account_name,
|
||||
pos->debit_account->receiver_name);
|
||||
trans = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_uint64 ("row_id",
|
||||
pos->row_id),
|
||||
@ -2428,6 +2542,10 @@ handle_mhd_request (void *cls,
|
||||
MHD_RESULT ret;
|
||||
|
||||
(void) version;
|
||||
if (0 == strncmp (url,
|
||||
"/taler-wire-gateway/",
|
||||
strlen ("/taler-wire-gateway/")))
|
||||
url += strlen ("/taler-wire-gateway");
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Handling request for `%s'\n",
|
||||
url);
|
||||
@ -2723,6 +2841,7 @@ TALER_FAKEBANK_start2 (uint16_t port,
|
||||
#else
|
||||
{
|
||||
int pipefd[2];
|
||||
|
||||
if (0 != pipe (pipefd))
|
||||
{
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
|
||||
|
@ -185,14 +185,17 @@ main (int argc,
|
||||
&num_threads),
|
||||
GNUNET_GETOPT_OPTION_END
|
||||
};
|
||||
enum GNUNET_GenericReturnValue iret;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PROGRAM_run (argc, argv,
|
||||
"taler-fakebank-run",
|
||||
"Runs the fakebank",
|
||||
options,
|
||||
&run,
|
||||
NULL))
|
||||
iret = GNUNET_PROGRAM_run (argc, argv,
|
||||
"taler-fakebank-run",
|
||||
"Runs the fakebank",
|
||||
options,
|
||||
&run,
|
||||
NULL);
|
||||
if (GNUNET_SYSERR == iret)
|
||||
return EXIT_INVALIDARGUMENT;
|
||||
if (GNUNET_NO == iret)
|
||||
return EXIT_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ echo -n "Making wire transfer to exchange ..."
|
||||
taler-exchange-wire-gateway-client \
|
||||
-b http://localhost:8899/exchange/ \
|
||||
-S 0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00 \
|
||||
-D payto://x-taler-bank/localhost:8899/user \
|
||||
-D payto://x-taler-bank/localhost:8899/user?receiver-name=user \
|
||||
-a TESTKUDOS:4 > /dev/null
|
||||
echo " OK"
|
||||
|
||||
@ -64,8 +64,9 @@ echo -n "Making wire transfer from exchange..."
|
||||
./taler-exchange-wire-gateway-client \
|
||||
-b http://localhost:8899/exchange/ \
|
||||
-S 0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00 \
|
||||
-C payto://x-taler-bank/localhost:8899/merchant \
|
||||
-a TESTKUDOS:2 > /dev/null
|
||||
-C payto://x-taler-bank/localhost:8899/merchant?receiver-name=merchant \
|
||||
-a TESTKUDOS:2 \
|
||||
-L DEBUG > /dev/null
|
||||
echo " OK"
|
||||
|
||||
|
||||
|
@ -63,5 +63,6 @@ taler_exchange_benchmark_LDADD = \
|
||||
$(XLIB)
|
||||
|
||||
EXTRA_DIST = \
|
||||
benchmark.conf \
|
||||
benchmark-cs.conf \
|
||||
benchmark-rsa.conf \
|
||||
exchange_benchmark_home/.local/share/taler/exchange/offline-keys/master.priv
|
||||
|
@ -143,29 +143,6 @@ make_amount (unsigned int val,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize @a out with an amount given by @a val and
|
||||
* @a frac using the main "currency".
|
||||
*
|
||||
* @param val value to set
|
||||
* @param frac fraction to set
|
||||
* @param[out] out where to write the amount
|
||||
*/
|
||||
static void
|
||||
make_amountN (unsigned int val,
|
||||
unsigned int frac,
|
||||
struct TALER_AmountNBO *out)
|
||||
{
|
||||
struct TALER_Amount in;
|
||||
|
||||
make_amount (val,
|
||||
frac,
|
||||
&in);
|
||||
TALER_amount_hton (out,
|
||||
&in);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create random-ish timestamp.
|
||||
*
|
||||
@ -306,6 +283,9 @@ add_deposit (const struct Merchant *m)
|
||||
d.coin.denom_pub_hash = h_denom_pub;
|
||||
d.coin.denom_sig = denom_sig;
|
||||
RANDOMIZE (&d.h_contract_terms);
|
||||
memset (&d.coin.h_age_commitment,
|
||||
0,
|
||||
sizeof (d.coin.h_age_commitment));
|
||||
|
||||
if (0 >=
|
||||
plugin->ensure_coin_known (plugin->cls,
|
||||
@ -430,7 +410,7 @@ run (void *cls,
|
||||
const char *cfgfile,
|
||||
const struct GNUNET_CONFIGURATION_Handle *c)
|
||||
{
|
||||
struct TALER_EXCHANGEDB_DenominationKeyInformationP issue;
|
||||
struct TALER_EXCHANGEDB_DenominationKeyInformation issue;
|
||||
|
||||
(void) cls;
|
||||
(void) args;
|
||||
@ -466,24 +446,18 @@ run (void *cls,
|
||||
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
|
||||
NULL);
|
||||
RANDOMIZE (&issue.signature);
|
||||
issue.properties.purpose.purpose = htonl (
|
||||
TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY);
|
||||
issue.properties.purpose.size = htonl (sizeof (issue.properties));
|
||||
RANDOMIZE (&issue.properties.master);
|
||||
issue.properties.start
|
||||
= GNUNET_TIME_timestamp_hton (start);
|
||||
issue.properties.expire_withdraw
|
||||
= GNUNET_TIME_timestamp_hton (
|
||||
GNUNET_TIME_absolute_to_timestamp (
|
||||
GNUNET_TIME_absolute_add (start.abs_time,
|
||||
GNUNET_TIME_UNIT_DAYS)));
|
||||
issue.properties.expire_deposit
|
||||
= GNUNET_TIME_timestamp_hton (end);
|
||||
issue.properties.expire_legal
|
||||
= GNUNET_TIME_timestamp_hton (
|
||||
GNUNET_TIME_absolute_to_timestamp (
|
||||
GNUNET_TIME_absolute_add (end.abs_time,
|
||||
GNUNET_TIME_UNIT_YEARS)));
|
||||
issue.start
|
||||
= start;
|
||||
issue.expire_withdraw
|
||||
= GNUNET_TIME_absolute_to_timestamp (
|
||||
GNUNET_TIME_absolute_add (start.abs_time,
|
||||
GNUNET_TIME_UNIT_DAYS));
|
||||
issue.expire_deposit
|
||||
= end;
|
||||
issue.expire_legal
|
||||
= GNUNET_TIME_absolute_to_timestamp (
|
||||
GNUNET_TIME_absolute_add (end.abs_time,
|
||||
GNUNET_TIME_UNIT_YEARS));
|
||||
{
|
||||
struct TALER_DenominationPrivateKey pk;
|
||||
struct TALER_DenominationPublicKey denom_pub;
|
||||
@ -505,12 +479,12 @@ run (void *cls,
|
||||
alg_values.cipher = TALER_DENOMINATION_RSA;
|
||||
TALER_denom_pub_hash (&denom_pub,
|
||||
&h_denom_pub);
|
||||
make_amountN (2, 0, &issue.properties.value);
|
||||
make_amountN (0, 5, &issue.properties.fees.withdraw);
|
||||
make_amountN (0, 5, &issue.properties.fees.deposit);
|
||||
make_amountN (0, 5, &issue.properties.fees.refresh);
|
||||
make_amountN (0, 5, &issue.properties.fees.refund);
|
||||
issue.properties.denom_hash = h_denom_pub;
|
||||
make_amount (2, 0, &issue.value);
|
||||
make_amount (0, 5, &issue.fees.withdraw);
|
||||
make_amount (0, 5, &issue.fees.deposit);
|
||||
make_amount (0, 5, &issue.fees.refresh);
|
||||
make_amount (0, 5, &issue.fees.refund);
|
||||
issue.denom_hash = h_denom_pub;
|
||||
if (0 >=
|
||||
plugin->insert_denomination_info (plugin->cls,
|
||||
&denom_pub,
|
||||
@ -528,20 +502,21 @@ run (void *cls,
|
||||
&bks);
|
||||
|
||||
{
|
||||
uint64_t seed;
|
||||
struct GNUNET_HashCode seed;
|
||||
struct TALER_AgeMask mask = {
|
||||
.bits = 1 || 1 << 8 || 1 << 12 || 1 << 16 || 1 << 18
|
||||
};
|
||||
struct TALER_AgeCommitmentProof acp = {0};
|
||||
|
||||
seed = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
UINT64_MAX);
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||
&seed,
|
||||
sizeof(seed));
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_age_restriction_commit (
|
||||
&mask,
|
||||
13,
|
||||
seed,
|
||||
&seed,
|
||||
&acp));
|
||||
|
||||
TALER_age_commitment_hash (&acp.commitment, &hac);
|
||||
@ -574,7 +549,7 @@ run (void *cls,
|
||||
}
|
||||
|
||||
{
|
||||
struct TALER_Amount wire_fee;
|
||||
struct TALER_WireFeeSet fees;
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
unsigned int year;
|
||||
struct GNUNET_TIME_Timestamp ws;
|
||||
@ -585,7 +560,9 @@ run (void *cls,
|
||||
{
|
||||
ws = GNUNET_TIME_absolute_to_timestamp (GNUNET_TIME_year_to_time (y - 1));
|
||||
we = GNUNET_TIME_absolute_to_timestamp (GNUNET_TIME_year_to_time (y));
|
||||
make_amount (0, 5, &wire_fee);
|
||||
make_amount (0, 5, &fees.wire);
|
||||
make_amount (0, 5, &fees.wad);
|
||||
make_amount (0, 5, &fees.closing);
|
||||
memset (&master_sig,
|
||||
0,
|
||||
sizeof (master_sig));
|
||||
@ -594,8 +571,7 @@ run (void *cls,
|
||||
"x-taler-bank",
|
||||
ws,
|
||||
we,
|
||||
&wire_fee,
|
||||
&wire_fee,
|
||||
&fees,
|
||||
&master_sig))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
|
@ -111,9 +111,9 @@ static char *cfg_filename;
|
||||
static int use_fakebank = 1;
|
||||
|
||||
/**
|
||||
* Launch taler-exchange-wirewatch.
|
||||
* Number of taler-exchange-wirewatchers to launch.
|
||||
*/
|
||||
static int start_wirewatch;
|
||||
static unsigned int start_wirewatch;
|
||||
|
||||
/**
|
||||
* Verbosity level.
|
||||
@ -265,8 +265,9 @@ run (void *cls,
|
||||
|
||||
(void) cls;
|
||||
len = howmany_reserves + 2;
|
||||
all_commands = GNUNET_new_array (len,
|
||||
struct TALER_TESTING_Command);
|
||||
all_commands = GNUNET_malloc_large (len
|
||||
* sizeof (struct TALER_TESTING_Command));
|
||||
GNUNET_assert (NULL != all_commands);
|
||||
GNUNET_asprintf (&total_reserve_amount,
|
||||
"%s:5",
|
||||
currency);
|
||||
@ -465,14 +466,17 @@ launch_fakebank (void *cls)
|
||||
*
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static int
|
||||
static enum GNUNET_GenericReturnValue
|
||||
parallel_benchmark (void)
|
||||
{
|
||||
enum GNUNET_GenericReturnValue result = GNUNET_OK;
|
||||
pid_t fakebank = -1;
|
||||
struct GNUNET_OS_Process *bankd = NULL;
|
||||
struct GNUNET_OS_Process *wirewatch = NULL;
|
||||
struct GNUNET_OS_Process *wirewatch[GNUNET_NZL (start_wirewatch)];
|
||||
|
||||
memset (wirewatch,
|
||||
0,
|
||||
sizeof (wirewatch));
|
||||
if ( (MODE_BANK == mode) ||
|
||||
(MODE_BOTH == mode) )
|
||||
{
|
||||
@ -560,19 +564,30 @@ parallel_benchmark (void)
|
||||
GNUNET_OS_process_wait (dbinit));
|
||||
GNUNET_OS_process_destroy (dbinit);
|
||||
}
|
||||
if (start_wirewatch)
|
||||
/* start exchange wirewatch */
|
||||
for (unsigned int w = 0; w<start_wirewatch; w++)
|
||||
{
|
||||
/* start exchange wirewatch */
|
||||
wirewatch = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-wirewatch",
|
||||
"taler-exchange-wirewatch",
|
||||
"-c", cfg_filename,
|
||||
NULL);
|
||||
if (NULL == wirewatch)
|
||||
wirewatch[w] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-wirewatch",
|
||||
"taler-exchange-wirewatch",
|
||||
"-c", cfg_filename,
|
||||
"-L", loglev,
|
||||
NULL);
|
||||
if (NULL == wirewatch[w])
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to launch wirewatch, aborting benchmark\n");
|
||||
for (unsigned int x = 0; x<w; x++)
|
||||
{
|
||||
GNUNET_break (0 ==
|
||||
GNUNET_OS_process_kill (wirewatch[x],
|
||||
SIGTERM));
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_OS_process_wait (wirewatch[x]));
|
||||
GNUNET_OS_process_destroy (wirewatch[x]);
|
||||
wirewatch[x] = NULL;
|
||||
}
|
||||
if (-1 != fakebank)
|
||||
{
|
||||
int wstatus;
|
||||
@ -618,17 +633,61 @@ parallel_benchmark (void)
|
||||
if ( (MODE_BANK == mode) ||
|
||||
(MODE_BOTH == mode) )
|
||||
{
|
||||
if (NULL != wirewatch)
|
||||
/* Ensure wirewatch runs to completion! */
|
||||
if (0 != start_wirewatch)
|
||||
{
|
||||
/* stop wirewatch */
|
||||
/* replace ONE of the wirewatchers with one that is in test-mode */
|
||||
GNUNET_break (0 ==
|
||||
GNUNET_OS_process_kill (wirewatch,
|
||||
GNUNET_OS_process_kill (wirewatch[0],
|
||||
SIGTERM));
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_OS_process_wait (wirewatch));
|
||||
GNUNET_OS_process_destroy (wirewatch);
|
||||
wirewatch = NULL;
|
||||
GNUNET_OS_process_wait (wirewatch[0]));
|
||||
GNUNET_OS_process_destroy (wirewatch[0]);
|
||||
wirewatch[0] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-wirewatch",
|
||||
"taler-exchange-wirewatch",
|
||||
"-c", cfg_filename,
|
||||
"-L", loglev,
|
||||
"-t",
|
||||
NULL);
|
||||
/* wait for it to finish! */
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_OS_process_wait (wirewatch[0]));
|
||||
GNUNET_OS_process_destroy (wirewatch[0]);
|
||||
wirewatch[0] = NULL;
|
||||
/* Then stop the rest, which should basically also be finished */
|
||||
for (unsigned int w = 1; w<start_wirewatch; w++)
|
||||
{
|
||||
GNUNET_break (0 ==
|
||||
GNUNET_OS_process_kill (wirewatch[w],
|
||||
SIGTERM));
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_OS_process_wait (wirewatch[w]));
|
||||
GNUNET_OS_process_destroy (wirewatch[w]);
|
||||
}
|
||||
|
||||
/* But be extra sure we did finish all shards by doing one more */
|
||||
wirewatch[0] = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
|
||||
NULL, NULL, NULL,
|
||||
"taler-exchange-wirewatch",
|
||||
"taler-exchange-wirewatch",
|
||||
"-c", cfg_filename,
|
||||
"-L", loglev,
|
||||
"-t",
|
||||
NULL);
|
||||
/* wait for it to finish! */
|
||||
GNUNET_break (GNUNET_OK ==
|
||||
GNUNET_OS_process_wait (wirewatch[0]));
|
||||
GNUNET_OS_process_destroy (wirewatch[0]);
|
||||
wirewatch[0] = NULL;
|
||||
}
|
||||
|
||||
/* Now stop the time, if this was the right mode */
|
||||
if ( (GNUNET_YES != linger) &&
|
||||
(MODE_BANK != mode) )
|
||||
duration = GNUNET_TIME_absolute_get_duration (start_time);
|
||||
|
||||
/* stop fakebank */
|
||||
if (-1 != fakebank)
|
||||
{
|
||||
@ -727,9 +786,10 @@ main (int argc,
|
||||
&history_size),
|
||||
GNUNET_GETOPT_option_version (PACKAGE_VERSION " " VCS_VERSION),
|
||||
GNUNET_GETOPT_option_verbose (&verbose),
|
||||
GNUNET_GETOPT_option_flag ('w',
|
||||
GNUNET_GETOPT_option_uint ('w',
|
||||
"wirewatch",
|
||||
"run taler-exchange-wirewatch",
|
||||
"NPROC",
|
||||
"run NPROC taler-exchange-wirewatch processes",
|
||||
&start_wirewatch),
|
||||
GNUNET_GETOPT_OPTION_END
|
||||
};
|
||||
@ -858,14 +918,17 @@ main (int argc,
|
||||
howmany_clients,
|
||||
GNUNET_STRINGS_relative_time_to_string (duration,
|
||||
GNUNET_YES));
|
||||
tps = ((unsigned long long) howmany_reserves) * howmany_clients * 1000LLU
|
||||
/ (duration.rel_value_us / 1000LL);
|
||||
fprintf (stdout,
|
||||
"RAW: %04u %04u %16llu (%llu TPS)\n",
|
||||
howmany_reserves,
|
||||
howmany_clients,
|
||||
(unsigned long long) duration.rel_value_us,
|
||||
tps);
|
||||
if (! GNUNET_TIME_relative_is_zero (duration))
|
||||
{
|
||||
tps = ((unsigned long long) howmany_reserves) * howmany_clients * 1000LLU
|
||||
/ (duration.rel_value_us / 1000LL);
|
||||
fprintf (stdout,
|
||||
"RAW: %04u %04u %16llu (%llu TPS)\n",
|
||||
howmany_reserves,
|
||||
howmany_clients,
|
||||
(unsigned long long) duration.rel_value_us,
|
||||
tps);
|
||||
}
|
||||
fprintf (stdout,
|
||||
"CPU time: sys %llu user %llu\n", \
|
||||
(unsigned long long) (usage.ru_stime.tv_sec * 1000 * 1000
|
||||
|
@ -68,7 +68,6 @@ taler_crypto_worker_LDADD = \
|
||||
-lgnunetutil \
|
||||
-lgnunetjson \
|
||||
-ljansson \
|
||||
-lpthread \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(XLIB)
|
||||
|
||||
|
@ -93,6 +93,76 @@ run (void *cls,
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"got request\n");
|
||||
if (0 == strcmp ("eddsa_get_public",
|
||||
op))
|
||||
{
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub;
|
||||
struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv;
|
||||
json_t *resp;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("eddsa_priv",
|
||||
&eddsa_priv),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
if (GNUNET_OK != GNUNET_JSON_parse (args,
|
||||
spec,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"malformed op args\n");
|
||||
global_ret = 1;
|
||||
return;
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&eddsa_priv,
|
||||
&eddsa_pub);
|
||||
resp = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("eddsa_pub",
|
||||
&eddsa_pub)
|
||||
);
|
||||
json_dumpf (resp, stdout, JSON_COMPACT);
|
||||
printf ("\n");
|
||||
fflush (stdout);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"sent response\n");
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
continue;
|
||||
}
|
||||
if (0 == strcmp ("ecdhe_get_public",
|
||||
op))
|
||||
{
|
||||
struct GNUNET_CRYPTO_EcdhePublicKey ecdhe_pub;
|
||||
struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_priv;
|
||||
json_t *resp;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("ecdhe_priv",
|
||||
&ecdhe_priv),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
if (GNUNET_OK != GNUNET_JSON_parse (args,
|
||||
spec,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"malformed op args\n");
|
||||
global_ret = 1;
|
||||
return;
|
||||
}
|
||||
GNUNET_CRYPTO_ecdhe_key_get_public (&ecdhe_priv,
|
||||
&ecdhe_pub);
|
||||
resp = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("ecdhe_pub",
|
||||
&ecdhe_pub)
|
||||
);
|
||||
json_dumpf (resp, stdout, JSON_COMPACT);
|
||||
printf ("\n");
|
||||
fflush (stdout);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"sent response\n");
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
continue;
|
||||
}
|
||||
if (0 == strcmp ("eddsa_verify",
|
||||
op))
|
||||
{
|
||||
@ -135,6 +205,53 @@ run (void *cls,
|
||||
fflush (stdout);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"sent response\n");
|
||||
GNUNET_JSON_parse_free (eddsa_verify_spec);
|
||||
continue;
|
||||
}
|
||||
if (0 == strcmp ("kx_ecdhe_eddsa",
|
||||
op))
|
||||
{
|
||||
struct GNUNET_CRYPTO_EcdhePrivateKey priv;
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey pub;
|
||||
struct GNUNET_HashCode key_material;
|
||||
json_t *resp;
|
||||
struct GNUNET_JSON_Specification kx_spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("eddsa_pub",
|
||||
&pub),
|
||||
GNUNET_JSON_spec_fixed_auto ("ecdhe_priv",
|
||||
&priv),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
if (GNUNET_OK != GNUNET_JSON_parse (args,
|
||||
kx_spec,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"malformed op args\n");
|
||||
global_ret = 1;
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK != GNUNET_CRYPTO_ecdh_eddsa (&priv,
|
||||
&pub,
|
||||
&key_material))
|
||||
{
|
||||
// FIXME: Return as result?
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"kx failed\n");
|
||||
global_ret = 1;
|
||||
return;
|
||||
}
|
||||
resp = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("h",
|
||||
&key_material)
|
||||
);
|
||||
json_dumpf (resp, stdout, JSON_COMPACT);
|
||||
printf ("\n");
|
||||
fflush (stdout);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"sent response\n");
|
||||
GNUNET_JSON_parse_free (kx_spec);
|
||||
continue;
|
||||
}
|
||||
if (0 == strcmp ("eddsa_sign",
|
||||
@ -153,32 +270,34 @@ run (void *cls,
|
||||
&msg_size),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
if (GNUNET_OK != GNUNET_JSON_parse (args,
|
||||
eddsa_sign_spec,
|
||||
NULL,
|
||||
NULL))
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (args,
|
||||
eddsa_sign_spec,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"malformed op args\n");
|
||||
global_ret = 1;
|
||||
return;
|
||||
}
|
||||
GNUNET_CRYPTO_eddsa_sign_ (
|
||||
&priv,
|
||||
msg,
|
||||
&sig
|
||||
);
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
GNUNET_CRYPTO_eddsa_sign_ (
|
||||
&priv,
|
||||
msg,
|
||||
&sig));
|
||||
resp = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("sig", &sig)
|
||||
);
|
||||
json_dumpf (resp, stdout, JSON_COMPACT);
|
||||
json_dumpf (resp, stdout,
|
||||
JSON_COMPACT);
|
||||
printf ("\n");
|
||||
fflush (stdout);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"sent response\n");
|
||||
GNUNET_JSON_parse_free (eddsa_sign_spec);
|
||||
continue;
|
||||
}
|
||||
#if FIXME_FLORIAN
|
||||
if (0 == strcmp ("setup_refresh_planchet", op))
|
||||
{
|
||||
struct TALER_TransferSecretP transfer_secret;
|
||||
@ -192,7 +311,13 @@ run (void *cls,
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
struct TALER_PlanchetSecretsP ps;
|
||||
struct TALER_CoinSpendPrivateKeyP coin_priv;
|
||||
struct TALER_PlanchetMasterSecretP ps;
|
||||
struct TALER_ExchangeWithdrawValues alg_values = {
|
||||
// FIXME: also allow CS
|
||||
.cipher = TALER_DENOMINATION_RSA,
|
||||
};
|
||||
union TALER_DenominationBlindingKeyP dbk;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (args,
|
||||
@ -208,22 +333,90 @@ run (void *cls,
|
||||
TALER_transfer_secret_to_planchet_secret (&transfer_secret,
|
||||
coin_index,
|
||||
&ps);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&ps.coin_priv.eddsa_priv,
|
||||
TALER_planchet_setup_coin_priv (&ps,
|
||||
&alg_values,
|
||||
&coin_priv);
|
||||
GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv,
|
||||
&coin_pub.eddsa_pub);
|
||||
TALER_planchet_blinding_secret_create (&ps,
|
||||
&alg_values,
|
||||
&dbk);
|
||||
|
||||
resp = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_auto ("coin_priv", &ps.coin_priv),
|
||||
GNUNET_JSON_pack_data_auto ("coin_priv", &coin_priv),
|
||||
GNUNET_JSON_pack_data_auto ("coin_pub", &coin_pub),
|
||||
GNUNET_JSON_pack_data_auto ("blinding_key", &ps.blinding_key)
|
||||
GNUNET_JSON_pack_data_auto ("blinding_key", &dbk.rsa_bks)
|
||||
);
|
||||
json_dumpf (resp, stdout, JSON_COMPACT);
|
||||
printf ("\n");
|
||||
fflush (stdout);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"sent response\n");
|
||||
GNUNET_JSON_parse_free (setup_refresh_planchet_spec);
|
||||
continue;
|
||||
}
|
||||
if (0 == strcmp ("rsa_blind", op))
|
||||
{
|
||||
struct GNUNET_HashCode hm;
|
||||
struct GNUNET_CRYPTO_RsaBlindingKeySecret bks;
|
||||
void *pub_enc;
|
||||
size_t pub_enc_size;
|
||||
int success;
|
||||
struct GNUNET_CRYPTO_RsaPublicKey *pub;
|
||||
void *blinded_buf;
|
||||
size_t blinded_size;
|
||||
json_t *resp;
|
||||
struct GNUNET_JSON_Specification rsa_blind_spec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("hm",
|
||||
&hm),
|
||||
GNUNET_JSON_spec_fixed_auto ("bks",
|
||||
&bks),
|
||||
GNUNET_JSON_spec_varsize ("pub",
|
||||
&pub_enc,
|
||||
&pub_enc_size),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (args,
|
||||
rsa_blind_spec,
|
||||
NULL,
|
||||
NULL))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"malformed op args\n");
|
||||
global_ret = 1;
|
||||
return;
|
||||
}
|
||||
pub = GNUNET_CRYPTO_rsa_public_key_decode (pub_enc,
|
||||
pub_enc_size);
|
||||
success = GNUNET_CRYPTO_rsa_blind (&hm,
|
||||
&bks,
|
||||
pub,
|
||||
&blinded_buf,
|
||||
&blinded_size);
|
||||
|
||||
if (GNUNET_YES == success)
|
||||
{
|
||||
resp = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_data_varsize ("blinded", blinded_buf, blinded_size),
|
||||
GNUNET_JSON_pack_bool ("success", true)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
resp = GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_bool ("success", false)
|
||||
);
|
||||
}
|
||||
json_dumpf (resp, stdout, JSON_COMPACT);
|
||||
printf ("\n");
|
||||
fflush (stdout);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"sent response\n");
|
||||
GNUNET_JSON_parse_free (rsa_blind_spec);
|
||||
GNUNET_free (blinded_buf);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"unsupported operation '%s'\n",
|
||||
op);
|
||||
|
@ -44,6 +44,30 @@ static int clear_shards;
|
||||
*/
|
||||
static int gc_db;
|
||||
|
||||
/**
|
||||
* -P option: setup a partitioned database
|
||||
*/
|
||||
static uint32_t num_partitions;
|
||||
|
||||
/**
|
||||
* -F option: setup a sharded database, i.e. create foreign tables/server
|
||||
*/
|
||||
static int shard_db;
|
||||
|
||||
/**
|
||||
* -f option: force partitions to be created when there is only one
|
||||
*/
|
||||
static int force_create_partitions;
|
||||
|
||||
/**
|
||||
* -S option: setup a database on a shard server, creates tables with suffix shard_idx
|
||||
*/
|
||||
static uint32_t shard_idx;
|
||||
|
||||
/**
|
||||
* -R option: do full shard DB reset
|
||||
*/
|
||||
static uint32_t reset_shard_db;
|
||||
|
||||
/**
|
||||
* Main function that will be run.
|
||||
@ -80,6 +104,35 @@ run (void *cls,
|
||||
"Could not drop tables as requested. Either database was not yet initialized, or permission denied. Consult the logs. Will still try to create new tables.\n");
|
||||
}
|
||||
}
|
||||
if (0 <
|
||||
reset_shard_db)
|
||||
{
|
||||
if (GNUNET_OK != plugin->drop_shard_tables (plugin->cls, reset_shard_db))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Could not drop shard tables as requested. Either database was not yet initialized or permission denied. Consult the logs.\n");
|
||||
global_ret = EXIT_FAILURE;
|
||||
return;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||
"Dropped shard database, please call taler-exchange-dbinit -S <N> to initialize a new shard database\n");
|
||||
return;
|
||||
}
|
||||
if (0 <
|
||||
shard_idx)
|
||||
{
|
||||
if (GNUNET_OK != plugin->create_shard_tables (plugin->cls,
|
||||
shard_idx))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Could not create shard database\n");
|
||||
global_ret = EXIT_NOTINSTALLED;
|
||||
}
|
||||
/* We do not want to continue if we are on a shard */
|
||||
TALER_EXCHANGEDB_plugin_unload (plugin);
|
||||
plugin = NULL;
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
plugin->create_tables (plugin->cls))
|
||||
{
|
||||
@ -90,6 +143,38 @@ run (void *cls,
|
||||
global_ret = EXIT_NOPERMISSION;
|
||||
return;
|
||||
}
|
||||
if (1 <
|
||||
num_partitions
|
||||
|| (
|
||||
1 == num_partitions
|
||||
&& force_create_partitions))
|
||||
{
|
||||
enum GNUNET_GenericReturnValue r = GNUNET_OK;
|
||||
if (shard_db)
|
||||
{
|
||||
r = plugin->setup_foreign_servers (plugin->cls,
|
||||
num_partitions);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = plugin->setup_partitions (plugin->cls,
|
||||
num_partitions);
|
||||
}
|
||||
if (GNUNET_OK != r)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Could not setup partitions. Dropping default ones again\n");
|
||||
if (GNUNET_OK != plugin->drop_tables (plugin->cls))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Could not drop tables after failed partitioning, please delete the DB manually\n");
|
||||
}
|
||||
TALER_EXCHANGEDB_plugin_unload (plugin);
|
||||
plugin = NULL;
|
||||
global_ret = EXIT_NOTINSTALLED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (gc_db || clear_shards)
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
@ -150,6 +235,29 @@ main (int argc,
|
||||
"shardunlock",
|
||||
"unlock all revolving shard locks (use after system crash or shard size change while services are not running)",
|
||||
&clear_shards),
|
||||
GNUNET_GETOPT_option_uint ('P',
|
||||
"partition",
|
||||
"NUMBER",
|
||||
"Setup a partitioned database where each table which can be partitioned holds NUMBER partitions on a single DB node (NOTE: sharding add -F for sharding)",
|
||||
&num_partitions),
|
||||
GNUNET_GETOPT_option_flag ('F',
|
||||
"foreign",
|
||||
"Setup a sharded database with foreign servers (shards) / tables rather than a partitioned one, must be called as DB superuser.",
|
||||
&shard_db),
|
||||
GNUNET_GETOPT_option_uint ('S',
|
||||
"shard",
|
||||
"INDEX",
|
||||
"Setup a shard server, creates tables with INDEX as suffix",
|
||||
&shard_idx),
|
||||
GNUNET_GETOPT_option_uint ('R',
|
||||
"reset-shard",
|
||||
"OLD_SHARD_IDX",
|
||||
"reset a shard database, does not reinitialize i.e. call taler-exchange-dbinit -S afterwards (DANGEROUS: all existsing data is lost!)",
|
||||
&reset_shard_db),
|
||||
GNUNET_GETOPT_option_flag ('f',
|
||||
"force",
|
||||
"Force partitions to be created if there is only one partition",
|
||||
&force_create_partitions),
|
||||
GNUNET_GETOPT_OPTION_END
|
||||
};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
@ -67,6 +67,13 @@
|
||||
*/
|
||||
#define OP_SET_WIRE_FEE "exchange-set-wire-fee-0"
|
||||
|
||||
/**
|
||||
* Name of the operation to set a 'global-fee'
|
||||
* The last component --by convention-- identifies the protocol version
|
||||
* and should be incremented whenever the JSON format of the 'argument' changes.
|
||||
*/
|
||||
#define OP_SET_GLOBAL_FEE "exchange-set-global-fee-0"
|
||||
|
||||
/**
|
||||
* Name of the operation to 'upload' key signatures
|
||||
* The last component --by convention-- identifies the protocol version
|
||||
@ -377,6 +384,34 @@ struct WireFeeRequest
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Data structure for announcing global fees.
|
||||
*/
|
||||
struct GlobalFeeRequest
|
||||
{
|
||||
|
||||
/**
|
||||
* Kept in a DLL.
|
||||
*/
|
||||
struct GlobalFeeRequest *next;
|
||||
|
||||
/**
|
||||
* Kept in a DLL.
|
||||
*/
|
||||
struct GlobalFeeRequest *prev;
|
||||
|
||||
/**
|
||||
* Operation handle.
|
||||
*/
|
||||
struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle *h;
|
||||
|
||||
/**
|
||||
* Array index of the associated command.
|
||||
*/
|
||||
size_t idx;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Ongoing /keys request.
|
||||
*/
|
||||
@ -510,6 +545,16 @@ static struct WireFeeRequest *wfr_head;
|
||||
*/
|
||||
static struct WireFeeRequest *wfr_tail;
|
||||
|
||||
/**
|
||||
* Active global fee requests.
|
||||
*/
|
||||
static struct GlobalFeeRequest *gfr_head;
|
||||
|
||||
/**
|
||||
* Active global fee requests.
|
||||
*/
|
||||
static struct GlobalFeeRequest *gfr_tail;
|
||||
|
||||
/**
|
||||
* Active keys upload requests.
|
||||
*/
|
||||
@ -646,6 +691,21 @@ do_shutdown (void *cls)
|
||||
GNUNET_free (wfr);
|
||||
}
|
||||
}
|
||||
{
|
||||
struct GlobalFeeRequest *gfr;
|
||||
|
||||
while (NULL != (gfr = gfr_head))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Aborting incomplete global fee #%u\n",
|
||||
(unsigned int) gfr->idx);
|
||||
TALER_EXCHANGE_management_set_global_fees_cancel (gfr->h);
|
||||
GNUNET_CONTAINER_DLL_remove (gfr_head,
|
||||
gfr_tail,
|
||||
gfr);
|
||||
GNUNET_free (gfr);
|
||||
}
|
||||
}
|
||||
{
|
||||
struct UploadKeysRequest *ukr;
|
||||
|
||||
@ -727,6 +787,7 @@ test_shutdown (void)
|
||||
(NULL == war_head) &&
|
||||
(NULL == wdr_head) &&
|
||||
(NULL == wfr_head) &&
|
||||
(NULL == gfr_head) &&
|
||||
(NULL == ukr_head) &&
|
||||
(NULL == uer_head) &&
|
||||
(NULL == mgkh) &&
|
||||
@ -1334,6 +1395,20 @@ upload_wire_add (const char *exchange_url,
|
||||
}
|
||||
GNUNET_free (wire_method);
|
||||
}
|
||||
{
|
||||
char *msg = TALER_payto_validate (payto_uri);
|
||||
|
||||
if (NULL != msg)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"payto URI is malformed: %s\n",
|
||||
msg);
|
||||
GNUNET_free (msg);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
war = GNUNET_new (struct WireAddRequest);
|
||||
war->idx = idx;
|
||||
war->h =
|
||||
@ -1491,8 +1566,7 @@ upload_wire_fee (const char *exchange_url,
|
||||
struct WireFeeRequest *wfr;
|
||||
const char *err_name;
|
||||
unsigned int err_line;
|
||||
struct TALER_Amount wire_fee;
|
||||
struct TALER_Amount closing_fee;
|
||||
struct TALER_WireFeeSet fees;
|
||||
struct GNUNET_TIME_Timestamp start_time;
|
||||
struct GNUNET_TIME_Timestamp end_time;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
@ -1500,10 +1574,13 @@ upload_wire_fee (const char *exchange_url,
|
||||
&wire_method),
|
||||
TALER_JSON_spec_amount ("wire_fee",
|
||||
currency,
|
||||
&wire_fee),
|
||||
&fees.wire),
|
||||
TALER_JSON_spec_amount ("wad_fee",
|
||||
currency,
|
||||
&fees.wad),
|
||||
TALER_JSON_spec_amount ("closing_fee",
|
||||
currency,
|
||||
&closing_fee),
|
||||
&fees.closing),
|
||||
GNUNET_JSON_spec_timestamp ("start_time",
|
||||
&start_time),
|
||||
GNUNET_JSON_spec_timestamp ("end_time",
|
||||
@ -1539,8 +1616,7 @@ upload_wire_fee (const char *exchange_url,
|
||||
wire_method,
|
||||
start_time,
|
||||
end_time,
|
||||
&wire_fee,
|
||||
&closing_fee,
|
||||
&fees,
|
||||
&master_sig,
|
||||
&wire_fee_cb,
|
||||
wfr);
|
||||
@ -1550,6 +1626,129 @@ upload_wire_fee (const char *exchange_url,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with information about the post global fee operation result.
|
||||
*
|
||||
* @param cls closure with a `struct WireFeeRequest`
|
||||
* @param hr HTTP response data
|
||||
*/
|
||||
static void
|
||||
global_fee_cb (
|
||||
void *cls,
|
||||
const struct TALER_EXCHANGE_HttpResponse *hr)
|
||||
{
|
||||
struct GlobalFeeRequest *gfr = cls;
|
||||
|
||||
if (MHD_HTTP_NO_CONTENT != hr->http_status)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Upload failed for command %u with status %u: %s (%s)\n",
|
||||
(unsigned int) gfr->idx,
|
||||
hr->http_status,
|
||||
TALER_ErrorCode_get_hint (hr->ec),
|
||||
hr->hint);
|
||||
global_ret = EXIT_FAILURE;
|
||||
}
|
||||
GNUNET_CONTAINER_DLL_remove (gfr_head,
|
||||
gfr_tail,
|
||||
gfr);
|
||||
GNUNET_free (gfr);
|
||||
test_shutdown ();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Upload global fee.
|
||||
*
|
||||
* @param exchange_url base URL of the exchange
|
||||
* @param idx index of the operation we are performing (for logging)
|
||||
* @param value arguments for denomination revocation
|
||||
*/
|
||||
static void
|
||||
upload_global_fee (const char *exchange_url,
|
||||
size_t idx,
|
||||
const json_t *value)
|
||||
{
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
struct GlobalFeeRequest *gfr;
|
||||
const char *err_name;
|
||||
unsigned int err_line;
|
||||
struct TALER_GlobalFeeSet fees;
|
||||
struct GNUNET_TIME_Timestamp start_time;
|
||||
struct GNUNET_TIME_Timestamp end_time;
|
||||
struct GNUNET_TIME_Relative purse_timeout;
|
||||
struct GNUNET_TIME_Relative kyc_timeout;
|
||||
struct GNUNET_TIME_Relative history_expiration;
|
||||
uint32_t purse_account_limit;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_amount ("history_fee",
|
||||
currency,
|
||||
&fees.history),
|
||||
TALER_JSON_spec_amount ("kyc_fee",
|
||||
currency,
|
||||
&fees.kyc),
|
||||
TALER_JSON_spec_amount ("account_fee",
|
||||
currency,
|
||||
&fees.account),
|
||||
TALER_JSON_spec_amount ("purse_fee",
|
||||
currency,
|
||||
&fees.purse),
|
||||
GNUNET_JSON_spec_relative_time ("purse_timeout",
|
||||
&purse_timeout),
|
||||
GNUNET_JSON_spec_relative_time ("kyc_timeout",
|
||||
&kyc_timeout),
|
||||
GNUNET_JSON_spec_relative_time ("history_expiration",
|
||||
&history_expiration),
|
||||
GNUNET_JSON_spec_uint32 ("purse_account_limit",
|
||||
&purse_account_limit),
|
||||
GNUNET_JSON_spec_timestamp ("start_time",
|
||||
&start_time),
|
||||
GNUNET_JSON_spec_timestamp ("end_time",
|
||||
&end_time),
|
||||
GNUNET_JSON_spec_fixed_auto ("master_sig",
|
||||
&master_sig),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_JSON_parse (value,
|
||||
spec,
|
||||
&err_name,
|
||||
&err_line))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Invalid input to set wire fee: %s#%u at %u (skipping)\n",
|
||||
err_name,
|
||||
err_line,
|
||||
(unsigned int) idx);
|
||||
json_dumpf (value,
|
||||
stderr,
|
||||
JSON_INDENT (2));
|
||||
global_ret = EXIT_FAILURE;
|
||||
test_shutdown ();
|
||||
return;
|
||||
}
|
||||
gfr = GNUNET_new (struct GlobalFeeRequest);
|
||||
gfr->idx = idx;
|
||||
gfr->h =
|
||||
TALER_EXCHANGE_management_set_global_fees (ctx,
|
||||
exchange_url,
|
||||
start_time,
|
||||
end_time,
|
||||
&fees,
|
||||
purse_timeout,
|
||||
kyc_timeout,
|
||||
history_expiration,
|
||||
purse_account_limit,
|
||||
&master_sig,
|
||||
&global_fee_cb,
|
||||
gfr);
|
||||
GNUNET_CONTAINER_DLL_insert (gfr_head,
|
||||
gfr_tail,
|
||||
gfr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with information about the post upload keys operation result.
|
||||
*
|
||||
@ -1891,6 +2090,10 @@ trigger_upload (const char *exchange_url)
|
||||
.key = OP_SET_WIRE_FEE,
|
||||
.cb = &upload_wire_fee
|
||||
},
|
||||
{
|
||||
.key = OP_SET_GLOBAL_FEE,
|
||||
.cb = &upload_global_fee
|
||||
},
|
||||
{
|
||||
.key = OP_UPLOAD_SIGS,
|
||||
.cb = &upload_keys
|
||||
@ -2271,6 +2474,20 @@ do_add_wire (char *const *args)
|
||||
if (GNUNET_OK !=
|
||||
load_offline_key (GNUNET_NO))
|
||||
return;
|
||||
{
|
||||
char *msg = TALER_payto_validate (args[0]);
|
||||
|
||||
if (NULL != msg)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"payto URI is malformed: %s\n",
|
||||
msg);
|
||||
GNUNET_free (msg);
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
}
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
{
|
||||
char *wire_method;
|
||||
@ -2360,8 +2577,8 @@ do_del_wire (char *const *args)
|
||||
* Set wire fees for the given year.
|
||||
*
|
||||
* @param args the array of command-line arguments to process next;
|
||||
* args[0] must be the year, args[1] the wire fee and args[2]
|
||||
* the closing fee.
|
||||
* args[0] must be the year, args[1] the wire method, args[2] the wire fee and args[3]
|
||||
* the closing fee and args[4] the wad fee.
|
||||
*/
|
||||
static void
|
||||
do_set_wire_fee (char *const *args)
|
||||
@ -2369,8 +2586,7 @@ do_set_wire_fee (char *const *args)
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
char dummy;
|
||||
unsigned int year;
|
||||
struct TALER_Amount wire_fee;
|
||||
struct TALER_Amount closing_fee;
|
||||
struct TALER_WireFeeSet fees;
|
||||
struct GNUNET_TIME_Timestamp start_time;
|
||||
struct GNUNET_TIME_Timestamp end_time;
|
||||
|
||||
@ -2386,6 +2602,7 @@ do_set_wire_fee (char *const *args)
|
||||
(NULL == args[1]) ||
|
||||
(NULL == args[2]) ||
|
||||
(NULL == args[3]) ||
|
||||
(NULL == args[4]) ||
|
||||
( (1 != sscanf (args[0],
|
||||
"%u%c",
|
||||
&year,
|
||||
@ -2394,13 +2611,16 @@ do_set_wire_fee (char *const *args)
|
||||
args[0])) ) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_string_to_amount (args[2],
|
||||
&wire_fee)) ||
|
||||
&fees.wire)) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_string_to_amount (args[3],
|
||||
&closing_fee)) )
|
||||
&fees.closing)) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_string_to_amount (args[4],
|
||||
&fees.wad)) )
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"You must use YEAR, METHOD, WIRE-FEE and CLOSING-FEE as arguments for this subcommand\n");
|
||||
"You must use YEAR, METHOD, WIRE-FEE, CLOSING-FEE and WAD-FEE as arguments for this subcommand\n");
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
@ -2419,8 +2639,7 @@ do_set_wire_fee (char *const *args)
|
||||
TALER_exchange_offline_wire_fee_sign (args[1],
|
||||
start_time,
|
||||
end_time,
|
||||
&wire_fee,
|
||||
&closing_fee,
|
||||
&fees,
|
||||
&master_priv,
|
||||
&master_sig);
|
||||
output_operation (OP_SET_WIRE_FEE,
|
||||
@ -2432,12 +2651,139 @@ do_set_wire_fee (char *const *args)
|
||||
GNUNET_JSON_pack_timestamp ("end_time",
|
||||
end_time),
|
||||
TALER_JSON_pack_amount ("wire_fee",
|
||||
&wire_fee),
|
||||
&fees.wire),
|
||||
TALER_JSON_pack_amount ("wad_fee",
|
||||
&fees.wad),
|
||||
TALER_JSON_pack_amount ("closing_fee",
|
||||
&closing_fee),
|
||||
&fees.closing),
|
||||
GNUNET_JSON_pack_data_auto ("master_sig",
|
||||
&master_sig)));
|
||||
next (args + 4);
|
||||
next (args + 5);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set global fees for the given year.
|
||||
*
|
||||
* @param args the array of command-line arguments to process next;
|
||||
* args[0] must be the year, args[1] the history fee, args[2] the kyc fee, args[3]
|
||||
* the account fee and args[4] the purse fee. These are followed by args[5] purse timeout,
|
||||
* args[6] kyc timeout and args[7] history expiration. Last is args[8] the (free) purse account limit.
|
||||
*/
|
||||
static void
|
||||
do_set_global_fee (char *const *args)
|
||||
{
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
char dummy;
|
||||
unsigned int year;
|
||||
struct TALER_GlobalFeeSet fees;
|
||||
struct GNUNET_TIME_Relative purse_timeout;
|
||||
struct GNUNET_TIME_Relative kyc_timeout;
|
||||
struct GNUNET_TIME_Relative history_expiration;
|
||||
unsigned int purse_account_limit;
|
||||
struct GNUNET_TIME_Timestamp start_time;
|
||||
struct GNUNET_TIME_Timestamp end_time;
|
||||
|
||||
if (NULL != in)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Downloaded data was not consumed, not setting global fee\n");
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_FAILURE;
|
||||
return;
|
||||
}
|
||||
if ( (NULL == args[0]) ||
|
||||
(NULL == args[1]) ||
|
||||
(NULL == args[2]) ||
|
||||
(NULL == args[3]) ||
|
||||
(NULL == args[4]) ||
|
||||
(NULL == args[5]) ||
|
||||
(NULL == args[6]) ||
|
||||
(NULL == args[7]) ||
|
||||
(NULL == args[8]) ||
|
||||
( (1 != sscanf (args[0],
|
||||
"%u%c",
|
||||
&year,
|
||||
&dummy)) &&
|
||||
(0 != strcasecmp ("now",
|
||||
args[0])) ) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_string_to_amount (args[1],
|
||||
&fees.history)) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_string_to_amount (args[2],
|
||||
&fees.kyc)) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_string_to_amount (args[3],
|
||||
&fees.account)) ||
|
||||
(GNUNET_OK !=
|
||||
TALER_string_to_amount (args[4],
|
||||
&fees.purse)) ||
|
||||
(GNUNET_OK !=
|
||||
GNUNET_STRINGS_fancy_time_to_relative (args[5],
|
||||
&purse_timeout)) ||
|
||||
(GNUNET_OK !=
|
||||
GNUNET_STRINGS_fancy_time_to_relative (args[6],
|
||||
&kyc_timeout)) ||
|
||||
(GNUNET_OK !=
|
||||
GNUNET_STRINGS_fancy_time_to_relative (args[7],
|
||||
&history_expiration)) ||
|
||||
(1 != sscanf (args[8],
|
||||
"%u%c",
|
||||
&purse_account_limit,
|
||||
&dummy)) )
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"You must use YEAR, HISTORY-FEE, KYC-FEE, ACCOUNT-FEE, PURSE-FEE, PURSE-TIMEOUT, KYC-TIMEOUT, HISTORY-EXPIRATION and PURSE-ACCOUNT-LIMIT as arguments for this subcommand\n");
|
||||
test_shutdown ();
|
||||
global_ret = EXIT_INVALIDARGUMENT;
|
||||
return;
|
||||
}
|
||||
if (0 == strcasecmp ("now",
|
||||
args[0]))
|
||||
year = GNUNET_TIME_get_current_year ();
|
||||
if (GNUNET_OK !=
|
||||
load_offline_key (GNUNET_NO))
|
||||
return;
|
||||
start_time = GNUNET_TIME_absolute_to_timestamp (
|
||||
GNUNET_TIME_year_to_time (year));
|
||||
end_time = GNUNET_TIME_absolute_to_timestamp (
|
||||
GNUNET_TIME_year_to_time (year + 1));
|
||||
|
||||
TALER_exchange_offline_global_fee_sign (start_time,
|
||||
end_time,
|
||||
&fees,
|
||||
purse_timeout,
|
||||
kyc_timeout,
|
||||
history_expiration,
|
||||
(uint32_t) purse_account_limit,
|
||||
&master_priv,
|
||||
&master_sig);
|
||||
output_operation (OP_SET_GLOBAL_FEE,
|
||||
GNUNET_JSON_PACK (
|
||||
GNUNET_JSON_pack_timestamp ("start_time",
|
||||
start_time),
|
||||
GNUNET_JSON_pack_timestamp ("end_time",
|
||||
end_time),
|
||||
TALER_JSON_pack_amount ("history_fee",
|
||||
&fees.history),
|
||||
TALER_JSON_pack_amount ("kyc_fee",
|
||||
&fees.kyc),
|
||||
TALER_JSON_pack_amount ("account_fee",
|
||||
&fees.account),
|
||||
TALER_JSON_pack_amount ("purse_fee",
|
||||
&fees.purse),
|
||||
GNUNET_JSON_pack_time_rel ("purse_timeout",
|
||||
purse_timeout),
|
||||
GNUNET_JSON_pack_time_rel ("kyc_timeout",
|
||||
kyc_timeout),
|
||||
GNUNET_JSON_pack_time_rel ("history_expiration",
|
||||
history_expiration),
|
||||
GNUNET_JSON_pack_uint64 ("purse_account_limit",
|
||||
(uint32_t) purse_account_limit),
|
||||
GNUNET_JSON_pack_data_auto ("master_sig",
|
||||
&master_sig)));
|
||||
next (args + 9);
|
||||
}
|
||||
|
||||
|
||||
@ -3649,8 +3995,6 @@ do_extensions_sign (char *const *args)
|
||||
struct TALER_MasterSignatureP sig;
|
||||
const struct TALER_Extension *it;
|
||||
|
||||
TALER_extensions_init ();
|
||||
|
||||
if (GNUNET_OK != TALER_extensions_load_taler_config (kcfg))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
@ -3827,9 +4171,15 @@ work (void *cls)
|
||||
{
|
||||
.name = "wire-fee",
|
||||
.help =
|
||||
"sign wire fees for the given year (year, wire method, wire fee and closing fee must be given as arguments)",
|
||||
"sign wire fees for the given year (year, wire method, wire fee, closing fee and wad fee must be given as arguments)",
|
||||
.cb = &do_set_wire_fee
|
||||
},
|
||||
{
|
||||
.name = "global-fee",
|
||||
.help =
|
||||
"sign global fees for the given year (year, history fee, kyc fee, account fee, purse fee, purse timeout, kyc timeout, history expiration and the maximum number of free purses per account must be given as arguments)",
|
||||
.cb = &do_set_global_fee
|
||||
},
|
||||
{
|
||||
.name = "upload",
|
||||
.help =
|
||||
@ -3878,7 +4228,9 @@ run (void *cls,
|
||||
}
|
||||
|
||||
/* load age mask, if age restriction is enabled */
|
||||
TALER_extensions_init ();
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_extension_age_restriction_register ());
|
||||
|
||||
if (GNUNET_OK != TALER_extensions_load_taler_config (kcfg))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
|
2
src/exchange/.gitignore
vendored
2
src/exchange/.gitignore
vendored
@ -9,3 +9,5 @@ test_taler_exchange_wirewatch-postgres
|
||||
test_taler_exchange_httpd_home/.config/taler/account-1.json
|
||||
taler-exchange-closer
|
||||
taler-exchange-transfer
|
||||
taler-exchange-router
|
||||
taler-exchange-expire
|
||||
|
@ -19,7 +19,9 @@ pkgcfg_DATA = \
|
||||
bin_PROGRAMS = \
|
||||
taler-exchange-aggregator \
|
||||
taler-exchange-closer \
|
||||
taler-exchange-expire \
|
||||
taler-exchange-httpd \
|
||||
taler-exchange-router \
|
||||
taler-exchange-transfer \
|
||||
taler-exchange-wirewatch
|
||||
|
||||
@ -50,9 +52,22 @@ taler_exchange_closer_LDADD = \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
taler_exchange_wirewatch_SOURCES = \
|
||||
taler-exchange-wirewatch.c
|
||||
taler_exchange_wirewatch_LDADD = \
|
||||
taler_exchange_expire_SOURCES = \
|
||||
taler-exchange-expire.c
|
||||
taler_exchange_expire_LDADD = \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
|
||||
-ljansson \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
taler_exchange_router_SOURCES = \
|
||||
taler-exchange-router.c
|
||||
taler_exchange_router_LDADD = \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
@ -76,10 +91,26 @@ taler_exchange_transfer_LDADD = \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
taler_exchange_wirewatch_SOURCES = \
|
||||
taler-exchange-wirewatch.c
|
||||
taler_exchange_wirewatch_LDADD = \
|
||||
$(LIBGCRYPT_LIBS) \
|
||||
$(top_builddir)/src/json/libtalerjson.la \
|
||||
$(top_builddir)/src/util/libtalerutil.la \
|
||||
$(top_builddir)/src/bank-lib/libtalerbank.la \
|
||||
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
|
||||
-ljansson \
|
||||
-lgnunetcurl \
|
||||
-lgnunetutil \
|
||||
$(XLIB)
|
||||
|
||||
|
||||
taler_exchange_httpd_SOURCES = \
|
||||
taler-exchange-httpd.c taler-exchange-httpd.h \
|
||||
taler-exchange-httpd_auditors.c taler-exchange-httpd_auditors.h \
|
||||
taler-exchange-httpd_csr.c taler-exchange-httpd_csr \
|
||||
taler-exchange-httpd_batch-withdraw.c taler-exchange-httpd_batch-withdraw.h \
|
||||
taler-exchange-httpd_contract.c taler-exchange-httpd_contract.h \
|
||||
taler-exchange-httpd_csr.c taler-exchange-httpd_csr.h \
|
||||
taler-exchange-httpd_db.c taler-exchange-httpd_db.h \
|
||||
taler-exchange-httpd_deposit.c taler-exchange-httpd_deposit.h \
|
||||
taler-exchange-httpd_deposits_get.c taler-exchange-httpd_deposits_get.h \
|
||||
@ -94,6 +125,7 @@ taler_exchange_httpd_SOURCES = \
|
||||
taler-exchange-httpd_management_auditors_AP_disable.c \
|
||||
taler-exchange-httpd_management_denominations_HDP_revoke.c \
|
||||
taler-exchange-httpd_management_extensions.c \
|
||||
taler-exchange-httpd_management_global_fees.c \
|
||||
taler-exchange-httpd_management_post_keys.c \
|
||||
taler-exchange-httpd_management_signkey_EP_revoke.c \
|
||||
taler-exchange-httpd_management_wire_enable.c \
|
||||
@ -102,11 +134,18 @@ taler_exchange_httpd_SOURCES = \
|
||||
taler-exchange-httpd_melt.c taler-exchange-httpd_melt.h \
|
||||
taler-exchange-httpd_metrics.c taler-exchange-httpd_metrics.h \
|
||||
taler-exchange-httpd_mhd.c taler-exchange-httpd_mhd.h \
|
||||
taler-exchange-httpd_purses_create.c taler-exchange-httpd_purses_create.h \
|
||||
taler-exchange-httpd_purses_deposit.c taler-exchange-httpd_purses_deposit.h \
|
||||
taler-exchange-httpd_purses_get.c taler-exchange-httpd_purses_get.h \
|
||||
taler-exchange-httpd_purses_merge.c taler-exchange-httpd_purses_merge.h \
|
||||
taler-exchange-httpd_recoup.c taler-exchange-httpd_recoup.h \
|
||||
taler-exchange-httpd_recoup-refresh.c taler-exchange-httpd_recoup-refresh.h \
|
||||
taler-exchange-httpd_refreshes_reveal.c taler-exchange-httpd_refreshes_reveal.h \
|
||||
taler-exchange-httpd_refund.c taler-exchange-httpd_refund.h \
|
||||
taler-exchange-httpd_reserves_get.c taler-exchange-httpd_reserves_get.h \
|
||||
taler-exchange-httpd_reserves_history.c taler-exchange-httpd_reserves_history.h \
|
||||
taler-exchange-httpd_reserves_purse.c taler-exchange-httpd_reserves_purse.h \
|
||||
taler-exchange-httpd_reserves_status.c taler-exchange-httpd_reserves_status.h \
|
||||
taler-exchange-httpd_responses.c taler-exchange-httpd_responses.h \
|
||||
taler-exchange-httpd_terms.c taler-exchange-httpd_terms.h \
|
||||
taler-exchange-httpd_transfers_get.c taler-exchange-httpd_transfers_get.h \
|
||||
|
@ -47,6 +47,15 @@ BASE_URL = http://localhost:8081/
|
||||
# How long should the aggregator sleep if it has nothing to do?
|
||||
AGGREGATOR_IDLE_SLEEP_INTERVAL = 60 s
|
||||
|
||||
# FIXME: document!
|
||||
ROUTER_IDLE_SLEEP_INTERVAL = 60 s
|
||||
|
||||
# How big is an individual shard to be processed
|
||||
# by taler-exchange-expire (in time). It may take
|
||||
# this much time for an expired purse to be really
|
||||
# cleaned up and the coins refunded.
|
||||
EXPIRE_SHARD_SIZE = 1 h
|
||||
|
||||
# How long should the transfer tool
|
||||
# sleep if it has nothing to do?
|
||||
TRANSFER_IDLE_SLEEP_INTERVAL = 60 s
|
||||
@ -66,6 +75,17 @@ CLOSER_IDLE_SLEEP_INTERVAL = 60 s
|
||||
# aggregation logic will break badly!
|
||||
AGGREGATOR_SHARD_SIZE = 2147483648
|
||||
|
||||
# Values of 0 or above 2^31 disable sharding, which
|
||||
# is a sane default for most use-cases.
|
||||
# When changing this value, you MUST stop all
|
||||
# aggregators and manually run
|
||||
#
|
||||
# $ taler-exchange-dbinit -s
|
||||
#
|
||||
# against the exchange's database. Otherwise, the
|
||||
# aggregation logic will break badly!
|
||||
ROUTER_SHARD_SIZE = 2147483648
|
||||
|
||||
# How long should wirewatch sleep if it has nothing to do?
|
||||
# (Set very aggressively here for the demonstrators to be
|
||||
# super fast.)
|
||||
|
@ -43,7 +43,7 @@ struct AggregationUnit
|
||||
struct TALER_MerchantPublicKeyP merchant_pub;
|
||||
|
||||
/**
|
||||
* Total amount to be transferred, before subtraction of @e wire_fee and rounding down.
|
||||
* Total amount to be transferred, before subtraction of @e fees.wire and rounding down.
|
||||
*/
|
||||
struct TALER_Amount total_amount;
|
||||
|
||||
@ -55,18 +55,13 @@ struct AggregationUnit
|
||||
/**
|
||||
* Wire fee we charge for @e wp at @e execution_time.
|
||||
*/
|
||||
struct TALER_Amount wire_fee;
|
||||
struct TALER_WireFeeSet fees;
|
||||
|
||||
/**
|
||||
* Wire transfer identifier we use.
|
||||
*/
|
||||
struct TALER_WireTransferIdentifierRawP wtid;
|
||||
|
||||
/**
|
||||
* Row ID of the transaction that started it all.
|
||||
*/
|
||||
uint64_t row_id;
|
||||
|
||||
/**
|
||||
* The current time (which triggered the aggregation and
|
||||
* defines the wire fee).
|
||||
@ -81,7 +76,7 @@ struct AggregationUnit
|
||||
/**
|
||||
* Selected wire target for the aggregation.
|
||||
*/
|
||||
uint64_t wire_target;
|
||||
struct TALER_PaytoHashP h_payto;
|
||||
|
||||
/**
|
||||
* Exchange wire account to be used for the preparation and
|
||||
@ -89,21 +84,6 @@ struct AggregationUnit
|
||||
*/
|
||||
const struct TALER_EXCHANGEDB_AccountInfo *wa;
|
||||
|
||||
/**
|
||||
* Array of row_ids from the aggregation.
|
||||
*/
|
||||
uint64_t additional_rows[TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT];
|
||||
|
||||
/**
|
||||
* Offset specifying how many @e additional_rows are in use.
|
||||
*/
|
||||
unsigned int rows_offset;
|
||||
|
||||
/**
|
||||
* Set to true if we encountered a refund during #refund_by_coin_cb.
|
||||
* Used to wave the deposit fee.
|
||||
*/
|
||||
bool have_refund;
|
||||
};
|
||||
|
||||
|
||||
@ -317,312 +297,6 @@ parse_wirewatch_config (void)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback invoked with information about refunds applicable
|
||||
* to a particular coin. Subtract refunded amount(s) from
|
||||
* the aggregation unit's total amount.
|
||||
*
|
||||
* @param cls closure with a `struct AggregationUnit *`
|
||||
* @param amount_with_fee what was the refunded amount with the fee
|
||||
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
refund_by_coin_cb (void *cls,
|
||||
const struct TALER_Amount *amount_with_fee)
|
||||
{
|
||||
struct AggregationUnit *aux = cls;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Aggregator subtracts applicable refund of amount %s\n",
|
||||
TALER_amount2s (amount_with_fee));
|
||||
aux->have_refund = true;
|
||||
if (0 >
|
||||
TALER_amount_subtract (&aux->total_amount,
|
||||
&aux->total_amount,
|
||||
amount_with_fee))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about deposits that have been made,
|
||||
* with the goal of executing the corresponding wire transaction.
|
||||
*
|
||||
* @param cls a `struct AggregationUnit`
|
||||
* @param row_id identifies database entry
|
||||
* @param merchant_pub public key of the merchant
|
||||
* @param coin_pub public key of the coin
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @param deposit_fee amount the exchange gets to keep as transaction fees
|
||||
* @param h_contract_terms hash of the proposal data known to merchant and customer
|
||||
* @param wire_target target account for the wire transfer
|
||||
* @param payto_uri URI of the target account
|
||||
* @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to continue to iterate
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
deposit_cb (void *cls,
|
||||
uint64_t row_id,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
const struct TALER_Amount *deposit_fee,
|
||||
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||
uint64_t wire_target,
|
||||
const char *payto_uri)
|
||||
{
|
||||
struct AggregationUnit *au = cls;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
au->merchant_pub = *merchant_pub;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Aggregator processing payment %s with amount %s\n",
|
||||
TALER_B2S (coin_pub),
|
||||
TALER_amount2s (amount_with_fee));
|
||||
au->row_id = row_id;
|
||||
au->total_amount = *amount_with_fee;
|
||||
au->have_refund = false;
|
||||
qs = db_plugin->select_refunds_by_coin (db_plugin->cls,
|
||||
coin_pub,
|
||||
&au->merchant_pub,
|
||||
h_contract_terms,
|
||||
&refund_by_coin_cb,
|
||||
au);
|
||||
if (0 > qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
if (! au->have_refund)
|
||||
{
|
||||
struct TALER_Amount ntotal;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Non-refunded transaction, subtracting deposit fee %s\n",
|
||||
TALER_amount2s (deposit_fee));
|
||||
if (0 >
|
||||
TALER_amount_subtract (&ntotal,
|
||||
amount_with_fee,
|
||||
deposit_fee))
|
||||
{
|
||||
/* This should never happen, issue a warning, but continue processing
|
||||
with an amount of zero, least we hang here for good. */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Fatally malformed record at row %llu over %s (deposit fee exceeds deposited value)\n",
|
||||
(unsigned long long) row_id,
|
||||
TALER_amount2s (amount_with_fee));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_set_zero (au->total_amount.currency,
|
||||
&au->total_amount));
|
||||
}
|
||||
else
|
||||
{
|
||||
au->total_amount = ntotal;
|
||||
}
|
||||
}
|
||||
|
||||
GNUNET_assert (NULL == au->payto_uri);
|
||||
au->payto_uri = GNUNET_strdup (payto_uri);
|
||||
au->wire_target = wire_target;
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||
&au->wtid,
|
||||
sizeof (au->wtid));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Starting aggregation under H(WTID)=%s, starting amount %s at %llu\n",
|
||||
TALER_B2S (&au->wtid),
|
||||
TALER_amount2s (amount_with_fee),
|
||||
(unsigned long long) row_id);
|
||||
au->wa = TALER_EXCHANGEDB_find_account_by_payto_uri (payto_uri);
|
||||
if (NULL == au->wa)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"No exchange account configured for `%s', please fix your setup to continue!\n",
|
||||
payto_uri);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
|
||||
/* make sure we have current fees */
|
||||
au->execution_time = GNUNET_TIME_timestamp_get ();
|
||||
{
|
||||
struct TALER_Amount closing_fee;
|
||||
struct GNUNET_TIME_Timestamp start_date;
|
||||
struct GNUNET_TIME_Timestamp end_date;
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = db_plugin->get_wire_fee (db_plugin->cls,
|
||||
au->wa->method,
|
||||
au->execution_time,
|
||||
&start_date,
|
||||
&end_date,
|
||||
&au->wire_fee,
|
||||
&closing_fee,
|
||||
&master_sig);
|
||||
if (0 >= qs)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Could not get wire fees for %s at %s. Aborting run.\n",
|
||||
au->wa->method,
|
||||
GNUNET_TIME_timestamp2s (au->execution_time));
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Aggregator starts aggregation for deposit %llu to %s with wire fee %s\n",
|
||||
(unsigned long long) row_id,
|
||||
TALER_B2S (&au->wtid),
|
||||
TALER_amount2s (&au->wire_fee));
|
||||
qs = db_plugin->insert_aggregation_tracking (db_plugin->cls,
|
||||
&au->wtid,
|
||||
row_id);
|
||||
if (qs <= 0)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Aggregator marks deposit %llu as done\n",
|
||||
(unsigned long long) row_id);
|
||||
qs = db_plugin->mark_deposit_done (db_plugin->cls,
|
||||
row_id);
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called with details about another deposit we
|
||||
* can aggregate into an existing aggregation unit.
|
||||
*
|
||||
* @param cls a `struct AggregationUnit`
|
||||
* @param row_id identifies database entry
|
||||
* @param coin_pub public key of the coin
|
||||
* @param amount_with_fee amount that was deposited including fee
|
||||
* @param deposit_fee amount the exchange gets to keep as transaction fees
|
||||
* @param h_contract_terms hash of the proposal data known to merchant and customer
|
||||
* @return transaction status code
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
aggregate_cb (void *cls,
|
||||
uint64_t row_id,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_Amount *amount_with_fee,
|
||||
const struct TALER_Amount *deposit_fee,
|
||||
const struct TALER_PrivateContractHashP *h_contract_terms)
|
||||
{
|
||||
struct AggregationUnit *au = cls;
|
||||
struct TALER_Amount old;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
if (au->rows_offset >= TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT)
|
||||
{
|
||||
/* Bug: we asked for at most #TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT results! */
|
||||
GNUNET_break (0);
|
||||
/* Skip this one, but keep going with the overall transaction */
|
||||
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
||||
}
|
||||
|
||||
/* add to total */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Adding transaction amount %s from row %llu to aggregation\n",
|
||||
TALER_amount2s (amount_with_fee),
|
||||
(unsigned long long) row_id);
|
||||
/* save the existing total aggregate in 'old', for later */
|
||||
old = au->total_amount;
|
||||
/* we begin with the total contribution of the current coin */
|
||||
au->total_amount = *amount_with_fee;
|
||||
/* compute contribution of this coin (after fees) */
|
||||
au->have_refund = false;
|
||||
qs = db_plugin->select_refunds_by_coin (db_plugin->cls,
|
||||
coin_pub,
|
||||
&au->merchant_pub,
|
||||
h_contract_terms,
|
||||
&refund_by_coin_cb,
|
||||
au);
|
||||
if (0 > qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
if (! au->have_refund)
|
||||
{
|
||||
struct TALER_Amount tmp;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Subtracting deposit fee %s for non-refunded coin\n",
|
||||
TALER_amount2s (deposit_fee));
|
||||
if (0 >
|
||||
TALER_amount_subtract (&tmp,
|
||||
&au->total_amount,
|
||||
deposit_fee))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Fatally malformed record at %llu over amount %s (deposit fee exceeds deposited value)\n",
|
||||
(unsigned long long) row_id,
|
||||
TALER_amount2s (&au->total_amount));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_set_zero (old.currency,
|
||||
&au->total_amount));
|
||||
}
|
||||
else
|
||||
{
|
||||
au->total_amount = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* now add the au->total_amount with the (remaining) contribution of
|
||||
the current coin to the 'old' value with the current aggregate value */
|
||||
{
|
||||
struct TALER_Amount tmp;
|
||||
|
||||
if (0 >
|
||||
TALER_amount_add (&tmp,
|
||||
&au->total_amount,
|
||||
&old))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Overflow or currency incompatibility during aggregation at %llu\n",
|
||||
(unsigned long long) row_id);
|
||||
/* Skip this one, but keep going! */
|
||||
au->total_amount = old;
|
||||
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
||||
}
|
||||
au->total_amount = tmp;
|
||||
}
|
||||
|
||||
/* "append" to our list of rows */
|
||||
au->additional_rows[au->rows_offset++] = row_id;
|
||||
/* insert into aggregation tracking table */
|
||||
qs = db_plugin->insert_aggregation_tracking (db_plugin->cls,
|
||||
&au->wtid,
|
||||
row_id);
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
qs = db_plugin->mark_deposit_done (db_plugin->cls,
|
||||
row_id);
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
return qs;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Aggregator marked deposit %llu as DONE\n",
|
||||
(unsigned long long) row_id);
|
||||
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform a database commit. If it fails, print a warning.
|
||||
*
|
||||
@ -685,10 +359,17 @@ run_aggregation (void *cls)
|
||||
struct Shard *s = cls;
|
||||
struct AggregationUnit au_active;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct TALER_Amount trans;
|
||||
bool have_transient = true; /* squash compiler warning */
|
||||
|
||||
task = NULL;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Checking for ready deposits to aggregate\n");
|
||||
/* make sure we have current fees */
|
||||
memset (&au_active,
|
||||
0,
|
||||
sizeof (au_active));
|
||||
au_active.execution_time = GNUNET_TIME_timestamp_get ();
|
||||
if (GNUNET_OK !=
|
||||
db_plugin->start_deferred_wire_out (db_plugin->cls))
|
||||
{
|
||||
@ -699,16 +380,13 @@ run_aggregation (void *cls)
|
||||
release_shard (s);
|
||||
return;
|
||||
}
|
||||
memset (&au_active,
|
||||
0,
|
||||
sizeof (au_active));
|
||||
qs = db_plugin->get_ready_deposit (
|
||||
db_plugin->cls,
|
||||
s->shard_start,
|
||||
s->shard_end,
|
||||
kyc_off ? true : false,
|
||||
&deposit_cb,
|
||||
&au_active);
|
||||
&au_active.merchant_pub,
|
||||
&au_active.payto_uri);
|
||||
switch (qs)
|
||||
{
|
||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
||||
@ -766,22 +444,100 @@ run_aggregation (void *cls)
|
||||
/* continued below */
|
||||
break;
|
||||
}
|
||||
au_active.wa = TALER_EXCHANGEDB_find_account_by_payto_uri (
|
||||
au_active.payto_uri);
|
||||
if (NULL == au_active.wa)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"No exchange account configured for `%s', please fix your setup to continue!\n",
|
||||
au_active.payto_uri);
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
release_shard (s);
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
struct GNUNET_TIME_Timestamp start_date;
|
||||
struct GNUNET_TIME_Timestamp end_date;
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
|
||||
qs = db_plugin->get_wire_fee (db_plugin->cls,
|
||||
au_active.wa->method,
|
||||
au_active.execution_time,
|
||||
&start_date,
|
||||
&end_date,
|
||||
&au_active.fees,
|
||||
&master_sig);
|
||||
if (0 >= qs)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Could not get wire fees for %s at %s. Aborting run.\n",
|
||||
au_active.wa->method,
|
||||
GNUNET_TIME_timestamp2s (au_active.execution_time));
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
release_shard (s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Now try to find other deposits to aggregate */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Found ready deposit for %s, aggregating by target %llu\n",
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Found ready deposit for %s, aggregating by target %s\n",
|
||||
TALER_B2S (&au_active.merchant_pub),
|
||||
(unsigned long long) au_active.wire_target);
|
||||
qs = db_plugin->iterate_matching_deposits (db_plugin->cls,
|
||||
au_active.wire_target,
|
||||
&au_active.merchant_pub,
|
||||
&aggregate_cb,
|
||||
&au_active,
|
||||
TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT);
|
||||
au_active.payto_uri);
|
||||
TALER_payto_hash (au_active.payto_uri,
|
||||
&au_active.h_payto);
|
||||
|
||||
qs = db_plugin->select_aggregation_transient (db_plugin->cls,
|
||||
&au_active.h_payto,
|
||||
au_active.wa->section_name,
|
||||
&au_active.wtid,
|
||||
&trans);
|
||||
switch (qs)
|
||||
{
|
||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to lookup transient aggregates!\n");
|
||||
cleanup_au (&au_active);
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
release_shard (s);
|
||||
return;
|
||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
||||
/* serializiability issue, try again */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Serialization issue, trying again later!\n");
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
cleanup_au (&au_active);
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_aggregation,
|
||||
s);
|
||||
return;
|
||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
||||
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
|
||||
&au_active.wtid,
|
||||
sizeof (au_active.wtid));
|
||||
have_transient = false;
|
||||
break;
|
||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
||||
have_transient = true;
|
||||
break;
|
||||
}
|
||||
qs = db_plugin->aggregate (db_plugin->cls,
|
||||
&au_active.h_payto,
|
||||
&au_active.merchant_pub,
|
||||
&au_active.wtid,
|
||||
&au_active.total_amount);
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to execute deposit iteration!\n");
|
||||
"Failed to execute aggregation!\n");
|
||||
cleanup_au (&au_active);
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
global_ret = EXIT_FAILURE;
|
||||
@ -801,61 +557,48 @@ run_aggregation (void *cls)
|
||||
s);
|
||||
return;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Found %d other deposits to combine into wire transfer.\n",
|
||||
qs);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Aggregation total is %s.\n",
|
||||
TALER_amount2s (&au_active.total_amount));
|
||||
|
||||
/* Subtract wire transfer fee and round to the unit supported by the
|
||||
wire transfer method; Check if after rounding down, we still have
|
||||
an amount to transfer, and if not mark as 'tiny'. */
|
||||
if (have_transient)
|
||||
GNUNET_assert (0 <=
|
||||
TALER_amount_add (&au_active.total_amount,
|
||||
&au_active.total_amount,
|
||||
&trans));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Rounding aggregate of %s\n",
|
||||
TALER_amount2s (&au_active.total_amount));
|
||||
if ( (0 >=
|
||||
TALER_amount_subtract (&au_active.final_amount,
|
||||
&au_active.total_amount,
|
||||
&au_active.wire_fee)) ||
|
||||
&au_active.fees.wire)) ||
|
||||
(GNUNET_SYSERR ==
|
||||
TALER_amount_round_down (&au_active.final_amount,
|
||||
¤cy_round_unit)) ||
|
||||
( (0 == au_active.final_amount.value) &&
|
||||
(0 == au_active.final_amount.fraction) ) )
|
||||
(TALER_amount_is_zero (&au_active.final_amount)) )
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Aggregate value too low for transfer (%d/%s)\n",
|
||||
qs,
|
||||
TALER_amount2s (&au_active.final_amount));
|
||||
/* Rollback ongoing transaction, as we will not use the respective
|
||||
WTID and thus need to remove the tracking data */
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
|
||||
/* There were results, just the value was too low. Start another
|
||||
transaction to mark all* of the selected deposits as minor! */
|
||||
if (GNUNET_OK !=
|
||||
db_plugin->start (db_plugin->cls,
|
||||
"aggregator mark tiny transactions"))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to start database transaction!\n");
|
||||
global_ret = EXIT_FAILURE;
|
||||
cleanup_au (&au_active);
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
release_shard (s);
|
||||
return;
|
||||
}
|
||||
/* Mark transactions by row_id as minor */
|
||||
qs = db_plugin->mark_deposit_tiny (db_plugin->cls,
|
||||
au_active.row_id);
|
||||
if (0 <= qs)
|
||||
{
|
||||
for (unsigned int i = 0; i<au_active.rows_offset; i++)
|
||||
{
|
||||
qs = db_plugin->mark_deposit_tiny (db_plugin->cls,
|
||||
au_active.additional_rows[i]);
|
||||
if (0 > qs)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (have_transient)
|
||||
qs = db_plugin->update_aggregation_transient (db_plugin->cls,
|
||||
&au_active.h_payto,
|
||||
&au_active.wtid,
|
||||
&au_active.total_amount);
|
||||
else
|
||||
qs = db_plugin->create_aggregation_transient (db_plugin->cls,
|
||||
&au_active.h_payto,
|
||||
au_active.wa->section_name,
|
||||
&au_active.wtid,
|
||||
&au_active.total_amount);
|
||||
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Serialization issue, trying again later!\n");
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
cleanup_au (&au_active);
|
||||
@ -867,6 +610,7 @@ run_aggregation (void *cls)
|
||||
}
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
cleanup_au (&au_active);
|
||||
global_ret = EXIT_FAILURE;
|
||||
@ -908,15 +652,20 @@ run_aggregation (void *cls)
|
||||
buf_size);
|
||||
GNUNET_free (buf);
|
||||
}
|
||||
/* Commit the WTID data to 'wire_out' to finally satisfy aggregation
|
||||
table constraints */
|
||||
/* Commit the WTID data to 'wire_out' */
|
||||
if (qs >= 0)
|
||||
qs = db_plugin->store_wire_transfer_out (db_plugin->cls,
|
||||
au_active.execution_time,
|
||||
&au_active.wtid,
|
||||
au_active.wire_target,
|
||||
&au_active.h_payto,
|
||||
au_active.wa->section_name,
|
||||
&au_active.final_amount);
|
||||
|
||||
if ( (qs >= 0) &&
|
||||
have_transient)
|
||||
qs = db_plugin->delete_aggregation_transient (db_plugin->cls,
|
||||
&au_active.h_payto,
|
||||
&au_active.wtid);
|
||||
cleanup_au (&au_active);
|
||||
|
||||
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||
@ -960,6 +709,7 @@ run_aggregation (void *cls)
|
||||
GNUNET_break (0);
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
db_plugin->rollback (db_plugin->cls); /* just in case */
|
||||
release_shard (s);
|
||||
return;
|
||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
||||
@ -973,6 +723,7 @@ run_aggregation (void *cls)
|
||||
GNUNET_break (0);
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
db_plugin->rollback (db_plugin->cls); /* just in case */
|
||||
release_shard (s);
|
||||
return;
|
||||
}
|
||||
|
@ -217,6 +217,7 @@ expired_reserve_cb (void *cls,
|
||||
struct TALER_WireTransferIdentifierRawP wtid;
|
||||
struct TALER_Amount amount_without_fee;
|
||||
struct TALER_Amount closing_fee;
|
||||
struct TALER_WireFeeSet fees;
|
||||
enum TALER_AmountArithmeticResult ret;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
const struct TALER_EXCHANGEDB_AccountInfo *wa;
|
||||
@ -241,10 +242,9 @@ expired_reserve_cb (void *cls,
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
|
||||
/* lookup `closing_fee` from time of actual reserve expiration
|
||||
/* lookup `fees` from time of actual reserve expiration
|
||||
(we may be lagging behind!) */
|
||||
{
|
||||
struct TALER_Amount wire_fee;
|
||||
struct GNUNET_TIME_Timestamp start_date;
|
||||
struct GNUNET_TIME_Timestamp end_date;
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
@ -255,8 +255,7 @@ expired_reserve_cb (void *cls,
|
||||
expiration_date,
|
||||
&start_date,
|
||||
&end_date,
|
||||
&wire_fee,
|
||||
&closing_fee,
|
||||
&fees,
|
||||
&master_sig);
|
||||
if (0 >= qs)
|
||||
{
|
||||
@ -269,6 +268,7 @@ expired_reserve_cb (void *cls,
|
||||
}
|
||||
|
||||
/* calculate transfer amount */
|
||||
closing_fee = fees.closing;
|
||||
ret = TALER_amount_subtract (&amount_without_fee,
|
||||
left,
|
||||
&closing_fee);
|
||||
|
504
src/exchange/taler-exchange-expire.c
Normal file
504
src/exchange/taler-exchange-expire.c
Normal file
@ -0,0 +1,504 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
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, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file taler-exchange-expire.c
|
||||
* @brief Process that cleans up expired purses
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <jansson.h>
|
||||
#include <pthread.h>
|
||||
#include "taler_exchangedb_lib.h"
|
||||
#include "taler_exchangedb_plugin.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_bank_service.h"
|
||||
|
||||
|
||||
/**
|
||||
* Work shard we are processing.
|
||||
*/
|
||||
struct Shard
|
||||
{
|
||||
|
||||
/**
|
||||
* When did we start processing the shard?
|
||||
*/
|
||||
struct GNUNET_TIME_Timestamp start_time;
|
||||
|
||||
/**
|
||||
* Starting row of the shard.
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute shard_start;
|
||||
|
||||
/**
|
||||
* Inclusive end row of the shard.
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute shard_end;
|
||||
|
||||
/**
|
||||
* Number of starting points found in the shard.
|
||||
*/
|
||||
uint64_t work_counter;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The exchange's configuration.
|
||||
*/
|
||||
static const struct GNUNET_CONFIGURATION_Handle *cfg;
|
||||
|
||||
/**
|
||||
* Our database plugin.
|
||||
*/
|
||||
static struct TALER_EXCHANGEDB_Plugin *db_plugin;
|
||||
|
||||
/**
|
||||
* Next task to run, if any.
|
||||
*/
|
||||
static struct GNUNET_SCHEDULER_Task *task;
|
||||
|
||||
/**
|
||||
* How long should we sleep when idle before trying to find more work?
|
||||
*/
|
||||
static struct GNUNET_TIME_Relative expire_idle_sleep_interval;
|
||||
|
||||
/**
|
||||
* How big are the shards we are processing? Is an inclusive offset, so every
|
||||
* shard ranges from [X,X+shard_size) exclusive. So a shard covers
|
||||
* shard_size slots.
|
||||
*/
|
||||
static struct GNUNET_TIME_Relative shard_size;
|
||||
|
||||
/**
|
||||
* Value to return from main(). 0 on success, non-zero on errors.
|
||||
*/
|
||||
static int global_ret;
|
||||
|
||||
/**
|
||||
* #GNUNET_YES if we are in test mode and should exit when idle.
|
||||
*/
|
||||
static int test_mode;
|
||||
|
||||
/**
|
||||
* If this is a first-time run, we immediately
|
||||
* try to catch up with the present.
|
||||
*/
|
||||
static bool jump_mode;
|
||||
|
||||
|
||||
/**
|
||||
* Select a shard to work on.
|
||||
*
|
||||
* @param cls NULL
|
||||
*/
|
||||
static void
|
||||
run_shard (void *cls);
|
||||
|
||||
|
||||
/**
|
||||
* We're being aborted with CTRL-C (or SIGTERM). Shut down.
|
||||
*
|
||||
* @param cls closure
|
||||
*/
|
||||
static void
|
||||
shutdown_task (void *cls)
|
||||
{
|
||||
(void) cls;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Running shutdown\n");
|
||||
if (NULL != task)
|
||||
{
|
||||
GNUNET_SCHEDULER_cancel (task);
|
||||
task = NULL;
|
||||
}
|
||||
TALER_EXCHANGEDB_plugin_unload (db_plugin);
|
||||
db_plugin = NULL;
|
||||
cfg = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the configuration for expire.
|
||||
*
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
parse_expire_config (void)
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_time (cfg,
|
||||
"exchange",
|
||||
"EXPIRE_IDLE_SLEEP_INTERVAL",
|
||||
&expire_idle_sleep_interval))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange",
|
||||
"EXPIRE_IDLE_SLEEP_INTERVAL");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (NULL ==
|
||||
(db_plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to initialize DB subsystem\n");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform a database commit. If it fails, print a warning.
|
||||
*
|
||||
* @return status of commit
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
commit_or_warn (void)
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = db_plugin->commit (db_plugin->cls);
|
||||
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||
return qs;
|
||||
GNUNET_log ((GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||
? GNUNET_ERROR_TYPE_INFO
|
||||
: GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to commit database transaction!\n");
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release lock on shard @a s in the database.
|
||||
* On error, terminates this process.
|
||||
*
|
||||
* @param[in] s shard to free (and memory to release)
|
||||
*/
|
||||
static void
|
||||
release_shard (struct Shard *s)
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
unsigned long long wc = (unsigned long long) s->work_counter;
|
||||
|
||||
qs = db_plugin->complete_shard (
|
||||
db_plugin->cls,
|
||||
"expire",
|
||||
s->shard_start.abs_value_us,
|
||||
s->shard_end.abs_value_us);
|
||||
GNUNET_free (s);
|
||||
switch (qs)
|
||||
{
|
||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
|
||||
GNUNET_break (0);
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
||||
/* Strange, but let's just continue */
|
||||
break;
|
||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Purse expiration shard completed with %llu purses\n",
|
||||
wc);
|
||||
/* normal case */
|
||||
break;
|
||||
}
|
||||
if ( (0 == wc) &&
|
||||
(test_mode) &&
|
||||
(! jump_mode) )
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release lock on shard @a s in the database due to an abort of the
|
||||
* operation. On error, terminates this process.
|
||||
*
|
||||
* @param[in] s shard to free (and memory to release)
|
||||
*/
|
||||
static void
|
||||
abort_shard (struct Shard *s)
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = db_plugin->abort_shard (db_plugin->cls,
|
||||
"expire",
|
||||
s->shard_start.abs_value_us,
|
||||
s->shard_end.abs_value_us);
|
||||
if (0 >= qs)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to abort shard (%d)!\n",
|
||||
qs);
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main function that processes the work in one shard.
|
||||
*
|
||||
* @param[in] cls a `struct Shard` to process
|
||||
*/
|
||||
static void
|
||||
run_expire (void *cls)
|
||||
{
|
||||
struct Shard *s = cls;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
task = NULL;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Checking for expired purses\n");
|
||||
if (GNUNET_SYSERR ==
|
||||
db_plugin->preflight (db_plugin->cls))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to obtain database connection!\n");
|
||||
abort_shard (s);
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
db_plugin->start (db_plugin->cls,
|
||||
"expire-purse"))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
global_ret = EXIT_FAILURE;
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
abort_shard (s);
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
qs = db_plugin->expire_purse (db_plugin->cls,
|
||||
s->shard_start,
|
||||
s->shard_end);
|
||||
switch (qs)
|
||||
{
|
||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
||||
GNUNET_break (0);
|
||||
global_ret = EXIT_FAILURE;
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
abort_shard (s);
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
abort_shard (s);
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_shard,
|
||||
NULL);
|
||||
return;
|
||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
||||
if (0 > commit_or_warn ())
|
||||
{
|
||||
db_plugin->rollback (db_plugin->cls);
|
||||
abort_shard (s);
|
||||
}
|
||||
else
|
||||
{
|
||||
release_shard (s);
|
||||
}
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_shard,
|
||||
NULL);
|
||||
return;
|
||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
||||
/* commit, and go again immediately */
|
||||
s->work_counter++;
|
||||
(void) commit_or_warn ();
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_expire,
|
||||
s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Select a shard to work on.
|
||||
*
|
||||
* @param cls NULL
|
||||
*/
|
||||
static void
|
||||
run_shard (void *cls)
|
||||
{
|
||||
struct Shard *s;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
(void) cls;
|
||||
task = NULL;
|
||||
if (GNUNET_SYSERR ==
|
||||
db_plugin->preflight (db_plugin->cls))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to obtain database connection!\n");
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
s = GNUNET_new (struct Shard);
|
||||
s->start_time = GNUNET_TIME_timestamp_get ();
|
||||
qs = db_plugin->begin_shard (db_plugin->cls,
|
||||
"expire",
|
||||
shard_size,
|
||||
jump_mode
|
||||
? GNUNET_TIME_absolute_subtract (
|
||||
GNUNET_TIME_absolute_get (),
|
||||
shard_size).
|
||||
abs_value_us
|
||||
: shard_size.rel_value_us,
|
||||
&s->shard_start.abs_value_us,
|
||||
&s->shard_end.abs_value_us);
|
||||
jump_mode = false;
|
||||
if (0 >= qs)
|
||||
{
|
||||
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
|
||||
{
|
||||
static struct GNUNET_TIME_Relative delay;
|
||||
|
||||
GNUNET_free (s);
|
||||
delay = GNUNET_TIME_randomized_backoff (delay,
|
||||
GNUNET_TIME_UNIT_SECONDS);
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_delayed (delay,
|
||||
&run_shard,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to begin shard (%d)!\n",
|
||||
qs);
|
||||
GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
|
||||
global_ret = EXIT_FAILURE;
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_future (s->shard_end))
|
||||
{
|
||||
abort_shard (s);
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_at (s->shard_end,
|
||||
&run_shard,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
/* If this is a first-time run, we immediately
|
||||
try to catch up with the present */
|
||||
if (GNUNET_TIME_absolute_is_zero (s->shard_start))
|
||||
jump_mode = true;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Starting shard [%llu:%llu)!\n",
|
||||
(unsigned long long) s->shard_start.abs_value_us,
|
||||
(unsigned long long) s->shard_end.abs_value_us);
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_expire,
|
||||
s);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* First task.
|
||||
*
|
||||
* @param cls closure, NULL
|
||||
* @param args remaining command-line arguments
|
||||
* @param cfgfile name of the configuration file used (for saving, can be NULL!)
|
||||
* @param c configuration
|
||||
*/
|
||||
static void
|
||||
run (void *cls,
|
||||
char *const *args,
|
||||
const char *cfgfile,
|
||||
const struct GNUNET_CONFIGURATION_Handle *c)
|
||||
{
|
||||
(void) cls;
|
||||
(void) args;
|
||||
(void) cfgfile;
|
||||
|
||||
cfg = c;
|
||||
if (GNUNET_OK != parse_expire_config ())
|
||||
{
|
||||
cfg = NULL;
|
||||
global_ret = EXIT_NOTCONFIGURED;
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_time (cfg,
|
||||
"exchange",
|
||||
"EXPIRE_SHARD_SIZE",
|
||||
&shard_size))
|
||||
{
|
||||
cfg = NULL;
|
||||
global_ret = EXIT_NOTCONFIGURED;
|
||||
return;
|
||||
}
|
||||
GNUNET_assert (NULL == task);
|
||||
task = GNUNET_SCHEDULER_add_now (&run_shard,
|
||||
NULL);
|
||||
GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
|
||||
cls);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The main function of the taler-exchange-expire.
|
||||
*
|
||||
* @param argc number of arguments from the command line
|
||||
* @param argv command line arguments
|
||||
* @return 0 ok, non-zero on error, see #global_ret
|
||||
*/
|
||||
int
|
||||
main (int argc,
|
||||
char *const *argv)
|
||||
{
|
||||
struct GNUNET_GETOPT_CommandLineOption options[] = {
|
||||
GNUNET_GETOPT_option_timetravel ('T',
|
||||
"timetravel"),
|
||||
GNUNET_GETOPT_option_flag ('t',
|
||||
"test",
|
||||
"run in test mode and exit when idle",
|
||||
&test_mode),
|
||||
GNUNET_GETOPT_OPTION_END
|
||||
};
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_get_utf8_args (argc, argv,
|
||||
&argc, &argv))
|
||||
return EXIT_INVALIDARGUMENT;
|
||||
TALER_OS_init ();
|
||||
ret = GNUNET_PROGRAM_run (
|
||||
argc, argv,
|
||||
"taler-exchange-expire",
|
||||
gettext_noop (
|
||||
"background process that expires purses"),
|
||||
options,
|
||||
&run, NULL);
|
||||
GNUNET_free_nz ((void *) argv);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
return EXIT_INVALIDARGUMENT;
|
||||
if (GNUNET_NO == ret)
|
||||
return EXIT_SUCCESS;
|
||||
return global_ret;
|
||||
}
|
||||
|
||||
|
||||
/* end of taler-exchange-expire.c */
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
@ -30,6 +30,8 @@
|
||||
#include <limits.h>
|
||||
#include "taler_mhd_lib.h"
|
||||
#include "taler-exchange-httpd_auditors.h"
|
||||
#include "taler-exchange-httpd_batch-withdraw.h"
|
||||
#include "taler-exchange-httpd_contract.h"
|
||||
#include "taler-exchange-httpd_csr.h"
|
||||
#include "taler-exchange-httpd_deposit.h"
|
||||
#include "taler-exchange-httpd_deposits_get.h"
|
||||
@ -43,11 +45,18 @@
|
||||
#include "taler-exchange-httpd_melt.h"
|
||||
#include "taler-exchange-httpd_metrics.h"
|
||||
#include "taler-exchange-httpd_mhd.h"
|
||||
#include "taler-exchange-httpd_purses_create.h"
|
||||
#include "taler-exchange-httpd_purses_deposit.h"
|
||||
#include "taler-exchange-httpd_purses_get.h"
|
||||
#include "taler-exchange-httpd_purses_merge.h"
|
||||
#include "taler-exchange-httpd_recoup.h"
|
||||
#include "taler-exchange-httpd_recoup-refresh.h"
|
||||
#include "taler-exchange-httpd_refreshes_reveal.h"
|
||||
#include "taler-exchange-httpd_refund.h"
|
||||
#include "taler-exchange-httpd_reserves_get.h"
|
||||
#include "taler-exchange-httpd_reserves_history.h"
|
||||
#include "taler-exchange-httpd_reserves_purse.h"
|
||||
#include "taler-exchange-httpd_reserves_status.h"
|
||||
#include "taler-exchange-httpd_terms.h"
|
||||
#include "taler-exchange-httpd_transfers_get.h"
|
||||
#include "taler-exchange-httpd_wire.h"
|
||||
@ -57,6 +66,18 @@
|
||||
#include "taler_extensions.h"
|
||||
#include <gnunet/gnunet_mhd_compat.h>
|
||||
|
||||
/**
|
||||
* Macro to enable P2P handlers. ON for debugging,
|
||||
* FIXME: set to OFF for 0.9.0 release as the feature is not stable!
|
||||
*/
|
||||
#define WITH_P2P 1
|
||||
|
||||
/**
|
||||
* Should the experimental batch withdraw be supported?
|
||||
* ON for testing disable for 0.9.0 release!
|
||||
*/
|
||||
#define WITH_EXPERIMENTAL 1
|
||||
|
||||
/**
|
||||
* Backlog for listen operation on unix domain sockets.
|
||||
*/
|
||||
@ -130,8 +151,7 @@ char *TEH_base_url;
|
||||
/**
|
||||
* Age restriction flags and mask
|
||||
*/
|
||||
bool TEH_age_restriction_enabled = false;
|
||||
struct TALER_AgeMask TEH_age_mask = {0};
|
||||
bool TEH_age_restriction_enabled = true;
|
||||
|
||||
/**
|
||||
* Default timeout in seconds for HTTP requests.
|
||||
@ -237,8 +257,7 @@ r404 (struct MHD_Connection *connection,
|
||||
*
|
||||
* @param rc request context
|
||||
* @param root uploaded JSON data
|
||||
* @param args array of additional options (first must be the
|
||||
* reserve public key, the second one should be "withdraw")
|
||||
* @param args array of additional options
|
||||
* @return MHD result code
|
||||
*/
|
||||
static MHD_RESULT
|
||||
@ -309,6 +328,186 @@ handle_post_coins (struct TEH_RequestContext *rc,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signature of functions that handle operations on reserves.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param reserve_pub the public key of the reserve
|
||||
* @param root uploaded JSON data
|
||||
* @return MHD result code
|
||||
*/
|
||||
typedef MHD_RESULT
|
||||
(*ReserveOpHandler)(struct TEH_RequestContext *rc,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
const json_t *root);
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/reserves/$RESERVE_PUB/$OP" POST request. Parses the "reserve_pub"
|
||||
* EdDSA key of the reserve and demultiplexes based on $OP.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param root uploaded JSON data
|
||||
* @param args array of additional options
|
||||
* @return MHD result code
|
||||
*/
|
||||
static MHD_RESULT
|
||||
handle_post_reserves (struct TEH_RequestContext *rc,
|
||||
const json_t *root,
|
||||
const char *const args[2])
|
||||
{
|
||||
struct TALER_ReservePublicKeyP reserve_pub;
|
||||
static const struct
|
||||
{
|
||||
/**
|
||||
* Name of the operation (args[1])
|
||||
*/
|
||||
const char *op;
|
||||
|
||||
/**
|
||||
* Function to call to perform the operation.
|
||||
*/
|
||||
ReserveOpHandler handler;
|
||||
|
||||
} h[] = {
|
||||
{
|
||||
.op = "withdraw",
|
||||
.handler = &TEH_handler_withdraw
|
||||
},
|
||||
#if WITH_EXPERIMENTAL
|
||||
{
|
||||
.op = "batch-withdraw",
|
||||
.handler = &TEH_handler_batch_withdraw
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.op = "status",
|
||||
.handler = &TEH_handler_reserves_status
|
||||
},
|
||||
{
|
||||
.op = "history",
|
||||
.handler = &TEH_handler_reserves_history
|
||||
},
|
||||
#if WITH_P2P
|
||||
{
|
||||
.op = "purse",
|
||||
.handler = &TEH_handler_reserves_purse
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.op = NULL,
|
||||
.handler = NULL
|
||||
},
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (args[0],
|
||||
strlen (args[0]),
|
||||
&reserve_pub,
|
||||
sizeof (reserve_pub)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_GENERIC_RESERVE_PUB_MALFORMED,
|
||||
args[0]);
|
||||
}
|
||||
for (unsigned int i = 0; NULL != h[i].op; i++)
|
||||
if (0 == strcmp (h[i].op,
|
||||
args[1]))
|
||||
return h[i].handler (rc,
|
||||
&reserve_pub,
|
||||
root);
|
||||
return r404 (rc->connection,
|
||||
args[1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signature of functions that handle operations on purses.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param purse_pub the public key of the purse
|
||||
* @param root uploaded JSON data
|
||||
* @return MHD result code
|
||||
*/
|
||||
typedef MHD_RESULT
|
||||
(*PurseOpHandler)(struct MHD_Connection *connection,
|
||||
const struct TALER_PurseContractPublicKeyP *purse_pub,
|
||||
const json_t *root);
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/purses/$RESERVE_PUB/$OP" POST request. Parses the "purse_pub"
|
||||
* EdDSA key of the purse and demultiplexes based on $OP.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param root uploaded JSON data
|
||||
* @param args array of additional options
|
||||
* @return MHD result code
|
||||
*/
|
||||
static MHD_RESULT
|
||||
handle_post_purses (struct TEH_RequestContext *rc,
|
||||
const json_t *root,
|
||||
const char *const args[2])
|
||||
{
|
||||
struct TALER_PurseContractPublicKeyP purse_pub;
|
||||
static const struct
|
||||
{
|
||||
/**
|
||||
* Name of the operation (args[1])
|
||||
*/
|
||||
const char *op;
|
||||
|
||||
/**
|
||||
* Function to call to perform the operation.
|
||||
*/
|
||||
PurseOpHandler handler;
|
||||
|
||||
} h[] = {
|
||||
#if WITH_P2P
|
||||
{
|
||||
.op = "create",
|
||||
.handler = &TEH_handler_purses_create
|
||||
},
|
||||
{
|
||||
.op = "deposit",
|
||||
.handler = &TEH_handler_purses_deposit
|
||||
},
|
||||
{
|
||||
.op = "merge",
|
||||
.handler = &TEH_handler_purses_merge
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.op = NULL,
|
||||
.handler = NULL
|
||||
},
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (args[0],
|
||||
strlen (args[0]),
|
||||
&purse_pub,
|
||||
sizeof (purse_pub)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_GENERIC_PURSE_PUB_MALFORMED,
|
||||
args[0]);
|
||||
}
|
||||
for (unsigned int i = 0; NULL != h[i].op; i++)
|
||||
if (0 == strcmp (h[i].op,
|
||||
args[1]))
|
||||
return h[i].handler (rc->connection,
|
||||
&purse_pub,
|
||||
root);
|
||||
return r404 (rc->connection,
|
||||
args[1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increments our request counter and checks if this
|
||||
* process should commit suicide.
|
||||
@ -444,7 +643,7 @@ proceed_with_handler (struct TEH_RequestContext *rc,
|
||||
size_t *upload_data_size)
|
||||
{
|
||||
const struct TEH_RequestHandler *rh = rc->rh;
|
||||
const char *args[rh->nargs + 1];
|
||||
const char *args[rh->nargs + 2];
|
||||
size_t ulen = strlen (url) + 1;
|
||||
json_t *root = NULL;
|
||||
MHD_RESULT ret;
|
||||
@ -492,54 +691,43 @@ proceed_with_handler (struct TEH_RequestContext *rc,
|
||||
|
||||
{
|
||||
char d[ulen];
|
||||
unsigned int i;
|
||||
char *sp;
|
||||
|
||||
/* Parse command-line arguments, if applicable */
|
||||
args[0] = NULL;
|
||||
if (rh->nargs > 0)
|
||||
/* Parse command-line arguments */
|
||||
/* make a copy of 'url' because 'strtok_r()' will modify */
|
||||
memcpy (d,
|
||||
url,
|
||||
ulen);
|
||||
i = 0;
|
||||
args[i++] = strtok_r (d, "/", &sp);
|
||||
while ( (NULL != args[i - 1]) &&
|
||||
(i <= rh->nargs + 1) )
|
||||
args[i++] = strtok_r (NULL, "/", &sp);
|
||||
/* make sure above loop ran nicely until completion, and also
|
||||
that there is no excess data in 'd' afterwards */
|
||||
if ( ( (rh->nargs_is_upper_bound) &&
|
||||
(i - 1 > rh->nargs) ) ||
|
||||
( (! rh->nargs_is_upper_bound) &&
|
||||
(i - 1 != rh->nargs) ) )
|
||||
{
|
||||
unsigned int i;
|
||||
const char *fin;
|
||||
char *sp;
|
||||
char emsg[128 + 512];
|
||||
|
||||
/* make a copy of 'url' because 'strtok_r()' will modify */
|
||||
memcpy (d,
|
||||
url,
|
||||
ulen);
|
||||
i = 0;
|
||||
args[i++] = strtok_r (d, "/", &sp);
|
||||
while ( (NULL != args[i - 1]) &&
|
||||
(i < rh->nargs) )
|
||||
args[i++] = strtok_r (NULL, "/", &sp);
|
||||
/* make sure above loop ran nicely until completion, and also
|
||||
that there is no excess data in 'd' afterwards */
|
||||
if ( (! rh->nargs_is_upper_bound) &&
|
||||
( (i != rh->nargs) ||
|
||||
(NULL == args[i - 1]) ||
|
||||
(NULL != (fin = strtok_r (NULL, "/", &sp))) ) )
|
||||
{
|
||||
char emsg[128 + 512];
|
||||
|
||||
GNUNET_snprintf (emsg,
|
||||
sizeof (emsg),
|
||||
"Got %u/%u segments for %s request ('%s')",
|
||||
(NULL == args[i - 1])
|
||||
? i - 1
|
||||
: i + ((NULL != fin) ? 1 : 0),
|
||||
rh->nargs,
|
||||
rh->url,
|
||||
url);
|
||||
GNUNET_break_op (0);
|
||||
json_decref (root);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
|
||||
emsg);
|
||||
}
|
||||
|
||||
/* just to be safe(r), we always terminate the array with a NULL
|
||||
(even if handlers requested precise number of arguments) */
|
||||
args[i] = NULL;
|
||||
GNUNET_snprintf (emsg,
|
||||
sizeof (emsg),
|
||||
"Got %u+/%u segments for `%s' request (`%s')",
|
||||
i - 1,
|
||||
rh->nargs,
|
||||
rh->url,
|
||||
url);
|
||||
GNUNET_break_op (0);
|
||||
json_decref (root);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
|
||||
emsg);
|
||||
}
|
||||
GNUNET_assert (NULL == args[i - 1]);
|
||||
|
||||
/* Above logic ensures that 'root' is exactly non-NULL for POST operations,
|
||||
so we test for 'root' to decide which handler to invoke. */
|
||||
@ -743,6 +931,18 @@ handle_post_management (struct TEH_RequestContext *rc,
|
||||
return TEH_handler_management_post_wire_fees (rc->connection,
|
||||
root);
|
||||
}
|
||||
if (0 == strcmp (args[0],
|
||||
"global-fee"))
|
||||
{
|
||||
if (NULL != args[1])
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return r404 (rc->connection,
|
||||
"/management/global-fee/*");
|
||||
}
|
||||
return TEH_handler_management_post_global_fees (rc->connection,
|
||||
root);
|
||||
}
|
||||
if (0 == strcmp (args[0],
|
||||
"extensions"))
|
||||
{
|
||||
@ -946,7 +1146,7 @@ handle_mhd_request (void *cls,
|
||||
{
|
||||
.url = "reserves",
|
||||
.method = MHD_HTTP_METHOD_POST,
|
||||
.handler.post = &TEH_handler_withdraw,
|
||||
.handler.post = &handle_post_reserves,
|
||||
.nargs = 2
|
||||
},
|
||||
/* coins */
|
||||
@ -983,6 +1183,29 @@ handle_mhd_request (void *cls,
|
||||
.handler.get = &TEH_handler_deposits_get,
|
||||
.nargs = 4
|
||||
},
|
||||
/* Operating on purses */
|
||||
{
|
||||
.url = "purses",
|
||||
.method = MHD_HTTP_METHOD_POST,
|
||||
.handler.post = &handle_post_purses,
|
||||
.nargs = 2 // ??
|
||||
},
|
||||
#if WITH_P2P
|
||||
/* Getting purse status */
|
||||
{
|
||||
.url = "purses",
|
||||
.method = MHD_HTTP_METHOD_GET,
|
||||
.handler.get = &TEH_handler_purses_get,
|
||||
.nargs = 2
|
||||
},
|
||||
/* Getting contracts */
|
||||
{
|
||||
.url = "contracts",
|
||||
.method = MHD_HTTP_METHOD_GET,
|
||||
.handler.get = &TEH_handler_contracts_get,
|
||||
.nargs = 1
|
||||
},
|
||||
#endif
|
||||
/* KYC endpoints */
|
||||
{
|
||||
.url = "kyc-check",
|
||||
@ -1321,12 +1544,12 @@ parse_kyc_oauth_cfg (void)
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
|
||||
"exchange-kyc-oauth2",
|
||||
"KYC_OAUTH2_URL",
|
||||
"KYC_OAUTH2_AUTH_URL",
|
||||
&s))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange-kyc-oauth2",
|
||||
"KYC_OAUTH2_URL");
|
||||
"KYC_OAUTH2_AUTH_URL");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if ( (! TALER_url_valid_charset (s)) ||
|
||||
@ -1339,12 +1562,40 @@ parse_kyc_oauth_cfg (void)
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange-kyc-oauth2",
|
||||
"KYC_OAUTH2_URL",
|
||||
"KYC_OAUTH2_AUTH_URL",
|
||||
"not a valid URL");
|
||||
GNUNET_free (s);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TEH_kyc_config.details.oauth2.url = s;
|
||||
TEH_kyc_config.details.oauth2.auth_url = s;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
|
||||
"exchange-kyc-oauth2",
|
||||
"KYC_OAUTH2_LOGIN_URL",
|
||||
&s))
|
||||
{
|
||||
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange-kyc-oauth2",
|
||||
"KYC_OAUTH2_LOGIN_URL");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if ( (! TALER_url_valid_charset (s)) ||
|
||||
( (0 != strncasecmp (s,
|
||||
"http://",
|
||||
strlen ("http://"))) &&
|
||||
(0 != strncasecmp (s,
|
||||
"https://",
|
||||
strlen ("https://"))) ) )
|
||||
{
|
||||
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||
"exchange-kyc-oauth2",
|
||||
"KYC_OAUTH2_LOGIN_URL",
|
||||
"not a valid URL");
|
||||
GNUNET_free (s);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TEH_kyc_config.details.oauth2.login_url = s;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
|
||||
@ -1834,6 +2085,7 @@ do_shutdown (void *cls)
|
||||
mhd = TALER_MHD_daemon_stop ();
|
||||
TEH_resume_keys_requests (true);
|
||||
TEH_reserves_get_cleanup ();
|
||||
TEH_purses_get_cleanup ();
|
||||
TEH_kyc_check_cleanup ();
|
||||
TEH_kyc_proof_cleanup ();
|
||||
if (NULL != mhd)
|
||||
|
@ -93,8 +93,14 @@ struct TEH_KycOptions
|
||||
|
||||
/**
|
||||
* URL of the OAuth2.0 endpoint for KYC checks.
|
||||
* (token/auth)
|
||||
*/
|
||||
char *url;
|
||||
char *auth_url;
|
||||
|
||||
/**
|
||||
* URL of the OAuth2.0 endpoint for KYC checks.
|
||||
*/
|
||||
char *login_url;
|
||||
|
||||
/**
|
||||
* URL of the user info access endpoint.
|
||||
@ -190,7 +196,6 @@ extern char *TEH_currency;
|
||||
* Age restriction extension state
|
||||
*/
|
||||
extern bool TEH_age_restriction_enabled;
|
||||
extern struct TALER_AgeMask TEH_age_mask;
|
||||
|
||||
/**
|
||||
* Our (externally visible) base URL.
|
||||
|
@ -140,6 +140,7 @@ add_auditor_denom_sig (void *cls,
|
||||
TALER_B2S (awc->auditor_pub));
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
|
||||
if (GNUNET_OK !=
|
||||
TALER_auditor_denom_validity_verify (
|
||||
auditor_url,
|
||||
@ -213,7 +214,7 @@ TEH_handler_auditors (
|
||||
return MHD_YES; /* failure */
|
||||
ret = TEH_DB_run_transaction (connection,
|
||||
"add auditor denom sig",
|
||||
TEH_MT_OTHER,
|
||||
TEH_MT_REQUEST_OTHER,
|
||||
&res,
|
||||
&add_auditor_denom_sig,
|
||||
&awc);
|
||||
|
691
src/exchange/taler-exchange-httpd_batch-withdraw.c
Normal file
691
src/exchange/taler-exchange-httpd_batch-withdraw.c
Normal file
@ -0,0 +1,691 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software 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,
|
||||
see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file taler-exchange-httpd_batch-withdraw.c
|
||||
* @brief Handle /reserves/$RESERVE_PUB/batch-withdraw requests
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <jansson.h>
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_mhd_lib.h"
|
||||
#include "taler-exchange-httpd_batch-withdraw.h"
|
||||
#include "taler-exchange-httpd_responses.h"
|
||||
#include "taler-exchange-httpd_keys.h"
|
||||
|
||||
|
||||
/**
|
||||
* Information per planchet in the batch.
|
||||
*/
|
||||
struct PlanchetContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Hash of the (blinded) message to be signed by the Exchange.
|
||||
*/
|
||||
struct TALER_BlindedCoinHashP h_coin_envelope;
|
||||
|
||||
/**
|
||||
* Value of the coin being exchanged (matching the denomination key)
|
||||
* plus the transaction fee. We include this in what is being
|
||||
* signed so that we can verify a reserve's remaining total balance
|
||||
* without needing to access the respective denomination key
|
||||
* information each time.
|
||||
*/
|
||||
struct TALER_Amount amount_with_fee;
|
||||
|
||||
/**
|
||||
* Blinded planchet.
|
||||
*/
|
||||
struct TALER_BlindedPlanchet blinded_planchet;
|
||||
|
||||
/**
|
||||
* Set to the resulting signed coin data to be returned to the client.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_CollectableBlindcoin collectable;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Context for #batch_withdraw_transaction.
|
||||
*/
|
||||
struct BatchWithdrawContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Public key of the reserv.
|
||||
*/
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub;
|
||||
|
||||
/**
|
||||
* KYC status of the reserve used for the operation.
|
||||
*/
|
||||
struct TALER_EXCHANGEDB_KycStatus kyc;
|
||||
|
||||
/**
|
||||
* Array of @e planchets_length planchets we are processing.
|
||||
*/
|
||||
struct PlanchetContext *planchets;
|
||||
|
||||
/**
|
||||
* Total amount from all coins with fees.
|
||||
*/
|
||||
struct TALER_Amount batch_total;
|
||||
|
||||
/**
|
||||
* Length of the @e planchets array.
|
||||
*/
|
||||
unsigned int planchets_length;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function implementing withdraw transaction. Runs the
|
||||
* transaction logic; IF it returns a non-error code, the transaction
|
||||
* logic MUST NOT queue a MHD response. IF it returns an hard error,
|
||||
* the transaction logic MUST queue a MHD response and set @a mhd_ret.
|
||||
* IF it returns the soft error code, the function MAY be called again
|
||||
* to retry and MUST not queue a MHD response.
|
||||
*
|
||||
* Note that "wc->collectable.sig" is set before entering this function as we
|
||||
* signed before entering the transaction.
|
||||
*
|
||||
* @param cls a `struct BatchWithdrawContext *`
|
||||
* @param connection MHD request which triggered the transaction
|
||||
* @param[out] mhd_ret set to MHD response status for @a connection,
|
||||
* if transaction failed (!)
|
||||
* @return transaction status
|
||||
*/
|
||||
static enum GNUNET_DB_QueryStatus
|
||||
batch_withdraw_transaction (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
MHD_RESULT *mhd_ret)
|
||||
{
|
||||
struct BatchWithdrawContext *wc = cls;
|
||||
struct GNUNET_TIME_Timestamp now;
|
||||
uint64_t ruuid;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
bool balance_ok = false;
|
||||
bool found = false;
|
||||
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
qs = TEH_plugin->do_batch_withdraw (TEH_plugin->cls,
|
||||
now,
|
||||
wc->reserve_pub,
|
||||
&wc->batch_total,
|
||||
&found,
|
||||
&balance_ok,
|
||||
&wc->kyc,
|
||||
&ruuid);
|
||||
if (0 > qs)
|
||||
{
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"update_reserve_batch_withdraw");
|
||||
return qs;
|
||||
}
|
||||
if (! found)
|
||||
{
|
||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN,
|
||||
NULL);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
if (! balance_ok)
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls);
|
||||
*mhd_ret = TEH_RESPONSE_reply_reserve_insufficient_balance (
|
||||
connection,
|
||||
&wc->batch_total,
|
||||
wc->reserve_pub);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
|
||||
if ( (TEH_KYC_NONE != TEH_kyc_config.mode) &&
|
||||
(! wc->kyc.ok) &&
|
||||
(TALER_EXCHANGEDB_KYC_W2W == wc->kyc.type) )
|
||||
{
|
||||
/* Wallet-to-wallet payments _always_ require KYC */
|
||||
*mhd_ret = TALER_MHD_REPLY_JSON_PACK (
|
||||
connection,
|
||||
MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
|
||||
GNUNET_JSON_pack_uint64 ("payment_target_uuid",
|
||||
wc->kyc.payment_target_uuid));
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
if ( (TEH_KYC_NONE != TEH_kyc_config.mode) &&
|
||||
(! wc->kyc.ok) &&
|
||||
(TALER_EXCHANGEDB_KYC_WITHDRAW == wc->kyc.type) &&
|
||||
(! GNUNET_TIME_relative_is_zero (TEH_kyc_config.withdraw_period)) )
|
||||
{
|
||||
/* Withdraws require KYC if above threshold */
|
||||
enum GNUNET_DB_QueryStatus qs2;
|
||||
bool below_limit;
|
||||
|
||||
qs2 = TEH_plugin->do_withdraw_limit_check (
|
||||
TEH_plugin->cls,
|
||||
ruuid,
|
||||
GNUNET_TIME_absolute_subtract (now.abs_time,
|
||||
TEH_kyc_config.withdraw_period),
|
||||
&TEH_kyc_config.withdraw_limit,
|
||||
&below_limit);
|
||||
if (0 > qs2)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs2);
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs2)
|
||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"do_withdraw_limit_check");
|
||||
return qs2;
|
||||
}
|
||||
if (! below_limit)
|
||||
{
|
||||
*mhd_ret = TALER_MHD_REPLY_JSON_PACK (
|
||||
connection,
|
||||
MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS,
|
||||
GNUNET_JSON_pack_uint64 ("payment_target_uuid",
|
||||
wc->kyc.payment_target_uuid));
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add information about each planchet in the batch */
|
||||
for (unsigned int i = 0; i<wc->planchets_length; i++)
|
||||
{
|
||||
struct PlanchetContext *pc = &wc->planchets[i];
|
||||
const struct TALER_BlindedPlanchet *bp = &pc->blinded_planchet;
|
||||
const struct TALER_CsNonce *nonce;
|
||||
bool denom_unknown = true;
|
||||
bool conflict = true;
|
||||
bool nonce_reuse = true;
|
||||
|
||||
nonce = (TALER_DENOMINATION_CS == bp->cipher)
|
||||
? &bp->details.cs_blinded_planchet.nonce
|
||||
: NULL;
|
||||
qs = TEH_plugin->do_batch_withdraw_insert (TEH_plugin->cls,
|
||||
nonce,
|
||||
&pc->collectable,
|
||||
now,
|
||||
ruuid,
|
||||
&denom_unknown,
|
||||
&conflict,
|
||||
&nonce_reuse);
|
||||
if (0 > qs)
|
||||
{
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"do_withdraw");
|
||||
return qs;
|
||||
}
|
||||
if (denom_unknown)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
|
||||
NULL);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) ||
|
||||
(conflict) )
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Idempotent coin in batch, not allowed. Aborting.\n");
|
||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_CONFLICT,
|
||||
TALER_EC_EXCHANGE_WITHDRAW_BATCH_IDEMPOTENT_PLANCHET,
|
||||
NULL);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
if (nonce_reuse)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
*mhd_ret = TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_WITHDRAW_NONCE_REUSE,
|
||||
NULL);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
}
|
||||
TEH_METRICS_num_success[TEH_MT_SUCCESS_BATCH_WITHDRAW]++;
|
||||
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates our final (successful) response.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param wc operation context
|
||||
* @return MHD queue status
|
||||
*/
|
||||
static MHD_RESULT
|
||||
generate_reply_success (const struct TEH_RequestContext *rc,
|
||||
const struct BatchWithdrawContext *wc)
|
||||
{
|
||||
json_t *sigs;
|
||||
|
||||
sigs = json_array ();
|
||||
GNUNET_assert (NULL != sigs);
|
||||
for (unsigned int i = 0; i<wc->planchets_length; i++)
|
||||
{
|
||||
struct PlanchetContext *pc = &wc->planchets[i];
|
||||
|
||||
GNUNET_assert (
|
||||
0 ==
|
||||
json_array_append_new (
|
||||
sigs,
|
||||
GNUNET_JSON_PACK (
|
||||
TALER_JSON_pack_blinded_denom_sig (
|
||||
"ev_sig",
|
||||
&pc->collectable.sig))));
|
||||
}
|
||||
TEH_METRICS_batch_withdraw_num_coins += wc->planchets_length;
|
||||
return TALER_MHD_REPLY_JSON_PACK (
|
||||
rc->connection,
|
||||
MHD_HTTP_OK,
|
||||
GNUNET_JSON_pack_array_steal ("ev_sigs",
|
||||
sigs));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the @a rc is replayed and we already have an
|
||||
* answer. If so, replay the existing answer and return the
|
||||
* HTTP response.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param wc parsed request data
|
||||
* @param[out] mret HTTP status, set if we return true
|
||||
* @return true if the request is idempotent with an existing request
|
||||
* false if we did not find the request in the DB and did not set @a mret
|
||||
*/
|
||||
static bool
|
||||
check_request_idempotent (const struct TEH_RequestContext *rc,
|
||||
const struct BatchWithdrawContext *wc,
|
||||
MHD_RESULT *mret)
|
||||
{
|
||||
for (unsigned int i = 0; i<wc->planchets_length; i++)
|
||||
{
|
||||
struct PlanchetContext *pc = &wc->planchets[i];
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = TEH_plugin->get_withdraw_info (TEH_plugin->cls,
|
||||
&pc->h_coin_envelope,
|
||||
&pc->collectable);
|
||||
if (0 > qs)
|
||||
{
|
||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
*mret = TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"get_withdraw_info");
|
||||
return true; /* well, kind-of */
|
||||
}
|
||||
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
|
||||
return false;
|
||||
}
|
||||
/* generate idempotent reply */
|
||||
TEH_METRICS_num_requests[TEH_MT_REQUEST_IDEMPOTENT_BATCH_WITHDRAW]++;
|
||||
*mret = generate_reply_success (rc,
|
||||
wc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The request was parsed successfully. Prepare
|
||||
* our side for the main DB transaction.
|
||||
*
|
||||
* @param rc request details
|
||||
* @param wc storage for request processing
|
||||
* @return MHD result for the @a rc
|
||||
*/
|
||||
static MHD_RESULT
|
||||
prepare_transaction (const struct TEH_RequestContext *rc,
|
||||
struct BatchWithdrawContext *wc)
|
||||
{
|
||||
/* Note: We could check the reserve balance here,
|
||||
just to be reasonably sure that the reserve has
|
||||
a sufficient balance before doing the "expensive"
|
||||
signatures... */
|
||||
/* Sign before transaction! */
|
||||
for (unsigned int i = 0; i<wc->planchets_length; i++)
|
||||
{
|
||||
struct PlanchetContext *pc = &wc->planchets[i];
|
||||
enum TALER_ErrorCode ec;
|
||||
|
||||
ec = TEH_keys_denomination_sign_withdraw (
|
||||
&pc->collectable.denom_pub_hash,
|
||||
&pc->blinded_planchet,
|
||||
&pc->collectable.sig);
|
||||
if (TALER_EC_NONE != ec)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_ec (rc->connection,
|
||||
ec,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* run transaction */
|
||||
{
|
||||
MHD_RESULT mhd_ret;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (rc->connection,
|
||||
"run batch withdraw",
|
||||
TEH_MT_REQUEST_WITHDRAW,
|
||||
&mhd_ret,
|
||||
&batch_withdraw_transaction,
|
||||
wc))
|
||||
{
|
||||
return mhd_ret;
|
||||
}
|
||||
}
|
||||
/* return final positive response */
|
||||
return generate_reply_success (rc,
|
||||
wc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Continue processing the request @a rc by parsing the
|
||||
* @a planchets and then running the transaction.
|
||||
*
|
||||
* @param rc request details
|
||||
* @param wc storage for request processing
|
||||
* @param planchets array of planchets to parse
|
||||
* @return MHD result for the @a rc
|
||||
*/
|
||||
static MHD_RESULT
|
||||
parse_planchets (const struct TEH_RequestContext *rc,
|
||||
struct BatchWithdrawContext *wc,
|
||||
const json_t *planchets)
|
||||
{
|
||||
struct TEH_KeyStateHandle *ksh;
|
||||
MHD_RESULT mret;
|
||||
|
||||
for (unsigned int i = 0; i<wc->planchets_length; i++)
|
||||
{
|
||||
struct PlanchetContext *pc = &wc->planchets[i];
|
||||
struct GNUNET_JSON_Specification ispec[] = {
|
||||
GNUNET_JSON_spec_fixed_auto ("reserve_sig",
|
||||
&pc->collectable.reserve_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
|
||||
&pc->collectable.denom_pub_hash),
|
||||
TALER_JSON_spec_blinded_planchet ("coin_ev",
|
||||
&pc->blinded_planchet),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
|
||||
res = TALER_MHD_parse_json_data (rc->connection,
|
||||
json_array_get (planchets,
|
||||
i),
|
||||
ispec);
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
}
|
||||
pc->collectable.reserve_pub = *wc->reserve_pub;
|
||||
for (unsigned int k = 0; k<i; k++)
|
||||
{
|
||||
const struct PlanchetContext *kpc = &wc->planchets[k];
|
||||
|
||||
if (0 ==
|
||||
TALER_blinded_planchet_cmp (&kpc->blinded_planchet,
|
||||
&pc->blinded_planchet))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"duplicate planchet");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ksh = TEH_keys_get_state ();
|
||||
if (NULL == ksh)
|
||||
{
|
||||
if (! check_request_idempotent (rc,
|
||||
wc,
|
||||
&mret))
|
||||
{
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||
NULL);
|
||||
}
|
||||
return mret;
|
||||
}
|
||||
for (unsigned int i = 0; i<wc->planchets_length; i++)
|
||||
{
|
||||
struct PlanchetContext *pc = &wc->planchets[i];
|
||||
struct TEH_DenominationKey *dk;
|
||||
|
||||
dk = TEH_keys_denomination_by_hash2 (ksh,
|
||||
&pc->collectable.denom_pub_hash,
|
||||
NULL,
|
||||
NULL);
|
||||
if (NULL == dk)
|
||||
{
|
||||
if (! check_request_idempotent (rc,
|
||||
wc,
|
||||
&mret))
|
||||
{
|
||||
return TEH_RESPONSE_reply_unknown_denom_pub_hash (
|
||||
rc->connection,
|
||||
&pc->collectable.denom_pub_hash);
|
||||
}
|
||||
return mret;
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_withdraw.abs_time))
|
||||
{
|
||||
/* This denomination is past the expiration time for withdraws */
|
||||
if (! check_request_idempotent (rc,
|
||||
wc,
|
||||
&mret))
|
||||
{
|
||||
return TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
rc->connection,
|
||||
&pc->collectable.denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
|
||||
"WITHDRAW");
|
||||
}
|
||||
return mret;
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
|
||||
{
|
||||
/* This denomination is not yet valid, no need to check
|
||||
for idempotency! */
|
||||
return TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
rc->connection,
|
||||
&pc->collectable.denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
|
||||
"WITHDRAW");
|
||||
}
|
||||
if (dk->recoup_possible)
|
||||
{
|
||||
/* This denomination has been revoked */
|
||||
if (! check_request_idempotent (rc,
|
||||
wc,
|
||||
&mret))
|
||||
{
|
||||
return TEH_RESPONSE_reply_expired_denom_pub_hash (
|
||||
rc->connection,
|
||||
&pc->collectable.denom_pub_hash,
|
||||
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
|
||||
"WITHDRAW");
|
||||
}
|
||||
return mret;
|
||||
}
|
||||
if (dk->denom_pub.cipher != pc->blinded_planchet.cipher)
|
||||
{
|
||||
/* denomination cipher and blinded planchet cipher not the same */
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_GENERIC_CIPHER_MISMATCH,
|
||||
NULL);
|
||||
}
|
||||
if (0 >
|
||||
TALER_amount_add (&pc->collectable.amount_with_fee,
|
||||
&dk->meta.value,
|
||||
&dk->meta.fees.withdraw))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
|
||||
NULL);
|
||||
}
|
||||
if (0 >
|
||||
TALER_amount_add (&wc->batch_total,
|
||||
&wc->batch_total,
|
||||
&pc->collectable.amount_with_fee))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_coin_ev_hash (&pc->blinded_planchet,
|
||||
&pc->collectable.denom_pub_hash,
|
||||
&pc->collectable.h_coin_envelope))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
|
||||
NULL);
|
||||
}
|
||||
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_withdraw_verify (&pc->collectable.denom_pub_hash,
|
||||
&pc->collectable.amount_with_fee,
|
||||
&pc->collectable.h_coin_envelope,
|
||||
&pc->collectable.reserve_pub,
|
||||
&pc->collectable.reserve_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
/* everything parsed */
|
||||
return prepare_transaction (rc,
|
||||
wc);
|
||||
}
|
||||
|
||||
|
||||
MHD_RESULT
|
||||
TEH_handler_batch_withdraw (struct TEH_RequestContext *rc,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
const json_t *root)
|
||||
{
|
||||
struct BatchWithdrawContext wc;
|
||||
json_t *planchets;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_json ("planchets",
|
||||
&planchets),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
memset (&wc,
|
||||
0,
|
||||
sizeof (wc));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_set_zero (TEH_currency,
|
||||
&wc.batch_total));
|
||||
wc.reserve_pub = reserve_pub;
|
||||
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
|
||||
res = TALER_MHD_parse_json_data (rc->connection,
|
||||
root,
|
||||
spec);
|
||||
if (GNUNET_OK != res)
|
||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
||||
}
|
||||
if ( (! json_is_array (planchets)) ||
|
||||
(0 == json_array_size (planchets)) )
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"planchets");
|
||||
}
|
||||
wc.planchets_length = json_array_size (planchets);
|
||||
if (wc.planchets_length > TALER_MAX_FRESH_COINS)
|
||||
{
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"too many planchets");
|
||||
}
|
||||
{
|
||||
struct PlanchetContext splanchets[wc.planchets_length];
|
||||
MHD_RESULT ret;
|
||||
|
||||
memset (splanchets,
|
||||
0,
|
||||
sizeof (splanchets));
|
||||
wc.planchets = splanchets;
|
||||
ret = parse_planchets (rc,
|
||||
&wc,
|
||||
planchets);
|
||||
/* Clean up */
|
||||
for (unsigned int i = 0; i<wc.planchets_length; i++)
|
||||
{
|
||||
struct PlanchetContext *pc = &wc.planchets[i];
|
||||
|
||||
TALER_blinded_planchet_free (&pc->blinded_planchet);
|
||||
TALER_blinded_denom_sig_free (&pc->collectable.sig);
|
||||
}
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* end of taler-exchange-httpd_batch-withdraw.c */
|
48
src/exchange/taler-exchange-httpd_batch-withdraw.h
Normal file
48
src/exchange/taler-exchange-httpd_batch-withdraw.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
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, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file taler-exchange-httpd_batch-withdraw.h
|
||||
* @brief Handle /reserve/batch-withdraw requests
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#ifndef TALER_EXCHANGE_HTTPD_BATCH_WITHDRAW_H
|
||||
#define TALER_EXCHANGE_HTTPD_BATCH_WITHDRAW_H
|
||||
|
||||
#include <microhttpd.h>
|
||||
#include "taler-exchange-httpd.h"
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/reserves/$RESERVE_PUB/batch-withdraw" request. Parses the batch of
|
||||
* requested "denom_pub" which specifies the key/value of the coin to be
|
||||
* withdrawn, and checks that the signature "reserve_sig" makes this a valid
|
||||
* withdrawal request from the specified reserve. If so, the envelope with
|
||||
* the blinded coin "coin_ev" is passed down to execute the withdrawal
|
||||
* operation.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param root uploaded JSON data
|
||||
* @param reserve_pub public key of the reserve
|
||||
* @return MHD result code
|
||||
*/
|
||||
MHD_RESULT
|
||||
TEH_handler_batch_withdraw (struct TEH_RequestContext *rc,
|
||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
const json_t *root);
|
||||
|
||||
#endif
|
99
src/exchange/taler-exchange-httpd_contract.c
Normal file
99
src/exchange/taler-exchange-httpd_contract.c
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
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, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file taler-exchange-httpd_contract.c
|
||||
* @brief Handle GET /contracts/$C_PUB requests
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <jansson.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler_mhd_lib.h"
|
||||
#include "taler-exchange-httpd_contract.h"
|
||||
#include "taler-exchange-httpd_mhd.h"
|
||||
#include "taler-exchange-httpd_responses.h"
|
||||
|
||||
|
||||
MHD_RESULT
|
||||
TEH_handler_contracts_get (struct TEH_RequestContext *rc,
|
||||
const char *const args[1])
|
||||
{
|
||||
struct TALER_ContractDiffiePublicP contract_pub;
|
||||
struct TALER_PurseContractPublicKeyP purse_pub;
|
||||
void *econtract;
|
||||
size_t econtract_size;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
struct TALER_PurseContractSignatureP econtract_sig;
|
||||
MHD_RESULT res;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (args[0],
|
||||
strlen (args[0]),
|
||||
&contract_pub,
|
||||
sizeof (contract_pub)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_CONTRACTS_INVALID_CONTRACT_PUB,
|
||||
args[0]);
|
||||
}
|
||||
|
||||
qs = TEH_plugin->select_contract (TEH_plugin->cls,
|
||||
&contract_pub,
|
||||
&purse_pub,
|
||||
&econtract_sig,
|
||||
&econtract_size,
|
||||
&econtract);
|
||||
switch (qs)
|
||||
{
|
||||
case GNUNET_DB_STATUS_HARD_ERROR:
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"select_contract");
|
||||
case GNUNET_DB_STATUS_SOFT_ERROR:
|
||||
GNUNET_break (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_DB_FETCH_FAILED,
|
||||
"select_contract");
|
||||
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_NOT_FOUND,
|
||||
TALER_EC_EXCHANGE_CONTRACTS_UNKNOWN,
|
||||
NULL);
|
||||
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
|
||||
break; /* handled below */
|
||||
}
|
||||
res = TALER_MHD_REPLY_JSON_PACK (
|
||||
rc->connection,
|
||||
MHD_HTTP_OK,
|
||||
GNUNET_JSON_pack_data_auto ("purse_pub",
|
||||
&purse_pub),
|
||||
GNUNET_JSON_pack_data_auto ("econtract_sig",
|
||||
&econtract_sig),
|
||||
GNUNET_JSON_pack_data_varsize ("econtract",
|
||||
econtract,
|
||||
econtract_size));
|
||||
GNUNET_free (econtract);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* end of taler-exchange-httpd_contract.c */
|
44
src/exchange/taler-exchange-httpd_contract.h
Normal file
44
src/exchange/taler-exchange-httpd_contract.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
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, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
/**
|
||||
* @file taler-exchange-httpd_contract.h
|
||||
* @brief Handle /coins/$COIN_PUB/contract requests
|
||||
* @author Florian Dold
|
||||
* @author Benedikt Mueller
|
||||
* @author Christian Grothoff
|
||||
*/
|
||||
#ifndef TALER_EXCHANGE_HTTPD_CONTRACT_H
|
||||
#define TALER_EXCHANGE_HTTPD_CONTRACT_H
|
||||
|
||||
#include <gnunet/gnunet_util_lib.h>
|
||||
#include <microhttpd.h>
|
||||
#include "taler-exchange-httpd.h"
|
||||
|
||||
|
||||
/**
|
||||
* Handle a GET "/contracts/$C_PUB" request. Returns the
|
||||
* encrypted contract.
|
||||
*
|
||||
* @param rc request context
|
||||
* @param args array of additional options (length: 1, first is the contract_pub)
|
||||
* @return MHD result code
|
||||
*/
|
||||
MHD_RESULT
|
||||
TEH_handler_contracts_get (struct TEH_RequestContext *rc,
|
||||
const char *const args[1]);
|
||||
|
||||
|
||||
#endif
|
@ -61,15 +61,19 @@ TEH_make_coin_known (const struct TALER_CoinPublicInfo *coin,
|
||||
NULL);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
case TALER_EXCHANGEDB_CKS_DENOM_CONFLICT:
|
||||
/* FIXME-Oec: insufficient_funds != denom conflict! */
|
||||
*mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||
connection,
|
||||
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY,
|
||||
&h_denom_pub,
|
||||
&coin->coin_pub);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
case TALER_EXCHANGEDB_CKS_AGE_CONFLICT:
|
||||
/* FIXME-Oec: insufficient_funds != Age conflict! */
|
||||
*mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||
connection,
|
||||
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
|
||||
&h_denom_pub,
|
||||
&coin->coin_pub);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
@ -81,7 +85,7 @@ TEH_make_coin_known (const struct TALER_CoinPublicInfo *coin,
|
||||
enum GNUNET_GenericReturnValue
|
||||
TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||
const char *name,
|
||||
enum TEH_MetricType mt,
|
||||
enum TEH_MetricTypeRequest mt,
|
||||
MHD_RESULT *mhd_ret,
|
||||
TEH_DB_TransactionCallback cb,
|
||||
void *cb_cls)
|
||||
@ -99,7 +103,7 @@ TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||
NULL);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_assert (mt < TEH_MT_COUNT);
|
||||
GNUNET_assert (mt < TEH_MT_REQUEST_COUNT);
|
||||
TEH_METRICS_num_requests[mt]++;
|
||||
for (unsigned int retries = 0;
|
||||
retries < MAX_TRANSACTION_COMMIT_RETRIES;
|
||||
@ -123,10 +127,12 @@ TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||
connection,
|
||||
mhd_ret);
|
||||
if (0 > qs)
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls);
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
return GNUNET_SYSERR;
|
||||
if (0 <= qs)
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
qs = TEH_plugin->commit (TEH_plugin->cls);
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
@ -149,6 +155,7 @@ TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||
return GNUNET_OK;
|
||||
TEH_METRICS_num_conflict[mt]++;
|
||||
}
|
||||
TEH_plugin->rollback (TEH_plugin->cls);
|
||||
TALER_LOG_ERROR ("Transaction `%s' commit failed %u times\n",
|
||||
name,
|
||||
MAX_TRANSACTION_COMMIT_RETRIES);
|
||||
|
@ -96,7 +96,7 @@ typedef enum GNUNET_DB_QueryStatus
|
||||
enum GNUNET_GenericReturnValue
|
||||
TEH_DB_run_transaction (struct MHD_Connection *connection,
|
||||
const char *name,
|
||||
enum TEH_MetricType mt,
|
||||
enum TEH_MetricTypeRequest mt,
|
||||
MHD_RESULT *mhd_ret,
|
||||
TEH_DB_TransactionCallback cb,
|
||||
void *cb_cls);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2014-2021 Taler Systems SA
|
||||
Copyright (C) 2014-2022 Taler Systems SA
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU Affero General Public License as published by the Free Software
|
||||
@ -57,41 +57,36 @@
|
||||
* @return MHD result code
|
||||
*/
|
||||
static MHD_RESULT
|
||||
reply_deposit_success (struct MHD_Connection *connection,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_MerchantWireHashP *h_wire,
|
||||
const struct TALER_ExtensionContractHashP *h_extensions,
|
||||
const struct
|
||||
TALER_PrivateContractHashP *h_contract_terms,
|
||||
struct GNUNET_TIME_Timestamp exchange_timestamp,
|
||||
struct GNUNET_TIME_Timestamp refund_deadline,
|
||||
struct GNUNET_TIME_Timestamp wire_deadline,
|
||||
const struct TALER_MerchantPublicKeyP *merchant,
|
||||
const struct TALER_Amount *amount_without_fee)
|
||||
reply_deposit_success (
|
||||
struct MHD_Connection *connection,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_MerchantWireHashP *h_wire,
|
||||
const struct TALER_ExtensionContractHashP *h_extensions,
|
||||
const struct TALER_PrivateContractHashP *h_contract_terms,
|
||||
struct GNUNET_TIME_Timestamp exchange_timestamp,
|
||||
struct GNUNET_TIME_Timestamp refund_deadline,
|
||||
struct GNUNET_TIME_Timestamp wire_deadline,
|
||||
const struct TALER_MerchantPublicKeyP *merchant,
|
||||
const struct TALER_Amount *amount_without_fee)
|
||||
{
|
||||
struct TALER_ExchangePublicKeyP pub;
|
||||
struct TALER_ExchangeSignatureP sig;
|
||||
struct TALER_DepositConfirmationPS dc = {
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
|
||||
.purpose.size = htonl (sizeof (dc)),
|
||||
.h_contract_terms = *h_contract_terms,
|
||||
.h_wire = *h_wire,
|
||||
.exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
|
||||
.refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
|
||||
.wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
|
||||
.coin_pub = *coin_pub,
|
||||
.merchant_pub = *merchant
|
||||
};
|
||||
enum TALER_ErrorCode ec;
|
||||
|
||||
if (NULL != h_extensions)
|
||||
dc.h_extensions = *h_extensions;
|
||||
TALER_amount_hton (&dc.amount_without_fee,
|
||||
amount_without_fee);
|
||||
if (TALER_EC_NONE !=
|
||||
(ec = TEH_keys_exchange_sign (&dc,
|
||||
&pub,
|
||||
&sig)))
|
||||
(ec = TALER_exchange_online_deposit_confirmation_sign (
|
||||
&TEH_keys_exchange_sign_,
|
||||
h_contract_terms,
|
||||
h_wire,
|
||||
h_extensions,
|
||||
exchange_timestamp,
|
||||
wire_deadline,
|
||||
refund_deadline,
|
||||
amount_without_fee,
|
||||
coin_pub,
|
||||
merchant,
|
||||
&pub,
|
||||
&sig)))
|
||||
{
|
||||
return TALER_MHD_reply_with_ec (connection,
|
||||
ec,
|
||||
@ -162,6 +157,12 @@ deposit_transaction (void *cls,
|
||||
bool balance_ok;
|
||||
bool in_conflict;
|
||||
|
||||
qs = TEH_make_coin_known (&dc->deposit->coin,
|
||||
connection,
|
||||
&dc->known_coin_id,
|
||||
mhd_ret);
|
||||
if (qs < 0)
|
||||
return qs;
|
||||
qs = TEH_plugin->do_deposit (TEH_plugin->cls,
|
||||
dc->deposit,
|
||||
dc->known_coin_id,
|
||||
@ -183,40 +184,30 @@ deposit_transaction (void *cls,
|
||||
}
|
||||
if (in_conflict)
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls);
|
||||
/* FIXME: conficting contract != insufficient funds */
|
||||
*mhd_ret
|
||||
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||
connection,
|
||||
TALER_EC_EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT,
|
||||
&dc->deposit->coin.denom_pub_hash,
|
||||
&dc->deposit->coin.coin_pub);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
if (! balance_ok)
|
||||
{
|
||||
TEH_plugin->rollback (TEH_plugin->cls);
|
||||
*mhd_ret
|
||||
= TEH_RESPONSE_reply_coin_insufficient_funds (
|
||||
connection,
|
||||
TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS,
|
||||
&dc->deposit->coin.denom_pub_hash,
|
||||
&dc->deposit->coin.coin_pub);
|
||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||
}
|
||||
TEH_METRICS_num_success[TEH_MT_SUCCESS_DEPOSIT]++;
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a "/coins/$COIN_PUB/deposit" request. Parses the JSON, and, if
|
||||
* successful, passes the JSON data to #deposit_transaction() to
|
||||
* further check the details of the operation specified. If everything checks
|
||||
* out, this will ultimately lead to the "/deposit" being executed, or
|
||||
* rejected.
|
||||
*
|
||||
* @param connection the MHD connection to handle
|
||||
* @param coin_pub public key of the coin
|
||||
* @param root uploaded JSON data
|
||||
* @return MHD result code
|
||||
*/
|
||||
MHD_RESULT
|
||||
TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
@ -243,14 +234,16 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
&deposit.h_contract_terms),
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||
&deposit.coin.h_age_commitment)),
|
||||
&deposit.coin.h_age_commitment),
|
||||
&deposit.coin.no_age_commitment),
|
||||
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||
&deposit.csig),
|
||||
GNUNET_JSON_spec_timestamp ("timestamp",
|
||||
&deposit.timestamp),
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
||||
&deposit.refund_deadline)),
|
||||
&deposit.refund_deadline),
|
||||
NULL),
|
||||
GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
|
||||
&deposit.wire_deadline),
|
||||
GNUNET_JSON_spec_end ()
|
||||
@ -340,6 +333,16 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return mret;
|
||||
}
|
||||
if (0 > TALER_amount_cmp (&dk->meta.value,
|
||||
&deposit.amount_with_fee))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_EXCHANGE_GENERIC_AMOUNT_EXCEEDS_DENOMINATION_VALUE,
|
||||
NULL);
|
||||
}
|
||||
if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit.abs_time))
|
||||
{
|
||||
/* This denomination is past the expiration time for deposits */
|
||||
@ -382,6 +385,17 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
|
||||
deposit.deposit_fee = dk->meta.fees.deposit;
|
||||
/* check coin signature */
|
||||
switch (dk->denom_pub.cipher)
|
||||
{
|
||||
case TALER_DENOMINATION_RSA:
|
||||
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_RSA]++;
|
||||
break;
|
||||
case TALER_DENOMINATION_CS:
|
||||
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_CS]++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (GNUNET_YES !=
|
||||
TALER_test_coin_valid (&deposit.coin,
|
||||
&dk->denom_pub))
|
||||
@ -389,7 +403,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_UNAUTHORIZED,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_EXCHANGE_DENOMINATION_SIGNATURE_INVALID,
|
||||
NULL);
|
||||
}
|
||||
@ -405,6 +419,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
NULL);
|
||||
}
|
||||
|
||||
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_deposit_verify (&deposit.amount_with_fee,
|
||||
&deposit.deposit_fee,
|
||||
@ -422,7 +437,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
TALER_LOG_WARNING ("Invalid signature on /deposit request\n");
|
||||
GNUNET_JSON_parse_free (spec);
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_UNAUTHORIZED,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_EXCHANGE_DEPOSIT_COIN_SIGNATURE_INVALID,
|
||||
NULL);
|
||||
}
|
||||
@ -437,6 +452,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
"preflight failure");
|
||||
}
|
||||
|
||||
#if NOT_MOVED
|
||||
{
|
||||
MHD_RESULT mhd_ret = MHD_NO;
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
@ -463,7 +479,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
if (qs < 0)
|
||||
return mhd_ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* execute transaction */
|
||||
{
|
||||
@ -472,7 +488,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"execute deposit",
|
||||
TEH_MT_DEPOSIT,
|
||||
TEH_MT_REQUEST_DEPOSIT,
|
||||
&mhd_ret,
|
||||
&deposit_transaction,
|
||||
&dc))
|
||||
|
@ -31,70 +31,6 @@
|
||||
#include "taler-exchange-httpd_responses.h"
|
||||
|
||||
|
||||
/**
|
||||
* A merchant asked for details about a deposit. Provide
|
||||
* them. Generates the 200 reply.
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param h_contract_terms hash of the contract
|
||||
* @param h_wire hash of wire account details
|
||||
* @param coin_pub public key of the coin
|
||||
* @param coin_contribution how much did the coin we asked about
|
||||
* contribute to the total transfer value? (deposit value minus fee)
|
||||
* @param wtid raw wire transfer identifier
|
||||
* @param exec_time execution time of the wire transfer
|
||||
* @return MHD result code
|
||||
*/
|
||||
static MHD_RESULT
|
||||
reply_deposit_details (struct MHD_Connection *connection,
|
||||
const struct
|
||||
TALER_PrivateContractHashP *h_contract_terms,
|
||||
const struct TALER_MerchantWireHashP *h_wire,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_Amount *coin_contribution,
|
||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||
struct GNUNET_TIME_Timestamp exec_time)
|
||||
{
|
||||
struct TALER_ExchangePublicKeyP pub;
|
||||
struct TALER_ExchangeSignatureP sig;
|
||||
struct TALER_ConfirmWirePS cw = {
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE),
|
||||
.purpose.size = htonl (sizeof (cw)),
|
||||
.h_wire = *h_wire,
|
||||
.h_contract_terms = *h_contract_terms,
|
||||
.wtid = *wtid,
|
||||
.coin_pub = *coin_pub,
|
||||
.execution_time = GNUNET_TIME_timestamp_hton (exec_time)
|
||||
};
|
||||
enum TALER_ErrorCode ec;
|
||||
|
||||
TALER_amount_hton (&cw.coin_contribution,
|
||||
coin_contribution);
|
||||
if (TALER_EC_NONE !=
|
||||
(ec = TEH_keys_exchange_sign (&cw,
|
||||
&pub,
|
||||
&sig)))
|
||||
{
|
||||
return TALER_MHD_reply_with_ec (connection,
|
||||
ec,
|
||||
NULL);
|
||||
}
|
||||
return TALER_MHD_REPLY_JSON_PACK (
|
||||
connection,
|
||||
MHD_HTTP_OK,
|
||||
GNUNET_JSON_pack_data_auto ("wtid",
|
||||
wtid),
|
||||
GNUNET_JSON_pack_timestamp ("execution_time",
|
||||
exec_time),
|
||||
TALER_JSON_pack_amount ("coin_contribution",
|
||||
coin_contribution),
|
||||
GNUNET_JSON_pack_data_auto ("exchange_sig",
|
||||
&sig),
|
||||
GNUNET_JSON_pack_data_auto ("exchange_pub",
|
||||
&pub));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closure for #handle_wtid_data.
|
||||
*/
|
||||
@ -102,14 +38,26 @@ struct DepositWtidContext
|
||||
{
|
||||
|
||||
/**
|
||||
* Deposit details.
|
||||
* Hash over the proposal data of the contract for which this deposit is made.
|
||||
*/
|
||||
const struct TALER_DepositTrackPS *tps;
|
||||
struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
|
||||
|
||||
/**
|
||||
* Public key of the merchant.
|
||||
* Hash over the wiring information of the merchant.
|
||||
*/
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub;
|
||||
struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
|
||||
|
||||
/**
|
||||
* The Merchant's public key. The deposit inquiry request is to be
|
||||
* signed by the corresponding private key (using EdDSA).
|
||||
*/
|
||||
struct TALER_MerchantPublicKeyP merchant;
|
||||
|
||||
/**
|
||||
* The coin's public key. This is the value that must have been
|
||||
* signed (blindly) by the Exchange.
|
||||
*/
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
|
||||
/**
|
||||
* Set by #handle_wtid data to the wire transfer ID.
|
||||
@ -151,6 +99,55 @@ struct DepositWtidContext
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A merchant asked for details about a deposit. Provide
|
||||
* them. Generates the 200 reply.
|
||||
*
|
||||
* @param connection connection to the client
|
||||
* @param ctx details to respond with
|
||||
* @return MHD result code
|
||||
*/
|
||||
static MHD_RESULT
|
||||
reply_deposit_details (
|
||||
struct MHD_Connection *connection,
|
||||
const struct DepositWtidContext *ctx)
|
||||
{
|
||||
struct TALER_ExchangePublicKeyP pub;
|
||||
struct TALER_ExchangeSignatureP sig;
|
||||
enum TALER_ErrorCode ec;
|
||||
|
||||
if (TALER_EC_NONE !=
|
||||
(ec = TALER_exchange_online_confirm_wire_sign (
|
||||
&TEH_keys_exchange_sign_,
|
||||
&ctx->h_wire,
|
||||
&ctx->h_contract_terms,
|
||||
&ctx->wtid,
|
||||
&ctx->coin_pub,
|
||||
ctx->execution_time,
|
||||
&ctx->coin_delta,
|
||||
&pub,
|
||||
&sig)))
|
||||
{
|
||||
return TALER_MHD_reply_with_ec (connection,
|
||||
ec,
|
||||
NULL);
|
||||
}
|
||||
return TALER_MHD_REPLY_JSON_PACK (
|
||||
connection,
|
||||
MHD_HTTP_OK,
|
||||
GNUNET_JSON_pack_data_auto ("wtid",
|
||||
&ctx->wtid),
|
||||
GNUNET_JSON_pack_timestamp ("execution_time",
|
||||
ctx->execution_time),
|
||||
TALER_JSON_pack_amount ("coin_contribution",
|
||||
&ctx->coin_delta),
|
||||
GNUNET_JSON_pack_data_auto ("exchange_sig",
|
||||
&sig),
|
||||
GNUNET_JSON_pack_data_auto ("exchange_pub",
|
||||
&pub));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a "deposits" GET. Returns the transfer information
|
||||
* associated with the given deposit.
|
||||
@ -178,11 +175,10 @@ deposits_get_transaction (void *cls,
|
||||
struct TALER_Amount fee;
|
||||
|
||||
qs = TEH_plugin->lookup_transfer_by_deposit (TEH_plugin->cls,
|
||||
&ctx->tps->h_contract_terms,
|
||||
&ctx->tps->h_wire,
|
||||
&ctx->tps->coin_pub,
|
||||
ctx->merchant_pub,
|
||||
|
||||
&ctx->h_contract_terms,
|
||||
&ctx->h_wire,
|
||||
&ctx->coin_pub,
|
||||
&ctx->merchant,
|
||||
&pending,
|
||||
&ctx->wtid,
|
||||
&ctx->execution_time,
|
||||
@ -228,52 +224,41 @@ deposits_get_transaction (void *cls,
|
||||
* Lookup and return the wire transfer identifier.
|
||||
*
|
||||
* @param connection the MHD connection to handle
|
||||
* @param tps signed request to execute
|
||||
* @param merchant_pub public key from the merchant
|
||||
* @param ctx context of the signed request to execute
|
||||
* @return MHD result code
|
||||
*/
|
||||
static MHD_RESULT
|
||||
handle_track_transaction_request (
|
||||
struct MHD_Connection *connection,
|
||||
const struct TALER_DepositTrackPS *tps,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub)
|
||||
struct DepositWtidContext *ctx)
|
||||
{
|
||||
MHD_RESULT mhd_ret;
|
||||
struct DepositWtidContext ctx = {
|
||||
.tps = tps,
|
||||
.merchant_pub = merchant_pub
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TEH_DB_run_transaction (connection,
|
||||
"handle deposits GET",
|
||||
TEH_MT_OTHER,
|
||||
TEH_MT_REQUEST_OTHER,
|
||||
&mhd_ret,
|
||||
&deposits_get_transaction,
|
||||
&ctx))
|
||||
ctx))
|
||||
return mhd_ret;
|
||||
if (GNUNET_SYSERR == ctx.pending)
|
||||
if (GNUNET_SYSERR == ctx->pending)
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
|
||||
"wire fees exceed aggregate in database");
|
||||
if (GNUNET_YES == ctx.pending)
|
||||
if (GNUNET_YES == ctx->pending)
|
||||
return TALER_MHD_REPLY_JSON_PACK (
|
||||
connection,
|
||||
MHD_HTTP_ACCEPTED,
|
||||
GNUNET_JSON_pack_uint64 ("payment_target_uuid",
|
||||
ctx.kyc.payment_target_uuid),
|
||||
ctx->kyc.payment_target_uuid),
|
||||
GNUNET_JSON_pack_bool ("kyc_ok",
|
||||
ctx.kyc.ok),
|
||||
ctx->kyc.ok),
|
||||
GNUNET_JSON_pack_timestamp ("execution_time",
|
||||
ctx.execution_time));
|
||||
ctx->execution_time));
|
||||
return reply_deposit_details (connection,
|
||||
&tps->h_contract_terms,
|
||||
&tps->h_wire,
|
||||
&tps->coin_pub,
|
||||
&ctx.coin_delta,
|
||||
&ctx.wtid,
|
||||
ctx.execution_time);
|
||||
ctx);
|
||||
}
|
||||
|
||||
|
||||
@ -283,16 +268,13 @@ TEH_handler_deposits_get (struct TEH_RequestContext *rc,
|
||||
{
|
||||
enum GNUNET_GenericReturnValue res;
|
||||
struct TALER_MerchantSignatureP merchant_sig;
|
||||
struct TALER_DepositTrackPS tps = {
|
||||
.purpose.size = htonl (sizeof (tps)),
|
||||
.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION)
|
||||
};
|
||||
struct DepositWtidContext ctx;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (args[0],
|
||||
strlen (args[0]),
|
||||
&tps.h_wire,
|
||||
sizeof (tps.h_wire)))
|
||||
&ctx.h_wire,
|
||||
sizeof (ctx.h_wire)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
@ -303,8 +285,8 @@ TEH_handler_deposits_get (struct TEH_RequestContext *rc,
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (args[1],
|
||||
strlen (args[1]),
|
||||
&tps.merchant,
|
||||
sizeof (tps.merchant)))
|
||||
&ctx.merchant,
|
||||
sizeof (ctx.merchant)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
@ -315,8 +297,8 @@ TEH_handler_deposits_get (struct TEH_RequestContext *rc,
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (args[2],
|
||||
strlen (args[2]),
|
||||
&tps.h_contract_terms,
|
||||
sizeof (tps.h_contract_terms)))
|
||||
&ctx.h_contract_terms,
|
||||
sizeof (ctx.h_contract_terms)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
@ -327,8 +309,8 @@ TEH_handler_deposits_get (struct TEH_RequestContext *rc,
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (args[3],
|
||||
strlen (args[3]),
|
||||
&tps.coin_pub,
|
||||
sizeof (tps.coin_pub)))
|
||||
&ctx.coin_pub,
|
||||
sizeof (ctx.coin_pub)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
@ -344,22 +326,25 @@ TEH_handler_deposits_get (struct TEH_RequestContext *rc,
|
||||
return MHD_NO; /* internal error */
|
||||
if (GNUNET_NO == res)
|
||||
return MHD_YES; /* parse error */
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION,
|
||||
&tps,
|
||||
&merchant_sig.eddsa_sig,
|
||||
&tps.merchant.eddsa_pub))
|
||||
TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID,
|
||||
NULL);
|
||||
if (GNUNET_OK !=
|
||||
TALER_merchant_deposit_verify (&ctx.merchant,
|
||||
&ctx.coin_pub,
|
||||
&ctx.h_contract_terms,
|
||||
&ctx.h_wire,
|
||||
&merchant_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return handle_track_transaction_request (rc->connection,
|
||||
&tps,
|
||||
&tps.merchant);
|
||||
&ctx);
|
||||
}
|
||||
|
||||
|
||||
|
@ -131,11 +131,8 @@ extension_update_event_cb (void *cls,
|
||||
/* Special case age restriction: Update global flag and mask */
|
||||
if (TALER_Extension_AgeRestriction == type)
|
||||
{
|
||||
TEH_age_mask.bits = 0;
|
||||
TEH_age_restriction_enabled =
|
||||
TALER_extensions_age_restriction_is_enabled ();
|
||||
if (TEH_age_restriction_enabled)
|
||||
TEH_age_mask = TALER_extensions_age_restriction_ageMask ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +140,8 @@ extension_update_event_cb (void *cls,
|
||||
enum GNUNET_GenericReturnValue
|
||||
TEH_extensions_init ()
|
||||
{
|
||||
TALER_extensions_init ();
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_extension_age_restriction_register ());
|
||||
|
||||
/* Set the event handler for updates */
|
||||
struct GNUNET_DB_EventHeaderP ev = {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -82,6 +82,64 @@ struct TEH_DenominationKey
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set of global fees (and options) for a time range.
|
||||
*/
|
||||
struct TEH_GlobalFee
|
||||
{
|
||||
/**
|
||||
* Kept in a DLL.
|
||||
*/
|
||||
struct TEH_GlobalFee *next;
|
||||
|
||||
/**
|
||||
* Kept in a DLL.
|
||||
*/
|
||||
struct TEH_GlobalFee *prev;
|
||||
|
||||
/**
|
||||
* Beginning of the validity period (inclusive).
|
||||
*/
|
||||
struct GNUNET_TIME_Timestamp start_date;
|
||||
|
||||
/**
|
||||
* End of the validity period (exclusive).
|
||||
*/
|
||||
struct GNUNET_TIME_Timestamp end_date;
|
||||
|
||||
/**
|
||||
* How long do unmerged purses stay around at most?
|
||||
*/
|
||||
struct GNUNET_TIME_Relative purse_timeout;
|
||||
|
||||
/**
|
||||
* How long do we keep accounts without KYC?
|
||||
*/
|
||||
struct GNUNET_TIME_Relative kyc_timeout;
|
||||
|
||||
/**
|
||||
* What is the longest history we return?
|
||||
*/
|
||||
struct GNUNET_TIME_Relative history_expiration;
|
||||
|
||||
/**
|
||||
* Signature affirming these details.
|
||||
*/
|
||||
struct TALER_MasterSignatureP master_sig;
|
||||
|
||||
/**
|
||||
* Fee structure for operations that do not depend
|
||||
* on a denomination or wire method.
|
||||
*/
|
||||
struct TALER_GlobalFeeSet fees;
|
||||
|
||||
/**
|
||||
* Number of free purses per account.
|
||||
*/
|
||||
uint32_t purse_account_limit;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Snapshot of the (coin and signing) keys (including private keys) of
|
||||
* the exchange. There can be multiple instances of this struct, as it is
|
||||
@ -129,6 +187,20 @@ void
|
||||
TEH_keys_update_states (void);
|
||||
|
||||
|
||||
/**
|
||||
* Look up global fee structure by @a ts.
|
||||
*
|
||||
* @param ksh key state state to look in
|
||||
* @param ts timestamp to lookup global fees at
|
||||
* @return the global fee details, or
|
||||
* NULL if none are configured for @a ts
|
||||
*/
|
||||
const struct TEH_GlobalFee *
|
||||
TEH_keys_global_fee_by_time (
|
||||
struct TEH_KeyStateHandle *ksh,
|
||||
struct GNUNET_TIME_Timestamp ts);
|
||||
|
||||
|
||||
/**
|
||||
* Look up the issue for a denom public key. Note that the result
|
||||
* must only be used in this thread and only until another key or
|
||||
@ -141,10 +213,10 @@ TEH_keys_update_states (void);
|
||||
* or NULL if @a h_denom_pub could not be found
|
||||
*/
|
||||
struct TEH_DenominationKey *
|
||||
TEH_keys_denomination_by_hash (const struct
|
||||
TALER_DenominationHashP *h_denom_pub,
|
||||
struct MHD_Connection *conn,
|
||||
MHD_RESULT *mret);
|
||||
TEH_keys_denomination_by_hash (
|
||||
const struct TALER_DenominationHashP *h_denom_pub,
|
||||
struct MHD_Connection *conn,
|
||||
MHD_RESULT *mret);
|
||||
|
||||
|
||||
/**
|
||||
@ -246,8 +318,8 @@ TEH_keys_denomination_cs_r_pub_melt (
|
||||
* @param h_denom_pub hash of the public key to revoke
|
||||
*/
|
||||
void
|
||||
TEH_keys_denomination_revoke (const struct
|
||||
TALER_DenominationHashP *h_denom_pub);
|
||||
TEH_keys_denomination_revoke (
|
||||
const struct TALER_DenominationHashP *h_denom_pub);
|
||||
|
||||
|
||||
/**
|
||||
@ -295,7 +367,7 @@ TEH_keys_exchange_sign_ (
|
||||
* number of bytes of the data structure, including its header. Use
|
||||
* #TEH_keys_exchange_sign() instead of calling this function directly!
|
||||
*
|
||||
* @param ksh key state state to look in
|
||||
* @param cls key state state to look in
|
||||
* @param purpose the message to sign
|
||||
* @param[out] pub set to the current public signing key of the exchange
|
||||
* @param[out] sig signature over purpose using current signing key
|
||||
@ -303,7 +375,7 @@ TEH_keys_exchange_sign_ (
|
||||
*/
|
||||
enum TALER_ErrorCode
|
||||
TEH_keys_exchange_sign2_ (
|
||||
struct TEH_KeyStateHandle *ksh,
|
||||
void *cls,
|
||||
const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
|
||||
struct TALER_ExchangePublicKeyP *pub,
|
||||
struct TALER_ExchangeSignatureP *sig);
|
||||
|
@ -62,7 +62,7 @@ struct KycPoller
|
||||
/**
|
||||
* UUID being checked.
|
||||
*/
|
||||
uint64_t payment_target_uuid;
|
||||
uint64_t auth_payment_target_uuid;
|
||||
|
||||
/**
|
||||
* Current KYC status.
|
||||
@ -76,9 +76,9 @@ struct KycPoller
|
||||
struct TALER_PaytoHashP h_payto;
|
||||
|
||||
/**
|
||||
* Hash of the payto:// URI that was given to us for auth.
|
||||
* Payto URL as a string, as given to us by t
|
||||
*/
|
||||
struct TALER_PaytoHashP auth_h_payto;
|
||||
const char *hps;
|
||||
|
||||
/**
|
||||
* When will this request time out?
|
||||
@ -170,7 +170,6 @@ kyc_check (void *cls,
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = TEH_plugin->select_kyc_status (TEH_plugin->cls,
|
||||
kyp->payment_target_uuid,
|
||||
&kyp->h_payto,
|
||||
&kyp->kyc);
|
||||
if (qs < 0)
|
||||
@ -261,7 +260,7 @@ TEH_handler_kyc_check (
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"payment_target_uuid");
|
||||
}
|
||||
kyp->payment_target_uuid = (uint64_t) payment_target_uuid;
|
||||
kyp->auth_payment_target_uuid = (uint64_t) payment_target_uuid;
|
||||
}
|
||||
{
|
||||
const char *ts;
|
||||
@ -291,32 +290,28 @@ TEH_handler_kyc_check (
|
||||
tms));
|
||||
}
|
||||
}
|
||||
kyp->hps = MHD_lookup_connection_value (rc->connection,
|
||||
MHD_GET_ARGUMENT_KIND,
|
||||
"h_payto");
|
||||
if (NULL == kyp->hps)
|
||||
{
|
||||
const char *hps;
|
||||
|
||||
hps = MHD_lookup_connection_value (rc->connection,
|
||||
MHD_GET_ARGUMENT_KIND,
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MISSING,
|
||||
"h_payto");
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (kyp->hps,
|
||||
strlen (kyp->hps),
|
||||
&kyp->h_payto,
|
||||
sizeof (kyp->h_payto)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"h_payto");
|
||||
if (NULL == hps)
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MISSING,
|
||||
"h_payto");
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (hps,
|
||||
strlen (hps),
|
||||
&kyp->auth_h_payto,
|
||||
sizeof (kyp->auth_h_payto)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"h_payto");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,7 +329,7 @@ TEH_handler_kyc_check (
|
||||
struct TALER_KycCompletedEventP rep = {
|
||||
.header.size = htons (sizeof (rep)),
|
||||
.header.type = htons (TALER_DBEVENT_EXCHANGE_KYC_COMPLETED),
|
||||
.h_payto = kyp->auth_h_payto
|
||||
.h_payto = kyp->h_payto
|
||||
};
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
@ -350,19 +345,24 @@ TEH_handler_kyc_check (
|
||||
now = GNUNET_TIME_timestamp_get ();
|
||||
ret = TEH_DB_run_transaction (rc->connection,
|
||||
"kyc check",
|
||||
TEH_MT_OTHER,
|
||||
TEH_MT_REQUEST_OTHER,
|
||||
&res,
|
||||
&kyc_check,
|
||||
kyp);
|
||||
if (GNUNET_SYSERR == ret)
|
||||
return res;
|
||||
if (0 !=
|
||||
GNUNET_memcmp (&kyp->h_payto,
|
||||
&kyp->auth_h_payto))
|
||||
|
||||
if (kyp->auth_payment_target_uuid !=
|
||||
kyp->kyc.payment_target_uuid)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Account %llu provided, but payto %s is for %llu\n",
|
||||
(unsigned long long) kyp->auth_payment_target_uuid,
|
||||
kyp->hps,
|
||||
(unsigned long long) kyp->kyc.payment_target_uuid);
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_UNAUTHORIZED,
|
||||
MHD_HTTP_FORBIDDEN,
|
||||
TALER_EC_EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED,
|
||||
"h_payto");
|
||||
}
|
||||
@ -389,14 +389,14 @@ TEH_handler_kyc_check (
|
||||
|
||||
GNUNET_assert (TEH_KYC_OAUTH2 == TEH_kyc_config.mode);
|
||||
GNUNET_asprintf (&redirect_uri,
|
||||
"%s/kyc-proof/%llu",
|
||||
"%s/kyc-proof/%s",
|
||||
TEH_base_url,
|
||||
(unsigned long long) kyp->payment_target_uuid);
|
||||
kyp->hps);
|
||||
redirect_uri_encoded = TALER_urlencode (redirect_uri);
|
||||
GNUNET_free (redirect_uri);
|
||||
GNUNET_asprintf (&url,
|
||||
"%s/login?client_id=%s&redirect_uri=%s",
|
||||
TEH_kyc_config.details.oauth2.url,
|
||||
"%s?client_id=%s&redirect_uri=%s",
|
||||
TEH_kyc_config.details.oauth2.login_url,
|
||||
TEH_kyc_config.details.oauth2.client_id,
|
||||
redirect_uri_encoded);
|
||||
GNUNET_free (redirect_uri_encoded);
|
||||
@ -414,19 +414,15 @@ TEH_handler_kyc_check (
|
||||
{
|
||||
struct TALER_ExchangePublicKeyP pub;
|
||||
struct TALER_ExchangeSignatureP sig;
|
||||
struct TALER_ExchangeAccountSetupSuccessPS as = {
|
||||
.purpose.purpose = htonl (
|
||||
TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
|
||||
.purpose.size = htonl (sizeof (as)),
|
||||
.h_payto = kyp->h_payto,
|
||||
.timestamp = GNUNET_TIME_timestamp_hton (now)
|
||||
};
|
||||
enum TALER_ErrorCode ec;
|
||||
|
||||
if (TALER_EC_NONE !=
|
||||
(ec = TEH_keys_exchange_sign (&as,
|
||||
&pub,
|
||||
&sig)))
|
||||
(ec = TALER_exchange_online_account_setup_success_sign (
|
||||
&TEH_keys_exchange_sign_,
|
||||
&kyp->h_payto,
|
||||
now,
|
||||
&pub,
|
||||
&sig)))
|
||||
{
|
||||
return TALER_MHD_reply_with_ec (rc->connection,
|
||||
ec,
|
||||
|
@ -78,9 +78,9 @@ struct KycProofContext
|
||||
char *id;
|
||||
|
||||
/**
|
||||
* Payment target this is about.
|
||||
* Hash of payment target URI this is about.
|
||||
*/
|
||||
unsigned long long payment_target_uuid;
|
||||
struct TALER_PaytoHashP h_payto;
|
||||
|
||||
/**
|
||||
* HTTP response to return.
|
||||
@ -171,7 +171,7 @@ persist_kyc_ok (void *cls,
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
qs = TEH_plugin->set_kyc_ok (TEH_plugin->cls,
|
||||
kpc->payment_target_uuid,
|
||||
&kpc->h_payto,
|
||||
kpc->id);
|
||||
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
|
||||
{
|
||||
@ -530,24 +530,21 @@ TEH_handler_kyc_proof (
|
||||
|
||||
if (NULL == kpc)
|
||||
{ /* first time */
|
||||
char dummy;
|
||||
|
||||
kpc = GNUNET_new (struct KycProofContext);
|
||||
kpc->rc = rc;
|
||||
rc->rh_ctx = kpc;
|
||||
rc->rh_cleaner = &clean_kpc;
|
||||
|
||||
if (1 !=
|
||||
sscanf (args[0],
|
||||
"%llu%c",
|
||||
&kpc->payment_target_uuid,
|
||||
&dummy))
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_STRINGS_string_to_data (args[0],
|
||||
strlen (args[0]),
|
||||
&kpc->h_payto,
|
||||
sizeof (kpc->h_payto)))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||
"payment_target_uuid");
|
||||
"h_payto");
|
||||
}
|
||||
kpc->authorization_code
|
||||
= MHD_lookup_connection_value (rc->connection,
|
||||
@ -582,8 +579,8 @@ TEH_handler_kyc_proof (
|
||||
"curl_easy_init");
|
||||
}
|
||||
GNUNET_asprintf (&kpc->token_url,
|
||||
"%stoken",
|
||||
TEH_kyc_config.details.oauth2.url);
|
||||
"%s",
|
||||
TEH_kyc_config.details.oauth2.auth_url);
|
||||
GNUNET_assert (CURLE_OK ==
|
||||
curl_easy_setopt (eh,
|
||||
CURLOPT_URL,
|
||||
@ -606,8 +603,8 @@ TEH_handler_kyc_proof (
|
||||
char *request_uri;
|
||||
|
||||
GNUNET_asprintf (&request_uri,
|
||||
"%slogin?client_id=%s",
|
||||
TEH_kyc_config.details.oauth2.url,
|
||||
"%s?client_id=%s",
|
||||
TEH_kyc_config.details.oauth2.login_url,
|
||||
TEH_kyc_config.details.oauth2.client_id);
|
||||
redirect_uri = curl_easy_escape (eh,
|
||||
request_uri,
|
||||
@ -678,7 +675,7 @@ TEH_handler_kyc_proof (
|
||||
|
||||
ret = TEH_DB_run_transaction (kpc->rc->connection,
|
||||
"check proof kyc",
|
||||
TEH_MT_OTHER,
|
||||
TEH_MT_REQUEST_OTHER,
|
||||
&res,
|
||||
&persist_kyc_ok,
|
||||
kpc);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user