implement new behavior in exchange httpd and libtalerexchange (for #6416)
This commit is contained in:
parent
8a1402a5d5
commit
92ac6dd11a
@ -273,7 +273,7 @@ TEH_RESPONSE_compile_transaction_history (
|
|||||||
if (0 !=
|
if (0 !=
|
||||||
json_array_append_new (
|
json_array_append_new (
|
||||||
history,
|
history,
|
||||||
json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o, s:o}",
|
json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
|
||||||
"type",
|
"type",
|
||||||
"OLD-COIN-RECOUP",
|
"OLD-COIN-RECOUP",
|
||||||
"amount",
|
"amount",
|
||||||
@ -284,8 +284,8 @@ TEH_RESPONSE_compile_transaction_history (
|
|||||||
GNUNET_JSON_from_data_auto (&epub),
|
GNUNET_JSON_from_data_auto (&epub),
|
||||||
"coin_pub",
|
"coin_pub",
|
||||||
GNUNET_JSON_from_data_auto (&pr->coin.coin_pub),
|
GNUNET_JSON_from_data_auto (&pr->coin.coin_pub),
|
||||||
"h_denom_pub",
|
"coin_sig",
|
||||||
GNUNET_JSON_from_data_auto (&pr->coin.denom_pub_hash),
|
GNUNET_JSON_from_data_auto (&pr->coin_sig),
|
||||||
"timestamp",
|
"timestamp",
|
||||||
GNUNET_JSON_from_time_abs (pr->timestamp))))
|
GNUNET_JSON_from_time_abs (pr->timestamp))))
|
||||||
{
|
{
|
||||||
@ -323,7 +323,7 @@ TEH_RESPONSE_compile_transaction_history (
|
|||||||
if (0 !=
|
if (0 !=
|
||||||
json_array_append_new (
|
json_array_append_new (
|
||||||
history,
|
history,
|
||||||
json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o, s:o}",
|
json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
|
||||||
"type",
|
"type",
|
||||||
"RECOUP",
|
"RECOUP",
|
||||||
"amount",
|
"amount",
|
||||||
@ -336,6 +336,12 @@ TEH_RESPONSE_compile_transaction_history (
|
|||||||
GNUNET_JSON_from_data_auto (&recoup->reserve_pub),
|
GNUNET_JSON_from_data_auto (&recoup->reserve_pub),
|
||||||
"h_denom_pub",
|
"h_denom_pub",
|
||||||
GNUNET_JSON_from_data_auto (&recoup->h_denom_pub),
|
GNUNET_JSON_from_data_auto (&recoup->h_denom_pub),
|
||||||
|
"coin_sig",
|
||||||
|
GNUNET_JSON_from_data_auto (&recoup->coin_sig),
|
||||||
|
"coin_blind",
|
||||||
|
GNUNET_JSON_from_data_auto (&recoup->coin_blind),
|
||||||
|
"reserve_pub",
|
||||||
|
GNUNET_JSON_from_data_auto (&recoup->reserve_pub),
|
||||||
"timestamp",
|
"timestamp",
|
||||||
GNUNET_JSON_from_time_abs (recoup->timestamp))))
|
GNUNET_JSON_from_time_abs (recoup->timestamp))))
|
||||||
{
|
{
|
||||||
@ -379,7 +385,7 @@ TEH_RESPONSE_compile_transaction_history (
|
|||||||
if (0 !=
|
if (0 !=
|
||||||
json_array_append_new (
|
json_array_append_new (
|
||||||
history,
|
history,
|
||||||
json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o, s:o}",
|
json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
|
||||||
"type",
|
"type",
|
||||||
"RECOUP-REFRESH",
|
"RECOUP-REFRESH",
|
||||||
"amount",
|
"amount",
|
||||||
@ -392,6 +398,10 @@ TEH_RESPONSE_compile_transaction_history (
|
|||||||
GNUNET_JSON_from_data_auto (&pr->old_coin_pub),
|
GNUNET_JSON_from_data_auto (&pr->old_coin_pub),
|
||||||
"h_denom_pub",
|
"h_denom_pub",
|
||||||
GNUNET_JSON_from_data_auto (&pr->coin.denom_pub_hash),
|
GNUNET_JSON_from_data_auto (&pr->coin.denom_pub_hash),
|
||||||
|
"coin_sig",
|
||||||
|
GNUNET_JSON_from_data_auto (&pr->coin_sig),
|
||||||
|
"coin_blind",
|
||||||
|
GNUNET_JSON_from_data_auto (&pr->coin_blind),
|
||||||
"timestamp",
|
"timestamp",
|
||||||
GNUNET_JSON_from_time_abs (pr->timestamp))))
|
GNUNET_JSON_from_time_abs (pr->timestamp))))
|
||||||
{
|
{
|
||||||
|
@ -1811,6 +1811,7 @@ TALER_EXCHANGE_deposits_get_cancel (
|
|||||||
* @param currency expected currency for the coin
|
* @param currency expected currency for the coin
|
||||||
* @param coin_pub public key of the coin
|
* @param coin_pub public key of the coin
|
||||||
* @param history history of the coin in json encoding
|
* @param history history of the coin in json encoding
|
||||||
|
* @param[out] h_denom_pub set to the hash of the coin's denomination (if available)
|
||||||
* @param[out] total how much of the coin has been spent according to @a history
|
* @param[out] total how much of the coin has been spent according to @a history
|
||||||
* @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not
|
* @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not
|
||||||
*/
|
*/
|
||||||
@ -1820,6 +1821,7 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
const char *currency,
|
const char *currency,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
json_t *history,
|
json_t *history,
|
||||||
|
struct GNUNET_HashCode *h_denom_pub,
|
||||||
struct TALER_Amount *total);
|
struct TALER_Amount *total);
|
||||||
|
|
||||||
|
|
||||||
|
@ -447,6 +447,7 @@ TALER_EXCHANGE_free_reserve_history (
|
|||||||
* @param currency expected currency for the coin
|
* @param currency expected currency for the coin
|
||||||
* @param coin_pub public key of the coin
|
* @param coin_pub public key of the coin
|
||||||
* @param history history of the coin in json encoding
|
* @param history history of the coin in json encoding
|
||||||
|
* @param[out] h_denom_pub set to the hash of the coin's denomination (if available)
|
||||||
* @param[out] total how much of the coin has been spent according to @a history
|
* @param[out] total how much of the coin has been spent according to @a history
|
||||||
* @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not
|
* @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not
|
||||||
*/
|
*/
|
||||||
@ -456,6 +457,7 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
const char *currency,
|
const char *currency,
|
||||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||||
json_t *history,
|
json_t *history,
|
||||||
|
struct GNUNET_HashCode *h_denom_pub,
|
||||||
struct TALER_Amount *total)
|
struct TALER_Amount *total)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -558,6 +560,7 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
*h_denom_pub = dr.h_denom_pub;
|
||||||
if (NULL != dk)
|
if (NULL != dk)
|
||||||
{
|
{
|
||||||
/* check that deposit fee matches our expectations from /keys! */
|
/* check that deposit fee matches our expectations from /keys! */
|
||||||
@ -615,6 +618,7 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
*h_denom_pub = rm.h_denom_pub;
|
||||||
if (NULL != dk)
|
if (NULL != dk)
|
||||||
{
|
{
|
||||||
/* check that melt fee matches our expectations from /keys! */
|
/* check that melt fee matches our expectations from /keys! */
|
||||||
@ -703,16 +707,159 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
else if (0 == strcasecmp (type,
|
else if (0 == strcasecmp (type,
|
||||||
"RECOUP"))
|
"RECOUP"))
|
||||||
{
|
{
|
||||||
struct TALER_RecoupConfirmationPS pc;
|
struct TALER_RecoupConfirmationPS pc = {
|
||||||
|
.purpose.size = htonl (sizeof (pc)),
|
||||||
|
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
|
||||||
|
.coin_pub = *coin_pub
|
||||||
|
};
|
||||||
|
struct TALER_RecoupRequestPS rr = {
|
||||||
|
.purpose.size = htonl (sizeof (pc)),
|
||||||
|
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
|
||||||
|
.coin_pub = *coin_pub
|
||||||
|
};
|
||||||
struct TALER_ExchangePublicKeyP exchange_pub;
|
struct TALER_ExchangePublicKeyP exchange_pub;
|
||||||
struct TALER_ExchangeSignatureP exchange_sig;
|
struct TALER_ExchangeSignatureP exchange_sig;
|
||||||
|
struct TALER_CoinSpendSignatureP coin_sig;
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
|
TALER_JSON_spec_amount_nbo ("amount",
|
||||||
|
&pc.recoup_amount),
|
||||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
|
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
|
||||||
&exchange_sig),
|
&exchange_sig),
|
||||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
|
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
|
||||||
&exchange_pub),
|
&exchange_pub),
|
||||||
GNUNET_JSON_spec_fixed_auto ("reserve_pub",
|
GNUNET_JSON_spec_fixed_auto ("reserve_pub",
|
||||||
&pc.reserve_pub),
|
&pc.reserve_pub),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||||
|
&coin_sig),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("coin_blind",
|
||||||
|
&rr.coin_blind),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
|
||||||
|
&rr.h_denom_pub),
|
||||||
|
TALER_JSON_spec_absolute_time_nbo ("timestamp",
|
||||||
|
&pc.timestamp),
|
||||||
|
GNUNET_JSON_spec_end ()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_JSON_parse (transaction,
|
||||||
|
spec,
|
||||||
|
NULL, NULL))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
TALER_amount_hton (&pc.recoup_amount,
|
||||||
|
&amount);
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP,
|
||||||
|
&pc,
|
||||||
|
&exchange_sig.eddsa_signature,
|
||||||
|
&exchange_pub.eddsa_pub))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
|
||||||
|
&rr,
|
||||||
|
&coin_sig.eddsa_signature,
|
||||||
|
&coin_pub->eddsa_pub))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
*h_denom_pub = rr.h_denom_pub;
|
||||||
|
add = GNUNET_YES;
|
||||||
|
}
|
||||||
|
else if (0 == strcasecmp (type,
|
||||||
|
"RECOUP-REFRESH"))
|
||||||
|
{
|
||||||
|
struct TALER_RecoupRefreshConfirmationPS pc = {
|
||||||
|
.purpose.size = htonl (sizeof (pc)),
|
||||||
|
.purpose.purpose = htonl (
|
||||||
|
TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
|
||||||
|
.coin_pub = *coin_pub
|
||||||
|
};
|
||||||
|
struct TALER_RecoupRequestPS rr = {
|
||||||
|
.purpose.size = htonl (sizeof (pc)),
|
||||||
|
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
|
||||||
|
.coin_pub = *coin_pub
|
||||||
|
};
|
||||||
|
struct TALER_ExchangePublicKeyP exchange_pub;
|
||||||
|
struct TALER_ExchangeSignatureP exchange_sig;
|
||||||
|
struct TALER_CoinSpendSignatureP coin_sig;
|
||||||
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
|
TALER_JSON_spec_amount_nbo ("amount",
|
||||||
|
&pc.recoup_amount),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
|
||||||
|
&exchange_sig),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
|
||||||
|
&exchange_pub),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("coin_sig",
|
||||||
|
&coin_sig),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("old_coin_pub",
|
||||||
|
&pc.old_coin_pub),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("coin_blind",
|
||||||
|
&rr.coin_blind),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
|
||||||
|
&rr.h_denom_pub),
|
||||||
|
TALER_JSON_spec_absolute_time_nbo ("timestamp",
|
||||||
|
&pc.timestamp),
|
||||||
|
GNUNET_JSON_spec_end ()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_JSON_parse (transaction,
|
||||||
|
spec,
|
||||||
|
NULL, NULL))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
TALER_amount_hton (&pc.recoup_amount,
|
||||||
|
&amount);
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_CRYPTO_eddsa_verify (
|
||||||
|
TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH,
|
||||||
|
&pc,
|
||||||
|
&exchange_sig.eddsa_signature,
|
||||||
|
&exchange_pub.eddsa_pub))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
|
||||||
|
&rr,
|
||||||
|
&coin_sig.eddsa_signature,
|
||||||
|
&coin_pub->eddsa_pub))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
*h_denom_pub = rr.h_denom_pub;
|
||||||
|
add = GNUNET_YES;
|
||||||
|
}
|
||||||
|
else if (0 == strcasecmp (type,
|
||||||
|
"OLD-COIN-RECOUP"))
|
||||||
|
{
|
||||||
|
struct TALER_RecoupRefreshConfirmationPS pc = {
|
||||||
|
.purpose.size = htonl (sizeof (pc)),
|
||||||
|
.purpose.purpose = htonl (
|
||||||
|
TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
|
||||||
|
.old_coin_pub = *coin_pub
|
||||||
|
};
|
||||||
|
struct TALER_ExchangePublicKeyP exchange_pub;
|
||||||
|
struct TALER_ExchangeSignatureP exchange_sig;
|
||||||
|
struct GNUNET_JSON_Specification spec[] = {
|
||||||
|
TALER_JSON_spec_amount_nbo ("amount",
|
||||||
|
&pc.recoup_amount),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
|
||||||
|
&exchange_sig),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
|
||||||
|
&exchange_pub),
|
||||||
|
GNUNET_JSON_spec_fixed_auto ("coin_pub",
|
||||||
|
&pc.coin_pub),
|
||||||
TALER_JSON_spec_absolute_time_nbo ("timestamp",
|
TALER_JSON_spec_absolute_time_nbo ("timestamp",
|
||||||
&pc.timestamp),
|
&pc.timestamp),
|
||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
@ -726,9 +873,6 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
pc.purpose.size = htonl (sizeof (pc));
|
|
||||||
pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP);
|
|
||||||
pc.coin_pub = *coin_pub;
|
|
||||||
TALER_amount_hton (&pc.recoup_amount,
|
TALER_amount_hton (&pc.recoup_amount,
|
||||||
&amount);
|
&amount);
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
@ -749,6 +893,7 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
GNUNET_assert (GNUNET_SYSERR == add);
|
GNUNET_assert (GNUNET_SYSERR == add);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GNUNET_YES == add)
|
if (GNUNET_YES == add)
|
||||||
{
|
{
|
||||||
/* This amount should be added to the total */
|
/* This amount should be added to the total */
|
||||||
@ -779,9 +924,11 @@ TALER_EXCHANGE_verify_coin_history (
|
|||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Finally, subtract 'rtotal' from total to handle the subtractions */
|
/* Finally, subtract 'rtotal' from total to handle the subtractions */
|
||||||
if (0 >
|
if (0 >
|
||||||
TALER_amount_subtract (total,
|
TALER_amount_subtract (total,
|
||||||
|
@ -246,13 +246,18 @@ verify_deposit_signature_ok (struct TALER_EXCHANGE_DepositHandle *dh,
|
|||||||
* @return #GNUNET_OK if the signature(s) is valid, #GNUNET_SYSERR if not
|
* @return #GNUNET_OK if the signature(s) is valid, #GNUNET_SYSERR if not
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
verify_deposit_signature_forbidden (
|
verify_deposit_signature_conflict (
|
||||||
const struct TALER_EXCHANGE_DepositHandle *dh,
|
const struct TALER_EXCHANGE_DepositHandle *dh,
|
||||||
const json_t *json)
|
const json_t *json)
|
||||||
{
|
{
|
||||||
json_t *history;
|
json_t *history;
|
||||||
struct TALER_Amount total;
|
struct TALER_Amount total;
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
struct GNUNET_HashCode h_denom_pub;
|
||||||
|
|
||||||
|
memset (&h_denom_pub,
|
||||||
|
0,
|
||||||
|
sizeof (h_denom_pub));
|
||||||
history = json_object_get (json,
|
history = json_object_get (json,
|
||||||
"history");
|
"history");
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
@ -260,11 +265,16 @@ verify_deposit_signature_forbidden (
|
|||||||
dh->dki.value.currency,
|
dh->dki.value.currency,
|
||||||
&dh->depconf.coin_pub,
|
&dh->depconf.coin_pub,
|
||||||
history,
|
history,
|
||||||
|
&h_denom_pub,
|
||||||
&total))
|
&total))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
ec = TALER_JSON_get_error_code (json);
|
||||||
|
switch (ec)
|
||||||
|
{
|
||||||
|
case TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS:
|
||||||
if (0 >
|
if (0 >
|
||||||
TALER_amount_add (&total,
|
TALER_amount_add (&total,
|
||||||
&total,
|
&total,
|
||||||
@ -284,6 +294,17 @@ verify_deposit_signature_forbidden (
|
|||||||
}
|
}
|
||||||
/* everything OK, proof of double-spending was provided */
|
/* everything OK, proof of double-spending was provided */
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
|
case TALER_EC_COIN_CONFLICTING_DENOMINATION_KEY:
|
||||||
|
if (0 != GNUNET_memcmp (&dh->dki.h_key,
|
||||||
|
&h_denom_pub))
|
||||||
|
return GNUNET_OK; /* indeed, proof with different denomination key provided */
|
||||||
|
/* invalid proof provided */
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
default:
|
||||||
|
/* unexpected error code */
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -343,7 +364,7 @@ handle_deposit_finished (void *cls,
|
|||||||
case MHD_HTTP_CONFLICT:
|
case MHD_HTTP_CONFLICT:
|
||||||
/* Double spending; check signatures on transaction history */
|
/* Double spending; check signatures on transaction history */
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
verify_deposit_signature_forbidden (dh,
|
verify_deposit_signature_conflict (dh,
|
||||||
j))
|
j))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
|
@ -178,6 +178,8 @@ verify_melt_signature_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
|||||||
GNUNET_JSON_spec_end ()
|
GNUNET_JSON_spec_end ()
|
||||||
};
|
};
|
||||||
const struct MeltedCoin *mc;
|
const struct MeltedCoin *mc;
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
struct GNUNET_HashCode h_denom_pub;
|
||||||
|
|
||||||
/* parse JSON reply */
|
/* parse JSON reply */
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
@ -211,6 +213,9 @@ verify_melt_signature_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* verify coin history */
|
/* verify coin history */
|
||||||
|
memset (&h_denom_pub,
|
||||||
|
0,
|
||||||
|
sizeof (h_denom_pub));
|
||||||
history = json_object_get (json,
|
history = json_object_get (json,
|
||||||
"history");
|
"history");
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
@ -218,6 +223,7 @@ verify_melt_signature_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
|||||||
original_value.currency,
|
original_value.currency,
|
||||||
&coin_pub,
|
&coin_pub,
|
||||||
history,
|
history,
|
||||||
|
&h_denom_pub,
|
||||||
&total))
|
&total))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
@ -226,6 +232,10 @@ verify_melt_signature_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
|||||||
}
|
}
|
||||||
json_decref (history);
|
json_decref (history);
|
||||||
|
|
||||||
|
ec = TALER_JSON_get_error_code (json);
|
||||||
|
switch (ec)
|
||||||
|
{
|
||||||
|
case TALER_EC_MELT_INSUFFICIENT_FUNDS:
|
||||||
/* check if melt operation was really too expensive given history */
|
/* check if melt operation was really too expensive given history */
|
||||||
if (0 >
|
if (0 >
|
||||||
TALER_amount_add (&total,
|
TALER_amount_add (&total,
|
||||||
@ -247,6 +257,18 @@ verify_melt_signature_conflict (struct TALER_EXCHANGE_MeltHandle *mh,
|
|||||||
|
|
||||||
/* everything OK, valid proof of double-spending was provided */
|
/* everything OK, valid proof of double-spending was provided */
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
|
case TALER_EC_COIN_CONFLICTING_DENOMINATION_KEY:
|
||||||
|
if (0 != GNUNET_memcmp (&mh->dki.h_key,
|
||||||
|
&h_denom_pub))
|
||||||
|
return GNUNET_OK; /* indeed, proof with different denomination key provided */
|
||||||
|
/* invalid proof provided */
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
default:
|
||||||
|
/* unexpected error code */
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,7 +187,9 @@ handle_recoup_finished (void *cls,
|
|||||||
/* Insufficient funds, proof attached */
|
/* Insufficient funds, proof attached */
|
||||||
json_t *history;
|
json_t *history;
|
||||||
struct TALER_Amount total;
|
struct TALER_Amount total;
|
||||||
|
struct GNUNET_HashCode h_denom_pub;
|
||||||
const struct TALER_EXCHANGE_DenomPublicKey *dki;
|
const struct TALER_EXCHANGE_DenomPublicKey *dki;
|
||||||
|
enum TALER_ErrorCode ec;
|
||||||
|
|
||||||
dki = &ph->pk;
|
dki = &ph->pk;
|
||||||
history = json_object_get (j,
|
history = json_object_get (j,
|
||||||
@ -197,6 +199,7 @@ handle_recoup_finished (void *cls,
|
|||||||
dki->fee_deposit.currency,
|
dki->fee_deposit.currency,
|
||||||
&ph->coin_pub,
|
&ph->coin_pub,
|
||||||
history,
|
history,
|
||||||
|
&h_denom_pub,
|
||||||
&total))
|
&total))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0);
|
GNUNET_break_op (0);
|
||||||
@ -208,6 +211,43 @@ handle_recoup_finished (void *cls,
|
|||||||
hr.ec = TALER_JSON_get_error_code (j);
|
hr.ec = TALER_JSON_get_error_code (j);
|
||||||
hr.hint = TALER_JSON_get_error_hint (j);
|
hr.hint = TALER_JSON_get_error_hint (j);
|
||||||
}
|
}
|
||||||
|
ec = TALER_JSON_get_error_code (j);
|
||||||
|
switch (ec)
|
||||||
|
{
|
||||||
|
case TALER_EC_RECOUP_COIN_BALANCE_ZERO:
|
||||||
|
if (0 > TALER_amount_cmp (&total,
|
||||||
|
&dki->value))
|
||||||
|
{
|
||||||
|
/* recoup MAY have still been possible */
|
||||||
|
/* FIXME: This code may falsely complain, as we do not
|
||||||
|
know that the smallest denomination offered by the
|
||||||
|
exchange is here. We should look at the key
|
||||||
|
structure of ph->exchange, and find the smallest
|
||||||
|
_currently withdrawable_ denomination and check
|
||||||
|
if the value remaining would suffice... */GNUNET_break_op (0);
|
||||||
|
hr.http_status = 0;
|
||||||
|
hr.ec = TALER_EC_RECOUP_REPLY_MALFORMED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TALER_EC_COIN_CONFLICTING_DENOMINATION_KEY:
|
||||||
|
if (0 == GNUNET_memcmp (&ph->pk.h_key,
|
||||||
|
&h_denom_pub))
|
||||||
|
{
|
||||||
|
/* invalid proof provided */
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
hr.http_status = 0;
|
||||||
|
hr.ec = TALER_EC_RECOUP_REPLY_MALFORMED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* valid error from exchange */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
hr.http_status = 0;
|
||||||
|
hr.ec = TALER_EC_RECOUP_REPLY_MALFORMED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
ph->cb (ph->cb_cls,
|
ph->cb (ph->cb_cls,
|
||||||
&hr,
|
&hr,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -175,7 +175,9 @@ insert_deposit_run (void *cls,
|
|||||||
|
|
||||||
GNUNET_CRYPTO_rsa_public_key_hash (dpk.rsa_public_key,
|
GNUNET_CRYPTO_rsa_public_key_hash (dpk.rsa_public_key,
|
||||||
&deposit.coin.denom_pub_hash);
|
&deposit.coin.denom_pub_hash);
|
||||||
|
GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
|
&deposit.coin.coin_pub,
|
||||||
|
sizeof (deposit.coin.coin_pub));
|
||||||
GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
|
GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
|
||||||
&hc);
|
&hc);
|
||||||
deposit.coin.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_sign_fdh (denom_priv,
|
deposit.coin.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_sign_fdh (denom_priv,
|
||||||
@ -198,10 +200,9 @@ insert_deposit_run (void *cls,
|
|||||||
deposit.receiver_wire_account,
|
deposit.receiver_wire_account,
|
||||||
&deposit.h_wire));
|
&deposit.h_wire));
|
||||||
deposit.timestamp = GNUNET_TIME_absolute_get ();
|
deposit.timestamp = GNUNET_TIME_absolute_get ();
|
||||||
GNUNET_TIME_round_abs (&deposit.timestamp);
|
(void) GNUNET_TIME_round_abs (&deposit.timestamp);
|
||||||
deposit.wire_deadline = GNUNET_TIME_relative_to_absolute (
|
deposit.wire_deadline = GNUNET_TIME_relative_to_absolute (ids->wire_deadline);
|
||||||
ids->wire_deadline);
|
(void) GNUNET_TIME_round_abs (&deposit.wire_deadline);
|
||||||
GNUNET_TIME_round_abs (&deposit.wire_deadline);
|
|
||||||
|
|
||||||
/* finally, actually perform the DB operation */
|
/* finally, actually perform the DB operation */
|
||||||
if ( (GNUNET_OK !=
|
if ( (GNUNET_OK !=
|
||||||
@ -222,6 +223,8 @@ insert_deposit_run (void *cls,
|
|||||||
ids->dbc->session)) )
|
ids->dbc->session)) )
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
|
ids->dbc->plugin->rollback (ids->dbc->plugin->cls,
|
||||||
|
ids->dbc->session);
|
||||||
TALER_TESTING_interpreter_fail (is);
|
TALER_TESTING_interpreter_fail (is);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user