summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/auditor/taler-auditor.c31
-rw-r--r--src/exchange/taler-exchange-aggregator.c32
-rw-r--r--src/include/taler_amount_lib.h7
-rw-r--r--src/util/amount.c16
-rw-r--r--src/util/test_amount.c15
5 files changed, 60 insertions, 41 deletions
diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index 8b2c2c37e..f3bb0e2b7 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -88,7 +88,7 @@ static char *currency;
/**
* How many fractional digits does the currency use?
*/
-static uint8_t currency_rounding_fractional_digits;
+static struct TALER_Amount currency_round_unit;
/**
* Our configuration.
@@ -2894,7 +2894,7 @@ check_wire_out_cb
/* Round down to amount supported by wire method */
GNUNET_break (TALER_amount_round_down (&final_amount,
- currency_rounding_fractional_digits));
+ &currency_round_unit));
/* Calculate the exchange's gain as the fees plus rounding differences! */
if (GNUNET_OK !=
@@ -5205,28 +5205,29 @@ run (void *cls,
return;
}
{
- unsigned long long num;
+ char *rounding_str;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
+ GNUNET_CONFIGURATION_get_value_string (cfg,
"taler",
- "CURRENCY_ROUNDING_FRACTIONAL_DIGITS",
- &num))
+ "CURRENCY_ROUND_UNIT",
+ &rounding_str))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "No [taler]/CURRENCY_ROUNDING_FRACTIONAL_DIGITS specified, defaulting to 2 digits.\n");
- currency_rounding_fractional_digits = 2;
+ "No [taler]/CURRENCY_ROUND_UNIT specified, defaulting to '0.01'.\n");
+ TALER_amount_get_zero (currency, &currency_round_unit);
+ currency_round_unit.fraction = TALER_AMOUNT_FRAC_BASE / 100;
}
- else if (num > TALER_AMOUNT_FRAC_LEN)
+ else if (GNUNET_OK !=
+ TALER_string_to_amount (rounding_str,
+ &currency_round_unit))
{
- global_ret = 1;
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Value of CURRENCY_ROUNDING_FRACTIONAL_DIGITS too big.\n");
+ "Invalid amount `%s' specified in `TALER' under `CURRENCY_ROUND_UNIT'\n",
+ rounding_str);
+ GNUNET_free (rounding_str);
+ global_ret = 1;
return;
}
- else
- {
- currency_rounding_fractional_digits = (uint8_t) num;
- }
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_time (cfg,
diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c
index 9032cd5e3..338e979e4 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -224,7 +224,7 @@ static char *exchange_currency_string;
/**
* How many fractional digits does the currency use?
*/
-static uint8_t currency_rounding_fractional_digits;
+static struct TALER_Amount currency_round_unit;
/**
* What is the base URL of this exchange?
@@ -615,29 +615,31 @@ exchange_serve_process_config ()
}
{
- unsigned long long num;
+ char *rounding_str;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
+ GNUNET_CONFIGURATION_get_value_string (cfg,
"taler",
- "CURRENCY_ROUNDING_FRACTIONAL_DIGITS",
- &num))
+ "CURRENCY_ROUND_UNIT",
+ &rounding_str))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "No [taler]/CURRENCY_ROUNDING_FRACTIONAL_DIGITS specified, defaulting to 2 digits.\n");
- currency_rounding_fractional_digits = 2;
+ "No [taler]/CURRENCY_ROUND_UNIT specified, defaulting to '0.01'.\n");
+ TALER_amount_get_zero (exchange_currency_string, &currency_round_unit);
+ currency_round_unit.fraction = TALER_AMOUNT_FRAC_BASE / 100;
}
- else if (num > TALER_AMOUNT_FRAC_LEN)
+ else if (GNUNET_OK !=
+ TALER_string_to_amount (rounding_str,
+ &currency_round_unit))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Value of CURRENCY_ROUNDING_FRACTIONAL_DIGITS too big.\n");
+ "Invalid amount `%s' specified in `TALER' under `CURRENCY_ROUND_UNIT'\n",
+ rounding_str);
+ GNUNET_free (rounding_str);
return GNUNET_SYSERR;
}
- else
- {
- currency_rounding_fractional_digits = (uint8_t) num;
- }
}
+
if (NULL ==
(db_plugin = TALER_EXCHANGEDB_plugin_load (cfg)))
{
@@ -1120,7 +1122,7 @@ expired_reserve_cb (void *cls,
/* round down to enable transfer */
if (GNUNET_SYSERR ==
TALER_amount_round_down (&amount_without_fee,
- currency_rounding_fractional_digits))
+ &currency_round_unit))
{
GNUNET_break (0);
global_ret = GNUNET_SYSERR;
@@ -1456,7 +1458,7 @@ run_aggregation (void *cls)
&au->wire_fee)) ||
(GNUNET_SYSERR ==
TALER_amount_round_down (&au->final_amount,
- currency_rounding_fractional_digits)) ||
+ &currency_round_unit)) ||
( (0 == au->final_amount.value) &&
(0 == au->final_amount.fraction) ) )
{
diff --git a/src/include/taler_amount_lib.h b/src/include/taler_amount_lib.h
index 7118e2ecf..df1cf06f9 100644
--- a/src/include/taler_amount_lib.h
+++ b/src/include/taler_amount_lib.h
@@ -311,15 +311,18 @@ TALER_amount2s (const struct TALER_Amount *amount);
/**
* Round the amount to something that can be transferred on the wire.
+ * The rounding mode is specified via the smallest transferable unit,
+ * which must only have a fractional part.
*
* @param[in,out] amount amount to round down
- * @param max_fractional_digits number of fractional digits to round down to
+ * @param[in] round_unit unit that should be rounded down to,
+ * the value part of this amount must be zero
* @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
* #GNUNET_SYSERR if the amount or currency was invalid
*/
int
TALER_amount_round_down (struct TALER_Amount *amount,
- uint8_t max_fractional_digits);
+ const struct TALER_Amount *round_unit);
#if 0 /* keep Emacsens' auto-indent happy */
diff --git a/src/util/amount.c b/src/util/amount.c
index 48f5d9891..1f00b1d6e 100644
--- a/src/util/amount.c
+++ b/src/util/amount.c
@@ -674,23 +674,27 @@ TALER_amount_divide (struct TALER_Amount *result,
/**
* Round the amount to something that can be transferred on the wire.
+ * The rounding mode is specified via the smallest transferable unit,
+ * which must only have a fractional part.
*
* @param[in,out] amount amount to round down
- * @param max_fractional_digits number of fractional digits to round down to
+ * @param[in] round_unit unit that should be rounded down to,
+ * the value part of this amount must be zero
* @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary,
* #GNUNET_SYSERR if the amount or currency was invalid
*/
int
TALER_amount_round_down (struct TALER_Amount *amount,
- uint8_t max_fractional_digits)
+ const struct TALER_Amount *round_unit)
{
uint32_t delta;
- uint32_t divisor = 1;
- for (unsigned int i = 0; i < max_fractional_digits; i++)
- divisor *= 10;
+ GNUNET_break (0 == round_unit->value);
- delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / divisor);
+ if (0 == round_unit->fraction)
+ return GNUNET_OK;
+
+ delta = amount->fraction % round_unit->fraction;
if (0 == delta)
return GNUNET_NO;
amount->fraction -= delta;
diff --git a/src/util/test_amount.c b/src/util/test_amount.c
index 4eeccd7e0..3bf8e6fb0 100644
--- a/src/util/test_amount.c
+++ b/src/util/test_amount.c
@@ -31,6 +31,7 @@ main (int argc,
struct TALER_Amount a1;
struct TALER_Amount a2;
struct TALER_Amount a3;
+ struct TALER_Amount r;
char *c;
GNUNET_log_setup ("test-amout",
@@ -237,25 +238,33 @@ main (int argc,
/* test rounding #1 */
GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("EUR:0.01",
+ &r));
+
+ 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 (GNUNET_OK == TALER_amount_round_down (&a1, &r));
+ GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, &r));
GNUNET_assert (0 == TALER_amount_cmp (&a1, &a2));
/* test rounding #2 */
GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("EUR:0.001",
+ &r));
+
+ 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 (GNUNET_NO == TALER_amount_round_down (&a1, &r));
GNUNET_assert (0 == TALER_amount_cmp (&a1, &a2));
return 0;