aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exchange/taler-exchange-httpd_purses_deposit.c50
-rw-r--r--src/exchange/taler-exchange-httpd_purses_merge.c2
-rw-r--r--src/include/taler_exchange_service.h8
-rw-r--r--src/include/taler_testing_lib.h2
-rw-r--r--src/lib/exchange_api_contracts_get.c20
-rw-r--r--src/lib/exchange_api_purse_deposit.c5
-rw-r--r--src/testing/test_exchange_p2p.c2
-rw-r--r--src/testing/testing_api_cmd_contract_get.c71
-rw-r--r--src/testing/testing_api_cmd_purse_deposit.c14
-rw-r--r--src/util/Makefile.am3
-rw-r--r--src/util/crypto_contract.c6
-rw-r--r--src/util/test_crypto.c46
12 files changed, 182 insertions, 47 deletions
diff --git a/src/exchange/taler-exchange-httpd_purses_deposit.c b/src/exchange/taler-exchange-httpd_purses_deposit.c
index 08a7d63b1..e2a5d34f4 100644
--- a/src/exchange/taler-exchange-httpd_purses_deposit.c
+++ b/src/exchange/taler-exchange-httpd_purses_deposit.c
@@ -329,7 +329,7 @@ parse_coin (struct MHD_Connection *connection,
if (GNUNET_OK !=
TALER_wallet_purse_deposit_verify (TEH_base_url,
pcc->purse_pub,
- &pcc->amount,
+ &coin->amount,
&coin->cpi.coin_pub,
&coin->coin_sig))
{
@@ -549,11 +549,49 @@ TEH_handler_purses_deposit (
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"deposits");
}
- /* FIXME: fetch basic purse properties
- (min age, purse_expiration, amount, merge_pub,
- h_contract_terms) from
- DB. Generate 404 or 410 (Gone) replies if
- applicable. */
+
+ {
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_TIME_Timestamp merge_timestamp;
+
+ qs = TEH_plugin->select_purse (
+ TEH_plugin->cls,
+ pcc.purse_pub,
+ &pcc.purse_expiration,
+ &pcc.amount,
+ &pcc.deposit_total,
+ &pcc.h_contract_terms,
+ &merge_timestamp);
+ switch (qs)
+ {
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "select purse");
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ GNUNET_break (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "select purse");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_EXCHANGE_GENERIC_PURSE_UNKNOWN,
+ NULL);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break; /* handled below */
+ }
+ if (GNUNET_TIME_absolute_is_past (pcc.purse_expiration.abs_time))
+ {
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_GONE,
+ TALER_EC_EXCHANGE_GENERIC_PURSE_EXPIRED,
+ NULL);
+ }
+ }
/* parse deposits */
pcc.coins = GNUNET_new_array (pcc.num_coins,
diff --git a/src/exchange/taler-exchange-httpd_purses_merge.c b/src/exchange/taler-exchange-httpd_purses_merge.c
index e79c41d85..eb264f486 100644
--- a/src/exchange/taler-exchange-httpd_purses_merge.c
+++ b/src/exchange/taler-exchange-httpd_purses_merge.c
@@ -384,7 +384,7 @@ TEH_handler_purses_merge (
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_NOT_FOUND,
- TALER_EC_EXCHANGE_MERGE_PURSE_NOT_FOUND,
+ TALER_EC_EXCHANGE_GENERIC_PURSE_UNKNOWN,
NULL);
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
/* continued below */
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index a36007757..2a88c1014 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -4004,14 +4004,14 @@ struct TALER_EXCHANGE_ContractGetResponse
struct TALER_PurseContractPublicKeyP purse_pub;
/**
- * Private key of the merge capability.
+ * Encrypted contract.
*/
- struct TALER_PurseMergePrivateKeyP merge_priv;
+ const void *econtract;
/**
- * Contract terms.
+ * Number of bytes in @e econtract.
*/
- const json_t *contract_terms;
+ size_t econtract_size;
} success;
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index f8ad120d3..fb3b553ce 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -2417,6 +2417,7 @@ TALER_TESTING_cmd_purse_create_with_deposit (
*
* @param label command label
* @param expected_http_status what HTTP status do we expect to get returned from the exchange
+ * @param for_merge true if for merge, false if for deposit
* @param contract_ref reference to a command providing us with the contract private key
* @return the command
*/
@@ -2424,6 +2425,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_contract_get (
const char *label,
unsigned int expected_http_status,
+ bool for_merge,
const char *contract_ref);
diff --git a/src/lib/exchange_api_contracts_get.c b/src/lib/exchange_api_contracts_get.c
index 76ae0052c..263a0cbe9 100644
--- a/src/lib/exchange_api_contracts_get.c
+++ b/src/lib/exchange_api_contracts_get.c
@@ -106,7 +106,6 @@ handle_contract_get_finished (void *cls,
{
void *econtract;
size_t econtract_size;
- json_t *contract;
struct TALER_PurseContractSignatureP econtract_sig;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("purse_pub",
@@ -143,24 +142,11 @@ handle_contract_get_finished (void *cls,
GNUNET_JSON_parse_free (spec);
break;
}
- contract = TALER_CRYPTO_contract_decrypt_for_merge (
- &cgh->contract_priv,
- &dr.details.success.purse_pub,
- econtract,
- econtract_size,
- &dr.details.success.merge_priv);
- GNUNET_JSON_parse_free (spec);
- if (NULL == contract)
- {
- GNUNET_break (0);
- dr.hr.http_status = 0;
- dr.hr.ec = TALER_EC_EXCHANGE_CONTRACTS_DECRYPTION_FAILED;
- break;
- }
- dr.details.success.contract_terms = contract;
+ dr.details.success.econtract = econtract;
+ dr.details.success.econtract_size = econtract_size;
cgh->cb (cgh->cb_cls,
&dr);
- json_decref (contract);
+ GNUNET_JSON_parse_free (spec);
TALER_EXCHANGE_contract_get_cancel (cgh);
return;
}
diff --git a/src/lib/exchange_api_purse_deposit.c b/src/lib/exchange_api_purse_deposit.c
index f604b8ccd..540be0e2c 100644
--- a/src/lib/exchange_api_purse_deposit.c
+++ b/src/lib/exchange_api_purse_deposit.c
@@ -281,6 +281,7 @@ TALER_EXCHANGE_purse_deposit (
const struct TALER_EXCHANGE_PurseDeposit *deposit = &deposits[i];
json_t *jdeposit;
struct TALER_CoinSpendSignatureP coin_sig;
+ struct TALER_CoinSpendPublicKeyP coin_pub;
#if FIXME_OEC
struct TALER_AgeCommitmentHash agh;
struct TALER_AgeCommitmentHash *aghp = NULL;
@@ -300,6 +301,8 @@ TALER_EXCHANGE_purse_deposit (
GNUNET_free (pch);
return NULL;
}
+ GNUNET_CRYPTO_eddsa_key_get_public (&deposit->coin_priv.eddsa_priv,
+ &coin_pub.eddsa_pub);
#endif
TALER_wallet_purse_deposit_sign (
url,
@@ -322,6 +325,8 @@ TALER_EXCHANGE_purse_deposit (
&deposit->h_denom_pub),
TALER_JSON_pack_denom_sig ("ub_sig",
&deposit->denom_sig),
+ GNUNET_JSON_pack_data_auto ("coin_pub",
+ &coin_pub),
GNUNET_JSON_pack_data_auto ("coin_sig",
&coin_sig));
GNUNET_assert (0 ==
diff --git a/src/testing/test_exchange_p2p.c b/src/testing/test_exchange_p2p.c
index c70fe9d8b..8e5fea0e7 100644
--- a/src/testing/test_exchange_p2p.c
+++ b/src/testing/test_exchange_p2p.c
@@ -160,6 +160,7 @@ run (void *cls,
TALER_TESTING_cmd_contract_get (
"push-get-contract",
MHD_HTTP_OK,
+ true, /* for merge */
"purse-with-deposit"),
TALER_TESTING_cmd_purse_merge (
"purse-merge-into-reserve",
@@ -181,6 +182,7 @@ run (void *cls,
TALER_TESTING_cmd_contract_get (
"pull-get-contract",
MHD_HTTP_OK,
+ false, /* for deposit */
"purse-create-with-reserve"),
TALER_TESTING_cmd_purse_deposit_coins (
"purse-deposit-coins",
diff --git a/src/testing/testing_api_cmd_contract_get.c b/src/testing/testing_api_cmd_contract_get.c
index 9432fdeef..10a43aa3b 100644
--- a/src/testing/testing_api_cmd_contract_get.c
+++ b/src/testing/testing_api_cmd_contract_get.c
@@ -41,6 +41,11 @@ struct ContractGetState
json_t *contract_terms;
/**
+ * Private key to decrypt the contract.
+ */
+ struct TALER_ContractDiffiePrivateP contract_priv;
+
+ /**
* Set to the returned merge key.
*/
struct TALER_PurseMergePrivateKeyP merge_priv;
@@ -70,6 +75,12 @@ struct ContractGetState
*/
unsigned int expected_response_code;
+ /**
+ * True if this is for a 'merge' operation,
+ * 'false' if this is for a 'deposit' operation.
+ */
+ bool merge;
+
};
@@ -109,10 +120,42 @@ get_cb (void *cls,
const struct TALER_PurseMergePrivateKeyP *mp;
const json_t *ct;
- /* check that we got what we expected to get! */
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_merge_priv (ref,
- &mp))
+ ds->purse_pub = dr->details.success.purse_pub;
+ if (ds->merge)
+ {
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_merge_priv (ref,
+ &mp))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (ds->is);
+ return;
+ }
+ ds->contract_terms =
+ TALER_CRYPTO_contract_decrypt_for_merge (
+ &ds->contract_priv,
+ &ds->purse_pub,
+ dr->details.success.econtract,
+ dr->details.success.econtract_size,
+ &ds->merge_priv);
+ if (0 !=
+ GNUNET_memcmp (mp,
+ &ds->merge_priv))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (ds->is);
+ return;
+ }
+ }
+ else
+ {
+ ds->contract_terms =
+ TALER_CRYPTO_contract_decrypt_for_deposit (
+ &ds->contract_priv,
+ dr->details.success.econtract,
+ dr->details.success.econtract_size);
+ }
+ if (NULL == ds->contract_terms)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (ds->is);
@@ -126,26 +169,14 @@ get_cb (void *cls,
TALER_TESTING_interpreter_fail (ds->is);
return;
}
- if (0 !=
- GNUNET_memcmp (mp,
- &dr->details.success.merge_priv))
- {
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (ds->is);
- return;
- }
if (1 != /* 1: equal, 0: not equal */
json_equal (ct,
- dr->details.success.contract_terms))
+ ds->contract_terms))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (ds->is);
return;
}
- ds->contract_terms = json_incref (
- (json_t *) dr->details.success.contract_terms);
- ds->merge_priv = dr->details.success.merge_priv;
- ds->purse_pub = dr->details.success.purse_pub;
}
TALER_TESTING_interpreter_next (ds->is);
}
@@ -180,6 +211,7 @@ get_run (void *cls,
TALER_TESTING_interpreter_fail (ds->is);
return;
}
+ ds->contract_priv = *contract_priv;
ds->dh = TALER_EXCHANGE_contract_get (
is->exchange,
contract_priv,
@@ -246,7 +278,8 @@ get_traits (void *cls,
TALER_TESTING_trait_end ()
};
- return TALER_TESTING_get_trait (traits,
+ /* skip 'merge_priv' if we are in 'merge' mode */
+ return TALER_TESTING_get_trait (&traits[ds->merge ? 0 : 1],
ret,
trait,
index);
@@ -257,6 +290,7 @@ struct TALER_TESTING_Command
TALER_TESTING_cmd_contract_get (
const char *label,
unsigned int expected_http_status,
+ bool for_merge,
const char *contract_ref)
{
struct ContractGetState *ds;
@@ -264,6 +298,7 @@ TALER_TESTING_cmd_contract_get (
ds = GNUNET_new (struct ContractGetState);
ds->expected_response_code = expected_http_status;
ds->contract_ref = contract_ref;
+ ds->merge = for_merge;
{
struct TALER_TESTING_Command cmd = {
.cls = ds,
diff --git a/src/testing/testing_api_cmd_purse_deposit.c b/src/testing/testing_api_cmd_purse_deposit.c
index c1466088f..ed4967776 100644
--- a/src/testing/testing_api_cmd_purse_deposit.c
+++ b/src/testing/testing_api_cmd_purse_deposit.c
@@ -154,9 +154,23 @@ deposit_run (void *cls,
{
struct PurseDepositState *ds = cls;
struct TALER_EXCHANGE_PurseDeposit deposits[ds->num_coin_references];
+ const struct TALER_PurseContractPublicKeyP *purse_pub;
+ const struct TALER_TESTING_Command *purse_cmd;
(void) cmd;
ds->is = is;
+
+ purse_cmd = TALER_TESTING_interpreter_lookup_command (is,
+ ds->purse_ref);
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_purse_pub (purse_cmd,
+ &purse_pub))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (is);
+ return;
+ }
+ ds->purse_pub = *purse_pub;
for (unsigned int i = 0; i<ds->num_coin_references; i++)
{
const struct Coin *cr = &ds->coin_references[i];
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index b92c427b0..94edac021 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -147,8 +147,9 @@ test_amount_LDADD = \
test_crypto_SOURCES = \
test_crypto.c
test_crypto_LDADD = \
+ libtalerutil.la \
-lgnunetutil \
- libtalerutil.la
+ -ljansson
test_payto_SOURCES = \
test_payto.c
diff --git a/src/util/crypto_contract.c b/src/util/crypto_contract.c
index fe6b1e6af..bcfe95239 100644
--- a/src/util/crypto_contract.c
+++ b/src/util/crypto_contract.c
@@ -278,6 +278,9 @@ TALER_CRYPTO_contract_encrypt_for_merge (
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
&nonce,
sizeof (nonce));
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Encrypting with key %s\n",
+ TALER_B2S (&key));
contract_encrypt (&nonce,
&key,
sizeof (key),
@@ -315,6 +318,9 @@ TALER_CRYPTO_contract_decrypt_for_merge (
GNUNET_break (0);
return NULL;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Decrypting with key %s\n",
+ TALER_B2S (&key));
if (GNUNET_OK !=
contract_decrypt (&key,
sizeof (key),
diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c
index a517b5bc3..186874e3c 100644
--- a/src/util/test_crypto.c
+++ b/src/util/test_crypto.c
@@ -438,6 +438,50 @@ test_merchant_sigs (void)
}
+static int
+test_contracts (void)
+{
+ struct TALER_ContractDiffiePrivateP cpriv;
+ struct TALER_PurseContractPublicKeyP purse_pub;
+ struct TALER_PurseContractPrivateKeyP purse_priv;
+ void *econtract;
+ size_t econtract_size;
+ struct TALER_PurseMergePrivateKeyP mpriv_in;
+ struct TALER_PurseMergePrivateKeyP mpriv_out;
+ json_t *c;
+
+ GNUNET_CRYPTO_ecdhe_key_create (&cpriv.ecdhe_priv);
+ GNUNET_CRYPTO_eddsa_key_create (&purse_priv.eddsa_priv);
+ GNUNET_CRYPTO_eddsa_key_get_public (&purse_priv.eddsa_priv,
+ &purse_pub.eddsa_pub);
+ memset (&mpriv_in,
+ 42,
+ sizeof (mpriv_in));
+ c = json_pack ("{s:s}", "test", "value");
+ GNUNET_assert (NULL != c);
+ TALER_CRYPTO_contract_encrypt_for_merge (&purse_pub,
+ &cpriv,
+ &mpriv_in,
+ c,
+ &econtract,
+ &econtract_size);
+ json_decref (c);
+ c = TALER_CRYPTO_contract_decrypt_for_merge (&cpriv,
+ &purse_pub,
+ econtract,
+ econtract_size,
+ &mpriv_out);
+ GNUNET_free (econtract);
+ if (NULL == c)
+ return 1;
+ json_decref (c);
+ if (0 != GNUNET_memcmp (&mpriv_in,
+ &mpriv_out))
+ return 1;
+ return 0;
+}
+
+
int
main (int argc,
const char *const argv[])
@@ -454,6 +498,8 @@ main (int argc,
return 4;
if (0 != test_merchant_sigs ())
return 5;
+ if (0 != test_contracts ())
+ return 6;
return 0;
}