exchange

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

json_pack.c (14291B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2021-2025 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 <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file json/json_pack.c
     18  * @brief helper functions for JSON object packing
     19  * @author Christian Grothoff
     20  * @author Özgür Kesim
     21  */
     22 #include <gnunet/gnunet_util_lib.h>
     23 #include "taler/taler_util.h"
     24 #include "taler/taler_json_lib.h"
     25 
     26 
     27 struct GNUNET_JSON_PackSpec
     28 TALER_JSON_pack_time_abs_human (const char *name,
     29                                 struct GNUNET_TIME_Absolute at)
     30 {
     31   struct GNUNET_JSON_PackSpec ps = {
     32     .field_name = name,
     33     .object = json_string (
     34       GNUNET_STRINGS_absolute_time_to_string (at))
     35   };
     36 
     37   return ps;
     38 }
     39 
     40 
     41 struct GNUNET_JSON_PackSpec
     42 TALER_JSON_pack_econtract (
     43   const char *name,
     44   const struct TALER_EncryptedContract *econtract)
     45 {
     46   struct GNUNET_JSON_PackSpec ps = {
     47     .field_name = name,
     48   };
     49 
     50   if (NULL == econtract)
     51     return ps;
     52   ps.object
     53     = GNUNET_JSON_PACK (
     54         GNUNET_JSON_pack_data_varsize ("econtract",
     55                                        econtract->econtract,
     56                                        econtract->econtract_size),
     57         GNUNET_JSON_pack_data_auto ("econtract_sig",
     58                                     &econtract->econtract_sig),
     59         GNUNET_JSON_pack_data_auto ("contract_pub",
     60                                     &econtract->contract_pub));
     61   return ps;
     62 }
     63 
     64 
     65 struct GNUNET_JSON_PackSpec
     66 TALER_JSON_pack_age_commitment (
     67   const char *name,
     68   const struct TALER_AgeCommitment *age_commitment)
     69 {
     70   struct GNUNET_JSON_PackSpec ps = {
     71     .field_name = name,
     72   };
     73   json_t *keys;
     74 
     75   if (NULL == age_commitment ||
     76       0 == age_commitment->num)
     77     return ps;
     78 
     79   GNUNET_assert (NULL !=
     80                  (keys = json_array ()));
     81 
     82   for (size_t i = 0;
     83        i < age_commitment->num;
     84        i++)
     85   {
     86     json_t *val;
     87     val = GNUNET_JSON_from_data (&age_commitment->pubs[i],
     88                                  sizeof(age_commitment->pubs[i]));
     89     GNUNET_assert (NULL != val);
     90     GNUNET_assert (0 ==
     91                    json_array_append_new (keys, val));
     92   }
     93 
     94   ps.object = keys;
     95   return ps;
     96 }
     97 
     98 
     99 struct GNUNET_JSON_PackSpec
    100 TALER_JSON_pack_kycte (const char *name,
    101                        enum TALER_KYCLOGIC_KycTriggerEvent event)
    102 {
    103   const char *str = "INVALID";
    104 
    105   switch (event)
    106   {
    107   case TALER_KYCLOGIC_KYC_TRIGGER_NONE:
    108     str = "NONE";
    109     break;
    110   case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW:
    111     str = "WITHDRAW";
    112     break;
    113   case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT:
    114     str = "DEPOSIT";
    115     break;
    116   case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE:
    117     str = "MERGE";
    118     break;
    119   case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE:
    120     str = "BALANCE";
    121     break;
    122   case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE:
    123     str = "CLOSE";
    124     break;
    125   case TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE:
    126     str = "AGGREGATE";
    127     break;
    128   case TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION:
    129     str = "TRANSACTION";
    130     break;
    131   case TALER_KYCLOGIC_KYC_TRIGGER_REFUND:
    132     str = "REFUND";
    133     break;
    134   }
    135   return GNUNET_JSON_pack_string (name,
    136                                   str);
    137 }
    138 
    139 
    140 struct GNUNET_JSON_PackSpec
    141 TALER_JSON_pack_denom_pub (
    142   const char *name,
    143   const struct TALER_DenominationPublicKey *pk)
    144 {
    145   const struct GNUNET_CRYPTO_BlindSignPublicKey *bsp;
    146   struct GNUNET_JSON_PackSpec ps = {
    147     .field_name = name,
    148   };
    149 
    150   if (NULL == pk)
    151     return ps;
    152   bsp = pk->bsign_pub_key;
    153   switch (bsp->cipher)
    154   {
    155   case GNUNET_CRYPTO_BSA_INVALID:
    156     break;
    157   case GNUNET_CRYPTO_BSA_RSA:
    158     ps.object
    159       = GNUNET_JSON_PACK (
    160           GNUNET_JSON_pack_string ("cipher",
    161                                    "RSA"),
    162           GNUNET_JSON_pack_uint64 ("age_mask",
    163                                    pk->age_mask.bits),
    164           GNUNET_JSON_pack_rsa_public_key ("rsa_pub",
    165                                            bsp->details.rsa_public_key));
    166     return ps;
    167   case GNUNET_CRYPTO_BSA_CS:
    168     ps.object
    169       = GNUNET_JSON_PACK (
    170           GNUNET_JSON_pack_string ("cipher",
    171                                    "CS"),
    172           GNUNET_JSON_pack_uint64 ("age_mask",
    173                                    pk->age_mask.bits),
    174           GNUNET_JSON_pack_data_varsize ("cs_pub",
    175                                          &bsp->details.cs_public_key,
    176                                          sizeof (bsp->details.cs_public_key)));
    177     return ps;
    178   }
    179   GNUNET_assert (0);
    180   return ps;
    181 }
    182 
    183 
    184 struct GNUNET_JSON_PackSpec
    185 TALER_JSON_pack_token_pub (
    186   const char *name,
    187   const struct TALER_TokenIssuePublicKey *pk)
    188 {
    189   const struct GNUNET_CRYPTO_BlindSignPublicKey *bsp;
    190   struct GNUNET_JSON_PackSpec ps = {
    191     .field_name = name,
    192   };
    193 
    194   if (NULL == pk)
    195     return ps;
    196   bsp = pk->public_key;
    197   switch (bsp->cipher)
    198   {
    199   case GNUNET_CRYPTO_BSA_INVALID:
    200     break;
    201   case GNUNET_CRYPTO_BSA_RSA:
    202     ps.object
    203       = GNUNET_JSON_PACK (
    204           GNUNET_JSON_pack_string ("cipher",
    205                                    "RSA"),
    206           GNUNET_JSON_pack_rsa_public_key ("rsa_pub",
    207                                            bsp->details.rsa_public_key));
    208     return ps;
    209   case GNUNET_CRYPTO_BSA_CS:
    210     ps.object
    211       = GNUNET_JSON_PACK (
    212           GNUNET_JSON_pack_string ("cipher",
    213                                    "CS"),
    214           GNUNET_JSON_pack_data_varsize ("cs_pub",
    215                                          &bsp->details.cs_public_key,
    216                                          sizeof (bsp->details.cs_public_key)));
    217     return ps;
    218   }
    219   GNUNET_assert (0);
    220   return ps;
    221 }
    222 
    223 
    224 struct GNUNET_JSON_PackSpec
    225 TALER_JSON_pack_denom_sig (
    226   const char *name,
    227   const struct TALER_DenominationSignature *sig)
    228 {
    229   struct GNUNET_JSON_PackSpec ps = {
    230     .field_name = name,
    231   };
    232   if (NULL == sig)
    233     return ps;
    234   return GNUNET_JSON_pack_unblinded_signature (name,
    235                                                sig->unblinded_sig);
    236 }
    237 
    238 
    239 struct GNUNET_JSON_PackSpec
    240 TALER_JSON_pack_token_issue_sig (
    241   const char *name,
    242   const struct TALER_TokenIssueSignature *sig)
    243 {
    244   struct GNUNET_JSON_PackSpec ps = {
    245     .field_name = name,
    246   };
    247   if (NULL == sig)
    248     return ps;
    249   return GNUNET_JSON_pack_unblinded_signature (name,
    250                                                sig->signature);
    251 }
    252 
    253 
    254 struct GNUNET_JSON_PackSpec
    255 TALER_JSON_pack_token_envelope (
    256   const char *name,
    257   const struct TALER_TokenEnvelope *envelope)
    258 {
    259   struct GNUNET_JSON_PackSpec ps = {
    260     .field_name = name,
    261   };
    262 
    263   if (NULL == envelope)
    264     return ps;
    265   return GNUNET_JSON_pack_blinded_message (name,
    266                                            envelope->blinded_pub);
    267 }
    268 
    269 
    270 struct GNUNET_JSON_PackSpec
    271 TALER_JSON_pack_exchange_blinding_values (
    272   const char *name,
    273   const struct TALER_ExchangeBlindingValues *ewv)
    274 {
    275   const struct GNUNET_CRYPTO_BlindingInputValues *biv;
    276   struct GNUNET_JSON_PackSpec ps = {
    277     .field_name = name,
    278   };
    279 
    280   if (NULL == ewv)
    281     return ps;
    282   biv = ewv->blinding_inputs;
    283   switch (biv->cipher)
    284   {
    285   case GNUNET_CRYPTO_BSA_INVALID:
    286     break;
    287   case GNUNET_CRYPTO_BSA_RSA:
    288     ps.object = GNUNET_JSON_PACK (
    289       GNUNET_JSON_pack_string ("cipher",
    290                                "RSA"));
    291     return ps;
    292   case GNUNET_CRYPTO_BSA_CS:
    293     ps.object = GNUNET_JSON_PACK (
    294       GNUNET_JSON_pack_string ("cipher",
    295                                "CS"),
    296       GNUNET_JSON_pack_data_varsize (
    297         "r_pub_0",
    298         &biv->details.cs_values.r_pub[0],
    299         sizeof(struct GNUNET_CRYPTO_CsRPublic)),
    300       GNUNET_JSON_pack_data_varsize (
    301         "r_pub_1",
    302         &biv->details.cs_values.r_pub[1],
    303         sizeof(struct GNUNET_CRYPTO_CsRPublic))
    304       );
    305     return ps;
    306   }
    307   GNUNET_assert (0);
    308   return ps;
    309 }
    310 
    311 
    312 struct GNUNET_JSON_PackSpec
    313 TALER_JSON_pack_blinding_prepare_response (
    314   const char *name,
    315   const struct TALER_BlindingPrepareResponse *bpr)
    316 {
    317   struct GNUNET_JSON_PackSpec ps = {
    318     .field_name = name,
    319   };
    320   if (NULL == bpr)
    321     return ps;
    322   switch (bpr->cipher)
    323   {
    324   case GNUNET_CRYPTO_BSA_INVALID:
    325     break;
    326   case GNUNET_CRYPTO_BSA_RSA:
    327     ps.object = GNUNET_JSON_PACK (
    328       GNUNET_JSON_pack_string ("cipher",
    329                                "RSA"));
    330     return ps;
    331   case GNUNET_CRYPTO_BSA_CS: {
    332       json_t *j_rpubs = json_array ();
    333 
    334       GNUNET_assert (NULL!=j_rpubs);
    335 
    336       for (size_t i = 0; i < bpr->num; i++)
    337       {
    338         struct GNUNET_CRYPTO_CSPublicRPairP *pair =
    339           &bpr->details.cs[i];
    340         json_t *j_pubs[2];
    341         json_t *j_pair;
    342 
    343         j_pair =  json_array ();
    344         GNUNET_assert (NULL != j_pair);
    345 
    346         j_pubs[0] = GNUNET_JSON_from_data (
    347           &pair->r_pub[0],
    348           sizeof(pair->r_pub[0]));
    349         GNUNET_assert (NULL != j_pubs[0]);
    350 
    351         j_pubs[1] = GNUNET_JSON_from_data (
    352           &pair->r_pub[1],
    353           sizeof(pair->r_pub[1]));
    354         GNUNET_assert (NULL != j_pubs[1]);
    355 
    356         GNUNET_assert (0 == json_array_append_new (j_pair, j_pubs[0]));
    357         GNUNET_assert (0 == json_array_append_new (j_pair, j_pubs[1]));
    358         GNUNET_assert (0 == json_array_append_new (j_rpubs, j_pair));
    359       }
    360 
    361       ps.object = GNUNET_JSON_PACK (
    362         GNUNET_JSON_pack_string ("cipher", "CS"),
    363         GNUNET_JSON_pack_array_steal ("r_pubs", j_rpubs));
    364       return ps;
    365     }
    366   }
    367   GNUNET_assert (0);
    368   return ps;
    369 }
    370 
    371 
    372 struct GNUNET_JSON_PackSpec
    373 TALER_JSON_pack_blinded_denom_sig (
    374   const char *name,
    375   const struct TALER_BlindedDenominationSignature *sig)
    376 {
    377   const struct GNUNET_CRYPTO_BlindedSignature *bs;
    378   struct GNUNET_JSON_PackSpec ps = {
    379     .field_name = name,
    380   };
    381 
    382   if (NULL == sig)
    383     return ps;
    384   bs = sig->blinded_sig;
    385   switch (bs->cipher)
    386   {
    387   case GNUNET_CRYPTO_BSA_INVALID:
    388     break;
    389   case GNUNET_CRYPTO_BSA_RSA:
    390     ps.object = GNUNET_JSON_PACK (
    391       GNUNET_JSON_pack_string ("cipher",
    392                                "RSA"),
    393       GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature",
    394                                       bs->details.blinded_rsa_signature));
    395     return ps;
    396   case GNUNET_CRYPTO_BSA_CS:
    397     ps.object = GNUNET_JSON_PACK (
    398       GNUNET_JSON_pack_string ("cipher",
    399                                "CS"),
    400       GNUNET_JSON_pack_uint64 ("b",
    401                                bs->details.blinded_cs_answer.b),
    402       GNUNET_JSON_pack_data_auto ("s",
    403                                   &bs->details.blinded_cs_answer.s_scalar));
    404     return ps;
    405   }
    406   GNUNET_assert (0);
    407   return ps;
    408 }
    409 
    410 
    411 struct GNUNET_JSON_PackSpec
    412 TALER_JSON_pack_blinded_planchet (
    413   const char *name,
    414   const struct TALER_BlindedPlanchet *blinded_planchet)
    415 {
    416   struct GNUNET_JSON_PackSpec ps = {
    417     .field_name = name,
    418   };
    419 
    420   if (NULL == blinded_planchet)
    421     return ps;
    422   return GNUNET_JSON_pack_blinded_message (name,
    423                                            blinded_planchet->blinded_message);
    424 }
    425 
    426 
    427 struct GNUNET_JSON_PackSpec
    428 TALER_JSON_pack_amount (const char *name,
    429                         const struct TALER_Amount *amount)
    430 {
    431   struct GNUNET_JSON_PackSpec ps = {
    432     .field_name = name,
    433     .object = (NULL != amount)
    434               ? TALER_JSON_from_amount (amount)
    435               : NULL
    436   };
    437 
    438   return ps;
    439 }
    440 
    441 
    442 struct GNUNET_JSON_PackSpec
    443 TALER_JSON_pack_amount_array (const char *name,
    444                               size_t len,
    445                               const struct TALER_Amount *amounts)
    446 {
    447   struct GNUNET_JSON_PackSpec ps = {
    448     .field_name = name,
    449   };
    450 
    451   if (NULL == amounts)
    452   {
    453     ps.object = json_null ();
    454     return ps;
    455   }
    456   {
    457     json_t *array = json_array ();
    458 
    459     GNUNET_assert (NULL != array);
    460     for (size_t i = 0; i<len; i++)
    461     {
    462       json_t *entry;
    463 
    464       char *amount_str = TALER_amount_to_string (&amounts[i]);
    465       GNUNET_assert (NULL != amount_str);
    466 
    467       entry = json_string (amount_str);
    468 
    469       GNUNET_free (amount_str);
    470       GNUNET_assert (NULL != entry);
    471       GNUNET_assert (0 ==
    472                      json_array_append_new (array,
    473                                             entry));
    474     }
    475     ps.object = array;
    476   }
    477   return ps;
    478 }
    479 
    480 
    481 struct GNUNET_JSON_PackSpec
    482 TALER_JSON_pack_full_payto (
    483   const char *name,
    484   const struct TALER_FullPayto payto)
    485 {
    486   return GNUNET_JSON_pack_string (name,
    487                                   payto.full_payto);
    488 }
    489 
    490 
    491 struct GNUNET_JSON_PackSpec
    492 TALER_JSON_pack_normalized_payto (
    493   const char *name,
    494   const struct TALER_NormalizedPayto payto)
    495 {
    496   return GNUNET_JSON_pack_string (name,
    497                                   payto.normalized_payto);
    498 }
    499 
    500 
    501 struct GNUNET_JSON_PackSpec
    502 TALER_JSON_pack_tuple (
    503   const char *name,
    504   const struct GNUNET_JSON_PackSpec packers[])
    505 {
    506   static size_t max_packers = 256;
    507   struct GNUNET_JSON_PackSpec ps = {
    508     .field_name = name,
    509   };
    510   size_t idx;
    511   json_t *j_array = json_array ();
    512 
    513   GNUNET_assert (NULL!=j_array);
    514 
    515   for (idx = 0; idx < max_packers; idx++)
    516   {
    517     if (NULL == packers[idx].object)
    518       break;
    519 
    520     GNUNET_assert (0 ==
    521                    json_array_append_new (j_array,
    522                                           packers[idx].object));
    523   }
    524 
    525   GNUNET_assert (idx != max_packers);
    526 
    527   ps.object = j_array;
    528   return ps;
    529 
    530 }
    531 
    532 
    533 struct GNUNET_JSON_PackSpec
    534 TALER_JSON_pack_array_of_data (
    535   const char *name,
    536   size_t num,
    537   const void *data,
    538   size_t size)
    539 {
    540   const char *blob = data;
    541   struct GNUNET_JSON_PackSpec ps = {
    542     .field_name = name,
    543   };
    544   json_t *j_array = json_array ();
    545 
    546   GNUNET_assert (NULL!=j_array);
    547   if (0 == num)
    548   {
    549     ps.object = j_array;
    550     return ps;
    551   }
    552   GNUNET_assert ((0 == size) ||
    553                  (num == 1) ||
    554                  (num * size > size));
    555 
    556   for (size_t idx = 0; idx < num; idx++)
    557   {
    558     GNUNET_assert (0 ==
    559                    json_array_append_new (
    560                      j_array,
    561                      GNUNET_JSON_from_data (
    562                        blob,
    563                        size)));
    564     blob += size;
    565   }
    566 
    567   ps.object = j_array;
    568   return ps;
    569 }
    570 
    571 
    572 /* End of json/json_pack.c */