From d185fd574e54c82799d3519bf774b50d421fa370 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Nov 2015 15:59:05 +0100 Subject: rearranging code to (1) satisfy naming and coding conventions a bit more, and (2) provide a task handle for each mint, which may fix #4042 --- src/backend-lib/Makefile.am | 18 +- src/backend-lib/merchant_api_contract.c | 60 ---- src/backend-lib/merchant_api_deposit.c | 111 ------- src/backend-lib/merchant_db.c | 134 +++++---- src/backend-lib/merchant_db.h | 198 ------------- src/backend-lib/taler_merchant_contract_lib.h | 11 - src/backend-lib/taler_merchant_deposit_lib.h | 28 -- src/backend-lib/taler_merchant_lib.h | 2 - src/backend/Makefile.am | 1 - src/backend/merchant.c | 183 ------------ src/backend/taler-merchant-httpd.c | 403 +++++++++++++++++++------- src/backend/taler-merchant-httpd.h | 114 +++++++- src/backend/taler-merchant-httpd_contract.c | 20 +- src/backend/taler-merchant-httpd_pay.c | 57 +++- src/backend/taler-mint-httpd_parsing.c | 6 +- src/include/Makefile.am | 8 +- src/include/merchant.h | 204 ------------- src/include/taler_merchantdb_lib.h | 200 +++++++++++++ 18 files changed, 747 insertions(+), 1011 deletions(-) delete mode 100644 src/backend-lib/merchant_api_contract.c delete mode 100644 src/backend-lib/merchant_api_deposit.c delete mode 100644 src/backend-lib/merchant_db.h delete mode 100644 src/backend-lib/taler_merchant_contract_lib.h delete mode 100644 src/backend-lib/taler_merchant_deposit_lib.h delete mode 100644 src/backend-lib/taler_merchant_lib.h delete mode 100644 src/include/merchant.h create mode 100644 src/include/taler_merchantdb_lib.h diff --git a/src/backend-lib/Makefile.am b/src/backend-lib/Makefile.am index 583c4d03..8139e9c8 100644 --- a/src/backend-lib/Makefile.am +++ b/src/backend-lib/Makefile.am @@ -2,22 +2,12 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include lib_LTLIBRARIES = \ - libtalermerchant.la + libtalermerchantdb.la -include_HEADERS = \ - taler_merchant_lib.h \ - taler_merchant_contract_lib.h \ - taler_merchant_deposit_lib.h +libtalermerchantdb_la_SOURCES = \ + merchant_db.c -libtalermerchant_la_SOURCES = \ - merchant_api_contract.c \ - merchant_api_deposit.c \ - taler_merchant_contract_lib.h \ - taler_merchant_deposit_lib.h \ - merchant_db.c merchant_db.h \ - merchant.h - -libtalermerchant_la_LIBADD = \ +libtalermerchantdb_la_LIBADD = \ $(LIBGCRYPT_LIBS) \ -ltalerutil \ -lgnunetutil \ diff --git a/src/backend-lib/merchant_api_contract.c b/src/backend-lib/merchant_api_contract.c deleted file mode 100644 index 20b69cd3..00000000 --- a/src/backend-lib/merchant_api_contract.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, If not, see -*/ - -/** - * @file merchant/merchant_db.c - * @brief DB work related to contract management - * @author Marcello Stanisci - */ - -#include "platform.h" -#include -#include -#include -#include "merchant.h" -#include "merchant_db.h" -#include "taler_merchant_contract_lib.h" - -/** - * Take the global wire details and return a JSON containing them, - * compliantly with the Taler's API. - * @param wire the merchant's wire details - * @param salt the nounce for hashing the wire details with - * @param edate when the beneficiary wants this transfer to take place - * @return JSON representation of the wire details, NULL upon errors - */ - -json_t * -MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire, - uint64_t salt) - -{ - - json_t *root; - json_t *j_salt; - - j_salt = json_integer (salt); - - if (NULL == (root = json_pack ("{s:s, s:s, s:s, s:s, s:I}", - "type", "SEPA", - "IBAN", wire->iban, - "name", wire->name, - "bic", wire->bic, - "r", json_integer_value (j_salt)))) - return NULL; - - return root; -} diff --git a/src/backend-lib/merchant_api_deposit.c b/src/backend-lib/merchant_api_deposit.c deleted file mode 100644 index a3cae20c..00000000 --- a/src/backend-lib/merchant_api_deposit.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, If not, see -*/ - -/** - * @file merchant/merchant_db.c - * @brief DB and crypto work related to deposit management - * @author Marcello Stanisci - */ - - -#include "platform.h" -#include -#include -#include -#include -#include "merchant.h" -#include "merchant_db.h" -#include "taler_merchant_contract_lib.h" - -/** -* Verify the signature on a successful deposit permission -* @param h_contract the hashed stringification of this contract -* @param h_wire the hashed 'wire' object holdign the merchant bank's details -* @param timestamp the 32bit wide number representing the number of seconds -* since the Epoch -* @param refund the refund deadline for this deal, expressed in seconds as @a -* timestamp -* @param trans_id an id number for this deal -* @param amount_minus_fee what paid minus its deposit fee -* @param coin_pub the coin's public key -* @param sig the mint's signature -* @param mint_pub mint's key to verify this signature against -* @return GNUNET_OK if the verification succeeds, GNUNET_NO if not, -* GNUNET_SYSERR upon errors -*/ - -uint32_t -MERCHANT_verify_confirmation (const struct GNUNET_HashCode *h_contract, - const struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute refund, - uint64_t trans_id, - const struct TALER_Amount *amount_minus_fee, - const struct TALER_CoinSpendPublicKeyP *coin, - const struct TALER_MerchantPublicKeyP *merchant, - const struct GNUNET_CRYPTO_EddsaSignature *sig, - const struct TALER_MintPublicKeyP *mint_pub) -{ - struct TALER_DepositConfirmationPS dc; - - dc.h_contract = *h_contract; - dc.h_wire = *h_wire; - - dc.merchant = *merchant; - dc.coin_pub = *coin; - - dc.timestamp = GNUNET_TIME_absolute_hton (timestamp); - dc.refund_deadline = GNUNET_TIME_absolute_hton (refund); - TALER_amount_hton (&dc.amount_without_fee, amount_minus_fee); - dc.transaction_id = GNUNET_htonll (trans_id); - - #ifdef DEBUG - char *hwire_enc; - char *hcontract_enc; - char *merchant_enc; - char *coinpub_enc; - - hwire_enc = GNUNET_STRINGS_data_to_string_alloc (h_wire, sizeof (struct GNUNET_HashCode)); - hcontract_enc = GNUNET_STRINGS_data_to_string_alloc (h_contract, sizeof (struct GNUNET_HashCode)); - merchant_enc = GNUNET_STRINGS_data_to_string_alloc (&merchant.eddsa_pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); - coinpub_enc = GNUNET_STRINGS_data_to_string_alloc (&coin.eddsa_pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); - - printf ("Signing Confirmation:\nH_wire: %s\nH_contract: %s\nmerchant_pub: %s\ncoin_pub: %s\n" - "timestamp: %llu,\nrefund: %llu,\namount: %s %llu.%lu,\ntrid: %llu\n", - hwire_enc, - hcontract_enc, - merchant_enc, - coinpub_enc, - timestamp_abs.abs_value_us, - refund_abs.abs_value_us, - amount_minus_fee->currency, - amount_minus_fee->value, - amount_minus_fee->fraction, - trans_id); - #endif - - dc.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_DEPOSIT); - dc.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)); - - if (GNUNET_SYSERR == - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_CONFIRM_DEPOSIT, - &dc.purpose, - sig, - &mint_pub->eddsa_pub)) - return GNUNET_NO; - return GNUNET_OK; -} - diff --git a/src/backend-lib/merchant_db.c b/src/backend-lib/merchant_db.c index f30e3d88..6575b9ed 100644 --- a/src/backend-lib/merchant_db.c +++ b/src/backend-lib/merchant_db.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) + (C) 2014, 2015 Christian Grothoff (and other contributing authors) 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 @@ -19,12 +19,20 @@ * @brief database helper functions used by the merchant * @author Sree Harsha Totakura */ - #include "platform.h" #include #include #include -#include "merchant_db.h" +#include "taler_merchantdb_lib.h" + +/** + * Shorthand for exit jumps. + */ +#define EXITIF(cond) \ + do { \ + if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ + } while (0) + #define PQSQL_strerror(kind, cmd, res) \ @@ -245,6 +253,7 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp) return GNUNET_SYSERR; } + /** * Update the pending column of a deposit permission * @param conn handle to DB @@ -252,7 +261,7 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp) * update * @param pending true if still pending, false otherwise (i.e. the * mint did respond something) - * @return GNUNET_OK if successful, GNUNET_SYSERR upon errors + * @return #GNUNET_OK if successful, #GNUNET_SYSERR upon errors */ uint32_t MERCHANT_DB_update_deposit_permission (PGconn *conn, @@ -265,7 +274,7 @@ MERCHANT_DB_update_deposit_permission (PGconn *conn, struct TALER_PQ_QueryParam params[] = { TALER_PQ_query_param_uint32 (&pending), TALER_PQ_query_param_uint64 (&transaction_id), - TALER_PQ_query_param_end + TALER_PQ_query_param_end }; res = TALER_PQ_exec_prepared (conn, "update_deposit_permission", params); @@ -292,16 +301,18 @@ MERCHANT_DB_update_deposit_permission (PGconn *conn, } } + /** * Store a deposit permission in DB. To be mainly used if /deposit should * be retried; also, the merchant can benefit from this information in case - * he needs to later investigate about some transaction_id. + * he needs to later investigate about some @a transaction_id. + * * @param conn DB handle * @param transaction_id identification number of this payment (which is the * same id of the related contract) * @param pending if true, this payment got to a persistent state * @param which mint is to get this deposit permission - * @return GNUNET_OK if successful, GNUNET_SYSERR upon errors + * @return #GNUNET_OK if successful, #GNUNET_SYSERR upon errors */ uint32_t MERCHANT_DB_store_deposit_permission (PGconn *conn, @@ -312,14 +323,14 @@ MERCHANT_DB_store_deposit_permission (PGconn *conn, { PGresult *res; ExecStatusType status; - struct TALER_PQ_QueryParam params[] = { TALER_PQ_query_param_fixed_size (deposit_permission, strlen (deposit_permission)), TALER_PQ_query_param_uint64 (&transaction_id), - TALER_PQ_query_param_uint32 (&pending), + TALER_PQ_query_param_uint32 (&pending), TALER_PQ_query_param_fixed_size (mint_url, strlen (mint_url)), - TALER_PQ_query_param_end + TALER_PQ_query_param_end }; + res = TALER_PQ_exec_prepared (conn, "store_deposit_permission", params); status = PQresultStatus (res); @@ -351,33 +362,33 @@ MERCHANT_DB_store_deposit_permission (PGconn *conn, PQclear (res); return GNUNET_SYSERR; } - + PQclear (res); return GNUNET_OK; } -/** -* Insert a contract record into the database and if successfull -* return the serial number of the inserted row. -* -* @param conn the database connection -* @param timestamp the timestamp of this contract -* @param expiry the time when the contract will expire -* @param edate when the merchant wants to receive the wire transfer -* corresponding to this deal (this value is also a field inside the -* 'wire' JSON format) -* @param refund deadline until which the merchant can return the paid -* amount -* @param amount the taler amount corresponding to the contract -* @param hash of the stringified JSON corresponding to this contract -* @param c_id contract's id -* @param desc descripition of the contract -* @param nounce a random 64-bit nounce -* @param product description to identify a product -* @return GNUNET_OK on success, GNUNET_NO if attempting to insert an -* already inserted @a c_id, GNUNET_SYSERR for other errors. -*/ +/** + * Insert a contract record into the database and if successfull + * return the serial number of the inserted row. + * + * @param conn the database connection + * @param timestamp the timestamp of this contract + * @param expiry the time when the contract will expire + * @param edate when the merchant wants to receive the wire transfer + * corresponding to this deal (this value is also a field inside the + * 'wire' JSON format) + * @param refund deadline until which the merchant can return the paid + * amount + * @param amount the taler amount corresponding to the contract + * @param hash of the stringified JSON corresponding to this contract + * @param c_id contract's id + * @param desc descripition of the contract + * @param nounce a random 64-bit nounce + * @param product description to identify a product + * @return #GNUNET_OK on success, #GNUNET_NO if attempting to insert an + * already inserted @a c_id, #GNUNET_SYSERR for other errors. + */ uint32_t MERCHANT_DB_contract_create (PGconn *conn, const struct GNUNET_TIME_Absolute timestamp, @@ -392,16 +403,16 @@ MERCHANT_DB_contract_create (PGconn *conn, uint64_t product) { PGresult *res; - #if 0 +#if 0 uint64_t expiry_ms_nbo; uint64_t value_nbo; uint32_t fraction_nbo; uint64_t nounce_nbo; - #endif +#endif ExecStatusType status; struct TALER_PQ_QueryParam params[] = { - TALER_PQ_query_param_uint64 (&c_id), + TALER_PQ_query_param_uint64 (&c_id), TALER_PQ_query_param_fixed_size (h_contract, sizeof (struct GNUNET_HashCode)), TALER_PQ_query_param_absolute_time (×tamp), TALER_PQ_query_param_absolute_time (&expiry), @@ -412,11 +423,11 @@ MERCHANT_DB_contract_create (PGconn *conn, though the column is declared as *blob*. Will this be liked by the DB ? */ TALER_PQ_query_param_fixed_size (desc, strlen (desc)), - TALER_PQ_query_param_uint64 (&nounce), + TALER_PQ_query_param_uint64 (&nounce), TALER_PQ_query_param_uint64 (&product), TALER_PQ_query_param_end }; - + /* NOTE: the statement is prepared by MERCHANT_DB_initialize function */ res = TALER_PQ_exec_prepared (conn, "contract_create", params); status = PQresultStatus (res); @@ -450,9 +461,9 @@ MERCHANT_DB_contract_create (PGconn *conn, PQclear (res); return GNUNET_OK; - } + long long MERCHANT_DB_get_contract_product (PGconn *conn, uint64_t contract_id) @@ -483,6 +494,7 @@ MERCHANT_DB_get_contract_product (PGconn *conn, return -1; } + unsigned int MERCHANT_DB_checkout_create (PGconn *conn, struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub, @@ -552,21 +564,19 @@ MERCHANT_DB_get_checkout_product (PGconn *conn, PQclear (res); return -1; } -/* end of merchant-db.c */ /** -* The query gets a contract's nounce and edate used to reproduce -* a 'wire' JSON object. This function is also useful to check whether -* a claimed contract existed or not. -* @param conn handle to the DB -* @param h_contract the parameter for the row to match against -* @param nounce where to store the found nounce -* @param edate where to store the found edate -* @return GNUNET_OK on success, GNUNET_SYSERR upon errors -* -*/ - + * The query gets a contract's nounce and edate used to reproduce + * a 'wire' JSON object. This function is also useful to check whether + * a claimed contract existed or not. + * + * @param conn handle to the DB + * @param h_contract the parameter for the row to match against + * @param nounce where to store the found nounce + * @param edate where to store the found edate + * @return #GNUNET_OK on success, #GNUNET_SYSERR upon errors + */ uint32_t MERCHANT_DB_get_contract_values (PGconn *conn, const struct GNUNET_HashCode *h_contract, @@ -580,13 +590,12 @@ MERCHANT_DB_get_contract_values (PGconn *conn, TALER_PQ_query_param_fixed_size (h_contract, sizeof (struct GNUNET_HashCode)), TALER_PQ_query_param_end }; - struct TALER_PQ_ResultSpec rs[] = { TALER_PQ_result_spec_uint64 ("nounce", nounce), TALER_PQ_result_spec_absolute_time ("edate", edate), TALER_PQ_result_spec_end }; - + res = TALER_PQ_exec_prepared (conn, "get_contract_hash", params); status = PQresultStatus (res); @@ -607,16 +616,16 @@ MERCHANT_DB_get_contract_values (PGconn *conn, return GNUNET_SYSERR; } -/** -* Get a set of values representing a contract. This function is meant -* to obsolete the '_get_contract_values' version. -* @param h_contract the hashcode of this contract -* @param contract_handle where to store the results -* @raturn GNUNET_OK in case of success, GNUNET_SYSERR -* upon errors -* -*/ +/** + * Get a set of values representing a contract. This function is meant + * to obsolete the '_get_contract_values' version. + * + * @param h_contract the hashcode of this contract + * @param contract_handle where to store the results + * @raturn GNUNET_OK in case of success, GNUNET_SYSERR + * upon errors + */ uint32_t MERCHANT_DB_get_contract_handle (PGconn *conn, const struct GNUNET_HashCode *h_contract, @@ -639,9 +648,8 @@ MERCHANT_DB_get_contract_handle (PGconn *conn, TALER_PQ_result_spec_uint64 ("contract_id", &ch.contract_id), TALER_PQ_result_spec_end }; - - res = TALER_PQ_exec_prepared (conn, "get_contract_set", params); + res = TALER_PQ_exec_prepared (conn, "get_contract_set", params); status = PQresultStatus (res); EXITIF (PGRES_TUPLES_OK != status); if (0 == PQntuples (res)) diff --git a/src/backend-lib/merchant_db.h b/src/backend-lib/merchant_db.h deleted file mode 100644 index aa157712..00000000 --- a/src/backend-lib/merchant_db.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, If not, see -*/ - -/** - * @file merchant/merchant_db.h - * @brief database helper functions used by the merchant - * @author Sree Harsha Totakura - */ - -#ifndef MERCHANT_DB_H -#define MERCHANT_DB_H - -#include -#include - -/* Set of values that represent a contract. To be expanded on an - as-needed basis */ -struct MERCHANT_contract_handle -{ - /* The nounce used when hashing the wire details - for this contract */ - uint64_t nounce; - - /* The maximum time when the merchant expects the money tranfer - to his bank account to happen */ - struct GNUNET_TIME_Absolute edate; - - /* The time when this contract was generated */ - struct GNUNET_TIME_Absolute timestamp; - - /* The maximum time until which the merchant could issue a - refund to the customer */ - struct GNUNET_TIME_Absolute refund_deadline; - - /* The identification number for this contract */ - uint64_t contract_id; - -}; - -/** - * Connect to postgresql database - * - * @param cfg the configuration handle - * @return connection to the postgresql database; NULL upon error - */ -PGconn * -MERCHANT_DB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); - - -/** - * Disconnect from the database - * - * @param conn database handle to close - */ -void -MERCHANT_DB_disconnect (PGconn *conn); - - -/** - * Initialize merchant tables - * - * @param conn the connection handle to postgres db. - * @param tmp GNUNET_YES if the tables are to be made temporary i.e. their - * contents are dropped when the @a conn is closed - * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure - */ -int -MERCHANT_DB_initialize (PGconn *conn, int tmp); - - -/** -* Inserts a contract record into the database and if successfull returns the -* serial number of the inserted row. -* -* @param conn the database connection -* @param timestamp the timestamp of this contract -* @param expiry the time when the contract will expire -* @param edate when the merchant wants to receive the wire transfer corresponding -* to this deal (this value is also a field inside the 'wire' JSON format) -* @param refund deadline until which the merchant can return the paid amount -* @param amount the taler amount corresponding to the contract -* @param hash of the stringified JSON corresponding to this contract -* @param c_id contract's id -* @param desc descripition of the contract -* @param nounce a random 64-bit nounce -* @param product description to identify a product -* @return GNUNET_OK on success, GNUNET_SYSERR upon error -*/ - -uint32_t -MERCHANT_DB_contract_create (PGconn *conn, - const struct GNUNET_TIME_Absolute timestamp, - const struct GNUNET_TIME_Absolute expiry, - struct GNUNET_TIME_Absolute edate, - struct GNUNET_TIME_Absolute refund, - const struct TALER_Amount *amount, - const struct GNUNET_HashCode *h_contract, - uint64_t c_id, - const char *desc, - uint64_t nounce, - uint64_t product); - -long long -MERCHANT_DB_get_contract_product (PGconn *conn, - uint64_t contract_id); - -/** - * Update the pending column of a deposit permission - * @param conn handle to DB - * @param transaction_id identification number of the deposit to - * update - * @param pending true if still pending, false otherwise (i.e. the - * mint did respond something) - * @return GNUNET_OK if successful, GNUNET_SYSERR upon errors - */ -uint32_t -MERCHANT_DB_update_deposit_permission (PGconn *conn, - uint64_t transaction_id, - unsigned int pending); - -unsigned int -MERCHANT_DB_checkout_create (PGconn *conn, - struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub, - uint64_t transaction_id, - struct TALER_Amount *amount, - struct GNUNET_CRYPTO_rsa_Signature *coin_sig); - - -long long -MERCHANT_DB_get_checkout_product (PGconn *conn, - struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub); - -/** -* The query gets a contract's nounce and edate used to reproduce -* a 'wire' JSON object. This function is also useful to check whether -* a claimed contract existed or not. -* @param conn handle to the DB -* @param h_contract the parameter for the row to match against -* @param nounce where to store the found nounce -* @param edate where to store the found edate -* @return GNUNET_OK on success, GNUNET_SYSERR upon errors -* -*/ - -uint32_t -MERCHANT_DB_get_contract_values (PGconn *conn, - const struct GNUNET_HashCode *h_contract, - uint64_t *nounce, - struct GNUNET_TIME_Absolute *edate); - -#endif /* MERCHANT_DB_H */ - -/** -* Get a set of values representing a contract. This function is meant -* to obsolete the '_get_contract_values' version. -* @param h_contract the hashcode of this contract -* @param contract_handle where to store the results -* @raturn GNUNET_OK in case of success, GNUNET_SYSERR -* upon errors -* -*/ - -uint32_t -MERCHANT_DB_get_contract_handle (PGconn *conn, - const struct GNUNET_HashCode *h_contract, - struct MERCHANT_contract_handle *contract_handle); - -/** - * Store a deposit permission in DB. To be mainly used if /deposit should - * be retried; also, the merchant can benefit from this information in case - * he needs to later investigate about some transaction_id. - * @param conn DB handle - * @param transaction_id identification number of this payment (which is the - * same id of the related contract) - * @param pending if true, this payment got to a persistent state - * @param which mint is to get this deposit permission - * @return GNUNET_OK if successful, GNUNET_SYSERR upon errors - */ -uint32_t -MERCHANT_DB_store_deposit_permission (PGconn *conn, - const char *deposit_permission, - uint64_t transaction_id, - unsigned int pending, - const char *mint_url); -/* end of merchant-db.h */ diff --git a/src/backend-lib/taler_merchant_contract_lib.h b/src/backend-lib/taler_merchant_contract_lib.h deleted file mode 100644 index 3f95841f..00000000 --- a/src/backend-lib/taler_merchant_contract_lib.h +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Take the global wire details and return a JSON containing them, - * compliantly with the Taler's API. - * @param wire the merchant's wire details - * @param salt the nounce for hashing the wire details with - * @return JSON representation of the wire details, NULL upon errors - */ - -json_t * -MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire, - uint64_t salt); diff --git a/src/backend-lib/taler_merchant_deposit_lib.h b/src/backend-lib/taler_merchant_deposit_lib.h deleted file mode 100644 index 95bbea78..00000000 --- a/src/backend-lib/taler_merchant_deposit_lib.h +++ /dev/null @@ -1,28 +0,0 @@ -/** -* Verify the signature on a successful deposit permission -* @param h_contract the hashed stringification of this contract -* @param h_wire the hashed 'wire' object holdign the merchant bank's details -* @param timestamp the 32bit wide number representing the number of seconds -* since the Epoch -* @param refund the refund deadline for this deal, expressed in seconds as @a -* timestamp -* @param trans_id an id number for this deal -* @param amount_minus_fee what paid minus its deposit fee -* @param coin_pub the coin's public key -* @param sig the mint's signature -* @param mint_pub mint's key to verify this signature against -* @return GNUNET_OK if the verification succeeds, GNUNET_NO if not, -* GNUNET_SYSERR upon errors -*/ - -uint32_t -MERCHANT_verify_confirmation (const struct GNUNET_HashCode *h_contract, - const struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute refund, - uint64_t trans_id, - const struct TALER_Amount *amount_minus_fee, - const struct TALER_CoinSpendPublicKeyP *coin, - const struct TALER_MerchantPublicKeyP *merchant, - const struct GNUNET_CRYPTO_EddsaSignature *sig, - const struct TALER_MintPublicKeyP *mint_pub); diff --git a/src/backend-lib/taler_merchant_lib.h b/src/backend-lib/taler_merchant_lib.h deleted file mode 100644 index ff8d85b7..00000000 --- a/src/backend-lib/taler_merchant_lib.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "taler_merchant_contract_lib.h" -#include "taler_merchant_deposit_lib.h" diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 08601781..c1d71a68 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -6,7 +6,6 @@ bin_PROGRAMS = \ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd.c taler-merchant-httpd.h \ - merchant.c merchant.h \ ../backend-lib/merchant_db.c ../backend-lib/merchant_db.h \ taler-mint-httpd_parsing.c taler-mint-httpd_parsing.h \ taler-mint-httpd_responses.c taler-mint-httpd_responses.h \ diff --git a/src/backend/merchant.c b/src/backend/merchant.c index 02b37fb8..b0ab811f 100644 --- a/src/backend/merchant.c +++ b/src/backend/merchant.c @@ -31,189 +31,6 @@ } while (0) -/** - * Parses mints from the configuration. - * - * @param cfg the configuration - * @param mints the array of mints upon successful parsing. Will be NULL upon - * error. - * @return the number of mints in the above array; GNUNET_SYSERR upon error in - * parsing. - */ -int -TALER_MERCHANT_parse_mints (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct MERCHANT_Mint **mints) -{ - char *mints_str; - char *token_nf; /* do no free (nf) */ - char *mint_section; - char *mint_hostname; - struct MERCHANT_Mint *r_mints; - struct MERCHANT_Mint mint; - unsigned int cnt; - int OK; - - OK = 0; - mints_str = NULL; - token_nf = NULL; - mint_section = NULL; - mint_hostname = NULL; - r_mints = NULL; - cnt = 0; - EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "merchant", - "TRUSTED_MINTS", - &mints_str)); - for (token_nf = strtok (mints_str, " "); - NULL != token_nf; - token_nf = strtok (NULL, " ")) - { - GNUNET_assert (0 < GNUNET_asprintf (&mint_section, - "mint-%s", token_nf)); - EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - mint_section, - "HOSTNAME", - &mint_hostname)); - mint.hostname = mint_hostname; - GNUNET_array_append (r_mints, cnt, mint); - mint_hostname = NULL; - GNUNET_free (mint_section); - mint_section = NULL; - } - OK = 1; - - EXITIF_exit: - GNUNET_free_non_null (mints_str); - GNUNET_free_non_null (mint_section); - GNUNET_free_non_null (mint_hostname); - if (!OK) - { - GNUNET_free_non_null (r_mints); - return GNUNET_SYSERR; - } - - *mints = r_mints; - return cnt; -} - -/** - * Parses auditors from the configuration. - * - * @param cfg the configuration - * @param mints the array of auditors upon successful parsing. Will be NULL upon - * error. - * @return the number of auditors in the above array; GNUNET_SYSERR upon error in - * parsing. - */ -int -TALER_MERCHANT_parse_auditors (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct MERCHANT_Auditor **auditors) -{ - char *auditors_str; - char *token_nf; /* do no free (nf) */ - char *auditor_section; - char *auditor_name; - struct MERCHANT_Auditor *r_auditors; - struct MERCHANT_Auditor auditor; - unsigned int cnt; - int OK; - - OK = 0; - auditors_str = NULL; - token_nf = NULL; - auditor_section = NULL; - auditor_name = NULL; - r_auditors = NULL; - cnt = 0; - EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "merchant", - "AUDITORS", - &auditors_str)); - for (token_nf = strtok (auditors_str, " "); - NULL != token_nf; - token_nf = strtok (NULL, " ")) - { - GNUNET_assert (0 < GNUNET_asprintf (&auditor_section, - "auditor-%s", token_nf)); - EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - auditor_section, - "NAME", - &auditor_name)); - auditor.name = auditor_name; - GNUNET_array_append (r_auditors, cnt, auditor); - auditor_name = NULL; - GNUNET_free (auditor_section); - auditor_section = NULL; - } - OK = 1; - - EXITIF_exit: - GNUNET_free_non_null (auditors_str); - GNUNET_free_non_null (auditor_section); - GNUNET_free_non_null (auditor_name); - if (!OK) - { - GNUNET_free_non_null (r_auditors); - return GNUNET_SYSERR; - } - - *auditors = r_auditors; - return cnt; -} -/** - * Parse the SEPA information from the configuration. If any of the required - * fileds is missing return NULL. - * - * @param cfg the configuration - * @return Sepa details as a structure; NULL upon error - */ -struct MERCHANT_WIREFORMAT_Sepa * -TALER_MERCHANT_parse_wireformat_sepa (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct MERCHANT_WIREFORMAT_Sepa *wf; - - wf = GNUNET_new (struct MERCHANT_WIREFORMAT_Sepa); - EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "wire-sepa", - "IBAN", - &wf->iban)); - EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "wire-sepa", - "NAME", - &wf->name)); - EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, - "wire-sepa", - "BIC", - &wf->bic)); - return wf; - - EXITIF_exit: - GNUNET_free_non_null (wf->iban); - GNUNET_free_non_null (wf->name); - GNUNET_free_non_null (wf->bic); - GNUNET_free (wf); - return NULL; - -} - - -/** - * Destroy and free resouces occupied by the wireformat structure - * - * @param wf the wireformat structure - */ -void -TALER_MERCHANT_destroy_wireformat_sepa (struct MERCHANT_WIREFORMAT_Sepa *wf) -{ - GNUNET_free_non_null (wf->iban); - GNUNET_free_non_null (wf->name); - GNUNET_free_non_null (wf->bic); - GNUNET_free (wf); -} - /* end of merchant.c */ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index ba359bd1..d135a7c5 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) + (C) 2014, 2015 Christian Grothoff (and other contributing authors) 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 @@ -30,14 +30,29 @@ #include #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_responses.h" -#include "merchant_db.h" -#include "merchant.h" -#include "taler_merchant_lib.h" +#include "taler_merchantdb_lib.h" #include "taler-merchant-httpd.h" #include "taler-mint-httpd_mhd.h" #include "taler-merchant-httpd_contract.h" #include "taler-merchant-httpd_pay.h" + + +/** + * Merchant's private key + */ +struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; + +/** + * Our wireformat + */ +struct MERCHANT_WIREFORMAT_Sepa *wire; + +/** + * Salt used to hash the wire object + */ +long long salt; + /** * Our hostname */ @@ -48,15 +63,10 @@ static char *hostname; */ static long long unsigned port; -/** - * Merchant's private key - */ -struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; - /** * File holding the merchant's private key */ -char *keyfile; +static char *keyfile; /** * This value tells the mint by which date this merchant would like @@ -65,14 +75,14 @@ char *keyfile; struct GNUNET_TIME_Relative edate_delay; /** - * To make 'TMH_PARSE_navigate_json ()' compile + * Which currency is supported by this merchant? */ -char *TMH_mint_currency_string; +char *TMH_merchant_currency_string; /** - * Trusted mints + * Trusted mints (FIXME: they are NOT all trusted!). */ -struct MERCHANT_Mint *mints; +struct MERCHANT_Mint **mints; /** * Active auditors @@ -90,22 +100,7 @@ static struct GNUNET_SCHEDULER_Task *shutdown_task; static struct GNUNET_SCHEDULER_Task *mhd_task; /** - * Context "poller" identifier - */ -struct GNUNET_SCHEDULER_Task *poller_task; - -/** - * Our wireformat - */ -struct MERCHANT_WIREFORMAT_Sepa *wire; - -/** - * Salt used to hash the wire object - */ -long long salt; - -/** - * The number of accepted mints + * Length of the #mints array. */ unsigned int nmints; @@ -134,6 +129,36 @@ PGconn *db_conn; */ static struct MHD_Daemon *mhd; + +/** + * Take the global wire details and return a JSON containing them, + * compliantly with the Taler's API. + * + * @param wire the merchant's wire details + * @param salt the nounce for hashing the wire details with + * @param edate when the beneficiary wants this transfer to take place + * @return JSON representation of the wire details, NULL upon errors + */ +json_t * +MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire, + uint64_t salt) + +{ + json_t *root; + json_t *j_salt; + + j_salt = json_integer (salt); + if (NULL == (root = json_pack ("{s:s, s:s, s:s, s:s, s:I}", + "type", "SEPA", + "IBAN", wire->iban, + "name", wire->name, + "bic", wire->bic, + "r", json_integer_value (j_salt)))) + return NULL; + return root; +} + + /** * A client has requested the given url using the given method * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT, @@ -255,6 +280,7 @@ url_handler (void *cls, } + /** * Function called with information about who is auditing * a particular mint and what key the mint is using. @@ -288,7 +314,6 @@ keys_mgmt_cb (void *cls, const struct TALER_MINT_Keys *keys) } else printf ("no keys gotten\n"); - } @@ -306,14 +331,13 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) for (cnt = 0; cnt < nmints; cnt++) { - if (NULL != mints[cnt].conn) - TALER_MINT_disconnect (mints[cnt].conn); - - } - if (NULL != poller_task) - { - GNUNET_SCHEDULER_cancel (poller_task); - poller_task = NULL; + if (NULL != mints[cnt]->conn) + TALER_MINT_disconnect (mints[cnt]->conn); + if (NULL != mints[cnt]->poller_task) + { + GNUNET_SCHEDULER_cancel (mints[cnt]->poller_task); + mints[cnt]->poller_task = NULL; + } } if (NULL != mhd_task) { @@ -338,13 +362,14 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** * Task that runs the context's event loop using the GNUnet scheduler. * - * @param cls mint context + * @param cls a `struct MERCHANT_Mint *` * @param tc scheduler context (unused) */ void context_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + struct MERCHANT_Mint *mint = cls; long timeout; int max_fd; fd_set read_fd_set; @@ -353,17 +378,15 @@ context_task (void *cls, struct GNUNET_NETWORK_FDSet *rs; struct GNUNET_NETWORK_FDSet *ws; struct GNUNET_TIME_Relative delay; - struct TALER_MINT_Context *ctx; - ctx = (struct TALER_MINT_Context *) cls; - poller_task = NULL; - TALER_MINT_perform (ctx); + mint->poller_task = NULL; + TALER_MINT_perform (mint->ctx); max_fd = -1; timeout = -1; FD_ZERO (&read_fd_set); FD_ZERO (&write_fd_set); FD_ZERO (&except_fd_set); - TALER_MINT_get_select_info (ctx, + TALER_MINT_get_select_info (mint->ctx, &read_fd_set, &write_fd_set, &except_fd_set, @@ -383,13 +406,13 @@ context_task (void *cls, GNUNET_NETWORK_fdset_copy_native (ws, &write_fd_set, max_fd + 1); - poller_task = - GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, - delay, - rs, - ws, - &context_task, - cls); + mint->poller_task = + GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, + delay, + rs, + ws, + &context_task, + mint); GNUNET_NETWORK_fdset_destroy (rs); GNUNET_NETWORK_fdset_destroy (ws); } @@ -460,6 +483,191 @@ TM_trigger_daemon () } +/** + * Parses mints listed in the configuration. + * + * @param cfg the configuration + * @return the number of mints in the above array; #GNUNET_SYSERR upon error in + * parsing. + */ +static int +parse_mints (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + char *mints_str; + char *token_nf; /* do no free (nf) */ + char *mint_section; + char *mint_hostname; + struct MERCHANT_Mint **r_mints; + struct MERCHANT_Mint *mint; + unsigned int cnt; + int ok; + + ok = 0; + mints_str = NULL; + token_nf = NULL; + mint_section = NULL; + mint_hostname = NULL; + r_mints = NULL; + cnt = 0; + EXITIF (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "merchant", + "TRUSTED_MINTS", + &mints_str)); + for (token_nf = strtok (mints_str, " "); + NULL != token_nf; + token_nf = strtok (NULL, " ")) + { + GNUNET_assert (0 < GNUNET_asprintf (&mint_section, + "mint-%s", token_nf)); + EXITIF (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + mint_section, + "HOSTNAME", + &mint_hostname)); + mint = GNUNET_new (struct MERCHANT_Mint); + mint->hostname = mint_hostname; + GNUNET_array_append (r_mints, + cnt, + mint); + GNUNET_free (mint_section); + mint_section = NULL; + } + ok = 1; + + EXITIF_exit: + GNUNET_free_non_null (mints_str); + GNUNET_free_non_null (mint_section); + GNUNET_free_non_null (mint_hostname); + if (! ok) + { + GNUNET_free_non_null (r_mints); + return GNUNET_SYSERR; + } + mints = r_mints; + return cnt; +} + + +/** + * Parses auditors from the configuration. + * + * @param cfg the configuration + * @param mints the array of auditors upon successful parsing. Will be NULL upon + * error. + * @return the number of auditors in the above array; #GNUNET_SYSERR upon error in + * parsing. + */ +static int +parse_auditors (const struct GNUNET_CONFIGURATION_Handle *cfg, + struct MERCHANT_Auditor **auditors) +{ + char *auditors_str; + char *token_nf; /* do no free (nf) */ + char *auditor_section; + char *auditor_name; + struct MERCHANT_Auditor *r_auditors; + struct MERCHANT_Auditor auditor; + unsigned int cnt; + int ok; + + ok = 0; + auditors_str = NULL; + token_nf = NULL; + auditor_section = NULL; + auditor_name = NULL; + r_auditors = NULL; + cnt = 0; + EXITIF (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "merchant", + "AUDITORS", + &auditors_str)); + for (token_nf = strtok (auditors_str, " "); + NULL != token_nf; + token_nf = strtok (NULL, " ")) + { + GNUNET_assert (0 < GNUNET_asprintf (&auditor_section, + "auditor-%s", token_nf)); + EXITIF (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + auditor_section, + "NAME", + &auditor_name)); + auditor.name = auditor_name; + GNUNET_array_append (r_auditors, cnt, auditor); + auditor_name = NULL; + GNUNET_free (auditor_section); + auditor_section = NULL; + } + ok = 1; + + EXITIF_exit: + GNUNET_free_non_null (auditors_str); + GNUNET_free_non_null (auditor_section); + GNUNET_free_non_null (auditor_name); + if (! ok) + { + GNUNET_free_non_null (r_auditors); + return GNUNET_SYSERR; + } + + *auditors = r_auditors; + return cnt; +} + + +/** + * Parse the SEPA information from the configuration. If any of the required + * fileds is missing return NULL. + * + * @param cfg the configuration + * @return Sepa details as a structure; NULL upon error + */ +static struct MERCHANT_WIREFORMAT_Sepa * +parse_wireformat_sepa (const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct MERCHANT_WIREFORMAT_Sepa *wf; + + wf = GNUNET_new (struct MERCHANT_WIREFORMAT_Sepa); + EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, + "wire-sepa", + "IBAN", + &wf->iban)); + EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, + "wire-sepa", + "NAME", + &wf->name)); + EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, + "wire-sepa", + "BIC", + &wf->bic)); + return wf; + + EXITIF_exit: + GNUNET_free_non_null (wf->iban); + GNUNET_free_non_null (wf->name); + GNUNET_free_non_null (wf->bic); + GNUNET_free (wf); + return NULL; +} + + +/** + * Destroy and free resouces occupied by the wireformat structure + * + * @param wf the wireformat structure + */ +static void +destroy_wireformat_sepa (struct MERCHANT_WIREFORMAT_Sepa *wf) +{ + GNUNET_free_non_null (wf->iban); + GNUNET_free_non_null (wf->name); + GNUNET_free_non_null (wf->bic); + GNUNET_free (wf); +} + + /** * Function that queries MHD's select sets and * starts the task waiting for them. @@ -510,7 +718,6 @@ prepare_daemon () } - /** * Main function that will be run by the scheduler. * @@ -521,42 +728,42 @@ prepare_daemon () * @param config configuration */ void -run (void *cls, char *const *args, const char *cfgfile, +run (void *cls, + char *const *args, + const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { - unsigned int cnt; - mints = NULL; - keyfile = NULL; + result = GNUNET_SYSERR; shutdown_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, - &do_shutdown, - NULL); + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, + &do_shutdown, + NULL); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "merchant launched\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "merchant launched\n"); EXITIF (GNUNET_SYSERR == - (nmints = - TALER_MERCHANT_parse_mints (config, - &mints))); + (nmints = + parse_mints (config))); EXITIF (GNUNET_SYSERR == - (nauditors = - TALER_MERCHANT_parse_auditors (config, - &auditors))); + (nauditors = + parse_auditors (config, + &auditors))); EXITIF (NULL == - (wire = - TALER_MERCHANT_parse_wireformat_sepa (config))); + (wire = + parse_wireformat_sepa (config))); EXITIF (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (config, - "merchant", - "KEYFILE", - &keyfile)); + GNUNET_CONFIGURATION_get_value_filename (config, + "merchant", + "KEYFILE", + &keyfile)); EXITIF (NULL == - (privkey = - GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile))); + (privkey = + GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile))); EXITIF (NULL == - (db_conn = MERCHANT_DB_connect (config))); + (db_conn = MERCHANT_DB_connect (config))); EXITIF (GNUNET_OK != MERCHANT_DB_initialize (db_conn, dry)); EXITIF (GNUNET_SYSERR == @@ -573,7 +780,7 @@ run (void *cls, char *const *args, const char *cfgfile, GNUNET_CONFIGURATION_get_value_string (config, "merchant", "CURRENCY", - &TMH_mint_currency_string)); + &TMH_merchant_currency_string)); EXITIF (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (config, @@ -586,16 +793,17 @@ run (void *cls, char *const *args, const char *cfgfile, for (cnt = 0; cnt < nmints; cnt++) { - EXITIF (NULL == (mints[cnt].ctx = TALER_MINT_init ())); - mints[cnt].pending = 1; - mints[cnt].conn = TALER_MINT_connect (mints[cnt].ctx, - mints[cnt].hostname, - &keys_mgmt_cb, - &mints[cnt], - TALER_MINT_OPTION_END); - EXITIF (NULL == mints[cnt].conn); - poller_task = - GNUNET_SCHEDULER_add_now (&context_task, mints[cnt].ctx); + EXITIF (NULL == (mints[cnt]->ctx = TALER_MINT_init ())); + mints[cnt]->pending = 1; + mints[cnt]->conn = TALER_MINT_connect (mints[cnt]->ctx, + mints[cnt]->hostname, + &keys_mgmt_cb, + mints[cnt], + TALER_MINT_OPTION_END); + EXITIF (NULL == mints[cnt]->conn); + mints[cnt]->poller_task = + GNUNET_SCHEDULER_add_now (&context_task, + mints[cnt]); } mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME, @@ -609,15 +817,15 @@ run (void *cls, char *const *args, const char *cfgfile, result = GNUNET_OK; mhd_task = prepare_daemon (); - EXITIF_exit: - if (GNUNET_OK != result) - GNUNET_SCHEDULER_shutdown (); + EXITIF_exit: + if (GNUNET_OK != result) + GNUNET_SCHEDULER_shutdown (); GNUNET_free_non_null (keyfile); - if (GNUNET_OK != result) - GNUNET_SCHEDULER_shutdown (); - + if (GNUNET_OK != result) + GNUNET_SCHEDULER_shutdown (); } + /** * The main function of the serve tool * @@ -628,14 +836,12 @@ run (void *cls, char *const *args, const char *cfgfile, int main (int argc, char *const *argv) { - - static const struct GNUNET_GETOPT_CommandLineOption options[] = { + static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'t', "temp", NULL, gettext_noop ("Use temporary database tables"), GNUNET_NO, &GNUNET_GETOPT_set_one, &dry}, - GNUNET_GETOPT_OPTION_END - }; - + GNUNET_GETOPT_OPTION_END + }; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, @@ -644,5 +850,4 @@ main (int argc, char *const *argv) options, &run, NULL)) return 3; return (GNUNET_OK == result) ? 0 : 1; - } diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h index b60d91bd..7dc1b647 100644 --- a/src/backend/taler-merchant-httpd.h +++ b/src/backend/taler-merchant-httpd.h @@ -19,13 +19,86 @@ * @author Marcello Stanisci */ -#include "merchant_db.h" +#include "platform.h" +#include "taler_merchantdb_lib.h" /** - * Kick MHD to run now, to be called after MHD_resume_connection(). + * Shorthand for exit jumps. */ -void -TM_trigger_daemon (void); +#define EXITIF(cond) \ + do { \ + if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ + } while (0) + + +/** + * Mint + */ +struct MERCHANT_Mint +{ + /** + * Hostname + */ + char *hostname; + + /** + * A connection to this mint + */ + struct TALER_MINT_Handle *conn; + + /** + * This mint's context (useful to the event loop) + */ + struct TALER_MINT_Context *ctx; + + /** + * Task we use to drive the interaction with this mint. + */ + struct GNUNET_SCHEDULER_Task *poller_task; + + /** + * Flag which indicates whether some HTTP transfer between + * this merchant and the mint is still ongoing + */ + int pending; + +}; + + +struct MERCHANT_WIREFORMAT_Sepa +{ + /** + * The international bank account number + */ + char *iban; + + /** + * Name of the bank account holder + */ + char *name; + + /** + *The bank identification code + */ + char *bic; + + /** + * The latest payout date when the payment corresponding to this account has + * to take place. A value of 0 indicates a transfer as soon as possible. + */ + struct GNUNET_TIME_AbsoluteNBO payout; +}; + + +struct MERCHANT_Auditor +{ + /** + * Auditor's legal name + */ + char *name; + +}; + struct TM_HandlerContext; @@ -48,10 +121,15 @@ struct TM_HandlerContext }; -extern struct MERCHANT_Mint *mints; extern struct MERCHANT_WIREFORMAT_Sepa *wire; + +extern struct MERCHANT_Mint **mints; + +extern struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; + + extern PGconn *db_conn; extern long long salt; @@ -60,11 +138,29 @@ extern unsigned int nmints; extern struct GNUNET_TIME_Relative edate_delay; -extern struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; - -extern struct GNUNET_SCHEDULER_Task *poller_task; - void context_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + + + + +/** + * Take the global wire details and return a JSON containing them, + * compliantly with the Taler's API. + * + * @param wire the merchant's wire details + * @param salt the nounce for hashing the wire details with + * @return JSON representation of the wire details, NULL upon errors + */ +json_t * +MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire, + uint64_t salt); + + +/** + * Kick MHD to run now, to be called after MHD_resume_connection(). + */ +void +TM_trigger_daemon (void); diff --git a/src/backend/taler-merchant-httpd_contract.c b/src/backend/taler-merchant-httpd_contract.c index c42a8b37..d6c1b8fd 100644 --- a/src/backend/taler-merchant-httpd_contract.c +++ b/src/backend/taler-merchant-httpd_contract.c @@ -32,9 +32,7 @@ #include "taler-mint-httpd.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_responses.h" -#include "merchant_db.h" -#include "merchant.h" -#include "taler_merchant_lib.h" +#include "taler_merchantdb_lib.h" #include "taler-merchant-httpd.h" extern struct MERCHANT_Auditor *auditors; @@ -71,7 +69,7 @@ MH_handler_contract (struct TMH_RequestHandler *rh, int cnt; struct GNUNET_HashCode h_wire; struct GNUNET_CRYPTO_EddsaPublicKey pubkey; - struct MERCHANT_Contract contract; + struct TALER_ContractPS contract; char *contract_str; struct GNUNET_CRYPTO_EddsaSignature contract_sig; @@ -86,15 +84,15 @@ MH_handler_contract (struct TMH_RequestHandler *rh, return MHD_YES; /* Generate preferred mint(s) array. */ - + trusted_mints = json_array (); for (cnt = 0; cnt < nmints; cnt++) { - if (!mints[cnt].pending) + if (! mints[cnt]->pending) { - keys = TALER_MINT_get_keys (mints[cnt].conn); + keys = TALER_MINT_get_keys (mints[cnt]->conn); mint = json_pack ("{s:s, s:o}", - "url", mints[cnt].hostname, + "url", mints[cnt]->hostname, "master_pub", TALER_json_from_data (&keys->master_pub.eddsa_pub, @@ -131,7 +129,7 @@ MH_handler_contract (struct TMH_RequestHandler *rh, json_object_set_new (root, "auditors", j_auditors); if (NULL == (j_wire = MERCHANT_get_wire_json (wire, - salt))) + salt))) return MHD_NO; /* hash wire objcet */ @@ -149,7 +147,7 @@ MH_handler_contract (struct TMH_RequestHandler *rh, TALER_json_from_data (&pubkey, sizeof (pubkey))); /* Sign */ - contract_str = json_dumps (root, JSON_COMPACT | JSON_SORT_KEYS); + contract_str = json_dumps (root, JSON_COMPACT | JSON_SORT_KEYS); GNUNET_CRYPTO_hash (contract_str, strlen (contract_str), &contract.h_contract); contract.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT); contract.purpose.size = htonl (sizeof (contract)); @@ -164,5 +162,5 @@ MH_handler_contract (struct TMH_RequestHandler *rh, "H_contract", TALER_json_from_data (&contract.h_contract, sizeof (contract.h_contract))); - + } diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c index 1951d2d0..1885c59c 100644 --- a/src/backend/taler-merchant-httpd_pay.c +++ b/src/backend/taler-merchant-httpd_pay.c @@ -18,7 +18,6 @@ * @brief HTTP serving layer mainly intended to communicate with the frontend * @author Marcello Stanisci */ - #include "platform.h" #include #include @@ -33,9 +32,41 @@ #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_responses.h" #include "taler-mint-httpd_mhd.h" -#include "merchant_db.h" -#include "merchant.h" -#include "taler_merchant_lib.h" +#include "taler_merchantdb_lib.h" + + +/** + * Outcome of a /deposit request for a coin. Typically forming an array enclosed + * into the unique PayContext + */ +struct MERCHANT_DepositConfirmation +{ + /** + * Reference to the per-deposit-handler Context. Needed by the + * cleanup function to get it freed + */ + struct DepositCallbackContext *dcc; + + /** + * The mint's response body (JSON). Mainly useful in case + * some callback needs to send back to the to the wallet the + * outcome of an erroneous coin + */ + json_t *proof; + + /** + * True if this coin's outcome has been read from + * its cb + */ + unsigned int ackd; + + /** + * The mint's response to this /deposit + */ + unsigned int exit_status; + +}; + /** @@ -73,9 +104,9 @@ deposit_fee_from_coin_aggregate (struct MHD_Connection *connection, if (GNUNET_OK != res) return res; /* may return GNUNET_NO */ - if (1 == mints[mint_index].pending) + if (1 == mints[mint_index]->pending) return GNUNET_SYSERR; - keys = TALER_MINT_get_keys (mints[mint_index].conn); + keys = TALER_MINT_get_keys (mints[mint_index]->conn); denom_details = TALER_MINT_get_denomination_key (keys, &denom); if (NULL == denom_details) { @@ -203,7 +234,7 @@ deposit_cb (void *cls, return; } } - + printf ("All /deposit(s) ack'd\n"); dcc->pc->response = MHD_create_response_from_buffer (strlen ("All coins ack'd by the mint\n"), @@ -386,7 +417,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh, } /* test it by checking public key */ - if (0 == strcmp (mints[mint_index].hostname, + if (0 == strcmp (mints[mint_index]->hostname, chosen_mint)) break; @@ -498,7 +529,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh, deposit_permission_str, transaction_id, 1, - mints[mint_index].hostname)) + mints[mint_index]->hostname)) return TMH_RESPONSE_reply_internal_error (connection, "internal DB failure"); res = TMH_PARSE_json_data (connection, coin_aggregate, @@ -512,7 +543,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh, percoin_dcc->index = coins_index; percoin_dcc->pc = pc; - dh = TALER_MINT_deposit (mints[mint_index].conn, + dh = TALER_MINT_deposit (mints[mint_index]->conn, &percoin_amount, edate, wire_details, @@ -535,13 +566,13 @@ MH_handler_pay (struct TMH_RequestHandler *rh, return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_SERVICE_UNAVAILABLE, "{s:s, s:i}", - "mint", mints[mint_index].hostname, + "mint", mints[mint_index]->hostname, "transaction_id", transaction_id); } } - GNUNET_SCHEDULER_cancel (poller_task); - GNUNET_SCHEDULER_add_now (context_task, mints[mint_index].ctx); + GNUNET_SCHEDULER_cancel (mints[mint_index]->poller_task); + GNUNET_SCHEDULER_add_now (context_task, mints[mint_index]->ctx); return MHD_YES; /* 4 Return response code: success, or whatever data the diff --git a/src/backend/taler-mint-httpd_parsing.c b/src/backend/taler-mint-httpd_parsing.c index 9efd6c23..314d8839 100644 --- a/src/backend/taler-mint-httpd_parsing.c +++ b/src/backend/taler-mint-httpd_parsing.c @@ -32,8 +32,8 @@ 'TMH_PARSE_nagivate_json ()' compile fine; so its value will be kept on some merchant's accepted currency. For multi currencies merchants, that of course would require a patch */ +extern char *TMH_merchant_currency_string; -extern char *TMH_mint_currency_string; /** * Initial size for POST request buffer. */ @@ -634,7 +634,7 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection, case TMH_PARSE_JNC_RET_STRING: { - void **where = va_arg (argp, void **); + void **where = va_arg (argp, void **); *where = (void*) json_string_value (root); ret = GNUNET_OK; } @@ -876,7 +876,7 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection, break; } if (0 != strcmp (where->currency, - TMH_mint_currency_string)) + TMH_merchant_currency_string)) { GNUNET_break_op (0); ret = (MHD_YES != diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 3db59c88..77977b5f 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -1,2 +1,8 @@ +# This Makefile.am is in the public domain EXTRA_DIST = \ - platform.h + platform.h + +talerincludedir = $(includedir)/taler + +talerinclude_HEADERS = \ + taler_merchantdb_lib.h diff --git a/src/include/merchant.h b/src/include/merchant.h deleted file mode 100644 index eb430360..00000000 --- a/src/include/merchant.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - This file is part of TALER - (C) 2014 Christian Grothoff (and other contributing authors) - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, If not, see -*/ - -/** - * @file include/merchant.h - * @brief Common utility functions for merchant - * @author Sree Harsha Totakura - */ - -#ifndef MERCHANT_H -#define MERCHANT_H - -#include -#include -#include "merchant.h" - -/** - * Macro to round microseconds to seconds in GNUNET_TIME_* structs. - */ -#define ROUND_TO_SECS(name,us_field) name.us_field -= name.us_field % (1000 * 1000) - -/** - * Shorthand for exit jumps. - */ -#define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) - -/** - * Outcome of a /deposit request for a coin. Typically forming an array enclosed - * into the unique PayContext - */ -struct MERCHANT_DepositConfirmation -{ - /** - * Reference to the per-deposit-handler Context. Needed by the - * cleanup function to get it freed - */ - struct DepositCallbackContext *dcc; - - /** - * True if this coin's outcome has been read from - * its cb - */ - unsigned int ackd; - - /** - * The mint's response to this /deposit - */ - unsigned int exit_status; - - /** - * The mint's response body (JSON). Mainly useful in case - * some callback needs to send back to the to the wallet the - * outcome of an erroneous coin - */ - json_t *proof; - -}; - - -/** - * Mint - */ -struct MERCHANT_Mint -{ - /** - * Hostname - */ - char *hostname; - - /** - * Flag which indicates whether some HTTP transfer between - * this merchant and the mint is still ongoing - */ - int pending; - - /** - * A connection to this mint - */ - struct TALER_MINT_Handle *conn; - - /** - * This mint's context (useful to the event loop) - */ - struct TALER_MINT_Context *ctx; - -}; - -struct MERCHANT_Auditor -{ - /** - * Auditor's legal name - */ - char *name; - -}; - -/** - * The contract sent by the merchant to the wallet - */ -struct MERCHANT_Contract -{ - /** - * Purpose header for the signature over contract - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the JSON contract in UTF-8 including 0-termination, - * using JSON_COMPACT | JSON_SORT_KEYS - */ - struct GNUNET_HashCode h_contract; - -}; - - - -/** - * Parses mints from the configuration. - * - * @param cfg the configuration - * @param mints the array of mints upon successful parsing. Will be NULL upon - * error. - * @return the number of mints in the above array; GNUNET_SYSERR upon error in - * parsing. - */ -int -TALER_MERCHANT_parse_mints (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct MERCHANT_Mint **mints); - -/** - * Parses auditors from the configuration. - * - * @param cfg the configuration - * @param mints the array of auditors upon successful parsing. Will be NULL upon - * error. - * @return the number of auditors in the above array; GNUNET_SYSERR upon error in - * parsing. - */ -int -TALER_MERCHANT_parse_auditors (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct MERCHANT_Auditor **auditors); - -GNUNET_NETWORK_STRUCT_BEGIN -struct MERCHANT_WIREFORMAT_Sepa -{ - /** - * The international bank account number - */ - char *iban; - - /** - * Name of the bank account holder - */ - char *name; - - /** - *The bank identification code - */ - char *bic; - - /** - * The latest payout date when the payment corresponding to this account has - * to take place. A value of 0 indicates a transfer as soon as possible. - */ - struct GNUNET_TIME_AbsoluteNBO payout; -}; -GNUNET_NETWORK_STRUCT_END - -/** - * Parse the SEPA information from the configuration. If any of the required - * fileds is missing return NULL. - * - * @param cfg the configuration - * @return Sepa details as a structure; NULL upon error - */ -struct MERCHANT_WIREFORMAT_Sepa * -TALER_MERCHANT_parse_wireformat_sepa (const struct GNUNET_CONFIGURATION_Handle *cfg); - - -/** - * Destroy and free resouces occupied by the wireformat structure - * - * @param wf the wireformat structure - */ -void -TALER_MERCHANT_destroy_wireformat_sepa (struct MERCHANT_WIREFORMAT_Sepa *wf); - -#endif /* MERCHANT_H */ diff --git a/src/include/taler_merchantdb_lib.h b/src/include/taler_merchantdb_lib.h new file mode 100644 index 00000000..f650a8aa --- /dev/null +++ b/src/include/taler_merchantdb_lib.h @@ -0,0 +1,200 @@ +/* + This file is part of TALER + (C) 2014, 2015 Christian Grothoff (and other contributing authors) + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, If not, see +*/ + +/** + * @file include/taler_merchantdb_lib.h + * @brief database helper functions used by the merchant backend + * @author Sree Harsha Totakura + */ + +#ifndef MERCHANT_DB_H +#define MERCHANT_DB_H + +#include +#include + + + +/* Set of values that represent a contract. To be expanded on an + as-needed basis */ +struct MERCHANT_contract_handle +{ + /* The nounce used when hashing the wire details + for this contract */ + uint64_t nounce; + + /* The maximum time when the merchant expects the money tranfer + to his bank account to happen */ + struct GNUNET_TIME_Absolute edate; + + /* The time when this contract was generated */ + struct GNUNET_TIME_Absolute timestamp; + + /* The maximum time until which the merchant could issue a + refund to the customer */ + struct GNUNET_TIME_Absolute refund_deadline; + + /* The identification number for this contract */ + uint64_t contract_id; + +}; + +/** + * Connect to postgresql database + * + * @param cfg the configuration handle + * @return connection to the postgresql database; NULL upon error + */ +PGconn * +MERCHANT_DB_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); + + +/** + * Disconnect from the database + * + * @param conn database handle to close + */ +void +MERCHANT_DB_disconnect (PGconn *conn); + + +/** + * Initialize merchant tables + * + * @param conn the connection handle to postgres db. + * @param tmp GNUNET_YES if the tables are to be made temporary i.e. their + * contents are dropped when the @a conn is closed + * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure + */ +int +MERCHANT_DB_initialize (PGconn *conn, int tmp); + + +/** + * Inserts a contract record into the database and if successfull returns the + * serial number of the inserted row. + * + * @param conn the database connection + * @param timestamp the timestamp of this contract + * @param expiry the time when the contract will expire + * @param edate when the merchant wants to receive the wire transfer corresponding + * to this deal (this value is also a field inside the 'wire' JSON format) + * @param refund deadline until which the merchant can return the paid amount + * @param amount the taler amount corresponding to the contract + * @param hash of the stringified JSON corresponding to this contract + * @param c_id contract's id + * @param desc descripition of the contract + * @param nounce a random 64-bit nounce + * @param product description to identify a product + * @return #GNUNET_OK on success, #GNUNET_SYSERR upon error + */ +uint32_t +MERCHANT_DB_contract_create (PGconn *conn, + const struct GNUNET_TIME_Absolute timestamp, + const struct GNUNET_TIME_Absolute expiry, + struct GNUNET_TIME_Absolute edate, + struct GNUNET_TIME_Absolute refund, + const struct TALER_Amount *amount, + const struct GNUNET_HashCode *h_contract, + uint64_t c_id, + const char *desc, + uint64_t nounce, + uint64_t product); + + +long long +MERCHANT_DB_get_contract_product (PGconn *conn, + uint64_t contract_id); + + +/** + * Update the pending column of a deposit permission + * + * @param conn handle to DB + * @param transaction_id identification number of the deposit to + * update + * @param pending true if still pending, false otherwise (i.e. the + * mint did respond something) + * @return #GNUNET_OK if successful, #GNUNET_SYSERR upon errors + */ +uint32_t +MERCHANT_DB_update_deposit_permission (PGconn *conn, + uint64_t transaction_id, + unsigned int pending); + +unsigned int +MERCHANT_DB_checkout_create (PGconn *conn, + struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub, + uint64_t transaction_id, + struct TALER_Amount *amount, + struct GNUNET_CRYPTO_rsa_Signature *coin_sig); + + +long long +MERCHANT_DB_get_checkout_product (PGconn *conn, + struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub); + +/** + * The query gets a contract's nounce and edate used to reproduce + * a 'wire' JSON object. This function is also useful to check whether + * a claimed contract existed or not. + * + * @param conn handle to the DB + * @param h_contract the parameter for the row to match against + * @param nounce where to store the found nounce + * @param edate where to store the found expiration date + * @return #GNUNET_OK on success, #GNUNET_SYSERR upon errors + */ +uint32_t +MERCHANT_DB_get_contract_values (PGconn *conn, + const struct GNUNET_HashCode *h_contract, + uint64_t *nounce, + struct GNUNET_TIME_Absolute *edate); + +#endif /* MERCHANT_DB_H */ + +/** + * Get a set of values representing a contract. This function is meant + * to obsolete the '_get_contract_values' version. + * + * @param h_contract the hashcode of this contract + * @param contract_handle where to store the results + * @raturn #GNUNET_OK in case of success, #GNUNET_SYSERR + * upon errors + */ +uint32_t +MERCHANT_DB_get_contract_handle (PGconn *conn, + const struct GNUNET_HashCode *h_contract, + struct MERCHANT_contract_handle *contract_handle); + +/** + * Store a deposit permission in DB. To be mainly used if /deposit should + * be retried; also, the merchant can benefit from this information in case + * he needs to later investigate about some transaction_id. + * @param conn DB handle + * @param transaction_id identification number of this payment (which is the + * same id of the related contract) + * @param pending if true, this payment got to a persistent state + * @param which mint is to get this deposit permission + * @return #GNUNET_OK if successful, #GNUNET_SYSERR upon errors + */ +uint32_t +MERCHANT_DB_store_deposit_permission (PGconn *conn, + const char *deposit_permission, + uint64_t transaction_id, + unsigned int pending, + const char *mint_url); +/* end of merchant-db.h */ -- cgit v1.2.3