summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/taler_exchange_service.h31
-rw-r--r--src/lib/exchange_api_purse_merge.c31
-rw-r--r--src/lib/exchange_api_reserves_history.c39
-rw-r--r--src/testing/testing_api_cmd_purse_merge.c115
-rw-r--r--src/testing/testing_api_cmd_reserve_history.c69
5 files changed, 232 insertions, 53 deletions
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index afaa28136..d3ec7d2b5 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -1768,6 +1768,18 @@ struct TALER_EXCHANGE_ReserveHistory
struct TALER_EXCHANGE_HttpResponse hr;
/**
+ * Timestamp of when we made the history request
+ * (client-side).
+ */
+ struct GNUNET_TIME_Timestamp ts;
+
+ /**
+ * Reserve signature affirming the history request
+ * (generated as part of the request).
+ */
+ const struct TALER_ReserveSignatureP *reserve_sig;
+
+ /**
* Details depending on @e hr.http_status.
*/
union
@@ -4389,6 +4401,11 @@ struct TALER_EXCHANGE_AccountMergeResponse
struct TALER_EXCHANGE_HttpResponse hr;
/**
+ * Reserve signature affirming the merge.
+ */
+ const struct TALER_ReserveSignatureP *reserve_sig;
+
+ /**
* Details depending on the HTTP status.
*/
union
@@ -4398,6 +4415,20 @@ struct TALER_EXCHANGE_AccountMergeResponse
*/
struct
{
+ /**
+ * Signature by the exchange affirming the merge.
+ */
+ struct TALER_ExchangeSignatureP exchange_sig;
+
+ /**
+ * Online signing key used by the exchange.
+ */
+ struct TALER_ExchangePublicKeyP exchange_pub;
+
+ /**
+ * Timestamp of the exchange for @e exchange_sig.
+ */
+ struct GNUNET_TIME_Timestamp etime;
} success;
diff --git a/src/lib/exchange_api_purse_merge.c b/src/lib/exchange_api_purse_merge.c
index a32b44d48..0812fdadf 100644
--- a/src/lib/exchange_api_purse_merge.c
+++ b/src/lib/exchange_api_purse_merge.c
@@ -104,6 +104,12 @@ struct TALER_EXCHANGE_AccountMergeHandle
* Our merge key.
*/
struct TALER_PurseMergePrivateKeyP merge_priv;
+
+ /**
+ * Reserve signature affirming the merge.
+ */
+ struct TALER_ReserveSignatureP reserve_sig;
+
};
@@ -168,7 +174,8 @@ handle_purse_merge_finished (void *cls,
const json_t *j = response;
struct TALER_EXCHANGE_AccountMergeResponse dr = {
.hr.reply = j,
- .hr.http_status = (unsigned int) response_code
+ .hr.http_status = (unsigned int) response_code,
+ .reserve_sig = &pch->reserve_sig
};
pch->job = NULL;
@@ -180,17 +187,14 @@ handle_purse_merge_finished (void *cls,
case MHD_HTTP_OK:
{
const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_TIME_Timestamp etime;
struct TALER_Amount total_deposited;
- struct TALER_ExchangeSignatureP exchange_sig;
- struct TALER_ExchangePublicKeyP exchange_pub;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &exchange_sig),
+ &dr.details.success.exchange_sig),
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &exchange_pub),
+ &dr.details.success.exchange_pub),
GNUNET_JSON_spec_timestamp ("exchange_timestamp",
- &etime),
+ &dr.details.success.etime),
TALER_JSON_spec_amount ("merge_amount",
pch->purse_value_after_fees.currency,
&total_deposited),
@@ -210,7 +214,7 @@ handle_purse_merge_finished (void *cls,
key_state = TALER_EXCHANGE_get_keys (pch->exchange);
if (GNUNET_OK !=
TALER_EXCHANGE_test_signing_key (key_state,
- &exchange_pub))
+ &dr.details.success.exchange_pub))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
@@ -219,15 +223,15 @@ handle_purse_merge_finished (void *cls,
}
if (GNUNET_OK !=
TALER_exchange_online_purse_merged_verify (
- etime,
+ dr.details.success.etime,
pch->purse_expiration,
&pch->purse_value_after_fees,
&pch->purse_pub,
&pch->h_contract_terms,
&pch->reserve_pub,
pch->provider_url,
- &exchange_pub,
- &exchange_sig))
+ &dr.details.success.exchange_pub,
+ &dr.details.success.exchange_sig))
{
GNUNET_break_op (0);
dr.hr.http_status = 0;
@@ -367,7 +371,6 @@ TALER_EXCHANGE_account_merge (
json_t *merge_obj;
CURL *eh;
struct TALER_PurseMergeSignatureP merge_sig;
- struct TALER_ReserveSignatureP reserve_sig;
char arg_str[sizeof (pch->purse_pub) * 2 + 32];
char *reserve_url;
@@ -442,7 +445,7 @@ TALER_EXCHANGE_account_merge (
min_age,
TALER_WAMF_MODE_MERGE_FULLY_PAID_PURSE,
reserve_priv,
- &reserve_sig);
+ &pch->reserve_sig);
}
merge_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_string ("payto_uri",
@@ -450,7 +453,7 @@ TALER_EXCHANGE_account_merge (
GNUNET_JSON_pack_data_auto ("merge_sig",
&merge_sig),
GNUNET_JSON_pack_data_auto ("reserve_sig",
- &reserve_sig),
+ &pch->reserve_sig),
GNUNET_JSON_pack_timestamp ("merge_timestamp",
merge_timestamp));
GNUNET_assert (NULL != merge_obj);
diff --git a/src/lib/exchange_api_reserves_history.c b/src/lib/exchange_api_reserves_history.c
index d9c42d691..2925b0253 100644
--- a/src/lib/exchange_api_reserves_history.c
+++ b/src/lib/exchange_api_reserves_history.c
@@ -65,14 +65,24 @@ struct TALER_EXCHANGE_ReservesHistoryHandle
TALER_EXCHANGE_ReservesHistoryCallback cb;
/**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
* Public key of the reserve we are querying.
*/
struct TALER_ReservePublicKeyP reserve_pub;
/**
- * Closure for @a cb.
+ * Our signature.
*/
- void *cb_cls;
+ struct TALER_ReserveSignatureP reserve_sig;
+
+ /**
+ * When did we make the request.
+ */
+ struct GNUNET_TIME_Timestamp ts;
};
@@ -93,7 +103,9 @@ handle_reserves_history_ok (struct TALER_EXCHANGE_ReservesHistoryHandle *rsh,
unsigned int len;
struct TALER_EXCHANGE_ReserveHistory rs = {
.hr.reply = j,
- .hr.http_status = MHD_HTTP_OK
+ .hr.http_status = MHD_HTTP_OK,
+ .ts = rsh->ts,
+ .reserve_sig = &rsh->reserve_sig
};
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any ("balance",
@@ -247,9 +259,8 @@ TALER_EXCHANGE_reserves_history (
struct GNUNET_CURL_Context *ctx;
CURL *eh;
char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
- struct TALER_ReserveSignatureP reserve_sig;
- struct GNUNET_TIME_Timestamp ts
- = GNUNET_TIME_timestamp_get ();
+ const struct TALER_EXCHANGE_Keys *keys;
+ const struct TALER_EXCHANGE_GlobalFee *gf;
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
@@ -261,6 +272,7 @@ TALER_EXCHANGE_reserves_history (
rsh->exchange = exchange;
rsh->cb = cb;
rsh->cb_cls = cb_cls;
+ rsh->ts = GNUNET_TIME_timestamp_get ();
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
&rsh->reserve_pub.eddsa_pub);
{
@@ -293,16 +305,21 @@ TALER_EXCHANGE_reserves_history (
GNUNET_free (rsh);
return NULL;
}
- TALER_wallet_reserve_history_sign (ts,
- NULL, /* FIXME: fee! */
+ keys = TALER_EXCHANGE_get_keys (exchange);
+ GNUNET_assert (NULL != keys);
+ gf = TALER_EXCHANGE_get_global_fee (keys,
+ rsh->ts);
+ GNUNET_assert (NULL != gf);
+ TALER_wallet_reserve_history_sign (rsh->ts,
+ &gf->fees.history,
reserve_priv,
- &reserve_sig);
+ &rsh->reserve_sig);
{
json_t *history_obj = GNUNET_JSON_PACK (
GNUNET_JSON_pack_timestamp ("request_timestamp",
- ts),
+ rsh->ts),
GNUNET_JSON_pack_data_auto ("reserve_sig",
- &reserve_sig));
+ &rsh->reserve_sig));
if (GNUNET_OK !=
TALER_curl_easy_post (&rsh->post_ctx,
diff --git a/src/testing/testing_api_cmd_purse_merge.c b/src/testing/testing_api_cmd_purse_merge.c
index 27aa120ed..28193b3e8 100644
--- a/src/testing/testing_api_cmd_purse_merge.c
+++ b/src/testing/testing_api_cmd_purse_merge.c
@@ -72,6 +72,42 @@ struct PurseMergeState
struct TALER_TESTING_Interpreter *is;
/**
+ * Reserve history entry that corresponds to this operation.
+ * Will be of type #TALER_EXCHANGE_RTT_MERGE.
+ */
+ struct TALER_EXCHANGE_ReserveHistoryEntry reserve_history;
+
+ /**
+ * Public key of the purse.
+ */
+ struct TALER_PurseContractPublicKeyP purse_pub;
+
+ /**
+ * Public key of the merge capability.
+ */
+ struct TALER_PurseMergePublicKeyP merge_pub;
+
+ /**
+ * Contract value.
+ */
+ struct TALER_Amount value_after_fees;
+
+ /**
+ * Hash of the contract.
+ */
+ struct TALER_PrivateContractHashP h_contract_terms;
+
+ /**
+ * When does the purse expire.
+ */
+ struct GNUNET_TIME_Timestamp purse_expiration;
+
+ /**
+ * Minimum age of deposits into the purse.
+ */
+ uint32_t min_age;
+
+ /**
* Expected HTTP response code.
*/
unsigned int expected_response_code;
@@ -93,6 +129,36 @@ merge_cb (void *cls,
struct PurseMergeState *ds = cls;
ds->dh = NULL;
+ if (MHD_HTTP_OK == dr->hr.http_status)
+ {
+ const struct TALER_EXCHANGE_Keys *keys;
+ const struct TALER_EXCHANGE_GlobalFee *gf;
+
+ ds->reserve_history.type = TALER_EXCHANGE_RTT_MERGE;
+ keys = TALER_EXCHANGE_get_keys (ds->is->exchange);
+ GNUNET_assert (NULL != keys);
+ gf = TALER_EXCHANGE_get_global_fee (keys,
+ ds->merge_timestamp);
+ GNUNET_assert (NULL != gf);
+ ds->reserve_history.amount = gf->fees.purse;
+ ds->reserve_history.details.merge_details.purse_fee = gf->fees.purse;
+ ds->reserve_history.details.merge_details.h_contract_terms
+ = ds->h_contract_terms;
+ ds->reserve_history.details.merge_details.merge_pub
+ = ds->merge_pub;
+ ds->reserve_history.details.merge_details.reserve_sig
+ = *dr->reserve_sig;
+ ds->reserve_history.details.merge_details.merge_timestamp
+ = ds->merge_timestamp;
+ ds->reserve_history.details.merge_details.purse_expiration
+ = ds->purse_expiration;
+ ds->reserve_history.details.merge_details.min_age
+ = ds->min_age;
+ ds->reserve_history.details.merge_details.flags
+ = TALER_WAMF_MODE_MERGE_FULLY_PAID_PURSE;
+ }
+
+
if (ds->expected_response_code != dr->hr.http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -124,13 +190,8 @@ merge_run (void *cls,
struct TALER_TESTING_Interpreter *is)
{
struct PurseMergeState *ds = cls;
- const struct TALER_PurseContractPublicKeyP *purse_pub;
const struct TALER_PurseMergePrivateKeyP *merge_priv;
const json_t *ct;
- struct TALER_PrivateContractHashP h_contract_terms;
- uint32_t min_age = 0;
- struct TALER_Amount value_after_fees;
- struct GNUNET_TIME_Timestamp purse_expiration;
const struct TALER_TESTING_Command *ref;
(void) cmd;
@@ -146,14 +207,20 @@ merge_run (void *cls,
TALER_TESTING_interpreter_fail (ds->is);
return;
}
- if (GNUNET_OK !=
- TALER_TESTING_get_trait_purse_pub (ref,
- &purse_pub))
{
- GNUNET_break (0);
- TALER_TESTING_interpreter_fail (ds->is);
- return;
+ const struct TALER_PurseContractPublicKeyP *purse_pub;
+
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_purse_pub (ref,
+ &purse_pub))
+ {
+ GNUNET_break (0);
+ TALER_TESTING_interpreter_fail (ds->is);
+ return;
+ }
+ ds->purse_pub = *purse_pub;
}
+
if (GNUNET_OK !=
TALER_TESTING_get_trait_contract_terms (ref,
&ct))
@@ -164,7 +231,7 @@ merge_run (void *cls,
}
if (GNUNET_OK !=
TALER_JSON_contract_hash (ct,
- &h_contract_terms))
+ &ds->h_contract_terms))
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (ds->is);
@@ -173,12 +240,12 @@ merge_run (void *cls,
{
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_timestamp ("pay_deadline",
- &purse_expiration),
+ &ds->purse_expiration),
TALER_JSON_spec_amount_any ("amount",
- &value_after_fees),
+ &ds->value_after_fees),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_uint32 ("minimum_age",
- &min_age),
+ &ds->min_age),
NULL),
GNUNET_JSON_spec_end ()
};
@@ -217,17 +284,19 @@ merge_run (void *cls,
}
GNUNET_CRYPTO_eddsa_key_get_public (&ds->reserve_priv.eddsa_priv,
&ds->reserve_pub.eddsa_pub);
+ GNUNET_CRYPTO_eddsa_key_get_public (&merge_priv->eddsa_priv,
+ &ds->merge_pub.eddsa_pub);
ds->merge_timestamp = GNUNET_TIME_timestamp_get ();
ds->dh = TALER_EXCHANGE_account_merge (
is->exchange,
NULL, /* no wad */
&ds->reserve_priv,
- purse_pub,
+ &ds->purse_pub,
merge_priv,
- &h_contract_terms,
- min_age,
- &value_after_fees,
- purse_expiration,
+ &ds->h_contract_terms,
+ ds->min_age,
+ &ds->value_after_fees,
+ ds->purse_expiration,
ds->merge_timestamp,
&merge_cb,
ds);
@@ -285,12 +354,16 @@ merge_traits (void *cls,
{
struct PurseMergeState *ds = cls;
struct TALER_TESTING_Trait traits[] = {
+ /* history entry MUST be first due to response code logic below! */
+ TALER_TESTING_make_trait_reserve_history (&ds->reserve_history),
TALER_TESTING_make_trait_timestamp (0,
&ds->merge_timestamp),
TALER_TESTING_trait_end ()
};
- return TALER_TESTING_get_trait (traits,
+ return TALER_TESTING_get_trait ((ds->expected_response_code == MHD_HTTP_OK)
+ ? &traits[0] /* we have reserve history */
+ : &traits[1], /* skip reserve history */
ret,
trait,
index);
diff --git a/src/testing/testing_api_cmd_reserve_history.c b/src/testing/testing_api_cmd_reserve_history.c
index e79180643..ec190d5ce 100644
--- a/src/testing/testing_api_cmd_reserve_history.c
+++ b/src/testing/testing_api_cmd_reserve_history.c
@@ -32,6 +32,12 @@
*/
struct HistoryState
{
+
+ /**
+ * Public key of the reserve being analyzed.
+ */
+ struct TALER_ReservePublicKeyP reserve_pub;
+
/**
* Label to the command which created the reserve to check,
* needed to resort the reserve key.
@@ -54,19 +60,21 @@ struct HistoryState
const struct TALER_ReservePrivateKeyP *reserve_priv;
/**
- * Public key of the reserve being analyzed.
+ * Interpreter state.
*/
- struct TALER_ReservePublicKeyP reserve_pub;
+ struct TALER_TESTING_Interpreter *is;
/**
- * Expected HTTP response code.
+ * Reserve history entry that corresponds to this operation.
+ * Will be of type #TALER_EXCHANGE_RTT_HISTORY.
*/
- unsigned int expected_response_code;
+ struct TALER_EXCHANGE_ReserveHistoryEntry reserve_history;
/**
- * Interpreter state.
+ * Expected HTTP response code.
*/
- struct TALER_TESTING_Interpreter *is;
+ unsigned int expected_response_code;
+
};
@@ -177,6 +185,21 @@ reserve_history_cb (void *cls,
struct TALER_Amount eb;
ss->rsh = NULL;
+ if (MHD_HTTP_OK == rs->hr.http_status)
+ {
+ const struct TALER_EXCHANGE_Keys *keys;
+ const struct TALER_EXCHANGE_GlobalFee *gf;
+
+ ss->reserve_history.type = TALER_EXCHANGE_RTT_HISTORY;
+ keys = TALER_EXCHANGE_get_keys (ss->is->exchange);
+ GNUNET_assert (NULL != keys);
+ gf = TALER_EXCHANGE_get_global_fee (keys,
+ rs->ts);
+ GNUNET_assert (NULL != gf);
+ ss->reserve_history.amount = gf->fees.history;
+ ss->reserve_history.details.history_details.request_timestamp = rs->ts;
+ ss->reserve_history.details.history_details.reserve_sig = *rs->reserve_sig;
+ }
if (ss->expected_response_code != rs->hr.http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -291,6 +314,37 @@ history_run (void *cls,
/**
+ * Offer internal data from a "history" CMD, to other commands.
+ *
+ * @param cls closure.
+ * @param[out] ret result.
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ * @return #GNUNET_OK on success.
+ */
+static enum GNUNET_GenericReturnValue
+history_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ struct HistoryState *hs = cls;
+ struct TALER_TESTING_Trait traits[] = {
+ /* history entry MUST be first due to response code logic below! */
+ TALER_TESTING_make_trait_reserve_history (&hs->reserve_history),
+ TALER_TESTING_trait_end ()
+ };
+
+ return TALER_TESTING_get_trait ((hs->expected_response_code == MHD_HTTP_OK)
+ ? &traits[0] /* we have reserve history */
+ : &traits[1], /* skip reserve history */
+ ret,
+ trait,
+ index);
+}
+
+
+/**
* Cleanup the state from a "reserve history" CMD, and possibly
* cancel a pending operation thereof.
*
@@ -334,7 +388,8 @@ TALER_TESTING_cmd_reserve_history (const char *label,
.cls = ss,
.label = label,
.run = &history_run,
- .cleanup = &history_cleanup
+ .cleanup = &history_cleanup,
+ .traits = &history_traits
};
return cmd;