From c1f28638c9929424f9ad395c7016e6ea2022d751 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 17 Jan 2016 18:19:09 +0100 Subject: working on #3888 --- src/include/taler_mintdb_plugin.h | 48 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index d9a1c6c85..a4a94faa9 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -571,7 +571,7 @@ typedef void /** * Function called with the results of the lookup of the * wire transfer identifier information. - * + * * @param cls closure * @param wtid base32-encoded wire transfer identifier, NULL * if the transaction was not yet done @@ -585,6 +585,31 @@ typedef void const char *wtid, struct GNUNET_TIME_Absolute execution_time); + +/** + * Function called with the results of the lookup of the + * transaction data associated with a wire transfer identifier. + * + * @param cls closure + * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls) + * @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls) + * @param h_contract which contract was this payment about + * @param transaction_id merchant's transaction ID for the payment + * @param coin_pub which public key was this payment about + * @param deposit_value amount contributed by this coin in total + * @param deposit_fee deposit fee charged by mint for this coin + */ +typedef void +(*TALER_MINTDB_TransactionDataCallback)(void *cls, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct GNUNET_HashCode *h_wire, + const struct GNUNET_HashCode *h_contract, + uint64_t transaction_id, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *deposit_value, + const struct TALER_Amount *deposit_fee); + + /** * @brief The plugin API, returned from the plugin's "init" function. * The argument given to "init" is simply a configuration handle. @@ -1194,11 +1219,30 @@ struct TALER_MINTDB_Plugin struct TALER_MINTDB_TransactionList *list); + /** + * Lookup the list of Taler transactions that was aggregated + * into a wire transfer by the respective @a raw_wtid. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param raw_wtid the raw wire transfer identifier we used + * @param raw_len number of bytes in @a raw_wtid (right now always 32) + * @param cb function to call on each transaction found + * @param cb_cls closure for @a cb + * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors + */ + int + (*lookup_wire_transactions) (void *cls, + const void *raw_wtid, + size_t raw_len, + TALER_MINTDB_TransactionDataCallback cb, + void *cb_cls); + + /** * Try to find the wire transfer details for a deposit operation. * If we did not execute the deposit yet, return when it is supposed * to be executed. - * + * * @param cls closure * @param h_contract hash of the contract * @param h_wire hash of merchant wire details -- cgit v1.2.3 From 80f6c4240ee26884ac2dfdc02ff6b8aac0951777 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 19 Jan 2016 14:39:00 +0100 Subject: -fix (C) notices --- src/include/taler_amount_lib.h | 2 +- src/include/taler_crypto_lib.h | 2 +- src/include/taler_json_lib.h | 2 +- src/include/taler_mint_service.h | 2 +- src/include/taler_mintdb_lib.h | 2 +- src/include/taler_mintdb_plugin.h | 2 +- src/include/taler_pq_lib.h | 2 +- src/include/taler_signatures.h | 2 +- src/include/taler_util.h | 2 +- src/include/taler_util_wallet.h | 2 +- src/mint-lib/mint_api_admin.c | 2 +- src/mint-lib/mint_api_common.c | 2 +- src/mint-lib/mint_api_common.h | 2 +- src/mint-lib/mint_api_context.c | 2 +- src/mint-lib/mint_api_context.h | 2 +- src/mint-lib/mint_api_deposit.c | 2 +- src/mint-lib/mint_api_handle.c | 2 +- src/mint-lib/mint_api_handle.h | 2 +- src/mint-lib/mint_api_refresh.c | 2 +- src/mint-lib/mint_api_refresh_link.c | 2 +- src/mint-lib/mint_api_reserve.c | 2 +- src/mint-lib/mint_api_wire.c | 2 +- src/mint-lib/test_mint_api.c | 2 +- src/mint-tools/taler-auditor-sign.c | 2 +- src/mint-tools/taler-mint-dbinit.c | 2 +- src/mint-tools/taler-mint-keycheck.c | 2 +- src/mint-tools/taler-mint-keyup.c | 2 +- src/mint-tools/taler-mint-reservemod.c | 2 +- src/mint-tools/taler-mint-sepa.c | 2 +- src/mint/taler-mint-httpd_db.c | 2 +- src/mint/taler-mint-httpd_db.h | 2 +- src/mintdb/mintdb_keyio.c | 2 +- src/mintdb/mintdb_plugin.c | 2 +- src/mintdb/perf_taler_mintdb.c | 2 +- src/mintdb/perf_taler_mintdb_init.c | 2 +- src/mintdb/perf_taler_mintdb_init.h | 2 +- src/mintdb/perf_taler_mintdb_interpreter.c | 2 +- src/mintdb/perf_taler_mintdb_interpreter.h | 2 +- src/mintdb/perf_taler_mintdb_values.h | 2 +- src/mintdb/plugin_mintdb_common.c | 2 +- src/mintdb/plugin_mintdb_postgres.c | 2 +- src/mintdb/test_mintdb.c | 2 +- src/mintdb/test_mintdb_deposits.c | 2 +- src/mintdb/test_perf_taler_mintdb.c | 2 +- src/pq/db_pq.c | 2 +- src/pq/pq_helper.c | 2 +- src/pq/test_pq.c | 2 +- src/util/amount.c | 2 +- src/util/crypto.c | 2 +- src/util/json.c | 2 +- src/util/os_installation.c | 2 +- src/util/test_amount.c | 2 +- src/util/test_crypto.c | 2 +- src/util/test_json.c | 2 +- src/util/test_wireformats.c | 2 +- src/util/util.c | 2 +- src/util/wireformats.c | 2 +- 57 files changed, 57 insertions(+), 57 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_amount_lib.h b/src/include/taler_amount_lib.h index 8661ed913..094b96f7f 100644 --- a/src/include/taler_amount_lib.h +++ b/src/include/taler_amount_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 87020fbbe..20cb434f1 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index 8bdcf2709..d9fa05188 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h index 78650edfe..a7b6afd11 100644 --- a/src/include/taler_mint_service.h +++ b/src/include/taler_mint_service.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software diff --git a/src/include/taler_mintdb_lib.h b/src/include/taler_mintdb_lib.h index 7dfef8dc5..70e314d9a 100644 --- a/src/include/taler_mintdb_lib.h +++ b/src/include/taler_mintdb_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index a4a94faa9..90319b964 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index 2fe66c52f..e0ca429e1 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index ef9486e49..ac0119831 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015, 2016 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/include/taler_util.h b/src/include/taler_util.h index b6dd9596a..380901812 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/include/taler_util_wallet.h b/src/include/taler_util_wallet.h index 4699a469d..87efcddaa 100644 --- a/src/include/taler_util_wallet.h +++ b/src/include/taler_util_wallet.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_admin.c b/src/mint-lib/mint_api_admin.c index 472b02e7d..641e0690f 100644 --- a/src/mint-lib/mint_api_admin.c +++ b/src/mint-lib/mint_api_admin.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_common.c b/src/mint-lib/mint_api_common.c index fd85fbdc4..faba38c74 100644 --- a/src/mint-lib/mint_api_common.c +++ b/src/mint-lib/mint_api_common.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_common.h b/src/mint-lib/mint_api_common.h index d256fa428..10a202146 100644 --- a/src/mint-lib/mint_api_common.h +++ b/src/mint-lib/mint_api_common.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_context.c b/src/mint-lib/mint_api_context.c index e60e01b07..3a86efb64 100644 --- a/src/mint-lib/mint_api_context.c +++ b/src/mint-lib/mint_api_context.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_context.h b/src/mint-lib/mint_api_context.h index 79613cc8b..181a4808f 100644 --- a/src/mint-lib/mint_api_context.h +++ b/src/mint-lib/mint_api_context.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_deposit.c b/src/mint-lib/mint_api_deposit.c index 58436adfa..400372925 100644 --- a/src/mint-lib/mint_api_deposit.c +++ b/src/mint-lib/mint_api_deposit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_handle.c b/src/mint-lib/mint_api_handle.c index 49960cb10..077e42c24 100644 --- a/src/mint-lib/mint_api_handle.c +++ b/src/mint-lib/mint_api_handle.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_handle.h b/src/mint-lib/mint_api_handle.h index fae30a309..0dae58db6 100644 --- a/src/mint-lib/mint_api_handle.h +++ b/src/mint-lib/mint_api_handle.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_refresh.c b/src/mint-lib/mint_api_refresh.c index 9effa3d40..cea16b153 100644 --- a/src/mint-lib/mint_api_refresh.c +++ b/src/mint-lib/mint_api_refresh.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_refresh_link.c b/src/mint-lib/mint_api_refresh_link.c index d4060bd1c..17c96039e 100644 --- a/src/mint-lib/mint_api_refresh_link.c +++ b/src/mint-lib/mint_api_refresh_link.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_reserve.c b/src/mint-lib/mint_api_reserve.c index a726eca46..1f8140cff 100644 --- a/src/mint-lib/mint_api_reserve.c +++ b/src/mint-lib/mint_api_reserve.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/mint_api_wire.c b/src/mint-lib/mint_api_wire.c index 5fc82f72d..0947354ad 100644 --- a/src/mint-lib/mint_api_wire.c +++ b/src/mint-lib/mint_api_wire.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-lib/test_mint_api.c b/src/mint-lib/test_mint_api.c index 024e080fc..0e3b2bed8 100644 --- a/src/mint-lib/test_mint_api.c +++ b/src/mint-lib/test_mint_api.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-tools/taler-auditor-sign.c b/src/mint-tools/taler-auditor-sign.c index bd37e68de..7e6d3b12a 100644 --- a/src/mint-tools/taler-auditor-sign.c +++ b/src/mint-tools/taler-auditor-sign.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-tools/taler-mint-dbinit.c b/src/mint-tools/taler-mint-dbinit.c index 3293a69ab..2d9f77764 100644 --- a/src/mint-tools/taler-mint-dbinit.c +++ b/src/mint-tools/taler-mint-dbinit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-tools/taler-mint-keycheck.c b/src/mint-tools/taler-mint-keycheck.c index c5ac86cb6..4fa2707f8 100644 --- a/src/mint-tools/taler-mint-keycheck.c +++ b/src/mint-tools/taler-mint-keycheck.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-tools/taler-mint-keyup.c b/src/mint-tools/taler-mint-keyup.c index e2c8d7986..b82554b94 100644 --- a/src/mint-tools/taler-mint-keyup.c +++ b/src/mint-tools/taler-mint-keyup.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-tools/taler-mint-reservemod.c b/src/mint-tools/taler-mint-reservemod.c index 11d67ed5d..38d27054a 100644 --- a/src/mint-tools/taler-mint-reservemod.c +++ b/src/mint-tools/taler-mint-reservemod.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint-tools/taler-mint-sepa.c b/src/mint-tools/taler-mint-sepa.c index 21f4af9c4..e66db541e 100644 --- a/src/mint-tools/taler-mint-sepa.c +++ b/src/mint-tools/taler-mint-sepa.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 1b0af585d..14e03dfd2 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index 0ee3d0509..e366112dd 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/mintdb_keyio.c b/src/mintdb/mintdb_keyio.c index 5bfe5bb12..89ac9055a 100644 --- a/src/mintdb/mintdb_keyio.c +++ b/src/mintdb/mintdb_keyio.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/mintdb_plugin.c b/src/mintdb/mintdb_plugin.c index 2e8d206fd..f1b2ad044 100644 --- a/src/mintdb/mintdb_plugin.c +++ b/src/mintdb/mintdb_plugin.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/perf_taler_mintdb.c b/src/mintdb/perf_taler_mintdb.c index 73708a6c7..fbaa2ce34 100644 --- a/src/mintdb/perf_taler_mintdb.c +++ b/src/mintdb/perf_taler_mintdb.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/perf_taler_mintdb_init.c b/src/mintdb/perf_taler_mintdb_init.c index 141ac1ab8..97a1b4c99 100644 --- a/src/mintdb/perf_taler_mintdb_init.c +++ b/src/mintdb/perf_taler_mintdb_init.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/perf_taler_mintdb_init.h b/src/mintdb/perf_taler_mintdb_init.h index 063259f51..f94beef10 100644 --- a/src/mintdb/perf_taler_mintdb_init.h +++ b/src/mintdb/perf_taler_mintdb_init.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/perf_taler_mintdb_interpreter.c b/src/mintdb/perf_taler_mintdb_interpreter.c index 9084513fb..293d5f35f 100644 --- a/src/mintdb/perf_taler_mintdb_interpreter.c +++ b/src/mintdb/perf_taler_mintdb_interpreter.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/perf_taler_mintdb_interpreter.h b/src/mintdb/perf_taler_mintdb_interpreter.h index 722d1a07d..3510e3dd4 100644 --- a/src/mintdb/perf_taler_mintdb_interpreter.h +++ b/src/mintdb/perf_taler_mintdb_interpreter.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/perf_taler_mintdb_values.h b/src/mintdb/perf_taler_mintdb_values.h index 25202edd1..35f87f5b0 100644 --- a/src/mintdb/perf_taler_mintdb_values.h +++ b/src/mintdb/perf_taler_mintdb_values.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/plugin_mintdb_common.c b/src/mintdb/plugin_mintdb_common.c index bbe104f6c..1f2fdc58b 100644 --- a/src/mintdb/plugin_mintdb_common.c +++ b/src/mintdb/plugin_mintdb_common.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index 2ebc8f0ff..057ea9fe8 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/test_mintdb.c b/src/mintdb/test_mintdb.c index 5b9d1c2ec..0cd660a4d 100644 --- a/src/mintdb/test_mintdb.c +++ b/src/mintdb/test_mintdb.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/test_mintdb_deposits.c b/src/mintdb/test_mintdb_deposits.c index 171fa2c69..3ce0a35a5 100644 --- a/src/mintdb/test_mintdb_deposits.c +++ b/src/mintdb/test_mintdb_deposits.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/mintdb/test_perf_taler_mintdb.c b/src/mintdb/test_perf_taler_mintdb.c index 2830ef812..789a0dd4f 100644 --- a/src/mintdb/test_perf_taler_mintdb.c +++ b/src/mintdb/test_perf_taler_mintdb.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/pq/db_pq.c b/src/pq/db_pq.c index e1a082e44..59a1db022 100644 --- a/src/pq/db_pq.c +++ b/src/pq/db_pq.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/pq/pq_helper.c b/src/pq/pq_helper.c index bd54447e7..d245ffdb8 100644 --- a/src/pq/pq_helper.c +++ b/src/pq/pq_helper.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c index bda227587..f0413d1ff 100644 --- a/src/pq/test_pq.c +++ b/src/pq/test_pq.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2015 Christian Grothoff (and other contributing authors) + (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/util/amount.c b/src/util/amount.c index 7260b150f..dc2d2e400 100644 --- a/src/util/amount.c +++ b/src/util/amount.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/util/crypto.c b/src/util/crypto.c index ebf6413db..9e6890569 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/util/json.c b/src/util/json.c index cea0118e1..6aca7548c 100644 --- a/src/util/json.c +++ b/src/util/json.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/util/os_installation.c b/src/util/os_installation.c index ec1868a84..0eab118fe 100644 --- a/src/util/os_installation.c +++ b/src/util/os_installation.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2006-2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2006-2014 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published diff --git a/src/util/test_amount.c b/src/util/test_amount.c index 4741bcf36..3f33334bc 100644 --- a/src/util/test_amount.c +++ b/src/util/test_amount.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2015 Christian Grothoff (and other contributing authors) + (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c index a5313195a..59acd7814 100644 --- a/src/util/test_crypto.c +++ b/src/util/test_crypto.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2015 Christian Grothoff (and other contributing authors) + (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/util/test_json.c b/src/util/test_json.c index c48fe68bd..5e2f50fe8 100644 --- a/src/util/test_json.c +++ b/src/util/test_json.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2015 Christian Grothoff (and other contributing authors) + (C) 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/util/test_wireformats.c b/src/util/test_wireformats.c index 7e0e5bbc4..b41abb802 100644 --- a/src/util/test_wireformats.c +++ b/src/util/test_wireformats.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) + (C) 2014 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/util/util.c b/src/util/util.c index 08438cfab..addafacf7 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/util/wireformats.c b/src/util/wireformats.c index dab7fb926..cd5a9c3d4 100644 --- a/src/util/wireformats.c +++ b/src/util/wireformats.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software -- cgit v1.2.3 From 43e04f2ad105ff4712697b3480bbb75330f69ad3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 20 Jan 2016 18:50:19 +0100 Subject: work on #3888 --- src/include/taler_mintdb_plugin.h | 15 +++++---- src/include/taler_signatures.h | 16 +++++----- src/mint/taler-mint-httpd_db.c | 40 ++++++++++++++++++++++-- src/mint/taler-mint-httpd_responses.c | 59 ++++++++++++++++++++++++++++++----- src/mint/taler-mint-httpd_responses.h | 14 +++++++-- src/mintdb/plugin_mintdb_postgres.c | 8 ++--- 6 files changed, 120 insertions(+), 32 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 90319b964..9e4f891c5 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -573,8 +573,11 @@ typedef void * wire transfer identifier information. * * @param cls closure - * @param wtid base32-encoded wire transfer identifier, NULL + * @param wtid wire transfer identifier, NULL * if the transaction was not yet done + * @param coin_contribution how much did the coin we asked about + * contribute to the total transfer value? (deposit value minus fee) + * @param total_amount how much was the total wire transfer? * @param execution_time when was the transaction done, or * when we expect it to be done (if @a wtid was NULL); * #GNUNET_TIME_UNIT_FOREVER_ABS if the /deposit is unknown @@ -582,7 +585,9 @@ typedef void */ typedef void (*TALER_MINTDB_DepositWtidCallback)(void *cls, - const char *wtid, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *total_amount, struct GNUNET_TIME_Absolute execution_time); @@ -1224,16 +1229,14 @@ struct TALER_MINTDB_Plugin * into a wire transfer by the respective @a raw_wtid. * * @param cls the @e cls of this struct with the plugin-specific state - * @param raw_wtid the raw wire transfer identifier we used - * @param raw_len number of bytes in @a raw_wtid (right now always 32) + * @param wtid the raw wire transfer identifier we used * @param cb function to call on each transaction found * @param cb_cls closure for @a cb * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors */ int (*lookup_wire_transactions) (void *cls, - const void *raw_wtid, - size_t raw_len, + const struct TALER_WireTransferIdentifierRawP *wtid, TALER_MINTDB_TransactionDataCallback cb, void *cb_cls); diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 62e602a01..29008fc9a 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -893,7 +893,7 @@ struct TALER_ConfirmWirePS /** * Raw value (binary encoding) of the wire transfer subject. */ - struct TALER_WireTransferIdentifierRawP raw; + struct TALER_WireTransferIdentifierRawP wtid; /** * The coin's public key. This is the value that must have been @@ -903,13 +903,13 @@ struct TALER_ConfirmWirePS /** * Merchant-generated transaction ID to detect duplicate - * transactions. The merchant must communicate a merchant-unique ID - * to the customer for each transaction. Note that different coins - * that are part of the same transaction can use the same - * transaction ID. The transaction ID is useful for later disputes, - * and the merchant's contract offer (@e h_contract) with the - * customer should include the offer's term and transaction ID - * signed with a key from the merchant. + * transactions, in big endian. The merchant must communicate a + * merchant-unique ID to the customer for each transaction. Note + * that different coins that are part of the same transaction can + * use the same transaction ID. The transaction ID is useful for + * later disputes, and the merchant's contract offer (@e h_contract) + * with the customer should include the offer's term and transaction + * ID signed with a key from the merchant. */ uint64_t transaction_id GNUNET_PACKED; diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 14e03dfd2..d31dcd2ba 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1702,7 +1702,6 @@ TMH_DB_execute_wire_deposits (struct MHD_Connection *connection, ctx.deposits = json_array (); ret = TMH_plugin->lookup_wire_transactions (TMH_plugin->cls, &wtid->raw, - sizeof (wtid->raw), &handle_transaction_data, &ctx); if (GNUNET_SYSERR == ret) @@ -1742,6 +1741,26 @@ struct DepositWtidContext */ struct MHD_Connection *connection; + /** + * Hash of the contract we are looking up. + */ + struct GNUNET_HashCode h_contract; + + /** + * Hash of the wire transfer details we are looking up. + */ + struct GNUNET_HashCode h_wire; + + /** + * Public key we are looking up. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * Transaction ID we are looking up. + */ + uint64_t transaction_id; + /** * MHD result code to return. */ @@ -1754,8 +1773,11 @@ struct DepositWtidContext * wire transfer identifier information. * * @param cls our context for transmission - * @param wtid base32-encoded wire transfer identifier, NULL + * @param wtid raw wire transfer identifier, NULL * if the transaction was not yet done + * @param coin_contribution how much did the coin we asked about + * contribute to the total transfer value? (deposit value minus fee) + * @param total_amount how much was the total wire transfer? * @param execution_time when was the transaction done, or * when we expect it to be done (if @a wtid was NULL); * #GNUNET_TIME_UNIT_FOREVER_ABS if the /deposit is unknown @@ -1763,7 +1785,9 @@ struct DepositWtidContext */ static void handle_wtid_data (void *cls, - const char *wtid, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *total_amount, struct GNUNET_TIME_Absolute execution_time) { struct DepositWtidContext *ctx = cls; @@ -1780,6 +1804,12 @@ handle_wtid_data (void *cls, else { ctx->res = TMH_RESPONSE_reply_deposit_wtid (ctx->connection, + &ctx->h_contract, + &ctx->h_wire, + &ctx->coin_pub, + coin_contribution, + total_amount, + ctx->transaction_id, wtid, execution_time); } @@ -1810,6 +1840,10 @@ TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection, struct DepositWtidContext ctx; ctx.connection = connection; + ctx.h_contract = *h_contract; + ctx.h_wire = *h_wire; + ctx.coin_pub = *coin_pub; + ctx.transaction_id = transaction_id; ctx.res = MHD_NO; /* this value should never be read... */ ret = TMH_plugin->wire_lookup_deposit_wtid (TMH_plugin->cls, h_contract, diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 9a55d5aab..d89b74c8f 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -1092,34 +1092,69 @@ TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection, * them. Generates the 200 reply. * * @param connection connection to the client - * @param wtid wire transfer identifier (as 0-terminated string) + * @param h_contract 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 total_amount how much was the total wire transfer? + * @param transaction_id merchant transaction identifier + * @param wtid raw wire transfer identifier * @param exec_time execution time of the wire transfer * @return MHD result code */ int TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, - const char *wtid, + const struct GNUNET_HashCode *h_contract, + const struct GNUNET_HashCode *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *total_amount, + uint64_t transaction_id, + const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute exec_time) { struct TALER_ConfirmWirePS cw; struct TALER_MintPublicKeyP pub; struct TALER_MintSignatureP sig; + struct TALER_WireTransferIdentifierP wtid_crc; + char *wtid_s; + int ret; + /* Create signature for the reply */ cw.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_WIRE); cw.purpose.size = htonl (sizeof (struct TALER_ConfirmWirePS)); - // FIXME: fill in rest of 'cw'! + cw.h_wire = *h_wire; + cw.h_contract = *h_contract; + cw.wtid = *wtid; + cw.coin_pub = *coin_pub; + cw.transaction_id = GNUNET_htonll (transaction_id); + cw.execution_time = GNUNET_TIME_absolute_hton (exec_time); + TALER_amount_hton (&cw.coin_contribution, + coin_contribution); + TALER_amount_hton (&cw.total_amount, + total_amount); TMH_KS_sign (&cw.purpose, &pub, &sig); - return TMH_RESPONSE_reply_json_pack (connection, - MHD_HTTP_FOUND, + /* Compute checksum and crockford encoding if wire transfer subject */ + wtid_crc.raw = *wtid; + wtid_crc.crc8 = GNUNET_CRYPTO_crc8_n (wtid, + sizeof (struct TALER_WireTransferIdentifierRawP)); + + wtid_s = GNUNET_STRINGS_data_to_string_alloc (&wtid_crc, + sizeof (wtid_crc)); + ret = TMH_RESPONSE_reply_json_pack (connection, + MHD_HTTP_OK, "{s:s, s:o, s:o, s:o}", - "wtid", wtid, + "wtid", wtid_s, "execution_time", TALER_json_from_abs (exec_time), "mint_sig", TALER_json_from_data (&sig, sizeof (sig)), "mint_pub", TALER_json_from_data (&pub, sizeof (pub))); + GNUNET_free (wtid_s); + return ret; } @@ -1141,8 +1176,16 @@ TMH_RESPONSE_reply_wire_deposit_details (struct MHD_Connection *connection, const struct GNUNET_HashCode *h_wire, json_t *deposits) { - GNUNET_break (0); // FIXME: not implemented - return MHD_NO; + /* FIXME: #4135: signing not implemented here */ + return TMH_RESPONSE_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o, s:o, s:o}", + "total", TALER_json_from_amount (total), + "merchant_pub", TALER_json_from_data (merchant_pub, + sizeof (struct TALER_MerchantPublicKeyP)), + "h_wire", TALER_json_from_data (h_wire, + sizeof (struct GNUNET_HashCode)), + "deposits", deposits); } diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index 6debbc935..caad29047 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -277,13 +277,23 @@ TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection, * them. Generates the 200 reply. * * @param connection connection to the client - * @param wtid wire transfer identifier (as 0-terminated string) + * @param h_contract hash of the contract + * @param h_wire hash of wire account details + * @param coin_pub public key of the coin + * @param transaction_id merchant transaction identifier + * @param wtid raw wire transfer identifier * @param exec_time execution time of the wire transfer * @return MHD result code */ int TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, - const char *wtid, + const struct GNUNET_HashCode *h_contract, + const struct GNUNET_HashCode *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *total_amount, + uint64_t transaction_id, + const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute exec_time); diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index 057ea9fe8..ad0c91150 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -3366,19 +3366,17 @@ postgres_get_coin_transactions (void *cls, /** * Lookup the list of Taler transactions that was aggregated - * into a wire transfer by the respective @a raw_wtid. + * into a wire transfer by the respective @a wtid. * * @param cls closure - * @param raw_wtid the raw wire transfer identifier we used - * @param raw_len number of bytes in @a raw_wtid (right now always 32) + * @param wtid the raw wire transfer identifier we used * @param cb function to call on each transaction found * @param cb_cls closure for @a cb * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors */ static int postgres_lookup_wire_transactions (void *cls, - const void *raw_wtid, - size_t raw_len, + const struct TALER_WireTransferIdentifierRawP *wtid, TALER_MINTDB_TransactionDataCallback cb, void *cb_cls) { -- cgit v1.2.3 From 8f071e2200f0421caf1969c71a16ed62b3356fb5 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 21 Jan 2016 08:44:45 +0100 Subject: adding aggregation_tracking table to postgres plugin --- src/include/taler_crypto_lib.h | 5 ++ src/include/taler_mintdb_plugin.h | 29 ++++++++- src/mintdb/plugin_mintdb_postgres.c | 119 ++++++++++++++++++++++++++++++++++-- 3 files changed, 148 insertions(+), 5 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 36ca6a023..6056270fa 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -434,6 +434,11 @@ struct TALER_RefreshLinkDecrypted */ #define TALER_WIRE_TRANSFER_IDENTIFIER_LEN 32 +/** + * #TALER_WIRE_TRANSFER_IDENTIFIER_LEN as a string. + */ +#define TALER_WIRE_TRANSFER_IDENTIFIER_LEN_STR "32" + /** * Raw value of a wire transfer subjects, without the checksum. */ diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 9e4f891c5..baf587886 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 GNUnet e.V. + Copyright (C) 2014, 2015, 2016 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1266,6 +1266,33 @@ struct TALER_MINTDB_Plugin TALER_MINTDB_DepositWtidCallback cb, void *cb_cls); + + /** + * Function called to insert aggregation information into the DB. + * + * @param cls closure + * @param wtid the raw wire transfer identifier we used + * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls) + * @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls) + * @param h_contract which contract was this payment about + * @param transaction_id merchant's transaction ID for the payment + * @param coin_pub which public key was this payment about + * @param deposit_value amount contributed by this coin in total + * @param deposit_fee deposit fee charged by mint for this coin + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + */ + int + (*insert_aggregation_tracking)(void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct GNUNET_HashCode *h_wire, + const struct GNUNET_HashCode *h_contract, + uint64_t transaction_id, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *deposit_value, + const struct TALER_Amount *deposit_fee); + + }; diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index ad0c91150..ca8edcffd 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015 GNUnet e.V. + Copyright (C) 2014, 2015, 2016 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -445,9 +445,34 @@ postgres_create_tables (void *cls, ",coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)" ",wire TEXT NOT NULL" ")"); - /* Index for get_deposit statement on coin_pub, transactiojn_id and merchant_pub */ + /* Index for get_deposit statement on coin_pub, transaction_id and merchant_pub */ SQLEXEC_INDEX("CREATE INDEX deposits_coin_pub_index " "ON deposits(coin_pub, transaction_id, merchant_pub)"); + /* Table for the tracking API, mapping from wire transfer identifiers + to transactions and back */ + SQLEXEC("CREATE TABLE IF NOT EXISTS aggregation_tracking " + "(h_contract BYTEA PRIMARY KEY CHECK (LENGTH(h_contract)=64)" + ",h_wire BYTEA PRIMARY KEY CHECK (LENGTH(h_wire)=64)" + ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)" + ",merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)" + ",transaction_id INT8 NOT NULL" + ",wtid_raw BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=" TALER_WIRE_TRANSFER_IDENTIFIER_LEN_STR ")" + ",execution_time INT8 NOT NULL" + ",coin_amount_val INT8 NOT NULL" + ",coin_amount_frac INT4 NOT NULL" + ",coin_amount_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" + ",transaction_total_val INT8 NOT NULL" + ",transaction_total_frac INT4 NOT NULL" + ",transaction_total_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" + ")"); + /* Index for lookup_transactions statement on wtid */ + SQLEXEC_INDEX("CREATE INDEX aggregation_tracking_wtid_index " + "ON aggregation_tracking(wtid_raw)"); + /* Index for lookup_deposit_wtid statement */ + SQLEXEC_INDEX("CREATE INDEX aggregation_tracking_deposit_index " + "ON aggregation_tracking(coin_pub,h_contract,h_wire,transaction_id,merchant_pub)"); + + #undef SQLEXEC #undef SQLEXEC_INDEX @@ -947,6 +972,63 @@ postgres_prepare (PGconn *db_conn) " AND rm.oldcoin_index = rcl.oldcoin_index" " AND rcl.cnc_index=rs.noreveal_index", 1, NULL); + /* Used in #postgres_lookup_wire_transactions */ + PREPARE ("lookup_transactions", + "SELECT" + " h_contract" + ",h_wire" + ",coin_pub" + ",merchant_pub" + ",transaction_id" + ",execution_time" + ",coin_amount_val" + ",coin_amount_frac" + ",coin_amount_curr" + ",transaction_total_val" + ",transaction_total_frac" + ",transaction_total_curr" + " FROM aggregation_tracking" + " WHERE wtid_raw=$1", + 1, NULL); + /* Used in #postgres_wire_lookup_deposit_wtid */ + PREPARE ("lookup_deposit_wtid", + "SELECT" + " wtid_raw" + ",execution_time" + ",coin_amount_val" + ",coin_amount_frac" + ",coin_amount_curr" + ",transaction_total_val" + ",transaction_total_frac" + ",transaction_total_curr" + " FROM aggregation_tracking" + " WHERE" + " coin_pub=$1 AND" + " h_contract=$2 AND" + " h_wire=$3 AND" + " transaction_id=$4 AND" + " merchant_pub=$5", + 5, NULL); + /* Used in #postgres_insert_aggregation_tracking */ + PREPARE ("insert_aggregation_tracking", + "INSERT INTO aggregation_tracking " + "(h_contract" + ",h_wire" + ",coin_pub" + ",merchant_pub" + ",transaction_id" + ",wtid_raw" + ",execution_time" + ",coin_amount_val" + ",coin_amount_frac" + ",coin_amount_curr" + ",transaction_total_val" + ",transaction_total_frac" + ",transaction_total_curr" + ") VALUES " + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", + 13, NULL); + return GNUNET_OK; #undef PREPARE } @@ -3415,6 +3497,36 @@ postgres_wire_lookup_deposit_wtid (void *cls, } +/** + * Function called to insert aggregation information into the DB. + * + * @param cls closure + * @param wtid the raw wire transfer identifier we used + * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls) + * @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls) + * @param h_contract which contract was this payment about + * @param transaction_id merchant's transaction ID for the payment + * @param coin_pub which public key was this payment about + * @param deposit_value amount contributed by this coin in total + * @param deposit_fee deposit fee charged by mint for this coin + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + */ +static int +postgres_insert_aggregation_tracking (void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct GNUNET_HashCode *h_wire, + const struct GNUNET_HashCode *h_contract, + uint64_t transaction_id, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *deposit_value, + const struct TALER_Amount *deposit_fee) +{ + GNUNET_break (0); // not implemented + return GNUNET_SYSERR; +} + + /** * Initialize Postgres database subsystem. * @@ -3466,7 +3578,6 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->have_deposit = &postgres_have_deposit; plugin->iterate_deposits = &postgres_iterate_deposits; plugin->insert_deposit = &postgres_insert_deposit; - plugin->get_refresh_session = &postgres_get_refresh_session; plugin->create_refresh_session = &postgres_create_refresh_session; plugin->insert_refresh_melt = &postgres_insert_refresh_melt; @@ -3477,7 +3588,6 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->get_refresh_commit_coins = &postgres_get_refresh_commit_coins; plugin->insert_refresh_commit_links = &postgres_insert_refresh_commit_links; plugin->get_refresh_commit_links = &postgres_get_refresh_commit_links; - plugin->get_melt_commitment = &postgres_get_melt_commitment; plugin->free_melt_commitment = &common_free_melt_commitment; plugin->insert_refresh_out = &postgres_insert_refresh_out; @@ -3488,6 +3598,7 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->free_coin_transaction_list = &common_free_coin_transaction_list; plugin->lookup_wire_transactions = &postgres_lookup_wire_transactions; plugin->wire_lookup_deposit_wtid = &postgres_wire_lookup_deposit_wtid; + plugin->insert_aggregation_tracking = &postgres_insert_aggregation_tracking; return plugin; } -- cgit v1.2.3 From 9ccba0e77f1c388bbfb7e6bea1b650797d57d023 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 21 Jan 2016 11:24:18 +0100 Subject: implementing insert function into aggregation table --- src/include/taler_mintdb_plugin.h | 16 ++++++++++---- src/mint-lib/mint_api_context.c | 2 +- src/mint/taler-mint-httpd_db.c | 16 ++++++++++++++ src/mintdb/plugin_mintdb_postgres.c | 43 +++++++++++++++++++++++++++++++++++-- 4 files changed, 70 insertions(+), 7 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index baf587886..2ffde2285 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -1229,6 +1229,7 @@ struct TALER_MINTDB_Plugin * into a wire transfer by the respective @a raw_wtid. * * @param cls the @e cls of this struct with the plugin-specific state + * @param session database connection * @param wtid the raw wire transfer identifier we used * @param cb function to call on each transaction found * @param cb_cls closure for @a cb @@ -1236,6 +1237,7 @@ struct TALER_MINTDB_Plugin */ int (*lookup_wire_transactions) (void *cls, + struct TALER_MINTDB_Session *session, const struct TALER_WireTransferIdentifierRawP *wtid, TALER_MINTDB_TransactionDataCallback cb, void *cb_cls); @@ -1247,6 +1249,7 @@ struct TALER_MINTDB_Plugin * to be executed. * * @param cls closure + * @param session database connection * @param h_contract hash of the contract * @param h_wire hash of merchant wire details * @param coin_pub public key of deposited coin @@ -1258,6 +1261,7 @@ struct TALER_MINTDB_Plugin */ int (*wire_lookup_deposit_wtid)(void *cls, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *h_contract, const struct GNUNET_HashCode *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, @@ -1271,26 +1275,30 @@ struct TALER_MINTDB_Plugin * Function called to insert aggregation information into the DB. * * @param cls closure + * @param session database connection * @param wtid the raw wire transfer identifier we used * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls) * @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls) * @param h_contract which contract was this payment about * @param transaction_id merchant's transaction ID for the payment + * @param execution_time when did we execute the transaction * @param coin_pub which public key was this payment about - * @param deposit_value amount contributed by this coin in total - * @param deposit_fee deposit fee charged by mint for this coin + * @param coin_value amount contributed by this coin to the total + * @param transaction_value total amount of the wire transaction * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ int (*insert_aggregation_tracking)(void *cls, + struct TALER_MINTDB_Session *session, const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct GNUNET_HashCode *h_wire, const struct GNUNET_HashCode *h_contract, uint64_t transaction_id, + struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *deposit_value, - const struct TALER_Amount *deposit_fee); + const struct TALER_Amount *coin_value, + const struct TALER_Amount *transaction_value); }; diff --git a/src/mint-lib/mint_api_context.c b/src/mint-lib/mint_api_context.c index 3a86efb64..2767906b5 100644 --- a/src/mint-lib/mint_api_context.c +++ b/src/mint-lib/mint_api_context.c @@ -288,7 +288,7 @@ TALER_MINT_perform (struct TALER_MINT_Context *ctx) GNUNET_assert (CURLE_OK == curl_easy_getinfo (cmsg->easy_handle, CURLINFO_PRIVATE, - (char *) &job)); + (char **) &job)); GNUNET_assert (job->ctx == ctx); job->jcc (job->jcc_cls, cmsg->easy_handle); diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index d31dcd2ba..cc1642202 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1697,10 +1697,18 @@ TMH_DB_execute_wire_deposits (struct MHD_Connection *connection, { int ret; struct WtidTransactionContext ctx; + struct TALER_MINTDB_Session *session; + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, + TMH_test_mode))) + { + GNUNET_break (0); + return TMH_RESPONSE_reply_internal_db_error (connection); + } ctx.is_valid = GNUNET_NO; ctx.deposits = json_array (); ret = TMH_plugin->lookup_wire_transactions (TMH_plugin->cls, + session, &wtid->raw, &handle_transaction_data, &ctx); @@ -1838,7 +1846,14 @@ TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection, { int ret; struct DepositWtidContext ctx; + struct TALER_MINTDB_Session *session; + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, + TMH_test_mode))) + { + GNUNET_break (0); + return TMH_RESPONSE_reply_internal_db_error (connection); + } ctx.connection = connection; ctx.h_contract = *h_contract; ctx.h_wire = *h_wire; @@ -1846,6 +1861,7 @@ TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection, ctx.transaction_id = transaction_id; ctx.res = MHD_NO; /* this value should never be read... */ ret = TMH_plugin->wire_lookup_deposit_wtid (TMH_plugin->cls, + session, h_contract, h_wire, coin_pub, diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index ca8edcffd..f3760216f 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -3451,6 +3451,7 @@ postgres_get_coin_transactions (void *cls, * into a wire transfer by the respective @a wtid. * * @param cls closure + * @param session database connection * @param wtid the raw wire transfer identifier we used * @param cb function to call on each transaction found * @param cb_cls closure for @a cb @@ -3458,6 +3459,7 @@ postgres_get_coin_transactions (void *cls, */ static int postgres_lookup_wire_transactions (void *cls, + struct TALER_MINTDB_Session *session, const struct TALER_WireTransferIdentifierRawP *wtid, TALER_MINTDB_TransactionDataCallback cb, void *cb_cls) @@ -3473,6 +3475,7 @@ postgres_lookup_wire_transactions (void *cls, * to be executed. * * @param cls closure + * @param session database connection * @param h_contract hash of the contract * @param h_wire hash of merchant wire details * @param coin_pub public key of deposited coin @@ -3484,6 +3487,7 @@ postgres_lookup_wire_transactions (void *cls, */ static int postgres_wire_lookup_deposit_wtid (void *cls, + struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *h_contract, const struct GNUNET_HashCode *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, @@ -3501,6 +3505,7 @@ postgres_wire_lookup_deposit_wtid (void *cls, * Function called to insert aggregation information into the DB. * * @param cls closure + * @param session database connection * @param wtid the raw wire transfer identifier we used * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls) * @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls) @@ -3513,15 +3518,49 @@ postgres_wire_lookup_deposit_wtid (void *cls, */ static int postgres_insert_aggregation_tracking (void *cls, + struct TALER_MINTDB_Session *session, const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct GNUNET_HashCode *h_wire, const struct GNUNET_HashCode *h_contract, uint64_t transaction_id, + struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *deposit_value, - const struct TALER_Amount *deposit_fee) + const struct TALER_Amount *coin_value, + const struct TALER_Amount *transaction_value) { + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_auto_from_type (h_contract), + TALER_PQ_query_param_auto_from_type (h_wire), + TALER_PQ_query_param_auto_from_type (coin_pub), + TALER_PQ_query_param_auto_from_type (merchant_pub), + TALER_PQ_query_param_uint64 (&transaction_id), + TALER_PQ_query_param_auto_from_type (wtid), + TALER_PQ_query_param_absolute_time (&execution_time), + TALER_PQ_query_param_amount (coin_value), + TALER_PQ_query_param_amount (transaction_value), + TALER_PQ_query_param_end + }; + PGresult *result; + + result = TALER_PQ_exec_prepared (session->conn, + "insert_aggregation_tracking", + params); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + if (0 != strcmp ("1", PQcmdTuples (result))) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; + GNUNET_break (0); // not implemented return GNUNET_SYSERR; } -- cgit v1.2.3 From c12a899f32e1ce432181fa428ebe77bd72ce4394 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 21 Jan 2016 12:09:17 +0100 Subject: finish implementation of DB tracing functions --- src/include/taler_mintdb_plugin.h | 57 ++++---- src/mint/taler-mint-httpd_db.c | 78 ++++++---- src/mintdb/plugin_mintdb_postgres.c | 277 ++++++++++++++++++++++++++++++++---- 3 files changed, 332 insertions(+), 80 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 2ffde2285..e5cf6d6f1 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -570,23 +570,24 @@ typedef void /** * Function called with the results of the lookup of the - * wire transfer identifier information. + * wire transfer identifier information. Only called if + * we are at least aware of the transaction existing. * * @param cls closure * @param wtid wire transfer identifier, NULL * if the transaction was not yet done * @param coin_contribution how much did the coin we asked about - * contribute to the total transfer value? (deposit value minus fee) + * contribute to the total transfer value? (deposit value including fee) + * @param coin_fee how much did the mint charge for the deposit fee * @param total_amount how much was the total wire transfer? * @param execution_time when was the transaction done, or - * when we expect it to be done (if @a wtid was NULL); - * #GNUNET_TIME_UNIT_FOREVER_ABS if the /deposit is unknown - * to the mint + * when we expect it to be done (if @a wtid was NULL) */ typedef void (*TALER_MINTDB_DepositWtidCallback)(void *cls, const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *coin_fee, const struct TALER_Amount *total_amount, struct GNUNET_TIME_Absolute execution_time); @@ -601,18 +602,20 @@ typedef void * @param h_contract which contract was this payment about * @param transaction_id merchant's transaction ID for the payment * @param coin_pub which public key was this payment about - * @param deposit_value amount contributed by this coin in total - * @param deposit_fee deposit fee charged by mint for this coin + * @param coin_value amount contributed by this coin in total (with fee) + * @param coin_fee applicable fee for this coin + * @param transfer_value total amount of the wire transfer */ typedef void -(*TALER_MINTDB_TransactionDataCallback)(void *cls, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_wire, - const struct GNUNET_HashCode *h_contract, - uint64_t transaction_id, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *deposit_value, - const struct TALER_Amount *deposit_fee); +(*TALER_MINTDB_WireTransferDataCallback)(void *cls, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct GNUNET_HashCode *h_wire, + const struct GNUNET_HashCode *h_contract, + uint64_t transaction_id, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *coin_value, + const struct TALER_Amount *coin_fee, + const struct TALER_Amount *transfer_value); /** @@ -1233,14 +1236,15 @@ struct TALER_MINTDB_Plugin * @param wtid the raw wire transfer identifier we used * @param cb function to call on each transaction found * @param cb_cls closure for @a cb - * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors + * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors, + * #GNUNET_NO if we found no results */ int - (*lookup_wire_transactions) (void *cls, - struct TALER_MINTDB_Session *session, - const struct TALER_WireTransferIdentifierRawP *wtid, - TALER_MINTDB_TransactionDataCallback cb, - void *cb_cls); + (*lookup_wire_transfer) (void *cls, + struct TALER_MINTDB_Session *session, + const struct TALER_WireTransferIdentifierRawP *wtid, + TALER_MINTDB_WireTransferDataCallback cb, + void *cb_cls); /** @@ -1257,7 +1261,8 @@ struct TALER_MINTDB_Plugin * @param transaction_id transaction identifier * @param cb function to call with the result * @param cb_cls closure to pass to @a cb - * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors, + * #GNUNET_NO if nothing was found */ int (*wire_lookup_deposit_wtid)(void *cls, @@ -1283,8 +1288,9 @@ struct TALER_MINTDB_Plugin * @param transaction_id merchant's transaction ID for the payment * @param execution_time when did we execute the transaction * @param coin_pub which public key was this payment about - * @param coin_value amount contributed by this coin to the total - * @param transaction_value total amount of the wire transaction + * @param coin_value amount contributed by this coin in total + * @param coin_fee deposit fee charged by mint for this coin + * @param transfer_value total amount of the wire transfer * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ int @@ -1298,7 +1304,8 @@ struct TALER_MINTDB_Plugin struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, - const struct TALER_Amount *transaction_value); + const struct TALER_Amount *coin_fee, + const struct TALER_Amount *transfer_value); }; diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index cc1642202..fb4ee1b7a 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1565,6 +1565,12 @@ struct WtidTransactionContext */ struct TALER_Amount total; + /** + * Value we find in the DB for the @e total; only valid if @e is_valid + * is #GNUNET_YES. + */ + struct TALER_Amount db_transaction_value; + /** * Public key of the merchant, only valid if @e is_valid * is #GNUNET_YES. @@ -1606,6 +1612,7 @@ struct WtidTransactionContext * @param coin_pub which public key was this payment about * @param deposit_value amount contributed by this coin in total * @param deposit_fee deposit fee charged by mint for this coin + * @param transaction_value total value of the wire transaction */ static void handle_transaction_data (void *cls, @@ -1615,7 +1622,8 @@ handle_transaction_data (void *cls, uint64_t transaction_id, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *deposit_value, - const struct TALER_Amount *deposit_fee) + const struct TALER_Amount *deposit_fee, + const struct TALER_Amount *transaction_value) { struct WtidTransactionContext *ctx = cls; struct TALER_Amount delta; @@ -1626,6 +1634,7 @@ handle_transaction_data (void *cls, { ctx->merchant_pub = *merchant_pub; ctx->h_wire = *h_wire; + ctx->db_transaction_value = *transaction_value; ctx->is_valid = GNUNET_YES; if (GNUNET_OK != TALER_amount_subtract (&ctx->total, @@ -1644,7 +1653,9 @@ handle_transaction_data (void *cls, sizeof (struct TALER_MerchantPublicKeyP))) || (0 != memcmp (&ctx->h_wire, h_wire, - sizeof (struct GNUNET_HashCode))) ) + sizeof (struct GNUNET_HashCode))) || + (0 != TALER_amount_cmp (transaction_value, + &ctx->db_transaction_value)) ) { GNUNET_break (0); ctx->is_valid = GNUNET_SYSERR; @@ -1707,11 +1718,11 @@ TMH_DB_execute_wire_deposits (struct MHD_Connection *connection, } ctx.is_valid = GNUNET_NO; ctx.deposits = json_array (); - ret = TMH_plugin->lookup_wire_transactions (TMH_plugin->cls, - session, - &wtid->raw, - &handle_transaction_data, - &ctx); + ret = TMH_plugin->lookup_wire_transfer (TMH_plugin->cls, + session, + &wtid->raw, + &handle_transaction_data, + &ctx); if (GNUNET_SYSERR == ret) { GNUNET_break (0); @@ -1730,8 +1741,15 @@ TMH_DB_execute_wire_deposits (struct MHD_Connection *connection, return TMH_RESPONSE_reply_arg_unknown (connection, "wtid"); } + if (0 != TALER_amount_cmp (&ctx.total, + &ctx.db_transaction_value)) + { + /* FIXME: this CAN actually differ, due to rounding + down. But we should still check that the values + do match after rounding 'total' down! */ + } return TMH_RESPONSE_reply_wire_deposit_details (connection, - &ctx.total, + &ctx.db_transaction_value, &ctx.merchant_pub, &ctx.h_wire, ctx.deposits); @@ -1784,7 +1802,8 @@ struct DepositWtidContext * @param wtid raw wire transfer identifier, NULL * if the transaction was not yet done * @param coin_contribution how much did the coin we asked about - * contribute to the total transfer value? (deposit value minus fee) + * contribute to the total transfer value? (deposit value including fee) + * @param coin_fee how much did the mint charge for the deposit fee * @param total_amount how much was the total wire transfer? * @param execution_time when was the transaction done, or * when we expect it to be done (if @a wtid was NULL); @@ -1795,31 +1814,40 @@ static void handle_wtid_data (void *cls, const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *coin_contribution, + const struct TALER_Amount *coin_fee, const struct TALER_Amount *total_amount, struct GNUNET_TIME_Absolute execution_time) { struct DepositWtidContext *ctx = cls; + struct TALER_Amount coin_delta; if (NULL == wtid) { - if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == - execution_time.abs_value_us) - ctx->res = TMH_RESPONSE_reply_deposit_unknown (ctx->connection); - else - ctx->res = TMH_RESPONSE_reply_deposit_pending (ctx->connection, - execution_time); + ctx->res = TMH_RESPONSE_reply_deposit_pending (ctx->connection, + execution_time); } else { - ctx->res = TMH_RESPONSE_reply_deposit_wtid (ctx->connection, - &ctx->h_contract, - &ctx->h_wire, - &ctx->coin_pub, - coin_contribution, - total_amount, - ctx->transaction_id, - wtid, - execution_time); + if (GNUNET_SYSERR == + TALER_amount_subtract (&coin_delta, + coin_contribution, + coin_fee)) + { + GNUNET_break (0); + ctx->res = TMH_RESPONSE_reply_internal_db_error (ctx->connection); + } + else + { + ctx->res = TMH_RESPONSE_reply_deposit_wtid (ctx->connection, + &ctx->h_contract, + &ctx->h_wire, + &ctx->coin_pub, + &coin_delta, + total_amount, + ctx->transaction_id, + wtid, + execution_time); + } } } @@ -1874,6 +1902,8 @@ TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection, GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } + if (GNUNET_NO == ret) + return TMH_RESPONSE_reply_deposit_unknown (connection); return ctx.res; } diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index f3760216f..38ce45eb9 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -875,6 +875,26 @@ postgres_prepare (PGconn *db_conn) " (merchant_pub=$3)" " )", 3, NULL); + /* Fetch an existing deposit request. + Used in #postgres_wire_lookup_deposit_wtid(). */ + PREPARE ("get_deposit_for_wtid", + "SELECT" + " amount_with_fee_val" + ",amount_with_fee_frac" + ",amount_with_fee_curr" + ",deposit_fee_val" + ",deposit_fee_frac" + ",deposit_fee_curr" + ",wire_deadline" + " FROM deposits" + " WHERE (" + " (coin_pub=$1) AND" + " (transaction_id=$2) AND" + " (merchant_pub=$3) AND" + " (h_contract=$4) AND" + " (h_wire=$5)" + " )", + 5, NULL); /* Used in #postgres_iterate_deposits() */ PREPARE ("deposits_iterate", @@ -972,7 +992,7 @@ postgres_prepare (PGconn *db_conn) " AND rm.oldcoin_index = rcl.oldcoin_index" " AND rcl.cnc_index=rs.noreveal_index", 1, NULL); - /* Used in #postgres_lookup_wire_transactions */ + /* Used in #postgres_lookup_wire_transfer */ PREPARE ("lookup_transactions", "SELECT" " h_contract" @@ -984,9 +1004,12 @@ postgres_prepare (PGconn *db_conn) ",coin_amount_val" ",coin_amount_frac" ",coin_amount_curr" - ",transaction_total_val" - ",transaction_total_frac" - ",transaction_total_curr" + ",coin_fee_val" + ",coin_fee_frac" + ",coin_fee_curr" + ",transfer_total_val" + ",transfer_total_frac" + ",transfer_total_curr" " FROM aggregation_tracking" " WHERE wtid_raw=$1", 1, NULL); @@ -998,9 +1021,12 @@ postgres_prepare (PGconn *db_conn) ",coin_amount_val" ",coin_amount_frac" ",coin_amount_curr" - ",transaction_total_val" - ",transaction_total_frac" - ",transaction_total_curr" + ",coin_fee_val" + ",coin_fee_frac" + ",coin_fee_curr" + ",transfer_total_val" + ",transfer_total_frac" + ",transfer_total_curr" " FROM aggregation_tracking" " WHERE" " coin_pub=$1 AND" @@ -1022,12 +1048,15 @@ postgres_prepare (PGconn *db_conn) ",coin_amount_val" ",coin_amount_frac" ",coin_amount_curr" - ",transaction_total_val" - ",transaction_total_frac" - ",transaction_total_curr" + ",coin_fee_val" + ",coin_fee_frac" + ",coin_fee_curr" + ",transfer_total_val" + ",transfer_total_frac" + ",transfer_total_curr" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", - 13, NULL); + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)", + 16, NULL); return GNUNET_OK; #undef PREPARE @@ -3455,17 +3484,83 @@ postgres_get_coin_transactions (void *cls, * @param wtid the raw wire transfer identifier we used * @param cb function to call on each transaction found * @param cb_cls closure for @a cb - * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors + * @return #GNUNET_OK on success, #GNUNET_SYSERR on database errors, + * #GNUNET_NO if we found no results */ static int -postgres_lookup_wire_transactions (void *cls, - struct TALER_MINTDB_Session *session, - const struct TALER_WireTransferIdentifierRawP *wtid, - TALER_MINTDB_TransactionDataCallback cb, - void *cb_cls) +postgres_lookup_wire_transfer (void *cls, + struct TALER_MINTDB_Session *session, + const struct TALER_WireTransferIdentifierRawP *wtid, + TALER_MINTDB_WireTransferDataCallback cb, + void *cb_cls) { - GNUNET_break (0); // not implemented! - return GNUNET_SYSERR; + PGresult *result; + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_auto_from_type (wtid), + TALER_PQ_query_param_end + }; + int nrows; + int i; + + /* check if the melt record exists and get it */ + result = TALER_PQ_exec_prepared (session->conn, + "lookup_transactions", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + nrows = PQntuples (result); + if (0 == nrows) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "lookup_wire_transfer() returned 0 matching rows\n"); + PQclear (result); + return GNUNET_NO; + } + for (i=0;iconn, + "lookup_deposit_wtid", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + nrows = PQntuples (result); + if (0 == nrows) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "lookup_wire_transfer() returned 0 matching rows\n"); + PQclear (result); + + /* Check if transaction exists in deposits, so that we just + do not have a WTID yet, if so, do call the CB with a NULL wtid + and return GNUNET_YES! */ + { + struct TALER_PQ_QueryParam params2[] = { + TALER_PQ_query_param_auto_from_type (coin_pub), + TALER_PQ_query_param_uint64 (&transaction_id), + TALER_PQ_query_param_auto_from_type (merchant_pub), + TALER_PQ_query_param_auto_from_type (h_contract), + TALER_PQ_query_param_auto_from_type (h_wire), + TALER_PQ_query_param_end + }; + + result = TALER_PQ_exec_prepared (session->conn, + "get_deposit_for_wtid", + params2); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + } + nrows = PQntuples (result); + if (0 == nrows) + { + PQclear (result); + return GNUNET_NO; + } + + /* Ok, we're aware of the transaction, but it has not yet been + executed */ + { + struct GNUNET_TIME_Absolute exec_time; + struct TALER_Amount coin_amount; + struct TALER_Amount coin_fee; + struct TALER_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_amount ("coin_amount", &coin_amount), + TALER_PQ_result_spec_amount ("deposit_fee", &coin_fee), + TALER_PQ_result_spec_absolute_time ("wire_deadline", &exec_time), + TALER_PQ_result_spec_end + }; + if (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0)) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + cb (cb_cls, + NULL, + &coin_amount, + &coin_fee, + NULL, + exec_time); + PQclear (result); + return GNUNET_YES; + } + } + if (1 != nrows) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + { + struct TALER_WireTransferIdentifierRawP wtid; + struct GNUNET_TIME_Absolute exec_time; + struct TALER_Amount coin_amount; + struct TALER_Amount coin_fee; + struct TALER_Amount transaction_amount; + struct TALER_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_auto_from_type ("wtid_raw", &wtid), + TALER_PQ_result_spec_absolute_time ("execution_time", &exec_time), + TALER_PQ_result_spec_amount ("coin_amount", &coin_amount), + TALER_PQ_result_spec_amount ("coin_fee", &coin_fee), + TALER_PQ_result_spec_amount ("transfer_total", &transaction_amount), + TALER_PQ_result_spec_end + }; + if (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0)) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + cb (cb_cls, + &wtid, + &coin_amount, + &coin_fee, + &transaction_amount, + exec_time); + } + PQclear (result); + return GNUNET_OK; } @@ -3512,8 +3727,9 @@ postgres_wire_lookup_deposit_wtid (void *cls, * @param h_contract which contract was this payment about * @param transaction_id merchant's transaction ID for the payment * @param coin_pub which public key was this payment about - * @param deposit_value amount contributed by this coin in total - * @param deposit_fee deposit fee charged by mint for this coin + * @param coin_value amount contributed by this coin in total + * @param coin_fee deposit fee charged by mint for this coin + * @param transfer_value total amount of the wire transfer * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ static int @@ -3527,7 +3743,8 @@ postgres_insert_aggregation_tracking (void *cls, struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, - const struct TALER_Amount *transaction_value) + const struct TALER_Amount *coin_fee, + const struct TALER_Amount *transfer_value) { struct TALER_PQ_QueryParam params[] = { TALER_PQ_query_param_auto_from_type (h_contract), @@ -3538,7 +3755,8 @@ postgres_insert_aggregation_tracking (void *cls, TALER_PQ_query_param_auto_from_type (wtid), TALER_PQ_query_param_absolute_time (&execution_time), TALER_PQ_query_param_amount (coin_value), - TALER_PQ_query_param_amount (transaction_value), + TALER_PQ_query_param_amount (coin_fee), + TALER_PQ_query_param_amount (transfer_value), TALER_PQ_query_param_end }; PGresult *result; @@ -3560,9 +3778,6 @@ postgres_insert_aggregation_tracking (void *cls, } PQclear (result); return GNUNET_OK; - - GNUNET_break (0); // not implemented - return GNUNET_SYSERR; } @@ -3635,7 +3850,7 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->get_transfer = &postgres_get_transfer; plugin->get_coin_transactions = &postgres_get_coin_transactions; plugin->free_coin_transaction_list = &common_free_coin_transaction_list; - plugin->lookup_wire_transactions = &postgres_lookup_wire_transactions; + plugin->lookup_wire_transfer = &postgres_lookup_wire_transfer; plugin->wire_lookup_deposit_wtid = &postgres_wire_lookup_deposit_wtid; plugin->insert_aggregation_tracking = &postgres_insert_aggregation_tracking; return plugin; -- cgit v1.2.3 From 57c1d2318f14c4b5c21609cb96f32517d02752e7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 25 Jan 2016 14:57:32 +0100 Subject: getting aggregator structure laid out for #4141 --- src/include/Makefile.am | 1 + src/include/taler_mintdb_plugin.h | 8 +- src/mint/Makefile.am | 1 + src/mint/taler-mint-aggregator.c | 164 ++++++++++++++++++++++++++++++++++++-- src/wire/Makefile.am | 13 +++ src/wire/test_sepa_wireformat.c | 53 +----------- 6 files changed, 182 insertions(+), 58 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 2f3973c4f..4d7ae3cb2 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -21,6 +21,7 @@ talerinclude_HEADERS = \ taler_mintdb_plugin.h \ taler_pq_lib.h \ taler_signatures.h \ + taler_wire_lib.h \ taler_wire_plugin.h endif diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index e5cf6d6f1..4230a761f 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -1145,10 +1145,10 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_out) (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_HashCode *session_hash, - uint16_t newcoin_index, - const struct TALER_DenominationSignature *ev_sig); + struct TALER_MINTDB_Session *session, + const struct GNUNET_HashCode *session_hash, + uint16_t newcoin_index, + const struct TALER_DenominationSignature *ev_sig); /** diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am index fda014d56..8e2eae77b 100644 --- a/src/mint/Makefile.am +++ b/src/mint/Makefile.am @@ -15,6 +15,7 @@ taler_mint_aggregator_SOURCES = \ taler_mint_aggregator_LDADD = \ $(LIBGCRYPT_LIBS) \ $(top_builddir)/src/util/libtalerutil.la \ + $(top_builddir)/src/wire/libtalerwire.la \ $(top_builddir)/src/mintdb/libtalermintdb.la \ -ljansson \ -lgnunetutil diff --git a/src/mint/taler-mint-aggregator.c b/src/mint/taler-mint-aggregator.c index a739d87e0..d3c66f025 100644 --- a/src/mint/taler-mint-aggregator.c +++ b/src/mint/taler-mint-aggregator.c @@ -23,13 +23,20 @@ #include #include #include -#include "taler_wire_plugin.h" +#include "taler_mintdb_lib.h" +#include "taler_mintdb_plugin.h" +#include "taler_wire_lib.h" /** * Which currency is used by this mint? */ static char *mint_currency_string; +/** + * Which wireformat should be supported by this aggregator? + */ +static char *mint_wireformat; + /** * Base directory of the mint (global) */ @@ -45,6 +52,16 @@ static struct GNUNET_CONFIGURATION_Handle *cfg; */ static struct TALER_MINTDB_Plugin *db_plugin; +/** + * Our wire plugin. + */ +static struct TALER_WIRE_Plugin *wire_plugin; + +/** + * Task for the main #run() function. + */ +static struct GNUNET_SCHEDULER_Task *task; + /** * Load configuration parameters for the mint @@ -56,7 +73,7 @@ static struct TALER_MINTDB_Plugin *db_plugin; static int mint_serve_process_config (const char *mint_directory) { - unsigned long long port; + char *type; cfg = TALER_config_load (mint_directory); if (NULL == cfg) @@ -84,19 +101,151 @@ mint_serve_process_config (const char *mint_directory) (unsigned int) TALER_CURRENCY_LEN); return GNUNET_SYSERR; } + if (NULL != mint_wireformat) + GNUNET_CONFIGURATION_set_value_string (cfg, + "mint", + "wireformat", + mint_wireformat); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "mint", + "wireformat", + &type)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint", + "wireformat"); + return GNUNET_SYSERR; + } if (NULL == (db_plugin = TALER_MINTDB_plugin_load (cfg))) { fprintf (stderr, "Failed to initialize DB subsystem\n"); + GNUNET_free (type); + return GNUNET_SYSERR; + } + + if (NULL == + (wire_plugin = TALER_WIRE_plugin_load (cfg, + type))) + { + fprintf (stderr, + "Failed to load wire plugin for `%s'\n", + type); + GNUNET_free (type); return GNUNET_SYSERR; } + GNUNET_free (type); return GNUNET_OK; } +/** + * Function called with details about deposits that have been made, + * with the goal of executing the corresponding wire transaction. + * + * @param cls closure + * @param id transaction ID (used as future `min_id` to avoid + * iterating over transactions more than once) + * @param amount_with_fee amount that was deposited including fee + * @param deposit_fee amount the mint gets to keep as transaction fees + * @param transaction_id unique transaction ID chosen by the merchant + * @param h_contract hash of the contract between merchant and customer + * @param wire_deadline by which the merchant adviced that he would like the + * wire transfer to be executed + * @param wire wire details for the merchant + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +static int +deposit_cb (void *cls, + uint64_t id, + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *deposit_fee, + uint64_t transaction_id, + const struct GNUNET_HashCode *h_contract, + struct GNUNET_TIME_Absolute wire_deadline, + const json_t *wire) +{ + /* FIXME: compute aggregates, etc. */ + return GNUNET_OK; +} + + +/** + * Main work function that queries the DB and executes transactions. + */ +static void +run (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + int *global_ret = cls; + struct TALER_MINTDB_Session *session; + int ret; + + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + return; + if (NULL == (session = db_plugin->get_session (db_plugin->cls, + GNUNET_NO))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to obtain database session!\n"); + *global_ret = GNUNET_SYSERR; + return; + } + if (GNUNET_OK != + db_plugin->start (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to start database transaction!\n"); + *global_ret = GNUNET_SYSERR; + return; + } + ret = db_plugin->iterate_deposits (db_plugin->cls, + session, + 0 /* FIXME: remove? */, + 128 /* FIXME: make configurable? */, + &deposit_cb, + NULL); + if (GNUNET_OK != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to execute deposit iteration!\n"); + *global_ret = GNUNET_SYSERR; + db_plugin->rollback (db_plugin->cls, + session); + return; + } + /* FIXME: finish aggregate computation */ + /* FIXME: insert pre-commit data for transaction into DB */ + /* FIXME: mark transactions selected for aggregate as finished */ + + if (GNUNET_OK != + db_plugin->commit (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to commit database transaction!\n"); + } + + /* FIXME: run 2nd transaction: + - begin + - select pre-commit data from DB + - execute wire transfer + - insert aggregation tracking information into DB + - commit! + */ + + + task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS /* FIXME: adjust! */, + &run, + global_ret); +} + + /** * The main function of the taler-mint-httpd server ("the mint"). * @@ -112,11 +261,14 @@ main (int argc, {'d', "mint-dir", "DIR", "mint directory with configuration and keys for operating the mint", 1, &GNUNET_GETOPT_set_filename, &mint_directory}, + {'f', "format", "WIREFORMAT", + "wireformat to use, overrides WIREFORMAT option in [mint] section", 1, + &GNUNET_GETOPT_set_filename, &mint_wireformat}, TALER_GETOPT_OPTION_HELP ("background process that aggregates and executes wire transfers to merchants"), GNUNET_GETOPT_OPTION_VERSION (VERSION "-" VCS_VERSION), GNUNET_GETOPT_OPTION_END }; - int ret; + int ret = GNUNET_OK; GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-aggregator", @@ -133,14 +285,16 @@ main (int argc, "Mint directory not specified\n"); return 1; } - if (GNUNET_OK != mint_serve_process_config (mint_directory)) + { return 1; + } - + GNUNET_SCHEDULER_run (&run, &ret); TALER_MINTDB_plugin_unload (db_plugin); + TALER_WIRE_plugin_unload (wire_plugin); return (GNUNET_SYSERR == ret) ? 1 : 0; } diff --git a/src/wire/Makefile.am b/src/wire/Makefile.am index 528d91014..fb6f25616 100644 --- a/src/wire/Makefile.am +++ b/src/wire/Makefile.am @@ -15,6 +15,9 @@ plugin_LTLIBRARIES = \ noinst_LTLIBRARIES = \ libtaler_plugin_wire_template.la +lib_LTLIBRARIES = \ + libtalerwire.la + libtaler_plugin_wire_test_la_SOURCES = \ plugin_wire_test.c @@ -47,6 +50,15 @@ libtaler_plugin_wire_template_la_LDFLAGS = \ -lgnunetutil $(XLIB) +libtalerwire_la_SOURCES = \ + wire.c +libtalerwire_la_LIBADD = \ + -lgnunetutil + $(XLIB) +libtalerwire_la_LDFLAGS = \ + -version-info 0:0:0 \ + -export-dynamic -no-undefined + TESTS = \ test_sepa_wireformat @@ -61,4 +73,5 @@ test_sepa_wireformat_SOURCES = \ test_sepa_wireformat_LDADD = \ -lgnunetutil \ -ljansson \ + libtalerwire.la \ $(top_builddir)/src/util/libtalerutil.la diff --git a/src/wire/test_sepa_wireformat.c b/src/wire/test_sepa_wireformat.c index 958aac260..edbe5bc45 100644 --- a/src/wire/test_sepa_wireformat.c +++ b/src/wire/test_sepa_wireformat.c @@ -22,7 +22,7 @@ #include "platform.h" #include "taler_util.h" -#include "taler_wire_plugin.h" +#include "taler_wire_lib.h" /* Valid SEPA data */ @@ -62,51 +62,6 @@ static const char * const unsupported_wire_str = \"address\": \"foobar\"}"; -/** - * Initialize the plugin. - * - * @param cfg configuration to use - * @return #GNUNET_OK on success - */ -static struct TALER_WIRE_Plugin * -wire_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *plugin_name) -{ - char *lib_name; - struct TALER_WIRE_Plugin *plugin; - - (void) GNUNET_asprintf (&lib_name, - "libtaler_plugin_wire_%s", - plugin_name); - plugin = GNUNET_PLUGIN_load (lib_name, - (void *) cfg); - if (NULL != plugin) - plugin->library_name = lib_name; - else - GNUNET_free (lib_name); - return plugin; -} - - -/** - * Shutdown the plugin. - * - * @param plugin the plugin to unload - */ -static void -wire_plugin_unload (struct TALER_WIRE_Plugin *plugin) -{ - char *lib_name; - - if (NULL == plugin) - return; - lib_name = plugin->library_name; - GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name, - plugin)); - GNUNET_free (lib_name); -} - - int main(int argc, const char *const argv[]) @@ -125,8 +80,8 @@ main(int argc, "mint", "currency", "EUR"); - plugin = wire_plugin_load (cfg, - "sepa"); + plugin = TALER_WIRE_plugin_load (cfg, + "sepa"); GNUNET_assert (NULL != plugin); (void) memset(&error, 0, sizeof(error)); GNUNET_assert (NULL != (wire = json_loads (unsupported_wire_str, 0, NULL))); @@ -141,7 +96,7 @@ main(int argc, GNUNET_assert (NULL != (wire = json_loads (valid_wire_str, 0, &error))); ret = plugin->wire_validate (wire); json_decref (wire); - wire_plugin_unload (plugin); + TALER_WIRE_plugin_unload (plugin); GNUNET_CONFIGURATION_destroy (cfg); if (GNUNET_NO == ret) return 1; -- cgit v1.2.3 From bd3700e608daf2ae52400275b1957656ccf2d6aa Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 25 Jan 2016 15:08:29 +0100 Subject: getting aggregator structure laid out for #4141 --- src/include/taler_mintdb_plugin.h | 74 ++++++++++++++++++++++++++++++++++++++- src/mint/taler-mint-aggregator.c | 21 ++++++----- 2 files changed, 86 insertions(+), 9 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 4230a761f..e91eb7d48 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -618,6 +618,19 @@ typedef void const struct TALER_Amount *transfer_value); +/** + * Callback with data about a prepared transaction. + * + * @param cls closure + * @param buf transaction data that was persisted, NULL on error + * @param buf_size number of bytes in @a buf, 0 on error + */ +typedef void +(*TALER_MINTDB_WirePreparationCallback) (void *cls, + const char *buf, + size_t buf_size); + + /** * @brief The plugin API, returned from the plugin's "init" function. * The argument given to "init" is simply a configuration handle. @@ -1308,7 +1321,66 @@ struct TALER_MINTDB_Plugin const struct TALER_Amount *transfer_value); + + /** + * Function called to insert wire transfer commit data into the DB. + * + * @param cls closure + * @param session database connection + * @param type type fo the wire transfer (i.e. "sepa") + * @param buf buffer with wire transfer preparation data + * @param buf_size number of bytes in @a buf + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + */ + int + (*wire_prepare_data_insert)(void *cls, + struct TALER_MINTDB_Session *session, + const char *type, + const char *buf, + size_t buf_size); + + + /** + * Function called to mark wire transfer commit data as finished. + * + * @param cls closure + * @param session database connection + * @param type type fo the wire transfer (i.e. "sepa") + * @param buf buffer with wire transfer preparation data + * @param buf_size number of bytes in @a buf + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + */ + int + (*wire_prepare_data_mark_finished)(void *cls, + struct TALER_MINTDB_Session *session, + const char *type, + const char *buf, + size_t buf_size); + + + /** + * Function called to iterate over unfinished wire transfer + * preparation data. Fetches at most one item. + * + * @param cls closure + * @param session database connection + * @param type type fo the wire transfer (i.e. "sepa") + * @param cb function to call for ONE unfinished item + * @param cb_cls closure for @a cb + * @return #GNUNET_OK on success, + * #GNUNET_NO if there are no entries, + * #GNUNET_SYSERR on DB errors + */ + int + (*wire_prepare_data_iterate)(void *cls, + struct TALER_MINTDB_Session *session, + const char *type, + TALER_MINTDB_WirePreparationCallback cb, + void *cb_cls); + + + }; -#endif /* _NEURO_MINT_DB_H */ +#endif /* _TALER_MINT_DB_H */ diff --git a/src/mint/taler-mint-aggregator.c b/src/mint/taler-mint-aggregator.c index d3c66f025..70a68d007 100644 --- a/src/mint/taler-mint-aggregator.c +++ b/src/mint/taler-mint-aggregator.c @@ -220,9 +220,11 @@ run (void *cls, return; } /* FIXME: finish aggregate computation */ - /* FIXME: insert pre-commit data for transaction into DB */ - /* FIXME: mark transactions selected for aggregate as finished */ + /* wire_plugin->prepare_wire_transfer () -- ASYNC! */ + /* db_plugin->wire_prepare_data_insert () -- transactional! */ + /* db_plugin->XXX () -- mark transactions selected for aggregate as finished */ + /* then finally: commit! */ if (GNUNET_OK != db_plugin->commit (db_plugin->cls, session)) @@ -231,12 +233,15 @@ run (void *cls, "Failed to commit database transaction!\n"); } - /* FIXME: run 2nd transaction: - - begin - - select pre-commit data from DB - - execute wire transfer - - insert aggregation tracking information into DB - - commit! + /* While possible, run 2nd type of transaction: + db_plugin->start() + - select pre-commit data from DB: + db_plugin->wire_prepare_data_iterate () + - execute wire transfer (successfully!) + wire_plugin->execute_wire_transfer() # ASYNC! + db_plugin->wire_prepare_data_mark_finished () + db_plugin->insert_aggregation_tracking () + db_plugin->commit() */ -- cgit v1.2.3 From 0ba855ae92c2bf38c51f830fdea3062e88fd44f3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 25 Jan 2016 15:18:31 +0100 Subject: more mintdb API design for #4141 --- src/include/taler_mintdb_plugin.h | 76 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index e91eb7d48..65c694a72 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -543,6 +543,8 @@ struct TALER_MINTDB_Session; */ typedef int (*TALER_MINTDB_DepositIterator)(void *cls, + // unsigned long long rowid, /* ? */ + // May also need/want Merchant pub!? uint64_t id, const struct TALER_Amount *amount_with_fee, const struct TALER_Amount *deposit_fee, @@ -893,6 +895,78 @@ struct TALER_MINTDB_Plugin const struct TALER_MINTDB_Deposit *deposit); + /** + * Mark a deposit as tiny, thereby declaring that it cannot be + * executed by itself and should no longer be returned by + * @e iterate_ready_deposits() + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to the database + * @param deposit_rowid identifies the deposit row to modify + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ + int + (*mark_deposit_tiny) (void *cls, + struct TALER_MINTDB_Session *session, + unsigned long long rowid); + + + /** + * Mark a deposit as done, thereby declaring that it cannot be + * executed at all anymore, and should no longer be returned by + * @e iterate_ready_deposits() or @e iterate_matching_deposits(). + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to the database + * @param deposit_rowid identifies the deposit row to modify + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ + int + (*mark_deposit_done) (void *cls, + struct TALER_MINTDB_Session *session, + unsigned long long rowid); + + + /** + * Obtain information about deposits that are ready to be executed. + * Such deposits must not be marked as "tiny" or "done", and the + * execution time must be in the past. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to the database + * @param deposit_cb function to call for ONE such deposit + * @param deposit_cb_cls closure for @a deposit_cb + * @return number of rows processed, 0 if none exist, + * #GNUNET_SYSERR on error + */ + int + (*iterate_ready_deposits) (void *cls, + struct TALER_MINTDB_Session *session, + TALER_MINTDB_DepositIterator deposit_cb, + void *deposit_cb_cls); + + + /** + * Obtain information about other pending deposits for the same + * destination. Those deposits must not already be "done". + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to the database + * @param h_wire destination of the wire transfer + * @param FIXME: do we also need merchant_pub here? + * @param deposit_cb function to call for each deposit + * @param deposit_cb_cls closure for @a deposit_cb + * @return number of rows processed, 0 if none exist, + * #GNUNET_SYSERR on error + */ + int + (*iterate_matching_deposits) (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_HashCode *h_wire, + TALER_MINTDB_DepositIterator deposit_cb, + void *deposit_cb_cls); + + /** * Obtain information about deposits. Iterates over all deposits * above a certain ID. Use a @a min_id of 0 to start at the beginning. @@ -907,6 +981,7 @@ struct TALER_MINTDB_Plugin * @param deposit_cb_cls closure for @a deposit_cb * @return number of rows processed, 0 if none exist, * #GNUNET_SYSERR on error + * @deprecated this is likely dead */ int (*iterate_deposits) (void *cls, @@ -1379,7 +1454,6 @@ struct TALER_MINTDB_Plugin void *cb_cls); - }; -- cgit v1.2.3 From 48c2edc28dc54c21ecb30b9aec31a3699c3f9bd0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 27 Jan 2016 16:42:24 +0100 Subject: working on mintdb for #4141 --- src/include/taler_mintdb_plugin.h | 54 +++---- src/mint/taler-mint-aggregator.c | 21 +-- src/mintdb/plugin_mintdb_postgres.c | 295 ++++++++++++++++++++++++++++++------ 3 files changed, 278 insertions(+), 92 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 65c694a72..11b305839 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -530,22 +530,24 @@ struct TALER_MINTDB_Session; * corresponding wire transaction. * * @param cls closure - * @param id transaction ID (used as future `min_id` to avoid - * iterating over transactions more than once) + * @param rowid unique ID for the deposit in our DB, used for marking + * it as 'tiny' or 'done' + * @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 mint gets to keep as transaction fees * @param transaction_id unique transaction ID chosen by the merchant * @param h_contract hash of the contract between merchant and customer * @param wire_deadline by which the merchant adviced that he would like the * wire transfer to be executed - * @param wire wire details for the merchant + * @param wire wire details for the merchant, NULL from iterate_matching_deposits() * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ typedef int (*TALER_MINTDB_DepositIterator)(void *cls, - // unsigned long long rowid, /* ? */ - // May also need/want Merchant pub!? - uint64_t id, + unsigned long long rowid, + 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, uint64_t transaction_id, @@ -940,10 +942,10 @@ struct TALER_MINTDB_Plugin * #GNUNET_SYSERR on error */ int - (*iterate_ready_deposits) (void *cls, - struct TALER_MINTDB_Session *session, - TALER_MINTDB_DepositIterator deposit_cb, - void *deposit_cb_cls); + (*get_ready_deposit) (void *cls, + struct TALER_MINTDB_Session *session, + TALER_MINTDB_DepositIterator deposit_cb, + void *deposit_cb_cls); /** @@ -953,9 +955,10 @@ struct TALER_MINTDB_Plugin * @param cls the @e cls of this struct with the plugin-specific state * @param session connection to the database * @param h_wire destination of the wire transfer - * @param FIXME: do we also need merchant_pub here? + * @param merchant_pub public key of the merchant * @param deposit_cb function to call for each deposit * @param deposit_cb_cls closure for @a deposit_cb + * @param limit maximum number of matching deposits to return * @return number of rows processed, 0 if none exist, * #GNUNET_SYSERR on error */ @@ -963,33 +966,10 @@ struct TALER_MINTDB_Plugin (*iterate_matching_deposits) (void *cls, struct TALER_MINTDB_Session *session, const struct GNUNET_HashCode *h_wire, + const struct TALER_MerchantPublicKeyP *merchant_pub, TALER_MINTDB_DepositIterator deposit_cb, - void *deposit_cb_cls); - - - /** - * Obtain information about deposits. Iterates over all deposits - * above a certain ID. Use a @a min_id of 0 to start at the beginning. - * This operation is executed in its own transaction in transaction - * mode "REPEATABLE READ", i.e. we should only see valid deposits. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to the database - * @param min_id deposit to start at - * @param limit maximum number of transactions to fetch - * @param deposit_cb function to call for each deposit - * @param deposit_cb_cls closure for @a deposit_cb - * @return number of rows processed, 0 if none exist, - * #GNUNET_SYSERR on error - * @deprecated this is likely dead - */ - int - (*iterate_deposits) (void *cls, - struct TALER_MINTDB_Session *session, - uint64_t min_id, - uint32_t limit, - TALER_MINTDB_DepositIterator deposit_cb, - void *deposit_cb_cls); + void *deposit_cb_cls, + uint32_t limit); /** diff --git a/src/mint/taler-mint-aggregator.c b/src/mint/taler-mint-aggregator.c index 70a68d007..ee0f6ab22 100644 --- a/src/mint/taler-mint-aggregator.c +++ b/src/mint/taler-mint-aggregator.c @@ -148,8 +148,9 @@ mint_serve_process_config (const char *mint_directory) * with the goal of executing the corresponding wire transaction. * * @param cls closure - * @param id transaction ID (used as future `min_id` to avoid - * iterating over transactions more than once) + * @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 mint gets to keep as transaction fees * @param transaction_id unique transaction ID chosen by the merchant @@ -161,7 +162,9 @@ mint_serve_process_config (const char *mint_directory) */ static int deposit_cb (void *cls, - uint64_t id, + unsigned long long 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, uint64_t transaction_id, @@ -204,12 +207,12 @@ run (void *cls, *global_ret = GNUNET_SYSERR; return; } - ret = db_plugin->iterate_deposits (db_plugin->cls, - session, - 0 /* FIXME: remove? */, - 128 /* FIXME: make configurable? */, - &deposit_cb, - NULL); + ret = db_plugin->get_ready_deposit (db_plugin->cls, + session, + &deposit_cb, + NULL); + // FIXME: handle 0 == ret... + if (GNUNET_OK != ret) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index e9a9466b2..5ebf8dc7b 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -425,7 +425,7 @@ postgres_create_tables (void *cls, /* This table contains the wire transfers the mint is supposed to execute to transmit funds to the merchants (and manage refunds). */ SQLEXEC("CREATE TABLE IF NOT EXISTS deposits " - "(serial_id BIGSERIAL" + "(serial_id BIGSERIAL PRIMARY KEY" ",coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)" ",denom_pub BYTEA NOT NULL REFERENCES denominations (pub)" ",denom_sig BYTEA NOT NULL" @@ -444,6 +444,8 @@ postgres_create_tables (void *cls, ",h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)" ",coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)" ",wire TEXT NOT NULL" + ",tiny BOOLEAN NOT NULL DEFAULT false" + ",done BOOLEAN NOT NULL DEFAULT false" ")"); /* Index for get_deposit statement on coin_pub, transaction_id and merchant_pub */ SQLEXEC_INDEX("CREATE INDEX deposits_coin_pub_index " @@ -899,8 +901,8 @@ postgres_prepare (PGconn *db_conn) " )", 5, NULL); - /* Used in #postgres_iterate_deposits() */ - PREPARE ("deposits_iterate", + /* Used in #postgres_get_ready_deposit() */ + PREPARE ("deposits_get_ready", "SELECT" " serial_id" ",amount_with_fee_val" @@ -913,11 +915,50 @@ postgres_prepare (PGconn *db_conn) ",transaction_id" ",h_contract" ",wire" + ",merchant_pub" + ",coin_pub" " FROM deposits" - " WHERE serial_id>=$1" - " ORDER BY serial_id ASC" - " LIMIT $2;", - 2, NULL); + " WHERE" + " tiny=false AND" + " done=false" + " ORDER BY execution_time ASC" + " LIMIT 1;", + 0, NULL); + /* Used in #postgres_iterate_matching_deposits() */ + PREPARE ("deposits_iterate_matching", + "SELECT" + " serial_id" + ",amount_with_fee_val" + ",amount_with_fee_frac" + ",amount_with_fee_curr" + ",deposit_fee_val" + ",deposit_fee_frac" + ",deposit_fee_curr" + ",wire_deadline" + ",transaction_id" + ",h_contract" + ",coin_pub" + " FROM deposits" + " WHERE" + " merchant_pub=$1 AND" + " h_wire=$2 AND" + " done=false" + " ORDER BY execution_time ASC" + " LIMIT $3", + 3, NULL); + /* Used in #postgres_mark_deposit_tiny() */ + PREPARE ("mark_deposit_tiny", + "UPDATE deposits" + " SET tiny=true" + " WHERE serial_id=$1", + 1, NULL); + /* Used in #postgres_mark_deposit_done() */ + PREPARE ("mark_deposit_done", + "UPDATE deposits" + " SET done=true" + " WHERE serial_id=$1", + 1, NULL); + /* Used in #postgres_get_coin_transactions() to obtain information about how a coin has been spend with /deposit requests. */ PREPARE ("get_deposit_with_coin_pub", @@ -2039,82 +2080,239 @@ postgres_have_deposit (void *cls, /** - * Obtain information about deposits. Iterates over all deposits - * above a certain ID. Use a @a min_id of 0 to start at the beginning. - * This operation is executed in its own transaction in transaction - * mode "REPEATABLE READ", i.e. we should only see valid deposits. + * Mark a deposit as tiny, thereby declaring that it cannot be + * executed by itself and should no longer be returned by + * @e iterate_ready_deposits() * * @param cls the @e cls of this struct with the plugin-specific state * @param session connection to the database - * @param min_id deposit to start at - * @param limit maximum number of transactions to fetch - * @param deposit_cb function to call for each deposit + * @param deposit_rowid identifies the deposit row to modify + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +static int +postgres_mark_deposit_tiny (void *cls, + struct TALER_MINTDB_Session *session, + unsigned long long rowid) +{ + uint64_t serial_id = rowid; + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_uint64 (&serial_id), + TALER_PQ_query_param_end + }; + PGresult *result; + + result = TALER_PQ_exec_prepared (session->conn, + "mark_deposit_tiny", + params); + if (PGRES_COMMAND_OK != + PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; +} + + +/** + * Mark a deposit as done, thereby declaring that it cannot be + * executed at all anymore, and should no longer be returned by + * @e iterate_ready_deposits() or @e iterate_matching_deposits(). + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to the database + * @param deposit_rowid identifies the deposit row to modify + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +static int +postgres_mark_deposit_done (void *cls, + struct TALER_MINTDB_Session *session, + unsigned long long rowid) +{ + uint64_t serial_id = rowid; + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_uint64 (&serial_id), + TALER_PQ_query_param_end + }; + PGresult *result; + + result = TALER_PQ_exec_prepared (session->conn, + "mark_deposit_done", + params); + if (PGRES_COMMAND_OK != + PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; +} + + +/** + * Obtain information about deposits that are ready to be executed. + * Such deposits must not be marked as "tiny" or "done", and the + * execution time must be in the past. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to the database + * @param deposit_cb function to call for ONE such deposit * @param deposit_cb_cls closure for @a deposit_cb * @return number of rows processed, 0 if none exist, * #GNUNET_SYSERR on error */ static int -postgres_iterate_deposits (void *cls, - struct TALER_MINTDB_Session *session, - uint64_t min_id, - uint32_t limit, - TALER_MINTDB_DepositIterator deposit_cb, - void *deposit_cb_cls) +postgres_get_ready_deposit (void *cls, + struct TALER_MINTDB_Session *session, + TALER_MINTDB_DepositIterator deposit_cb, + void *deposit_cb_cls) { struct TALER_PQ_QueryParam params[] = { - TALER_PQ_query_param_uint64 (&min_id), - TALER_PQ_query_param_uint32 (&limit), TALER_PQ_query_param_end }; PGresult *result; - unsigned int i; unsigned int n; + int ret; - if (GNUNET_OK != - postgres_start (cls, session)) - return GNUNET_SYSERR; - result = PQexec (session->conn, - "SET TRANSACTION REPEATABLE READ"); - if (PGRES_COMMAND_OK != + result = TALER_PQ_exec_prepared (session->conn, + "deposits_get_ready", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) { - TALER_LOG_ERROR ("Failed to set transaction to REPEATABL EREAD: %s\n", - PQresultErrorMessage (result)); - GNUNET_break (0); + BREAK_DB_ERR (result); PQclear (result); return GNUNET_SYSERR; } + if (0 == (n = PQntuples (result))) + { + PQclear (result); + return 0; + } + GNUNET_break (1 == n); + { + struct TALER_Amount amount_with_fee; + struct TALER_Amount deposit_fee; + struct GNUNET_TIME_Absolute wire_deadline; + struct GNUNET_HashCode h_contract; + struct TALER_MerchantPublicKeyP merchant_pub; + struct TALER_CoinSpendPublicKeyP coin_pub; + uint64_t transaction_id; + uint64_t serial_id; + json_t *wire; + struct TALER_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_uint64 ("serial_id", + &serial_id), + TALER_PQ_result_spec_uint64 ("transaction_id", + &transaction_id), + TALER_PQ_result_spec_amount ("amount_with_fee", + &amount_with_fee), + TALER_PQ_result_spec_amount ("deposit_fee", + &deposit_fee), + TALER_PQ_result_spec_absolute_time ("wire_deadline", + &wire_deadline), + TALER_PQ_result_spec_auto_from_type ("h_contract", + &h_contract), + TALER_PQ_result_spec_auto_from_type ("merchant_pub", + &merchant_pub), + TALER_PQ_result_spec_auto_from_type ("coin_pub", + &coin_pub), + TALER_PQ_result_spec_json ("wire", + &wire), + TALER_PQ_result_spec_end + }; + if (GNUNET_OK != + TALER_PQ_extract_result (result, rs, 0)) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + ret = deposit_cb (deposit_cb_cls, + serial_id, + &merchant_pub, + &coin_pub, + &amount_with_fee, + &deposit_fee, + transaction_id, + &h_contract, + wire_deadline, + wire); + TALER_PQ_cleanup_result (rs); + PQclear (result); + } + return (GNUNET_OK == ret) ? 1 : 0; +} + + +/** + * Obtain information about other pending deposits for the same + * destination. Those deposits must not already be "done". + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param session connection to the database + * @param h_wire destination of the wire transfer + * @param merchant_pub public key of the merchant + * @param deposit_cb function to call for each deposit + * @param deposit_cb_cls closure for @a deposit_cb + * @param limit maximum number of matching deposits to return + * @return number of rows processed, 0 if none exist, + * #GNUNET_SYSERR on error + */ +static int +postgres_iterate_matching_deposits (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_HashCode *h_wire, + const struct TALER_MerchantPublicKeyP *merchant_pub, + TALER_MINTDB_DepositIterator deposit_cb, + void *deposit_cb_cls, + uint32_t limit) +{ + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_auto_from_type (merchant_pub), + TALER_PQ_query_param_auto_from_type (h_wire), + TALER_PQ_query_param_uint32 (&limit), + TALER_PQ_query_param_end + }; + PGresult *result; + unsigned int i; + unsigned int n; result = TALER_PQ_exec_prepared (session->conn, - "deposits_iterate", + "deposits_iterate_matching", params); if (PGRES_TUPLES_OK != PQresultStatus (result)) { BREAK_DB_ERR (result); PQclear (result); - postgres_rollback (cls, session); return GNUNET_SYSERR; } if (0 == (n = PQntuples (result))) { PQclear (result); - postgres_rollback (cls, session); return 0; } + if (n > limit) + n = limit; for (i=0;iget_reserve_history = &postgres_get_reserve_history; plugin->free_reserve_history = &common_free_reserve_history; plugin->have_deposit = &postgres_have_deposit; - plugin->iterate_deposits = &postgres_iterate_deposits; + plugin->mark_deposit_tiny = &postgres_mark_deposit_tiny; + plugin->mark_deposit_done = &postgres_mark_deposit_done; + plugin->get_ready_deposit = &postgres_get_ready_deposit; + plugin->iterate_matching_deposits = &postgres_iterate_matching_deposits; plugin->insert_deposit = &postgres_insert_deposit; plugin->get_refresh_session = &postgres_get_refresh_session; plugin->create_refresh_session = &postgres_create_refresh_session; -- cgit v1.2.3 From 9a45742fe4b819c22b0b0d8832ff4a0a07096a90 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 27 Jan 2016 16:46:51 +0100 Subject: adding stubs for wire prepare data functions --- src/include/taler_mintdb_plugin.h | 1 - src/mintdb/plugin_mintdb_postgres.c | 72 +++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 11b305839..ba09ea42e 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -1376,7 +1376,6 @@ struct TALER_MINTDB_Plugin const struct TALER_Amount *transfer_value); - /** * Function called to insert wire transfer commit data into the DB. * diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index 5ebf8dc7b..1e48a2ecf 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -3987,6 +3987,75 @@ postgres_insert_aggregation_tracking (void *cls, } +/** + * Function called to insert wire transfer commit data into the DB. + * + * @param cls closure + * @param session database connection + * @param type type fo the wire transfer (i.e. "sepa") + * @param buf buffer with wire transfer preparation data + * @param buf_size number of bytes in @a buf + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + */ +static int +postgres_wire_prepare_data_insert (void *cls, + struct TALER_MINTDB_Session *session, + const char *type, + const char *buf, + size_t buf_size) +{ + GNUNET_break (0); // not implemented + return GNUNET_SYSERR; +} + + +/** + * Function called to mark wire transfer commit data as finished. + * + * @param cls closure + * @param session database connection + * @param type type fo the wire transfer (i.e. "sepa") + * @param buf buffer with wire transfer preparation data + * @param buf_size number of bytes in @a buf + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + */ +static int +postgres_wire_prepare_data_mark_finished (void *cls, + struct TALER_MINTDB_Session *session, + const char *type, + const char *buf, + size_t buf_size) +{ + GNUNET_break (0); // not implemented + return GNUNET_SYSERR; +} + + +/** + * Function called to iterate over unfinished wire transfer + * preparation data. Fetches at most one item. + * + * @param cls closure + * @param session database connection + * @param type type fo the wire transfer (i.e. "sepa") + * @param cb function to call for ONE unfinished item + * @param cb_cls closure for @a cb + * @return #GNUNET_OK on success, + * #GNUNET_NO if there are no entries, + * #GNUNET_SYSERR on DB errors + */ +static int +postgres_wire_prepare_data_iterate (void *cls, + struct TALER_MINTDB_Session *session, + const char *type, + TALER_MINTDB_WirePreparationCallback cb, + void *cb_cls) +{ + GNUNET_break (0); // not implemented + return GNUNET_SYSERR; +} + + /** * Initialize Postgres database subsystem. * @@ -4064,6 +4133,9 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->lookup_wire_transfer = &postgres_lookup_wire_transfer; plugin->wire_lookup_deposit_wtid = &postgres_wire_lookup_deposit_wtid; plugin->insert_aggregation_tracking = &postgres_insert_aggregation_tracking; + plugin->wire_prepare_data_insert = &postgres_wire_prepare_data_insert; + plugin->wire_prepare_data_mark_finished = &postgres_wire_prepare_data_mark_finished; + plugin->wire_prepare_data_iterate = &postgres_wire_prepare_data_iterate; return plugin; } -- cgit v1.2.3 From b7215299d8fee1b57c1aa9f5bbb8f8202cfd0369 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 27 Jan 2016 17:09:08 +0100 Subject: adding SQL for prewire data storage --- src/include/taler_mintdb_plugin.h | 2 ++ src/mintdb/plugin_mintdb_postgres.c | 72 +++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index ba09ea42e..1d40f2935 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -626,11 +626,13 @@ typedef void * Callback with data about a prepared transaction. * * @param cls closure + * @param rowid row identifier used to mark prepared transaction as done * @param buf transaction data that was persisted, NULL on error * @param buf_size number of bytes in @a buf, 0 on error */ typedef void (*TALER_MINTDB_WirePreparationCallback) (void *cls, + unsigned long long rowid, const char *buf, size_t buf_size); diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index 1e48a2ecf..0f3779694 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -477,6 +477,18 @@ postgres_create_tables (void *cls, SQLEXEC_INDEX("CREATE INDEX aggregation_tracking_deposit_index " "ON aggregation_tracking(coin_pub,h_contract,h_wire,transaction_id,merchant_pub)"); + /* This table contains the pre-commit data for + wire transfers the mint is about to execute. */ + SQLEXEC("CREATE TABLE IF NOT EXISTS prewire " + "(serial_id BIGSERIAL PRIMARY KEY" + ",type TEXT NOT NULL" + ",finished BOOLEAN NOT NULL DEFAULT false" + ",buf BYTEA NOT NULL" + ")"); + /* Index for prepare_data_iterate statement */ + SQLEXEC_INDEX("CREATE INDEX prepare_iteration_index " + "ON prewire(type,finished)"); + #undef SQLEXEC #undef SQLEXEC_INDEX @@ -588,6 +600,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1, $2, $3, $4, $5);", 5, NULL); + /* Used in #postgres_reserves_update() when the reserve is updated */ PREPARE ("reserve_update", "UPDATE reserves" @@ -597,6 +610,7 @@ postgres_prepare (PGconn *db_conn) ",current_balance_frac=$3 " "WHERE current_balance_curr=$4 AND reserve_pub=$5", 5, NULL); + /* Used in #postgres_reserves_in_insert() to store transaction details */ PREPARE ("reserves_in_add_transaction", "INSERT INTO reserves_in " @@ -609,6 +623,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1, $2, $3, $4, $5, $6);", 6, NULL); + /* Used in #postgres_get_reserve_history() to obtain inbound transactions for a reserve */ PREPARE ("reserves_in_get_transactions", @@ -621,6 +636,7 @@ postgres_prepare (PGconn *db_conn) " FROM reserves_in" " WHERE reserve_pub=$1", 1, NULL); + /* Used in #postgres_insert_withdraw_info() to store the signature of a blinded coin with the blinded coin's details before returning it during /reserve/withdraw. We store @@ -645,6 +661,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);", 12, NULL); + /* Used in #postgres_get_withdraw_info() to locate the response for a /reserve/withdraw request using the hash of the blinded message. Used to @@ -665,6 +682,7 @@ postgres_prepare (PGconn *db_conn) " FROM reserves_out" " WHERE h_blind_ev=$1", 1, NULL); + /* Used during #postgres_get_reserve_history() to obtain all of the /reserve/withdraw operations that have been performed on a given reserve. (i.e. to @@ -685,6 +703,7 @@ postgres_prepare (PGconn *db_conn) " FROM reserves_out" " WHERE reserve_pub=$1;", 1, NULL); + /* Used in #postgres_get_refresh_session() to fetch high-level information about a refresh session */ PREPARE ("get_refresh_session", @@ -695,6 +714,7 @@ postgres_prepare (PGconn *db_conn) " FROM refresh_sessions " " WHERE session_hash=$1 ", 1, NULL); + /* Used in #postgres_create_refresh_session() to store high-level information about a refresh session */ PREPARE ("insert_refresh_session", @@ -706,6 +726,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1, $2, $3, $4);", 4, NULL); + /* Used in #postgres_get_known_coin() to fetch the denomination public key and signature for a coin known to the mint. */ @@ -716,6 +737,7 @@ postgres_prepare (PGconn *db_conn) " FROM known_coins" " WHERE coin_pub=$1", 1, NULL); + /* Used in #postgres_insert_known_coin() to store the denomination public key and signature for a coin known to the mint. */ @@ -727,6 +749,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1,$2,$3);", 3, NULL); + /* Store information about the desired denominations for a refresh operation, used in #postgres_insert_refresh_order() */ PREPARE ("insert_refresh_order", @@ -737,6 +760,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1, $2, $3);", 3, NULL); + /* Obtain information about the desired denominations for a refresh operation, used in #postgres_get_refresh_order() */ PREPARE ("get_refresh_order", @@ -762,6 +786,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);", 10, NULL); + /* Used in #postgres_get_refresh_melt to obtain information about melted coins */ PREPARE ("get_refresh_melt", @@ -777,6 +802,7 @@ postgres_prepare (PGconn *db_conn) " FROM refresh_melts" " WHERE session_hash=$1 AND oldcoin_index=$2", 2, NULL); + /* Query the 'refresh_melts' by coin public key */ PREPARE ("get_refresh_melt_by_coin", "SELECT" @@ -792,6 +818,7 @@ postgres_prepare (PGconn *db_conn) " FROM refresh_melts" " WHERE coin_pub=$1", 1, NULL); + /* Used in #postgres_insert_refresh_commit_links() to store commitments */ PREPARE ("insert_refresh_commit_link", @@ -804,6 +831,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1, $2, $3, $4, $5);", 5, NULL); + /* Used in #postgres_get_refresh_commit_links() to retrieve original commitments during /refresh/reveal */ PREPARE ("get_refresh_commit_link", @@ -813,6 +841,7 @@ postgres_prepare (PGconn *db_conn) " FROM refresh_commit_link" " WHERE session_hash=$1 AND cnc_index=$2 AND oldcoin_index=$3", 3, NULL); + /* Used in #postgres_insert_refresh_commit_coins() to store coin commitments. */ PREPARE ("insert_refresh_commit_coin", @@ -825,6 +854,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1, $2, $3, $4, $5);", 5, NULL); + /* Used in #postgres_get_refresh_commit_coins() to retrieve the original coin envelopes, to either be verified or signed. */ @@ -835,6 +865,7 @@ postgres_prepare (PGconn *db_conn) " FROM refresh_commit_coin" " WHERE session_hash=$1 AND cnc_index=$2 AND newcoin_index=$3", 3, NULL); + /* Store information about a /deposit the mint is to execute. Used in #postgres_insert_deposit(). */ PREPARE ("insert_deposit", @@ -861,6 +892,7 @@ postgres_prepare (PGconn *db_conn) "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10," " $11, $12, $13, $14, $15, $16, $17, $18);", 18, NULL); + /* Fetch an existing deposit request, used to ensure idempotency during /deposit processing. Used in #postgres_have_deposit(). */ PREPARE ("get_deposit", @@ -880,6 +912,7 @@ postgres_prepare (PGconn *db_conn) " (merchant_pub=$3)" " )", 3, NULL); + /* Fetch an existing deposit request. Used in #postgres_wire_lookup_deposit_wtid(). */ PREPARE ("get_deposit_for_wtid", @@ -924,6 +957,7 @@ postgres_prepare (PGconn *db_conn) " ORDER BY execution_time ASC" " LIMIT 1;", 0, NULL); + /* Used in #postgres_iterate_matching_deposits() */ PREPARE ("deposits_iterate_matching", "SELECT" @@ -946,12 +980,14 @@ postgres_prepare (PGconn *db_conn) " ORDER BY execution_time ASC" " LIMIT $3", 3, NULL); + /* Used in #postgres_mark_deposit_tiny() */ PREPARE ("mark_deposit_tiny", "UPDATE deposits" " SET tiny=true" " WHERE serial_id=$1", 1, NULL); + /* Used in #postgres_mark_deposit_done() */ PREPARE ("mark_deposit_done", "UPDATE deposits" @@ -993,6 +1029,7 @@ postgres_prepare (PGconn *db_conn) ") VALUES " "($1, $2, $3)", 3, NULL); + /* Used in #postgres_get_link_data_list(). We use the session_hash to obtain the "noreveal_index" for that session, and then select the encrypted link vectors (link_vector_enc) and the @@ -1018,6 +1055,7 @@ postgres_prepare (PGconn *db_conn) " AND ro.newcoin_index=rc.newcoin_index" " AND rcc.cnc_index=rs.noreveal_index", 1, NULL); + /* Used in #postgres_get_transfer(). Given the public key of a melted coin, we obtain the corresponding encrypted link secret and the transfer public key. This is done by first finding @@ -1036,6 +1074,7 @@ postgres_prepare (PGconn *db_conn) " AND rm.oldcoin_index = rcl.oldcoin_index" " AND rcl.cnc_index=rs.noreveal_index", 1, NULL); + /* Used in #postgres_lookup_wire_transfer */ PREPARE ("lookup_transactions", "SELECT" @@ -1057,6 +1096,7 @@ postgres_prepare (PGconn *db_conn) " FROM aggregation_tracking" " WHERE wtid_raw=$1", 1, NULL); + /* Used in #postgres_wire_lookup_deposit_wtid */ PREPARE ("lookup_deposit_wtid", "SELECT" @@ -1079,6 +1119,7 @@ postgres_prepare (PGconn *db_conn) " transaction_id=$4 AND" " merchant_pub=$5", 5, NULL); + /* Used in #postgres_insert_aggregation_tracking */ PREPARE ("insert_aggregation_tracking", "INSERT INTO aggregation_tracking " @@ -1102,6 +1143,37 @@ postgres_prepare (PGconn *db_conn) "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)", 16, NULL); + + /* Used in #postgres_wire_prepare_data_insert() to store + wire transfer information before actually committing it with the bank */ + PREPARE ("wire_prepare_data_insert", + "INSERT INTO prewire " + "(type" + ",buf" + ") VALUES " + "($1, $2)", + 2, NULL); + + /* Used in #postgres_wire_prepare_data_mark_finished() */ + PREPARE ("wire_prepare_data_mark_done", + "UPDATE prewire" + " SET finished=true" + " WHERE serial_id=$1", + 1, NULL); + + /* Used in #postgres_wire_prepare_data_iterate() */ + PREPARE ("wire_prepare_data_iterate", + "SELECT" + " serial_id" + ",buf" + " FROM prewire" + " WHERE" + " type=$1 AND" + " finished=false" + " ORDER BY serial_id ASC" + " LIMIT 1", + 1, NULL); + return GNUNET_OK; #undef PREPARE } -- cgit v1.2.3 From 649879b0b6413166e4e24c7bd52993576b72d266 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 27 Jan 2016 18:28:52 +0100 Subject: implementing prepare data postgres functions for #4141 --- src/include/taler_mintdb_plugin.h | 22 +++---- src/include/taler_pq_lib.h | 12 ++-- src/mintdb/plugin_mintdb_postgres.c | 128 +++++++++++++++++++++++++++++------- 3 files changed, 121 insertions(+), 41 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 1d40f2935..7c48114b8 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -1383,7 +1383,7 @@ struct TALER_MINTDB_Plugin * * @param cls closure * @param session database connection - * @param type type fo the wire transfer (i.e. "sepa") + * @param type type of the wire transfer (i.e. "sepa") * @param buf buffer with wire transfer preparation data * @param buf_size number of bytes in @a buf * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors @@ -1401,21 +1401,17 @@ struct TALER_MINTDB_Plugin * * @param cls closure * @param session database connection - * @param type type fo the wire transfer (i.e. "sepa") - * @param buf buffer with wire transfer preparation data - * @param buf_size number of bytes in @a buf + * @param rowid which entry to mark as finished * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ int (*wire_prepare_data_mark_finished)(void *cls, struct TALER_MINTDB_Session *session, - const char *type, - const char *buf, - size_t buf_size); + unsigned long long rowid); /** - * Function called to iterate over unfinished wire transfer + * Function called to get an unfinished wire transfer * preparation data. Fetches at most one item. * * @param cls closure @@ -1428,11 +1424,11 @@ struct TALER_MINTDB_Plugin * #GNUNET_SYSERR on DB errors */ int - (*wire_prepare_data_iterate)(void *cls, - struct TALER_MINTDB_Session *session, - const char *type, - TALER_MINTDB_WirePreparationCallback cb, - void *cb_cls); + (*wire_prepare_data_get)(void *cls, + struct TALER_MINTDB_Session *session, + const char *type, + TALER_MINTDB_WirePreparationCallback cb, + void *cb_cls); }; diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index e0ca429e1..c9a9ebdc5 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -156,7 +156,7 @@ struct TALER_PQ_QueryParam * @param x pointer to the query parameter to pass */ struct TALER_PQ_QueryParam -TALER_PQ_query_param_amount_nbo(const struct TALER_AmountNBO *x); +TALER_PQ_query_param_amount_nbo (const struct TALER_AmountNBO *x); /** @@ -168,7 +168,7 @@ TALER_PQ_query_param_amount_nbo(const struct TALER_AmountNBO *x); * @param x pointer to the query parameter to pass */ struct TALER_PQ_QueryParam -TALER_PQ_query_param_amount(const struct TALER_Amount *x); +TALER_PQ_query_param_amount (const struct TALER_Amount *x); /** @@ -178,7 +178,7 @@ TALER_PQ_query_param_amount(const struct TALER_Amount *x); * @param x the query parameter to pass. */ struct TALER_PQ_QueryParam -TALER_PQ_query_param_rsa_public_key(const struct GNUNET_CRYPTO_rsa_PublicKey *x); +TALER_PQ_query_param_rsa_public_key (const struct GNUNET_CRYPTO_rsa_PublicKey *x); /** @@ -188,7 +188,7 @@ TALER_PQ_query_param_rsa_public_key(const struct GNUNET_CRYPTO_rsa_PublicKey *x) * @param x the query parameter to pass */ struct TALER_PQ_QueryParam -TALER_PQ_query_param_rsa_signature(const struct GNUNET_CRYPTO_rsa_Signature *x); +TALER_PQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_rsa_Signature *x); /** @@ -198,7 +198,7 @@ TALER_PQ_query_param_rsa_signature(const struct GNUNET_CRYPTO_rsa_Signature *x); * @param x pointer to the query parameter to pass */ struct TALER_PQ_QueryParam -TALER_PQ_query_param_absolute_time(const struct GNUNET_TIME_Absolute *x); +TALER_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x); /** @@ -208,7 +208,7 @@ TALER_PQ_query_param_absolute_time(const struct GNUNET_TIME_Absolute *x); * @param x pointer to the query parameter to pass */ struct TALER_PQ_QueryParam -TALER_PQ_query_param_absolute_time_nbo(const struct GNUNET_TIME_AbsoluteNBO *x); +TALER_PQ_query_param_absolute_time_nbo (const struct GNUNET_TIME_AbsoluteNBO *x); /** diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index 0f3779694..ee63b006d 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -1161,8 +1161,8 @@ postgres_prepare (PGconn *db_conn) " WHERE serial_id=$1", 1, NULL); - /* Used in #postgres_wire_prepare_data_iterate() */ - PREPARE ("wire_prepare_data_iterate", + /* Used in #postgres_wire_prepare_data_get() */ + PREPARE ("wire_prepare_data_get", "SELECT" " serial_id" ",buf" @@ -4064,7 +4064,7 @@ postgres_insert_aggregation_tracking (void *cls, * * @param cls closure * @param session database connection - * @param type type fo the wire transfer (i.e. "sepa") + * @param type type of the wire transfer (i.e. "sepa") * @param buf buffer with wire transfer preparation data * @param buf_size number of bytes in @a buf * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors @@ -4076,8 +4076,24 @@ postgres_wire_prepare_data_insert (void *cls, const char *buf, size_t buf_size) { - GNUNET_break (0); // not implemented - return GNUNET_SYSERR; + PGresult *result; + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_fixed_size (type, strlen (type) + 1), + TALER_PQ_query_param_fixed_size (buf, buf_size), + TALER_PQ_query_param_end + }; + + result = TALER_PQ_exec_prepared (session->conn, + "wire_prepare_data_insert", + params); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; } @@ -4086,25 +4102,38 @@ postgres_wire_prepare_data_insert (void *cls, * * @param cls closure * @param session database connection - * @param type type fo the wire transfer (i.e. "sepa") - * @param buf buffer with wire transfer preparation data - * @param buf_size number of bytes in @a buf + * @param rowid which entry to mark as finished * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ static int postgres_wire_prepare_data_mark_finished (void *cls, struct TALER_MINTDB_Session *session, - const char *type, - const char *buf, - size_t buf_size) + unsigned long long rowid) { - GNUNET_break (0); // not implemented - return GNUNET_SYSERR; + uint64_t serial_id = rowid; + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_uint64 (&serial_id), + TALER_PQ_query_param_end + }; + PGresult *result; + + result = TALER_PQ_exec_prepared (session->conn, + "wire_prepare_data_mark_done", + params); + if (PGRES_COMMAND_OK != + PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; } /** - * Function called to iterate over unfinished wire transfer + * Function called to get an unfinished wire transfer * preparation data. Fetches at most one item. * * @param cls closure @@ -4117,14 +4146,69 @@ postgres_wire_prepare_data_mark_finished (void *cls, * #GNUNET_SYSERR on DB errors */ static int -postgres_wire_prepare_data_iterate (void *cls, - struct TALER_MINTDB_Session *session, - const char *type, - TALER_MINTDB_WirePreparationCallback cb, - void *cb_cls) +postgres_wire_prepare_data_get (void *cls, + struct TALER_MINTDB_Session *session, + const char *type, + TALER_MINTDB_WirePreparationCallback cb, + void *cb_cls) { - GNUNET_break (0); // not implemented - return GNUNET_SYSERR; + PGresult *result; + struct TALER_PQ_QueryParam params[] = { + TALER_PQ_query_param_fixed_size (type, strlen (type) + 1), + TALER_PQ_query_param_end + }; + + result = TALER_PQ_exec_prepared (session->conn, + "wire_prepare_data_get", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + QUERY_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + if (0 == PQntuples (result)) + { + PQclear (result); + return GNUNET_NO; + } + if (1 != PQntuples (result)) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + + { + uint64_t serial_id; + void *buf = NULL; + size_t buf_size; + struct TALER_PQ_ResultSpec rs[] = { + TALER_PQ_result_spec_uint64 ("serial_id", + &serial_id), + TALER_PQ_result_spec_variable_size ("buf", + &buf, + &buf_size), + TALER_PQ_result_spec_end + }; + + if (GNUNET_OK != + TALER_PQ_extract_result (result, + rs, + 0)) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + cb (cb_cls, + serial_id, + buf, + buf_size); + TALER_PQ_cleanup_result (rs); + } + PQclear (result); + return GNUNET_OK; } @@ -4207,7 +4291,7 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->insert_aggregation_tracking = &postgres_insert_aggregation_tracking; plugin->wire_prepare_data_insert = &postgres_wire_prepare_data_insert; plugin->wire_prepare_data_mark_finished = &postgres_wire_prepare_data_mark_finished; - plugin->wire_prepare_data_iterate = &postgres_wire_prepare_data_iterate; + plugin->wire_prepare_data_get = &postgres_wire_prepare_data_get; return plugin; } -- cgit v1.2.3 From 46d9cc367bdc9bf8cda7ae12e78ea0a2e0853d36 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 28 Jan 2016 03:58:21 +0100 Subject: finishing core logic for #4141, but untested --- src/include/taler_mint_service.h | 5 +- src/include/taler_mintdb_plugin.h | 6 +- src/include/taler_signatures.h | 14 - src/mint-lib/mint_api_deposit_wtid.c | 9 +- src/mint/taler-mint-aggregator.c | 661 ++++++++++++++++++++++++++++++++-- src/mint/taler-mint-httpd_db.c | 3 - src/mint/taler-mint-httpd_responses.c | 5 - src/mint/taler-mint-httpd_responses.h | 2 +- src/mintdb/plugin_mintdb_postgres.c | 25 +- 9 files changed, 640 insertions(+), 90 deletions(-) (limited to 'src/include/taler_mintdb_plugin.h') diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h index b151cb009..1502edfbc 100644 --- a/src/include/taler_mint_service.h +++ b/src/include/taler_mint_service.h @@ -1173,8 +1173,6 @@ struct TALER_MINT_DepositWtidHandle; * yet execute the transaction * @param execution_time actual or planned execution time for the wire transfer * @param coin_contribution contribution to the @a total_amount of the deposited coin (may be NULL) - * @param total_amount total amount of the wire transfer, or NULL if the mint could - * not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK) */ typedef void (*TALER_MINT_DepositWtidCallback)(void *cls, @@ -1182,8 +1180,7 @@ typedef void json_t *json, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute execution_time, - const struct TALER_Amount *coin_contribution, - const struct TALER_Amount *total_amount); + const struct TALER_Amount *coin_contribution); /** diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index 7c48114b8..d2cc3d76e 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -583,7 +583,6 @@ typedef void * @param coin_contribution how much did the coin we asked about * contribute to the total transfer value? (deposit value including fee) * @param coin_fee how much did the mint charge for the deposit fee - * @param total_amount how much was the total wire transfer? * @param execution_time when was the transaction done, or * when we expect it to be done (if @a wtid was NULL) */ @@ -592,7 +591,6 @@ typedef void const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *coin_contribution, const struct TALER_Amount *coin_fee, - const struct TALER_Amount *total_amount, struct GNUNET_TIME_Absolute execution_time); @@ -1360,7 +1358,6 @@ struct TALER_MINTDB_Plugin * @param coin_pub which public key was this payment about * @param coin_value amount contributed by this coin in total * @param coin_fee deposit fee charged by mint for this coin - * @param transfer_value total amount of the wire transfer * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ int @@ -1374,8 +1371,7 @@ struct TALER_MINTDB_Plugin struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, - const struct TALER_Amount *coin_fee, - const struct TALER_Amount *transfer_value); + const struct TALER_Amount *coin_fee); /** diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 85c681dac..2526597ee 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -953,20 +953,6 @@ struct TALER_ConfirmWirePS */ struct TALER_AmountNBO coin_contribution; - /** - * The total amount the mint transferred in the transaction. - * Note that we may be aggregating multiple coin's @e coin_contribution - * values into a single wire transfer, so this value may be larger - * than that of @e coin_contribution. It may also be smaller, as - * @e coin_contribution may be say "1.123456" but the wire unit may - * be rounded down, i.e. to "1.12" (depending on the transfer method). - * - * Note that the mint books the deltas from rounding down as profit, - * so aggregating transfers is a good thing for the merchant (as it - * reduces rounding down expenses). - */ - struct TALER_AmountNBO total_amount; - }; GNUNET_NETWORK_STRUCT_END diff --git a/src/mint-lib/mint_api_deposit_wtid.c b/src/mint-lib/mint_api_deposit_wtid.c index 50f9c55d8..d29f406e3 100644 --- a/src/mint-lib/mint_api_deposit_wtid.c +++ b/src/mint-lib/mint_api_deposit_wtid.c @@ -148,9 +148,7 @@ handle_deposit_wtid_finished (void *cls, const struct TALER_WireTransferIdentifierRawP *wtid = NULL; struct GNUNET_TIME_Absolute execution_time = GNUNET_TIME_UNIT_FOREVER_ABS; const struct TALER_Amount *coin_contribution = NULL; - const struct TALER_Amount *total_amount = NULL; struct TALER_Amount coin_contribution_s; - struct TALER_Amount total_amount_s; dwh->job = NULL; json = MAC_download_get_result (&dwh->db, @@ -166,7 +164,6 @@ handle_deposit_wtid_finished (void *cls, MAJ_spec_fixed_auto ("wtid", &dwh->depconf.wtid), MAJ_spec_absolute_time ("execution_time", &execution_time), MAJ_spec_amount ("coin_contribution", &coin_contribution_s), - MAJ_spec_amount ("total_amount", &total_amount_s), MAJ_spec_end }; @@ -183,9 +180,6 @@ handle_deposit_wtid_finished (void *cls, TALER_amount_hton (&dwh->depconf.coin_contribution, &coin_contribution_s); coin_contribution = &coin_contribution_s; - TALER_amount_hton (&dwh->depconf.total_amount, - &total_amount_s); - total_amount = &total_amount_s; if (GNUNET_OK != verify_deposit_wtid_signature_ok (dwh, json)) @@ -244,8 +238,7 @@ handle_deposit_wtid_finished (void *cls, json, wtid, execution_time, - coin_contribution, - total_amount); + coin_contribution); json_decref (json); TALER_MINT_deposit_wtid_cancel (dwh); } diff --git a/src/mint/taler-mint-aggregator.c b/src/mint/taler-mint-aggregator.c index ee0f6ab22..5e05c8673 100644 --- a/src/mint/taler-mint-aggregator.c +++ b/src/mint/taler-mint-aggregator.c @@ -18,6 +18,10 @@ * @file taler-mint-aggregator.c * @brief Process that aggregates outgoing transactions and executes them * @author Christian Grothoff + * + * TODO: + * - simplify global_ret: make it a global! + * - handle shutdown more nicely (call 'cancel' method on wire transfers) */ #include "platform.h" #include @@ -62,6 +66,16 @@ static struct TALER_WIRE_Plugin *wire_plugin; */ static struct GNUNET_SCHEDULER_Task *task; +/** + * Limit on the number of transactions we aggregate at once. Note + * that the limit must be big enough to ensure that when transactions + * of the smallest possible unit are aggregated, they do surpass the + * "tiny" threshold beyond which we never trigger a wire transaction! + * + * TODO: make configurable (via config file or command line option) + */ +static unsigned int aggregation_limit = 10000; + /** * Load configuration parameters for the mint @@ -143,11 +157,86 @@ mint_serve_process_config (const char *mint_directory) } +/** + * Information about one aggregation process to + * be executed. + */ +struct AggregationUnit +{ + /** + * Public key of the merchant. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + + /** + * Total amount to be transferred. + */ + struct TALER_Amount total_amount; + + /** + * Hash of @e wire. + */ + struct GNUNET_HashCode h_wire; + + /** + * Wire transfer identifier we use. + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * Row ID of the transaction that started it all. + */ + unsigned long long row_id; + + /** + * The current time. + */ + struct GNUNET_TIME_Absolute execution_time; + + /** + * Wire details of the merchant. + */ + json_t *wire; + + /** + * Database session for all of our transactions. + */ + struct TALER_MINTDB_Session *session; + + /** + * Wire preparation handle. + */ + struct TALER_WIRE_PrepareHandle *ph; + + /** + * Array of #aggregation_limit row_ids from the + * aggregation. + */ + unsigned long long *additional_rows; + + /** + * Pointer to global return value. Closure for #run(). + */ + int *global_ret; + + /** + * Offset specifying how many #additional_rows are in use. + */ + unsigned int rows_offset; + + /** + * Set to #GNUNET_YES if we have to abort due to failure. + */ + int failed; + +}; + + /** * Function called with details about deposits that have been made, * with the goal of executing the corresponding wire transaction. * - * @param cls closure + * @param cls closure with the `struct AggregationUnit` * @param row_id identifies database entry * @param merchant_pub public key of the merchant * @param coin_pub public key of the coin @@ -172,20 +261,187 @@ deposit_cb (void *cls, struct GNUNET_TIME_Absolute wire_deadline, const json_t *wire) { - /* FIXME: compute aggregates, etc. */ + struct AggregationUnit *au = cls; + + au->merchant_pub = *merchant_pub; + if (GNUNET_OK != + TALER_amount_subtract (&au->total_amount, + amount_with_fee, + deposit_fee)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Fatally malformed record at %llu\n", + row_id); + return GNUNET_SYSERR; + } + au->row_id = row_id; + au->wire = (json_t *) wire; + au->execution_time = GNUNET_TIME_absolute_get (); + TALER_hash_json (au->wire, + &au->h_wire); + json_incref (au->wire); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &au->wtid, + sizeof (au->wtid)); + if (GNUNET_OK != + db_plugin->insert_aggregation_tracking (db_plugin->cls, + au->session, + &au->wtid, + merchant_pub, + &au->h_wire, + h_contract, + transaction_id, + au->execution_time, + coin_pub, + amount_with_fee, + deposit_fee)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + db_plugin->mark_deposit_done (db_plugin->cls, + au->session, + row_id)) + { + GNUNET_break (0); + au->failed = GNUNET_YES; + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + + +/** + * Function called with details about another deposit we + * can aggregate into an existing aggregation unit. + * + * @param cls closure with the `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 mint gets to keep as transaction fees + * @param transaction_id unique transaction ID chosen by the merchant + * @param h_contract hash of the contract between merchant and customer + * @param wire_deadline by which the merchant adviced that he would like the + * wire transfer to be executed + * @param wire wire details for the merchant + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +static int +aggregate_cb (void *cls, + unsigned long long 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, + uint64_t transaction_id, + const struct GNUNET_HashCode *h_contract, + struct GNUNET_TIME_Absolute wire_deadline, + const json_t *wire) +{ + struct AggregationUnit *au = cls; + struct TALER_Amount delta; + + GNUNET_break (0 == + memcmp (&au->merchant_pub, + merchant_pub, + sizeof (struct TALER_MerchantPublicKeyP))); + /* compute contribution of this coin after fees */ + if (GNUNET_OK != + TALER_amount_subtract (&delta, + amount_with_fee, + deposit_fee)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Fatally malformed record at %llu\n", + row_id); + return GNUNET_SYSERR; + } + /* add to total */ + if (GNUNET_OK != + TALER_amount_add (&au->total_amount, + &au->total_amount, + &delta)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Overflow or currency incompatibility during aggregation at %llu\n", + row_id); + /* Skip this one, but keep going! */ + return GNUNET_OK; + } + if (au->rows_offset >= aggregation_limit) + { + /* Bug: we asked for at most #aggregation_limit results! */ + GNUNET_break (0); + /* Skip this one, but keep going. */ + return GNUNET_OK; + } + if (NULL == au->additional_rows) + au->additional_rows = GNUNET_new_array (aggregation_limit, + unsigned long long); + /* "append" to our list of rows */ + au->additional_rows[au->rows_offset++] = row_id; + /* insert into aggregation tracking table */ + if (GNUNET_OK != + db_plugin->insert_aggregation_tracking (db_plugin->cls, + au->session, + &au->wtid, + merchant_pub, + &au->h_wire, + h_contract, + transaction_id, + au->execution_time, + coin_pub, + amount_with_fee, + deposit_fee)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + db_plugin->mark_deposit_done (db_plugin->cls, + au->session, + row_id)) + { + GNUNET_break (0); + au->failed = GNUNET_YES; + return GNUNET_SYSERR; + } return GNUNET_OK; } /** - * Main work function that queries the DB and executes transactions. + * Function to be called with the prepared transfer data. + * + * @param cls closure with the `struct AggregationUnit` + * @param buf transaction data to persist, NULL on error + * @param buf_size number of bytes in @a buf, 0 on error + */ +static void +prepare_cb (void *cls, + const char *buf, + size_t buf_size); + + +/** + * Main work function that queries the DB and aggregates transactions + * into larger wire transfers. + * + * @param cls pointer to an `int` which we will return from main() + * @param tc scheduler context */ static void -run (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +run_aggregation (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { int *global_ret = cls; struct TALER_MINTDB_Session *session; + struct AggregationUnit *au; + unsigned int i; int ret; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) @@ -207,50 +463,399 @@ run (void *cls, *global_ret = GNUNET_SYSERR; return; } + au = GNUNET_new (struct AggregationUnit); + au->session = session; ret = db_plugin->get_ready_deposit (db_plugin->cls, session, &deposit_cb, - NULL); - // FIXME: handle 0 == ret... - + au); if (GNUNET_OK != ret) + { + GNUNET_free (au); + db_plugin->rollback (db_plugin->cls, + session); + if (0 != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to execute deposit iteration!\n"); + *global_ret = GNUNET_SYSERR; + return; + } + /* nothing to do, sleep for a minute and try again */ + task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, + &run_aggregation, + global_ret); + return; + } + /* Now try to find other deposits to aggregate */ + ret = db_plugin->iterate_matching_deposits (db_plugin->cls, + session, + &au->h_wire, + &au->merchant_pub, + &aggregate_cb, + au, + aggregation_limit); + if ( (GNUNET_SYSERR == ret) || + (GNUNET_YES == au->failed) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to execute deposit iteration!\n"); + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + db_plugin->rollback (db_plugin->cls, + session); *global_ret = GNUNET_SYSERR; + return; + } + /* Round to the unit supported by the wire transfer method */ + GNUNET_assert (GNUNET_SYSERR != + wire_plugin->amount_round (wire_plugin->cls, + &au->total_amount)); + /* Check if after rounding down, we still have an amount to transfer */ + if ( (0 == au->total_amount.value) && + (0 == au->total_amount.fraction) ) + { + /* 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, + session); + /* Start another transaction to mark all* of the selected deposits + *as minor! */ + if (GNUNET_OK != + db_plugin->start (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to start database transaction!\n"); + *global_ret = GNUNET_SYSERR; + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + return; + } + /* Mark transactions by row_id as minor */ + ret = GNUNET_OK; + if (GNUNET_OK != + db_plugin->mark_deposit_tiny (db_plugin->cls, + session, + au->row_id)) + ret = GNUNET_SYSERR; + else + for (i=0;irows_offset;i++) + if (GNUNET_OK != + db_plugin->mark_deposit_tiny (db_plugin->cls, + session, + au->additional_rows[i])) + ret = GNUNET_SYSERR; + /* commit */ + if (GNUNET_OK != + db_plugin->commit (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to commit database transaction!\n"); + } + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + /* start again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; + } + au->global_ret = global_ret; + au->ph = wire_plugin->prepare_wire_transfer (wire_plugin->cls, + au->wire, + &au->total_amount, + &au->wtid, + &prepare_cb, + au); + /* FIXME: currently we have no clean-up plan on + shutdown to call prepare_wire_transfer_cancel! + Maybe make 'au' global? */ + if (NULL == au->ph) + { + GNUNET_break (0); /* why? how to best recover? */ db_plugin->rollback (db_plugin->cls, session); + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + /* start again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); return; } - /* FIXME: finish aggregate computation */ - /* wire_plugin->prepare_wire_transfer () -- ASYNC! */ - /* db_plugin->wire_prepare_data_insert () -- transactional! */ - /* db_plugin->XXX () -- mark transactions selected for aggregate as finished */ + /* otherwise we continue with #prepare_cb(), see below */ +} + - /* then finally: commit! */ +/** + * Execute the wire transfers that we have committed to + * do. + * + * @param cls pointer to an `int` which we will return from main() + * @param tc scheduler context + */ +static void +run_transfers (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + +/** + * Function to be called with the prepared transfer data. + * + * @param cls closure with the `struct AggregationUnit` + * @param buf transaction data to persist, NULL on error + * @param buf_size number of bytes in @a buf, 0 on error + */ +static void +prepare_cb (void *cls, + const char *buf, + size_t buf_size) +{ + struct AggregationUnit *au = cls; + int *global_ret = au->global_ret; + struct TALER_MINTDB_Session *session = au->session; + + GNUNET_free_non_null (au->additional_rows); + GNUNET_free (au); + if (NULL == buf) + { + GNUNET_break (0); /* why? how to best recover? */ + db_plugin->rollback (db_plugin->cls, + session); + /* start again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; + } + + /* Commit our intention to execute the wire transfer! */ + if (GNUNET_OK != + db_plugin->wire_prepare_data_insert (db_plugin->cls, + session, + mint_wireformat, + buf, + buf_size)) + { + GNUNET_break (0); /* why? how to best recover? */ + db_plugin->rollback (db_plugin->cls, + session); + /* start again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; + } + + /* Now we can finally commit the overall transaction, as we are + again consistent if all of this passes. */ if (GNUNET_OK != db_plugin->commit (db_plugin->cls, session)) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failed to commit database transaction!\n"); + /* try again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; } - /* While possible, run 2nd type of transaction: - db_plugin->start() - - select pre-commit data from DB: - db_plugin->wire_prepare_data_iterate () - - execute wire transfer (successfully!) - wire_plugin->execute_wire_transfer() # ASYNC! - db_plugin->wire_prepare_data_mark_finished () - db_plugin->insert_aggregation_tracking () - db_plugin->commit() - */ + /* run alternative task: actually do wire transfer! */ + task = GNUNET_SCHEDULER_add_now (&run_transfers, + &global_ret); +} + + +/** + * Data we keep to #run_transfers(). + */ +struct WirePrepareData +{ + + /** + * Database session for all of our transactions. + */ + struct TALER_MINTDB_Session *session; + + /** + * Wire execution handle. + */ + struct TALER_WIRE_ExecuteHandle *eh; + + /** + * Pointer to global return value. Closure for #run(). + */ + int *global_ret; + + + /** + * Row ID of the transfer. + */ + unsigned long long row_id; +}; - task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS /* FIXME: adjust! */, - &run, - global_ret); + +/** + * Function called with the result from the execute step. + * + * @param cls closure with the `struct WirePrepareData` + * @param success #GNUNET_OK on success, #GNUNET_SYSERR on failure + * @param emsg NULL on success, otherwise an error message + */ +static void +wire_confirm_cb (void *cls, + int success, + const char *emsg) +{ + struct WirePrepareData *wpd = cls; + int *global_ret = wpd->global_ret; + struct TALER_MINTDB_Session *session = wpd->session; + + wpd->eh = NULL; + if (GNUNET_SYSERR == success) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Wire transaction failed: %s\n", + emsg); + db_plugin->rollback (db_plugin->cls, + session); + *global_ret = GNUNET_SYSERR; + GNUNET_free (wpd); + return; + } + if (GNUNET_OK != + db_plugin->wire_prepare_data_mark_finished (db_plugin->cls, + session, + wpd->row_id)) + { + GNUNET_break (0); /* why!? */ + db_plugin->rollback (db_plugin->cls, + session); + *global_ret = GNUNET_SYSERR; + GNUNET_free (wpd); + return; + } + GNUNET_free (wpd); + if (GNUNET_OK != + db_plugin->commit (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Failed to commit database transaction!\n"); + /* try again */ + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + return; + } + /* continue with #run_transfers(), just to guard + against the unlikely case that there are more. */ + task = GNUNET_SCHEDULER_add_now (&run_transfers, + &global_ret); + +} + + +/** + * Callback with data about a prepared transaction. + * + * @param cls closure with the `struct WirePrepareData` + * @param rowid row identifier used to mark prepared transaction as done + * @param buf transaction data that was persisted, NULL on error + * @param buf_size number of bytes in @a buf, 0 on error + */ +static void +wire_prepare_cb (void *cls, + unsigned long long rowid, + const char *buf, + size_t buf_size) +{ + struct WirePrepareData *wpd = cls; + int *global_ret = wpd->global_ret; + + wpd->row_id = rowid; + wpd->eh = wire_plugin->execute_wire_transfer (wire_plugin->cls, + buf, + buf_size, + &wire_confirm_cb, + wpd); + /* FIXME: currently we have no clean-up plan on + shutdown to call execute_wire_transfer_cancel! + Maybe make 'wpd' global? */ + if (NULL == wpd->eh) + { + GNUNET_break (0); /* why? how to best recover? */ + db_plugin->rollback (db_plugin->cls, + wpd->session); + *global_ret = GNUNET_SYSERR; + GNUNET_free (wpd); + return; + } +} + + +/** + * Execute the wire transfers that we have committed to + * do. + * + * @param cls pointer to an `int` which we will return from main() + * @param tc scheduler context + */ +static void +run_transfers (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + int *global_ret = cls; + int ret; + struct WirePrepareData *wpd; + struct TALER_MINTDB_Session *session; + + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + return; + if (NULL == (session = db_plugin->get_session (db_plugin->cls, + GNUNET_NO))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to obtain database session!\n"); + *global_ret = GNUNET_SYSERR; + return; + } + if (GNUNET_OK != + db_plugin->start (db_plugin->cls, + session)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to start database transaction!\n"); + *global_ret = GNUNET_SYSERR; + return; + } + wpd = GNUNET_new (struct WirePrepareData); + wpd->session = session; + wpd->global_ret = global_ret; + ret = db_plugin->wire_prepare_data_get (db_plugin->cls, + session, + mint_wireformat, + &wire_prepare_cb, + wpd); + if (GNUNET_SYSERR == ret) + { + GNUNET_break (0); /* why? how to best recover? */ + db_plugin->rollback (db_plugin->cls, + session); + *global_ret = GNUNET_SYSERR; + GNUNET_free (wpd); + return; + } + if (GNUNET_NO == ret) + { + /* no more prepared wire transfers, go back to aggregation! */ + db_plugin->rollback (db_plugin->cls, + session); + task = GNUNET_SCHEDULER_add_now (&run_aggregation, + global_ret); + GNUNET_free (wpd); + return; + } + /* otherwise, continues in #wire_prepare_cb() */ } @@ -299,7 +904,7 @@ main (int argc, return 1; } - GNUNET_SCHEDULER_run (&run, &ret); + GNUNET_SCHEDULER_run (&run_transfers, &ret); TALER_MINTDB_plugin_unload (db_plugin); TALER_WIRE_plugin_unload (wire_plugin); diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index c39cbbcf7..b93ead3af 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1804,7 +1804,6 @@ struct DepositWtidContext * @param coin_contribution how much did the coin we asked about * contribute to the total transfer value? (deposit value including fee) * @param coin_fee how much did the mint charge for the deposit fee - * @param total_amount how much was the total wire transfer? * @param execution_time when was the transaction done, or * when we expect it to be done (if @a wtid was NULL); * #GNUNET_TIME_UNIT_FOREVER_ABS if the /deposit is unknown @@ -1815,7 +1814,6 @@ handle_wtid_data (void *cls, const struct TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *coin_contribution, const struct TALER_Amount *coin_fee, - const struct TALER_Amount *total_amount, struct GNUNET_TIME_Absolute execution_time) { struct DepositWtidContext *ctx = cls; @@ -1843,7 +1841,6 @@ handle_wtid_data (void *cls, &ctx->h_wire, &ctx->coin_pub, &coin_delta, - total_amount, ctx->transaction_id, wtid, execution_time); diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 041f694bf..2ebd0d331 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -1097,7 +1097,6 @@ TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection, * @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 total_amount how much was the total wire transfer? * @param transaction_id merchant transaction identifier * @param wtid raw wire transfer identifier * @param exec_time execution time of the wire transfer @@ -1109,7 +1108,6 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, const struct GNUNET_HashCode *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_contribution, - const struct TALER_Amount *total_amount, uint64_t transaction_id, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute exec_time) @@ -1128,8 +1126,6 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, cw.execution_time = GNUNET_TIME_absolute_hton (exec_time); TALER_amount_hton (&cw.coin_contribution, coin_contribution); - TALER_amount_hton (&cw.total_amount, - total_amount); TMH_KS_sign (&cw.purpose, &pub, &sig); @@ -1140,7 +1136,6 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, sizeof (*wtid)), "execution_time", TALER_json_from_abs (exec_time), "coin_contribution", TALER_json_from_amount (coin_contribution), - "total_amount", TALER_json_from_amount (total_amount), "mint_sig", TALER_json_from_data (&sig, sizeof (sig)), "mint_pub", TALER_json_from_data (&pub, diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index caad29047..a0396c8a1 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -280,6 +280,7 @@ TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection, * @param h_contract hash of the contract * @param h_wire hash of wire account details * @param coin_pub public key of the coin + * @param coin_contribution contribution of this coin to the total amount transferred * @param transaction_id merchant transaction identifier * @param wtid raw wire transfer identifier * @param exec_time execution time of the wire transfer @@ -291,7 +292,6 @@ TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, const struct GNUNET_HashCode *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_contribution, - const struct TALER_Amount *total_amount, uint64_t transaction_id, const struct TALER_WireTransferIdentifierRawP *wtid, struct GNUNET_TIME_Absolute exec_time); diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index fc204f5e2..2ab3e81ac 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -466,9 +466,6 @@ postgres_create_tables (void *cls, ",coin_fee_val INT8 NOT NULL" ",coin_fee_frac INT4 NOT NULL" ",coin_fee_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" - ",transfer_total_val INT8 NOT NULL" - ",transfer_total_frac INT4 NOT NULL" - ",transfer_total_curr VARCHAR("TALER_CURRENCY_LEN_STR") NOT NULL" ")"); /* Index for lookup_transactions statement on wtid */ SQLEXEC_INDEX("CREATE INDEX aggregation_tracking_wtid_index " @@ -1090,9 +1087,6 @@ postgres_prepare (PGconn *db_conn) ",coin_fee_val" ",coin_fee_frac" ",coin_fee_curr" - ",transfer_total_val" - ",transfer_total_frac" - ",transfer_total_curr" " FROM aggregation_tracking" " WHERE wtid_raw=$1", 1, NULL); @@ -1108,9 +1102,6 @@ postgres_prepare (PGconn *db_conn) ",coin_fee_val" ",coin_fee_frac" ",coin_fee_curr" - ",transfer_total_val" - ",transfer_total_frac" - ",transfer_total_curr" " FROM aggregation_tracking" " WHERE" " coin_pub=$1 AND" @@ -1136,12 +1127,9 @@ postgres_prepare (PGconn *db_conn) ",coin_fee_val" ",coin_fee_frac" ",coin_fee_curr" - ",transfer_total_val" - ",transfer_total_frac" - ",transfer_total_curr" ") VALUES " - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)", - 16, NULL); + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", + 13, NULL); /* Used in #postgres_wire_prepare_data_insert() to store @@ -3950,7 +3938,6 @@ postgres_wire_lookup_deposit_wtid (void *cls, NULL, &coin_amount, &coin_fee, - NULL, exec_time); PQclear (result); return GNUNET_YES; @@ -3967,13 +3954,11 @@ postgres_wire_lookup_deposit_wtid (void *cls, struct GNUNET_TIME_Absolute exec_time; struct TALER_Amount coin_amount; struct TALER_Amount coin_fee; - struct TALER_Amount transaction_amount; struct TALER_PQ_ResultSpec rs[] = { TALER_PQ_result_spec_auto_from_type ("wtid_raw", &wtid), TALER_PQ_result_spec_absolute_time ("execution_time", &exec_time), TALER_PQ_result_spec_amount ("coin_amount", &coin_amount), TALER_PQ_result_spec_amount ("coin_fee", &coin_fee), - TALER_PQ_result_spec_amount ("transfer_total", &transaction_amount), TALER_PQ_result_spec_end }; if (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0)) @@ -3986,7 +3971,6 @@ postgres_wire_lookup_deposit_wtid (void *cls, &wtid, &coin_amount, &coin_fee, - &transaction_amount, exec_time); } PQclear (result); @@ -4007,7 +3991,6 @@ postgres_wire_lookup_deposit_wtid (void *cls, * @param coin_pub which public key was this payment about * @param coin_value amount contributed by this coin in total * @param coin_fee deposit fee charged by mint for this coin - * @param transfer_value total amount of the wire transfer * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors */ static int @@ -4021,8 +4004,7 @@ postgres_insert_aggregation_tracking (void *cls, struct GNUNET_TIME_Absolute execution_time, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, - const struct TALER_Amount *coin_fee, - const struct TALER_Amount *transfer_value) + const struct TALER_Amount *coin_fee) { struct TALER_PQ_QueryParam params[] = { TALER_PQ_query_param_auto_from_type (h_contract), @@ -4034,7 +4016,6 @@ postgres_insert_aggregation_tracking (void *cls, TALER_PQ_query_param_absolute_time (&execution_time), TALER_PQ_query_param_amount (coin_value), TALER_PQ_query_param_amount (coin_fee), - TALER_PQ_query_param_amount (transfer_value), TALER_PQ_query_param_end }; PGresult *result; -- cgit v1.2.3