aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/taler_mint_service.h2
-rw-r--r--src/include/taler_util.h24
-rw-r--r--src/mint-lib/mint_api_admin.c4
-rw-r--r--src/mint-lib/mint_api_deposit.c20
-rw-r--r--src/mint-lib/test-mint-home/config/mint-common.conf5
-rw-r--r--src/mint-lib/test_mint_api.c50
-rw-r--r--src/mint-tools/taler-mint-keyup.c28
-rw-r--r--src/mint/taler-mint-httpd_db.c8
-rw-r--r--src/mint/taler-mint-httpd_deposit.c17
-rw-r--r--src/mint/taler-mint-httpd_keystate.c1
-rw-r--r--src/mint/taler-mint-httpd_parsing.c95
-rw-r--r--src/mint/taler-mint-httpd_parsing.h30
-rw-r--r--src/mint/taler-mint-httpd_responses.c21
-rw-r--r--src/mint/taler-mint-httpd_responses.h5
-rw-r--r--src/util/json.c25
-rw-r--r--src/util/test_json.c4
-rw-r--r--src/util/util.c40
-rw-r--r--src/util/wireformats.c39
18 files changed, 301 insertions, 117 deletions
diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h
index 132dfa31d..5ee2331f4 100644
--- a/src/include/taler_mint_service.h
+++ b/src/include/taler_mint_service.h
@@ -651,7 +651,7 @@ struct TALER_MINT_AdminAddIncomingHandle *
TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount,
- const struct GNUNET_TIME_Absolute execution_date,
+ struct GNUNET_TIME_Absolute execution_date,
const json_t *wire,
TALER_MINT_AdminAddIncomingResultCallback res_cb,
void *res_cb_cls);
diff --git a/src/include/taler_util.h b/src/include/taler_util.h
index c9db9f789..00397cc88 100644
--- a/src/include/taler_util.h
+++ b/src/include/taler_util.h
@@ -74,6 +74,30 @@ TALER_gcrypt_init (void);
/**
+ * Round a time value so that it is suitable for transmission
+ * via JSON encodings.
+ *
+ * @param at time to round
+ * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
+ * it was just now rounded
+ */
+int
+TALER_round_abs_time (struct GNUNET_TIME_Absolute *at);
+
+
+/**
+ * Round a time value so that it is suitable for transmission
+ * via JSON encodings.
+ *
+ * @param rt time to round
+ * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
+ * it was just now rounded
+ */
+int
+TALER_round_rel_time (struct GNUNET_TIME_Relative *rt);
+
+
+/**
* Load configuration by parsing all configuration
* files in the given directory.
*
diff --git a/src/mint-lib/mint_api_admin.c b/src/mint-lib/mint_api_admin.c
index 0169f8e7d..47158665a 100644
--- a/src/mint-lib/mint_api_admin.c
+++ b/src/mint-lib/mint_api_admin.c
@@ -246,7 +246,7 @@ struct TALER_MINT_AdminAddIncomingHandle *
TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,
const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount,
- const struct GNUNET_TIME_Absolute execution_date,
+ struct GNUNET_TIME_Absolute execution_date,
const json_t *wire,
TALER_MINT_AdminAddIncomingResultCallback res_cb,
void *res_cb_cls)
@@ -256,6 +256,8 @@ TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,
json_t *admin_obj;
CURL *eh;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_round_abs_time (&execution_date));
if (GNUNET_YES !=
MAH_handle_is_ready (mint))
{
diff --git a/src/mint-lib/mint_api_deposit.c b/src/mint-lib/mint_api_deposit.c
index 3c6939668..008634f20 100644
--- a/src/mint-lib/mint_api_deposit.c
+++ b/src/mint-lib/mint_api_deposit.c
@@ -37,7 +37,7 @@
*/
#define JSON_WARN(error) \
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \
- "JSON parsing failed at %s:%u: %s (%s)", \
+ "JSON parsing failed at %s:%u: %s (%s)\n", \
__FILE__, __LINE__, error.text, error.source)
@@ -464,8 +464,8 @@ verify_signatures (const struct TALER_MINT_DenomPublicKey *dki,
TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
return GNUNET_SYSERR;
}
- if (TALER_amount_cmp (&dki->fee_deposit,
- amount) < 0)
+ if (0 < TALER_amount_cmp (&dki->fee_deposit,
+ amount))
{
TALER_LOG_WARNING ("Deposit amount smaller than fee\n");
return GNUNET_SYSERR;
@@ -615,17 +615,17 @@ TALER_MINT_deposit (struct TALER_MINT_Handle *mint,
}
deposit_obj = json_pack ("{s:o, s:o," /* f/wire */
- " s:s, s:s," /* H_wire, H_contract */
- " s:s, s:s," /* coin_pub, denom_pub */
- " s:s, s:s," /* ub_sig, timestamp */
- " s:I, s:s," /* transaction id, merchant_pub */
- " s:s, s:s}", /* refund_deadline, coin_sig */
+ " s:o, s:o," /* H_wire, H_contract */
+ " s:o, s:o," /* coin_pub, denom_pub */
+ " s:o, s:o," /* ub_sig, timestamp */
+ " s:I, s:o," /* transaction id, merchant_pub */
+ " s:o, s:o}", /* refund_deadline, coin_sig */
"f", TALER_json_from_amount (amount),
"wire", wire_details,
"H_wire", TALER_json_from_data (&h_wire,
sizeof (h_wire)),
- "H_contract", TALER_json_from_data (&h_contract,
- sizeof (h_contract)),
+ "H_contract", TALER_json_from_data (h_contract,
+ sizeof (struct GNUNET_HashCode)),
"coin_pub", TALER_json_from_data (coin_pub,
sizeof (*coin_pub)),
"denom_pub", TALER_json_from_rsa_public_key (denom_pub->rsa_public_key),
diff --git a/src/mint-lib/test-mint-home/config/mint-common.conf b/src/mint-lib/test-mint-home/config/mint-common.conf
index 6d03c2a5b..1b8aa4218 100644
--- a/src/mint-lib/test-mint-home/config/mint-common.conf
+++ b/src/mint-lib/test-mint-home/config/mint-common.conf
@@ -2,8 +2,9 @@
# Currency supported by the mint (can only be one)
CURRENCY = EUR
-# Wire format supproted by the mint (currently only SEPA is implemented)
-WIREFORMAT = SEPA
+# Wire format supproted by the mint
+# TEST is used for testing... (what a shock)
+WIREFORMAT = TEST
# HTTP port the mint listens to
PORT = 8081
diff --git a/src/mint-lib/test_mint_api.c b/src/mint-lib/test_mint_api.c
index c59d4a03b..58f502bae 100644
--- a/src/mint-lib/test_mint_api.c
+++ b/src/mint-lib/test_mint_api.c
@@ -27,6 +27,7 @@
*/
#include "platform.h"
#include "taler_util.h"
+#include "taler_signatures.h"
#include "taler_mint_service.h"
#include <microhttpd.h>
@@ -506,6 +507,7 @@ interpreter_run (void *cls,
struct TALER_ReservePublicKeyP reserve_pub;
struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_Amount amount;
+ struct GNUNET_TIME_Absolute execution_date;
json_t *wire;
is->task = NULL;
@@ -566,14 +568,22 @@ interpreter_run (void *cls,
fail (is);
return;
}
+ execution_date = GNUNET_TIME_absolute_get ();
+ TALER_round_abs_time (&execution_date);
cmd->details.admin_add_incoming.aih
= TALER_MINT_admin_add_incoming (mint,
&reserve_pub,
&amount,
- GNUNET_TIME_absolute_get (),
+ execution_date,
wire,
&add_incoming_cb,
is);
+ if (NULL == cmd->details.admin_add_incoming.aih)
+ {
+ GNUNET_break (0);
+ fail (is);
+ return;
+ }
trigger_context_task ();
return;
case OC_WITHDRAW_SIGN:
@@ -629,6 +639,12 @@ interpreter_run (void *cls,
&cmd->details.withdraw_sign.blinding_key,
&withdraw_sign_cb,
is);
+ if (NULL == cmd->details.withdraw_sign.wsh)
+ {
+ GNUNET_break (0);
+ fail (is);
+ return;
+ }
trigger_context_task ();
return;
case OC_DEPOSIT:
@@ -690,9 +706,30 @@ interpreter_run (void *cls,
refund_deadline = GNUNET_TIME_UNIT_ZERO_ABS;
}
timestamp = GNUNET_TIME_absolute_get ();
+ TALER_round_abs_time (&timestamp);
+ {
+ struct TALER_DepositRequestPS dr;
+
+ dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
+ dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
+ dr.h_contract = h_contract;
+ TALER_hash_json (wire,
+ &dr.h_wire);
+ dr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
+ dr.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
+ dr.transaction_id = GNUNET_htonll (cmd->details.deposit.transaction_id);
+ TALER_amount_hton (&dr.amount_with_fee,
+ &amount);
+ TALER_amount_hton (&dr.deposit_fee,
+ &ref->details.withdraw_sign.pk->fee_deposit);
+ dr.merchant = merchant_pub;
+ dr.coin_pub = coin_pub;
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_eddsa_sign (&ref->details.withdraw_sign.coin_priv.eddsa_priv,
+ &dr.purpose,
+ &coin_sig.eddsa_signature));
- /* FIXME: init "coin_sig" here! */
-
+ }
cmd->details.deposit.dh
= TALER_MINT_deposit (mint,
&amount,
@@ -715,6 +752,7 @@ interpreter_run (void *cls,
fail (is);
return;
}
+ trigger_context_task ();
return;
}
default:
@@ -938,7 +976,7 @@ run (void *cls,
/* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
{ .oc = OC_ADMIN_ADD_INCOMING,
.label = "create-reserve-1",
- .details.admin_add_incoming.wire = "{ \"bank\":\"source bank\", \"account\":42 }",
+ .details.admin_add_incoming.wire = "{ \"type\":\"TEST\", \"bank\":\"source bank\", \"account\":42 }",
.details.admin_add_incoming.amount = "EUR:5.01" },
{ .oc = OC_WITHDRAW_SIGN,
.label = "withdraw-coin-1",
@@ -948,7 +986,7 @@ run (void *cls,
.label = "deposit-simple",
.details.deposit.amount = "EUR:5",
.details.deposit.coin_ref = "withdraw-coin-1",
- .details.deposit.wire_details = "{ \"bank\":\"dest bank\", \"account\":42 }",
+ .details.deposit.wire_details = "{ \"type\":\"TEST\", \"bank\":\"dest bank\", \"account\":42 }",
.details.deposit.contract = "{ \"items\"={ \"name\":\"ice cream\", \"value\":1 } }",
.details.deposit.transaction_id = 1 },
{ .oc = OC_END }
@@ -1007,7 +1045,7 @@ main (int argc,
"-d", "test-mint-home",
NULL);
/* give child time to start and bind against the socket */
- sleep (1);
+ sleep (5);
result = GNUNET_SYSERR;
GNUNET_SCHEDULER_run (&run, NULL);
GNUNET_OS_process_kill (mintd,
diff --git a/src/mint-tools/taler-mint-keyup.c b/src/mint-tools/taler-mint-keyup.c
index 468bd7766..7b9388573 100644
--- a/src/mint-tools/taler-mint-keyup.c
+++ b/src/mint-tools/taler-mint-keyup.c
@@ -34,14 +34,6 @@
*/
#define HASH_CUTOFF 20
-/**
- * Macro to round microseconds to seconds in GNUNET_TIME_* structs.
- *
- * @param name value to round
- * @param us_field rel_value_us or abs_value_us
- */
-#define ROUND_TO_SECS(name,us_field) name.us_field -= name.us_field % (1000 * 1000);
-
GNUNET_NETWORK_STRUCT_BEGIN
@@ -515,8 +507,7 @@ mint_keys_update_signkeys ()
"must be longer than signkey_duration");
return GNUNET_SYSERR;
}
- ROUND_TO_SECS (signkey_duration,
- rel_value_us);
+ TALER_round_rel_time (&signkey_duration);
GNUNET_asprintf (&signkey_dir,
"%s" DIR_SEPARATOR_STR TALER_MINTDB_DIR_SIGNING_KEYS,
mint_directory);
@@ -598,8 +589,7 @@ get_cointype_params (const char *ct,
"duration_withdraw");
return GNUNET_SYSERR;
}
- ROUND_TO_SECS (params->duration_withdraw,
- rel_value_us);
+ TALER_round_rel_time (&params->duration_withdraw);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (kcfg,
ct,
@@ -611,8 +601,7 @@ get_cointype_params (const char *ct,
"duration_spend");
return GNUNET_SYSERR;
}
- ROUND_TO_SECS (params->duration_spend,
- rel_value_us);
+ TALER_round_rel_time (&params->duration_spend);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (kcfg,
ct,
@@ -624,8 +613,7 @@ get_cointype_params (const char *ct,
"duration_legal");
return GNUNET_SYSERR;
}
- ROUND_TO_SECS (params->duration_legal,
- rel_value_us);
+ TALER_round_rel_time (&params->duration_legal);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (kcfg,
ct,
@@ -637,8 +625,7 @@ get_cointype_params (const char *ct,
"mint_denom_duration_overlap");
return GNUNET_SYSERR;
}
- ROUND_TO_SECS (params->duration_overlap,
- rel_value_us);
+ TALER_round_rel_time (&params->duration_overlap);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (kcfg,
ct,
@@ -914,7 +901,7 @@ main (int argc,
{
now = GNUNET_TIME_absolute_get ();
}
- ROUND_TO_SECS (now, abs_value_us);
+ TALER_round_abs_time (&now);
kcfg = TALER_config_load (mint_directory);
if (NULL == kcfg)
@@ -990,8 +977,7 @@ main (int argc,
_("must not be zero"));
return GNUNET_SYSERR;
}
- ROUND_TO_SECS (lookahead_sign,
- rel_value_us);
+ TALER_round_rel_time (&lookahead_sign);
lookahead_sign_stamp = GNUNET_TIME_absolute_add (now,
lookahead_sign);
diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c
index 5afc104f5..2ac3defde 100644
--- a/src/mint/taler-mint-httpd_db.c
+++ b/src/mint/taler-mint-httpd_db.c
@@ -126,6 +126,7 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
&deposit->h_wire,
&deposit->h_contract,
deposit->transaction_id,
+ deposit->timestamp,
deposit->refund_deadline,
&deposit->merchant_pub,
&amount_without_fee);
@@ -194,14 +195,19 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
TALER_LOG_WARNING ("/deposit transaction commit failed\n");
return TMH_RESPONSE_reply_commit_error (connection);
}
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_subtract (&amount_without_fee,
+ &deposit->amount_with_fee,
+ &deposit->deposit_fee));
return TMH_RESPONSE_reply_deposit_success (connection,
&deposit->coin.coin_pub,
&deposit->h_wire,
&deposit->h_contract,
deposit->transaction_id,
+ deposit->timestamp,
deposit->refund_deadline,
&deposit->merchant_pub,
- &deposit->amount_with_fee);
+ &amount_without_fee);
}
diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c
index 19ea9cb50..782d05a8b 100644
--- a/src/mint/taler-mint-httpd_deposit.c
+++ b/src/mint/taler-mint-httpd_deposit.c
@@ -101,14 +101,12 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
}
TALER_amount_ntoh (&fee_deposit,
&dki->issue.fee_deposit);
- if (TALER_amount_cmp (&fee_deposit,
- &deposit->amount_with_fee) < 0)
+ if (0 < TALER_amount_cmp (&fee_deposit,
+ &deposit->amount_with_fee))
{
TMH_KS_release (key_state);
- return (MHD_YES ==
- TMH_RESPONSE_reply_external_error (connection,
- "deposited amount smaller than depositing fee"))
- ? GNUNET_NO : GNUNET_SYSERR;
+ return TMH_RESPONSE_reply_external_error (connection,
+ "deposited amount smaller than depositing fee");
}
TMH_KS_release (key_state);
@@ -146,7 +144,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
TMH_PARSE_MEMBER_FIXED ("H_contract", &deposit.h_contract),
TMH_PARSE_MEMBER_FIXED ("H_wire", &deposit.h_wire),
TMH_PARSE_MEMBER_FIXED ("coin_sig", &deposit.csig),
- TMH_PARSE_MEMBER_FIXED ("transaction_id", &deposit.transaction_id),
+ TMH_PARSE_member_uint64 ("transaction_id", &deposit.transaction_id),
TMH_PARSE_member_time_abs ("timestamp", &deposit.timestamp),
TMH_PARSE_member_time_abs ("refund_deadline", &deposit.refund_deadline),
TMH_PARSE_MEMBER_END
@@ -160,6 +158,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
return MHD_NO; /* hard failure */
if (GNUNET_NO == res)
return MHD_YES; /* failure */
+
if (GNUNET_YES !=
TALER_json_validate_wireformat (TMH_expected_wire_format,
wire))
@@ -197,7 +196,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
&deposit.deposit_fee))
{
/* Total amount smaller than fee, invalid */
- TMH_PARSE_release_data (spec);
+ TMH_PARSE_release_data (spec);
return TMH_RESPONSE_reply_arg_invalid (connection,
"f");
}
@@ -247,7 +246,7 @@ TMH_DEPOSIT_handler_deposit (struct TMH_RequestHandler *rh,
if ( (GNUNET_NO == res) || (NULL == json) )
return MHD_YES;
if (-1 == json_unpack (json,
- "{s:s, s:o, f:o}",
+ "{s:o, s:o}",
"wire", &wire,
"f", &f))
{
diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c
index 2e81c8064..096023ac5 100644
--- a/src/mint/taler-mint-httpd_keystate.c
+++ b/src/mint/taler-mint-httpd_keystate.c
@@ -494,6 +494,7 @@ TMH_KS_acquire (void)
key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32,
GNUNET_NO);
key_state->reload_time = GNUNET_TIME_absolute_get ();
+ TALER_round_abs_time (&key_state->reload_time);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Loading keys from `%s'\n",
TMH_mint_directory);
diff --git a/src/mint/taler-mint-httpd_parsing.c b/src/mint/taler-mint-httpd_parsing.c
index 1a4215ba0..c5827da7e 100644
--- a/src/mint/taler-mint-httpd_parsing.c
+++ b/src/mint/taler-mint-httpd_parsing.c
@@ -549,6 +549,28 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection,
}
break;
+ case TMH_PARSE_JNC_RET_UINT64:
+ {
+ uint64_t *r_u64 = va_arg (argp, uint64_t *);
+
+ if (json_typeof (root) != JSON_INTEGER)
+ {
+ ret = (MHD_YES ==
+ TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_BAD_REQUEST,
+ "{s:s, s:s, s:i, s:o}",
+ "error", "wrong JSON field type",
+ "type_expected", "integer",
+ "type_actual", json_typeof (root),
+ "path", path))
+ ? GNUNET_NO : GNUNET_SYSERR;
+ break;
+ }
+ *r_u64 = (uint64_t) json_integer_value (root);
+ ret = GNUNET_OK;
+ }
+ break;
+
case TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY:
{
struct TALER_DenominationPublicKey *where;
@@ -803,6 +825,16 @@ TMH_PARSE_json_data (struct MHD_Connection *connection,
TMH_PARSE_JNC_RET_TIME_ABSOLUTE,
spec[i].destination);
break;
+ case TMH_PARSE_JNC_RET_UINT64:
+ GNUNET_assert (sizeof (uint64_t) ==
+ spec[i].destination_size_in);
+ ret = TMH_PARSE_navigate_json (connection,
+ root,
+ TMH_PARSE_JNC_FIELD,
+ spec[i].field_name,
+ TMH_PARSE_JNC_RET_UINT64,
+ spec[i].destination);
+ break;
}
}
if (GNUNET_YES != ret)
@@ -882,6 +914,8 @@ TMH_PARSE_release_data (struct TMH_PARSE_FieldSpecification *spec)
break;
case TMH_PARSE_JNC_RET_TIME_ABSOLUTE:
break;
+ case TMH_PARSE_JNC_RET_UINT64:
+ break;
}
}
}
@@ -889,8 +923,9 @@ TMH_PARSE_release_data (struct TMH_PARSE_FieldSpecification *spec)
/**
* Parse absolute time specified in JSON format. The JSON format is
- * "/TIMEVAL/" where TIMEVAL is in milliseconds. Additionally, we
- * support "/forever/" to represent the end of time.
+ * "/Date(TIMEVAL)/" where TIMEVAL is in seconds after the Unix Epoch.
+ * Additionally, we support "/forever/" and "/never/" to represent the
+ * end of time.
*
* @param connection the MHD connection (to report errors)
* @param f json specification of the amount
@@ -906,9 +941,7 @@ TMH_PARSE_time_abs_json (struct MHD_Connection *connection,
struct GNUNET_TIME_Absolute *time)
{
const char *val;
- size_t slen;
- unsigned long long int tval;
- char *endp;
+ unsigned long long tval;
val = json_string_value (f);
if (NULL == val)
@@ -921,30 +954,18 @@ TMH_PARSE_time_abs_json (struct MHD_Connection *connection,
return GNUNET_SYSERR;
return GNUNET_NO;
}
- slen = strlen (val);
- if ( (slen <= 2) ||
- ('/' != val[0]) ||
- ('/' != val[slen - 1]) )
- {
- if (MHD_YES !=
- TMH_RESPONSE_reply_json_pack (connection,
- MHD_HTTP_BAD_REQUEST,
- "{s:s, s:s}",
- "error", "timestamp expected",
- "value", val))
- return GNUNET_SYSERR;
- return GNUNET_NO;
- }
- if (0 == strcasecmp (val,
- "/forever/"))
+ if ( (0 == strcasecmp (val,
+ "/forever/")) ||
+ (0 == strcasecmp (val,
+ "/never/")) )
+
{
*time = GNUNET_TIME_UNIT_FOREVER_ABS;
return GNUNET_OK;
}
- tval = strtoull (&val[1],
- &endp,
- 10);
- if (&val[slen - 1] != endp)
+ if (1 != sscanf (val,
+ "/Date(%llu)/",
+ &tval))
{
if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection,
@@ -955,9 +976,9 @@ TMH_PARSE_time_abs_json (struct MHD_Connection *connection,
return GNUNET_SYSERR;
return GNUNET_NO;
}
- /* Time is in 'ms' in JSON, but in microseconds in GNUNET_TIME_Absolute */
- time->abs_value_us = tval * 1000LL;
- if ( (time->abs_value_us) / 1000LL != tval)
+ /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
+ time->abs_value_us = tval * 1000LL * 1000LL;
+ if ( (time->abs_value_us) / 1000LL / 1000LL != tval)
{
/* Integer overflow */
if (MHD_YES !=
@@ -1048,6 +1069,24 @@ TMH_PARSE_amount_json (struct MHD_Connection *connection,
/**
+ * Generate line in parser specification for 64-bit integer
+ * given as an integer in JSON.
+ *
+ * @param field name of the field
+ * @param[out] u64 integer to initialize
+ * @return corresponding field spec
+ */
+struct TMH_PARSE_FieldSpecification
+TMH_PARSE_member_uint64 (const char *field,
+ uint64_t *u64)
+{
+ struct TMH_PARSE_FieldSpecification ret =
+ { field, (void *) u64, sizeof (uint64_t), 0, TMH_PARSE_JNC_RET_UINT64, 0 };
+ return ret;
+}
+
+
+/**
* Generate line in parser specification for JSON object value.
*
* @param field name of the field
diff --git a/src/mint/taler-mint-httpd_parsing.h b/src/mint/taler-mint-httpd_parsing.h
index 44e74d27c..7d37bb18c 100644
--- a/src/mint/taler-mint-httpd_parsing.h
+++ b/src/mint/taler-mint-httpd_parsing.h
@@ -133,7 +133,14 @@ enum TMH_PARSE_JsonNavigationCommand
* encoded within its own json object.
* Param: struct GNUNET_TIME_Absolute *
*/
- TMH_PARSE_JNC_RET_TIME_ABSOLUTE
+ TMH_PARSE_JNC_RET_TIME_ABSOLUTE,
+
+ /**
+ * Return a `uint64_t` which was
+ * encoded as a JSON integer.
+ * Param: uint64_t *
+ */
+ TMH_PARSE_JNC_RET_UINT64
};
@@ -254,10 +261,23 @@ TMH_PARSE_release_data (struct TMH_PARSE_FieldSpecification *spec);
/**
+ * Generate line in parser specification for 64-bit integer
+ * given as an integer in JSON.
+ *
+ * @param field name of the field
+ * @param[out] u64 integer to initialize
+ * @return corresponding field spec
+ */
+struct TMH_PARSE_FieldSpecification
+TMH_PARSE_member_uint64 (const char *field,
+ uint64_t *u64);
+
+
+/**
* Generate line in parser specification for JSON array value.
*
* @param field name of the field
- * @param ptraddr address of JSON pointer to initialize
+ * @param[out] jsonp address of JSON pointer to initialize
* @return corresponding field spec
*/
struct TMH_PARSE_FieldSpecification
@@ -269,7 +289,7 @@ TMH_PARSE_member_array (const char *field,
* Generate line in parser specification for JSON object value.
*
* @param field name of the field
- * @param jsonp address of pointer to JSON to initialize
+ * @param[out] jsonp address of pointer to JSON to initialize
* @return corresponding field spec
*/
struct TMH_PARSE_FieldSpecification
@@ -351,8 +371,8 @@ TMH_PARSE_amount_json (struct MHD_Connection *connection,
/**
* Parse absolute time specified in JSON format. The JSON format is
- * "/TIMEVAL/" where TIMEVAL is in milliseconds. Additionally, we
- * support "/forever/" to represent the end of time.
+ * "/TIMEVAL/" where TIMEVAL is in seconds. Additionally, we
+ * support "/forever/" and "/never/" to represent the end of time.
*
* @param connection the MHD connection (to report errors)
* @param f json specification of the amount
diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c
index f36369984..bb7a72f8e 100644
--- a/src/mint/taler-mint-httpd_responses.c
+++ b/src/mint/taler-mint-httpd_responses.c
@@ -330,6 +330,7 @@ TMH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection)
* @param h_wire hash of wire details
* @param h_contract hash of contract details
* @param transaction_id transaction ID
+ * @param timestamp client's timestamp
* @param refund_deadline until when this deposit be refunded
* @param merchant merchant public key
* @param amount_without_fee fraction of coin value to deposit, without the fee
@@ -341,6 +342,7 @@ TMH_RESPONSE_reply_deposit_success (struct MHD_Connection *connection,
const struct GNUNET_HashCode *h_wire,
const struct GNUNET_HashCode *h_contract,
uint64_t transaction_id,
+ struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute refund_deadline,
const struct TALER_MerchantPublicKeyP *merchant,
const struct TALER_Amount *amount_without_fee)
@@ -348,14 +350,13 @@ TMH_RESPONSE_reply_deposit_success (struct MHD_Connection *connection,
struct TALER_DepositConfirmationPS dc;
struct TALER_MintSignatureP sig;
json_t *sig_json;
- int ret;
dc.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_DEPOSIT);
dc.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
dc.h_contract = *h_contract;
dc.h_wire = *h_wire;
dc.transaction_id = GNUNET_htonll (transaction_id);
- dc.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
+ dc.timestamp = GNUNET_TIME_absolute_hton (timestamp);
dc.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
TALER_amount_hton (&dc.amount_without_fee,
amount_without_fee);
@@ -363,15 +364,13 @@ TMH_RESPONSE_reply_deposit_success (struct MHD_Connection *connection,
dc.merchant = *merchant;
TMH_KS_sign (&dc.purpose,
&sig);
- sig_json = TALER_json_from_eddsa_sig (&dc.purpose,
- &sig.eddsa_signature);
- ret = TMH_RESPONSE_reply_json_pack (connection,
- MHD_HTTP_OK,
- "{s:s, s:o}",
- "status", "DEPOSIT_OK",
- "signature", sig_json);
- json_decref (sig_json);
- return ret;
+ sig_json = TALER_json_from_data (&sig,
+ sizeof (sig));
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_OK,
+ "{s:s, s:o}",
+ "status", "DEPOSIT_OK",
+ "sig", sig_json);
}
diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h
index 1f8e1e44c..7afd01884 100644
--- a/src/mint/taler-mint-httpd_responses.h
+++ b/src/mint/taler-mint-httpd_responses.h
@@ -205,6 +205,7 @@ TMH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection);
* @param h_wire hash of wire details
* @param h_contract hash of contract details
* @param transaction_id transaction ID
+ * @param timestamp client's timestamp
* @param refund_deadline until when this deposit be refunded
* @param merchant merchant public key
* @param amount_without_fee fraction of coin value to deposit (without fee)
@@ -216,7 +217,9 @@ TMH_RESPONSE_reply_deposit_success (struct MHD_Connection *connection,
const struct GNUNET_HashCode *h_wire,
const struct GNUNET_HashCode *h_contract,
uint64_t transaction_id,
- struct GNUNET_TIME_Absolute refund_deadline, const struct TALER_MerchantPublicKeyP *merchant,
+ struct GNUNET_TIME_Absolute timestamp,
+ struct GNUNET_TIME_Absolute refund_deadline,
+ const struct TALER_MerchantPublicKeyP *merchant,
const struct TALER_Amount *amount_without_fee);
diff --git a/src/util/json.c b/src/util/json.c
index 1c7cb7520..42f146463 100644
--- a/src/util/json.c
+++ b/src/util/json.c
@@ -89,11 +89,13 @@ TALER_json_from_abs (struct GNUNET_TIME_Absolute stamp)
char *mystr;
int ret;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_round_abs_time (&stamp));
if (stamp.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
return json_string ("/never/");
ret = GNUNET_asprintf (&mystr,
- "/%llu/",
- (long long) (stamp.abs_value_us / (1000LL * 1000LL)));
+ "/Date(%llu)/",
+ (unsigned long long) (stamp.abs_value_us / (1000LL * 1000LL)));
GNUNET_assert (ret > 0);
j = json_string (mystr);
GNUNET_free (mystr);
@@ -320,7 +322,7 @@ TALER_json_to_amount (json_t *json,
/**
- * Parse given JSON object to Amount
+ * Parse given JSON object to absolute time.
*
* @param json the json object representing Amount
* @param[out] abs where the amount has to be written
@@ -331,9 +333,7 @@ TALER_json_to_abs (json_t *json,
struct GNUNET_TIME_Absolute *abs)
{
const char *val;
- size_t slen;
unsigned long long int tval;
- char *endp;
val = json_string_value (json);
if (NULL == val)
@@ -341,14 +341,6 @@ TALER_json_to_abs (json_t *json,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- slen = strlen (val);
- if ( (slen <= 2) ||
- ('/' != val[0]) ||
- ('/' != val[slen - 1]) )
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
if ( (0 == strcasecmp (val,
"/forever/")) ||
(0 == strcasecmp (val,
@@ -357,10 +349,9 @@ TALER_json_to_abs (json_t *json,
*abs = GNUNET_TIME_UNIT_FOREVER_ABS;
return GNUNET_OK;
}
- tval = strtoull (&val[1],
- &endp,
- 10);
- if (&val[slen - 1] != endp)
+ if (1 != sscanf (val,
+ "/Date(%llu)/",
+ &tval))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
diff --git a/src/util/test_json.c b/src/util/test_json.c
index 6d887f489..c48fe68bd 100644
--- a/src/util/test_json.c
+++ b/src/util/test_json.c
@@ -65,7 +65,7 @@ test_time ()
struct GNUNET_TIME_Absolute a2;
a1 = GNUNET_TIME_absolute_get ();
- a1.abs_value_us -= a1.abs_value_us % 1000000; /* round! */
+ TALER_round_abs_time (&a1);
j = TALER_json_from_abs (a1);
GNUNET_assert (NULL != j);
GNUNET_assert (GNUNET_OK ==
@@ -110,7 +110,7 @@ test_raw ()
TALER_json_to_data (j,
blob2,
i));
- GNUNET_assert (0 ==
+ GNUNET_assert (0 ==
memcmp (blob,
blob2,
i));
diff --git a/src/util/util.c b/src/util/util.c
index 6da2f3f78..1d8b09c4d 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -64,6 +64,46 @@ TALER_config_get_denom (struct GNUNET_CONFIGURATION_Handle *cfg,
/**
+ * Round a time value so that it is suitable for transmission
+ * via JSON encodings.
+ *
+ * @param at time to round
+ * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
+ * it was just now rounded
+ */
+int
+TALER_round_abs_time (struct GNUNET_TIME_Absolute *at)
+{
+ if (at->abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
+ return GNUNET_OK;
+ if (0 == at->abs_value_us % 1000000)
+ return GNUNET_OK;
+ at->abs_value_us -= at->abs_value_us % 1000000;
+ return GNUNET_NO;
+}
+
+
+/**
+ * Round a time value so that it is suitable for transmission
+ * via JSON encodings.
+ *
+ * @param rt time to round
+ * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
+ * it was just now rounded
+ */
+int
+TALER_round_rel_time (struct GNUNET_TIME_Relative *rt)
+{
+ if (rt->rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
+ return GNUNET_OK;
+ if (0 == rt->rel_value_us % 1000000)
+ return GNUNET_OK;
+ rt->rel_value_us -= rt->rel_value_us % 1000000;
+ return GNUNET_NO;
+}
+
+
+/**
* Load configuration by parsing all configuration
* files in the given directory.
*
diff --git a/src/util/wireformats.c b/src/util/wireformats.c
index 7ea4fd067..88af4a438 100644
--- a/src/util/wireformats.c
+++ b/src/util/wireformats.c
@@ -330,7 +330,7 @@ validate_sepa (const json_t *wire)
((json_t *) wire,
&error, JSON_STRICT,
"{"
- "s:s " /* type: "SEPA" */
+ "s:s " /* TYPE: sepa */
"s:s " /* IBAN: iban */
"s:s " /* name: beneficiary name */
"s:s " /* BIC: beneficiary bank's BIC */
@@ -345,7 +345,6 @@ validate_sepa (const json_t *wire)
"edate", &edate,
"r", &r,
"address", &address));
- EXITIF (0 != strcmp (type, "SEPA"));
if (1 != validate_iban (iban))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -360,6 +359,20 @@ validate_sepa (const json_t *wire)
/**
+ * Validate TEST account details. The "test" format is used
+ * for testing, so this validator does nothing.
+ *
+ * @param wire JSON with the TEST details
+ * @return #GNUNET_YES if correctly formatted; #GNUNET_NO if not
+ */
+static int
+validate_test (const json_t *wire)
+{
+ return GNUNET_YES;
+}
+
+
+/**
* Handler for a wire format.
*/
struct FormatHandler
@@ -392,9 +405,29 @@ TALER_json_validate_wireformat (const char *type,
{
static const struct FormatHandler format_handlers[] = {
{ "SEPA", &validate_sepa },
+ { "TEST", &validate_test },
{ NULL, NULL}
};
unsigned int i;
+ char *stype;
+ json_error_t error;
+
+ UNPACK_EXITIF (0 != json_unpack_ex
+ ((json_t *) wire,
+ &error, 0,
+ "{"
+ "s:s " /* TYPE: type */
+ "}",
+ "type", &stype));
+ if (0 != strcasecmp (type,
+ stype))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Wireformat `%s' does not match mint's expected `%s' format\n",
+ stype,
+ type);
+ return GNUNET_NO;
+ }
for (i=0;NULL != format_handlers[i].type;i++)
if (0 == strcasecmp (format_handlers[i].type,
@@ -404,6 +437,8 @@ TALER_json_validate_wireformat (const char *type,
"Wireformat `%s' not supported\n",
type);
return GNUNET_NO;
+ EXITIF_exit:
+ return GNUNET_NO;
}
/* end of wireformats.c */