-refactor coin history checker

This commit is contained in:
Christian Grothoff 2022-05-23 00:19:57 +02:00
parent 3599ac0ac2
commit 3ee8879ada
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC

View File

@ -27,7 +27,7 @@
/** /**
* UUID array for duplicate detection. * Context for history entry helpers.
*/ */
struct HistoryParseContext struct HistoryParseContext
{ {
@ -543,7 +543,7 @@ TALER_EXCHANGE_parse_reserve_history (
.reserve_pub = reserve_pub, .reserve_pub = reserve_pub,
.uuids = uuid, .uuids = uuid,
.total_in = total_in, .total_in = total_in,
.total_in = total_out .total_out = total_out
}; };
GNUNET_assert (GNUNET_OK == GNUNET_assert (GNUNET_OK ==
@ -642,71 +642,74 @@ TALER_EXCHANGE_free_reserve_history (
} }
// FIMXE: also transform with helpers... /**
enum GNUNET_GenericReturnValue * Context for coin helpers.
TALER_EXCHANGE_verify_coin_history ( */
const struct TALER_EXCHANGE_DenomPublicKey *dk, struct CoinHistoryParseContext
const char *currency,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
json_t *history,
struct TALER_DenominationHashP *h_denom_pub,
struct TALER_Amount *total)
{ {
size_t len;
/**
* Denomination of the coin.
*/
const struct TALER_EXCHANGE_DenomPublicKey *dk;
/**
* Our coin public key.
*/
const struct TALER_CoinSpendPublicKeyP *coin_pub;
/**
* Hash of @e dk, set from parsing.
*/
struct TALER_DenominationHashP *h_denom_pub;
/**
* Where to sum up total refunds.
*/
struct TALER_Amount rtotal; struct TALER_Amount rtotal;
/**
* Where to sum up fees.
*/
struct TALER_Amount fee; struct TALER_Amount fee;
if (NULL == history) /**
{ * Total amount encountered.
GNUNET_break_op (0); */
return GNUNET_SYSERR; struct TALER_Amount *total;
}
len = json_array_size (history);
if (0 == len)
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (currency,
total));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (currency,
&rtotal));
for (size_t off = 0; off<len; off++)
{
int add;
json_t *transaction;
struct TALER_Amount amount;
const char *type;
struct GNUNET_JSON_Specification spec_glob[] = {
TALER_JSON_spec_amount_any ("amount",
&amount),
GNUNET_JSON_spec_string ("type",
&type),
GNUNET_JSON_spec_end ()
}; };
transaction = json_array_get (history,
off); /**
if (GNUNET_OK != * Signature of functions that operate on one of
GNUNET_JSON_parse (transaction, * the coin's history entries.
spec_glob, *
NULL, NULL)) * @param[in,out] pc overall context
{ * @param amount main amount of this operation
GNUNET_break_op (0); * @param transaction JSON details for the operation
return GNUNET_SYSERR; * @return #GNUNET_SYSERR on error,
} * #GNUNET_OK to add, #GNUNET_NO to subtract
if (GNUNET_YES != */
TALER_amount_cmp_currency (&amount, typedef enum GNUNET_GenericReturnValue
&rtotal)) (*CoinCheckHelper)(struct CoinHistoryParseContext *pc,
{ const struct TALER_Amount *amount,
GNUNET_break_op (0); json_t *transaction);
return GNUNET_SYSERR;
}
add = GNUNET_SYSERR; /**
if (0 == strcasecmp (type, * Handle deposit entry in the coin's history.
"DEPOSIT")) *
* @param[in,out] pc overall context
* @param amount main amount of this operation
* @param transaction JSON details for the operation
* @return #GNUNET_SYSERR on error,
* #GNUNET_OK to add, #GNUNET_NO to subtract
*/
static enum GNUNET_GenericReturnValue
help_deposit (struct CoinHistoryParseContext *pc,
const struct TALER_Amount *amount,
json_t *transaction)
{ {
struct TALER_MerchantWireHashP h_wire; struct TALER_MerchantWireHashP h_wire;
struct TALER_PrivateContractHashP h_contract_terms; struct TALER_PrivateContractHashP h_contract_terms;
@ -725,7 +728,7 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_JSON_spec_fixed_auto ("h_wire", GNUNET_JSON_spec_fixed_auto ("h_wire",
&h_wire), &h_wire),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub", GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
h_denom_pub), pc->h_denom_pub),
GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("h_age_commitment", GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
&hac), &hac),
@ -737,7 +740,7 @@ TALER_EXCHANGE_verify_coin_history (
&refund_deadline), &refund_deadline),
NULL), NULL),
TALER_JSON_spec_amount_any ("deposit_fee", TALER_JSON_spec_amount_any ("deposit_fee",
&fee), &pc->fee),
GNUNET_JSON_spec_fixed_auto ("merchant_pub", GNUNET_JSON_spec_fixed_auto ("merchant_pub",
&merchant_pub), &merchant_pub),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
@ -753,40 +756,53 @@ TALER_EXCHANGE_verify_coin_history (
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_wallet_deposit_verify ( TALER_wallet_deposit_verify (
&amount, amount,
&fee, &pc->fee,
&h_wire, &h_wire,
&h_contract_terms, &h_contract_terms,
no_hac ? NULL : &hac, no_hac ? NULL : &hac,
NULL /* h_extensions! */, NULL /* h_extensions! */,
h_denom_pub, pc->h_denom_pub,
wallet_timestamp, wallet_timestamp,
&merchant_pub, &merchant_pub,
refund_deadline, refund_deadline,
coin_pub, pc->coin_pub,
&sig)) &sig))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (NULL != dk) if (NULL != pc->dk)
{ {
/* check that deposit fee matches our expectations from /keys! */ /* check that deposit fee matches our expectations from /keys! */
if ( (GNUNET_YES != if ( (GNUNET_YES !=
TALER_amount_cmp_currency (&fee, TALER_amount_cmp_currency (&pc->fee,
&dk->fees.deposit)) || &pc->dk->fees.deposit)) ||
(0 != (0 !=
TALER_amount_cmp (&fee, TALER_amount_cmp (&pc->fee,
&dk->fees.deposit)) ) &pc->dk->fees.deposit)) )
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
} }
add = GNUNET_YES; return GNUNET_YES;
} }
else if (0 == strcasecmp (type,
"MELT"))
/**
* Handle melt entry in the coin's history.
*
* @param[in,out] pc overall context
* @param amount main amount of this operation
* @param transaction JSON details for the operation
* @return #GNUNET_SYSERR on error,
* #GNUNET_OK to add, #GNUNET_NO to subtract
*/
static enum GNUNET_GenericReturnValue
help_melt (struct CoinHistoryParseContext *pc,
const struct TALER_Amount *amount,
json_t *transaction)
{ {
struct TALER_CoinSpendSignatureP sig; struct TALER_CoinSpendSignatureP sig;
struct TALER_RefreshCommitmentP rc; struct TALER_RefreshCommitmentP rc;
@ -798,13 +814,13 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_JSON_spec_fixed_auto ("rc", GNUNET_JSON_spec_fixed_auto ("rc",
&rc), &rc),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub", GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
h_denom_pub), pc->h_denom_pub),
GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_fixed_auto ("h_age_commitment", GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
&h_age_commitment), &h_age_commitment),
&no_hac), &no_hac),
TALER_JSON_spec_amount_any ("melt_fee", TALER_JSON_spec_amount_any ("melt_fee",
&fee), &pc->fee),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
@ -817,15 +833,15 @@ TALER_EXCHANGE_verify_coin_history (
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (NULL != dk) if (NULL != pc->dk)
{ {
/* check that melt fee matches our expectations from /keys! */ /* check that melt fee matches our expectations from /keys! */
if ( (GNUNET_YES != if ( (GNUNET_YES !=
TALER_amount_cmp_currency (&fee, TALER_amount_cmp_currency (&pc->fee,
&dk->fees.refresh)) || &pc->dk->fees.refresh)) ||
(0 != (0 !=
TALER_amount_cmp (&fee, TALER_amount_cmp (&pc->fee,
&dk->fees.refresh)) ) &pc->dk->fees.refresh)) )
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
@ -834,23 +850,36 @@ TALER_EXCHANGE_verify_coin_history (
if (GNUNET_OK != if (GNUNET_OK !=
TALER_wallet_melt_verify ( TALER_wallet_melt_verify (
&amount, amount,
&fee, &pc->fee,
&rc, &rc,
h_denom_pub, pc->h_denom_pub,
no_hac no_hac
? NULL ? NULL
: &h_age_commitment, : &h_age_commitment,
coin_pub, pc->coin_pub,
&sig)) &sig))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
add = GNUNET_YES; return GNUNET_YES;
} }
else if (0 == strcasecmp (type,
"REFUND"))
/**
* Handle refund entry in the coin's history.
*
* @param[in,out] pc overall context
* @param amount main amount of this operation
* @param transaction JSON details for the operation
* @return #GNUNET_SYSERR on error,
* #GNUNET_OK to add, #GNUNET_NO to subtract
*/
static enum GNUNET_GenericReturnValue
help_refund (struct CoinHistoryParseContext *pc,
const struct TALER_Amount *amount,
json_t *transaction)
{ {
struct TALER_PrivateContractHashP h_contract_terms; struct TALER_PrivateContractHashP h_contract_terms;
struct TALER_MerchantPublicKeyP merchant_pub; struct TALER_MerchantPublicKeyP merchant_pub;
@ -883,13 +912,13 @@ TALER_EXCHANGE_verify_coin_history (
if (0 > if (0 >
TALER_amount_add (&sig_amount, TALER_amount_add (&sig_amount,
&refund_fee, &refund_fee,
&amount)) amount))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_merchant_refund_verify (coin_pub, TALER_merchant_refund_verify (pc->coin_pub,
&h_contract_terms, &h_contract_terms,
rtransaction_id, rtransaction_id,
&sig_amount, &sig_amount,
@ -908,23 +937,36 @@ TALER_EXCHANGE_verify_coin_history (
well-formendess check). */ well-formendess check). */
/* check that refund fee matches our expectations from /keys! */ /* check that refund fee matches our expectations from /keys! */
if (NULL != dk) if (NULL != pc->dk)
{ {
if ( (GNUNET_YES != if ( (GNUNET_YES !=
TALER_amount_cmp_currency (&refund_fee, TALER_amount_cmp_currency (&refund_fee,
&dk->fees.refund)) || &pc->dk->fees.refund)) ||
(0 != (0 !=
TALER_amount_cmp (&refund_fee, TALER_amount_cmp (&refund_fee,
&dk->fees.refund)) ) &pc->dk->fees.refund)) )
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
} }
add = GNUNET_NO; return GNUNET_NO;
} }
else if (0 == strcasecmp (type,
"RECOUP"))
/**
* Handle recoup entry in the coin's history.
*
* @param[in,out] pc overall context
* @param amount main amount of this operation
* @param transaction JSON details for the operation
* @return #GNUNET_SYSERR on error,
* #GNUNET_OK to add, #GNUNET_NO to subtract
*/
static enum GNUNET_GenericReturnValue
help_recoup (struct CoinHistoryParseContext *pc,
const struct TALER_Amount *amount,
json_t *transaction)
{ {
struct TALER_ReservePublicKeyP reserve_pub; struct TALER_ReservePublicKeyP reserve_pub;
struct GNUNET_TIME_Timestamp timestamp; struct GNUNET_TIME_Timestamp timestamp;
@ -933,8 +975,6 @@ TALER_EXCHANGE_verify_coin_history (
struct TALER_ExchangeSignatureP exchange_sig; struct TALER_ExchangeSignatureP exchange_sig;
struct TALER_CoinSpendSignatureP coin_sig; struct TALER_CoinSpendSignatureP coin_sig;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any ("amount",
&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",
@ -946,7 +986,7 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_JSON_spec_fixed_auto ("coin_blind", GNUNET_JSON_spec_fixed_auto ("coin_blind",
&coin_bks), &coin_bks),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub", GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
h_denom_pub), pc->h_denom_pub),
GNUNET_JSON_spec_timestamp ("timestamp", GNUNET_JSON_spec_timestamp ("timestamp",
&timestamp), &timestamp),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
@ -963,8 +1003,8 @@ TALER_EXCHANGE_verify_coin_history (
if (GNUNET_OK != if (GNUNET_OK !=
TALER_exchange_online_confirm_recoup_verify ( TALER_exchange_online_confirm_recoup_verify (
timestamp, timestamp,
&amount, amount,
coin_pub, pc->coin_pub,
&reserve_pub, &reserve_pub,
&exchange_pub, &exchange_pub,
&exchange_sig)) &exchange_sig))
@ -973,31 +1013,41 @@ TALER_EXCHANGE_verify_coin_history (
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_wallet_recoup_verify (h_denom_pub, TALER_wallet_recoup_verify (pc->h_denom_pub,
&coin_bks, &coin_bks,
coin_pub, pc->coin_pub,
&coin_sig)) &coin_sig))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
add = GNUNET_YES; return GNUNET_YES;
} }
else if (0 == strcasecmp (type,
"RECOUP-REFRESH"))
/**
* Handle recoup-refresh entry in the coin's history.
*
* @param[in,out] pc overall context
* @param amount main amount of this operation
* @param transaction JSON details for the operation
* @return #GNUNET_SYSERR on error,
* #GNUNET_OK to add, #GNUNET_NO to subtract
*/
static enum GNUNET_GenericReturnValue
help_recoup_refresh (struct CoinHistoryParseContext *pc,
const struct TALER_Amount *amount,
json_t *transaction)
{ {
/* This is the coin that was subjected to a recoup, /* This is the coin that was subjected to a recoup,
the value being credited to the old coin. */ the value being credited to the old coin. */
struct TALER_CoinSpendPublicKeyP old_coin_pub; struct TALER_CoinSpendPublicKeyP old_coin_pub;
union TALER_DenominationBlindingKeyP coin_bks; union TALER_DenominationBlindingKeyP coin_bks;
struct TALER_Amount amount;
struct GNUNET_TIME_Timestamp timestamp; struct GNUNET_TIME_Timestamp timestamp;
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 TALER_CoinSpendSignatureP coin_sig;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any ("amount",
&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",
@ -1009,7 +1059,7 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_JSON_spec_fixed_auto ("coin_blind", GNUNET_JSON_spec_fixed_auto ("coin_blind",
&coin_bks), &coin_bks),
GNUNET_JSON_spec_fixed_auto ("h_denom_pub", GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
h_denom_pub), pc->h_denom_pub),
GNUNET_JSON_spec_timestamp ("timestamp", GNUNET_JSON_spec_timestamp ("timestamp",
&timestamp), &timestamp),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
@ -1026,8 +1076,8 @@ TALER_EXCHANGE_verify_coin_history (
if (GNUNET_OK != if (GNUNET_OK !=
TALER_exchange_online_confirm_recoup_refresh_verify ( TALER_exchange_online_confirm_recoup_refresh_verify (
timestamp, timestamp,
&amount, amount,
coin_pub, pc->coin_pub,
&old_coin_pub, &old_coin_pub,
&exchange_pub, &exchange_pub,
&exchange_sig)) &exchange_sig))
@ -1036,18 +1086,31 @@ TALER_EXCHANGE_verify_coin_history (
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (GNUNET_OK != if (GNUNET_OK !=
TALER_wallet_recoup_verify (h_denom_pub, TALER_wallet_recoup_verify (pc->h_denom_pub,
&coin_bks, &coin_bks,
coin_pub, pc->coin_pub,
&coin_sig)) &coin_sig))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
add = GNUNET_YES; return GNUNET_YES;
} }
else if (0 == strcasecmp (type,
"OLD-COIN-RECOUP"))
/**
* Handle old coin recoup entry in the coin's history.
*
* @param[in,out] pc overall context
* @param amount main amount of this operation
* @param transaction JSON details for the operation
* @return #GNUNET_SYSERR on error,
* #GNUNET_OK to add, #GNUNET_NO to subtract
*/
static enum GNUNET_GenericReturnValue
help_old_coin_recoup (struct CoinHistoryParseContext *pc,
const struct TALER_Amount *amount,
json_t *transaction)
{ {
/* This is the coin that was credited in a recoup, /* This is the coin that was credited in a recoup,
the value being credited to the this coin. */ the value being credited to the this coin. */
@ -1056,8 +1119,6 @@ TALER_EXCHANGE_verify_coin_history (
struct TALER_CoinSpendPublicKeyP new_coin_pub; struct TALER_CoinSpendPublicKeyP new_coin_pub;
struct GNUNET_TIME_Timestamp timestamp; struct GNUNET_TIME_Timestamp timestamp;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount_any ("amount",
&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",
@ -1080,35 +1141,139 @@ TALER_EXCHANGE_verify_coin_history (
if (GNUNET_OK != if (GNUNET_OK !=
TALER_exchange_online_confirm_recoup_refresh_verify ( TALER_exchange_online_confirm_recoup_refresh_verify (
timestamp, timestamp,
&amount, amount,
&new_coin_pub, &new_coin_pub,
coin_pub, pc->coin_pub,
&exchange_pub, &exchange_pub,
&exchange_sig)) &exchange_sig))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
add = GNUNET_NO; return GNUNET_NO;
} }
else if (0 == strcasecmp (type,
"LOCK_NONCE"))
/**
* Handle purse deposit entry in the coin's history.
*
* @param[in,out] pc overall context
* @param amount main amount of this operation
* @param transaction JSON details for the operation
* @return #GNUNET_SYSERR on error,
* #GNUNET_OK to add, #GNUNET_NO to subtract
*/
static enum GNUNET_GenericReturnValue
help_purse_deposit (struct CoinHistoryParseContext *pc,
const struct TALER_Amount *amount,
json_t *transaction)
{ {
GNUNET_break (0); // FIXME: implement! GNUNET_break (0); // FIXME: implement!
return GNUNET_SYSERR;
} }
else
enum GNUNET_GenericReturnValue
TALER_EXCHANGE_verify_coin_history (
const struct TALER_EXCHANGE_DenomPublicKey *dk,
const char *currency,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
json_t *history,
struct TALER_DenominationHashP *h_denom_pub,
struct TALER_Amount *total)
{ {
/* signature not supported, new version on server? */ const struct
{
const char *type;
CoinCheckHelper helper;
} map[] = {
{ "DEPOSIT", &help_deposit },
{ "MELT", &help_melt },
{ "REFUND", &help_refund },
{ "RECOUP", &help_recoup },
{ "RECOUP-REFRESH", &help_recoup_refresh },
{ "OLD-COIN-RECOUP", &help_old_coin_recoup },
{ "PURSE_DEPOSIT", &help_purse_deposit },
{ NULL, NULL }
};
struct CoinHistoryParseContext pc = {
.dk = dk,
.coin_pub = coin_pub,
.total = total,
.h_denom_pub = h_denom_pub
};
size_t len;
if (NULL == history)
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
len = json_array_size (history);
if (0 == len)
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (currency,
total));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (currency,
&pc.rtotal));
for (size_t off = 0; off<len; off++)
{
enum GNUNET_GenericReturnValue add;
json_t *transaction;
struct TALER_Amount amount;
const char *type;
struct GNUNET_JSON_Specification spec_glob[] = {
TALER_JSON_spec_amount_any ("amount",
&amount),
GNUNET_JSON_spec_string ("type",
&type),
GNUNET_JSON_spec_end ()
};
transaction = json_array_get (history,
off);
if (GNUNET_OK !=
GNUNET_JSON_parse (transaction,
spec_glob,
NULL, NULL))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
if (GNUNET_YES !=
TALER_amount_cmp_currency (&amount,
&pc.rtotal))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
add = GNUNET_SYSERR;
for (unsigned int i = 0; NULL != map[i].type; i++)
{
if (0 == strcasecmp (type,
map[i].type))
{
add = map[i].helper (&pc,
&amount,
transaction);
break;
}
}
switch (add)
{
case GNUNET_SYSERR:
/* entry type not supported, new version on server? */
GNUNET_break_op (0); GNUNET_break_op (0);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected type `%s' in response\n", "Unexpected type `%s' in response\n",
type); type);
GNUNET_assert (GNUNET_SYSERR == add);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} case GNUNET_YES:
if (GNUNET_YES == add)
{
/* This amount should be added to the total */ /* This amount should be added to the total */
if (0 > if (0 >
TALER_amount_add (total, TALER_amount_add (total,
@ -1119,35 +1284,30 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
} case GNUNET_NO:
else
{
/* This amount should be subtracted from the total. /* This amount should be subtracted from the total.
However, for the implementation, we first *add* up all of However, for the implementation, we first *add* up all of
these negative amounts, as we might get refunds before these negative amounts, as we might get refunds before
deposits from a semi-evil exchange. Then, at the end, we do deposits from a semi-evil exchange. Then, at the end, we do
the subtraction by calculating "total = total - rtotal" */ the subtraction by calculating "total = total - rtotal" */
GNUNET_assert (GNUNET_NO == add);
if (0 > if (0 >
TALER_amount_add (&rtotal, TALER_amount_add (&pc.rtotal,
&rtotal, &pc.rtotal,
&amount)) &amount))
{ {
/* overflow in refund history? inconceivable! Bad exchange! */ /* overflow in refund history? inconceivable! Bad exchange! */
GNUNET_break_op (0); GNUNET_break_op (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
} /* end of switch(add) */
} }
}
/* 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,
total, total,
&rtotal)) &pc.rtotal))
{ {
/* underflow in history? inconceivable! Bad exchange! */ /* underflow in history? inconceivable! Bad exchange! */
GNUNET_break_op (0); GNUNET_break_op (0);