deal with aggregation fee lookup and calculations in auditor
This commit is contained in:
parent
4599b25895
commit
9fe8da0cc6
@ -267,6 +267,26 @@ report_reserve_balance (const struct TALER_Amount *total_balance,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report on the aggregation fees the exchange made.
|
||||||
|
*
|
||||||
|
* Note that this is for the "ongoing" reporting period. Historic
|
||||||
|
* revenue (as stored via the "insert_historic_reserve_revenue")
|
||||||
|
* is not included in the @a total_fee_balance.
|
||||||
|
*
|
||||||
|
* @param total_fee_balance how much money (in total) did the reserve
|
||||||
|
* make from aggregation fees
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
report_aggregation_fee_balance (const struct TALER_Amount *total_fee_balance)
|
||||||
|
{
|
||||||
|
// TODO: implement proper reporting logic writing to file.
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
|
||||||
|
_("Total aggregation fees are at %s\n"),
|
||||||
|
TALER_amount2s (total_fee_balance));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report state of denomination processing.
|
* Report state of denomination processing.
|
||||||
*
|
*
|
||||||
@ -1092,6 +1112,40 @@ struct WirePlugin
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about wire fees charged by the exchange.
|
||||||
|
*/
|
||||||
|
struct WireFeeInfo
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kept in a DLL.
|
||||||
|
*/
|
||||||
|
struct WireFeeInfo *next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kept in a DLL.
|
||||||
|
*/
|
||||||
|
struct WireFeeInfo *prev;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When does the fee go into effect (inclusive).
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Absolute start_date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When does the fee stop being in effect (exclusive).
|
||||||
|
*/
|
||||||
|
struct GNUNET_TIME_Absolute end_date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How high is the fee.
|
||||||
|
*/
|
||||||
|
struct TALER_Amount wire_fee;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closure for callbacks during #analyze_merchants().
|
* Closure for callbacks during #analyze_merchants().
|
||||||
*/
|
*/
|
||||||
@ -1108,6 +1162,16 @@ struct AggregationContext
|
|||||||
*/
|
*/
|
||||||
struct WirePlugin *wire_tail;
|
struct WirePlugin *wire_tail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DLL of wire fees charged by the exchange.
|
||||||
|
*/
|
||||||
|
struct WireFeeInfo *fee_head;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DLL of wire fees charged by the exchange.
|
||||||
|
*/
|
||||||
|
struct WireFeeInfo *fee_tail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How much did we make in aggregation fees.
|
* How much did we make in aggregation fees.
|
||||||
*/
|
*/
|
||||||
@ -1607,15 +1671,96 @@ wire_transfer_information_cb (void *cls,
|
|||||||
* Lookup the wire fee that the exchange charges at @a timestamp.
|
* Lookup the wire fee that the exchange charges at @a timestamp.
|
||||||
*
|
*
|
||||||
* @param ac context for caching the result
|
* @param ac context for caching the result
|
||||||
|
* @param type type of the wire plugin
|
||||||
* @param timestamp time for which we need the fee
|
* @param timestamp time for which we need the fee
|
||||||
* @return NULL on error (fee unknown)
|
* @return NULL on error (fee unknown)
|
||||||
*/
|
*/
|
||||||
static const struct TALER_Amount *
|
static const struct TALER_Amount *
|
||||||
get_wire_fee (struct AggregationContext *ac,
|
get_wire_fee (struct AggregationContext *ac,
|
||||||
|
const char *type,
|
||||||
struct GNUNET_TIME_Absolute timestamp)
|
struct GNUNET_TIME_Absolute timestamp)
|
||||||
{
|
{
|
||||||
GNUNET_break (0); /* not implemented! */
|
struct WireFeeInfo *wfi;
|
||||||
return NULL;
|
struct WireFeeInfo *pos;
|
||||||
|
struct TALER_MasterSignatureP master_sig;
|
||||||
|
|
||||||
|
/* Check if fee is already loaded in cache */
|
||||||
|
for (pos = ac->fee_head; NULL != pos; pos = pos->next)
|
||||||
|
{
|
||||||
|
if ( (pos->start_date.abs_value_us <= timestamp.abs_value_us) &&
|
||||||
|
(pos->end_date.abs_value_us > timestamp.abs_value_us) )
|
||||||
|
return &pos->wire_fee;
|
||||||
|
if (pos->start_date.abs_value_us > timestamp.abs_value_us)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lookup fee in exchange database */
|
||||||
|
wfi = GNUNET_new (struct WireFeeInfo);
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
edb->get_wire_fee (edb->cls,
|
||||||
|
esession,
|
||||||
|
type,
|
||||||
|
timestamp,
|
||||||
|
&wfi->start_date,
|
||||||
|
&wfi->end_date,
|
||||||
|
&wfi->wire_fee,
|
||||||
|
&master_sig))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
GNUNET_free (wfi);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check signature (not terribly meaningful as the exchange can
|
||||||
|
easily make this one up, but it means that we have proof that
|
||||||
|
the master key was used for inconsistent wire fees if a
|
||||||
|
merchant complains. */
|
||||||
|
{
|
||||||
|
struct TALER_MasterWireFeePS wp;
|
||||||
|
|
||||||
|
wp.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_WIRE_FEES);
|
||||||
|
wp.purpose.size = htonl (sizeof (wp));
|
||||||
|
GNUNET_CRYPTO_hash (type,
|
||||||
|
strlen (type) + 1,
|
||||||
|
&wp.h_wire_method);
|
||||||
|
wp.start_date = GNUNET_TIME_absolute_hton (wfi->start_date);
|
||||||
|
wp.end_date = GNUNET_TIME_absolute_hton (wfi->end_date);
|
||||||
|
TALER_amount_hton (&wp.wire_fee,
|
||||||
|
&wfi->wire_fee);
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_WIRE_FEES,
|
||||||
|
&wp.purpose,
|
||||||
|
&master_sig.eddsa_signature,
|
||||||
|
&master_pub.eddsa_pub))
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
GNUNET_free (wfi);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Established fee, keep in sorted list */
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"Wire fee is %s starting at %s\n",
|
||||||
|
TALER_amount2s (&wfi->wire_fee),
|
||||||
|
GNUNET_STRINGS_absolute_time_to_string (wfi->start_date));
|
||||||
|
if ( (NULL == pos) ||
|
||||||
|
(NULL == pos->prev) )
|
||||||
|
GNUNET_CONTAINER_DLL_insert (ac->fee_head,
|
||||||
|
ac->fee_tail,
|
||||||
|
wfi);
|
||||||
|
else
|
||||||
|
GNUNET_CONTAINER_DLL_insert_after (ac->fee_head,
|
||||||
|
ac->fee_tail,
|
||||||
|
pos->prev,
|
||||||
|
wfi);
|
||||||
|
/* Check non-overlaping fee invariant */
|
||||||
|
/* TODO: maybe report problems more nicely? */
|
||||||
|
if (NULL != wfi->prev)
|
||||||
|
GNUNET_break (wfi->prev->end_date.abs_value_us <= wfi->start_date.abs_value_us);
|
||||||
|
if (NULL != wfi->next)
|
||||||
|
GNUNET_break (wfi->next->start_date.abs_value_us >= wfi->end_date.abs_value_us);
|
||||||
|
return &wfi->wire_fee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1688,6 +1833,7 @@ check_wire_out_cb (void *cls,
|
|||||||
|
|
||||||
/* Subtract aggregation fee from total */
|
/* Subtract aggregation fee from total */
|
||||||
wire_fee = get_wire_fee (ac,
|
wire_fee = get_wire_fee (ac,
|
||||||
|
wcc.method,
|
||||||
date);
|
date);
|
||||||
if (NULL == wire_fee)
|
if (NULL == wire_fee)
|
||||||
{
|
{
|
||||||
@ -1750,7 +1896,7 @@ check_wire_out_cb (void *cls,
|
|||||||
|
|
||||||
/* Check that calculated amount matches actual amount */
|
/* Check that calculated amount matches actual amount */
|
||||||
if (0 != TALER_amount_cmp (amount,
|
if (0 != TALER_amount_cmp (amount,
|
||||||
&wcc.total_deposits))
|
&final_amount))
|
||||||
{
|
{
|
||||||
report_wire_out_inconsistency (wire,
|
report_wire_out_inconsistency (wire,
|
||||||
rowid,
|
rowid,
|
||||||
@ -1776,12 +1922,15 @@ analyze_aggregations (void *cls)
|
|||||||
{
|
{
|
||||||
struct AggregationContext ac;
|
struct AggregationContext ac;
|
||||||
struct WirePlugin *wc;
|
struct WirePlugin *wc;
|
||||||
|
struct WireFeeInfo *wfi;
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"Analyzing aggregations\n");
|
"Analyzing aggregations\n");
|
||||||
ac.ret = GNUNET_OK;
|
ac.ret = GNUNET_OK;
|
||||||
ac.wire_head = NULL;
|
ac.wire_head = NULL;
|
||||||
ac.wire_tail = NULL;
|
ac.wire_tail = NULL;
|
||||||
|
ac.fee_head = NULL;
|
||||||
|
ac.fee_tail = NULL;
|
||||||
/* FIXME: load existing value from DB! */
|
/* FIXME: load existing value from DB! */
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_amount_get_zero (currency,
|
TALER_amount_get_zero (currency,
|
||||||
@ -1805,13 +1954,20 @@ analyze_aggregations (void *cls)
|
|||||||
GNUNET_free (wc->type);
|
GNUNET_free (wc->type);
|
||||||
GNUNET_free (wc);
|
GNUNET_free (wc);
|
||||||
}
|
}
|
||||||
|
while (NULL != (wfi = ac.fee_head))
|
||||||
|
{
|
||||||
|
GNUNET_CONTAINER_DLL_remove (ac.fee_head,
|
||||||
|
ac.fee_tail,
|
||||||
|
wfi);
|
||||||
|
GNUNET_free (wfi);
|
||||||
|
}
|
||||||
if (GNUNET_OK != ac.ret)
|
if (GNUNET_OK != ac.ret)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
/* FIXME: store aggregation fee total to DB! */
|
/* FIXME: store aggregation fee total to DB! */
|
||||||
/* FIXME: report aggregation fee total */
|
report_aggregation_fee_balance (&ac.total_aggregation_fees);
|
||||||
return ac.ret;
|
return ac.ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user