-refactor coin history checker
This commit is contained in:
parent
3599ac0ac2
commit
3ee8879ada
@ -27,7 +27,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* UUID array for duplicate detection.
|
||||
* Context for history entry helpers.
|
||||
*/
|
||||
struct HistoryParseContext
|
||||
{
|
||||
@ -543,7 +543,7 @@ TALER_EXCHANGE_parse_reserve_history (
|
||||
.reserve_pub = reserve_pub,
|
||||
.uuids = uuid,
|
||||
.total_in = total_in,
|
||||
.total_in = total_out
|
||||
.total_out = total_out
|
||||
};
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
@ -642,71 +642,74 @@ TALER_EXCHANGE_free_reserve_history (
|
||||
}
|
||||
|
||||
|
||||
// FIMXE: also transform with helpers...
|
||||
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)
|
||||
/**
|
||||
* Context for coin helpers.
|
||||
*/
|
||||
struct CoinHistoryParseContext
|
||||
{
|
||||
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;
|
||||
|
||||
/**
|
||||
* Where to sum up fees.
|
||||
*/
|
||||
struct TALER_Amount fee;
|
||||
|
||||
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,
|
||||
&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 ()
|
||||
/**
|
||||
* Total amount encountered.
|
||||
*/
|
||||
struct TALER_Amount *total;
|
||||
|
||||
};
|
||||
|
||||
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,
|
||||
&rtotal))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
add = GNUNET_SYSERR;
|
||||
if (0 == strcasecmp (type,
|
||||
"DEPOSIT"))
|
||||
|
||||
/**
|
||||
* Signature of functions that operate on one of
|
||||
* the coin's history entries.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
typedef enum GNUNET_GenericReturnValue
|
||||
(*CoinCheckHelper)(struct CoinHistoryParseContext *pc,
|
||||
const struct TALER_Amount *amount,
|
||||
json_t *transaction);
|
||||
|
||||
|
||||
/**
|
||||
* Handle 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_deposit (struct CoinHistoryParseContext *pc,
|
||||
const struct TALER_Amount *amount,
|
||||
json_t *transaction)
|
||||
{
|
||||
struct TALER_MerchantWireHashP h_wire;
|
||||
struct TALER_PrivateContractHashP h_contract_terms;
|
||||
@ -725,7 +728,7 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
GNUNET_JSON_spec_fixed_auto ("h_wire",
|
||||
&h_wire),
|
||||
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
|
||||
h_denom_pub),
|
||||
pc->h_denom_pub),
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||
&hac),
|
||||
@ -737,7 +740,7 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
&refund_deadline),
|
||||
NULL),
|
||||
TALER_JSON_spec_amount_any ("deposit_fee",
|
||||
&fee),
|
||||
&pc->fee),
|
||||
GNUNET_JSON_spec_fixed_auto ("merchant_pub",
|
||||
&merchant_pub),
|
||||
GNUNET_JSON_spec_end ()
|
||||
@ -753,40 +756,53 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_deposit_verify (
|
||||
&amount,
|
||||
&fee,
|
||||
amount,
|
||||
&pc->fee,
|
||||
&h_wire,
|
||||
&h_contract_terms,
|
||||
no_hac ? NULL : &hac,
|
||||
NULL /* h_extensions! */,
|
||||
h_denom_pub,
|
||||
pc->h_denom_pub,
|
||||
wallet_timestamp,
|
||||
&merchant_pub,
|
||||
refund_deadline,
|
||||
coin_pub,
|
||||
pc->coin_pub,
|
||||
&sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (NULL != dk)
|
||||
if (NULL != pc->dk)
|
||||
{
|
||||
/* check that deposit fee matches our expectations from /keys! */
|
||||
if ( (GNUNET_YES !=
|
||||
TALER_amount_cmp_currency (&fee,
|
||||
&dk->fees.deposit)) ||
|
||||
TALER_amount_cmp_currency (&pc->fee,
|
||||
&pc->dk->fees.deposit)) ||
|
||||
(0 !=
|
||||
TALER_amount_cmp (&fee,
|
||||
&dk->fees.deposit)) )
|
||||
TALER_amount_cmp (&pc->fee,
|
||||
&pc->dk->fees.deposit)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
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_RefreshCommitmentP rc;
|
||||
@ -798,13 +814,13 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
GNUNET_JSON_spec_fixed_auto ("rc",
|
||||
&rc),
|
||||
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
|
||||
h_denom_pub),
|
||||
pc->h_denom_pub),
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
|
||||
&h_age_commitment),
|
||||
&no_hac),
|
||||
TALER_JSON_spec_amount_any ("melt_fee",
|
||||
&fee),
|
||||
&pc->fee),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
|
||||
@ -817,15 +833,15 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (NULL != dk)
|
||||
if (NULL != pc->dk)
|
||||
{
|
||||
/* check that melt fee matches our expectations from /keys! */
|
||||
if ( (GNUNET_YES !=
|
||||
TALER_amount_cmp_currency (&fee,
|
||||
&dk->fees.refresh)) ||
|
||||
TALER_amount_cmp_currency (&pc->fee,
|
||||
&pc->dk->fees.refresh)) ||
|
||||
(0 !=
|
||||
TALER_amount_cmp (&fee,
|
||||
&dk->fees.refresh)) )
|
||||
TALER_amount_cmp (&pc->fee,
|
||||
&pc->dk->fees.refresh)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
@ -834,23 +850,36 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_melt_verify (
|
||||
&amount,
|
||||
&fee,
|
||||
amount,
|
||||
&pc->fee,
|
||||
&rc,
|
||||
h_denom_pub,
|
||||
pc->h_denom_pub,
|
||||
no_hac
|
||||
? NULL
|
||||
: &h_age_commitment,
|
||||
coin_pub,
|
||||
pc->coin_pub,
|
||||
&sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
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_MerchantPublicKeyP merchant_pub;
|
||||
@ -883,13 +912,13 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
if (0 >
|
||||
TALER_amount_add (&sig_amount,
|
||||
&refund_fee,
|
||||
&amount))
|
||||
amount))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_merchant_refund_verify (coin_pub,
|
||||
TALER_merchant_refund_verify (pc->coin_pub,
|
||||
&h_contract_terms,
|
||||
rtransaction_id,
|
||||
&sig_amount,
|
||||
@ -908,23 +937,36 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
well-formendess check). */
|
||||
|
||||
/* check that refund fee matches our expectations from /keys! */
|
||||
if (NULL != dk)
|
||||
if (NULL != pc->dk)
|
||||
{
|
||||
if ( (GNUNET_YES !=
|
||||
TALER_amount_cmp_currency (&refund_fee,
|
||||
&dk->fees.refund)) ||
|
||||
&pc->dk->fees.refund)) ||
|
||||
(0 !=
|
||||
TALER_amount_cmp (&refund_fee,
|
||||
&dk->fees.refund)) )
|
||||
&pc->dk->fees.refund)) )
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
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 GNUNET_TIME_Timestamp timestamp;
|
||||
@ -933,8 +975,6 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
struct TALER_ExchangeSignatureP exchange_sig;
|
||||
struct TALER_CoinSpendSignatureP coin_sig;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_amount_any ("amount",
|
||||
&amount),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
|
||||
&exchange_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
|
||||
@ -946,7 +986,7 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
GNUNET_JSON_spec_fixed_auto ("coin_blind",
|
||||
&coin_bks),
|
||||
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
|
||||
h_denom_pub),
|
||||
pc->h_denom_pub),
|
||||
GNUNET_JSON_spec_timestamp ("timestamp",
|
||||
×tamp),
|
||||
GNUNET_JSON_spec_end ()
|
||||
@ -963,8 +1003,8 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
if (GNUNET_OK !=
|
||||
TALER_exchange_online_confirm_recoup_verify (
|
||||
timestamp,
|
||||
&amount,
|
||||
coin_pub,
|
||||
amount,
|
||||
pc->coin_pub,
|
||||
&reserve_pub,
|
||||
&exchange_pub,
|
||||
&exchange_sig))
|
||||
@ -973,31 +1013,41 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_recoup_verify (h_denom_pub,
|
||||
TALER_wallet_recoup_verify (pc->h_denom_pub,
|
||||
&coin_bks,
|
||||
coin_pub,
|
||||
pc->coin_pub,
|
||||
&coin_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
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,
|
||||
the value being credited to the old coin. */
|
||||
struct TALER_CoinSpendPublicKeyP old_coin_pub;
|
||||
union TALER_DenominationBlindingKeyP coin_bks;
|
||||
struct TALER_Amount amount;
|
||||
struct GNUNET_TIME_Timestamp timestamp;
|
||||
struct TALER_ExchangePublicKeyP exchange_pub;
|
||||
struct TALER_ExchangeSignatureP exchange_sig;
|
||||
struct TALER_CoinSpendSignatureP coin_sig;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_amount_any ("amount",
|
||||
&amount),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
|
||||
&exchange_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
|
||||
@ -1009,7 +1059,7 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
GNUNET_JSON_spec_fixed_auto ("coin_blind",
|
||||
&coin_bks),
|
||||
GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
|
||||
h_denom_pub),
|
||||
pc->h_denom_pub),
|
||||
GNUNET_JSON_spec_timestamp ("timestamp",
|
||||
×tamp),
|
||||
GNUNET_JSON_spec_end ()
|
||||
@ -1026,8 +1076,8 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
if (GNUNET_OK !=
|
||||
TALER_exchange_online_confirm_recoup_refresh_verify (
|
||||
timestamp,
|
||||
&amount,
|
||||
coin_pub,
|
||||
amount,
|
||||
pc->coin_pub,
|
||||
&old_coin_pub,
|
||||
&exchange_pub,
|
||||
&exchange_sig))
|
||||
@ -1036,18 +1086,31 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
TALER_wallet_recoup_verify (h_denom_pub,
|
||||
TALER_wallet_recoup_verify (pc->h_denom_pub,
|
||||
&coin_bks,
|
||||
coin_pub,
|
||||
pc->coin_pub,
|
||||
&coin_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
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,
|
||||
the value being credited to the this coin. */
|
||||
@ -1056,8 +1119,6 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
struct TALER_CoinSpendPublicKeyP new_coin_pub;
|
||||
struct GNUNET_TIME_Timestamp timestamp;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
TALER_JSON_spec_amount_any ("amount",
|
||||
&amount),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_sig",
|
||||
&exchange_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("exchange_pub",
|
||||
@ -1080,35 +1141,139 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
if (GNUNET_OK !=
|
||||
TALER_exchange_online_confirm_recoup_refresh_verify (
|
||||
timestamp,
|
||||
&amount,
|
||||
amount,
|
||||
&new_coin_pub,
|
||||
coin_pub,
|
||||
pc->coin_pub,
|
||||
&exchange_pub,
|
||||
&exchange_sig))
|
||||
{
|
||||
GNUNET_break_op (0);
|
||||
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!
|
||||
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_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Unexpected type `%s' in response\n",
|
||||
type);
|
||||
GNUNET_assert (GNUNET_SYSERR == add);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (GNUNET_YES == add)
|
||||
{
|
||||
case GNUNET_YES:
|
||||
/* This amount should be added to the total */
|
||||
if (0 >
|
||||
TALER_amount_add (total,
|
||||
@ -1119,35 +1284,30 @@ TALER_EXCHANGE_verify_coin_history (
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
case GNUNET_NO:
|
||||
/* This amount should be subtracted from the total.
|
||||
|
||||
However, for the implementation, we first *add* up all of
|
||||
these negative amounts, as we might get refunds before
|
||||
deposits from a semi-evil exchange. Then, at the end, we do
|
||||
the subtraction by calculating "total = total - rtotal" */
|
||||
GNUNET_assert (GNUNET_NO == add);
|
||||
if (0 >
|
||||
TALER_amount_add (&rtotal,
|
||||
&rtotal,
|
||||
TALER_amount_add (&pc.rtotal,
|
||||
&pc.rtotal,
|
||||
&amount))
|
||||
{
|
||||
/* overflow in refund history? inconceivable! Bad exchange! */
|
||||
GNUNET_break_op (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
} /* end of switch(add) */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Finally, subtract 'rtotal' from total to handle the subtractions */
|
||||
if (0 >
|
||||
TALER_amount_subtract (total,
|
||||
total,
|
||||
&rtotal))
|
||||
&pc.rtotal))
|
||||
{
|
||||
/* underflow in history? inconceivable! Bad exchange! */
|
||||
GNUNET_break_op (0);
|
||||
|
Loading…
Reference in New Issue
Block a user