aboutsummaryrefslogtreecommitdiff
path: root/src/backend-lib
diff options
context:
space:
mode:
authorMarcello Stanisci <marcello.stanisci@inria.fr>2015-09-15 18:02:09 +0200
committerMarcello Stanisci <marcello.stanisci@inria.fr>2015-09-15 18:02:09 +0200
commitf9e4086dffd7874abda25c6b6548c8fb39475100 (patch)
treea9a097afa71876ef0df1cf8b13cbd1ca1ab99fa0 /src/backend-lib
parenta25a80150f36d94f28075666932677571b3076d1 (diff)
downloadmerchant-f9e4086dffd7874abda25c6b6548c8fb39475100.tar.gz
merchant-f9e4086dffd7874abda25c6b6548c8fb39475100.tar.bz2
merchant-f9e4086dffd7874abda25c6b6548c8fb39475100.zip
adding merchant library +
testcases for contract mgmt + minor tree adjustments
Diffstat (limited to 'src/backend-lib')
-rw-r--r--src/backend-lib/Makefile.am24
-rw-r--r--src/backend-lib/merchant_db.c354
-rw-r--r--src/backend-lib/merchant_db.h101
-rw-r--r--src/backend-lib/taler-merchant-httpd_contract.c144
-rw-r--r--src/backend-lib/taler_merchant_contract_lib.h62
-rw-r--r--src/backend-lib/taler_merchant_lib.h1
6 files changed, 686 insertions, 0 deletions
diff --git a/src/backend-lib/Makefile.am b/src/backend-lib/Makefile.am
new file mode 100644
index 00000000..61867e41
--- /dev/null
+++ b/src/backend-lib/Makefile.am
@@ -0,0 +1,24 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+lib_LTLIBRARIES = \
+ libtalermerchant.la
+
+include_HEADERS = \
+ taler_merchant_lib.h \
+ taler_merchant_contract_lib.h
+
+libtalermerchant_la_SOURCES = \
+ taler-merchant-httpd_contract.c \
+ taler_merchant_contract_lib.h \
+ merchant_db.c merchant_db.h \
+ merchant.h
+
+libtalermerchant_la_LIBADD = \
+ $(LIBGCRYPT_LIBS) \
+ -ltalerutil \
+ -lgnunetutil \
+ -ltalerpq \
+ -lgnunetpostgres \
+ -lpq \
+ -lpthread
diff --git a/src/backend-lib/merchant_db.c b/src/backend-lib/merchant_db.c
new file mode 100644
index 00000000..274de25a
--- /dev/null
+++ b/src/backend-lib/merchant_db.c
@@ -0,0 +1,354 @@
+/*
+ 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-lib/merchant_db.h b/src/backend-lib/merchant_db.h
new file mode 100644
index 00000000..a723b229
--- /dev/null
+++ b/src/backend-lib/merchant_db.h
@@ -0,0 +1,101 @@
+/*
+ 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-lib/taler-merchant-httpd_contract.c b/src/backend-lib/taler-merchant-httpd_contract.c
new file mode 100644
index 00000000..55c56e0a
--- /dev/null
+++ b/src/backend-lib/taler-merchant-httpd_contract.c
@@ -0,0 +1,144 @@
+#include "platform.h"
+#include <jansson.h>
+#include <taler/taler_signatures.h>
+#include <gnunet/gnunet_util_lib.h>
+#include "merchant.h"
+#include "merchant_db.h"
+#include "taler_merchant_contract_lib.h"
+
+
+/* TODO: make this file a library, and programmatically call the following
+ * functions */
+
+/**
+ * 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)
+
+/**
+* Generate the hash containing the information (= a nounce + merchant's IBAN) to
+* redeem money from mint in a subsequent /deposit operation
+* @param nounce the nounce
+* @param wire the merchant's wire details
+* @return the hash to be included in the contract's blob
+*
+*/
+
+static struct GNUNET_HashCode
+hash_wireformat (uint64_t nounce, const struct MERCHANT_WIREFORMAT_Sepa *wire)
+{
+ struct GNUNET_HashContext *hc;
+ struct GNUNET_HashCode hash;
+
+ hc = GNUNET_CRYPTO_hash_context_start ();
+ GNUNET_CRYPTO_hash_context_read (hc, wire->iban, strlen (wire->iban));
+ GNUNET_CRYPTO_hash_context_read (hc, wire->name, strlen (wire->name));
+ GNUNET_CRYPTO_hash_context_read (hc, wire->bic, strlen (wire->bic));
+ nounce = GNUNET_htonll (nounce);
+ GNUNET_CRYPTO_hash_context_read (hc, &nounce, sizeof (nounce));
+ GNUNET_CRYPTO_hash_context_finish (hc, &hash);
+ return hash;
+}
+
+/**
+* Take from the frontend the (partly) generated contract and fill
+* the missing values in it; for example, the SEPA-aware values.
+* Moreover, it stores the contract in the DB and does the signature of it.
+* @param contract parsed contract, originated by the frontend
+* @param db_conn the handle to the local DB
+* @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
+*/
+
+/* TODO: this handles a simplified version (for debugging purposes)
+ of the contract. To expand to the full fledged version */
+
+json_t *
+MERCHANT_handle_contract (json_t *contract,
+ PGconn *db_conn,
+ struct GNUNET_CRYPTO_EddsaPrivateKey *kpriv,
+ const struct MERCHANT_WIREFORMAT_Sepa *wire,
+ struct GNUNET_CRYPTO_EddsaSignature *sig)
+{
+ json_t *root;
+ json_t *j_timestamp;
+ json_t *jh_wire;
+ json_t *j_amount;
+ json_int_t j_trans_id;
+
+ uint64_t nounce;
+ uint64_t product_id;
+ char *a;
+ char *h_wire_enc;
+ char *str;
+ struct GNUNET_HashCode h_wire;
+ struct GNUNET_TIME_Absolute timestamp;
+ struct TALER_Amount amount;
+ struct TALER_AmountNBO amount_nbo;
+ struct ContractNBO contract_nbo;
+
+ nounce = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+ // timing mgmt
+ timestamp = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+ 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);
+
+ str = json_dumps (contract, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
+
+
+ json_unpack (contract, "{s:o, s:I}",
+ "amount", &j_amount,
+ "trans_id", &j_trans_id);
+
+ /* needed for DB stuff */
+ TALER_json_to_amount (j_amount, &amount);
+ /* temporary way of getting this value. To be adapted to the expanded contract
+ format. See 'TODO' above. */
+ product_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+ /* adding the generated values in this JSON */
+ root = json_pack ("{s:o, s:I, s:s, s:o}",
+ "amount", j_amount,
+ "trans_id", j_trans_id,
+ "h_wire", jh_wire,
+ "timestamp", j_timestamp);
+ a = json_dumps (root, JSON_COMPACT | JSON_PRESERVE_ORDER);
+
+ // DB mgmt
+ if (GNUNET_SYSERR == MERCHANT_DB_contract_create (db_conn,
+ &timestamp,
+ &amount,
+ (uint64_t) j_trans_id, // safe?
+ a,
+ nounce,
+ product_id));
+ contract_nbo.h_wire = h_wire;
+ TALER_amount_hton (&amount_nbo, &amount);
+ contract_nbo.amount = amount_nbo;
+ contract_nbo.t = GNUNET_TIME_absolute_hton (timestamp);
+ contract_nbo.m = GNUNET_htonll ((uint64_t) j_trans_id); // safe?
+ GNUNET_CRYPTO_hash (a, strlen (a) + 1, &contract_nbo.h_contract_details);
+ free (a);
+ contract_nbo.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_CONTRACT);
+ contract_nbo.purpose.size = htonl (sizeof (struct ContractNBO));
+ GNUNET_CRYPTO_eddsa_sign (kpriv, &contract_nbo.purpose, sig);
+
+ return root;
+}
diff --git a/src/backend-lib/taler_merchant_contract_lib.h b/src/backend-lib/taler_merchant_contract_lib.h
new file mode 100644
index 00000000..4e345703
--- /dev/null
+++ b/src/backend-lib/taler_merchant_contract_lib.h
@@ -0,0 +1,62 @@
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+struct ContractNBO
+{
+ /**
+ * Purpose header for the signature over contract
+ */
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+ /**
+ * The transaction identifier. NOTE: it was m[13]. TODO:
+ * change the API accordingly!
+ */
+ uint64_t m;
+
+ /**
+ * Expiry time
+ */
+ struct GNUNET_TIME_AbsoluteNBO t;
+
+ /**
+ * The invoice amount
+ */
+ struct TALER_AmountNBO amount;
+
+ /**
+ * The hash of the merchant's wire details (bank account information), with a nounce
+ */
+ struct GNUNET_HashCode h_wire;
+
+ /**
+ * Hash of the JSON contract in UTF-8 including 0-termination,
+ * using JSON_COMPACT encoding with sorted fields.
+ */
+ struct GNUNET_HashCode h_contract_details;
+
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+/**
+* Take from the frontend the (partly) generated contract and fill
+* the missing values in it; for example, the SEPA-aware values.
+* Moreover, it stores the contract in the DB and does the signature of it.
+* @param contract parsed contract, originated by the frontend
+* @param db_conn the handle to the local DB
+* @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
+*/
+
+/* TODO: this handles a simplified version (for debugging purposes)
+ of the contract. To expand to the full fledged version */
+
+json_t *
+MERCHANT_handle_contract (json_t *contract,
+ PGconn *db_conn,
+ struct GNUNET_CRYPTO_EddsaPrivateKey *kpriv,
+ const struct MERCHANT_WIREFORMAT_Sepa *wire,
+ struct GNUNET_CRYPTO_EddsaSignature *sig);
diff --git a/src/backend-lib/taler_merchant_lib.h b/src/backend-lib/taler_merchant_lib.h
new file mode 100644
index 00000000..41891783
--- /dev/null
+++ b/src/backend-lib/taler_merchant_lib.h
@@ -0,0 +1 @@
+#include "taler_merchant_contract_lib.h"