summaryrefslogtreecommitdiff
path: root/src/backend-lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend-lib')
-rw-r--r--src/backend-lib/merchant_db.c127
-rw-r--r--src/backend-lib/merchant_db.h51
-rw-r--r--src/backend-lib/taler-merchant-httpd_contract.c142
-rw-r--r--src/backend-lib/taler_merchant_contract_lib.h51
4 files changed, 250 insertions, 121 deletions
diff --git a/src/backend-lib/merchant_db.c b/src/backend-lib/merchant_db.c
index 539af683..eef10f22 100644
--- a/src/backend-lib/merchant_db.c
+++ b/src/backend-lib/merchant_db.c
@@ -94,7 +94,9 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp)
"amount_currency VARCHAR(" TALER_CURRENCY_LEN_STR ") NOT NULL,"
"description TEXT NOT NULL,"
"nounce INT8 NOT NULL,"
+ "timestamp INT8 NOT NULL,"
"expiry INT8 NOT NULL,"
+ "edate INT8 NOT NULL,"
"product INT8 NOT NULL);"
"CREATE %1$s TABLE IF NOT EXISTS checkouts ("
"coin_pub BYTEA PRIMARY KEY,"
@@ -120,13 +122,33 @@ MERCHANT_DB_initialize (PGconn *conn, int tmp)
(conn,
"contract_create",
"INSERT INTO contracts"
- "(contract_id, hash, amount, amount_fraction, amount_currency,"
- "description, nounce, expiry, product) VALUES"
- "($1, $2, $3, $4, $5, $6, $7, $8, $9)",
- 9, NULL)));
+ "(contract_id, hash, timestamp, expiry, edate, amount, amount_fraction, amount_currency,"
+ "description, nounce, product) VALUES"
+ "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
+ 11, NULL)));
EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
PQclear (res);
+
+ /* Query aimed to get the contract's nounce and edate which will be
+ both used for regenerating a 'wire' JSON object to insert into the
+ deposit permission. Implicitly, this query will tell whether a contract
+ was created or not */
+
+ EXITIF (NULL == (res = PQprepare
+ (conn,
+ "get_contract_hash",
+ "SELECT ("
+ "nounce, edate"
+ ") FROM contracts "
+ "WHERE ("
+ "hash=$1"
+ ")",
+ 1, NULL)));
+ EXITIF (PGRES_COMMAND_OK != (status = PQresultStatus(res)));
+ PQclear (res);
+
+
EXITIF (NULL == (res = PQprepare
(conn,
"get_contract_product",
@@ -184,23 +206,28 @@ 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 hash of the stringified JSON corresponding to this contract
- * @param c_id contract's id
- * @param desc descripition of the contract
- * @param nounce a random 64-bit nounce
- * @param product description to identify a product
- * @return GNUNET_OK on success, GNUNET_SYSERR upon error
- */
+* Inserts a contract record into the database and if successfull returns the
+* serial number of the inserted row.
+*
+* @param conn the database connection
+* @param timestamp the timestamp of this contract
+* @param expiry the time when the contract will expire
+* @param edate when the merchant wants to receive the wire transfer corresponding
+* to this deal (this value is also a field inside the 'wire' JSON format)
+* @param amount the taler amount corresponding to the contract
+* @param hash of the stringified JSON corresponding to this contract
+* @param c_id contract's id
+* @param desc descripition of the contract
+* @param nounce a random 64-bit nounce
+* @param product description to identify a product
+* @return GNUNET_OK on success, GNUNET_SYSERR upon error
+*/
uint32_t
MERCHANT_DB_contract_create (PGconn *conn,
- const struct GNUNET_TIME_Absolute *expiry,
+ const struct GNUNET_TIME_Absolute timestamp,
+ const struct GNUNET_TIME_Absolute expiry,
+ struct GNUNET_TIME_Absolute edate,
const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_contract,
uint64_t c_id,
@@ -217,18 +244,18 @@ MERCHANT_DB_contract_create (PGconn *conn,
#endif
ExecStatusType status;
- /* 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_absolute_time (&timestamp),
+ TALER_PQ_query_param_absolute_time (&expiry),
+ TALER_PQ_query_param_absolute_time (&edate),
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?
+ /* A *string* is being put in the following statement,
+ though the column is declared as *blob*. Will this be
+ liked by the DB ? */
TALER_PQ_query_param_fixed_size (desc, strlen (desc)),
TALER_PQ_query_param_uint64 (&nounce),
- TALER_PQ_query_param_absolute_time (expiry),
TALER_PQ_query_param_uint64 (&product),
TALER_PQ_query_param_end
};
@@ -345,3 +372,55 @@ MERCHANT_DB_get_checkout_product (PGconn *conn,
return -1;
}
/* end of merchant-db.c */
+
+
+/**
+* The query gets a contract's nounce and edate used to reproduce
+* a 'wire' JSON object. This function is also useful to check whether
+* a claimed contract existed or not.
+* @param conn handle to the DB
+* @param h_contract the parameter for the row to match against
+* @param nounce where to store the found nounce
+* @param edate where to store the found edate
+* @return GNUNET_OK on success, GNUNET_SYSERR upon errors
+*
+*/
+
+uint32_t
+MERCHANT_DB_get_contract_values (PGconn *conn,
+ const struct GNUNET_HashCode *h_contract,
+ uint64_t *nounce,
+ struct GNUNET_TIME_Absolute *edate)
+{
+ PGresult *res;
+ ExecStatusType status;
+
+ struct TALER_PQ_QueryParam params[] = {
+ TALER_PQ_query_param_fixed_size (h_contract, sizeof (struct GNUNET_HashCode)),
+ TALER_PQ_query_param_end
+ };
+
+ struct TALER_PQ_ResultSpec rs[] = {
+ TALER_PQ_result_spec_uint64 ("nounce", nounce),
+ TALER_PQ_result_spec_absolute_time ("edate", edate),
+ TALER_PQ_result_spec_end
+ };
+
+ res = TALER_PQ_exec_prepared (conn, "get_checkout_product", params);
+
+ status = PQresultStatus (res);
+ EXITIF (PGRES_TUPLES_OK != status);
+ if (0 == PQntuples (res))
+ {
+ TALER_LOG_DEBUG ("Contract not found");
+ goto EXITIF_exit;
+ }
+ EXITIF (1 != PQntuples (res));
+ EXITIF (GNUNET_YES != TALER_PQ_extract_result (res, rs, 0));
+ PQclear (res);
+ return GNUNET_OK;
+
+ EXITIF_exit:
+ PQclear (res);
+ return GNUNET_SYSERR;
+}
diff --git a/src/backend-lib/merchant_db.h b/src/backend-lib/merchant_db.h
index 2b00f325..4c4577c7 100644
--- a/src/backend-lib/merchant_db.h
+++ b/src/backend-lib/merchant_db.h
@@ -58,23 +58,28 @@ 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 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
- * @param product description to identify a product
- * @return GNUNET_OK on success, GNUNET_SYSERR upon error
- */
+* Inserts a contract record into the database and if successfull returns the
+* serial number of the inserted row.
+*
+* @param conn the database connection
+* @param timestamp the timestamp of this contract
+* @param expiry the time when the contract will expire
+* @param edate when the merchant wants to receive the wire transfer corresponding
+* to this deal (this value is also a field inside the 'wire' JSON format)
+* @param amount the taler amount corresponding to the contract
+* @param hash of the stringified JSON corresponding to this contract
+* @param c_id contract's id
+* @param desc descripition of the contract
+* @param nounce a random 64-bit nounce
+* @param product description to identify a product
+* @return GNUNET_OK on success, GNUNET_SYSERR upon error
+*/
uint32_t
MERCHANT_DB_contract_create (PGconn *conn,
- const struct GNUNET_TIME_Absolute *expiry,
+ const struct GNUNET_TIME_Absolute timestamp,
+ const struct GNUNET_TIME_Absolute expiry,
+ struct GNUNET_TIME_Absolute edate,
const struct TALER_Amount *amount,
const struct GNUNET_HashCode *h_contract,
uint64_t c_id,
@@ -98,6 +103,24 @@ long long
MERCHANT_DB_get_checkout_product (PGconn *conn,
struct GNUNET_CRYPTO_rsa_PublicKey *coin_pub);
+/**
+* The query gets a contract's nounce and edate used to reproduce
+* a 'wire' JSON object. This function is also useful to check whether
+* a claimed contract existed or not.
+* @param conn handle to the DB
+* @param h_contract the parameter for the row to match against
+* @param nounce where to store the found nounce
+* @param edate where to store the found edate
+* @return GNUNET_OK on success, GNUNET_SYSERR upon errors
+*
+*/
+
+uint32_t
+MERCHANT_DB_get_contract_values (PGconn *conn,
+ const struct GNUNET_HashCode *h_contract,
+ uint64_t *nounce,
+ struct GNUNET_TIME_Absolute *edate);
+
#endif /* MERCHANT_DB_H */
/* 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
index 6a008455..7cfda21c 100644
--- a/src/backend-lib/taler-merchant-httpd_contract.c
+++ b/src/backend-lib/taler-merchant-httpd_contract.c
@@ -49,14 +49,57 @@ hash_wireformat (uint64_t nounce, const struct MERCHANT_WIREFORMAT_Sepa *wire)
}
/**
+ * Take the global wire details and return a JSON containing them,
+ * compliantly with the Taler's API.
+ * @param wire the merchant's wire details
+ * @param nounce the nounce for hashing the wire details with
+ * @param edate when the beneficiary wants this transfer to take place
+ * @return JSON representation of the wire details, NULL upon errors
+ */
+
+json_t *
+MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire,
+ uint64_t nounce,
+ const struct GNUNET_TIME_Absolute edate)
+
+{
+
+ json_t *root;
+ json_t *j_edate;
+ json_t *j_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;
+}
+
+
+
+/**
* Take from the frontend the (partly) generated contract and fill
* 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. It will be
* hold the new values.
* @param db_conn the handle to the local DB
-* @param wire merchant's bank's details
* @param contract where to store the (subset of the) contract to be (still) signed
+* @param timestamp contract's timestamp (shall be generated by the merchant)
+* @param expiry the time when the contract will expire
+* @param edate when the merchant wants to receive the wire transfer corresponding
+* to this deal (this value is also a field inside the 'wire' JSON format)
+* @param nounce the nounce used to hash the wire details
+* @param contract_str where to store the (stringified) contract
* @return GNUNET_OK on success; GNUNET_SYSERR upon errors
*/
@@ -65,97 +108,56 @@ hash_wireformat (uint64_t nounce, const struct MERCHANT_WIREFORMAT_Sepa *wire)
* still allocated */
uint32_t
-MERCHANT_handle_contract (json_t *j_contract,
+MERCHANT_handle_contract (const json_t *j_contract,
PGconn *db_conn,
- const struct MERCHANT_WIREFORMAT_Sepa *wire,
- struct Contract *contract)
+ struct Contract *contract,
+ struct GNUNET_TIME_Absolute timestamp,
+ struct GNUNET_TIME_Absolute expiry,
+ struct GNUNET_TIME_Absolute edate,
+ uint64_t nounce,
+ const char *contract_str)
{
- json_t *j_tmp;
- json_t *j_details;
- json_t *j_timestamp;
- json_t *jh_wire;
json_t *j_amount;
- json_t *j_mints;
- json_t *j_max_fee;
+ json_int_t j_product_id;
json_int_t j_trans_id;
- uint64_t nounce;
- json_t *j_product_id;
- json_t *j_items_tmp;
- char *a;
- #define DaEBUG
- #ifdef DEBUG
- char *str;
- #endif
- struct GNUNET_HashCode h_wire;
- struct GNUNET_TIME_Absolute timestamp;
struct TALER_Amount amount;
- struct TALER_AmountNBO amount_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);
- 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))
+
+ /* Extracting values useful for DB work. Only gettable from the JSON
+ since they are generated by the frontend */
+ if (-1 == json_unpack (j_contract, "{s:o, s:I, s:{s:{s:I}}}",
+ "amount", &j_amount,
+ "trans_id", &j_trans_id,
+ "details", "items",
+ "product_id", &j_product_id))
+ {
+ printf ("no unpacking\n");
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
- 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
-
- */
-
- GNUNET_CRYPTO_hash (a, strlen (a) + 1, &contract->h_contract_details);
+ contract_str = json_dumps (j_contract, JSON_COMPACT | JSON_PRESERVE_ORDER);
+ GNUNET_CRYPTO_hash (contract_str, strlen (contract_str) + 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,
- &timestamp,
+ timestamp,
+ expiry,
+ edate,
&amount,
&contract->h_contract_details,
(uint64_t) j_trans_id, // safe?
- a,
+ contract_str,
nounce,
- json_integer_value (j_product_id)))
+ (uint64_t) j_product_id))
return GNUNET_SYSERR;
- free (a);
-
- #ifdef OBSOLETE
- contract->h_wire = h_wire;
- TALER_amount_hton (&amount_nbo, &amount);
- contract->amount = amount_nbo;
- contract->t = GNUNET_TIME_absolute_hton (timestamp);
- contract->m = GNUNET_htonll ((uint64_t) j_trans_id); // safe?
- #endif
-
- #ifdef OBSOLETE
- contract->purpose.size = htonl (sizeof (struct ContractNBO));
- #endif
-
return GNUNET_OK;
}
diff --git a/src/backend-lib/taler_merchant_contract_lib.h b/src/backend-lib/taler_merchant_contract_lib.h
index 19fbe2f0..9094e223 100644
--- a/src/backend-lib/taler_merchant_contract_lib.h
+++ b/src/backend-lib/taler_merchant_contract_lib.h
@@ -57,24 +57,49 @@ struct ContractNBO
GNUNET_NETWORK_STRUCT_END
+
+/**
+ * Take the global wire details and return a JSON containing them,
+ * compliantly with the Taler's API.
+ * @param wire the merchant's wire details
+ * @param nounce the nounce for hashing the wire details with
+ * @param edate when the beneficiary wants this transfer to take place
+ * @return JSON representation of the wire details, NULL upon errors
+ */
+
+json_t *
+MERCHANT_get_wire_json (const struct MERCHANT_WIREFORMAT_Sepa *wire,
+ uint64_t nounce,
+ struct GNUNET_TIME_Absolute edate);
+
/**
* 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
+* 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. It will be
+* hold the new values.
* @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 GNUNET_OK if successful, GNUNET_SYSERR upon errors
-*
+* @param contract where to store the (subset of the) contract to be (still) signed
+* @param timestamp contract's timestamp (shall be generated by the merchant)
+* @param expiry the time when the contract will expire
+* @param edate when the merchant wants to receive the wire transfer corresponding
+* to this deal (this value is also a field inside the 'wire' JSON format)
+* @param nounce the nounce used to hash the wire details
+* @param contract_str where to store the hashed (stringified) contract
+* @return GNUNET_OK on success; GNUNET_SYSERR upon errors
*/
-/* TODO: this handles a simplified version (for debugging purposes)
- of the contract. To expand to the full fledged version */
+/**
+* TODO: inspect reference counting and, accordingly, free those json_t*(s)
+* still allocated */
uint32_t
-MERCHANT_handle_contract (json_t *j_contract,
+MERCHANT_handle_contract (const json_t *j_contract,
PGconn *db_conn,
- const struct MERCHANT_WIREFORMAT_Sepa *wire,
- struct Contract *contract);
+ struct Contract *contract,
+ struct GNUNET_TIME_Absolute timestamp,
+ struct GNUNET_TIME_Absolute expiry,
+ struct GNUNET_TIME_Absolute edate,
+ uint64_t nounce,
+ const char *contract_str);
+