commit 1e04bb2610bd142aebeb0fd040e649045ec785df
parent 5453309a27e2d3621225ac10785707b02459b51e
Author: Marcello Stanisci <marcello.stanisci@inria.fr>
Date: Wed, 23 Sep 2015 17:16:11 +0200
adding further columns to the "contracts" table: e.g. "edate",
"nounce", "timestamp". Plus, adding a function for querying the DB
in order to get the contract (nonce,edate) by looking for its hashed
stringification. Plus adjusting accordingly the testcase.
Diffstat:
6 files changed, 344 insertions(+), 280 deletions(-)
diff --git 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 (×tamp),
+ 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
@@ -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
@@ -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,
- ×tamp,
+ 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
@@ -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);
+
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
@@ -90,11 +90,6 @@ 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.
*/
static int dry;
@@ -282,38 +277,6 @@ 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
@@ -378,7 +341,6 @@ url_handler (void *cls,
#endif
struct MHD_Response *resp;
json_t *root;
- json_t *j_contract_complete;
json_t *j_sig_enc;
json_t *eddsa_pub_enc;
json_t *response;
@@ -389,9 +351,7 @@ url_handler (void *cls,
char *str; /* to debug JSONs */
char *deposit_body;
json_t *root_tmp;
- json_t *j_refund_deadline;
- json_t *j_amount_tmp;
- json_t *j_depperm;
+ json_t *j_contract_add;
json_t *j_details_tmp;
json_t *j_max_fee_tmp;
json_int_t j_int_trans_id_tmp;
@@ -402,12 +362,15 @@ url_handler (void *cls,
char *denom_key;
char *contract_sig;
char *h_contract;
+ struct GNUNET_TIME_Absolute now;
+ struct GNUNET_TIME_Absolute expiry;
+ struct GNUNET_TIME_Absolute edate;
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;
+ char *contract_str;
+ struct GNUNET_HashCode h_contract_str;
CURL *curl;
CURLcode curl_res;
@@ -455,110 +418,28 @@ url_handler (void *cls,
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 (?)
+ 2. wire
- (?) : 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);
+ TODO: Check if there is a row in 'contracts' table corresponding
+ to this contract ('s hash). If so, the corresponding 'nounce' and
+ 'edate' have to be retrieved */
+
+ j_wire =
- /* 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
+ /* Crafting the wire JSON */
+ if (NULL == (j_tmp = json_pack ("{s:o, s:I}",
+ "merchant_pub", eddsa_pub_enc,
+ "wire", j_wire)))
/* POST to mint's "/deposit" */
curl = curl_easy_init ();
@@ -656,16 +537,62 @@ url_handler (void *cls,
}
- if (NULL == (j_contract_complete = MERCHANT_handle_contract (root,
- db_conn,
- wire,
- &contract)))
+
+
+ /* timestamp */
+ now = GNUNET_TIME_absolute_get ();
+ /* expiry */
+ expiry = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_WEEKS);
+ /* edate */
+ edate = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_WEEKS);
+
+ /* getting the SEPA-aware JSON */
+ /* nounce for hashing the wire object */
+ nounce = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+ /* get wire object */
+ if (NULL ==
+ (j_wire = MERCHANT_get_wire_json (wire,
+ nounce,
+ edate)))
+ goto end;
+ /* hash wire objcet */
+ 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));
+ /* get key JSON entry */
+ eddsa_pub_enc = TALER_json_from_data ((void *) &pub, sizeof (pub));
+
+ if (NULL == (j_contract_add = json_pack ("{s:o, s:o, s:o}",
+ "merchant_pub", eddsa_pub_enc,
+ "H_wire", j_h_json_wire,
+ "timestamp", TALER_json_from_abs (now))))
+ {
+ printf ("BAD contract enhancement\n");
+ goto end;
+ }
+
+ /* melt to what received from the wallet */
+ if (-1 == json_object_update (j_contract_add, root))
+ {
+ printf ("depperm response not built\n");
+ goto end;
+ }
+
+ if (GNUNET_SYSERR == MERCHANT_handle_contract (root,
+ db_conn,
+ &contract,
+ now,
+ expiry,
+ edate,
+ nounce,
+ contract_str))
{
status = MHD_HTTP_INTERNAL_SERVER_ERROR;
goto end;
}
GNUNET_CRYPTO_eddsa_sign (privkey, &contract.purpose, &c_sig);
+ GNUNET_CRYPTO_hash (contract_str, strlen (contract_str) + 1, &h_contract_str);
/**
*
@@ -680,10 +607,16 @@ url_handler (void *cls,
j_sig_enc = TALER_json_from_eddsa_sig (&contract.purpose, &c_sig);
GNUNET_CRYPTO_eddsa_key_get_public (privkey, &pub);
eddsa_pub_enc = TALER_json_from_data ((void *) &pub, sizeof (pub));
- response = json_pack ("{s:o, s:o, s:o}",
- "contract", j_contract_complete,
+
+ response = json_pack ("{s:o, s:o, s:o, s:o}",
+ "contract", root,
"sig", j_sig_enc,
- "eddsa_pub", eddsa_pub_enc);
+ "eddsa_pub", eddsa_pub_enc,
+ "h_contract",
+ TALER_json_from_data (h_contract_str, sizeof (struct GNUNET_HashCode)));
+
+ GNUNET_free (contract_str);
+
TMH_RESPONSE_reply_json (connection, response, MHD_HTTP_OK);
return MHD_YES;
diff --git a/src/tests/merchant-contract-test.c b/src/tests/merchant-contract-test.c
@@ -73,6 +73,7 @@ run (void *cls, char *const *args, const char *cfgfile,
{
json_t *j_fake_contract;
json_t *j_root;
+ json_t *j_wire;
json_t *j_details;
json_t *j_mints;
json_t *j_item;
@@ -90,7 +91,9 @@ run (void *cls, char *const *args, const char *cfgfile,
json_t *j_merchant_zipcode;
json_t *j_lnames;
json_t *j_deldate;
+ json_t *j_expiry;
char *str;
+ char *contract_tmp_str;
char *desc;
struct TALER_Amount amount;
int64_t t_id;
@@ -101,6 +104,8 @@ run (void *cls, char *const *args, const char *cfgfile,
struct Contract contract;
#endif
struct GNUNET_TIME_Absolute deldate;
+ struct GNUNET_TIME_Absolute now;
+ uint64_t nounce;
db_conn = NULL;
keyfile = NULL;
@@ -201,8 +206,6 @@ 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 (),
@@ -264,23 +267,22 @@ run (void *cls, char *const *args, const char *cfgfile,
return;
#endif
+ nounce = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX);
+ now = GNUNET_TIME_absolute_get ();
+
+ j_wire = MERCHANT_get_wire_json (wire, nounce, now);
if (GNUNET_SYSERR == MERCHANT_handle_contract (j_fake_contract,
db_conn,
- wire,
- &contract))
- {
+ &contract,
+ now,
+ now,
+ now,
+ nounce,
+ contract_tmp_str))
printf ("errors in contract handling\n");
- return;
- }
-
- #if 1
- str = json_dumps (j_fake_contract, JSON_INDENT(2) | JSON_PRESERVE_ORDER);
- printf ("%s\n", str);
- return;
- #endif
-
-
+ else
+ printf ("handling contract fine\n");
}