round amounts based on config, do unit test for rounding
This commit is contained in:
parent
b37fff0d5b
commit
da5b3ba8ae
@ -85,6 +85,11 @@ static struct TALER_EXCHANGEDB_Plugin *edb;
|
||||
*/
|
||||
static char *currency;
|
||||
|
||||
/**
|
||||
* How many fractional digits does the currency use?
|
||||
*/
|
||||
static uint8_t currency_rounding_fractional_digits;
|
||||
|
||||
/**
|
||||
* Our configuration.
|
||||
*/
|
||||
@ -2895,7 +2900,8 @@ check_wire_out_cb
|
||||
}
|
||||
|
||||
/* Round down to amount supported by wire method */
|
||||
GNUNET_break (TALER_amount_round (&final_amount));
|
||||
GNUNET_break (TALER_amount_round_down (&final_amount,
|
||||
currency_rounding_fractional_digits));
|
||||
|
||||
/* Calculate the exchange's gain as the fees plus rounding differences! */
|
||||
if (GNUNET_OK !=
|
||||
@ -5204,6 +5210,30 @@ run (void *cls,
|
||||
global_ret = 1;
|
||||
return;
|
||||
}
|
||||
{
|
||||
unsigned long long num;
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_number (cfg,
|
||||
"taler",
|
||||
"CURRENCY_ROUNDING_FRACTIONAL_DIGITS",
|
||||
&num))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"No [taler]/CURRENCY_ROUNDING_FRACTIONAL_DIGITS specified, defaulting to 2 digits.\n");
|
||||
currency_rounding_fractional_digits = 2;
|
||||
}
|
||||
else if (num > TALER_AMOUNT_FRAC_LEN)
|
||||
{
|
||||
global_ret = 1;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Value of CURRENCY_ROUNDING_FRACTIONAL_DIGITS too big.\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
currency_rounding_fractional_digits = (uint8_t) num;
|
||||
}
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_time (cfg,
|
||||
"exchangedb",
|
||||
|
@ -226,6 +226,11 @@ static struct CloseTransferContext *ctc;
|
||||
*/
|
||||
static char *exchange_currency_string;
|
||||
|
||||
/**
|
||||
* How many fractional digits does the currency use?
|
||||
*/
|
||||
static uint8_t currency_rounding_fractional_digits;
|
||||
|
||||
/**
|
||||
* What is the base URL of this exchange?
|
||||
*/
|
||||
@ -614,6 +619,30 @@ exchange_serve_process_config ()
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
{
|
||||
unsigned long long num;
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONFIGURATION_get_value_number (cfg,
|
||||
"taler",
|
||||
"CURRENCY_ROUNDING_FRACTIONAL_DIGITS",
|
||||
&num))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"No [taler]/CURRENCY_ROUNDING_FRACTIONAL_DIGITS specified, defaulting to 2 digits.\n");
|
||||
currency_rounding_fractional_digits = 2;
|
||||
}
|
||||
else if (num > TALER_AMOUNT_FRAC_LEN)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Value of CURRENCY_ROUNDING_FRACTIONAL_DIGITS too big.\n");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
currency_rounding_fractional_digits = (uint8_t) num;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL ==
|
||||
(db_plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
|
||||
{
|
||||
@ -1116,7 +1145,8 @@ expired_reserve_cb (void *cls,
|
||||
}
|
||||
/* round down to enable transfer */
|
||||
if (GNUNET_SYSERR ==
|
||||
TALER_amount_round (&amount_without_fee))
|
||||
TALER_amount_round_down (&amount_without_fee,
|
||||
currency_rounding_fractional_digits))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
global_ret = GNUNET_SYSERR;
|
||||
@ -1447,7 +1477,8 @@ run_aggregation (void *cls)
|
||||
&au->total_amount,
|
||||
&au->wire_fee)) ||
|
||||
(GNUNET_SYSERR ==
|
||||
TALER_amount_round (&au->final_amount)) ||
|
||||
TALER_amount_round_down (&au->final_amount,
|
||||
currency_rounding_fractional_digits)) ||
|
||||
( (0 == au->final_amount.value) &&
|
||||
(0 == au->final_amount.fraction) ) )
|
||||
{
|
||||
|
@ -310,15 +310,16 @@ TALER_amount2s (const struct TALER_Amount *amount);
|
||||
|
||||
|
||||
/**
|
||||
* Round the amount to something that can be
|
||||
* transferred on the wire.
|
||||
* Round the amount to something that can be transferred on the wire.
|
||||
*
|
||||
* @param[in,out] amount amount to round down
|
||||
* @param max_fractional_digits number of fractional digits to round down to
|
||||
* @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
|
||||
* #GNUNET_SYSERR if the amount or currency was invalid
|
||||
*/
|
||||
int
|
||||
TALER_amount_round (struct TALER_Amount *amount);
|
||||
TALER_amount_round_down (struct TALER_Amount *amount,
|
||||
uint8_t max_fractional_digits);
|
||||
|
||||
|
||||
#if 0 /* keep Emacsens' auto-indent happy */
|
||||
|
@ -673,19 +673,24 @@ TALER_amount_divide (struct TALER_Amount *result,
|
||||
|
||||
|
||||
/**
|
||||
* Round the amount to something that can be
|
||||
* transferred on the wire.
|
||||
* Round the amount to something that can be transferred on the wire.
|
||||
*
|
||||
* @param[in,out] amount amount to round down
|
||||
* @param max_fractional_digits number of fractional digits to round down to
|
||||
* @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
|
||||
* #GNUNET_SYSERR if the amount or currency was invalid
|
||||
*/
|
||||
int
|
||||
TALER_amount_round (struct TALER_Amount *amount)
|
||||
TALER_amount_round_down (struct TALER_Amount *amount,
|
||||
uint8_t max_fractional_digits)
|
||||
{
|
||||
uint32_t delta;
|
||||
uint32_t divisor = 1;
|
||||
|
||||
delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / 100);
|
||||
for (unsigned int i = 0; i < max_fractional_digits; i++)
|
||||
divisor *= 10;
|
||||
|
||||
delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / divisor);
|
||||
if (0 == delta)
|
||||
return GNUNET_NO;
|
||||
amount->fraction -= delta;
|
||||
|
@ -234,6 +234,29 @@ main (int argc,
|
||||
GNUNET_assert (0 == a2.value);
|
||||
GNUNET_assert (1 == a2.fraction);
|
||||
|
||||
/* test rounding #1 */
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount ("EUR:4.001",
|
||||
&a1));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount ("EUR:4",
|
||||
&a2));
|
||||
|
||||
GNUNET_assert (GNUNET_OK == TALER_amount_round_down (&a1, 2));
|
||||
GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, 2));
|
||||
GNUNET_assert (0 == TALER_amount_cmp (&a1, &a2));
|
||||
|
||||
/* test rounding #2 */
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount ("EUR:4.001",
|
||||
&a1));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_string_to_amount ("EUR:4.001",
|
||||
&a2));
|
||||
GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, 3));
|
||||
GNUNET_assert (0 == TALER_amount_cmp (&a1, &a2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user