make recoup idempotent and simplify response
This commit is contained in:
parent
c17f05b5fd
commit
6a46b13e80
@ -34,112 +34,46 @@
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wallet asked for /recoup, return the successful response.
|
* A wallet asked for /recoup (refresh variant), return the successful
|
||||||
|
* response.
|
||||||
*
|
*
|
||||||
* @param connection connection to the client
|
* @param connection connection to the client
|
||||||
* @param coin_pub coin for which we are processing the recoup request
|
|
||||||
* @param old_coin_pub public key of the old coin that will receive the recoup
|
* @param old_coin_pub public key of the old coin that will receive the recoup
|
||||||
* @param amount the amount we will wire back
|
|
||||||
* @param timestamp when did the exchange receive the /recoup request
|
|
||||||
* @return MHD result code
|
* @return MHD result code
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
reply_recoup_refresh_success (struct MHD_Connection *connection,
|
reply_recoup_refresh_success (struct MHD_Connection *connection,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
|
||||||
const struct
|
const struct
|
||||||
TALER_CoinSpendPublicKeyP *old_coin_pub,
|
TALER_CoinSpendPublicKeyP *old_coin_pub)
|
||||||
const struct TALER_Amount *amount,
|
|
||||||
struct GNUNET_TIME_Absolute timestamp)
|
|
||||||
{
|
{
|
||||||
struct TALER_RecoupRefreshConfirmationPS pc;
|
|
||||||
struct TALER_ExchangePublicKeyP pub;
|
|
||||||
struct TALER_ExchangeSignatureP sig;
|
|
||||||
|
|
||||||
pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH);
|
|
||||||
pc.purpose.size = htonl (sizeof (struct TALER_RecoupRefreshConfirmationPS));
|
|
||||||
pc.timestamp = GNUNET_TIME_absolute_hton (timestamp);
|
|
||||||
TALER_amount_hton (&pc.recoup_amount,
|
|
||||||
amount);
|
|
||||||
pc.coin_pub = *coin_pub;
|
|
||||||
pc.old_coin_pub = *old_coin_pub;
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_KS_sign (&pc.purpose,
|
|
||||||
&pub,
|
|
||||||
&sig))
|
|
||||||
{
|
|
||||||
return TALER_MHD_reply_with_error (connection,
|
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
|
||||||
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
|
|
||||||
"no keys");
|
|
||||||
}
|
|
||||||
return TALER_MHD_reply_json_pack (connection,
|
return TALER_MHD_reply_json_pack (connection,
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"{s:o, s:o, s:o, s:o, s:o}",
|
"{s:o, s:b}",
|
||||||
"old_coin_pub",
|
"old_coin_pub",
|
||||||
GNUNET_JSON_from_data_auto (
|
GNUNET_JSON_from_data_auto (
|
||||||
old_coin_pub),
|
old_coin_pub),
|
||||||
"timestamp", GNUNET_JSON_from_time_abs (
|
"refreshed", 1);
|
||||||
timestamp),
|
|
||||||
"amount", TALER_JSON_from_amount (
|
|
||||||
amount),
|
|
||||||
"exchange_sig",
|
|
||||||
GNUNET_JSON_from_data_auto (&sig),
|
|
||||||
"exchange_pub",
|
|
||||||
GNUNET_JSON_from_data_auto (&pub));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wallet asked for /recoup, return the successful response.
|
* A wallet asked for /recoup (withdraw variant), return the successful
|
||||||
|
* response.
|
||||||
*
|
*
|
||||||
* @param connection connection to the client
|
* @param connection connection to the client
|
||||||
* @param coin_pub coin for which we are processing the recoup request
|
|
||||||
* @param reserve_pub public key of the reserve that will receive the recoup
|
* @param reserve_pub public key of the reserve that will receive the recoup
|
||||||
* @param amount the amount we will wire back
|
|
||||||
* @param timestamp when did the exchange receive the /recoup request
|
|
||||||
* @return MHD result code
|
* @return MHD result code
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
reply_recoup_success (struct MHD_Connection *connection,
|
reply_recoup_success (struct MHD_Connection *connection,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_ReservePublicKeyP *reserve_pub)
|
||||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
|
||||||
const struct TALER_Amount *amount,
|
|
||||||
struct GNUNET_TIME_Absolute timestamp)
|
|
||||||
{
|
{
|
||||||
struct TALER_RecoupConfirmationPS pc;
|
|
||||||
struct TALER_ExchangePublicKeyP pub;
|
|
||||||
struct TALER_ExchangeSignatureP sig;
|
|
||||||
|
|
||||||
pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP);
|
|
||||||
pc.purpose.size = htonl (sizeof (struct TALER_RecoupConfirmationPS));
|
|
||||||
pc.timestamp = GNUNET_TIME_absolute_hton (timestamp);
|
|
||||||
TALER_amount_hton (&pc.recoup_amount,
|
|
||||||
amount);
|
|
||||||
pc.coin_pub = *coin_pub;
|
|
||||||
pc.reserve_pub = *reserve_pub;
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TEH_KS_sign (&pc.purpose,
|
|
||||||
&pub,
|
|
||||||
&sig))
|
|
||||||
{
|
|
||||||
return TALER_MHD_reply_with_error (connection,
|
|
||||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
|
||||||
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
|
|
||||||
"no keys");
|
|
||||||
}
|
|
||||||
return TALER_MHD_reply_json_pack (connection,
|
return TALER_MHD_reply_json_pack (connection,
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"{s:o, s:o, s:o, s:o, s:o}",
|
"{s:o, s:b}",
|
||||||
"reserve_pub",
|
"reserve_pub",
|
||||||
GNUNET_JSON_from_data_auto (reserve_pub),
|
GNUNET_JSON_from_data_auto (reserve_pub),
|
||||||
"timestamp", GNUNET_JSON_from_time_abs (
|
"refreshed", 0);
|
||||||
timestamp),
|
|
||||||
"amount", TALER_JSON_from_amount (
|
|
||||||
amount),
|
|
||||||
"exchange_sig",
|
|
||||||
GNUNET_JSON_from_data_auto (&sig),
|
|
||||||
"exchange_pub",
|
|
||||||
GNUNET_JSON_from_data_auto (&pub));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -234,7 +168,9 @@ recoup_transaction (void *cls,
|
|||||||
struct RecoupContext *pc = cls;
|
struct RecoupContext *pc = cls;
|
||||||
struct TALER_EXCHANGEDB_TransactionList *tl;
|
struct TALER_EXCHANGEDB_TransactionList *tl;
|
||||||
struct TALER_Amount spent;
|
struct TALER_Amount spent;
|
||||||
|
struct TALER_Amount recouped;
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
int existing_recoup_found = GNUNET_NO;
|
||||||
|
|
||||||
/* Check whether a recoup is allowed, and if so, to which
|
/* Check whether a recoup is allowed, and if so, to which
|
||||||
reserve / account the money should go */
|
reserve / account the money should go */
|
||||||
@ -310,6 +246,21 @@ recoup_transaction (void *cls,
|
|||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_amount_get_zero (pc->value.currency,
|
TALER_amount_get_zero (pc->value.currency,
|
||||||
&spent));
|
&spent));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_get_zero (pc->value.currency,
|
||||||
|
&recouped));
|
||||||
|
/* Check if this coin has been recouped already at least once */
|
||||||
|
for (struct TALER_EXCHANGEDB_TransactionList *pos = tl;
|
||||||
|
NULL != pos;
|
||||||
|
pos = pos->next)
|
||||||
|
{
|
||||||
|
if ( (TALER_EXCHANGEDB_TT_RECOUP == pos->type) ||
|
||||||
|
(TALER_EXCHANGEDB_TT_RECOUP_REFRESH == pos->type) )
|
||||||
|
{
|
||||||
|
existing_recoup_found = GNUNET_YES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
TALER_EXCHANGEDB_calculate_transaction_list_totals (tl,
|
TALER_EXCHANGEDB_calculate_transaction_list_totals (tl,
|
||||||
&spent,
|
&spent,
|
||||||
@ -324,6 +275,12 @@ recoup_transaction (void *cls,
|
|||||||
"failed to calculate old coin transaction history");
|
"failed to calculate old coin transaction history");
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
}
|
}
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Recoup: calculated spent %s\n",
|
||||||
|
TALER_amount2s (&spent));
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
|
"Recoup: coin value %s\n",
|
||||||
|
TALER_amount2s (&pc->value));
|
||||||
if (GNUNET_SYSERR ==
|
if (GNUNET_SYSERR ==
|
||||||
TALER_amount_subtract (&pc->amount,
|
TALER_amount_subtract (&pc->amount,
|
||||||
&pc->value,
|
&pc->value,
|
||||||
@ -341,15 +298,26 @@ recoup_transaction (void *cls,
|
|||||||
if ( (0 == pc->amount.fraction) &&
|
if ( (0 == pc->amount.fraction) &&
|
||||||
(0 == pc->amount.value) )
|
(0 == pc->amount.value) )
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
TEH_plugin->rollback (TEH_plugin->cls,
|
TEH_plugin->rollback (TEH_plugin->cls,
|
||||||
session);
|
session);
|
||||||
|
if (GNUNET_NO == existing_recoup_found)
|
||||||
|
{
|
||||||
*mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection,
|
*mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection,
|
||||||
TALER_EC_RECOUP_COIN_BALANCE_ZERO,
|
TALER_EC_RECOUP_COIN_BALANCE_ZERO,
|
||||||
&pc->coin->coin_pub,
|
&pc->coin->coin_pub,
|
||||||
tl);
|
tl);
|
||||||
|
ret = GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We didn't add any new recoup transaction, but there was at least
|
||||||
|
one recoup before, so we give a success response. */
|
||||||
|
ret = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
|
||||||
|
}
|
||||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||||
tl);
|
tl);
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return ret;
|
||||||
}
|
}
|
||||||
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
|
||||||
tl);
|
tl);
|
||||||
@ -548,15 +516,9 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
|
|||||||
}
|
}
|
||||||
return (refreshed)
|
return (refreshed)
|
||||||
? reply_recoup_refresh_success (connection,
|
? reply_recoup_refresh_success (connection,
|
||||||
&coin->coin_pub,
|
&pc.target.old_coin_pub)
|
||||||
&pc.target.old_coin_pub,
|
|
||||||
&pc.amount,
|
|
||||||
pc.now)
|
|
||||||
: reply_recoup_success (connection,
|
: reply_recoup_success (connection,
|
||||||
&coin->coin_pub,
|
&pc.target.reserve_pub);
|
||||||
&pc.target.reserve_pub,
|
|
||||||
&pc.amount,
|
|
||||||
pc.now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1757,8 +1757,6 @@ typedef void
|
|||||||
void *cls,
|
void *cls,
|
||||||
unsigned int http_status,
|
unsigned int http_status,
|
||||||
enum TALER_ErrorCode ec,
|
enum TALER_ErrorCode ec,
|
||||||
const struct TALER_Amount *amount,
|
|
||||||
struct GNUNET_TIME_Absolute timestamp,
|
|
||||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||||
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
|
||||||
const json_t *full_response);
|
const json_t *full_response);
|
||||||
|
@ -1611,7 +1611,6 @@ TALER_TESTING_cmd_refund (const char *label,
|
|||||||
* offers a coin and reserve private key. May specify
|
* offers a coin and reserve private key. May specify
|
||||||
* the index of the coin using "$LABEL#$INDEX" syntax.
|
* the index of the coin using "$LABEL#$INDEX" syntax.
|
||||||
* Here, $INDEX must be a non-negative number.
|
* Here, $INDEX must be a non-negative number.
|
||||||
* @param amount denomination to pay back.
|
|
||||||
* @param melt_reference NULL if coin was not refreshed, otherwise label of the melt operation
|
* @param melt_reference NULL if coin was not refreshed, otherwise label of the melt operation
|
||||||
* @return the command.
|
* @return the command.
|
||||||
*/
|
*/
|
||||||
@ -1619,7 +1618,6 @@ struct TALER_TESTING_Command
|
|||||||
TALER_TESTING_cmd_recoup (const char *label,
|
TALER_TESTING_cmd_recoup (const char *label,
|
||||||
unsigned int expected_response_code,
|
unsigned int expected_response_code,
|
||||||
const char *coin_reference,
|
const char *coin_reference,
|
||||||
const char *amount,
|
|
||||||
const char *melt_reference);
|
const char *melt_reference);
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,9 +88,7 @@ struct TALER_EXCHANGE_RecoupHandle
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that the signature on the "200 OK" response
|
* Parse a recoup response. If it is valid, call the callback.
|
||||||
* from the exchange is valid. If it is, call the
|
|
||||||
* callback.
|
|
||||||
*
|
*
|
||||||
* @param ph recoup handle
|
* @param ph recoup handle
|
||||||
* @param json json reply with the signature
|
* @param json json reply with the signature
|
||||||
@ -98,30 +96,20 @@ struct TALER_EXCHANGE_RecoupHandle
|
|||||||
* #GNUNET_SYSERR if not (callback must still be called)
|
* #GNUNET_SYSERR if not (callback must still be called)
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
verify_recoup_signature_ok (const struct TALER_EXCHANGE_RecoupHandle *ph,
|
process_recoup_response (const struct TALER_EXCHANGE_RecoupHandle *ph,
|
||||||
const json_t *json)
|
const json_t *json)
|
||||||
{
|
{
|
||||||
struct TALER_RecoupConfirmationPS pc;
|
int refreshed;
|
||||||
struct TALER_RecoupRefreshConfirmationPS pr;
|
struct TALER_ReservePublicKeyP reserve_pub;
|
||||||
struct TALER_ExchangePublicKeyP exchange_pub;
|
struct TALER_CoinSpendPublicKeyP old_coin_pub;
|
||||||
struct TALER_ExchangeSignatureP exchange_sig;
|
|
||||||
struct TALER_Amount amount;
|
|
||||||
struct GNUNET_TIME_Absolute timestamp;
|
|
||||||
const struct TALER_EXCHANGE_Keys *key_state;
|
|
||||||
struct GNUNET_JSON_Specification spec_withdraw[] = {
|
struct GNUNET_JSON_Specification spec_withdraw[] = {
|
||||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig),
|
GNUNET_JSON_spec_boolean ("refreshed", &refreshed),
|
||||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub),
|
GNUNET_JSON_spec_fixed_auto ("reserve_pub", &reserve_pub),
|
||||||
TALER_JSON_spec_amount ("amount", &amount),
|
|
||||||
GNUNET_JSON_spec_absolute_time ("timestamp", ×tamp),
|
|
||||||
GNUNET_JSON_spec_fixed_auto ("reserve_pub", &pc.reserve_pub),
|
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
struct GNUNET_JSON_Specification spec_refresh[] = {
|
struct GNUNET_JSON_Specification spec_refresh[] = {
|
||||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig", &exchange_sig),
|
GNUNET_JSON_spec_boolean ("refreshed", &refreshed),
|
||||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub),
|
GNUNET_JSON_spec_fixed_auto ("old_coin_pub", &old_coin_pub),
|
||||||
TALER_JSON_spec_amount ("amount", &amount),
|
|
||||||
GNUNET_JSON_spec_absolute_time ("timestamp", ×tamp),
|
|
||||||
GNUNET_JSON_spec_fixed_auto ("old_coin_pub", &pr.old_coin_pub),
|
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -133,59 +121,16 @@ verify_recoup_signature_ok (const struct TALER_EXCHANGE_RecoupHandle *ph,
|
|||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
key_state = TALER_EXCHANGE_get_keys (ph->exchange);
|
if (ph->was_refreshed != refreshed)
|
||||||
if (GNUNET_OK !=
|
|
||||||
TALER_EXCHANGE_test_signing_key (key_state,
|
|
||||||
&exchange_pub))
|
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
if (ph->was_refreshed)
|
|
||||||
{
|
|
||||||
pr.purpose.purpose = htonl (
|
|
||||||
TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH);
|
|
||||||
pr.purpose.size = htonl (sizeof (pr));
|
|
||||||
pr.timestamp = GNUNET_TIME_absolute_hton (timestamp);
|
|
||||||
TALER_amount_hton (&pr.recoup_amount,
|
|
||||||
&amount);
|
|
||||||
pr.coin_pub = ph->coin_pub;
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
GNUNET_CRYPTO_eddsa_verify (
|
|
||||||
TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH,
|
|
||||||
&pr.purpose,
|
|
||||||
&exchange_sig.eddsa_signature,
|
|
||||||
&exchange_pub.eddsa_pub))
|
|
||||||
{
|
|
||||||
GNUNET_break_op (0);
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP);
|
|
||||||
pc.purpose.size = htonl (sizeof (pc));
|
|
||||||
pc.timestamp = GNUNET_TIME_absolute_hton (timestamp);
|
|
||||||
TALER_amount_hton (&pc.recoup_amount,
|
|
||||||
&amount);
|
|
||||||
pc.coin_pub = ph->coin_pub;
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP,
|
|
||||||
&pc.purpose,
|
|
||||||
&exchange_sig.eddsa_signature,
|
|
||||||
&exchange_pub.eddsa_pub))
|
|
||||||
{
|
|
||||||
GNUNET_break_op (0);
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ph->cb (ph->cb_cls,
|
ph->cb (ph->cb_cls,
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
TALER_EC_NONE,
|
TALER_EC_NONE,
|
||||||
&amount,
|
ph->was_refreshed ? NULL : &reserve_pub,
|
||||||
timestamp,
|
ph->was_refreshed ? &old_coin_pub : NULL,
|
||||||
ph->was_refreshed ? NULL : &pc.reserve_pub,
|
|
||||||
ph->was_refreshed ? &pr.old_coin_pub : NULL,
|
|
||||||
json);
|
json);
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
@ -217,7 +162,7 @@ handle_recoup_finished (void *cls,
|
|||||||
case MHD_HTTP_OK:
|
case MHD_HTTP_OK:
|
||||||
ec = TALER_EC_NONE;
|
ec = TALER_EC_NONE;
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
verify_recoup_signature_ok (ph,
|
process_recoup_response (ph,
|
||||||
j))
|
j))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
@ -256,8 +201,6 @@ handle_recoup_finished (void *cls,
|
|||||||
ph->cb (ph->cb_cls,
|
ph->cb (ph->cb_cls,
|
||||||
response_code,
|
response_code,
|
||||||
ec,
|
ec,
|
||||||
&total,
|
|
||||||
GNUNET_TIME_UNIT_FOREVER_ABS,
|
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
j);
|
j);
|
||||||
@ -299,8 +242,6 @@ handle_recoup_finished (void *cls,
|
|||||||
response_code,
|
response_code,
|
||||||
ec,
|
ec,
|
||||||
NULL,
|
NULL,
|
||||||
GNUNET_TIME_UNIT_FOREVER_ABS,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
NULL,
|
||||||
j);
|
j);
|
||||||
TALER_EXCHANGE_recoup_cancel (ph);
|
TALER_EXCHANGE_recoup_cancel (ph);
|
||||||
|
@ -409,7 +409,6 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_recoup ("recoup-1",
|
TALER_TESTING_cmd_recoup ("recoup-1",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"recoup-withdraw-coin-1",
|
"recoup-withdraw-coin-1",
|
||||||
"EUR:5",
|
|
||||||
NULL),
|
NULL),
|
||||||
/**
|
/**
|
||||||
* Re-withdraw from this reserve
|
* Re-withdraw from this reserve
|
||||||
@ -469,7 +468,6 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_recoup ("recoup-2",
|
TALER_TESTING_cmd_recoup ("recoup-2",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"recoup-withdraw-coin-2a",
|
"recoup-withdraw-coin-2a",
|
||||||
"EUR:0.5",
|
|
||||||
NULL),
|
NULL),
|
||||||
TALER_TESTING_cmd_end ()
|
TALER_TESTING_cmd_end ()
|
||||||
};
|
};
|
||||||
|
@ -587,7 +587,6 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_recoup ("recoup-1",
|
TALER_TESTING_cmd_recoup ("recoup-1",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"recoup-withdraw-coin-1",
|
"recoup-withdraw-coin-1",
|
||||||
"EUR:5",
|
|
||||||
NULL),
|
NULL),
|
||||||
/* Check the money is back with the reserve */
|
/* Check the money is back with the reserve */
|
||||||
TALER_TESTING_cmd_status ("recoup-reserve-status-1",
|
TALER_TESTING_cmd_status ("recoup-reserve-status-1",
|
||||||
@ -682,12 +681,10 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_recoup ("recoup-2",
|
TALER_TESTING_cmd_recoup ("recoup-2",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"recoup-withdraw-coin-2a",
|
"recoup-withdraw-coin-2a",
|
||||||
"EUR:0.5",
|
|
||||||
NULL),
|
NULL),
|
||||||
TALER_TESTING_cmd_recoup ("recoup-2b",
|
TALER_TESTING_cmd_recoup ("recoup-2b",
|
||||||
MHD_HTTP_CONFLICT,
|
MHD_HTTP_CONFLICT,
|
||||||
"recoup-withdraw-coin-2a",
|
"recoup-withdraw-coin-2a",
|
||||||
"EUR:0.5",
|
|
||||||
NULL),
|
NULL),
|
||||||
TALER_TESTING_cmd_deposit ("recoup-deposit-revoked",
|
TALER_TESTING_cmd_deposit ("recoup-deposit-revoked",
|
||||||
"recoup-withdraw-coin-2b",
|
"recoup-withdraw-coin-2b",
|
||||||
|
@ -117,27 +117,31 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_recoup ("recoup-1a",
|
TALER_TESTING_cmd_recoup ("recoup-1a",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"refresh-reveal-1#0",
|
"refresh-reveal-1#0",
|
||||||
"EUR:1",
|
|
||||||
"refresh-melt-1"),
|
"refresh-melt-1"),
|
||||||
TALER_TESTING_cmd_recoup ("recoup-1b",
|
TALER_TESTING_cmd_recoup ("recoup-1b",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"refresh-reveal-1#1",
|
"refresh-reveal-1#1",
|
||||||
"EUR:1",
|
|
||||||
"refresh-melt-1"),
|
"refresh-melt-1"),
|
||||||
TALER_TESTING_cmd_recoup ("recoup-1c",
|
TALER_TESTING_cmd_recoup ("recoup-1c",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"refresh-reveal-1#2",
|
"refresh-reveal-1#2",
|
||||||
"EUR:1",
|
"refresh-melt-1"),
|
||||||
|
/* Repeat recoup to test idempotency */
|
||||||
|
TALER_TESTING_cmd_recoup ("recoup-1c",
|
||||||
|
MHD_HTTP_OK,
|
||||||
|
"refresh-reveal-1#2",
|
||||||
|
"refresh-melt-1"),
|
||||||
|
TALER_TESTING_cmd_recoup ("recoup-1c",
|
||||||
|
MHD_HTTP_OK,
|
||||||
|
"refresh-reveal-1#2",
|
||||||
"refresh-melt-1"),
|
"refresh-melt-1"),
|
||||||
TALER_TESTING_cmd_recoup ("recoup-1c",
|
TALER_TESTING_cmd_recoup ("recoup-1c",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"refresh-reveal-1#2",
|
"refresh-reveal-1#2",
|
||||||
"EUR:1",
|
|
||||||
"refresh-melt-1"),
|
"refresh-melt-1"),
|
||||||
TALER_TESTING_cmd_recoup ("recoup-1c",
|
TALER_TESTING_cmd_recoup ("recoup-1c",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"refresh-reveal-1#2",
|
"refresh-reveal-1#2",
|
||||||
"EUR:1",
|
|
||||||
"refresh-melt-1"),
|
"refresh-melt-1"),
|
||||||
/* Now we have EUR:3.83 EUR back after 3x EUR:1 in recoups */
|
/* Now we have EUR:3.83 EUR back after 3x EUR:1 in recoups */
|
||||||
/* Melt original coin AGAIN, but only create one 0.1 EUR coin;
|
/* Melt original coin AGAIN, but only create one 0.1 EUR coin;
|
||||||
@ -168,14 +172,12 @@ run (void *cls,
|
|||||||
TALER_TESTING_cmd_recoup ("recoup-2",
|
TALER_TESTING_cmd_recoup ("recoup-2",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"refresh-reveal-2",
|
"refresh-reveal-2",
|
||||||
"EUR:0.1",
|
|
||||||
"refresh-melt-2"),
|
"refresh-melt-2"),
|
||||||
/* Due to recoup, original coin is now at EUR:3.79 */
|
/* Due to recoup, original coin is now at EUR:3.79 */
|
||||||
/* Refund original (now zombie) coin to reserve */
|
/* Refund original (now zombie) coin to reserve */
|
||||||
TALER_TESTING_cmd_recoup ("recoup-3",
|
TALER_TESTING_cmd_recoup ("recoup-3",
|
||||||
MHD_HTTP_OK,
|
MHD_HTTP_OK,
|
||||||
"withdraw-revocation-coin-1",
|
"withdraw-revocation-coin-1",
|
||||||
"EUR:3.79",
|
|
||||||
NULL),
|
NULL),
|
||||||
/* Check the money is back with the reserve */
|
/* Check the money is back with the reserve */
|
||||||
TALER_TESTING_cmd_status ("recoup-reserve-status-1",
|
TALER_TESTING_cmd_status ("recoup-reserve-status-1",
|
||||||
|
@ -86,11 +86,6 @@ struct RecoupState
|
|||||||
*/
|
*/
|
||||||
struct TALER_TESTING_Interpreter *is;
|
struct TALER_TESTING_Interpreter *is;
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount expected to be paid back.
|
|
||||||
*/
|
|
||||||
const char *amount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle to the ongoing operation.
|
* Handle to the ongoing operation.
|
||||||
*/
|
*/
|
||||||
@ -157,9 +152,6 @@ parse_coin_reference (const char *coin_reference,
|
|||||||
* @param cls closure
|
* @param cls closure
|
||||||
* @param http_status HTTP response code.
|
* @param http_status HTTP response code.
|
||||||
* @param ec taler-specific error code.
|
* @param ec taler-specific error code.
|
||||||
* @param amount amount the exchange will wire back for this coin.
|
|
||||||
* @param timestamp what time did the exchange receive the
|
|
||||||
* /recoup request
|
|
||||||
* @param reserve_pub public key of the reserve receiving the recoup, NULL if refreshed or on error
|
* @param reserve_pub public key of the reserve receiving the recoup, NULL if refreshed or on error
|
||||||
* @param old_coin_pub public key of the dirty coin, NULL if not refreshed or on error
|
* @param old_coin_pub public key of the dirty coin, NULL if not refreshed or on error
|
||||||
* @param full_response raw response from the exchange.
|
* @param full_response raw response from the exchange.
|
||||||
@ -168,8 +160,6 @@ static void
|
|||||||
recoup_cb (void *cls,
|
recoup_cb (void *cls,
|
||||||
unsigned int http_status,
|
unsigned int http_status,
|
||||||
enum TALER_ErrorCode ec,
|
enum TALER_ErrorCode ec,
|
||||||
const struct TALER_Amount *amount,
|
|
||||||
struct GNUNET_TIME_Absolute timestamp,
|
|
||||||
const struct TALER_ReservePublicKeyP *reserve_pub,
|
const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||||
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
|
||||||
const json_t *full_response)
|
const json_t *full_response)
|
||||||
@ -219,28 +209,7 @@ recoup_cb (void *cls,
|
|||||||
switch (http_status)
|
switch (http_status)
|
||||||
{
|
{
|
||||||
case MHD_HTTP_OK:
|
case MHD_HTTP_OK:
|
||||||
/* first, check amount */
|
/* check old_coin_pub or reserve_pub, respectively */
|
||||||
{
|
|
||||||
struct TALER_Amount expected_amount;
|
|
||||||
|
|
||||||
if (GNUNET_OK !=
|
|
||||||
TALER_string_to_amount (ps->amount, &expected_amount))
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
TALER_TESTING_interpreter_fail (is);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (0 != TALER_amount_cmp (amount, &expected_amount))
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
|
||||||
"Total amount mismatch to command %s\n",
|
|
||||||
cmd->label);
|
|
||||||
json_dumpf (full_response, stderr, 0);
|
|
||||||
TALER_TESTING_interpreter_fail (is);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* now, check old_coin_pub or reserve_pub, respectively */
|
|
||||||
if (NULL != ps->melt_reference)
|
if (NULL != ps->melt_reference)
|
||||||
{
|
{
|
||||||
const struct TALER_TESTING_Command *melt_cmd;
|
const struct TALER_TESTING_Command *melt_cmd;
|
||||||
@ -559,7 +528,6 @@ struct TALER_TESTING_Command
|
|||||||
TALER_TESTING_cmd_recoup (const char *label,
|
TALER_TESTING_cmd_recoup (const char *label,
|
||||||
unsigned int expected_response_code,
|
unsigned int expected_response_code,
|
||||||
const char *coin_reference,
|
const char *coin_reference,
|
||||||
const char *amount,
|
|
||||||
const char *melt_reference)
|
const char *melt_reference)
|
||||||
{
|
{
|
||||||
struct RecoupState *ps;
|
struct RecoupState *ps;
|
||||||
@ -567,7 +535,6 @@ TALER_TESTING_cmd_recoup (const char *label,
|
|||||||
ps = GNUNET_new (struct RecoupState);
|
ps = GNUNET_new (struct RecoupState);
|
||||||
ps->expected_response_code = expected_response_code;
|
ps->expected_response_code = expected_response_code;
|
||||||
ps->coin_reference = coin_reference;
|
ps->coin_reference = coin_reference;
|
||||||
ps->amount = amount;
|
|
||||||
ps->melt_reference = melt_reference;
|
ps->melt_reference = melt_reference;
|
||||||
{
|
{
|
||||||
struct TALER_TESTING_Command cmd = {
|
struct TALER_TESTING_Command cmd = {
|
||||||
|
Loading…
Reference in New Issue
Block a user