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 (14319B)


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