handle reserve open/close responses in reserve history in libtalerexchange

This commit is contained in:
Christian Grothoff 2022-10-15 22:03:55 +02:00
parent 7421142bc1
commit 518c7009e7
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
5 changed files with 216 additions and 13 deletions

View File

@ -1505,7 +1505,7 @@ enum TALER_EXCHANGE_ReserveTransactionType
/** /**
* Reserve closed operation. * Reserve closed operation.
*/ */
TALER_EXCHANGE_RTT_CLOSE, TALER_EXCHANGE_RTT_CLOSING,
/** /**
* Reserve history request. * Reserve history request.
@ -1513,9 +1513,19 @@ enum TALER_EXCHANGE_ReserveTransactionType
TALER_EXCHANGE_RTT_HISTORY, TALER_EXCHANGE_RTT_HISTORY,
/** /**
* Reserve purese merge operation. * Reserve purse merge operation.
*/ */
TALER_EXCHANGE_RTT_MERGE TALER_EXCHANGE_RTT_MERGE,
/**
* Reserve open request operation.
*/
TALER_EXCHANGE_RTT_OPEN,
/**
* Reserve close request operation.
*/
TALER_EXCHANGE_RTT_CLOSE
}; };
@ -1730,6 +1740,71 @@ struct TALER_EXCHANGE_ReserveHistoryEntry
} merge_details; } merge_details;
/**
* Information about an open request operation on the reserve.
* @e type is #TALER_EXCHANGE_RTT_OPEN.
*/
struct
{
/**
* Signature by the reserve approving the open.
*/
struct TALER_ReserveSignatureP reserve_sig;
/**
* Amount to be paid from the reserve balance to open
* the reserve.
*/
struct TALER_Amount reserve_payment;
/**
* When was the request created.
*/
struct GNUNET_TIME_Timestamp request_timestamp;
/**
* For how long should the reserve be kept open.
* (Determines amount to be paid.)
*/
struct GNUNET_TIME_Timestamp reserve_expiration;
/**
* How many open purses should be included with the
* open reserve?
* (Determines amount to be paid.)
*/
uint32_t purse_limit;
} open_request;
/**
* Information about an close request operation on the reserve.
* @e type is #TALER_EXCHANGE_RTT_CLOSE.
*/
struct
{
/**
* Signature by the reserve approving the close.
*/
struct TALER_ReserveSignatureP reserve_sig;
/**
* When was the request created.
*/
struct GNUNET_TIME_Timestamp request_timestamp;
/**
* Hash of the payto://-URI of the target account
* for the closure, or all zeros for the reserve
* origin account.
*/
struct TALER_PaytoHashP target_account_h_payto;
} close_request;
} details; } details;
}; };

View File

@ -340,7 +340,7 @@ parse_closing (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
rh->type = TALER_EXCHANGE_RTT_CLOSE; rh->type = TALER_EXCHANGE_RTT_CLOSING;
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_JSON_parse (transaction, GNUNET_JSON_parse (transaction,
closing_spec, closing_spec,
@ -531,6 +531,120 @@ parse_history (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
} }
/**
* Parse "open" reserve open entry.
*
* @param[in,out] rh entry to parse
* @param uc our context
* @param transaction the transaction to parse
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
parse_open (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
struct HistoryParseContext *uc,
const json_t *transaction)
{
struct GNUNET_JSON_Specification open_spec[] = {
GNUNET_JSON_spec_fixed_auto ("reserve_sig",
&rh->details.open_request.reserve_sig),
TALER_JSON_spec_amount_any ("open_payment",
&rh->details.open_request.reserve_payment),
GNUNET_JSON_spec_uint32 ("requested_min_purses",
&rh->details.open_request.purse_limit),
GNUNET_JSON_spec_timestamp ("request_timestamp",
&rh->details.open_request.request_timestamp),
GNUNET_JSON_spec_timestamp ("requested_expiration",
&rh->details.open_request.reserve_expiration),
GNUNET_JSON_spec_end ()
};
rh->type = TALER_EXCHANGE_RTT_OPEN;
if (GNUNET_OK !=
GNUNET_JSON_parse (transaction,
open_spec,
NULL, NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
if (GNUNET_OK !=
TALER_wallet_reserve_open_verify (
&rh->amount,
rh->details.open_request.request_timestamp,
rh->details.open_request.reserve_expiration,
rh->details.open_request.purse_limit,
uc->reserve_pub,
&rh->details.open_request.reserve_sig))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
if (0 >
TALER_amount_add (uc->total_out,
uc->total_out,
&rh->amount))
{
/* overflow in history already!? inconceivable! Bad exchange! */
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
/**
* Parse "close" reserve close entry.
*
* @param[in,out] rh entry to parse
* @param uc our context
* @param transaction the transaction to parse
* @return #GNUNET_OK on success
*/
static enum GNUNET_GenericReturnValue
parse_close (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
struct HistoryParseContext *uc,
const json_t *transaction)
{
struct GNUNET_JSON_Specification close_spec[] = {
GNUNET_JSON_spec_fixed_auto ("reserve_sig",
&rh->details.close_request.reserve_sig),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("h_payto",
&rh->details.close_request.
target_account_h_payto),
NULL),
GNUNET_JSON_spec_timestamp ("request_timestamp",
&rh->details.close_request.request_timestamp),
GNUNET_JSON_spec_end ()
};
rh->type = TALER_EXCHANGE_RTT_CLOSE;
if (GNUNET_OK !=
GNUNET_JSON_parse (transaction,
close_spec,
NULL, NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
/* force amount to invalid */
memset (&rh->amount,
0,
sizeof (rh->amount));
if (GNUNET_OK !=
TALER_wallet_reserve_close_verify (
rh->details.close_request.request_timestamp,
&rh->details.close_request.target_account_h_payto,
uc->reserve_pub,
&rh->details.close_request.reserve_sig))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
}
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
TALER_EXCHANGE_parse_reserve_history ( TALER_EXCHANGE_parse_reserve_history (
struct TALER_EXCHANGE_Handle *exchange, struct TALER_EXCHANGE_Handle *exchange,
@ -553,6 +667,8 @@ TALER_EXCHANGE_parse_reserve_history (
{ "MERGE", &parse_merge }, { "MERGE", &parse_merge },
{ "CLOSING", &parse_closing }, { "CLOSING", &parse_closing },
{ "HISTORY", &parse_history }, { "HISTORY", &parse_history },
{ "OPEN", &parse_open },
{ "CLOSE", &parse_close },
{ NULL, NULL } { NULL, NULL }
}; };
struct GNUNET_HashCode uuid[history_length]; struct GNUNET_HashCode uuid[history_length];
@ -651,12 +767,16 @@ TALER_EXCHANGE_free_reserve_history (
break; break;
case TALER_EXCHANGE_RTT_RECOUP: case TALER_EXCHANGE_RTT_RECOUP:
break; break;
case TALER_EXCHANGE_RTT_CLOSE: case TALER_EXCHANGE_RTT_CLOSING:
break; break;
case TALER_EXCHANGE_RTT_HISTORY: case TALER_EXCHANGE_RTT_HISTORY:
break; break;
case TALER_EXCHANGE_RTT_MERGE: case TALER_EXCHANGE_RTT_MERGE:
break; break;
case TALER_EXCHANGE_RTT_OPEN:
break;
case TALER_EXCHANGE_RTT_CLOSE:
break;
} }
} }
GNUNET_free (rhistory); GNUNET_free (rhistory);
@ -1253,6 +1373,8 @@ TALER_EXCHANGE_verify_coin_history (
{ "RECOUP-REFRESH", &help_recoup_refresh }, { "RECOUP-REFRESH", &help_recoup_refresh },
{ "OLD-COIN-RECOUP", &help_old_coin_recoup }, { "OLD-COIN-RECOUP", &help_old_coin_recoup },
{ "PURSE-DEPOSIT", &help_purse_deposit }, { "PURSE-DEPOSIT", &help_purse_deposit },
// FIXME: PURSE-REFUND missing here!
// FIXME: RESERVE-DEPOSIT missing here!
{ NULL, NULL } { NULL, NULL }
}; };
struct CoinHistoryParseContext pc = { struct CoinHistoryParseContext pc = {

View File

@ -70,7 +70,7 @@ TALER_TESTING_history_entry_cmp (
&h2->details.recoup_details.coin_pub)) ) &h2->details.recoup_details.coin_pub)) )
return 0; return 0;
return 1; return 1;
case TALER_EXCHANGE_RTT_CLOSE: case TALER_EXCHANGE_RTT_CLOSING:
/* testing_api_cmd_exec_closer doesn't set the /* testing_api_cmd_exec_closer doesn't set the
receiver_account_details, exchange_sig, exchange_pub or wtid or timestamp receiver_account_details, exchange_sig, exchange_pub or wtid or timestamp
so we cannot test for it here. but if the amount matches, so we cannot test for it here. but if the amount matches,
@ -130,6 +130,12 @@ TALER_TESTING_history_entry_cmp (
h2->details.merge_details.flags) ) h2->details.merge_details.flags) )
return 0; return 0;
return 1; return 1;
case TALER_EXCHANGE_RTT_OPEN:
// FIXME: verify response...
return 1;
case TALER_EXCHANGE_RTT_CLOSE:
// FIXME: verify response...
return 1;
} }
GNUNET_assert (0); GNUNET_assert (0);
return 1; return 1;

View File

@ -221,11 +221,11 @@ TALER_TESTING_cmd_exec_closer (const char *label,
/* expected amount includes fee, while our argument /* expected amount includes fee, while our argument
gives the amount _without_ the fee. So add the fee. */ gives the amount _without_ the fee. So add the fee. */
GNUNET_assert (0 <= GNUNET_assert (0 <=
TALER_amount_add (&as->reserve_history.amount, TALER_amount_add (
&as->reserve_history.amount, &as->reserve_history.amount,
&as->reserve_history.details.close_details. &as->reserve_history.amount,
fee)); &as->reserve_history.details.close_details.fee));
as->reserve_history.type = TALER_EXCHANGE_RTT_CLOSE; as->reserve_history.type = TALER_EXCHANGE_RTT_CLOSING;
} }
{ {
struct TALER_TESTING_Command cmd = { struct TALER_TESTING_Command cmd = {

View File

@ -1237,7 +1237,7 @@ TALER_wallet_account_merge_verify (
GNUNET_NETWORK_STRUCT_BEGIN GNUNET_NETWORK_STRUCT_BEGIN
/** /**
* Message signed by * Message signed by reserve key.
*/ */
struct TALER_ReserveOpenPS struct TALER_ReserveOpenPS
{ {
@ -1404,7 +1404,7 @@ TALER_wallet_reserve_open_deposit_verify (
GNUNET_NETWORK_STRUCT_BEGIN GNUNET_NETWORK_STRUCT_BEGIN
/** /**
* Message signed by * Message signed by reserve key.
*/ */
struct TALER_ReserveClosePS struct TALER_ReserveClosePS
{ {