exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

test_stefan.c (6824B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2023 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see
     15   <http://www.gnu.org/licenses/>
     16 */
     17 /**
     18  * @file lib/test_stefan.c
     19  * @brief test calculations on the STEFAN curve
     20  * @author Christian Grothoff
     21  */
     22 #include "taler/taler_json_lib.h"
     23 #include <gnunet/gnunet_curl_lib.h>
     24 #include "exchange_api_handle.h"
     25 
     26 
     27 /**
     28  * Check if @a a and @a b are numerically close.
     29  *
     30  * @param a an amount
     31  * @param b an amount
     32  * @return true if both values are quite close
     33  */
     34 static bool
     35 amount_close (const struct TALER_Amount *a,
     36               const struct TALER_Amount *b)
     37 {
     38   struct TALER_Amount delta;
     39 
     40   switch (TALER_amount_cmp (a,
     41                             b))
     42   {
     43   case -1: /* a < b */
     44     GNUNET_assert (0 <
     45                    TALER_amount_subtract (&delta,
     46                                           b,
     47                                           a));
     48     break;
     49   case 0:
     50     /* perfect */
     51     return true;
     52   case 1: /* a > b */
     53     GNUNET_assert (0 <
     54                    TALER_amount_subtract (&delta,
     55                                           a,
     56                                           b));
     57     break;
     58   }
     59   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     60               "Rounding error is %s\n",
     61               TALER_amount2s (&delta));
     62   if (delta.value > 0)
     63   {
     64     GNUNET_break (0);
     65     return false;
     66   }
     67   if (delta.fraction > 5000)
     68   {
     69     GNUNET_break (0);
     70     return false;
     71   }
     72   return true; /* let's consider this a rounding error */
     73 }
     74 
     75 
     76 int
     77 main (int argc,
     78       char **argv)
     79 {
     80   struct TALER_EXCHANGE_DenomPublicKey dk;
     81   struct TALER_EXCHANGE_Keys keys = {
     82     .denom_keys = &dk,
     83     .num_denom_keys = 1
     84   };
     85   struct TALER_Amount brut;
     86   struct TALER_Amount net;
     87 
     88   (void) argc;
     89   (void) argv;
     90   GNUNET_log_setup ("test-stefan",
     91                     "INFO",
     92                     NULL);
     93   GNUNET_assert (GNUNET_OK ==
     94                  TALER_string_to_amount ("MAGIC:0.00001",
     95                                          &dk.value));
     96   GNUNET_assert (GNUNET_OK ==
     97                  TALER_string_to_amount ("MAGIC:1",
     98                                          &keys.stefan_abs));
     99   GNUNET_assert (GNUNET_OK ==
    100                  TALER_string_to_amount ("MAGIC:0.13",
    101                                          &keys.stefan_log));
    102   keys.stefan_lin = 1.15;
    103   GNUNET_assert (GNUNET_OK ==
    104                  TALER_string_to_amount ("MAGIC:4",
    105                                          &brut));
    106   GNUNET_log_skip (1,
    107                    GNUNET_NO);
    108   GNUNET_assert (GNUNET_SYSERR ==
    109                  TALER_EXCHANGE_keys_stefan_b2n (&keys,
    110                                                  &brut,
    111                                                  &net));
    112   GNUNET_assert (GNUNET_OK ==
    113                  TALER_string_to_amount ("MAGIC:4",
    114                                          &net));
    115   GNUNET_log_skip (1,
    116                    GNUNET_NO);
    117   GNUNET_assert (GNUNET_SYSERR ==
    118                  TALER_EXCHANGE_keys_stefan_n2b (&keys,
    119                                                  &net,
    120                                                  &brut));
    121   keys.stefan_lin = 1.0;
    122   GNUNET_assert (GNUNET_OK ==
    123                  TALER_string_to_amount ("MAGIC:4",
    124                                          &brut));
    125   GNUNET_log_skip (1,
    126                    GNUNET_NO);
    127   GNUNET_assert (GNUNET_SYSERR ==
    128                  TALER_EXCHANGE_keys_stefan_b2n (&keys,
    129                                                  &brut,
    130                                                  &net));
    131   GNUNET_assert (GNUNET_OK ==
    132                  TALER_string_to_amount ("MAGIC:4",
    133                                          &net));
    134   GNUNET_log_skip (1,
    135                    GNUNET_NO);
    136   GNUNET_assert (GNUNET_SYSERR ==
    137                  TALER_EXCHANGE_keys_stefan_n2b (&keys,
    138                                                  &net,
    139                                                  &brut));
    140   GNUNET_assert (0 == GNUNET_get_log_skip ());
    141   keys.stefan_lin = 0.1;
    142 
    143   /* try various values for lin and log STEFAN values */
    144   for (unsigned int li = 1; li < 13; li += 1)
    145   {
    146     keys.stefan_lin = 1.0 * li / 100.0;
    147 
    148     for (unsigned int lx = 1; lx < 100; lx += 1)
    149     {
    150       keys.stefan_log.fraction = lx * TALER_AMOUNT_FRAC_BASE / 100;
    151 
    152       /* Check brutto-to-netto is stable */
    153       for (unsigned int i = 0; i<10; i++)
    154       {
    155         struct TALER_Amount rval;
    156 
    157         brut.value = i;
    158         brut.fraction = i * TALER_AMOUNT_FRAC_BASE / 10;
    159         GNUNET_assert (GNUNET_SYSERR !=
    160                        TALER_EXCHANGE_keys_stefan_b2n (&keys,
    161                                                        &brut,
    162                                                        &net));
    163         GNUNET_assert (GNUNET_SYSERR !=
    164                        TALER_EXCHANGE_keys_stefan_n2b (&keys,
    165                                                        &net,
    166                                                        &rval));
    167         if (TALER_amount_is_zero (&net))
    168           GNUNET_assert (TALER_amount_is_zero (&rval));
    169         else
    170         {
    171           GNUNET_assert (amount_close (&brut,
    172                                        &rval));
    173           TALER_EXCHANGE_keys_stefan_round (&keys,
    174                                             &rval);
    175           GNUNET_assert (amount_close (&brut,
    176                                        &rval));
    177         }
    178       }
    179 
    180       /* Check netto-to-brutto is stable */
    181       for (unsigned int i = 0; i<10; i++)
    182       {
    183         struct TALER_Amount rval;
    184 
    185         net.value = i;
    186         net.fraction = i * TALER_AMOUNT_FRAC_BASE / 10;
    187         GNUNET_assert (GNUNET_SYSERR !=
    188                        TALER_EXCHANGE_keys_stefan_n2b (&keys,
    189                                                        &net,
    190                                                        &brut));
    191         GNUNET_assert (GNUNET_SYSERR !=
    192                        TALER_EXCHANGE_keys_stefan_b2n (&keys,
    193                                                        &brut,
    194                                                        &rval));
    195         GNUNET_assert (amount_close (&net,
    196                                      &rval));
    197         TALER_EXCHANGE_keys_stefan_round (&keys,
    198                                           &rval);
    199         GNUNET_assert (amount_close (&net,
    200                                      &rval));
    201       }
    202     }
    203   }
    204   return 0;
    205 }