Compare commits

...

378 Commits

Author SHA1 Message Date
Christian Grothoff
8638446f94
-fix versions 2022-06-23 18:29:31 +02:00
Christian Grothoff
ca61b64149
-make pg a recommendation, include version 2022-06-23 18:29:06 +02:00
Christian Grothoff
a63e706cd7
-fix build issues 2022-06-23 18:21:26 +02:00
Christian Grothoff
debc6ed983
-fix initialization issue 2022-06-23 18:21:15 +02:00
Christian Grothoff
09c9054bae
-fix initialization issue 2022-06-23 18:20:20 +02:00
c165ef31fe
first steps towards new /keys response: grouped denominations added 2022-06-23 18:19:45 +02:00
Christian Grothoff
bdd81674cf
-fix versions 2022-06-21 10:44:58 +02:00
Christian Grothoff
eed3cda48c
-make pg a recommendation, include version 2022-06-20 23:37:22 +02:00
Christian Grothoff
3fe94eb144
-update Debian package: include expire service, update dependencies 2022-06-20 15:29:59 +02:00
Christian Grothoff
3d66034093
-fix build issues 2022-06-20 15:17:35 +02:00
Christian Grothoff
360382192f
-fix initialization issue 2022-06-20 14:31:10 +02:00
Christian Grothoff
ec2d596b46
-fix initialization issue 2022-06-20 14:28:28 +02:00
Christian Grothoff
007e4bc954
-fix #7262 2022-06-19 14:24:44 +02:00
Christian Grothoff
bad572a010
-add missing checkpointing logic 2022-06-19 14:04:41 +02:00
Christian Grothoff
8da74a6ca7
-more work on taler-helper-auditor-reserve p2p audits 2022-06-18 20:36:44 +02:00
Christian Grothoff
f6a7d4a1ed
-more DB logic for taler-helper-auditor-reserves 2022-06-15 22:31:44 +02:00
Christian Grothoff
eccf37e450
-more DB prep work towards reserve auditing with p2p payments 2022-06-15 20:49:39 +02:00
Christian Grothoff
83be3173d4
-preparatory steps to expand auditor to know about purse and history fees 2022-06-14 23:04:43 +02:00
Christian Grothoff
568d27abe5
-include purse deposits in aggregation coin value analysis; note issues discovered with deposit fee waiver logic 2022-06-14 22:43:38 +02:00
Christian Grothoff
963477e064
-fix comments 2022-06-14 15:57:48 +02:00
Christian Grothoff
58a0882909
-towards coin audits with purse deposits 2022-06-13 15:31:52 +02:00
Christian Grothoff
70a5ceecc1
-also exit in test mode 2022-06-13 11:25:47 +02:00
Christian Grothoff
3c4d6f1ba2
fix #7256 2022-06-13 09:51:18 +02:00
Christian Grothoff
007cc7abe8
-prevent editing of generated files 2022-06-13 09:47:25 +02:00
Christian Grothoff
7876bc0600
-prevent editing generated files 2022-06-13 09:46:31 +02:00
Christian Grothoff
03cfd2b1e5
-add default(0) 2022-06-13 09:44:56 +02:00
Christian Grothoff
6d16958a5c
fix #7255 2022-06-12 22:47:32 +02:00
Christian Grothoff
71a42d2be8
fix #7241 2022-06-12 22:35:51 +02:00
Christian Grothoff
393ae7f9a3
-add dB logic for auditor iteration over purse deposits 2022-06-12 17:23:36 +02:00
Christian Grothoff
e71782ea77
only exit on bank error from wirewatch if new '-e' option is given 2022-06-11 23:47:24 +02:00
Christian Grothoff
0e32eacdb0
-typo 2022-06-09 21:05:32 +02:00
Christian Grothoff
eaea32b319
tag 2022-06-09 13:57:03 +02:00
Christian Grothoff
f3ceeb00ea
-expand auditordb to track progress for p2p payments 2022-06-08 17:05:51 +02:00
Christian Grothoff
7700f6ff88
add core success count metrics 2022-06-08 15:47:47 +02:00
Christian Grothoff
f2e2c5c9d8
-fix refund check regression 2022-06-07 22:24:49 +02:00
Christian Grothoff
937524940a
coarsen deposit transaction 2022-06-07 20:46:52 +02:00
Christian Grothoff
982b60c93c
-more minor bugfixes 2022-06-07 17:04:23 +02:00
Christian Grothoff
446761b602
-more minor bugfixes 2022-06-07 16:57:12 +02:00
Christian Grothoff
f0bcbf6586
allow double-rollback, warn on rollback+commit 2022-06-07 15:59:35 +02:00
Christian Grothoff
b9a30d29cb
-fix minor bugs 2022-06-07 15:02:16 +02:00
Thien-Thi Nguyen
013942ba91
Mention GANA repo in guidelines 2022-06-06 09:58:43 -04:00
Thien-Thi Nguyen
070e6de61e
Add some guidelines for src/include/taler_signatures.h maintenance 2022-06-06 09:57:29 -04:00
Thien-Thi Nguyen
f8e77a27c0
Update ignorance 2022-06-06 03:02:34 -04:00
Thien-Thi Nguyen
555cc06220
Generate src/include/taler_signatures.h at bootstrap time
* src/include/taler_signatures.h: Delete file.
* contrib/gana-update.sh: Add calls to ‘domake’, ‘ensure’ for contrib/sigp.
2022-06-06 02:59:59 -04:00
Christian Grothoff
bdbd2a464d
no purse fee if purse is successfully merged 2022-06-05 21:00:49 +02:00
60f609135d
fixed typo 2022-06-05 14:46:26 +02:00
Christian Grothoff
b9963f7525
complete P2P/W2W conflict handling, deduplicate code across handlers 2022-06-05 14:07:23 +02:00
Christian Grothoff
6c81796d6f
-work on error proof response checking for p2p payments 2022-06-05 01:34:37 +02:00
Christian Grothoff
f4eb53f2a4
-fix dist 2022-06-05 00:53:09 +02:00
Christian Grothoff
8e0b998217
-unify API 2022-06-05 00:43:11 +02:00
Christian Grothoff
21a1c715ee
-refactor internal API to use new EncrptedContract struct where applicable 2022-06-05 00:36:19 +02:00
Christian Grothoff
efa0ca4ec1
-move econtract into sub-object with its own parser 2022-06-05 00:25:56 +02:00
Christian Grothoff
a17781ba8d
-more work on p2p payments and tests thereof 2022-06-04 22:00:02 +02:00
Thien-Thi Nguyen
6512456dc2
Add support for generating taler_signatures.h.
* contrib/sigp/: New dir.
* contrib/sigp/Makefile: New file.
* contrib/sigp/README: New file.
* contrib/sigp/h.footer: New file.
* contrib/sigp/h.header: New file.
* contrib/sigp/h.template: New file.
2022-06-04 09:34:49 -04:00
Thien-Thi Nguyen
baf00c0262
move "gana/" to caller
This allows for other prefix dirs to be used.

(domake): Consider $1 to be dir under ‘contrib/’.
(ensure): Likewise, for $2.
2022-06-04 09:34:42 -04:00
Christian Grothoff
93943bdb5b
add KYC errors for p2p payments 2022-06-04 15:19:57 +02:00
Christian Grothoff
3e99c50c0f
-fix SQL 2022-06-04 14:07:02 +02:00
Christian Grothoff
d04769b729
handle case where purse expiration refunded the coin's deposited amount 2022-06-04 14:04:27 +02:00
Christian Grothoff
04c32eafb9
-work on P2P payment details 2022-06-02 21:55:21 +02:00
Christian Grothoff
5dd03fe359
-some FIXMEs from API review 2022-06-02 12:59:06 +02:00
Christian Grothoff
65ce2eede6
-expand table list for taler-auditor-sync 2022-06-01 23:16:35 +02:00
Christian Grothoff
00c68e0a04
-work on SQL for P2P table replication 2022-06-01 23:03:49 +02:00
Christian Grothoff
f86eead6d6
-log invalid URI 2022-05-31 14:56:34 +02:00
Christian Grothoff
7193261e52
-log all BEGIN statements 2022-05-31 10:13:58 +02:00
Christian Grothoff
361f534dbb
add -I option to wirewatch 2022-05-31 08:46:43 +02:00
Christian Grothoff
300194f42a
-towards p2p auditor sync implementation: SQL still missing 2022-05-30 23:55:55 +02:00
Christian Grothoff
d55b093de8
-fix reserve history, include in tests 2022-05-30 19:31:49 +02:00
Christian Grothoff
ab4aa4dcfd
-add batch withdraw to test suite 2022-05-30 17:51:39 +02:00
Christian Grothoff
7b25787a4b
-generate 404 on non-existing accounts for fakebank, use payto://-URIs with receiver-name in tests 2022-05-30 16:31:24 +02:00
Christian Grothoff
7f902c0fc9
-sketch API for RSA parallel signing 2022-05-30 13:34:39 +02:00
Christian Grothoff
d40da21e90
add batch signing support to taler-exchange-secmod-rsa 2022-05-29 22:25:04 +02:00
Marco Boss
6d2ee2c88a
rewrite sharding initialization logic 2022-05-25 08:40:01 +02:00
Christian Grothoff
d77354b11a
use precise time for shards 2022-05-24 12:00:20 +02:00
Christian Grothoff
8e71a7e4de
lock into the future, instead of lock into past 2022-05-24 10:45:01 +02:00
Christian Grothoff
92e04e0a3f
-handle serialization issue 2022-05-24 10:11:43 +02:00
Christian Grothoff
daddc69dc9
-revise shard locking: resume open shards before starting new ones 2022-05-24 09:52:23 +02:00
Christian Grothoff
1d84c284ad
-incomplete batch_withdraw test command 2022-05-23 22:09:05 +02:00
Christian Grothoff
054f2ab51c
-implement batch withdraw client-side logic 2022-05-23 21:12:31 +02:00
Christian Grothoff
656b521a83
-passes, enable by default 2022-05-23 16:19:40 +02:00
Christian Grothoff
6ee4558b6f
-sql fix 2022-05-23 16:15:14 +02:00
Christian Grothoff
2e80f51e25
handle purse deposit client-side 2022-05-23 16:11:21 +02:00
Christian Grothoff
76b8a2a8de
include purse deposits in coin history 2022-05-23 16:02:55 +02:00
Christian Grothoff
a509a91f92
-more reserve history fixes 2022-05-23 15:29:35 +02:00
Christian Grothoff
cdd2930a99
-misc fixes to reserve history 2022-05-23 14:57:00 +02:00
Christian Grothoff
2035294adb
-more traits for reserve history checking 2022-05-23 12:17:41 +02:00
Christian Grothoff
f1a58b0fd8
-towards reserve history testing 2022-05-23 11:15:05 +02:00
Christian Grothoff
b3844e4923
-deduplicate and expand reserve history validation logic in testing library 2022-05-23 10:36:39 +02:00
Christian Grothoff
fcaf508647
-add missing break, clean up fee logic 2022-05-23 00:34:04 +02:00
Christian Grothoff
3ee8879ada
-refactor coin history checker 2022-05-23 00:19:57 +02:00
Christian Grothoff
3599ac0ac2
-complete extended reserve history signature check logic to libtalerexchange 2022-05-22 23:51:14 +02:00
Christian Grothoff
67535ebf65
-towards client-side support for merge and history requests in reserve history 2022-05-22 20:04:38 +02:00
Christian Grothoff
40daa209fb
-more work on reverse history 2022-05-22 18:21:15 +02:00
Christian Grothoff
8658ae03ca
-towards purse merge and history requests in reserve history (incomplete) 2022-05-22 16:58:48 +02:00
Christian Grothoff
4a5d71cca2
-implement reserve history DB logic 2022-05-22 16:18:09 +02:00
Christian Grothoff
96fb11bed0
-fix 2022-05-22 14:46:23 +02:00
Christian Grothoff
21bcc5fa0b
-fix wirewatch assertion 2022-05-22 13:48:56 +02:00
Christian Grothoff
3233195d2d
-fix NPE 2022-05-22 13:11:09 +02:00
Christian Grothoff
b1b943aa3e
-add metrics for idempotent (batch) withdraw 2022-05-22 13:06:17 +02:00
Christian Grothoff
737937291c
wirewatch spring cleaning 2022-05-21 21:07:24 +02:00
Christian Grothoff
a6494f9905
-experimental wirewatch change to keep shard locks across history requests 2022-05-21 02:00:31 +02:00
Christian Grothoff
9e0df07a16
latest_row_off is exclusive, remove bad comment 2022-05-21 01:41:02 +02:00
Christian Grothoff
c471ae447b
-log where it failed 2022-05-21 01:39:59 +02:00
Christian Grothoff
81ad77b8dc
-improve error handling 2022-05-21 01:39:34 +02:00
Christian Grothoff
421f59749e
anti-gummy patch 2022-05-20 16:49:48 +02:00
Sebastian
68b155aab5
missing plus sign for image data uris 2022-05-20 10:09:54 -03:00
Christian Grothoff
344c53c51d
enforce valid payto:// URI in exchange /wire response 2022-05-18 18:05:32 +02:00
Christian Grothoff
492d501570
-squash compiler warning 2022-05-18 09:57:56 +02:00
Christian Grothoff
a6b2108009
-check for ETag in request, generate 304 if applicable 2022-05-17 14:39:52 +02:00
Christian Grothoff
a6a1fa9fde
keep ETag around 2022-05-17 14:31:52 +02:00
Christian Grothoff
5e06f842dd
add ETag to /keys response 2022-05-17 14:30:58 +02:00
Christian Grothoff
b9d0b1aae4
-make batch withdraw requests idempotent 2022-05-17 12:29:00 +02:00
Christian Grothoff
7bd1828482
-deduplicate 2022-05-17 12:12:52 +02:00
Christian Grothoff
ccc7743fdd
-note what is untested 2022-05-17 11:52:36 +02:00
Christian Grothoff
3b5d9daca9
-expand test to include coin refund 2022-05-17 11:46:41 +02:00
Christian Grothoff
d8f1f7b761
integrate purse expiration into test, bugfixes 2022-05-17 11:21:20 +02:00
Christian Grothoff
802649c270
-add DB logic for purse expiration 2022-05-17 08:50:42 +02:00
Thien-Thi Nguyen
f089bbe536
split conf file reference to -cs and -rsa
This is a followup to 2022-02-04, "split .conf files into rsa and cs".
2022-05-17 02:20:05 -04:00
Thien-Thi Nguyen
8690892cac
fix typo: add extension .h to source filename 2022-05-17 02:12:45 -04:00
Christian Grothoff
02716c4084
-add skeleton logic for purse expiration 2022-05-16 15:43:40 +02:00
Christian Grothoff
d803d86bf9
-work purse_deposit conflict handling 2022-05-16 14:01:04 +02:00
Christian Grothoff
3db8f0f22d
improve cache control support for /wire, /keys and legal 2022-05-16 11:56:10 +02:00
Christian Grothoff
fac01f140f
-add purse-merge 409 handling client-side 2022-05-16 11:17:27 +02:00
Christian Grothoff
439c872af4
-implement purse_deposit error handling 2022-05-16 10:53:42 +02:00
Christian Grothoff
10a97996f7
-enable batch withdraw manual testing 2022-05-15 18:56:35 +02:00
Christian Grothoff
84b8886b12
-fix return value of taler-fakebank-run with -h option 2022-05-15 18:41:17 +02:00
Christian Grothoff
6150713fc4
-fix wire expiration 2022-05-14 15:11:16 +02:00
Christian Grothoff
2d0d8e7e8e
add max_age column 2022-05-14 12:24:25 +02:00
Marco Boss
42f3f83b7d
add recoup_by_reserve as sql function 2022-05-13 15:28:43 +02:00
Marco Boss
d6c161a72e
fix metrics of withdraw - no label 2022-05-12 19:32:10 +02:00
Marco Boss
db320d3e8e
add metrics for number of coins withdrawn in a batch request 2022-05-12 16:15:54 +02:00
Christian Grothoff
7689c71cea
-leak fix 2022-05-12 14:40:07 +02:00
Christian Grothoff
6518cc20dd
hande IF_NONE_MATCH in /wire request 2022-05-12 14:27:31 +02:00
Christian Grothoff
d0a0bd9725
Merge branch 'master' of git+ssh://git.taler.net/exchange 2022-05-12 14:15:07 +02:00
Christian Grothoff
75d9584e28
add Etag and 'expires' to /wire 2022-05-12 14:15:02 +02:00
Thien-Thi Nguyen
33312e5abf
define TALER_SIGNATURE_MASTER_PARTNER_DETAILS as 1048
This is to avoid a duplicate Number:
https://bugs.gnunet.org/view.php?id=7240
2022-05-12 07:44:47 -04:00
Christian Grothoff
6cf4a068ad
add 'Expires' header to ToS and PP replies 2022-05-12 13:38:47 +02:00
Christian Grothoff
35b4a51e14
combine auto-commited transactions in refresh/reveal into one big transaction 2022-05-12 13:31:15 +02:00
Christian Grothoff
93eb88a8c9
-fix argument order 2022-05-12 11:10:32 +02:00
Christian Grothoff
81732d49cc
-add FIXME 2022-05-12 09:52:41 +02:00
Thien-Thi Nguyen
842e04b13c
refactor
(domake, ensure): New funcs.
<top-level>: Use ‘domake’, ‘ensure’.
2022-05-11 04:27:50 -04:00
Christian Grothoff
99a844e52e
check reserve balance after p2p merges 2022-05-09 13:25:10 +02:00
Christian Grothoff
06bfbd9150
-sql fixes 2022-05-08 22:36:39 +02:00
Christian Grothoff
60c08dccec
expand P2P query logic 2022-05-08 21:04:55 +02:00
Christian Grothoff
02eb80e0b2
-address FIXMEs 2022-05-08 12:50:25 +02:00
Christian Grothoff
d3a6388199
pass purse_fee to determine how purse creation is paid for 2022-05-08 11:37:37 +02:00
Christian Grothoff
6b8e732bf8
-pub 2022-05-07 23:45:17 +02:00
Christian Grothoff
5f6d5bc3fc
-online 2022-05-07 23:43:39 +02:00
Christian Grothoff
415c922c92
-address FIXMEs for purses GET requests 2022-05-07 23:41:33 +02:00
Christian Grothoff
2d84d7f6dd
add function for purse status signing 2022-05-07 23:27:56 +02:00
Christian Grothoff
4199e4438d
rename function that is for the merchant signature to have merchant in the name 2022-05-07 23:21:27 +02:00
Christian Grothoff
8c9d5d6135
document required packages 2022-05-07 19:29:04 +02:00
Christian Grothoff
370ee3a417
-fix leaks 2022-05-07 18:58:29 +02:00
Christian Grothoff
65943dcb13
-payment router skeleton 2022-05-02 21:09:07 +02:00
Christian Grothoff
31e554ad46
-remove FIXMEs 2022-05-02 20:53:29 +02:00
Christian Grothoff
7ebdac0a8b
-investigate FIXME 2022-05-02 20:51:34 +02:00
Christian Grothoff
0a7b75b2cf
-regen DBs to fix #7236 2022-05-02 20:34:41 +02:00
Christian Grothoff
40440604dd
-address some FIXMEs 2022-05-02 19:55:40 +02:00
Christian Grothoff
1173502189
-fix leak 2022-05-02 19:48:23 +02:00
Marco Boss
72ae759fa0
include shard domain and remote users in taler config 2022-05-02 00:27:59 +02:00
Christian Grothoff
a4ede7caec
add batch withdraw to demultiplexer 2022-05-01 13:16:03 +02:00
Christian Grothoff
3d80b20459
-get batch withdraw to build 2022-05-01 13:01:32 +02:00
Christian Grothoff
7718cd4153
skeleton for batch withdraw logic (not finished) 2022-05-01 12:45:12 +02:00
Christian Grothoff
f99fb9ad4b
-GET purse test passes 2022-04-30 17:35:24 +02:00
Christian Grothoff
fed8353c67
-expand p2p tests with purse long poller 2022-04-30 14:03:57 +02:00
Christian Grothoff
fb8349a7e3
-add notifications for purse events 2022-04-30 13:46:35 +02:00
Christian Grothoff
8e4969eb66
-implement purses_get CMD 2022-04-30 12:02:43 +02:00
Christian Grothoff
c48b51be6f
-fix help text 2022-04-28 22:37:39 +02:00
1bb992d777
-logging 2022-04-27 21:00:23 +02:00
Christian Grothoff
3e8c797bb7
-get p2p test to pass 2022-04-27 13:28:28 +02:00
Christian Grothoff
d623cab1a3
-work on p2p payments 2022-04-27 13:09:41 +02:00
Christian Grothoff
1396afc136
-drop 2022-04-27 10:34:36 +02:00
Christian Grothoff
521e0bbcb5
-p2p fixes 2022-04-27 10:34:36 +02:00
9a05781ab3
-fix derivation, logging 2022-04-27 00:00:15 +02:00
17a00ef22d
age restriction: make seed a HashCode due to endianess and security level concerns 2022-04-26 23:34:14 +02:00
47e276e11a
-remove debug logging 2022-04-26 23:10:50 +02:00
be536de23c
various age restriction fixes, some of them half-baked 2022-04-26 23:10:12 +02:00
Christian Grothoff
336f2d8991
-misc. minor fixes 2022-04-26 17:46:36 +02:00
Christian Grothoff
25aa208d12
-draft pull p2p test case 2022-04-26 17:05:12 +02:00
Christian Grothoff
932cef3d8c
-complete purses_get draft implementation 2022-04-26 13:34:18 +02:00
Christian Grothoff
efb8c8037b
-implement purses get db sketch 2022-04-26 13:24:51 +02:00
a92d3aae7b
-use uint32_t instead of uint8_t + padding for the age 2022-04-26 11:23:27 +02:00
f24fc18564
use htonl, not GNUNET_htonll 2022-04-26 01:50:31 +02:00
38fcca16c8
fix age attestation signature padding and endianess 2022-04-26 01:28:36 +02:00
Christian Grothoff
505989a507
-mark FIXMEs 2022-04-25 13:30:03 +02:00
Christian Grothoff
5c0cbba761
-sketch implementation of exchange_do_reserve_purse() 2022-04-25 13:18:37 +02:00
Christian Grothoff
94038bfcfd
-sketch implementation of exchange_do_reserve_purse() 2022-04-25 13:11:13 +02:00
Christian Grothoff
b4965db0d2
-fix fieldnames, regenerated DBs 2022-04-24 20:49:11 +02:00
Christian Grothoff
b671d6b25d
get first p2p test to pass 2022-04-24 16:02:34 +02:00
Christian Grothoff
aedd2014ec
-misc p2p fixes 2022-04-24 15:29:58 +02:00
Thien-Thi Nguyen
36c568ab8d
Remove empty GNUNET_NETWORK_STRUCT_{BEGIN,END} pair 2022-04-24 08:48:51 -04:00
Christian Grothoff
345c141bad
-work on p2p payments 2022-04-23 20:50:27 +02:00
Christian Grothoff
b7a4fd401e
add subcommand to sign global fees in tests 2022-04-23 20:02:28 +02:00
Christian Grothoff
a1825d38b3
integrate p2p handlers with main dispatcher 2022-04-23 19:45:33 +02:00
Christian Grothoff
e270bc32cc
-expand p2p test to cover purse-with-deposit-merge sequence 2022-04-23 19:32:07 +02:00
Christian Grothoff
b054c969cb
-add more accounting fields to reserve table 2022-04-23 19:01:28 +02:00
Christian Grothoff
cf358f9546
-uncrustify 2022-04-23 18:13:15 +02:00
Christian Grothoff
e731739396
-create cmd for purse deposit 2022-04-23 18:11:31 +02:00
Christian Grothoff
cf11b3f0b2
-create cmd for purse creation from reserve 2022-04-23 18:01:00 +02:00
Christian Grothoff
132359a444
add purses-get to build 2022-04-23 12:34:48 +02:00
Thien-Thi Nguyen
a72337a5f3
Add abstractions: TALER_exchange_deposit_{sign,verify}
This change also removes ‘struct TALER_DepositTrackPS’
from the public API.

* src/include/taler_signatures.h (struct TALER_DepositTrackPS): Delete.

* src/util/exchange_signatures.c (struct TALER_DepositTrackPS): New.
  (TALER_exchange_deposit_sign): New func.
  (TALER_exchange_deposit_verify): New func.

* src/include/taler_crypto_lib.h
  (TALER_exchange_deposit_sign): New func decl.
  (TALER_exchange_deposit_verify): New func decl.

* src/exchange/taler-exchange-httpd_deposits_get.c
  (TEH_handler_deposits_get): Rework to use ‘TALER_exchange_deposit_verify’.

* src/lib/exchange_api_deposits_get.c
  (TALER_EXCHANGE_deposits_get): Rework to use ‘taler_exchange_deposit_sign’.
2022-04-22 20:29:45 -04:00
Christian Grothoff
e40a16aa8e
towards GET /purses/PID 2022-04-22 23:48:15 +02:00
Christian Grothoff
c30c7cde4d
add purses_deposit to build 2022-04-22 23:43:15 +02:00
Christian Grothoff
8ef3997160
-make purses_get compile 2022-04-22 23:34:37 +02:00
Christian Grothoff
ae2f1ced8b
skeleton for GET /purses/ client 2022-04-22 23:22:06 +02:00
Christian Grothoff
1002ac13e4
skeleton for /purses//deposit 2022-04-22 23:14:29 +02:00
31c545b9e8
-fixed tests for age restriction, now using correct seed 2022-04-22 15:15:57 +02:00
Christian Grothoff
eea35ffb01
-skeleton logic for deposits into purse 2022-04-21 22:44:51 +02:00
Christian Grothoff
53cde04c4e
-add FIXME 2022-04-21 21:05:49 +02:00
Christian Grothoff
582acc3cf3
add taler-exchange-httpd_reserves_purse.c to build 2022-04-21 21:04:33 +02:00
Christian Grothoff
c3e67dfc6b
-add purse_create_with_merge to build 2022-04-21 20:36:14 +02:00
Christian Grothoff
f5eef0c816
-more work on purse creation for reserve 2022-04-21 20:25:01 +02:00
061c4f72bd
-m statically link libtalerextensions.la from build-tree 2022-04-21 16:13:00 +02:00
b84c88fc04
Fixed seed size for TALER_age_restriction_commit
Also, added src/util/tv_age_restriction.{c,json} for/as test vectors for
age restriction.
2022-04-21 14:27:29 +02:00
137bd97154
cleanup of extension API
- removed TALER_extensions_init()
- added TALER_extension_age_restriction_register()
2022-04-21 12:54:59 +02:00
Christian Grothoff
4af1772f12
-work on create purse with merge 2022-04-20 23:07:44 +02:00
Christian Grothoff
1e0789eda3
-more deposit GET cleanup 2022-04-20 20:18:03 +02:00
Christian Grothoff
8776f16b06
-refactor deposits_get logic to help ttn with signature logic refactoring 2022-04-20 20:05:25 +02:00
14b57d3e13
find extensions case-insensitively 2022-04-19 18:37:56 +02:00
Thien-Thi Nguyen
509657bfef
Add abstraction: TALER_merchant_contract_sign
Additionally, this change removes ‘struct TALER_ProposalDataPS’
from the public API.

* src/include/taler_crypto_lib.h
  (TALER_merchant_contract_sign): New func decl.

* src/include/taler_signatures.h
  (struct TALER_ProposalDataPS): Delete.

* src/util/merchant_signatures.c
  (struct TALER_ProposalDataPS): Move here from taler_signatures.h.
  (TALER_merchant_contract_sign): New func.
2022-04-17 19:53:17 -04:00
Thien-Thi Nguyen
a7ad5a07e2
Add abstractions: TALER_merchant_pay_{sign,verify}
Additionally, this change removes ‘struct TALER_PaymentResponsePS’
from the public API.

* src/include/taler_crypto_lib.h
  (TALER_merchant_pay_sign): New func decl.
  (TALER_merchant_pay_verify): New func decl.

* src/include/taler_signatures.h
  (struct TALER_PaymentResponsePS): Delete.

* src/util/merchant_signatures.c
  (struct TALER_PaymentResponsePS): Move here from taler_signatures.h.
  (TALER_merchant_pay_sign): New func.
  (TALER_merchant_pay_verify): New func.
2022-04-17 04:53:17 -04:00
Thien-Thi Nguyen
ba69c32712
fix typo in last commit 2022-04-16 13:53:06 -04:00
Thien-Thi Nguyen
f32b183143
Update ignorance; nfc 2022-04-16 13:52:14 -04:00
Christian Grothoff
b496b8fed5
add more flexibility to endpoint naming for KYC 2022-04-16 17:51:27 +02:00
Christian Grothoff
fc1383ebd1
-skeleton for p2p test 2022-04-15 16:02:50 +02:00
Christian Grothoff
001f406ad6
regen test DBs to fix #7220 2022-04-15 11:42:57 +02:00
Christian Grothoff
a2604f7967
-style fix 2022-04-15 11:18:33 +02:00
Christian Grothoff
a13f90a15e
add wirewatch shutdown shard cleanup logic 2022-04-14 00:00:50 +02:00
Christian Grothoff
5882e6b56b
-edit correct file 2022-04-13 10:02:01 +02:00
Christian Grothoff
00928aba0a
-wip on p2p payments 2022-04-13 09:50:53 +02:00
Christian Grothoff
2299b8b193
-draft for purse merge command 2022-04-12 16:35:05 +02:00
Christian Grothoff
3893afa49c
-implementing purse merge DB logic 2022-04-12 11:58:21 +02:00
Christian Grothoff
cacb019501
testing command to GET contracts 2022-04-11 23:27:23 +02:00
Christian Grothoff
b91a406525
-finish first implementaation of exchange_api_contracts_get.c 2022-04-11 19:22:30 +02:00
Christian Grothoff
78cf27aaac
-skeleton for GET /contracts/ logic: add to build system 2022-04-11 18:58:54 +02:00
Christian Grothoff
6aad1fa351
-skeleton for GET /contracts/ logic 2022-04-11 18:56:05 +02:00
Christian Grothoff
7a1dcc52ca
-towards new GET /contracts/$C_PUB hander 2022-04-11 16:48:30 +02:00
Christian Grothoff
c8c1005297
-add draft handler for purse merge client request 2022-04-11 15:34:45 +02:00
Christian Grothoff
d30b7f8eeb
-load wire fees only when needed 2022-04-11 15:23:29 +02:00
Christian Grothoff
bd09b2302a
-add exchange-internal API to lookup current wire fees 2022-04-11 15:04:26 +02:00
Christian Grothoff
72dd9514aa
-draft implementation of /purses//merge endpoint 2022-04-11 13:52:06 +02:00
Christian Grothoff
f9971faa7a
-draft for merge endpoint 2022-04-08 19:23:19 +02:00
Marco Boss
fe2a15c558
Update queries for better network load in sharded setup 2022-04-06 14:21:57 +02:00
Christian Grothoff
89431a41b7
-complete va coin parser of purse_create_deposit CMD 2022-04-06 13:54:08 +02:00
Marco Boss
0a10644b81
improve some queries for sharding 2022-04-06 13:33:47 +02:00
Christian Grothoff
22cfc59d90
-towards testing purse creation 2022-04-06 12:50:07 +02:00
Marco Boss
adb999ce2c
fix sharding 2022-04-06 11:33:50 +02:00
Christian Grothoff
f3a4b00907
adapt to latest GNUnet API: GNUNET_JSON_spec_mark_optional() changed 2022-04-05 17:15:50 +02:00
Christian Grothoff
7191641406
implement more DB functions 2022-04-04 20:42:26 +02:00
Christian Grothoff
df8ff01f29
add contract_sig field 2022-04-04 17:04:31 +02:00
Marco Boss
914a77b5a7
Shard p2p tables 2022-04-04 16:40:59 +02:00
Marco Boss
970225516e
add p2p tables to sharding logic 2022-04-04 16:40:39 +02:00
Christian Grothoff
8c3e263b76
-ignore 2022-04-04 08:57:09 +02:00
Christian Grothoff
5147c8b788
-fix FTBFS 2022-04-04 08:55:01 +02:00
Christian Grothoff
831e32b7ad
-add logic for econtract_sig signatures 2022-04-04 07:29:50 +02:00
Marco Boss
393cea46d1
implement shard node setup and drop 2022-04-02 19:07:12 +02:00
Marco Boss
7ba135362e
fix name 2022-04-02 18:59:20 +02:00
Marco Boss
ae75ff2cb4
extend sharding logic that shard nodes can be initialied and dropped 2022-04-02 18:43:49 +02:00
Christian Grothoff
6f027fc130
add additinal signature 2022-04-02 17:25:18 +02:00
Marco Boss
caabee9e94
install shard-0000.sql 2022-04-02 14:33:50 +02:00
Marco Boss
86ee587b03
add shard-0000.sql 2022-04-02 14:31:59 +02:00
Marco Boss
ca536c0379
fix return 2022-04-02 14:25:04 +02:00
Marco Boss
5880a8ec4f
drop functions 2022-04-02 13:42:00 +02:00
Marco Boss
f596b27a97
fix format specifiers 2022-04-02 12:18:56 +02:00
Marco Boss
82718aecf8
fix argument to create_shard_server 2022-04-02 11:52:21 +02:00
Marco Boss
1b76ba5e9a
Include sharding sql logic 2022-04-02 09:28:25 +02:00
Marco Boss
0ba219fe5b
add permissions 2022-04-02 09:27:30 +02:00
Christian Grothoff
6c66f6f5cf
rollback transaction to end transaction scope before releasing the shard (fixes #7216) 2022-04-02 03:50:30 +02:00
Christian Grothoff
caf66486e7
work on purse creation logic 2022-04-01 16:39:07 +02:00
Marco Boss
45916b992b
remove built sql files from vc 2022-03-31 21:49:35 +02:00
Marco Boss
75c1e10a67
add shard init for shard node 2022-03-31 21:31:07 +02:00
Marco Boss
0cf9a9984c
add sharding logic 2022-03-31 17:00:44 +02:00
Christian Grothoff
747ae5ef09
privatize more signature structs, simplify code 2022-03-31 12:37:39 +02:00
Christian Grothoff
eadee56dcf
-remove row check, not stable enough to assert on 2022-03-30 12:00:20 +02:00
Christian Grothoff
6040c9ff0f
make struct private again 2022-03-30 01:36:52 +02:00
Sebastian
e5b65aa443
fix: wtid request param size 2022-03-29 17:53:50 -03:00
Sebastian
adc9dae4cc
make TALER_RefundConfirmationPS public 2022-03-29 14:12:45 -03:00
Christian Grothoff
074ea7502e
centralize exchange online signature logic 2022-03-29 15:21:49 +02:00
Christian Grothoff
3249687b2a
rename to avoid symbol conflict with musl 2022-03-28 18:18:08 +02:00
Christian Grothoff
b25c9398b7
starting work on purse-create endpoint 2022-03-28 17:50:23 +02:00
Christian Grothoff
a227ee6d1b
-first cut at contract encryption and decryption 2022-03-28 13:57:43 +02:00
Christian Grothoff
ee4077ef80
starting with purse creation client API 2022-03-28 13:19:40 +02:00
30985c0975
-rename variable 2022-03-28 12:34:14 +02:00
ccf2d69dfb
-fix leak in test_age_restriction.c 2022-03-28 12:33:41 +02:00
488d217381
-fix leaks in test_crypto.c 2022-03-28 11:17:49 +02:00
a2386abadb
[age restriction] progress 19/19 (final) - Use Edx25519 for crypto
We switch from EcDSA to Edx25519 for the underlying signature scheme.

Edx25519 is implemented in gnunet, starting with (gnunet-)commit
ce38d1f6c9bd7857a1c3bc2094a0ee9752b86c32.
2022-03-28 11:04:00 +02:00
Christian Grothoff
d61a19c275
-fix leak, uninitialized ps 2022-03-27 16:11:35 +02:00
Christian Grothoff
1f1d675f3d
-remove tiny field, no longer needed 2022-03-27 14:34:44 +02:00
Christian Grothoff
b9a9af3a59
new aggregator mega transaction logic 2022-03-27 13:48:25 +02:00
Christian Grothoff
d0a69da895
towards removing tiny bit 2022-03-27 10:32:28 +02:00
Christian Grothoff
646c9ad061
fix leak 2022-03-27 05:02:21 +02:00
Christian Grothoff
098d572471
change sharding strategy for refund table 2022-03-26 10:47:10 +01:00
Christian Grothoff
783e2ae424
add partitions to new p2p tables 2022-03-26 09:00:19 +01:00
Christian Grothoff
238761c87d
-regen DBs 2022-03-25 14:07:31 +01:00
Christian Grothoff
b856d56d95
rework deposits sharding, towards making aggregator faster (not necessarily done) 2022-03-24 17:33:29 +01:00
Christian Grothoff
c782dfe2aa
first draft of service API for p2p payments 2022-03-24 13:06:04 +01:00
Christian Grothoff
6ffc2c68a3
better query 2022-03-24 09:05:55 +01:00
b0cf653b83
implement more taler-crypto-worker ops 2022-03-24 01:37:48 +01:00
e336c02d14
implement more taler-crypto-worker ops 2022-03-24 01:10:00 +01:00
Christian Grothoff
f091808425
more skeleton logic for P2P operations on DB 2022-03-23 12:25:45 +01:00
Thien-Thi Nguyen
7d2a009e1b
Bump required version of libmicrohttpd to 0.9.71 2022-03-23 02:23:25 -04:00
Christian Grothoff
41399bc224
revise P2P signatures and signing schema to address recently discovered design concern resulting in the split of the purse key into purse-contract and purse-merge keys 2022-03-23 06:54:43 +01:00
Christian Grothoff
9b7716f9f2
fix #7151 2022-03-23 05:19:09 +01:00
Christian Grothoff
6505f69869
add one more p2p signature 2022-03-22 12:12:00 +01:00
Christian Grothoff
6868b78692
fix typo 2022-03-22 12:06:12 +01:00
Christian Grothoff
cce049a0b5
add missing table drops 2022-03-22 11:51:56 +01:00
Christian Grothoff
734b68d45e
-fix drop SQL issue: drop functions properly 2022-03-22 05:33:08 +01:00
Christian Grothoff
e200e86032
implement helper functions for p2p signatures, clean up existing signature logic 2022-03-22 02:33:51 +01:00
Christian Grothoff
bdc797a583
FIXMEs for Oec 2022-03-21 08:35:19 +01:00
Christian Grothoff
c7e2d206ba
add logic to check timestamp, revise history balance calculation logic in client 2022-03-21 03:59:31 +01:00
Christian Grothoff
1f86b02ffa
first rough-cut implementation of /reserves//history endpoint 2022-03-21 03:04:47 +01:00
Christian Grothoff
f5f15e6531
first rough-cut implementation of POST /reserves//status 2022-03-21 02:39:36 +01:00
Christian Grothoff
b560527ee3
ideas for mboss 2022-03-20 16:52:38 +01:00
Christian Grothoff
65808106c7
add test for reserve GET long polling 2022-03-20 15:42:16 +01:00
Christian Grothoff
532fabf20a
add variant of GET /reserves/ testing command with support for long polling (to diagnose reserve long polling issue reported by FD) 2022-03-20 14:50:13 +01:00
Christian Grothoff
28203913e2
add p2p tables from dd13 2022-03-20 14:03:07 +01:00
Christian Grothoff
e7fa97cc87
-rename file for consistency 2022-03-20 13:22:32 +01:00
Christian Grothoff
427417b835
towards support for new reserve history/status APIs 2022-03-20 13:20:45 +01:00
Christian Grothoff
dee45bf022
return new global fees from /keys 2022-03-20 09:44:42 +01:00
Christian Grothoff
1bb5a77c8d
add new reserve status/history signatures 2022-03-20 02:39:28 +01:00
Christian Grothoff
c83892ba29
-style fixes 2022-03-20 02:39:12 +01:00
Christian Grothoff
69927847cc
-style fixes 2022-03-20 02:38:48 +01:00
Christian Grothoff
5406d564fb
-style fixes 2022-03-19 16:16:28 +01:00
Christian Grothoff
938db9ac56
-fix memory leak introduced by Oec 2022-03-19 16:04:41 +01:00
Christian Grothoff
c4690a44bc
-minor code cleanup 2022-03-19 15:54:05 +01:00
Christian Grothoff
685837ad28
simplify auditor_api_handle.c, do not modify global context with respect to 'Expect' header 2022-03-19 15:25:43 +01:00
Christian Grothoff
f5e5f4b843
more work on recoup_by_reserve: add new materialized index to avoid hitting all partitions for the query 2022-03-19 14:05:45 +01:00
Christian Grothoff
f22125ce0f
add missing index, move indices closer to table generation 2022-03-19 12:58:37 +01:00
Thien-Thi Nguyen
b4f7231d17
[build int] Use ‘MHD_VERSION_AT_LEAST’
* configure.ac (microhttpd): Delete shell var.
(MHD_start_daemon): Delete AC_CHECK_LIB.
(MHD_DAEMON_INFO_CURRENT_CONNECTIONS): Delete AC_CHECK_DECL.
(MHD_VERSION_AT_LEAST): New macro call.
2022-03-19 07:52:53 -04:00
Thien-Thi Nguyen
98c21a5116
Add autoconf macro to check for minimum libmicrohttpd version
* m4/mhd.m4: New.
2022-03-19 07:52:53 -04:00
Christian Grothoff
52a8b8f888
-code cleanup 2022-03-19 08:34:58 +01:00
Christian Grothoff
280f94c3a6
improve style of some SQL queries (no semantic change) 2022-03-19 08:27:01 +01:00
Christian Grothoff
f0a95037ef
-fix memory leak 2022-03-19 08:26:40 +01:00
Christian Grothoff
badfde8962
add deposits_by_coin table to speed-up certain queries (in theory) 2022-03-18 15:47:25 +01:00
e909f5701b
system doc: include title page 2022-03-18 15:44:49 +01:00
Christian Grothoff
142a369e43
add selection by shard, ignore KYC in revocation test aggregation 2022-03-18 08:54:08 +01:00
Christian Grothoff
23af6c3c41
change table structures again to shard better by coin_pub and not use known_coin_id so much 2022-03-18 01:57:39 +01:00
Christian Grothoff
a59d39f699
reinit auditor bd: column dropped 2022-03-17 15:09:14 +01:00
Christian Grothoff
eac8b8c0da
-re-enable test-revocation.sh, works again 2022-03-17 15:06:58 +01:00
Christian Grothoff
bab36a2ac8
-remove dead field, return h_commitment_age to auditor 2022-03-17 14:45:12 +01:00
Christian Grothoff
12809b28ec
-misc fixes 2022-03-17 14:16:34 +01:00
Marco Boss
63879d9d20
more explicit cipher usage counters 2022-03-17 14:09:12 +01:00
Christian Grothoff
fe94405554
regenerate revokedb 2022-03-15 13:09:32 +01:00
Marco Boss
7529939a0f
add metrics for number of crypto operations 2022-03-14 20:06:07 +01:00
Christian Grothoff
687f0cab82
add arguments for new fees 2022-03-14 16:03:01 +01:00
Christian Grothoff
a8d80d519d
attempt to make GRID5K_MARCO_OPT superfluous 2022-03-14 07:34:21 +01:00
Marco Boss
7a74cde9c7
add option to exclude reserve history in grid5k experiments 2022-03-10 10:26:44 +01:00
Christian Grothoff
9a3d993d07
-also work with h_payto trait 2022-03-10 01:48:46 +01:00
MS
e1e68cebb8
cbdc-it 2022-03-09 17:59:24 +01:00
MS
92c594774e
rewording cbdc-it 2022-03-09 15:11:23 +01:00
2fe5223c72
add missing files for system documentation book 2022-03-08 21:56:46 +01:00
cd5ee2338c
-ensure label has no zero bytes 2022-03-08 11:47:51 +01:00
Christian Grothoff
ab3868f83b
-add global-fee subcommand to taler-exchange-offline 2022-03-05 19:03:40 +01:00
Christian Grothoff
54106e63dc
add client API for setting global fees 2022-03-05 18:18:25 +01:00
Christian Grothoff
a080f11890
add more logic for new global fees 2022-03-05 17:14:32 +01:00
Christian Grothoff
57470e4c08
-more work on global_fees 2022-03-05 16:16:38 +01:00
Christian Grothoff
5fa977cc05
work on global fee structure 2022-03-05 15:13:07 +01:00
Christian Grothoff
841e56bafd
also sync global fees table (new) 2022-03-05 14:38:03 +01:00
Christian Grothoff
7ff58c3d8f
refactor /wire to include logic to return the wad fee (for W2W payments) 2022-03-05 14:36:55 +01:00
8a906bf96c
sync tables "extensions" and "extension_details" with auditor 2022-03-05 13:39:01 +01:00
Christian Grothoff
43f8ab6b48
add signing/verifying functions for global fees 2022-03-05 12:04:13 +01:00
Christian Grothoff
4835ddf60b
introduce sets for wire fees and global fees 2022-03-05 11:56:58 +01:00
Christian Grothoff
3a1f418603
improve URI path checking, make it more strict and simplify logic 2022-03-04 22:29:29 +01:00
d0b27833b2
[age restriction] added unit test for get_age_group 2022-03-04 17:00:28 +01:00
Marco Boss
f5e1cf5e6d
rewrite query for recoup_by_reserve 2022-03-04 13:22:28 +01:00
Christian Grothoff
f9a2808ed0
-fix kyc test 2022-03-04 00:30:43 +01:00
Christian Grothoff
1643b745af
use 32 byte hash for hpayto, use that for joins on queries to better align queries with partitions 2022-03-03 23:52:08 +01:00
Christian Grothoff
f951cdef8c
include shard when marking deposits tiny/done to make better use of partitions/shards 2022-03-03 19:39:25 +01:00
4c53d42e44
[age restriction] progress 18/n - attestation tested
- Unit-tests for commit, derive, attest and verify added, with multiple
  combinations of minimum age and commited age.
- Fixed crypto implementation (eddsa -> ecdsa)
- Using now standard functionality from GNUNET:
  GNUNET_CRYPTO_ecdsa_{private,public}_key_derive

All tests pass (unit tests in util/ and 'make check' in testing).
2022-03-03 19:35:24 +01:00
Christian Grothoff
476ae53808
simply defer all, only way to do well with partitions 2022-03-03 17:48:00 +01:00
Thien-Thi Nguyen
80fc8231ad
Don't hardcode directory in taler-auditor-sync(1) invocation 2022-03-02 17:32:52 -05:00
Marco Boss
57e3864c09
Include partitioning in dbinit 2022-03-02 19:03:54 +01:00
Marco Boss
79d123d1b4
fix num partitions 2022-03-02 19:01:27 +01:00
Marco Boss
7f30609ff0
use plain uint32_t 2022-03-02 17:22:43 +01:00
Marco Boss
548613c617
fix 2022-03-02 13:30:44 +01:00
Marco Boss
41a9a73eb8
fix 2022-03-02 13:21:45 +01:00
10d7d93ad8
-tests now with age restriction 2022-03-02 11:59:21 +01:00
Marco Boss
cab654237f
clearer doc 2022-03-02 11:28:28 +01:00
Marco Boss
2abe9bf6d7
include partitioning logic in dbinit 2022-03-02 10:50:51 +01:00
313 changed files with 78830 additions and 14557 deletions

7
.gitignore vendored
View File

@ -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.*

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -0,0 +1,3 @@
/registry.rec
/taler_signatures.h
/taler_signatures.h.tmp

21
contrib/sigp/Makefile Normal file
View 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
View 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
View File

@ -0,0 +1,3 @@
#endif

32
contrib/sigp/h.header Normal file
View 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
View File

@ -0,0 +1,6 @@
/**
* {{Comment}}
*/
#define TALER_SIGNATURE_{{Name}} {{Number}}

View File

@ -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
View 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
Wallets 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 GPLs 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, attorneys 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 protocols 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 youre 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.

View File

@ -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&#37;&#52;&#48;taler-systems&#46;com">legal<span>&#64;</span>taler-systems<span>&#46;</span>com</a>. If you do not agree to this Agreement, you must not
<a class="reference external" href="mailto:ice&#37;&#52;&#48;bfh&#46;ch">ice<span>&#64;</span>bfh<span>&#46;</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.

View File

@ -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 youre 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.

View File

@ -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
View File

@ -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
View File

@ -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)

View File

@ -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
View File

@ -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

View File

@ -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*

View 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

View File

@ -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
View File

@ -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

View File

@ -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\

View File

@ -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 110 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 110 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

View File

@ -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

Binary file not shown.

Binary file not shown.

View 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

View 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

View 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

View 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

Binary file not shown.

View File

@ -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}

Binary file not shown.

49
m4/mhd.m4 Normal file
View 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

View File

@ -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 \

View File

@ -1 +1 @@
1646042841
1655640402

View File

@ -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/

View File

@ -1 +1 @@
TMQ09D9G18Z8TFEABD833SDJ6JQWRYKFHPTWT6DMPQS54ZC66RDG
JM0NJXHM6Y6HYAPK2WDFH3HDJ2E9KZWGKM3E0FYRV2V3HCTB3DQ0

File diff suppressed because it is too large Load Diff

186
src/auditor/batch.conf Normal file
View 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
View 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

View File

@ -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

View File

@ -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 "."

View File

@ -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);
}

View File

@ -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);

View File

@ -1 +1 @@
1638367019
1655640625

View File

@ -1 +1 @@
93PR4M9WR54W046A4DWR58V28T2G94DJCWHY0NMBW2S8N6W60AT0
MREDG0XYVSX4RPYSA6JNQZ93P2DDBG45F3M6RBZXRS49M0JTVN40

File diff suppressed because it is too large Load Diff

View File

@ -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");

View File

@ -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 }
};

View File

@ -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 \

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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)';

View File

@ -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
};

View File

@ -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");

View File

@ -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,

View File

@ -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;
}

View File

@ -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"

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -68,7 +68,6 @@ taler_crypto_worker_LDADD = \
-lgnunetutil \
-lgnunetjson \
-ljansson \
-lpthread \
$(LIBGCRYPT_LIBS) \
$(XLIB)

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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 \

View File

@ -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.)

View File

@ -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,
&currency_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;
}

View File

@ -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);

View 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 */

View File

@ -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)

View File

@ -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.

View File

@ -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);

View 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 */

View 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

View 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 */

View 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

View File

@ -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);

View File

@ -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);

View File

@ -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))

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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