misc bugfixes from tests

This commit is contained in:
Christian Grothoff 2015-07-05 16:55:01 +02:00
parent f623214c12
commit 922323b410
18 changed files with 300 additions and 116 deletions

View File

@ -651,7 +651,7 @@ struct TALER_MINT_AdminAddIncomingHandle *
TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint, TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,
const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount, const struct TALER_Amount *amount,
const struct GNUNET_TIME_Absolute execution_date, struct GNUNET_TIME_Absolute execution_date,
const json_t *wire, const json_t *wire,
TALER_MINT_AdminAddIncomingResultCallback res_cb, TALER_MINT_AdminAddIncomingResultCallback res_cb,
void *res_cb_cls); void *res_cb_cls);

View File

@ -73,6 +73,30 @@ void
TALER_gcrypt_init (void); 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 * Load configuration by parsing all configuration
* files in the given directory. * files in the given directory.

View File

@ -246,7 +246,7 @@ struct TALER_MINT_AdminAddIncomingHandle *
TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint, TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,
const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount, const struct TALER_Amount *amount,
const struct GNUNET_TIME_Absolute execution_date, struct GNUNET_TIME_Absolute execution_date,
const json_t *wire, const json_t *wire,
TALER_MINT_AdminAddIncomingResultCallback res_cb, TALER_MINT_AdminAddIncomingResultCallback res_cb,
void *res_cb_cls) void *res_cb_cls)
@ -256,6 +256,8 @@ TALER_MINT_admin_add_incoming (struct TALER_MINT_Handle *mint,
json_t *admin_obj; json_t *admin_obj;
CURL *eh; CURL *eh;
GNUNET_assert (GNUNET_OK ==
TALER_round_abs_time (&execution_date));
if (GNUNET_YES != if (GNUNET_YES !=
MAH_handle_is_ready (mint)) MAH_handle_is_ready (mint))
{ {

View File

@ -37,7 +37,7 @@
*/ */
#define JSON_WARN(error) \ #define JSON_WARN(error) \
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, \ 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) __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"); TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (TALER_amount_cmp (&dki->fee_deposit, if (0 < TALER_amount_cmp (&dki->fee_deposit,
amount) < 0) amount))
{ {
TALER_LOG_WARNING ("Deposit amount smaller than fee\n"); TALER_LOG_WARNING ("Deposit amount smaller than fee\n");
return GNUNET_SYSERR; 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 */ deposit_obj = json_pack ("{s:o, s:o," /* f/wire */
" s:s, s:s," /* H_wire, H_contract */ " s:o, s:o," /* H_wire, H_contract */
" s:s, s:s," /* coin_pub, denom_pub */ " s:o, s:o," /* coin_pub, denom_pub */
" s:s, s:s," /* ub_sig, timestamp */ " s:o, s:o," /* ub_sig, timestamp */
" s:I, s:s," /* transaction id, merchant_pub */ " s:I, s:o," /* transaction id, merchant_pub */
" s:s, s:s}", /* refund_deadline, coin_sig */ " s:o, s:o}", /* refund_deadline, coin_sig */
"f", TALER_json_from_amount (amount), "f", TALER_json_from_amount (amount),
"wire", wire_details, "wire", wire_details,
"H_wire", TALER_json_from_data (&h_wire, "H_wire", TALER_json_from_data (&h_wire,
sizeof (h_wire)), sizeof (h_wire)),
"H_contract", TALER_json_from_data (&h_contract, "H_contract", TALER_json_from_data (h_contract,
sizeof (h_contract)), sizeof (struct GNUNET_HashCode)),
"coin_pub", TALER_json_from_data (coin_pub, "coin_pub", TALER_json_from_data (coin_pub,
sizeof (*coin_pub)), sizeof (*coin_pub)),
"denom_pub", TALER_json_from_rsa_public_key (denom_pub->rsa_public_key), "denom_pub", TALER_json_from_rsa_public_key (denom_pub->rsa_public_key),

View File

@ -2,8 +2,9 @@
# Currency supported by the mint (can only be one) # Currency supported by the mint (can only be one)
CURRENCY = EUR CURRENCY = EUR
# Wire format supproted by the mint (currently only SEPA is implemented) # Wire format supproted by the mint
WIREFORMAT = SEPA # TEST is used for testing... (what a shock)
WIREFORMAT = TEST
# HTTP port the mint listens to # HTTP port the mint listens to
PORT = 8081 PORT = 8081

View File

@ -27,6 +27,7 @@
*/ */
#include "platform.h" #include "platform.h"
#include "taler_util.h" #include "taler_util.h"
#include "taler_signatures.h"
#include "taler_mint_service.h" #include "taler_mint_service.h"
#include <microhttpd.h> #include <microhttpd.h>
@ -506,6 +507,7 @@ interpreter_run (void *cls,
struct TALER_ReservePublicKeyP reserve_pub; struct TALER_ReservePublicKeyP reserve_pub;
struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_Amount amount; struct TALER_Amount amount;
struct GNUNET_TIME_Absolute execution_date;
json_t *wire; json_t *wire;
is->task = NULL; is->task = NULL;
@ -566,14 +568,22 @@ interpreter_run (void *cls,
fail (is); fail (is);
return; return;
} }
execution_date = GNUNET_TIME_absolute_get ();
TALER_round_abs_time (&execution_date);
cmd->details.admin_add_incoming.aih cmd->details.admin_add_incoming.aih
= TALER_MINT_admin_add_incoming (mint, = TALER_MINT_admin_add_incoming (mint,
&reserve_pub, &reserve_pub,
&amount, &amount,
GNUNET_TIME_absolute_get (), execution_date,
wire, wire,
&add_incoming_cb, &add_incoming_cb,
is); is);
if (NULL == cmd->details.admin_add_incoming.aih)
{
GNUNET_break (0);
fail (is);
return;
}
trigger_context_task (); trigger_context_task ();
return; return;
case OC_WITHDRAW_SIGN: case OC_WITHDRAW_SIGN:
@ -629,6 +639,12 @@ interpreter_run (void *cls,
&cmd->details.withdraw_sign.blinding_key, &cmd->details.withdraw_sign.blinding_key,
&withdraw_sign_cb, &withdraw_sign_cb,
is); is);
if (NULL == cmd->details.withdraw_sign.wsh)
{
GNUNET_break (0);
fail (is);
return;
}
trigger_context_task (); trigger_context_task ();
return; return;
case OC_DEPOSIT: case OC_DEPOSIT:
@ -690,9 +706,30 @@ interpreter_run (void *cls,
refund_deadline = GNUNET_TIME_UNIT_ZERO_ABS; refund_deadline = GNUNET_TIME_UNIT_ZERO_ABS;
} }
timestamp = GNUNET_TIME_absolute_get (); timestamp = GNUNET_TIME_absolute_get ();
TALER_round_abs_time (&timestamp);
{
struct TALER_DepositRequestPS dr;
/* FIXME: init "coin_sig" here! */ 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));
}
cmd->details.deposit.dh cmd->details.deposit.dh
= TALER_MINT_deposit (mint, = TALER_MINT_deposit (mint,
&amount, &amount,
@ -715,6 +752,7 @@ interpreter_run (void *cls,
fail (is); fail (is);
return; return;
} }
trigger_context_task ();
return; return;
} }
default: default:
@ -938,7 +976,7 @@ run (void *cls,
/* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */ /* Fill reserve with EUR:5.01, as withdraw fee is 1 ct per config */
{ .oc = OC_ADMIN_ADD_INCOMING, { .oc = OC_ADMIN_ADD_INCOMING,
.label = "create-reserve-1", .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" }, .details.admin_add_incoming.amount = "EUR:5.01" },
{ .oc = OC_WITHDRAW_SIGN, { .oc = OC_WITHDRAW_SIGN,
.label = "withdraw-coin-1", .label = "withdraw-coin-1",
@ -948,7 +986,7 @@ run (void *cls,
.label = "deposit-simple", .label = "deposit-simple",
.details.deposit.amount = "EUR:5", .details.deposit.amount = "EUR:5",
.details.deposit.coin_ref = "withdraw-coin-1", .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.contract = "{ \"items\"={ \"name\":\"ice cream\", \"value\":1 } }",
.details.deposit.transaction_id = 1 }, .details.deposit.transaction_id = 1 },
{ .oc = OC_END } { .oc = OC_END }
@ -1007,7 +1045,7 @@ main (int argc,
"-d", "test-mint-home", "-d", "test-mint-home",
NULL); NULL);
/* give child time to start and bind against the socket */ /* give child time to start and bind against the socket */
sleep (1); sleep (5);
result = GNUNET_SYSERR; result = GNUNET_SYSERR;
GNUNET_SCHEDULER_run (&run, NULL); GNUNET_SCHEDULER_run (&run, NULL);
GNUNET_OS_process_kill (mintd, GNUNET_OS_process_kill (mintd,

View File

@ -34,14 +34,6 @@
*/ */
#define HASH_CUTOFF 20 #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 GNUNET_NETWORK_STRUCT_BEGIN
@ -515,8 +507,7 @@ mint_keys_update_signkeys ()
"must be longer than signkey_duration"); "must be longer than signkey_duration");
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
ROUND_TO_SECS (signkey_duration, TALER_round_rel_time (&signkey_duration);
rel_value_us);
GNUNET_asprintf (&signkey_dir, GNUNET_asprintf (&signkey_dir,
"%s" DIR_SEPARATOR_STR TALER_MINTDB_DIR_SIGNING_KEYS, "%s" DIR_SEPARATOR_STR TALER_MINTDB_DIR_SIGNING_KEYS,
mint_directory); mint_directory);
@ -598,8 +589,7 @@ get_cointype_params (const char *ct,
"duration_withdraw"); "duration_withdraw");
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
ROUND_TO_SECS (params->duration_withdraw, TALER_round_rel_time (&params->duration_withdraw);
rel_value_us);
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (kcfg, GNUNET_CONFIGURATION_get_value_time (kcfg,
ct, ct,
@ -611,8 +601,7 @@ get_cointype_params (const char *ct,
"duration_spend"); "duration_spend");
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
ROUND_TO_SECS (params->duration_spend, TALER_round_rel_time (&params->duration_spend);
rel_value_us);
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (kcfg, GNUNET_CONFIGURATION_get_value_time (kcfg,
ct, ct,
@ -624,8 +613,7 @@ get_cointype_params (const char *ct,
"duration_legal"); "duration_legal");
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
ROUND_TO_SECS (params->duration_legal, TALER_round_rel_time (&params->duration_legal);
rel_value_us);
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (kcfg, GNUNET_CONFIGURATION_get_value_time (kcfg,
ct, ct,
@ -637,8 +625,7 @@ get_cointype_params (const char *ct,
"mint_denom_duration_overlap"); "mint_denom_duration_overlap");
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
ROUND_TO_SECS (params->duration_overlap, TALER_round_rel_time (&params->duration_overlap);
rel_value_us);
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (kcfg, GNUNET_CONFIGURATION_get_value_number (kcfg,
ct, ct,
@ -914,7 +901,7 @@ main (int argc,
{ {
now = GNUNET_TIME_absolute_get (); now = GNUNET_TIME_absolute_get ();
} }
ROUND_TO_SECS (now, abs_value_us); TALER_round_abs_time (&now);
kcfg = TALER_config_load (mint_directory); kcfg = TALER_config_load (mint_directory);
if (NULL == kcfg) if (NULL == kcfg)
@ -990,8 +977,7 @@ main (int argc,
_("must not be zero")); _("must not be zero"));
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
ROUND_TO_SECS (lookahead_sign, TALER_round_rel_time (&lookahead_sign);
rel_value_us);
lookahead_sign_stamp = GNUNET_TIME_absolute_add (now, lookahead_sign_stamp = GNUNET_TIME_absolute_add (now,
lookahead_sign); lookahead_sign);

View File

@ -126,6 +126,7 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
&deposit->h_wire, &deposit->h_wire,
&deposit->h_contract, &deposit->h_contract,
deposit->transaction_id, deposit->transaction_id,
deposit->timestamp,
deposit->refund_deadline, deposit->refund_deadline,
&deposit->merchant_pub, &deposit->merchant_pub,
&amount_without_fee); &amount_without_fee);
@ -194,14 +195,19 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection,
TALER_LOG_WARNING ("/deposit transaction commit failed\n"); TALER_LOG_WARNING ("/deposit transaction commit failed\n");
return TMH_RESPONSE_reply_commit_error (connection); 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, return TMH_RESPONSE_reply_deposit_success (connection,
&deposit->coin.coin_pub, &deposit->coin.coin_pub,
&deposit->h_wire, &deposit->h_wire,
&deposit->h_contract, &deposit->h_contract,
deposit->transaction_id, deposit->transaction_id,
deposit->timestamp,
deposit->refund_deadline, deposit->refund_deadline,
&deposit->merchant_pub, &deposit->merchant_pub,
&deposit->amount_with_fee); &amount_without_fee);
} }

View File

@ -101,14 +101,12 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
} }
TALER_amount_ntoh (&fee_deposit, TALER_amount_ntoh (&fee_deposit,
&dki->issue.fee_deposit); &dki->issue.fee_deposit);
if (TALER_amount_cmp (&fee_deposit, if (0 < TALER_amount_cmp (&fee_deposit,
&deposit->amount_with_fee) < 0) &deposit->amount_with_fee))
{ {
TMH_KS_release (key_state); TMH_KS_release (key_state);
return (MHD_YES == return TMH_RESPONSE_reply_external_error (connection,
TMH_RESPONSE_reply_external_error (connection, "deposited amount smaller than depositing fee");
"deposited amount smaller than depositing fee"))
? GNUNET_NO : GNUNET_SYSERR;
} }
TMH_KS_release (key_state); 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_contract", &deposit.h_contract),
TMH_PARSE_MEMBER_FIXED ("H_wire", &deposit.h_wire), TMH_PARSE_MEMBER_FIXED ("H_wire", &deposit.h_wire),
TMH_PARSE_MEMBER_FIXED ("coin_sig", &deposit.csig), 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 ("timestamp", &deposit.timestamp),
TMH_PARSE_member_time_abs ("refund_deadline", &deposit.refund_deadline), TMH_PARSE_member_time_abs ("refund_deadline", &deposit.refund_deadline),
TMH_PARSE_MEMBER_END TMH_PARSE_MEMBER_END
@ -160,6 +158,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
return MHD_NO; /* hard failure */ return MHD_NO; /* hard failure */
if (GNUNET_NO == res) if (GNUNET_NO == res)
return MHD_YES; /* failure */ return MHD_YES; /* failure */
if (GNUNET_YES != if (GNUNET_YES !=
TALER_json_validate_wireformat (TMH_expected_wire_format, TALER_json_validate_wireformat (TMH_expected_wire_format,
wire)) wire))
@ -197,7 +196,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection,
&deposit.deposit_fee)) &deposit.deposit_fee))
{ {
/* Total amount smaller than fee, invalid */ /* Total amount smaller than fee, invalid */
TMH_PARSE_release_data (spec); TMH_PARSE_release_data (spec);
return TMH_RESPONSE_reply_arg_invalid (connection, return TMH_RESPONSE_reply_arg_invalid (connection,
"f"); "f");
} }
@ -247,7 +246,7 @@ TMH_DEPOSIT_handler_deposit (struct TMH_RequestHandler *rh,
if ( (GNUNET_NO == res) || (NULL == json) ) if ( (GNUNET_NO == res) || (NULL == json) )
return MHD_YES; return MHD_YES;
if (-1 == json_unpack (json, if (-1 == json_unpack (json,
"{s:s, s:o, f:o}", "{s:o, s:o}",
"wire", &wire, "wire", &wire,
"f", &f)) "f", &f))
{ {

View File

@ -494,6 +494,7 @@ TMH_KS_acquire (void)
key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32, key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32,
GNUNET_NO); GNUNET_NO);
key_state->reload_time = GNUNET_TIME_absolute_get (); key_state->reload_time = GNUNET_TIME_absolute_get ();
TALER_round_abs_time (&key_state->reload_time);
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Loading keys from `%s'\n", "Loading keys from `%s'\n",
TMH_mint_directory); TMH_mint_directory);

View File

@ -549,6 +549,28 @@ TMH_PARSE_navigate_json (struct MHD_Connection *connection,
} }
break; 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: case TMH_PARSE_JNC_RET_RSA_PUBLIC_KEY:
{ {
struct TALER_DenominationPublicKey *where; struct TALER_DenominationPublicKey *where;
@ -803,6 +825,16 @@ TMH_PARSE_json_data (struct MHD_Connection *connection,
TMH_PARSE_JNC_RET_TIME_ABSOLUTE, TMH_PARSE_JNC_RET_TIME_ABSOLUTE,
spec[i].destination); spec[i].destination);
break; 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) if (GNUNET_YES != ret)
@ -882,6 +914,8 @@ TMH_PARSE_release_data (struct TMH_PARSE_FieldSpecification *spec)
break; break;
case TMH_PARSE_JNC_RET_TIME_ABSOLUTE: case TMH_PARSE_JNC_RET_TIME_ABSOLUTE:
break; 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 * Parse absolute time specified in JSON format. The JSON format is
* "/TIMEVAL/" where TIMEVAL is in milliseconds. Additionally, we * "/Date(TIMEVAL)/" where TIMEVAL is in seconds after the Unix Epoch.
* support "/forever/" to represent the end of time. * Additionally, we support "/forever/" and "/never/" to represent the
* end of time.
* *
* @param connection the MHD connection (to report errors) * @param connection the MHD connection (to report errors)
* @param f json specification of the amount * @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) struct GNUNET_TIME_Absolute *time)
{ {
const char *val; const char *val;
size_t slen; unsigned long long tval;
unsigned long long int tval;
char *endp;
val = json_string_value (f); val = json_string_value (f);
if (NULL == val) if (NULL == val)
@ -921,30 +954,18 @@ TMH_PARSE_time_abs_json (struct MHD_Connection *connection,
return GNUNET_SYSERR; return GNUNET_SYSERR;
return GNUNET_NO; return GNUNET_NO;
} }
slen = strlen (val); if ( (0 == strcasecmp (val,
if ( (slen <= 2) || "/forever/")) ||
('/' != val[0]) || (0 == strcasecmp (val,
('/' != val[slen - 1]) ) "/never/")) )
{
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/"))
{ {
*time = GNUNET_TIME_UNIT_FOREVER_ABS; *time = GNUNET_TIME_UNIT_FOREVER_ABS;
return GNUNET_OK; return GNUNET_OK;
} }
tval = strtoull (&val[1], if (1 != sscanf (val,
&endp, "/Date(%llu)/",
10); &tval))
if (&val[slen - 1] != endp)
{ {
if (MHD_YES != if (MHD_YES !=
TMH_RESPONSE_reply_json_pack (connection, TMH_RESPONSE_reply_json_pack (connection,
@ -955,9 +976,9 @@ TMH_PARSE_time_abs_json (struct MHD_Connection *connection,
return GNUNET_SYSERR; return GNUNET_SYSERR;
return GNUNET_NO; return GNUNET_NO;
} }
/* Time is in 'ms' in JSON, but in microseconds in GNUNET_TIME_Absolute */ /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
time->abs_value_us = tval * 1000LL; time->abs_value_us = tval * 1000LL * 1000LL;
if ( (time->abs_value_us) / 1000LL != tval) if ( (time->abs_value_us) / 1000LL / 1000LL != tval)
{ {
/* Integer overflow */ /* Integer overflow */
if (MHD_YES != if (MHD_YES !=
@ -1047,6 +1068,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. * Generate line in parser specification for JSON object value.
* *

View File

@ -133,7 +133,14 @@ enum TMH_PARSE_JsonNavigationCommand
* encoded within its own json object. * encoded within its own json object.
* Param: struct GNUNET_TIME_Absolute * * 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
}; };
@ -253,11 +260,24 @@ TMH_PARSE_release_data (struct TMH_PARSE_FieldSpecification *spec);
#define TMH_PARSE_MEMBER_VARIABLE(field) { field, NULL, 0, 0, TMH_PARSE_JNC_RET_DATA_VAR, 0 } #define TMH_PARSE_MEMBER_VARIABLE(field) { field, NULL, 0, 0, TMH_PARSE_JNC_RET_DATA_VAR, 0 }
/**
* 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. * Generate line in parser specification for JSON array value.
* *
* @param field name of the field * @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 * @return corresponding field spec
*/ */
struct TMH_PARSE_FieldSpecification struct TMH_PARSE_FieldSpecification
@ -269,7 +289,7 @@ TMH_PARSE_member_array (const char *field,
* Generate line in parser specification for JSON object value. * Generate line in parser specification for JSON object value.
* *
* @param field name of the field * @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 * @return corresponding field spec
*/ */
struct TMH_PARSE_FieldSpecification 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 * Parse absolute time specified in JSON format. The JSON format is
* "/TIMEVAL/" where TIMEVAL is in milliseconds. Additionally, we * "/TIMEVAL/" where TIMEVAL is in seconds. Additionally, we
* support "/forever/" to represent the end of time. * support "/forever/" and "/never/" to represent the end of time.
* *
* @param connection the MHD connection (to report errors) * @param connection the MHD connection (to report errors)
* @param f json specification of the amount * @param f json specification of the amount

View File

@ -330,6 +330,7 @@ TMH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection)
* @param h_wire hash of wire details * @param h_wire hash of wire details
* @param h_contract hash of contract details * @param h_contract hash of contract details
* @param transaction_id transaction ID * @param transaction_id transaction ID
* @param timestamp client's timestamp
* @param refund_deadline until when this deposit be refunded * @param refund_deadline until when this deposit be refunded
* @param merchant merchant public key * @param merchant merchant public key
* @param amount_without_fee fraction of coin value to deposit, without the fee * @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_wire,
const struct GNUNET_HashCode *h_contract, const struct GNUNET_HashCode *h_contract,
uint64_t transaction_id, uint64_t transaction_id,
struct GNUNET_TIME_Absolute timestamp,
struct GNUNET_TIME_Absolute refund_deadline, struct GNUNET_TIME_Absolute refund_deadline,
const struct TALER_MerchantPublicKeyP *merchant, const struct TALER_MerchantPublicKeyP *merchant,
const struct TALER_Amount *amount_without_fee) 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_DepositConfirmationPS dc;
struct TALER_MintSignatureP sig; struct TALER_MintSignatureP sig;
json_t *sig_json; json_t *sig_json;
int ret;
dc.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_DEPOSIT); dc.purpose.purpose = htonl (TALER_SIGNATURE_MINT_CONFIRM_DEPOSIT);
dc.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)); dc.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS));
dc.h_contract = *h_contract; dc.h_contract = *h_contract;
dc.h_wire = *h_wire; dc.h_wire = *h_wire;
dc.transaction_id = GNUNET_htonll (transaction_id); 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); dc.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
TALER_amount_hton (&dc.amount_without_fee, TALER_amount_hton (&dc.amount_without_fee,
amount_without_fee); amount_without_fee);
@ -363,15 +364,13 @@ TMH_RESPONSE_reply_deposit_success (struct MHD_Connection *connection,
dc.merchant = *merchant; dc.merchant = *merchant;
TMH_KS_sign (&dc.purpose, TMH_KS_sign (&dc.purpose,
&sig); &sig);
sig_json = TALER_json_from_eddsa_sig (&dc.purpose, sig_json = TALER_json_from_data (&sig,
&sig.eddsa_signature); sizeof (sig));
ret = TMH_RESPONSE_reply_json_pack (connection, return TMH_RESPONSE_reply_json_pack (connection,
MHD_HTTP_OK, MHD_HTTP_OK,
"{s:s, s:o}", "{s:s, s:o}",
"status", "DEPOSIT_OK", "status", "DEPOSIT_OK",
"signature", sig_json); "sig", sig_json);
json_decref (sig_json);
return ret;
} }

View File

@ -205,6 +205,7 @@ TMH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection);
* @param h_wire hash of wire details * @param h_wire hash of wire details
* @param h_contract hash of contract details * @param h_contract hash of contract details
* @param transaction_id transaction ID * @param transaction_id transaction ID
* @param timestamp client's timestamp
* @param refund_deadline until when this deposit be refunded * @param refund_deadline until when this deposit be refunded
* @param merchant merchant public key * @param merchant merchant public key
* @param amount_without_fee fraction of coin value to deposit (without fee) * @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_wire,
const struct GNUNET_HashCode *h_contract, const struct GNUNET_HashCode *h_contract,
uint64_t transaction_id, 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); const struct TALER_Amount *amount_without_fee);

View File

@ -89,11 +89,13 @@ TALER_json_from_abs (struct GNUNET_TIME_Absolute stamp)
char *mystr; char *mystr;
int ret; int ret;
GNUNET_assert (GNUNET_OK ==
TALER_round_abs_time (&stamp));
if (stamp.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) if (stamp.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
return json_string ("/never/"); return json_string ("/never/");
ret = GNUNET_asprintf (&mystr, ret = GNUNET_asprintf (&mystr,
"/%llu/", "/Date(%llu)/",
(long long) (stamp.abs_value_us / (1000LL * 1000LL))); (unsigned long long) (stamp.abs_value_us / (1000LL * 1000LL)));
GNUNET_assert (ret > 0); GNUNET_assert (ret > 0);
j = json_string (mystr); j = json_string (mystr);
GNUNET_free (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 json the json object representing Amount
* @param[out] abs where the amount has to be written * @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) struct GNUNET_TIME_Absolute *abs)
{ {
const char *val; const char *val;
size_t slen;
unsigned long long int tval; unsigned long long int tval;
char *endp;
val = json_string_value (json); val = json_string_value (json);
if (NULL == val) if (NULL == val)
@ -341,14 +341,6 @@ TALER_json_to_abs (json_t *json,
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; 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, if ( (0 == strcasecmp (val,
"/forever/")) || "/forever/")) ||
(0 == strcasecmp (val, (0 == strcasecmp (val,
@ -357,10 +349,9 @@ TALER_json_to_abs (json_t *json,
*abs = GNUNET_TIME_UNIT_FOREVER_ABS; *abs = GNUNET_TIME_UNIT_FOREVER_ABS;
return GNUNET_OK; return GNUNET_OK;
} }
tval = strtoull (&val[1], if (1 != sscanf (val,
&endp, "/Date(%llu)/",
10); &tval))
if (&val[slen - 1] != endp)
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;

View File

@ -65,7 +65,7 @@ test_time ()
struct GNUNET_TIME_Absolute a2; struct GNUNET_TIME_Absolute a2;
a1 = GNUNET_TIME_absolute_get (); 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); j = TALER_json_from_abs (a1);
GNUNET_assert (NULL != j); GNUNET_assert (NULL != j);
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
@ -110,7 +110,7 @@ test_raw ()
TALER_json_to_data (j, TALER_json_to_data (j,
blob2, blob2,
i)); i));
GNUNET_assert (0 == GNUNET_assert (0 ==
memcmp (blob, memcmp (blob,
blob2, blob2,
i)); i));

View File

@ -63,6 +63,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 * Load configuration by parsing all configuration
* files in the given directory. * files in the given directory.

View File

@ -330,7 +330,7 @@ validate_sepa (const json_t *wire)
((json_t *) wire, ((json_t *) wire,
&error, JSON_STRICT, &error, JSON_STRICT,
"{" "{"
"s:s " /* type: "SEPA" */ "s:s " /* TYPE: sepa */
"s:s " /* IBAN: iban */ "s:s " /* IBAN: iban */
"s:s " /* name: beneficiary name */ "s:s " /* name: beneficiary name */
"s:s " /* BIC: beneficiary bank's BIC */ "s:s " /* BIC: beneficiary bank's BIC */
@ -345,7 +345,6 @@ validate_sepa (const json_t *wire)
"edate", &edate, "edate", &edate,
"r", &r, "r", &r,
"address", &address)); "address", &address));
EXITIF (0 != strcmp (type, "SEPA"));
if (1 != validate_iban (iban)) if (1 != validate_iban (iban))
{ {
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@ -359,6 +358,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. * Handler for a wire format.
*/ */
@ -392,9 +405,29 @@ TALER_json_validate_wireformat (const char *type,
{ {
static const struct FormatHandler format_handlers[] = { static const struct FormatHandler format_handlers[] = {
{ "SEPA", &validate_sepa }, { "SEPA", &validate_sepa },
{ "TEST", &validate_test },
{ NULL, NULL} { NULL, NULL}
}; };
unsigned int i; 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++) for (i=0;NULL != format_handlers[i].type;i++)
if (0 == strcasecmp (format_handlers[i].type, if (0 == strcasecmp (format_handlers[i].type,
@ -404,6 +437,8 @@ TALER_json_validate_wireformat (const char *type,
"Wireformat `%s' not supported\n", "Wireformat `%s' not supported\n",
type); type);
return GNUNET_NO; return GNUNET_NO;
EXITIF_exit:
return GNUNET_NO;
} }
/* end of wireformats.c */ /* end of wireformats.c */