-work on reserve control tests

This commit is contained in:
Christian Grothoff 2022-10-12 22:16:40 +02:00
parent 3b34acdb72
commit 4702b156dc
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
13 changed files with 101 additions and 85 deletions

View File

@ -388,10 +388,6 @@ handle_post_reserves (struct TEH_RequestContext *rc,
.op = "open", .op = "open",
.handler = &TEH_handler_reserves_open .handler = &TEH_handler_reserves_open
}, },
{
.op = "attest",
.handler = &TEH_handler_reserves_attest
},
{ {
.op = "close", .op = "close",
.handler = &TEH_handler_reserves_close .handler = &TEH_handler_reserves_close
@ -1054,27 +1050,6 @@ handle_post_auditors (struct TEH_RequestContext *rc,
} }
/**
* Handle a GET "/reserves/$RID/$XXX" request.
*
* @param rc request context
* @param args array of additional options (length: 1, just the reserve_pub)
* @return MHD result code
*/
static MHD_RESULT
handler_reserves_get3 (struct TEH_RequestContext *rc,
const char *const args[3])
{
if (0 == strcmp (args[2],
"attest"))
return TEH_handler_reserves_get_attest (rc,
args);
GNUNET_break_op (0);
return r404 (rc->connection,
"/reserves/$RID/*");
}
/** /**
* Handle incoming HTTP request. * Handle incoming HTTP request.
* *
@ -1188,18 +1163,24 @@ handle_mhd_request (void *cls,
.handler.get = &TEH_handler_reserves_get, .handler.get = &TEH_handler_reserves_get,
.nargs = 1 .nargs = 1
}, },
{
.url = "reserves",
.method = MHD_HTTP_METHOD_GET,
.handler.get = &handler_reserves_get3,
.nargs = 3
},
{ {
.url = "reserves", .url = "reserves",
.method = MHD_HTTP_METHOD_POST, .method = MHD_HTTP_METHOD_POST,
.handler.post = &handle_post_reserves, .handler.post = &handle_post_reserves,
.nargs = 2 .nargs = 2
}, },
{
.url = "reserves-attest",
.method = MHD_HTTP_METHOD_GET,
.handler.get = &TEH_handler_reserves_get_attest,
.nargs = 1
},
{
.url = "reserves-attest",
.method = MHD_HTTP_METHOD_POST,
.handler.post = &TEH_handler_reserves_attest,
.nargs = 1
},
/* coins */ /* coins */
{ {
.url = "coins", .url = "coins",
@ -1441,7 +1422,8 @@ handle_mhd_request (void *cls,
continue; continue;
found = true; found = true;
/* The URL is a match! What we now do depends on the method. */ /* The URL is a match! What we now do depends on the method. */
if (0 == strcasecmp (method, MHD_HTTP_METHOD_OPTIONS)) if (0 == strcasecmp (method,
MHD_HTTP_METHOD_OPTIONS))
{ {
GNUNET_async_scope_restore (&old_scope); GNUNET_async_scope_restore (&old_scope);
return TALER_MHD_reply_cors_preflight (connection); return TALER_MHD_reply_cors_preflight (connection);

View File

@ -48,7 +48,7 @@ struct ReserveAttestContext
/** /**
* Public key of the reserve the inquiry is about. * Public key of the reserve the inquiry is about.
*/ */
const struct TALER_ReservePublicKeyP *reserve_pub; struct TALER_ReservePublicKeyP reserve_pub;
/** /**
* Hash of the payto URI of this reserve. * Hash of the payto URI of this reserve.
@ -122,7 +122,7 @@ reply_reserve_attest_success (struct MHD_Connection *connection,
&TEH_keys_exchange_sign_, &TEH_keys_exchange_sign_,
now, now,
rhc->etime, rhc->etime,
rhc->reserve_pub, &rhc->reserve_pub,
rhc->json_attest, rhc->json_attest,
&exchange_pub, &exchange_pub,
&exchange_sig); &exchange_sig);
@ -273,8 +273,8 @@ reserve_attest_transaction (void *cls,
MHD_RESULT MHD_RESULT
TEH_handler_reserves_attest (struct TEH_RequestContext *rc, TEH_handler_reserves_attest (struct TEH_RequestContext *rc,
const struct TALER_ReservePublicKeyP *reserve_pub, const json_t *root,
const json_t *root) const char *const args[1])
{ {
struct ReserveAttestContext rsc = { struct ReserveAttestContext rsc = {
.etime = GNUNET_TIME_UNIT_FOREVER_TS .etime = GNUNET_TIME_UNIT_FOREVER_TS
@ -291,7 +291,18 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,
}; };
struct GNUNET_TIME_Timestamp now; struct GNUNET_TIME_Timestamp now;
rsc.reserve_pub = reserve_pub; if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[0],
strlen (args[0]),
&rsc.reserve_pub,
sizeof (rsc.reserve_pub)))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_RESERVE_PUB_MALFORMED,
args[0]);
}
{ {
enum GNUNET_GenericReturnValue res; enum GNUNET_GenericReturnValue res;
@ -324,7 +335,7 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,
if (GNUNET_OK != if (GNUNET_OK !=
TALER_wallet_reserve_attest_request_verify (rsc.timestamp, TALER_wallet_reserve_attest_request_verify (rsc.timestamp,
rsc.details, rsc.details,
reserve_pub, &rsc.reserve_pub,
&rsc.reserve_sig)) &rsc.reserve_sig))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
@ -338,7 +349,7 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,
char *payto_uri; char *payto_uri;
payto_uri = TALER_reserve_make_payto (TEH_base_url, payto_uri = TALER_reserve_make_payto (TEH_base_url,
rsc.reserve_pub); &rsc.reserve_pub);
TALER_payto_hash (payto_uri, TALER_payto_hash (payto_uri,
&rsc.h_payto); &rsc.h_payto);
GNUNET_free (payto_uri); GNUNET_free (payto_uri);
@ -360,7 +371,7 @@ TEH_handler_reserves_attest (struct TEH_RequestContext *rc,
return TALER_MHD_reply_with_error (rc->connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_NOT_FOUND, MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN, TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN,
NULL); args[0]);
} }
if (TALER_EC_NONE != rsc.ec) if (TALER_EC_NONE != rsc.ec)
{ {

View File

@ -26,16 +26,16 @@
/** /**
* Handle a POST "/reserves/$RID/attest" request. * Handle a POST "/reserves-attest/$RID" request.
* *
* @param rc request context * @param rc request context
* @param reserve_pub public key of the reserve
* @param root uploaded body from the client * @param root uploaded body from the client
* @param args args[0] has public key of the reserve
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_reserves_attest (struct TEH_RequestContext *rc, TEH_handler_reserves_attest (struct TEH_RequestContext *rc,
const struct TALER_ReservePublicKeyP *reserve_pub, const json_t *root,
const json_t *root); const char *const args[1]);
#endif #endif

View File

@ -108,6 +108,7 @@ struct ReserveOpenContext
* for the operation. * for the operation.
*/ */
bool no_funds; bool no_funds;
}; };
@ -122,6 +123,8 @@ static MHD_RESULT
reply_reserve_open_success (struct MHD_Connection *connection, reply_reserve_open_success (struct MHD_Connection *connection,
const struct ReserveOpenContext *rsc) const struct ReserveOpenContext *rsc)
{ {
struct GNUNET_TIME_Timestamp now;
struct GNUNET_TIME_Timestamp re;
unsigned int status; unsigned int status;
status = MHD_HTTP_OK; status = MHD_HTTP_OK;
@ -129,11 +132,18 @@ reply_reserve_open_success (struct MHD_Connection *connection,
<, <,
rsc->desired_expiration)) rsc->desired_expiration))
status = MHD_HTTP_PAYMENT_REQUIRED; status = MHD_HTTP_PAYMENT_REQUIRED;
now = GNUNET_TIME_timestamp_get ();
if (GNUNET_TIME_timestamp_cmp (rsc->reserve_expiration,
<,
now))
re = now;
else
re = rsc->reserve_expiration;
return TALER_MHD_REPLY_JSON_PACK ( return TALER_MHD_REPLY_JSON_PACK (
connection, connection,
status, status,
GNUNET_JSON_pack_timestamp ("reserve_expiration", GNUNET_JSON_pack_timestamp ("reserve_expiration",
rsc->reserve_expiration), re),
TALER_JSON_pack_amount ("open_cost", TALER_JSON_pack_amount ("open_cost",
&rsc->open_cost)); &rsc->open_cost));
} }
@ -234,7 +244,8 @@ reserve_open_transaction (void *cls,
} }
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Do reserve open\n"); "Do reserve open with reserve payment of %s\n",
TALER_amount2s (&rsc->total));
qs = TEH_plugin->do_reserve_open (TEH_plugin->cls, qs = TEH_plugin->do_reserve_open (TEH_plugin->cls,
/* inputs */ /* inputs */
rsc->reserve_pub, rsc->reserve_pub,

View File

@ -460,8 +460,7 @@ BEGIN
'CREATE TABLE IF NOT EXISTS %I' 'CREATE TABLE IF NOT EXISTS %I'
'(reserve_open_deposit_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE / PRIMARY KEY' '(reserve_open_deposit_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE / PRIMARY KEY'
',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)' ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=32)' ',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32)'
',request_timestamp INT8 NOT NULL'
',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)' ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)'
',coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)' ',coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)'
',contribution_val INT8 NOT NULL' ',contribution_val INT8 NOT NULL'
@ -482,7 +481,7 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_reserve ' 'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_reserve '
'ON ' || table_name || ' ' 'ON ' || table_name || ' '
'(reserve_pub,request_timestamp);' '(reserve_pub);'
); );
END END
$$; $$;

View File

@ -259,8 +259,8 @@ SELECT create_table_reserves_open_deposits();
COMMENT ON TABLE reserves_open_deposits COMMENT ON TABLE reserves_open_deposits
IS 'coin contributions paying for a reserve to remain open'; IS 'coin contributions paying for a reserve to remain open';
COMMENT ON COLUMN reserves_open_deposits.request_timestamp COMMENT ON COLUMN reserves_open_deposits.reserve_pub
IS 'Identifies the specific reserve open request being paid for.'; IS 'Identifies the specific reserve being paid for (possibly together with reserve_sig).';
CREATE TABLE IF NOT EXISTS reserves_open_deposits_default CREATE TABLE IF NOT EXISTS reserves_open_deposits_default
PARTITION OF reserves_open_deposits PARTITION OF reserves_open_deposits

View File

@ -357,8 +357,6 @@ irbt_cb_table_reserves_open_requests (struct PostgresClosure *pg,
{ {
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint64 (&td->serial), GNUNET_PQ_query_param_uint64 (&td->serial),
GNUNET_PQ_query_param_timestamp (
&td->details.reserves_open_requests.request_timestamp),
GNUNET_PQ_query_param_timestamp ( GNUNET_PQ_query_param_timestamp (
&td->details.reserves_open_requests.expiration_date), &td->details.reserves_open_requests.expiration_date),
GNUNET_PQ_query_param_auto_from_type ( GNUNET_PQ_query_param_auto_from_type (
@ -402,8 +400,6 @@ irbt_cb_table_reserves_open_deposits (
{ {
struct GNUNET_PQ_QueryParam params[] = { struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint64 (&td->serial), GNUNET_PQ_query_param_uint64 (&td->serial),
GNUNET_PQ_query_param_timestamp (
&td->details.reserves_open_deposits.request_timestamp),
GNUNET_PQ_query_param_auto_from_type ( GNUNET_PQ_query_param_auto_from_type (
&td->details.reserves_open_deposits.coin_pub), &td->details.reserves_open_deposits.coin_pub),
GNUNET_PQ_query_param_auto_from_type ( GNUNET_PQ_query_param_auto_from_type (
@ -421,13 +417,12 @@ irbt_cb_table_reserves_open_deposits (
"(reserve_open_deposit_uuid" "(reserve_open_deposit_uuid"
",reserve_sig" ",reserve_sig"
",reserve_pub" ",reserve_pub"
",request_timestamp"
",coin_pub" ",coin_pub"
",coin_sig" ",coin_sig"
",contribution_val" ",contribution_val"
",contribution_frac" ",contribution_frac"
") VALUES " ") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8);"); "($1, $2, $3, $4, $5, $6, $7);");
return GNUNET_PQ_eval_prepared_non_select (pg->conn, return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"insert_into_table_reserves_open_deposits", "insert_into_table_reserves_open_deposits",
params); params);

View File

@ -2119,7 +2119,6 @@ BEGIN
INSERT INTO exchange.reserves_open_deposits INSERT INTO exchange.reserves_open_deposits
(reserve_sig (reserve_sig
,reserve_pub ,reserve_pub
,request_timestamp
,coin_pub ,coin_pub
,coin_sig ,coin_sig
,contribution_val ,contribution_val
@ -2128,7 +2127,6 @@ INSERT INTO exchange.reserves_open_deposits
VALUES VALUES
(in_reserve_sig (in_reserve_sig
,in_reserve_pub ,in_reserve_pub
,in_request_timestamp
,in_coin_pub ,in_coin_pub
,in_coin_sig ,in_coin_sig
,in_coin_total_val ,in_coin_total_val
@ -2238,6 +2236,7 @@ WHERE
IF NOT FOUND IF NOT FOUND
THEN THEN
-- FIXME: do we need to set a 'not found'? -- FIXME: do we need to set a 'not found'?
RAISE NOTICE 'reserve not found';
RETURN; RETURN;
END IF; END IF;
@ -2272,6 +2271,7 @@ THEN
my_purses_allowed = my_purses_allowed + (in_default_purse_limit * my_years_tmp); my_purses_allowed = my_purses_allowed + (in_default_purse_limit * my_years_tmp);
END IF; END IF;
-- Compute cost based on annual fees -- Compute cost based on annual fees
IF (my_years > 0) IF (my_years > 0)
THEN THEN
@ -2282,8 +2282,9 @@ THEN
out_open_cost_val=9223372036854775807; out_open_cost_val=9223372036854775807;
out_open_cost_frac=2147483647; out_open_cost_frac=2147483647;
out_final_expiration=my_expiration_date; out_final_expiration=my_expiration_date;
out_no_funds=true; out_no_funds=FALSE;
RETURN; RAISE NOTICE 'arithmetic issue computing amount';
RETURN;
END IF; END IF;
my_cost_val = CAST (my_cost_val + my_cost_tmp AS INT8); my_cost_val = CAST (my_cost_val + my_cost_tmp AS INT8);
my_cost_frac = my_years * in_open_fee_frac % 100000000; my_cost_frac = my_years * in_open_fee_frac % 100000000;
@ -2297,6 +2298,7 @@ THEN
out_open_cost_val = 0; out_open_cost_val = 0;
out_open_cost_frac = 0; out_open_cost_frac = 0;
out_no_funds=FALSE; out_no_funds=FALSE;
RAISE NOTICE 'no change required';
RETURN; RETURN;
END IF; END IF;
@ -2305,10 +2307,22 @@ IF ( (in_total_paid_val < my_cost_val) OR
( (in_total_paid_val = my_cost_val) AND ( (in_total_paid_val = my_cost_val) AND
(in_total_paid_frac < my_cost_frac) ) ) (in_total_paid_frac < my_cost_frac) ) )
THEN THEN
out_final_expiration=my_reserve_expiration;
out_open_cost_val = my_cost_val; out_open_cost_val = my_cost_val;
out_open_cost_frac = my_cost_frac; out_open_cost_frac = my_cost_frac;
out_no_funds=TRUE; out_no_funds=FALSE;
-- We must return a failure, which is indicated by
-- the expiration being below the desired expiration.
IF (my_reserve_expiration >= in_desired_expiration)
THEN
-- This case is relevant especially if the purse
-- count was to be increased and the payment was
-- insufficient to cover this for the full period.
RAISE NOTICE 'forcing low expiration time';
out_final_expiration = 0;
ELSE
out_final_expiration = my_reserve_expiration;
END IF;
RAISE NOTICE 'amount paid too low';
RETURN; RETURN;
END IF; END IF;
@ -2329,11 +2343,12 @@ ELSE
my_balance_val=0; my_balance_val=0;
my_balance_frac=my_balance_frac - in_reserve_payment_frac; my_balance_frac=my_balance_frac - in_reserve_payment_frac;
ELSE ELSE
out_final_expiration=my_reserve_expiration; out_final_expiration = my_reserve_expiration;
out_open_cost_val = my_cost_val; out_open_cost_val = my_cost_val;
out_open_cost_frac = my_cost_frac; out_open_cost_frac = my_cost_frac;
out_no_funds=TRUE; out_no_funds=TRUE;
RETURN; RAISE NOTICE 'reserve balance too low';
RETURN;
END IF; END IF;
END IF; END IF;
@ -2341,12 +2356,12 @@ UPDATE reserves SET
current_balance_val=my_balance_val current_balance_val=my_balance_val
,current_balance_frac=my_balance_frac ,current_balance_frac=my_balance_frac
,gc_date=my_reserve_expiration + in_reserve_gc_delay ,gc_date=my_reserve_expiration + in_reserve_gc_delay
,expiration_date=my_reserve_expiration ,expiration_date=my_expiration_date
,purses_allowed=my_purses_allowed ,purses_allowed=my_purses_allowed
WHERE WHERE
reserve_pub=in_reserve_pub; reserve_pub=in_reserve_pub;
out_final_expiration=my_reserve_expiration; out_final_expiration=my_expiration_date;
out_open_cost_val = my_cost_val; out_open_cost_val = my_cost_val;
out_open_cost_frac = my_cost_frac; out_open_cost_frac = my_cost_frac;
out_no_funds=FALSE; out_no_funds=FALSE;

View File

@ -331,7 +331,6 @@ struct TALER_EXCHANGEDB_TableData
struct struct
{ {
struct TALER_ReservePublicKeyP reserve_pub; struct TALER_ReservePublicKeyP reserve_pub;
struct GNUNET_TIME_Timestamp request_timestamp;
struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_CoinSpendSignatureP coin_sig; struct TALER_CoinSpendSignatureP coin_sig;
struct TALER_ReserveSignatureP reserve_sig; struct TALER_ReserveSignatureP reserve_sig;

View File

@ -16,7 +16,7 @@
*/ */
/** /**
* @file lib/exchange_api_reserves_attest.c * @file lib/exchange_api_reserves_attest.c
* @brief Implementation of the POST /reserves/$RESERVE_PUB/attest requests * @brief Implementation of the POST /reserves-attest/$RESERVE_PUB requests
* @author Christian Grothoff * @author Christian Grothoff
*/ */
#include "platform.h" #include "platform.h"
@ -33,7 +33,7 @@
/** /**
* @brief A /reserves/$RID/attest Handle * @brief A /reserves-attest/$RID Handle
*/ */
struct TALER_EXCHANGE_ReservesAttestHandle struct TALER_EXCHANGE_ReservesAttestHandle
{ {
@ -141,7 +141,7 @@ handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh,
/** /**
* Function called when we're done processing the * Function called when we're done processing the
* HTTP /reserves/$RID/attest request. * HTTP /reserves-attest/$RID request.
* *
* @param cls the `struct TALER_EXCHANGE_ReservesAttestHandle` * @param cls the `struct TALER_EXCHANGE_ReservesAttestHandle`
* @param response_code HTTP response code, 0 on error * @param response_code HTTP response code, 0 on error
@ -280,7 +280,7 @@ TALER_EXCHANGE_reserves_attest (
*end = '\0'; *end = '\0';
GNUNET_snprintf (arg_str, GNUNET_snprintf (arg_str,
sizeof (arg_str), sizeof (arg_str),
"/reserves/%s/attest", "/reserves-attest/%s",
pub_str); pub_str);
} }
rsh->url = TEAH_path_to_url (exchange, rsh->url = TEAH_path_to_url (exchange,

View File

@ -133,7 +133,7 @@ handle_reserves_get_attestable_ok (
/** /**
* Function called when we're done processing the * Function called when we're done processing the
* HTTP GET /reserves/$RID/attest request. * HTTP GET /reserves-attest/$RID request.
* *
* @param cls the `struct TALER_EXCHANGE_ReservesGetAttestableHandle` * @param cls the `struct TALER_EXCHANGE_ReservesGetAttestableHandle`
* @param response_code HTTP response code, 0 on error * @param response_code HTTP response code, 0 on error
@ -241,7 +241,7 @@ TALER_EXCHANGE_reserves_get_attestable (
*end = '\0'; *end = '\0';
GNUNET_snprintf (arg_str, GNUNET_snprintf (arg_str,
sizeof (arg_str), sizeof (arg_str),
"/reserves/%s/attest", "/reserves-attest/%s",
pub_str); pub_str);
} }
rgah = GNUNET_new (struct TALER_EXCHANGE_ReservesGetAttestHandle); rgah = GNUNET_new (struct TALER_EXCHANGE_ReservesGetAttestHandle);

View File

@ -382,7 +382,7 @@ run (void *cls,
MHD_HTTP_PAYMENT_REQUIRED, // FIXME: or CONFLICT? MHD_HTTP_PAYMENT_REQUIRED, // FIXME: or CONFLICT?
NULL, NULL,
NULL), NULL),
TALER_TESTING_cmd_reserve_open ("reserve-open-101-ok", TALER_TESTING_cmd_reserve_open ("reserve-open-101-ok-a",
"create-reserve-101", "create-reserve-101",
"EUR:0.01", "EUR:0.01",
GNUNET_TIME_UNIT_MONTHS, GNUNET_TIME_UNIT_MONTHS,
@ -394,30 +394,32 @@ run (void *cls,
"create-reserve-101", "create-reserve-101",
"EUR:1.03", "EUR:1.03",
MHD_HTTP_OK), MHD_HTTP_OK),
TALER_TESTING_cmd_reserve_open ("reserve-open-101-ok", TALER_TESTING_cmd_reserve_open ("reserve-open-101-ok-b",
"create-reserve-101", "create-reserve-101",
"EUR:0", "EUR:0",
GNUNET_TIME_UNIT_MONTHS, GNUNET_TIME_UNIT_MONTHS,
2, /* min purses */ 2, /* min purses */
MHD_HTTP_OK, MHD_HTTP_OK,
"withdraw-coin-100", "withdraw-coin-100",
"EUR:0.02", "EUR:0.03", /* 0.02 for the reserve open, 0.01 for deposit fee */
NULL, NULL,
NULL), NULL),
/* FIXME: use purse quota here */ /* FIXME: use purse creation with purse quota here */
TALER_TESTING_cmd_reserve_get_attestable ("reserve-101-attestable", TALER_TESTING_cmd_reserve_get_attestable ("reserve-101-attestable",
"create-reserve-101", "create-reserve-101",
MHD_HTTP_OK, MHD_HTTP_NOT_FOUND,
NULL), NULL),
TALER_TESTING_cmd_reserve_get_attestable ("reserve-101-attest", TALER_TESTING_cmd_reserve_get_attestable ("reserve-101-attest",
"create-reserve-101", "create-reserve-101",
MHD_HTTP_CONFLICT, MHD_HTTP_NOT_FOUND,
"nx-attribute-name", "nx-attribute-name",
NULL), NULL),
#if 0
TALER_TESTING_cmd_reserve_close ("reserve-101-close", TALER_TESTING_cmd_reserve_close ("reserve-101-close",
"create-reserve-101", "create-reserve-101",
NULL, /* to origin */ NULL, /* to origin */
MHD_HTTP_OK), MHD_HTTP_OK),
#endif
TALER_TESTING_cmd_end () TALER_TESTING_cmd_end ()
}; };

View File

@ -319,6 +319,7 @@ TALER_TESTING_cmd_reserve_open (const char *label,
ss->cpl++; ss->cpl++;
va_end (ap); va_end (ap);
GNUNET_assert (0 == (ss->cpl % 2)); GNUNET_assert (0 == (ss->cpl % 2));
ss->cpl /= 2; /* name and amount per coin */
ss->cd = GNUNET_new_array (ss->cpl, ss->cd = GNUNET_new_array (ss->cpl,
struct CoinDetail); struct CoinDetail);
i = 0; i = 0;
@ -326,11 +327,12 @@ TALER_TESTING_cmd_reserve_open (const char *label,
expected_response_code); expected_response_code);
while (NULL != (name = va_arg (ap, const char *))) while (NULL != (name = va_arg (ap, const char *)))
{ {
ss->cd[i].name = name; struct CoinDetail *cd = &ss->cd[i];
cd->name = name;
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount (va_arg (ap, TALER_string_to_amount (va_arg (ap,
const char *), const char *),
&ss->cd[i].amount)); &cd->amount));
i++; i++;
} }
va_end (ap); va_end (ap);