From 9e1c2739664c3b0567449c7103b1e028cda340aa Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Tue, 4 Aug 2015 19:06:35 +0200 Subject: adding contract generation and storing in DB + minor tree adjustment --- src/backend/melted/Makefile.am | 1 + src/backend/melted/copy.sh | 8 +- src/backend/melted/merchant.conf | 18 ++ src/backend/melted/merchant_db.c | 2 +- src/backend/melted/taler-merchant-httpd.c | 364 ++++++++++++++++++++++++++---- src/backend/merchant.c | 173 ++++++++++++++ src/backend/merchant.h | 110 +++++++++ 7 files changed, 626 insertions(+), 50 deletions(-) mode change 100644 => 100755 src/backend/melted/copy.sh create mode 100644 src/backend/melted/merchant.conf create mode 100644 src/backend/merchant.c create mode 100644 src/backend/merchant.h diff --git a/src/backend/melted/Makefile.am b/src/backend/melted/Makefile.am index 14b36e8a..66d784ec 100644 --- a/src/backend/melted/Makefile.am +++ b/src/backend/melted/Makefile.am @@ -50,6 +50,7 @@ taler_merchant_httpd_LDADD = \ -lmicrohttpd \ -ljansson \ -lgnunetutil \ + -ltalermint \ -ltalerpq \ -lgnunetpostgres \ -lpq \ diff --git a/src/backend/melted/copy.sh b/src/backend/melted/copy.sh old mode 100644 new mode 100755 index 6b2fd098..570bf545 --- a/src/backend/melted/copy.sh +++ b/src/backend/melted/copy.sh @@ -1,6 +1,7 @@ #!/bin/bash -# copy all the backend relevant files into the directory given -# as argument. The intended use is to move back and forth those files +# copy all the backend relevant files from the first to the second +# directory given in the arguments. +# The intended use is to move back and forth those files # (since they are git'ed on the merchant's repository) as long as not # configure flag like --enable-merchant will be available from the mint @@ -12,4 +13,5 @@ $1/merchant.c \ $1/merchant_db.c \ $1/merchant_db.h \ $1/merchant.h \ -$1/taler-merchant-httpd.c +$1/taler-merchant-httpd.c \ +$1/merchant.conf diff --git a/src/backend/melted/merchant.conf b/src/backend/melted/merchant.conf new file mode 100644 index 00000000..3b637448 --- /dev/null +++ b/src/backend/melted/merchant.conf @@ -0,0 +1,18 @@ +[merchant] +PORT = 9966 +HOSTNAME = localhost +TRUSTED_MINTS = taler +KEYFILE = merchant.priv + +[mint-taler] +HOSTNAME = demo.taler.net +PORT = 80 +PUBKEY = Q1WVGRGC1F4W7RYC6M23AEGFEXQEHQ730K3GG0B67VPHQSRR75H0 + +[merchant-db] +CONFIG = postgres:///taler + +[wire-sepa] +IBAN = DE67830654080004822650 +NAME = GNUNET E.V +BIC = GENODEF1SRL diff --git a/src/backend/melted/merchant_db.c b/src/backend/melted/merchant_db.c index 66ab5bcf..7a79a12c 100644 --- a/src/backend/melted/merchant_db.c +++ b/src/backend/melted/merchant_db.c @@ -103,7 +103,7 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp) tmp_str); ret = GNUNET_POSTGRES_exec (conn, sql); (void) GNUNET_POSTGRES_exec (conn, - (GNUNET_OK == ret) ? "COMMIT;" : "ROLLBACK"); + (GNUNET_OK == ret) ? "COMMIT;" : "ROLLBACK;"); GNUNET_free (sql); if (GNUNET_OK != ret) return ret; diff --git a/src/backend/melted/taler-merchant-httpd.c b/src/backend/melted/taler-merchant-httpd.c index 336f8915..bfa7904e 100644 --- a/src/backend/melted/taler-merchant-httpd.c +++ b/src/backend/melted/taler-merchant-httpd.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_mhd.h" #include "taler-mint-httpd_admin.h" @@ -46,12 +47,25 @@ TALER_MERCHANT_parse_wireformat_sepa (const struct GNUNET_CONFIGURATION_Handle * if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ } while (0) -// task 1. Just implement a hello world server launched a` la GNUNET +/** + * 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) + +/** + * Our hostname + */ +static char *hostname; /** * The port we are running on */ -unsigned short port; +static long long unsigned port; + +/** + * Merchant's private key + */ +struct GNUNET_CRYPTO_EddsaPrivateKey *privkey; /** * The MHD Daemon @@ -113,6 +127,11 @@ static struct GNUNET_SCHEDULER_Task *shutdown_task; */ static struct MERCHANT_WIREFORMAT_Sepa *wire; +/** + * Hash of the wireformat + */ +static struct GNUNET_HashCode h_wire; + /** * Should we do a dry run where temporary tables are used for storing the data. */ @@ -123,6 +142,74 @@ static int dry; */ static int result; +GNUNET_NETWORK_STRUCT_BEGIN + +struct Contract +{ + /** + * The signature of the merchant for this contract + */ + struct GNUNET_CRYPTO_EddsaSignature sig; + + /** + * Purpose header for the signature over contract + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * The transaction identifier + */ + char m[13]; + + /** + * Expiry time + */ + struct GNUNET_TIME_AbsoluteNBO t; + + /** + * The invoice amount + */ + struct TALER_AmountNBO amount; + + /** + * The hash of the preferred wire format + nounce + */ + struct GNUNET_HashCode h_wire; + + /** + * The contract data + */ + char a[]; +}; + +GNUNET_NETWORK_STRUCT_END + +/** + * Mint context + */ +static struct TALER_MINT_Context *mctx; + +/** + * Context information of the mints we trust + */ +struct Mint +{ + /** + * Public key of this mint + */ + struct GNUNET_CRYPTO_EddsaPublicKey pubkey; + + /** + * Connection handle to this mint + */ + struct TALER_MINT_Handle *conn; +}; + +/** + * Hashmap to store the mint context information + */ +static struct GNUNET_CONTAINER_MultiPeerMap *mints_map; + /** * Return the given message to the other end of connection * @msg (0-terminated) message to show @@ -158,7 +245,7 @@ static unsigned int generate_hello (struct MHD_Response **resp) // this parameter was preceded by a '_' in its original file. Why? { - const char *hello = "Hello customer"; + const char *hello = "Hello customer\n"; unsigned int ret; *resp = MHD_create_response_from_buffer (strlen (hello), (void *) hello, @@ -169,6 +256,26 @@ generate_hello (struct MHD_Response **resp) // this parameter was preceded by a } +/** + * Callback for catching serious error conditions from MHD. + * + * @param cls user specified value + * @param file where the error occured + * @param line where the error occured + * @param reason error detail, may be NULL + */ +static void +mhd_panic_cb (void *cls, + const char *file, + unsigned int line, + const char *reason) +{ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "MHD panicked at %s:%u: %s", + file, line, reason); + result = GNUNET_SYSERR; + GNUNET_SCHEDULER_shutdown (); +} /** * Manage a non 200 HTTP status. I.e. it shows a 'failure' page to @@ -182,7 +289,6 @@ generate_hello (struct MHD_Response **resp) // this parameter was preceded by a static int failure_resp (struct MHD_Connection *connection, unsigned int status) { - printf ("called failure mgmt\n"); static char page_404[]="\ \ Resource not found
\ @@ -251,6 +357,66 @@ hash_wireformat (uint64_t nounce) } + +/* +* Make a binary blob representing a contract, store it into the DB, sign it +* and return a pointer to the signed blob. +* @param a 0-terminated string representing the description of this +* purchase (it should contain a human readable description of the good +* in question) +* @param product some product numerical id. Its indended use is to link this +* good, or service being sold to the original products' DB managed by the frontend +* @price the cost of this good or service +* @return pointer to the allocated contract (which has a field, 'sig', holding +* its own signature), NULL upon errors +*/ + +struct Contract * +generate_and_store_contract (const char *a, uint64_t product, struct TALER_Amount *price) +{ + + struct Contract *contract; + struct GNUNET_TIME_Absolute expiry; + uint64_t nounce; + long long contract_id; + uint64_t contract_id_nbo; + + expiry = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), + GNUNET_TIME_UNIT_DAYS); + ROUND_TO_SECS (expiry, abs_value_us); + nounce = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); + contract_id = MERCHANT_DB_contract_create (db_conn, + expiry, + price, + a, + nounce, + product); + EXITIF (-1 == contract_id); + contract_id_nbo = GNUNET_htonll ((uint64_t) contract_id); + contract = GNUNET_malloc (sizeof (struct Contract) + strlen (a) + 1); + contract->purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT); + contract->purpose.size = htonl (sizeof (struct Contract) + - offsetof (struct Contract, purpose) + + strlen (a) + 1); + GNUNET_STRINGS_data_to_string (&contract_id_nbo, sizeof (contract_id_nbo), + contract->m, sizeof (contract->m)); + contract->t = GNUNET_TIME_absolute_hton (expiry); + (void) strcpy (contract->a, a); + contract->h_wire = hash_wireformat (nounce); + TALER_amount_hton (&contract->amount, price); + GNUNET_CRYPTO_eddsa_sign (privkey, &contract->purpose, &contract->sig); + return contract; + + /* legacy from old merchant */ + EXITIF_exit: + if (NULL != contract) + { + GNUNET_free (contract); + } + return NULL; +} + + /** * A client has requested the given url using the given method * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT, @@ -304,10 +470,18 @@ url_handler (void *cls, unsigned int status; unsigned int no_destroy; + uint64_t prod_id; + struct Contract contract; struct MHD_Response *resp; struct TALER_Amount price; - json_t json_price; + struct GNUNET_CRYPTO_EddsaPublicKey pub; + json_t *json_price; json_t *root; + json_t *contract_enc; + json_t *sig_enc; + json_t *eddsa_pub_enc; + json_t *response; + int res; char *desc; @@ -315,7 +489,7 @@ url_handler (void *cls, #define URL_CONTRACT "/contract" no_destroy = 0; resp = NULL; - status = 500; + status = MHD_HTTP_INTERNAL_SERVER_ERROR; if (0 == strncasecmp (url, URL_HELLO, sizeof (URL_HELLO))) { if (0 == strcmp (MHD_HTTP_METHOD_GET, method)) @@ -333,8 +507,6 @@ url_handler (void *cls, else /* - 1. parse the json - 2. generate the contract 3. pack the contract's json 4. return it */ @@ -346,43 +518,61 @@ url_handler (void *cls, &root); if (GNUNET_SYSERR == res) - return MHD_NO; + /* how to manage? */ if ( (GNUNET_NO == res) || (NULL == root) ) - return MHD_YES; - - /* not really needed for getting just a string. Though it'd be very handy - to enhace the mint's JSON-parsing capabilities with the merchant's needs. - - struct TMH_PARSE_FieldSpecification spec[] = { - TMH_PARSE_member_variable ("desc", (void **) &desc, &desc_len), - TMH_PARSE_member_amount ("price", &price), - TMH_PARSE_MEMBER_END - }; - res = TMH_PARSE_json_data (connection, - root, - spec); */ - /* - - The expected JSON : - - { - "desc" : "some description", - "price" : a JSON compliant TALER_Amount objet - } - - */ - - if (!json_unpack (root, "{s:s, s:o}", "desc", &desc, "price", &json_price)) + /* how to manage? */ + if (!json_unpack (root, "{s:s, s:I, s:o}", + "desc", &desc, + "product", &prod_id, + "price", json_price)) + /* still not possible to return a taler-compliant error message + since this JSON format is not among the taler officials ones */ status = generate_message (&resp, "unable to parse /contract JSON"); else { if (GNUNET_OK != TALER_json_to_amount (&json_price, &price)) + /* still not possible to return a taler-compliant error message + since this JSON format is not among the taler officials ones */ status = generate_message (&resp, "unable to parse `price' field in /contract JSON"); else { - /* Let's generate this contract! */ - /* First, initialize the DB, since it'll be stored there */ - + json_decref (root); + json_decref (json_price); + /* Let's generate this contract! */ + /* First, initialize the DB, since it'll be stored there */ + if (NULL == (contract = generate_and_store_contract (desc, prod_id, &price))) + { + /* status equals 500, so the user will get a "Internal server error" */ + failure_resp (connection, status); + return MHD_YES; + + } + else + { + /* the contract is good and stored in DB, produce now JSON to return. + As of now, the format is {"contract" : base32contract, + "sig" : contractSignature, + "eddsa_pub" : keyToCheckSignatureAgainst + } + + */ + + sig_enc = TALER_json_from_eddsa_sig (contract.purpose, contract.sig); + GNUNET_CRYPTO_eddsa_key_get_public (&privkey, &pub); + eddsa_pub_enc = TALER_json_from_data (pub, sizeof (pub)); + /* cutting of the signature at the beginning */ + contract_enc = TALER_json_from_data (&contract.purpose, sizeof (contract + - offsetof (struct Contract, purpose) + + 1)); + response = json_pack ("{s:o, s:o, s:o}", "contract", contract_enc, "sig", sig_enc, + "eddsa_pub", eddsa_pub_enc); + TMH_RESPONSE_reply_json (connection, response, MHD_HTTP_OK); + /* FRONTIER - CODE ABOVE STILL NOT TESTED */ + + } + + + @@ -404,13 +594,13 @@ url_handler (void *cls, if (!no_destroy) MHD_destroy_response (resp); } - else - EXITIF (GNUNET_OK != failure_resp (connection, status)); + else + EXITIF (GNUNET_OK != failure_resp (connection, status)); return MHD_YES; EXITIF_exit: result = GNUNET_SYSERR; - //GNUNET_SCHEDULER_shutdown (); to a later stage, maybe + GNUNET_SCHEDULER_shutdown (); return MHD_NO; } @@ -431,10 +621,38 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) MHD_stop_daemon (mhd); mhd = NULL; } + + if (NULL != db_conn) + { + MERCHANT_DB_disconnect (db_conn); + db_conn = NULL; + } + } + +/** + * Function called with information about who is auditing + * a particular mint and what key the mint is using. + * + * @param cls closure + * @param keys information about the various keys used + * by the mint + */ +void +keys_mgmt_cb (void *cls, const struct TALER_MINT_Keys *keys) +{ + /* which kind of mint's keys a merchant should need? Sign + keys? It has already the mint's (master?) public key from + the conf file */ + return; + +} + + + /** * Main function that will be run by the scheduler. * @@ -448,14 +666,63 @@ run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { - port = 9966; - - - EXITIF (NULL == (wire = TALER_MERCHANT_parse_wireformat_sepa (config))); - EXITIF (GNUNET_OK != MERCHANT_DB_initialize (db_conn, dry)); + char *keyfile; + unsigned int nmints; + unsigned int cnt; + struct MERCHANT_MintInfo *mint_infos; + void *keys_mgmt_cls; + mint_infos = NULL; + keyfile = NULL; + result = GNUNET_SYSERR; shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); + EXITIF (GNUNET_SYSERR == (nmints = TALER_MERCHANT_parse_mints (config, + &mint_infos))); + EXITIF (NULL == (wire = TALER_MERCHANT_parse_wireformat_sepa (config))); + EXITIF (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (config, + "merchant", + "KEYFILE", + &keyfile)); + EXITIF (NULL == (privkey = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile))); + EXITIF (NULL == (db_conn = MERCHANT_DB_connect (config))); + EXITIF (GNUNET_OK != MERCHANT_DB_initialize (db_conn, GNUNET_NO)); + EXITIF (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_number (config, + "merchant", + "port", + &port)); + EXITIF (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (config, + "merchant", + "hostname", + &hostname)); + + EXITIF (NULL == (mctx = TALER_MINT_init ())); + EXITIF (NULL == (mints_map = GNUNET_CONTAINER_multipeermap_create (nmints, GNUNET_YES))); + + for (cnt = 0; cnt < nmints; cnt++) + { + struct Mint *mint; + + mint = GNUNET_new (struct Mint); + mint->pubkey = mint_infos[cnt].pubkey; + /* port this to the new API */ + mint->conn = TALER_MINT_connect (mctx, + mint_infos[cnt].hostname, + &keys_mgmt_cb, + keys_mgmt_cls); /*<- safe?segfault friendly?*/ + + /* NOTE: the keys mgmt callback should roughly do what the following lines do */ + EXITIF (NULL == mint->conn); + + EXITIF (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put + (mints_map, + (struct GNUNET_PeerIdentity *) /* to retrieve now from cb's args -> */&mint->pubkey, + mint, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); + } + mhd = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, port, @@ -465,12 +732,17 @@ run (void *cls, char *const *args, const char *cfgfile, EXITIF (NULL == mhd); + /* WARNING: a 'poll_mhd ()' call is here in the original merchant. Is that + mandatory ? */ + GNUNET_CRYPTO_hash (wire, sizeof (*wire), &h_wire); result = GNUNET_OK; EXITIF_exit: if (GNUNET_OK != result) GNUNET_SCHEDULER_shutdown (); - + GNUNET_free_non_null (keyfile); + if (GNUNET_OK != result) + GNUNET_SCHEDULER_shutdown (); } diff --git a/src/backend/merchant.c b/src/backend/merchant.c new file mode 100644 index 00000000..f124a030 --- /dev/null +++ b/src/backend/merchant.c @@ -0,0 +1,173 @@ +/* + 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.c + * @brief Common utility functions for merchant + * @author Sree Harsha Totakura + */ + +#include "platform.h" +#include +#include "merchant.h" + + +#define EXITIF(cond) \ + do { \ + if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ + } 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_MintInfo **mints) +{ + char *mints_str; + char *token_nf; /* do no free (nf) */ + char *mint_section; + char *mint_hostname; + char *mint_pubkey_enc; + struct MERCHANT_MintInfo *r_mints; + struct MERCHANT_MintInfo mint; + unsigned long long mint_port; + unsigned int cnt; + int OK; + + OK = 0; + mints_str = NULL; + token_nf = NULL; + mint_section = NULL; + mint_hostname = NULL; + mint_pubkey_enc = 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)); + EXITIF (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + mint_section, + "PORT", + &mint_port)); + EXITIF (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + mint_section, + "PUBKEY", + &mint_pubkey_enc)); + EXITIF (GNUNET_OK != + GNUNET_CRYPTO_eddsa_public_key_from_string (mint_pubkey_enc, + strlen (mint_pubkey_enc), + &mint.pubkey)); + mint.hostname = mint_hostname; + mint.port = (uint16_t) mint_port; + GNUNET_array_append (r_mints, cnt, mint); + mint_hostname = NULL; + GNUNET_free (mint_pubkey_enc); + mint_pubkey_enc = 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); + GNUNET_free_non_null (mint_pubkey_enc); + if (!OK) + { + GNUNET_free_non_null (r_mints); + return GNUNET_SYSERR; + } + + *mints = r_mints; + 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/merchant.h b/src/backend/merchant.h new file mode 100644 index 00000000..c66131ed --- /dev/null +++ b/src/backend/merchant.h @@ -0,0 +1,110 @@ +/* + 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.c + * @brief Common utility functions for merchant + * @author Sree Harsha Totakura + */ + +#ifndef MERCHANT_H +#define MERCHANT_H + +#include +#include + +/** + * A mint + */ +struct MERCHANT_MintInfo { + /** + * Hostname + */ + char *hostname; + + /** + * The public key of the mint + */ + struct GNUNET_CRYPTO_EddsaPublicKey pubkey; + + /** + * The port where the mint's service is running + */ + uint16_t port; + +}; + + +/** + * 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_MintInfo **mints); + + +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 */ -- cgit v1.2.3