LCOV - code coverage report
Current view: top level - json - json_pack.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 61.1 % 221 135
Test Date: 2026-01-04 22:17:00 Functions: 68.4 % 19 13

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

Generated by: LCOV version 2.0-1