-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
|
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",
|
||||||
×tamp),
|
×tamp),
|
||||||
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",
|
||||||
×tamp),
|
×tamp),
|
||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user