commit 5453309a27e2d3621225ac10785707b02459b51e
parent e84d5dc451ad9fe214a3014457a1cf0c0e504e9a
Author: Marcello Stanisci <marcello.stanisci@inria.fr>
Date: Wed, 23 Sep 2015 10:21:05 +0200
adding column hash(a) in contracts table, plus
a few cleanings on the JSON manipulations.
Diffstat:
15 files changed, 306 insertions(+), 1027 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
@@ -1,2 +1,2 @@
AM_CPPFLAGS = -I$(top_srcdir)/src/include
-SUBDIRS = include backend-lib backend
+SUBDIRS = include backend-lib backend tests
diff --git a/src/backend-lib/merchant_db.c b/src/backend-lib/merchant_db.c
@@ -88,6 +88,7 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp)
"BEGIN TRANSACTION;"
"CREATE %1$s TABLE IF NOT EXISTS contracts ("
"contract_id INT8 PRIMARY KEY,"
+ "hash BYTEA NOT NULL,"
"amount INT8 NOT NULL,"
"amount_fraction INT4 NOT NULL,"
"amount_currency VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL,"
@@ -119,10 +120,10 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp)
(conn,
"contract_create",
"INSERT INTO contracts"
- "(contract_id, amount, amount_fraction, amount_currency,"
+ "(contract_id, hash, amount, amount_fraction, amount_currency,"
"description, nounce, expiry, product) VALUES"
- "($1, $2, $3, $4, $5, $6, $7, $8)",
- 8, NULL)));
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9)",
+ 9, NULL)));
EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
PQclear (res);
@@ -189,6 +190,7 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp)
* @param conn the database connection
* @param expiry the time when the contract will expire
* @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
@@ -200,6 +202,7 @@ uint32_t
MERCHANT_DB_contract_create (PGconn *conn,
const struct GNUNET_TIME_Absolute *expiry,
const struct TALER_Amount *amount,
+ const struct GNUNET_HashCode *h_contract,
uint64_t c_id,
const char *desc,
uint64_t nounce,
@@ -214,26 +217,16 @@ MERCHANT_DB_contract_create (PGconn *conn,
#endif
ExecStatusType status;
- #if 0
- /*
- NOTE: the conversion to nl(l) happens *inside* the query param helpers; since
- the policy imposes this format for storing values. */
- value_nbo = GNUNET_htonll (amount->value);
- fraction_nbo = GNUNET_htonll (amount->fraction);
- nounce_nbo = GNUNET_htonll (nounce);
- expiry_ms_nbo = GNUNET_htonll (expiry.abs_value_us);
- product = GNUNET_htonll (product);
- #endif
-
/* ported. To be tested/compiled */
struct TALER_PQ_QueryParam params[] = {
TALER_PQ_query_param_uint64 (&c_id),
+ TALER_PQ_query_param_fixed_size (h_contract, sizeof (struct GNUNET_HashCode)),
TALER_PQ_query_param_amount (amount),
/* a *string* is being put in the following statement,
though the API talks about a *blob*. Will this be liked by
the DB ? */
// the following inserts a string as a blob. Will Taler provide a param-from-string helper?
- TALER_PQ_query_param_fixed_size (desc, strlen(desc)),
+ TALER_PQ_query_param_fixed_size (desc, strlen (desc)),
TALER_PQ_query_param_uint64 (&nounce),
TALER_PQ_query_param_absolute_time (expiry),
TALER_PQ_query_param_uint64 (&product),
diff --git a/src/backend-lib/merchant_db.h b/src/backend-lib/merchant_db.h
@@ -64,6 +64,7 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp);
* @param conn the database connection
* @param expiry the time when the contract will expire
* @param amount the taler amount corresponding to the contract
+ * @param hash of the stringified JSON corresponding to this contract
* @param c_id this contract's identification number
* @param desc descripition of the contract
* @param nounce a random 64-bit nounce
@@ -75,6 +76,7 @@ uint32_t
MERCHANT_DB_contract_create (PGconn *conn,
const struct GNUNET_TIME_Absolute *expiry,
const struct TALER_Amount *amount,
+ const struct GNUNET_HashCode *h_contract,
uint64_t c_id,
const char *desc,
uint64_t nounce,
diff --git a/src/backend-lib/taler-merchant-httpd_contract.c b/src/backend-lib/taler-merchant-httpd_contract.c
@@ -50,26 +50,27 @@ hash_wireformat (uint64_t nounce, const struct MERCHANT_WIREFORMAT_Sepa *wire)
/**
* Take from the frontend the (partly) generated contract and fill
-* the missing values in it; for example, the SEPA-aware values.
+* the missing values in it; for example, the SEPA details.
* Moreover, it stores the contract in the DB.
-* @param j_contract parsed contract, originated by the frontend
+* @param j_contract parsed contract, originated by the frontend. It will be
+* hold the new values.
* @param db_conn the handle to the local DB
* @param wire merchant's bank's details
-* @param where to store the (subset of the) contract to be (still) signed
-* @return pointer to the complete JSON; NULL upon errors
+* @param contract where to store the (subset of the) contract to be (still) signed
+* @return GNUNET_OK on success; GNUNET_SYSERR upon errors
*/
/**
-* TODO: inspection of reference counting and, accordingly, free those json_t*(s)
+* TODO: inspect reference counting and, accordingly, free those json_t*(s)
* still allocated */
-json_t *
+uint32_t
MERCHANT_handle_contract (json_t *j_contract,
PGconn *db_conn,
const struct MERCHANT_WIREFORMAT_Sepa *wire,
struct Contract *contract)
{
- json_t *root;
+ json_t *j_tmp;
json_t *j_details;
json_t *j_timestamp;
json_t *jh_wire;
@@ -82,7 +83,7 @@ MERCHANT_handle_contract (json_t *j_contract,
json_t *j_product_id;
json_t *j_items_tmp;
char *a;
- char *h_wire_enc;
+ #define DaEBUG
#ifdef DEBUG
char *str;
#endif
@@ -97,54 +98,53 @@ MERCHANT_handle_contract (json_t *j_contract,
GNUNET_TIME_UNIT_DAYS);
ROUND_TO_SECS (timestamp, abs_value_us);
j_timestamp = TALER_json_from_abs (timestamp);
-
// wireformat mgmt
h_wire = hash_wireformat (nounce, wire);
- h_wire_enc = GNUNET_STRINGS_data_to_string_alloc (&h_wire,
- sizeof (struct GNUNET_HashCode));
- jh_wire = json_string (h_wire_enc);
- if (-1 == json_unpack (j_contract, "{s:o, s:o, s:I, s:o, s:o}",
- "amount", &j_amount,
- "max fee", &j_max_fee,
- "trans_id", &j_trans_id,
- "mints", &j_mints,
- "details", &j_details))
-
- return NULL;
-
- /* needed for DB stuff */
- TALER_json_to_amount (j_amount, &amount);
- j_items_tmp = json_object_get (j_details, "items");
- j_product_id = json_object_get (j_items_tmp, "product_id");
+ jh_wire = TALER_json_from_data (&h_wire, sizeof (struct GNUNET_HashCode));
+ /* adding the generated values in this JSON */
+ if (NULL == (j_tmp = json_pack ("{s:o, s:o}",
+ "h_wire", jh_wire,
+ "timestamp", j_timestamp)))
+ return GNUNET_SYSERR;
+
+ if (-1 == json_object_update (j_contract, j_tmp))
+ return GNUNET_SYSERR;
+ /* needed for DB work */
+ j_amount = json_object_get (j_contract, "amount");
+ TALER_json_to_amount (j_amount, &amount); // produces a WARNING..
+
+ a = json_dumps (j_contract, JSON_COMPACT | JSON_PRESERVE_ORDER);
#ifdef DEBUG
- printf ("prod id is at %p, eval to %d\n", j_product_id, json_integer_value (j_product_id));
- return NULL;
+ str = json_dumps (j_amount, JSON_COMPACT | JSON_PRESERVE_ORDER);
+ printf ("amount : \n%s", str);
+ return GNUNET_SYSERR;
#endif
+ /* TODO
+ Add a further field to the 'contract' table, indicating the timestamp
+ of this contract being finalized
+ */
- /* adding the generated values in this JSON */
- root = json_pack ("{s:o, s:o, s:I, s:s, s:o, s:o, s:o}",
- "amount", j_amount,
- "max fee", j_max_fee,
- "trans_id", j_trans_id,
- "h_wire", jh_wire,
- "timestamp", j_timestamp,
- "mints", j_mints,
- "details", j_details);
-
- a = json_dumps (root, JSON_COMPACT | JSON_PRESERVE_ORDER);
+ GNUNET_CRYPTO_hash (a, strlen (a) + 1, &contract->h_contract_details);
+ contract->purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
+ contract->purpose.size = htonl (sizeof (struct Contract));
// DB mgmt
if (GNUNET_SYSERR == MERCHANT_DB_contract_create (db_conn,
×tamp,
&amount,
+ &contract->h_contract_details,
(uint64_t) j_trans_id, // safe?
a,
nounce,
- json_integer_value (j_product_id)));
+ json_integer_value (j_product_id)))
+ return GNUNET_SYSERR;
+
+ free (a);
+
#ifdef OBSOLETE
contract->h_wire = h_wire;
TALER_amount_hton (&amount_nbo, &amount);
@@ -153,15 +153,9 @@ MERCHANT_handle_contract (json_t *j_contract,
contract->m = GNUNET_htonll ((uint64_t) j_trans_id); // safe?
#endif
- GNUNET_CRYPTO_hash (a, strlen (a) + 1, &contract->h_contract_details);
- free (a);
- contract->purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
-
#ifdef OBSOLETE
contract->purpose.size = htonl (sizeof (struct ContractNBO));
#endif
- contract->purpose.size = htonl (sizeof (struct Contract));
-
- return root;
+ return GNUNET_OK;
}
diff --git a/src/backend-lib/taler_merchant_contract_lib.h b/src/backend-lib/taler_merchant_contract_lib.h
@@ -66,13 +66,14 @@ GNUNET_NETWORK_STRUCT_END
* @param kpriv merchant's private key
* @param wire merchant's bank's details
* @param sig where to store the signature
-* @return pointer to the complete JSON; NULL upon errors
+* @return GNUNET_OK if successful, GNUNET_SYSERR upon errors
+*
*/
/* TODO: this handles a simplified version (for debugging purposes)
of the contract. To expand to the full fledged version */
-json_t *
+uint32_t
MERCHANT_handle_contract (json_t *j_contract,
PGconn *db_conn,
const struct MERCHANT_WIREFORMAT_Sepa *wire,
diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am
@@ -7,7 +7,7 @@ bin_PROGRAMS = \
taler_merchant_httpd_SOURCES = \
taler-merchant-httpd.c \
merchant.c merchant.h \
- merchant_db.c merchant_db.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 \
../backend-lib/taler-merchant-httpd_contract.h
@@ -17,6 +17,7 @@ taler_merchant_httpd_LDADD = \
-ltalerutil \
-lmicrohttpd \
-ljansson \
+ -lcurl \
-lgnunetutil \
$(top_srcdir)/src/backend-lib/libtalermerchant.la \
-ltalermint \
diff --git a/src/backend/merchant_db.c b/src/backend/merchant_db.c
@@ -1,354 +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 <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file merchant/merchant_db.c
- * @brief database helper functions used by the merchant
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- */
-
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <taler/taler_util.h>
-#include <taler/taler_pq_lib.h>
-#include "merchant_db.h"
-
-
-#define PQSQL_strerror(kind, cmd, res) \
- GNUNET_log_from (kind, "merchant-db", \
- "SQL %s failed at %s:%u with error: %s", \
- cmd, __FILE__, __LINE__, PQresultErrorMessage (res));
-
-/**
- * Shorthand for exit jumps.
- */
-#define EXITIF(cond) \
- do { \
- if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
- } while (0)
-
-
-/**
- * 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)
-{
- return GNUNET_POSTGRES_connect (cfg, "merchant-db");
-}
-
-
-/**
- * Disconnect from the database
- *
- * @param conn database handle to close
- */
-void
-MERCHANT_DB_disconnect (PGconn *conn)
-{
- PQfinish (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)
-{
- const char *tmp_str = (1 == tmp) ? "TEMPORARY" : "";
- char *sql;
- PGresult *res;
- ExecStatusType status;
- int ret;
-
- res = NULL;
- (void) GNUNET_asprintf (&sql,
- "BEGIN TRANSACTION;"
- "CREATE %1$s TABLE IF NOT EXISTS contracts ("
- "contract_id INT8 PRIMARY KEY,"
- "amount INT8 NOT NULL,"
- "amount_fraction INT4 NOT NULL,"
- "amount_currency VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL,"
- "description TEXT NOT NULL,"
- "nounce INT8 NOT NULL,"
- "expiry INT8 NOT NULL,"
- "product INT8 NOT NULL);"
- "CREATE %1$s TABLE IF NOT EXISTS checkouts ("
- "coin_pub BYTEA PRIMARY KEY,"
- "contract_id INT8 REFERENCES contracts(contract_id),"
- "amount INT4 NOT NULL,"
- "amount_fraction INT4 NOT NULL,"
- "coin_sig BYTEA NOT NULL);",
- tmp_str);
- ret = GNUNET_POSTGRES_exec (conn, sql);
- (void) GNUNET_POSTGRES_exec (conn,
- (GNUNET_OK == ret) ? "COMMIT;" : "ROLLBACK;");
- GNUNET_free (sql);
- if (GNUNET_OK != ret)
- return ret;
-
- while (NULL != (res = PQgetResult (conn)))
- {
- status = PQresultStatus (res);
- PQclear (res);
- }
-
- EXITIF (NULL == (res = PQprepare
- (conn,
- "contract_create",
- "INSERT INTO contracts"
- "(contract_id, amount, amount_fraction, amount_currency,"
- "description, nounce, expiry, product) VALUES"
- "($1, $2, $3, $4, $5, $6, $7, $8)",
- 8, NULL)));
- EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
- PQclear (res);
-
- EXITIF (NULL == (res = PQprepare
- (conn,
- "get_contract_product",
- "SELECT ("
- "product"
- ") FROM contracts "
- "WHERE ("
- "contract_id=$1"
- ")",
- 1, NULL)));
- EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
- PQclear (res);
-
- EXITIF (NULL == (res = PQprepare
- (conn,
- "checkout_create",
- "INSERT INTO checkouts ("
- "coin_pub,"
- "contract_id,"
- "amount,"
- "amount_fraction,"
- "coin_sig"
- ") VALUES ("
- "$1, $2, $3, $4, $5"
- ")",
- 5, NULL)));
- EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus (res)));
- PQclear (res);
-
- EXITIF (NULL == (res = PQprepare
- (conn,
- "get_checkout_product",
- "SELECT ("
- "product"
- ") FROM contracts "
- "WHERE "
- "contract_id IN ("
- "SELECT (contract_id) FROM checkouts "
- "WHERE coin_pub=$1"
- ")",
- 1, NULL)));
- EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus (res)));
- PQclear (res);
-
- return GNUNET_OK;
-
- EXITIF_exit:
- if (NULL != res)
- {
- PQSQL_strerror (GNUNET_ERROR_TYPE_ERROR, "PQprepare", res);
- PQclear (res);
- }
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Inserts a contract record into the database and if successfull returns the
- * serial number of the inserted row.
- *
- * @param conn the database connection
- * @param expiry the time when the contract will expire
- * @param amount the taler amount corresponding to the 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 *expiry,
- const struct TALER_Amount *amount,
- uint64_t c_id,
- const char *desc,
- uint64_t nounce,
- uint64_t product)
-{
- PGresult *res;
- #if 0
- uint64_t expiry_ms_nbo;
- uint64_t value_nbo;
- uint32_t fraction_nbo;
- uint64_t nounce_nbo;
- #endif
- ExecStatusType status;
-
- #if 0
- /*
- NOTE: the conversion to nl(l) happens *inside* the query param helpers; since
- the policy imposes this format for storing values. */
- value_nbo = GNUNET_htonll (amount->value);
- fraction_nbo = GNUNET_htonll (amount->fraction);
- nounce_nbo = GNUNET_htonll (nounce);
- expiry_ms_nbo = GNUNET_htonll (expiry.abs_value_us);
- product = GNUNET_htonll (product);
- #endif
-
- /* ported. To be tested/compiled */
- struct TALER_PQ_QueryParam params[] = {
- TALER_PQ_query_param_uint64 (&c_id),
- TALER_PQ_query_param_amount (amount),
- /* a *string* is being put in the following statement,
- though the API talks about a *blob*. Will this be liked by
- the DB ? */
- // the following inserts a string as a blob. Will Taler provide a param-from-string helper?
- TALER_PQ_query_param_fixed_size (desc, strlen(desc)),
- TALER_PQ_query_param_uint64 (&nounce),
- TALER_PQ_query_param_absolute_time (expiry),
- 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);
- EXITIF (PGRES_COMMAND_OK != status);
- PQclear (res);
- return GNUNET_OK;
-
- EXITIF_exit:
- PQclear (res);
- return GNUNET_SYSERR;
-}
-
-long long
-MERCHANT_DB_get_contract_product (PGconn *conn,
- uint64_t contract_id)
-{
- PGresult *res;
- uint64_t product;
- ExecStatusType status;
- struct TALER_PQ_QueryParam params[] = {
- TALER_PQ_query_param_uint64 (&contract_id),
- TALER_PQ_query_param_end
- };
- struct TALER_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_uint64 ("product", &product),
- TALER_PQ_result_spec_end
- };
-
- contract_id = GNUNET_htonll (contract_id);
- res = TALER_PQ_exec_prepared (conn, "get_contract_product", params);
- status = PQresultStatus (res);
- EXITIF (PGRES_TUPLES_OK != status);
- EXITIF (1 != PQntuples (res));
- EXITIF (GNUNET_YES != TALER_PQ_extract_result (res, rs, 0));
- PQclear (res);
- return GNUNET_ntohll ((uint64_t) product);
-
- EXITIF_exit:
- PQclear (res);
- return -1;
-}
-
-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)
-{
- PGresult *res;
- ExecStatusType status;
- uint32_t value_nbo;
- uint32_t fraction_nbo;
- struct TALER_PQ_QueryParam params[] = {
- TALER_PQ_query_param_rsa_public_key (coin_pub),
- TALER_PQ_query_param_uint64 (&transaction_id),
- TALER_PQ_query_param_uint32 (&value_nbo),
- TALER_PQ_query_param_uint32 (&fraction_nbo),
- TALER_PQ_query_param_rsa_signature (coin_sig),
- TALER_PQ_query_param_end
- };
-
- transaction_id = GNUNET_htonll (transaction_id);
- value_nbo = htonl (amount->value);
- fraction_nbo = htonl (amount->fraction);
- res = TALER_PQ_exec_prepared (conn, "checkout_create", params);
- status = PQresultStatus (res);
- EXITIF (PGRES_COMMAND_OK != status);
- PQclear (res);
- return GNUNET_OK;
-
- EXITIF_exit:
- PQclear (res);
- return GNUNET_SYSERR;
-}
-
-
-long long
-MERCHANT_DB_get_checkout_product (PGconn *conn,
- struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub)
-{
- PGresult *res;
- ExecStatusType status;
- uint64_t product;
- struct TALER_PQ_QueryParam params[] = {
- TALER_PQ_query_param_rsa_public_key (coin_pub),
- TALER_PQ_query_param_end
- };
- struct TALER_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_uint64 ("product", &product),
- TALER_PQ_result_spec_end
- };
-
- product = -1;
- res = TALER_PQ_exec_prepared (conn, "get_checkout_product", params);
- status = PQresultStatus (res);
- EXITIF (PGRES_TUPLES_OK != status);
- if (0 == PQntuples (res))
- {
- TALER_LOG_DEBUG ("Checkout not found for given coin");
- goto EXITIF_exit;
- }
- EXITIF (1 != PQntuples (res));
- EXITIF (GNUNET_YES != TALER_PQ_extract_result (res, rs, 0));
- PQclear (res);
- return GNUNET_ntohll ((uint64_t) product);
-
- EXITIF_exit:
- PQclear (res);
- return -1;
-}
-/* end of merchant-db.c */
diff --git a/src/backend/merchant_db.h b/src/backend/merchant_db.h
@@ -1,101 +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 <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file merchant/merchant_db.h
- * @brief database helper functions used by the merchant
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- */
-
-#ifndef MERCHANT_DB_H
-#define MERCHANT_DB_H
-
-#include <gnunet/gnunet_postgres_lib.h>
-#include <taler/taler_util.h>
-
-/**
- * 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 expiry the time when the contract will expire
- * @param amount the taler amount corresponding to the contract
- * @param c_id this contract's identification number
- * @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 *expiry,
- const struct TALER_Amount *amount,
- 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);
-
-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);
-
-#endif /* MERCHANT_DB_H */
-
-/* end of merchant-db.h */
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
@@ -24,6 +24,7 @@
#include <microhttpd.h>
#include <jansson.h>
#include <gnunet/gnunet_util_lib.h>
+#include <curl/curl.h>
#include <taler/taler_json_lib.h>
#include <taler/taler_mint_service.h>
#include "taler-mint-httpd_parsing.h"
@@ -151,7 +152,7 @@ unsigned int nmints;
*/
static unsigned int
-generate_message (struct MHD_Response **resp, const char *msg) // this parameter was preceded by a '_' in its original file. Why?
+generate_message (struct MHD_Response **resp, const char *msg)
{
unsigned int ret;
@@ -281,6 +282,38 @@ request</h3></center></body></html>";
return GNUNET_SYSERR;
}
+/**
+ * Take the global wire details and return a JSON containing them,
+ * compliantly with the Taler's API.
+ * @param edate when the beneficiary wants this transfer to take place
+ * @return JSON representation of the wire details, NULL upon errors
+ */
+
+static json_t *
+get_wire_json (struct GNUNET_TIME_Absolute edate)
+{
+
+ json_t *root;
+ json_t *j_edate;
+ json_t *j_nounce;
+ uint64_t nounce;
+
+ nounce = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+ j_nounce = json_integer (nounce);
+
+ j_edate = TALER_json_from_abs (edate);
+ if (NULL == (root = json_pack ("{s:s, s:s, s:s, s:s, s:o}",
+ "type", "SEPA",
+ "IBAN", wire->iban,
+ "name", wire->name,
+ "BIC", wire->bic,
+ "edate", j_edate,
+ "r", json_integer_value (j_nounce))))
+ return NULL;
+
+ return root;
+}
+
/**
* A client has requested the given url using the given method
@@ -344,27 +377,46 @@ url_handler (void *cls,
struct Contract contract;
#endif
struct MHD_Response *resp;
- json_t *j_contract_complete;
json_t *root;
+ json_t *j_contract_complete;
json_t *j_sig_enc;
json_t *eddsa_pub_enc;
json_t *response;
json_t *j_mints;
json_t *j_mint;
+ json_t *j_wire;
int cnt; /* loop counter */
char *str; /* to debug JSONs */
- #if 1
+ char *deposit_body;
json_t *root_tmp;
+ json_t *j_refund_deadline;
json_t *j_amount_tmp;
+ json_t *j_depperm;
json_t *j_details_tmp;
json_t *j_max_fee_tmp;
- json_int_t j_trans_id_tmp;
- #endif
+ json_int_t j_int_trans_id_tmp;
+ json_t *j_trans_id_tmp;
+ int64_t trans_id_tmp;
+ char *ub_sig;
+ char *coin_pub;
+ char *denom_key;
+ char *contract_sig;
+ char *h_contract;
+ struct GNUNET_HashCode h_json_wire;
+ struct TALER_Amount amount_tmp;
+ json_t *j_h_json_wire;
+ struct curl_slist *slist;
+
+ struct GNUNET_TIME_Absolute now;
+
+ CURL *curl;
+ CURLcode curl_res;
int res = GNUNET_SYSERR;
#define URL_HELLO "/hello"
#define URL_CONTRACT "/contract"
+ #define URL_DEPPERM "/pay"
no_destroy = 0;
resp = NULL;
status = MHD_HTTP_INTERNAL_SERVER_ERROR;
@@ -379,6 +431,172 @@ url_handler (void *cls,
}
}
+ if (0 == strncasecmp (url, URL_DEPPERM, sizeof (URL_DEPPERM)))
+ {
+ if (0 == strcmp (MHD_HTTP_METHOD_GET, method))
+ {
+ status = MHD_HTTP_METHOD_NOT_ALLOWED;
+ goto end;
+
+ }
+ else
+ res = TMH_PARSE_post_json (connection,
+ connection_cls,
+ upload_data,
+ upload_data_size,
+ &root);
+ if (GNUNET_SYSERR == res)
+ {
+ status = MHD_HTTP_BAD_REQUEST;
+ goto end;
+ }
+
+ /* the POST's body has to be fetched furthermore */
+ if ((GNUNET_NO == res) || (NULL == root))
+ return MHD_YES;
+
+ /* The frontend should supply a JSON in the format described in
+ http://link-to-specs : .. In practice, it just forwards what it
+ received from the wallet.
+
+ Roughly, the backend must add to this JSON:
+
+ 1. The merchant's public key
+ 2. A timestamp (?)
+ 3. wire (see mint's specs)
+ 4. h_wire
+ 5. refund deadline (?)
+
+ (?) : may the frontend will handle dates ?
+
+ */
+
+ #ifdef DEBUG
+ /* NOTE: there is no need to thoroughly unpack this JSON, since
+ the backend must just *add* fields to it */
+ if (-1 == (json_unpack (root,
+ "{s:s, s:I, s:s, s:s, s:s}",
+ "ub_sig", &ub_sig,
+ "coin_pub", &coin_pub,
+ "denom_pub", &denom_key,
+ "H_contract", &h_contract,
+ "sig", &contract_sig)))
+ {
+ printf ("no unpack\n");
+ status = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ goto end;
+ }
+
+ printf ("Got this deposit permission:\nub_sig: %s\ncoin_pub: %s\ndenom_key: %s\nsig: %s\n",
+ ub_sig, coin_pub, denom_key, contract_sig);
+
+ return MHD_NO;
+ #endif
+
+ /* TODO: Check if there is a row in 'contracts' table corresponding to this
+ contract ('s hash). This query has to return the trans_id and the amount for
+ this contract - faked values for now. See bug #XXXX */
+
+ /* FIXME fake trans_id */
+ trans_id_tmp = (int64_t) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+
+ if (trans_id_tmp < 0)
+ j_trans_id_tmp = json_integer ((-1) * trans_id_tmp);
+ else
+ j_trans_id_tmp = json_integer (trans_id_tmp);
+
+ /* FIXME fake amount to redeem */
+ TALER_amount_get_zero ("EUR", &amount_tmp);
+ amount_tmp.value = 5;
+ j_amount_tmp = TALER_json_from_amount (&amount_tmp);
+
+ /* Encoding merchant's key */
+ GNUNET_CRYPTO_eddsa_key_get_public (privkey, &pub);
+ eddsa_pub_enc = TALER_json_from_data ((void *) &pub, sizeof (pub));
+
+ /* Timestamping 'now' */
+ now = GNUNET_TIME_absolute_get ();
+
+ /* getting the SEPA-aware JSON */
+ if (NULL == (j_wire = get_wire_json (GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_WEEKS))))
+ goto end;
+
+ /* hash it*/
+ if (GNUNET_SYSERR == TALER_hash_json (j_wire, &h_json_wire))
+ goto end;
+
+ j_h_json_wire = TALER_json_from_data (&h_json_wire, sizeof (struct GNUNET_HashCode));
+ /* refund deadline */
+ j_refund_deadline = TALER_json_from_abs (GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_WEEKS));
+
+ /* pack it!*/
+ eddsa_pub_enc = TALER_json_from_data ((void *) &pub, sizeof (pub));
+
+ if (NULL == (j_depperm = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:I, s:o}",
+ "merchant_pub", eddsa_pub_enc,
+ "timestamp", TALER_json_from_abs (now),
+ "wire", j_wire,
+ "H_wire", j_h_json_wire,
+ "refund_deadline", j_refund_deadline,
+ "transaction_id", json_integer_value (j_trans_id_tmp),
+ "f", j_amount_tmp)))
+ {
+ printf ("BAD depperm packaging\n");
+ goto end;
+ }
+
+
+ /* melt to what received from the wallet */
+ if (-1 == json_object_update (j_depperm, root))
+ {
+ printf ("depperm response not built\n");
+ goto end;
+ }
+
+ #define DEBUGG
+ #ifdef DEBUG
+ str = json_dumps (j_depperm, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
+ printf ("Depperm is: \n%s", str);
+ return MHD_NO;
+ #endif
+
+ /* POST to mint's "/deposit" */
+ curl = curl_easy_init ();
+
+ if (curl)
+ {
+
+ slist = curl_slist_append (slist, "Content-type: application/json");
+ curl_easy_setopt (curl, CURLOPT_HTTPHEADER, slist);
+
+ /* FIXME the mint's URL is be retrieved from the partial deposit permission
+ (received by the wallet) */
+ curl_easy_setopt (curl, CURLOPT_URL, "http://demo.taler.net/deposit");
+
+ /* NOTE: hopefully, this string won't need any URL-encoding, since as for the
+ Jansson specs, any space and-or newline are not in place using JSON_COMPACT
+ flag */
+ deposit_body = json_dumps (j_depperm, JSON_COMPACT | JSON_PRESERVE_ORDER);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, deposit_body);
+
+ curl_res = curl_easy_perform (curl);
+
+ curl_slist_free_all(slist);
+ if(curl_res != CURLE_OK)
+ {
+ printf ("deposit rejected by mint\n");
+ goto end;
+ }
+ else
+ printf ("deposit ok\n");
+
+ curl_easy_cleanup(curl);
+
+
+ }
+
+ }
+
/*
* To be called by the frontend passing the contract with some "holes"
* which will be completed, stored in DB, signed, and returned
@@ -431,32 +649,14 @@ url_handler (void *cls,
}
- if (-1 == (json_unpack (root,
- "{s:o, s:o, s:I, s:o}",
- "amount", &j_amount_tmp,
- "max fee", &j_max_fee_tmp,
- "trans_id", &j_trans_id_tmp,
- "details", &j_details_tmp)))
+ if (-1 == (json_object_update (root, j_mints)))
{
- printf ("no unpack\n");
- status = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ printf ("no mints specified in contract\n");
goto end;
- }
-
- if (NULL == (root_tmp = json_pack ("{s:o, s:o, s:I, s:o, s:o}",
- "amount", j_amount_tmp,
- "max fee", j_max_fee_tmp,
- "trans_id", j_trans_id_tmp,
- "mints", j_mints,
- "details", j_details_tmp)))
- {
- printf ("no pack\n");
- status = MHD_HTTP_INTERNAL_SERVER_ERROR;
- goto end;
- }
- if (NULL == (j_contract_complete = MERCHANT_handle_contract (root_tmp,
+ }
+ if (NULL == (j_contract_complete = MERCHANT_handle_contract (root,
db_conn,
wire,
&contract)))
@@ -540,8 +740,6 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
}
-
-
/**
* Function called with information about who is auditing
* a particular mint and what key the mint is using.
@@ -550,7 +748,7 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
* @param keys information about the various keys used
* by the mint
*/
-void
+static void
keys_mgmt_cb (void *cls, const struct TALER_MINT_Keys *keys)
{
/* which kind of mint's keys a merchant should need? Sign
@@ -569,7 +767,7 @@ keys_mgmt_cb (void *cls, const struct TALER_MINT_Keys *keys)
* @param cfgfile name of the configuration file used (for saving, can be NULL!)
* @param config configuration
*/
-static void
+void
run (void *cls, char *const *args, const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *config)
{
@@ -592,7 +790,7 @@ run (void *cls, char *const *args, const char *cfgfile,
&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_OK != MERCHANT_DB_initialize (db_conn, GNUNET_YES));
EXITIF (GNUNET_SYSERR ==
GNUNET_CONFIGURATION_get_value_number (config,
"merchant",
@@ -661,7 +859,7 @@ 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},
@@ -677,6 +875,4 @@ main (int argc, char *const *argv)
return 3;
return (GNUNET_OK == result) ? 0 : 1;
-
-
}
diff --git a/src/frontend/fake_wire_transfer.php b/src/frontend/fake_wire_transfer.php
@@ -48,7 +48,7 @@ $json = json_encode (array ('reserve_pub' => $reserve_pk,
'wire' => array ('type' => 'test'),
'amount' => array ('value' => intval($kudos_amount),
'fraction' => 0,
- 'currency' => 'KUDOS')));
+ 'currency' => 'EUR'))); // TODO 'KUDOS' example needs 'KUDOS' denom keys ..
// craft the HTTP request
$req = new http\Client\Request ("POST",
diff --git a/src/frontend/generate_taler_contract.php b/src/frontend/generate_taler_contract.php
@@ -69,7 +69,7 @@ $value = $amount;
// We don't have a fraction.
$fraction = 0;
// This is our 'toy' currency
-$currency = "KUDOS";
+$currency = "EUR"; // NOTE: mint does NOT generate KUDOS denom. keys
// The tax for this deal
$teatax = array ('value' => 1,
'fraction' => 0,
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
@@ -1,5 +1,5 @@
# This Makefile.am is in the public domain
-AM_CPPFLAGS = -I$(top_srcdir)/src/include
+AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/backend-lib/
bin_PROGRAMS = \
merchant-contract-test
@@ -10,7 +10,7 @@ bin_PROGRAMS = \
merchant_contract_test_SOURCES = \
merchant-contract-test.c \
merchant.c \
- merchant_db.c merchant_db.h
+ ../backend-lib/merchant_db.c ../backend-lib/merchant_db.h
merchant_contract_test_LDADD = \
$(LIBGCRYPT_LIBS) \
diff --git a/src/tests/merchant-contract-test.c b/src/tests/merchant-contract-test.c
@@ -109,7 +109,7 @@ run (void *cls, char *const *args, const char *cfgfile,
db_conn = MERCHANT_DB_connect (config);
- if (GNUNET_OK != MERCHANT_DB_initialize (db_conn, GNUNET_NO))
+ if (GNUNET_OK != MERCHANT_DB_initialize (db_conn, GNUNET_YES))
{
printf ("no db init'd\n");
result = GNUNET_SYSERR;
@@ -135,7 +135,7 @@ run (void *cls, char *const *args, const char *cfgfile,
*/
/* Amount */
- TALER_amount_get_zero ("KUDOS", &amount);
+ TALER_amount_get_zero ("EUR", &amount);
j_amount = TALER_json_from_amount (&amount);
/* Transaction ID*/
@@ -203,11 +203,12 @@ run (void *cls, char *const *args, const char *cfgfile,
/* End of 'item' object definition */
printf ("[j_item address: %p]\n", j_item);
-
+
/* Delivery date: OPTIONAL FIELD */
deldate = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_WEEKS);
j_deldate = TALER_json_from_abs (deldate);
+
/* Delivery location: OPTIONAL FIELD */
@@ -252,28 +253,29 @@ run (void *cls, char *const *args, const char *cfgfile,
"Q1WVGRGC1F4W7RYC6M23AEGFEXQEHQ730K3GG0B67VPHQSRR75H0");
j_fake_contract = json_pack ("{s:o, s:o, s:I, s:o, s:o}",
- "amount", j_amount,
- "max fee", j_max_fee,
- "trans_id", json_integer_value (j_id),
- "mints", j_mints,
- "details", j_details);
+ "amount", j_amount,
+ "max fee", j_max_fee,
+ "trans_id", json_integer_value (j_id),
+ "mints", j_mints,
+ "details", j_details);
#if 0
str = json_dumps (j_fake_contract, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
printf ("%s\n", str);
return;
#endif
- if (NULL == (j_root = MERCHANT_handle_contract (j_fake_contract,
- db_conn,
- wire,
- &contract)))
+
+ if (GNUNET_SYSERR == MERCHANT_handle_contract (j_fake_contract,
+ db_conn,
+ wire,
+ &contract))
{
printf ("errors in contract handling\n");
return;
}
#if 1
- str = json_dumps (j_root, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
+ str = json_dumps (j_fake_contract, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
printf ("%s\n", str);
return;
#endif
diff --git a/src/tests/merchant_db.c b/src/tests/merchant_db.c
@@ -1,354 +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 <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file merchant/merchant_db.c
- * @brief database helper functions used by the merchant
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- */
-
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <taler/taler_util.h>
-#include <taler/taler_pq_lib.h>
-#include "merchant_db.h"
-
-
-#define PQSQL_strerror(kind, cmd, res) \
- GNUNET_log_from (kind, "merchant-db", \
- "SQL %s failed at %s:%u with error: %s", \
- cmd, __FILE__, __LINE__, PQresultErrorMessage (res));
-
-/**
- * Shorthand for exit jumps.
- */
-#define EXITIF(cond) \
- do { \
- if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
- } while (0)
-
-
-/**
- * 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)
-{
- return GNUNET_POSTGRES_connect (cfg, "merchant-db");
-}
-
-
-/**
- * Disconnect from the database
- *
- * @param conn database handle to close
- */
-void
-MERCHANT_DB_disconnect (PGconn *conn)
-{
- PQfinish (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)
-{
- const char *tmp_str = (1 == tmp) ? "TEMPORARY" : "";
- char *sql;
- PGresult *res;
- ExecStatusType status;
- int ret;
-
- res = NULL;
- (void) GNUNET_asprintf (&sql,
- "BEGIN TRANSACTION;"
- "CREATE %1$s TABLE IF NOT EXISTS contracts ("
- "contract_id INT8 PRIMARY KEY,"
- "amount INT8 NOT NULL,"
- "amount_fraction INT4 NOT NULL,"
- "amount_currency VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL,"
- "description TEXT NOT NULL,"
- "nounce INT8 NOT NULL,"
- "expiry INT8 NOT NULL,"
- "product INT8 NOT NULL);"
- "CREATE %1$s TABLE IF NOT EXISTS checkouts ("
- "coin_pub BYTEA PRIMARY KEY,"
- "contract_id INT8 REFERENCES contracts(contract_id),"
- "amount INT4 NOT NULL,"
- "amount_fraction INT4 NOT NULL,"
- "coin_sig BYTEA NOT NULL);",
- tmp_str);
- ret = GNUNET_POSTGRES_exec (conn, sql);
- (void) GNUNET_POSTGRES_exec (conn,
- (GNUNET_OK == ret) ? "COMMIT;" : "ROLLBACK;");
- GNUNET_free (sql);
- if (GNUNET_OK != ret)
- return ret;
-
- while (NULL != (res = PQgetResult (conn)))
- {
- status = PQresultStatus (res);
- PQclear (res);
- }
-
- EXITIF (NULL == (res = PQprepare
- (conn,
- "contract_create",
- "INSERT INTO contracts"
- "(contract_id, amount, amount_fraction, amount_currency,"
- "description, nounce, expiry, product) VALUES"
- "($1, $2, $3, $4, $5, $6, $7, $8)",
- 8, NULL)));
- EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
- PQclear (res);
-
- EXITIF (NULL == (res = PQprepare
- (conn,
- "get_contract_product",
- "SELECT ("
- "product"
- ") FROM contracts "
- "WHERE ("
- "contract_id=$1"
- ")",
- 1, NULL)));
- EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
- PQclear (res);
-
- EXITIF (NULL == (res = PQprepare
- (conn,
- "checkout_create",
- "INSERT INTO checkouts ("
- "coin_pub,"
- "contract_id,"
- "amount,"
- "amount_fraction,"
- "coin_sig"
- ") VALUES ("
- "$1, $2, $3, $4, $5"
- ")",
- 5, NULL)));
- EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus (res)));
- PQclear (res);
-
- EXITIF (NULL == (res = PQprepare
- (conn,
- "get_checkout_product",
- "SELECT ("
- "product"
- ") FROM contracts "
- "WHERE "
- "contract_id IN ("
- "SELECT (contract_id) FROM checkouts "
- "WHERE coin_pub=$1"
- ")",
- 1, NULL)));
- EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus (res)));
- PQclear (res);
-
- return GNUNET_OK;
-
- EXITIF_exit:
- if (NULL != res)
- {
- PQSQL_strerror (GNUNET_ERROR_TYPE_ERROR, "PQprepare", res);
- PQclear (res);
- }
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Inserts a contract record into the database and if successfull returns the
- * serial number of the inserted row.
- *
- * @param conn the database connection
- * @param expiry the time when the contract will expire
- * @param amount the taler amount corresponding to the 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 *expiry,
- const struct TALER_Amount *amount,
- uint64_t c_id,
- const char *desc,
- uint64_t nounce,
- uint64_t product)
-{
- PGresult *res;
- #if 0
- uint64_t expiry_ms_nbo;
- uint64_t value_nbo;
- uint32_t fraction_nbo;
- uint64_t nounce_nbo;
- #endif
- ExecStatusType status;
-
- #if 0
- /*
- NOTE: the conversion to nl(l) happens *inside* the query param helpers; since
- the policy imposes this format for storing values. */
- value_nbo = GNUNET_htonll (amount->value);
- fraction_nbo = GNUNET_htonll (amount->fraction);
- nounce_nbo = GNUNET_htonll (nounce);
- expiry_ms_nbo = GNUNET_htonll (expiry.abs_value_us);
- product = GNUNET_htonll (product);
- #endif
-
- /* ported. To be tested/compiled */
- struct TALER_PQ_QueryParam params[] = {
- TALER_PQ_query_param_uint64 (&c_id),
- TALER_PQ_query_param_amount (amount),
- /* a *string* is being put in the following statement,
- though the API talks about a *blob*. Will this be liked by
- the DB ? */
- // the following inserts a string as a blob. Will Taler provide a param-from-string helper?
- TALER_PQ_query_param_fixed_size (desc, strlen(desc)),
- TALER_PQ_query_param_uint64 (&nounce),
- TALER_PQ_query_param_absolute_time (expiry),
- 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);
- EXITIF (PGRES_COMMAND_OK != status);
- PQclear (res);
- return GNUNET_OK;
-
- EXITIF_exit:
- PQclear (res);
- return GNUNET_SYSERR;
-}
-
-long long
-MERCHANT_DB_get_contract_product (PGconn *conn,
- uint64_t contract_id)
-{
- PGresult *res;
- uint64_t product;
- ExecStatusType status;
- struct TALER_PQ_QueryParam params[] = {
- TALER_PQ_query_param_uint64 (&contract_id),
- TALER_PQ_query_param_end
- };
- struct TALER_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_uint64 ("product", &product),
- TALER_PQ_result_spec_end
- };
-
- contract_id = GNUNET_htonll (contract_id);
- res = TALER_PQ_exec_prepared (conn, "get_contract_product", params);
- status = PQresultStatus (res);
- EXITIF (PGRES_TUPLES_OK != status);
- EXITIF (1 != PQntuples (res));
- EXITIF (GNUNET_YES != TALER_PQ_extract_result (res, rs, 0));
- PQclear (res);
- return GNUNET_ntohll ((uint64_t) product);
-
- EXITIF_exit:
- PQclear (res);
- return -1;
-}
-
-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)
-{
- PGresult *res;
- ExecStatusType status;
- uint32_t value_nbo;
- uint32_t fraction_nbo;
- struct TALER_PQ_QueryParam params[] = {
- TALER_PQ_query_param_rsa_public_key (coin_pub),
- TALER_PQ_query_param_uint64 (&transaction_id),
- TALER_PQ_query_param_uint32 (&value_nbo),
- TALER_PQ_query_param_uint32 (&fraction_nbo),
- TALER_PQ_query_param_rsa_signature (coin_sig),
- TALER_PQ_query_param_end
- };
-
- transaction_id = GNUNET_htonll (transaction_id);
- value_nbo = htonl (amount->value);
- fraction_nbo = htonl (amount->fraction);
- res = TALER_PQ_exec_prepared (conn, "checkout_create", params);
- status = PQresultStatus (res);
- EXITIF (PGRES_COMMAND_OK != status);
- PQclear (res);
- return GNUNET_OK;
-
- EXITIF_exit:
- PQclear (res);
- return GNUNET_SYSERR;
-}
-
-
-long long
-MERCHANT_DB_get_checkout_product (PGconn *conn,
- struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub)
-{
- PGresult *res;
- ExecStatusType status;
- uint64_t product;
- struct TALER_PQ_QueryParam params[] = {
- TALER_PQ_query_param_rsa_public_key (coin_pub),
- TALER_PQ_query_param_end
- };
- struct TALER_PQ_ResultSpec rs[] = {
- TALER_PQ_result_spec_uint64 ("product", &product),
- TALER_PQ_result_spec_end
- };
-
- product = -1;
- res = TALER_PQ_exec_prepared (conn, "get_checkout_product", params);
- status = PQresultStatus (res);
- EXITIF (PGRES_TUPLES_OK != status);
- if (0 == PQntuples (res))
- {
- TALER_LOG_DEBUG ("Checkout not found for given coin");
- goto EXITIF_exit;
- }
- EXITIF (1 != PQntuples (res));
- EXITIF (GNUNET_YES != TALER_PQ_extract_result (res, rs, 0));
- PQclear (res);
- return GNUNET_ntohll ((uint64_t) product);
-
- EXITIF_exit:
- PQclear (res);
- return -1;
-}
-/* end of merchant-db.c */
diff --git a/src/tests/merchant_db.h b/src/tests/merchant_db.h
@@ -1,101 +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 <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file merchant/merchant_db.h
- * @brief database helper functions used by the merchant
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- */
-
-#ifndef MERCHANT_DB_H
-#define MERCHANT_DB_H
-
-#include <gnunet/gnunet_postgres_lib.h>
-#include <taler/taler_util.h>
-
-/**
- * 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 expiry the time when the contract will expire
- * @param amount the taler amount corresponding to the contract
- * @param c_id this contract's identification number
- * @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 *expiry,
- const struct TALER_Amount *amount,
- 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);
-
-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);
-
-#endif /* MERCHANT_DB_H */
-
-/* end of merchant-db.h */