LCOV - code coverage report
Current view: top level - util - exchange_signatures.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 73.8 % 351 259
Test Date: 2026-10-29 19:05:17 Functions: 73.8 % 42 31

            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 exchange_signatures.c
      18              :  * @brief Utility functions for Taler security module signatures
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #include "taler/taler_util.h"
      22              : #include "taler/taler_signatures.h"
      23              : 
      24              : 
      25              : GNUNET_NETWORK_STRUCT_BEGIN
      26              : 
      27              : /**
      28              :  * @brief Format used to generate the signature on a confirmation
      29              :  * from the exchange that a deposit request succeeded.
      30              :  */
      31              : struct TALER_DepositConfirmationPS
      32              : {
      33              :   /**
      34              :    * Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT.  Signed
      35              :    * by a `struct TALER_ExchangePublicKeyP` using EdDSA.
      36              :    */
      37              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
      38              : 
      39              :   /**
      40              :    * Hash over the contract for which this deposit is made.
      41              :    */
      42              :   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
      43              : 
      44              :   /**
      45              :    * Hash over the wiring information of the merchant.
      46              :    */
      47              :   struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
      48              : 
      49              :   /**
      50              :    * Hash over the optional policy extension of the deposit, 0 if there
      51              :    * was no policy.
      52              :    */
      53              :   struct TALER_ExtensionPolicyHashP h_policy GNUNET_PACKED;
      54              : 
      55              :   /**
      56              :    * Time when this confirmation was generated / when the exchange received
      57              :    * the deposit request.
      58              :    */
      59              :   struct GNUNET_TIME_TimestampNBO exchange_timestamp;
      60              : 
      61              :   /**
      62              :    * By when does the exchange expect to pay the merchant
      63              :    * (as per the merchant's request).
      64              :    */
      65              :   struct GNUNET_TIME_TimestampNBO wire_deadline;
      66              : 
      67              :   /**
      68              :    * How much time does the @e merchant have to issue a refund
      69              :    * request?  Zero if refunds are not allowed.  After this time, the
      70              :    * coin cannot be refunded.  Note that the wire transfer will not be
      71              :    * performed by the exchange until the refund deadline.  This value
      72              :    * is taken from the original deposit request.
      73              :    */
      74              :   struct GNUNET_TIME_TimestampNBO refund_deadline;
      75              : 
      76              :   /**
      77              :    * Amount to be deposited, excluding fee.  Calculated from the
      78              :    * amount with fee and the fee from the deposit request.
      79              :    */
      80              :   struct TALER_AmountNBO total_without_fee;
      81              : 
      82              :   /**
      83              :    * Hash over all of the coin signatures.
      84              :    */
      85              :   struct GNUNET_HashCode h_coin_sigs;
      86              : 
      87              :   /**
      88              :    * The Merchant's public key.  Allows the merchant to later refund
      89              :    * the transaction or to inquire about the wire transfer identifier.
      90              :    */
      91              :   struct TALER_MerchantPublicKeyP merchant_pub;
      92              : 
      93              : };
      94              : 
      95              : GNUNET_NETWORK_STRUCT_END
      96              : 
      97              : 
      98              : enum TALER_ErrorCode
      99           94 : TALER_exchange_online_deposit_confirmation_sign (
     100              :   TALER_ExchangeSignCallback scb,
     101              :   const struct TALER_PrivateContractHashP *h_contract_terms,
     102              :   const struct TALER_MerchantWireHashP *h_wire,
     103              :   const struct TALER_ExtensionPolicyHashP *h_policy,
     104              :   struct GNUNET_TIME_Timestamp exchange_timestamp,
     105              :   struct GNUNET_TIME_Timestamp wire_deadline,
     106              :   struct GNUNET_TIME_Timestamp refund_deadline,
     107              :   const struct TALER_Amount *total_without_fee,
     108              :   unsigned int num_coins,
     109              :   const struct TALER_CoinSpendSignatureP *coin_sigs[static num_coins],
     110              :   const struct TALER_MerchantPublicKeyP *merchant_pub,
     111              :   struct TALER_ExchangePublicKeyP *pub,
     112              :   struct TALER_ExchangeSignatureP *sig)
     113           94 : {
     114          188 :   struct TALER_DepositConfirmationPS dcs = {
     115           94 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
     116           94 :     .purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
     117              :     .h_contract_terms = *h_contract_terms,
     118              :     .h_wire = *h_wire,
     119           94 :     .exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
     120           94 :     .wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
     121           94 :     .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
     122              :     .merchant_pub = *merchant_pub,
     123              :     .h_policy = {{{0}}}
     124              :   };
     125              :   struct GNUNET_HashContext *hc;
     126              : 
     127           94 :   hc = GNUNET_CRYPTO_hash_context_start ();
     128          190 :   for (unsigned int i = 0; i<num_coins; i++)
     129           96 :     GNUNET_CRYPTO_hash_context_read (hc,
     130           96 :                                      coin_sigs[i],
     131              :                                      sizeof (*coin_sigs[i]));
     132           94 :   GNUNET_CRYPTO_hash_context_finish (hc,
     133              :                                      &dcs.h_coin_sigs);
     134           94 :   if (NULL != h_policy)
     135            0 :     dcs.h_policy = *h_policy;
     136           94 :   TALER_amount_hton (&dcs.total_without_fee,
     137              :                      total_without_fee);
     138           94 :   return scb (&dcs.purpose,
     139              :               pub,
     140              :               sig);
     141              : }
     142              : 
     143              : 
     144              : enum GNUNET_GenericReturnValue
     145          102 : TALER_exchange_online_deposit_confirmation_verify (
     146              :   const struct TALER_PrivateContractHashP *h_contract_terms,
     147              :   const struct TALER_MerchantWireHashP *h_wire,
     148              :   const struct TALER_ExtensionPolicyHashP *h_policy,
     149              :   struct GNUNET_TIME_Timestamp exchange_timestamp,
     150              :   struct GNUNET_TIME_Timestamp wire_deadline,
     151              :   struct GNUNET_TIME_Timestamp refund_deadline,
     152              :   const struct TALER_Amount *total_without_fee,
     153              :   unsigned int num_coins,
     154              :   const struct TALER_CoinSpendSignatureP *coin_sigs[static num_coins],
     155              :   const struct TALER_MerchantPublicKeyP *merchant_pub,
     156              :   const struct TALER_ExchangePublicKeyP *exchange_pub,
     157              :   const struct TALER_ExchangeSignatureP *exchange_sig)
     158          102 : {
     159          204 :   struct TALER_DepositConfirmationPS dcs = {
     160          102 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
     161          102 :     .purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
     162              :     .h_contract_terms = *h_contract_terms,
     163              :     .h_wire = *h_wire,
     164          102 :     .exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
     165          102 :     .wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
     166          102 :     .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
     167              :     .merchant_pub = *merchant_pub
     168              :   };
     169              :   struct GNUNET_HashContext *hc;
     170              : 
     171          102 :   hc = GNUNET_CRYPTO_hash_context_start ();
     172          206 :   for (unsigned int i = 0; i<num_coins; i++)
     173          104 :     GNUNET_CRYPTO_hash_context_read (hc,
     174          104 :                                      coin_sigs[i],
     175              :                                      sizeof (*coin_sigs[i]));
     176          102 :   GNUNET_CRYPTO_hash_context_finish (hc,
     177              :                                      &dcs.h_coin_sigs);
     178          102 :   if (NULL != h_policy)
     179          102 :     dcs.h_policy = *h_policy;
     180          102 :   TALER_amount_hton (&dcs.total_without_fee,
     181              :                      total_without_fee);
     182          102 :   if (GNUNET_OK !=
     183          102 :       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
     184              :                                   &dcs,
     185              :                                   &exchange_sig->eddsa_signature,
     186              :                                   &exchange_pub->eddsa_pub))
     187              :   {
     188            0 :     GNUNET_break_op (0);
     189            0 :     return GNUNET_SYSERR;
     190              :   }
     191          102 :   return GNUNET_OK;
     192              : }
     193              : 
     194              : 
     195              : GNUNET_NETWORK_STRUCT_BEGIN
     196              : 
     197              : /**
     198              :  * @brief Format used to generate the signature on a request to refund
     199              :  * a coin into the account of the customer.
     200              :  */
     201              : struct TALER_RefundConfirmationPS
     202              : {
     203              :   /**
     204              :    * Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND.
     205              :    */
     206              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     207              : 
     208              :   /**
     209              :    * Hash over the proposal data to identify the contract
     210              :    * which is being refunded.
     211              :    */
     212              :   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
     213              : 
     214              :   /**
     215              :    * The coin's public key.  This is the value that must have been
     216              :    * signed (blindly) by the Exchange.
     217              :    */
     218              :   struct TALER_CoinSpendPublicKeyP coin_pub;
     219              : 
     220              :   /**
     221              :    * The Merchant's public key.  Allows the merchant to later refund
     222              :    * the transaction or to inquire about the wire transfer identifier.
     223              :    */
     224              :   struct TALER_MerchantPublicKeyP merchant;
     225              : 
     226              :   /**
     227              :    * Merchant-generated transaction ID for the refund.
     228              :    */
     229              :   uint64_t rtransaction_id GNUNET_PACKED;
     230              : 
     231              :   /**
     232              :    * Amount to be refunded, including refund fee charged by the
     233              :    * exchange to the customer.
     234              :    */
     235              :   struct TALER_AmountNBO refund_amount;
     236              : };
     237              : 
     238              : GNUNET_NETWORK_STRUCT_END
     239              : 
     240              : 
     241              : enum TALER_ErrorCode
     242           10 : TALER_exchange_online_refund_confirmation_sign (
     243              :   TALER_ExchangeSignCallback scb,
     244              :   const struct TALER_PrivateContractHashP *h_contract_terms,
     245              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     246              :   const struct TALER_MerchantPublicKeyP *merchant,
     247              :   uint64_t rtransaction_id,
     248              :   const struct TALER_Amount *refund_amount,
     249              :   struct TALER_ExchangePublicKeyP *pub,
     250              :   struct TALER_ExchangeSignatureP *sig)
     251              : {
     252           20 :   struct TALER_RefundConfirmationPS rc = {
     253           10 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND),
     254           10 :     .purpose.size = htonl (sizeof (rc)),
     255              :     .h_contract_terms = *h_contract_terms,
     256              :     .coin_pub = *coin_pub,
     257              :     .merchant = *merchant,
     258           10 :     .rtransaction_id = GNUNET_htonll (rtransaction_id)
     259              :   };
     260              : 
     261           10 :   TALER_amount_hton (&rc.refund_amount,
     262              :                      refund_amount);
     263           10 :   return scb (&rc.purpose,
     264              :               pub,
     265              :               sig);
     266              : }
     267              : 
     268              : 
     269              : enum GNUNET_GenericReturnValue
     270           10 : TALER_exchange_online_refund_confirmation_verify (
     271              :   const struct TALER_PrivateContractHashP *h_contract_terms,
     272              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     273              :   const struct TALER_MerchantPublicKeyP *merchant,
     274              :   uint64_t rtransaction_id,
     275              :   const struct TALER_Amount *refund_amount,
     276              :   const struct TALER_ExchangePublicKeyP *pub,
     277              :   const struct TALER_ExchangeSignatureP *sig)
     278              : {
     279           20 :   struct TALER_RefundConfirmationPS rc = {
     280           10 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND),
     281           10 :     .purpose.size = htonl (sizeof (rc)),
     282              :     .h_contract_terms = *h_contract_terms,
     283              :     .coin_pub = *coin_pub,
     284              :     .merchant = *merchant,
     285           10 :     .rtransaction_id = GNUNET_htonll (rtransaction_id)
     286              :   };
     287              : 
     288           10 :   TALER_amount_hton (&rc.refund_amount,
     289              :                      refund_amount);
     290           10 :   if (GNUNET_OK !=
     291           10 :       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND,
     292              :                                   &rc,
     293              :                                   &sig->eddsa_signature,
     294              :                                   &pub->eddsa_pub))
     295              :   {
     296            0 :     GNUNET_break_op (0);
     297            0 :     return GNUNET_SYSERR;
     298              :   }
     299           10 :   return GNUNET_OK;
     300              : }
     301              : 
     302              : 
     303              : GNUNET_NETWORK_STRUCT_BEGIN
     304              : 
     305              : /**
     306              :  * @brief Format of the block signed by the Exchange in response to a successful
     307              :  * "/refresh/melt" request.  Hereby the exchange affirms that all of the
     308              :  * coins were successfully melted.  This also commits the exchange to a
     309              :  * particular index to not be revealed during the refresh.
     310              :  */
     311              : struct TALER_RefreshMeltConfirmationPS
     312              : {
     313              :   /**
     314              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT.   Signed
     315              :    * by a `struct TALER_ExchangePublicKeyP` using EdDSA.
     316              :    */
     317              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     318              : 
     319              :   /**
     320              :    * Commitment made in the /refresh/melt.
     321              :    */
     322              :   struct TALER_RefreshCommitmentP rc GNUNET_PACKED;
     323              : 
     324              :   /**
     325              :    * Index that the client will not have to reveal, in NBO.
     326              :    * Must be smaller than #TALER_CNC_KAPPA.
     327              :    */
     328              :   uint32_t noreveal_index GNUNET_PACKED;
     329              : 
     330              : };
     331              : 
     332              : GNUNET_NETWORK_STRUCT_END
     333              : 
     334              : 
     335              : enum TALER_ErrorCode
     336           40 : TALER_exchange_online_melt_confirmation_sign (
     337              :   TALER_ExchangeSignCallback scb,
     338              :   const struct TALER_RefreshCommitmentP *rc,
     339              :   uint32_t noreveal_index,
     340              :   struct TALER_ExchangePublicKeyP *pub,
     341              :   struct TALER_ExchangeSignatureP *sig)
     342              : {
     343           40 :   struct TALER_RefreshMeltConfirmationPS confirm = {
     344           40 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
     345           40 :     .purpose.size = htonl (sizeof (confirm)),
     346              :     .rc = *rc,
     347           40 :     .noreveal_index = htonl (noreveal_index)
     348              :   };
     349              : 
     350           40 :   return scb (&confirm.purpose,
     351              :               pub,
     352              :               sig);
     353              : }
     354              : 
     355              : 
     356              : enum GNUNET_GenericReturnValue
     357           40 : TALER_exchange_online_melt_confirmation_verify (
     358              :   const struct TALER_RefreshCommitmentP *rc,
     359              :   uint32_t noreveal_index,
     360              :   const struct TALER_ExchangePublicKeyP *exchange_pub,
     361              :   const struct TALER_ExchangeSignatureP *exchange_sig)
     362              : {
     363           40 :   struct TALER_RefreshMeltConfirmationPS confirm = {
     364           40 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
     365           40 :     .purpose.size = htonl (sizeof (confirm)),
     366              :     .rc = *rc,
     367           40 :     .noreveal_index = htonl (noreveal_index)
     368              :   };
     369              : 
     370              :   return
     371           40 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT,
     372              :                                 &confirm,
     373              :                                 &exchange_sig->eddsa_signature,
     374              :                                 &exchange_pub->eddsa_pub);
     375              : }
     376              : 
     377              : 
     378              : GNUNET_NETWORK_STRUCT_BEGIN
     379              : 
     380              : /**
     381              :  * @brief Format of the block signed by the Exchange in response to a
     382              :  * successful "/withdraw" request.
     383              :  * If age restriction is set, the exchange hereby also
     384              :  * affirms that the commitment along with the maximum age group and
     385              :  * the amount were accepted.  This also commits the exchange to a particular
     386              :  * index to not be revealed during the reveal.
     387              :  */
     388              : struct TALER_WithdrawConfirmationPS
     389              : {
     390              :   /**
     391              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW.   Signed by a
     392              :    * `struct TALER_ExchangePublicKeyP` using EdDSA.
     393              :    */
     394              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     395              : 
     396              :   /**
     397              :    * Commitment made in the /withdraw call.
     398              :    */
     399              :   struct TALER_HashBlindedPlanchetsP h_planchets GNUNET_PACKED;
     400              : 
     401              :   /**
     402              :    * If age restriction does not apply to this withdrawal,
     403              :    * (i.e. max_age was not set during the request)
     404              :    * MUST be 0xFFFFFFFF.
     405              :    * Otherwise (i.e. age restriction applies):
     406              :    * index that the client will not have to reveal, in NBO,
     407              :    * MUST be smaller than #TALER_CNC_KAPPA.
     408              :    */
     409              :   uint32_t noreveal_index GNUNET_PACKED;
     410              : 
     411              : };
     412              : 
     413              : GNUNET_NETWORK_STRUCT_END
     414              : 
     415              : enum TALER_ErrorCode
     416            3 : TALER_exchange_online_withdraw_age_confirmation_sign (
     417              :   TALER_ExchangeSignCallback scb,
     418              :   const struct TALER_HashBlindedPlanchetsP *h_planchets,
     419              :   uint32_t noreveal_index,
     420              :   struct TALER_ExchangePublicKeyP *pub,
     421              :   struct TALER_ExchangeSignatureP *sig)
     422              : {
     423              : 
     424            3 :   struct TALER_WithdrawConfirmationPS confirm = {
     425            3 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW),
     426            3 :     .purpose.size = htonl (sizeof (confirm)),
     427              :     .h_planchets = *h_planchets,
     428            3 :     .noreveal_index = htonl (noreveal_index)
     429              :   };
     430              : 
     431            3 :   return scb (&confirm.purpose,
     432              :               pub,
     433              :               sig);
     434              : }
     435              : 
     436              : 
     437              : enum TALER_ErrorCode
     438            0 : TALER_exchange_online_withdraw_confirmation_sign (
     439              :   TALER_ExchangeSignCallback scb,
     440              :   const struct TALER_HashBlindedPlanchetsP *h_planchets,
     441              :   struct TALER_ExchangePublicKeyP *pub,
     442              :   struct TALER_ExchangeSignatureP *sig)
     443              : {
     444              : 
     445            0 :   struct TALER_WithdrawConfirmationPS confirm = {
     446            0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW),
     447            0 :     .purpose.size = htonl (sizeof (confirm)),
     448              :     .h_planchets = *h_planchets,
     449            0 :     .noreveal_index = htonl (0xFFFFFFFF)
     450              :   };
     451              : 
     452            0 :   return scb (&confirm.purpose,
     453              :               pub,
     454              :               sig);
     455              : }
     456              : 
     457              : 
     458              : enum GNUNET_GenericReturnValue
     459            3 : TALER_exchange_online_withdraw_age_confirmation_verify (
     460              :   const struct TALER_HashBlindedPlanchetsP *h_planchets,
     461              :   uint32_t noreveal_index,
     462              :   const struct TALER_ExchangePublicKeyP *exchange_pub,
     463              :   const struct TALER_ExchangeSignatureP *exchange_sig)
     464              : {
     465            3 :   struct TALER_WithdrawConfirmationPS confirm = {
     466            3 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW),
     467            3 :     .purpose.size = htonl (sizeof (confirm)),
     468              :     .h_planchets = *h_planchets,
     469            3 :     .noreveal_index = htonl (noreveal_index)
     470              :   };
     471              : 
     472            3 :   if (GNUNET_OK !=
     473            3 :       GNUNET_CRYPTO_eddsa_verify (
     474              :         TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW,
     475              :         &confirm,
     476              :         &exchange_sig->eddsa_signature,
     477              :         &exchange_pub->eddsa_pub))
     478              :   {
     479            0 :     GNUNET_break_op (0);
     480            0 :     return GNUNET_SYSERR;
     481              :   }
     482            3 :   return GNUNET_OK;
     483              : }
     484              : 
     485              : 
     486              : enum GNUNET_GenericReturnValue
     487            0 : TALER_exchange_online_withdraw_confirmation_verify (
     488              :   const struct TALER_HashBlindedPlanchetsP *h_planchets,
     489              :   const struct TALER_ExchangePublicKeyP *exchange_pub,
     490              :   const struct TALER_ExchangeSignatureP *exchange_sig)
     491              : {
     492            0 :   struct TALER_WithdrawConfirmationPS confirm = {
     493            0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW),
     494            0 :     .purpose.size = htonl (sizeof (confirm)),
     495              :     .h_planchets = *h_planchets,
     496            0 :     .noreveal_index = htonl (0xFFFFFFFF)
     497              :   };
     498              : 
     499            0 :   if (GNUNET_OK !=
     500            0 :       GNUNET_CRYPTO_eddsa_verify (
     501              :         TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW,
     502              :         &confirm,
     503              :         &exchange_sig->eddsa_signature,
     504              :         &exchange_pub->eddsa_pub))
     505              :   {
     506            0 :     GNUNET_break_op (0);
     507            0 :     return GNUNET_SYSERR;
     508              :   }
     509            0 :   return GNUNET_OK;
     510              : }
     511              : 
     512              : 
     513              : GNUNET_NETWORK_STRUCT_BEGIN
     514              : 
     515              : /**
     516              :  * @brief Signature made by the exchange over the full set of keys, used
     517              :  * to detect cheating exchanges that give out different sets to
     518              :  * different users.
     519              :  */
     520              : struct TALER_ExchangeKeySetPS
     521              : {
     522              : 
     523              :   /**
     524              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_KEY_SET.   Signed
     525              :    * by a `struct TALER_ExchangePublicKeyP` using EdDSA.
     526              :    */
     527              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     528              : 
     529              :   /**
     530              :    * Time of the key set issue.
     531              :    */
     532              :   struct GNUNET_TIME_TimestampNBO list_issue_date;
     533              : 
     534              :   /**
     535              :    * Hash over the various denomination signing keys returned.
     536              :    */
     537              :   struct GNUNET_HashCode hc GNUNET_PACKED;
     538              : };
     539              : 
     540              : GNUNET_NETWORK_STRUCT_END
     541              : 
     542              : 
     543              : enum TALER_ErrorCode
     544          242 : TALER_exchange_online_key_set_sign (
     545              :   TALER_ExchangeSignCallback2 scb,
     546              :   void *cls,
     547              :   struct GNUNET_TIME_Timestamp timestamp,
     548              :   const struct GNUNET_HashCode *hc,
     549              :   struct TALER_ExchangePublicKeyP *pub,
     550              :   struct TALER_ExchangeSignatureP *sig)
     551              : {
     552          484 :   struct TALER_ExchangeKeySetPS ks = {
     553          242 :     .purpose.size = htonl (sizeof (ks)),
     554          242 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET),
     555          242 :     .list_issue_date = GNUNET_TIME_timestamp_hton (timestamp),
     556              :     .hc = *hc
     557              :   };
     558              : 
     559          242 :   return scb (cls,
     560              :               &ks.purpose,
     561              :               pub,
     562              :               sig);
     563              : }
     564              : 
     565              : 
     566              : enum GNUNET_GenericReturnValue
     567           42 : TALER_exchange_online_key_set_verify (
     568              :   struct GNUNET_TIME_Timestamp timestamp,
     569              :   const struct GNUNET_HashCode *hc,
     570              :   const struct TALER_ExchangePublicKeyP *pub,
     571              :   const struct TALER_ExchangeSignatureP *sig)
     572              : {
     573           84 :   struct TALER_ExchangeKeySetPS ks = {
     574           42 :     .purpose.size = htonl (sizeof (ks)),
     575           42 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET),
     576           42 :     .list_issue_date = GNUNET_TIME_timestamp_hton (timestamp),
     577              :     .hc = *hc
     578              :   };
     579              : 
     580              :   return
     581           42 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_KEY_SET,
     582              :                                 &ks,
     583              :                                 &sig->eddsa_signature,
     584              :                                 &pub->eddsa_pub);
     585              : }
     586              : 
     587              : 
     588              : GNUNET_NETWORK_STRUCT_BEGIN
     589              : 
     590              : /**
     591              :  * @brief Format internally used for packing the detailed information
     592              :  * to generate the signature for /track/transfer signatures.
     593              :  */
     594              : struct TALER_WireDepositDetailP
     595              : {
     596              : 
     597              :   /**
     598              :    * Hash of the contract
     599              :    */
     600              :   struct TALER_PrivateContractHashP h_contract_terms;
     601              : 
     602              :   /**
     603              :    * Time when the wire transfer was performed by the exchange.
     604              :    */
     605              :   struct GNUNET_TIME_TimestampNBO execution_time;
     606              : 
     607              :   /**
     608              :    * Coin's public key.
     609              :    */
     610              :   struct TALER_CoinSpendPublicKeyP coin_pub;
     611              : 
     612              :   /**
     613              :    * Total value of the coin.
     614              :    */
     615              :   struct TALER_AmountNBO deposit_value;
     616              : 
     617              :   /**
     618              :    * Fees charged by the exchange for the deposit.
     619              :    */
     620              :   struct TALER_AmountNBO deposit_fee;
     621              : 
     622              : };
     623              : 
     624              : GNUNET_NETWORK_STRUCT_END
     625              : 
     626              : 
     627              : void
     628           34 : TALER_exchange_online_wire_deposit_append (
     629              :   struct GNUNET_HashContext *hash_context,
     630              :   const struct TALER_PrivateContractHashP *h_contract_terms,
     631              :   struct GNUNET_TIME_Timestamp execution_time,
     632              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     633              :   const struct TALER_Amount *deposit_value,
     634              :   const struct TALER_Amount *deposit_fee)
     635              : {
     636           68 :   struct TALER_WireDepositDetailP dd = {
     637              :     .h_contract_terms = *h_contract_terms,
     638           34 :     .execution_time = GNUNET_TIME_timestamp_hton (execution_time),
     639              :     .coin_pub = *coin_pub
     640              :   };
     641           34 :   TALER_amount_hton (&dd.deposit_value,
     642              :                      deposit_value);
     643           34 :   TALER_amount_hton (&dd.deposit_fee,
     644              :                      deposit_fee);
     645           34 :   GNUNET_CRYPTO_hash_context_read (hash_context,
     646              :                                    &dd,
     647              :                                    sizeof (dd));
     648           34 : }
     649              : 
     650              : 
     651              : GNUNET_NETWORK_STRUCT_BEGIN
     652              : 
     653              : /**
     654              :  * @brief Format used to generate the signature for /wire/deposit
     655              :  * replies.
     656              :  */
     657              : struct TALER_WireDepositDataPS
     658              : {
     659              :   /**
     660              :    * Purpose header for the signature over the contract with
     661              :    * purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT.
     662              :    */
     663              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     664              : 
     665              :   /**
     666              :    * Total amount that was transferred.
     667              :    */
     668              :   struct TALER_AmountNBO total;
     669              : 
     670              :   /**
     671              :    * Wire fee that was charged.
     672              :    */
     673              :   struct TALER_AmountNBO wire_fee;
     674              : 
     675              :   /**
     676              :    * Public key of the merchant (for all aggregated transactions).
     677              :    */
     678              :   struct TALER_MerchantPublicKeyP merchant_pub;
     679              : 
     680              :   /**
     681              :    * Hash of bank account of the merchant.
     682              :    */
     683              :   struct TALER_FullPaytoHashP h_payto;
     684              : 
     685              :   /**
     686              :    * Hash of the individual deposits that were aggregated,
     687              :    * each in the format of a `struct TALER_WireDepositDetailP`.
     688              :    */
     689              :   struct GNUNET_HashCode h_details;
     690              : 
     691              : };
     692              : 
     693              : GNUNET_NETWORK_STRUCT_END
     694              : 
     695              : 
     696              : enum TALER_ErrorCode
     697            4 : TALER_exchange_online_wire_deposit_sign (
     698              :   TALER_ExchangeSignCallback scb,
     699              :   const struct TALER_Amount *total,
     700              :   const struct TALER_Amount *wire_fee,
     701              :   const struct TALER_MerchantPublicKeyP *merchant_pub,
     702              :   const struct TALER_FullPayto payto,
     703              :   const struct GNUNET_HashCode *h_details,
     704              :   struct TALER_ExchangePublicKeyP *pub,
     705              :   struct TALER_ExchangeSignatureP *sig)
     706              : {
     707            4 :   struct TALER_WireDepositDataPS wdp = {
     708            4 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
     709            4 :     .purpose.size = htonl (sizeof (wdp)),
     710              :     .merchant_pub = *merchant_pub,
     711              :     .h_details = *h_details
     712              :   };
     713              : 
     714            4 :   TALER_amount_hton (&wdp.total,
     715              :                      total);
     716            4 :   TALER_amount_hton (&wdp.wire_fee,
     717              :                      wire_fee);
     718            4 :   TALER_full_payto_hash (payto,
     719              :                          &wdp.h_payto);
     720            4 :   return scb (&wdp.purpose,
     721              :               pub,
     722              :               sig);
     723              : }
     724              : 
     725              : 
     726              : enum GNUNET_GenericReturnValue
     727            4 : TALER_exchange_online_wire_deposit_verify (
     728              :   const struct TALER_Amount *total,
     729              :   const struct TALER_Amount *wire_fee,
     730              :   const struct TALER_MerchantPublicKeyP *merchant_pub,
     731              :   const struct TALER_FullPaytoHashP *h_payto,
     732              :   const struct GNUNET_HashCode *h_details,
     733              :   const struct TALER_ExchangePublicKeyP *pub,
     734              :   const struct TALER_ExchangeSignatureP *sig)
     735              : {
     736            4 :   struct TALER_WireDepositDataPS wdp = {
     737            4 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
     738            4 :     .purpose.size = htonl (sizeof (wdp)),
     739              :     .merchant_pub = *merchant_pub,
     740              :     .h_details = *h_details,
     741              :     .h_payto = *h_payto
     742              :   };
     743              : 
     744            4 :   TALER_amount_hton (&wdp.total,
     745              :                      total);
     746            4 :   TALER_amount_hton (&wdp.wire_fee,
     747              :                      wire_fee);
     748            4 :   return GNUNET_CRYPTO_eddsa_verify (
     749              :     TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT,
     750              :     &wdp,
     751              :     &sig->eddsa_signature,
     752              :     &pub->eddsa_pub);
     753              : }
     754              : 
     755              : 
     756              : GNUNET_NETWORK_STRUCT_BEGIN
     757              : 
     758              : /**
     759              :  * Details affirmed by the exchange about a wire transfer the exchange
     760              :  * claims to have done with respect to a deposit operation.
     761              :  */
     762              : struct TALER_ConfirmWirePS
     763              : {
     764              :   /**
     765              :    * Purpose header for the signature over the contract with
     766              :    * purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE.
     767              :    */
     768              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     769              : 
     770              :   /**
     771              :    * Hash over the wiring information of the merchant.
     772              :    */
     773              :   struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
     774              : 
     775              :   /**
     776              :    * Hash over the contract for which this deposit is made.
     777              :    */
     778              :   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
     779              : 
     780              :   /**
     781              :    * Raw value (binary encoding) of the wire transfer subject.
     782              :    */
     783              :   struct TALER_WireTransferIdentifierRawP wtid;
     784              : 
     785              :   /**
     786              :    * The coin's public key.  This is the value that must have been
     787              :    * signed (blindly) by the Exchange.
     788              :    */
     789              :   struct TALER_CoinSpendPublicKeyP coin_pub;
     790              : 
     791              :   /**
     792              :    * When did the exchange execute this transfer? Note that the
     793              :    * timestamp may not be exactly the same on the wire, i.e.
     794              :    * because the wire has a different timezone or resolution.
     795              :    */
     796              :   struct GNUNET_TIME_TimestampNBO execution_time;
     797              : 
     798              :   /**
     799              :    * The contribution of @e coin_pub to the total transfer volume.
     800              :    * This is the value of the deposit minus the fee.
     801              :    */
     802              :   struct TALER_AmountNBO coin_contribution;
     803              : 
     804              : };
     805              : 
     806              : GNUNET_NETWORK_STRUCT_END
     807              : 
     808              : 
     809              : enum TALER_ErrorCode
     810            2 : TALER_exchange_online_confirm_wire_sign (
     811              :   TALER_ExchangeSignCallback scb,
     812              :   const struct TALER_MerchantWireHashP *h_wire,
     813              :   const struct TALER_PrivateContractHashP *h_contract_terms,
     814              :   const struct TALER_WireTransferIdentifierRawP *wtid,
     815              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     816              :   struct GNUNET_TIME_Timestamp execution_time,
     817              :   const struct TALER_Amount *coin_contribution,
     818              :   struct TALER_ExchangePublicKeyP *pub,
     819              :   struct TALER_ExchangeSignatureP *sig)
     820              : 
     821              : {
     822            2 :   struct TALER_ConfirmWirePS cw = {
     823            2 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE),
     824            2 :     .purpose.size = htonl (sizeof (cw)),
     825              :     .h_wire = *h_wire,
     826              :     .h_contract_terms = *h_contract_terms,
     827              :     .wtid = *wtid,
     828              :     .coin_pub = *coin_pub,
     829            2 :     .execution_time = GNUNET_TIME_timestamp_hton (execution_time)
     830              :   };
     831              : 
     832            2 :   TALER_amount_hton (&cw.coin_contribution,
     833              :                      coin_contribution);
     834            2 :   return scb (&cw.purpose,
     835              :               pub,
     836              :               sig);
     837              : }
     838              : 
     839              : 
     840              : enum GNUNET_GenericReturnValue
     841            2 : TALER_exchange_online_confirm_wire_verify (
     842              :   const struct TALER_MerchantWireHashP *h_wire,
     843              :   const struct TALER_PrivateContractHashP *h_contract_terms,
     844              :   const struct TALER_WireTransferIdentifierRawP *wtid,
     845              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     846              :   struct GNUNET_TIME_Timestamp execution_time,
     847              :   const struct TALER_Amount *coin_contribution,
     848              :   const struct TALER_ExchangePublicKeyP *pub,
     849              :   const struct TALER_ExchangeSignatureP *sig)
     850              : {
     851            2 :   struct TALER_ConfirmWirePS cw = {
     852            2 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE),
     853            2 :     .purpose.size = htonl (sizeof (cw)),
     854              :     .h_wire = *h_wire,
     855              :     .h_contract_terms = *h_contract_terms,
     856              :     .wtid = *wtid,
     857              :     .coin_pub = *coin_pub,
     858            2 :     .execution_time = GNUNET_TIME_timestamp_hton (execution_time)
     859              :   };
     860              : 
     861            2 :   TALER_amount_hton (&cw.coin_contribution,
     862              :                      coin_contribution);
     863              :   return
     864            2 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE,
     865              :                                 &cw,
     866              :                                 &sig->eddsa_signature,
     867              :                                 &pub->eddsa_pub);
     868              : }
     869              : 
     870              : 
     871              : GNUNET_NETWORK_STRUCT_BEGIN
     872              : 
     873              : /**
     874              :  * Response by which the exchange affirms that it will
     875              :  * refund a coin as part of the emergency /recoup
     876              :  * protocol.  The recoup will go back to the bank
     877              :  * account that created the reserve.
     878              :  */
     879              : struct TALER_RecoupConfirmationPS
     880              : {
     881              : 
     882              :   /**
     883              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP
     884              :    */
     885              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     886              : 
     887              :   /**
     888              :    * When did the exchange receive the recoup request?
     889              :    * Indirectly determines when the wire transfer is (likely)
     890              :    * to happen.
     891              :    */
     892              :   struct GNUNET_TIME_TimestampNBO timestamp;
     893              : 
     894              :   /**
     895              :    * How much of the coin's value will the exchange transfer?
     896              :    * (Needed in case the coin was partially spent.)
     897              :    */
     898              :   struct TALER_AmountNBO recoup_amount;
     899              : 
     900              :   /**
     901              :    * Public key of the coin.
     902              :    */
     903              :   struct TALER_CoinSpendPublicKeyP coin_pub;
     904              : 
     905              :   /**
     906              :    * Public key of the reserve that will receive the recoup.
     907              :    */
     908              :   struct TALER_ReservePublicKeyP reserve_pub;
     909              : };
     910              : 
     911              : GNUNET_NETWORK_STRUCT_END
     912              : 
     913              : 
     914              : enum TALER_ErrorCode
     915            8 : TALER_exchange_online_confirm_recoup_sign (
     916              :   TALER_ExchangeSignCallback scb,
     917              :   struct GNUNET_TIME_Timestamp timestamp,
     918              :   const struct TALER_Amount *recoup_amount,
     919              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     920              :   const struct TALER_ReservePublicKeyP *reserve_pub,
     921              :   struct TALER_ExchangePublicKeyP *pub,
     922              :   struct TALER_ExchangeSignatureP *sig)
     923              : {
     924           16 :   struct TALER_RecoupConfirmationPS pc = {
     925            8 :     .purpose.size = htonl (sizeof (pc)),
     926            8 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
     927            8 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
     928              :     .coin_pub = *coin_pub,
     929              :     .reserve_pub = *reserve_pub
     930              :   };
     931              : 
     932            8 :   TALER_amount_hton (&pc.recoup_amount,
     933              :                      recoup_amount);
     934            8 :   return scb (&pc.purpose,
     935              :               pub,
     936              :               sig);
     937              : }
     938              : 
     939              : 
     940              : enum GNUNET_GenericReturnValue
     941            8 : TALER_exchange_online_confirm_recoup_verify (
     942              :   struct GNUNET_TIME_Timestamp timestamp,
     943              :   const struct TALER_Amount *recoup_amount,
     944              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     945              :   const struct TALER_ReservePublicKeyP *reserve_pub,
     946              :   const struct TALER_ExchangePublicKeyP *pub,
     947              :   const struct TALER_ExchangeSignatureP *sig)
     948              : {
     949           16 :   struct TALER_RecoupConfirmationPS pc = {
     950            8 :     .purpose.size = htonl (sizeof (pc)),
     951            8 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
     952            8 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
     953              :     .coin_pub = *coin_pub,
     954              :     .reserve_pub = *reserve_pub
     955              :   };
     956              : 
     957            8 :   TALER_amount_hton (&pc.recoup_amount,
     958              :                      recoup_amount);
     959              :   return
     960            8 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP,
     961              :                                 &pc,
     962              :                                 &sig->eddsa_signature,
     963              :                                 &pub->eddsa_pub);
     964              : }
     965              : 
     966              : 
     967              : GNUNET_NETWORK_STRUCT_BEGIN
     968              : 
     969              : /**
     970              :  * Response by which the exchange affirms that it will refund a refreshed coin
     971              :  * as part of the emergency /recoup protocol.  The recoup will go back to the
     972              :  * old coin's balance.
     973              :  */
     974              : struct TALER_RecoupRefreshConfirmationPS
     975              : {
     976              : 
     977              :   /**
     978              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH
     979              :    */
     980              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     981              : 
     982              :   /**
     983              :    * When did the exchange receive the recoup request?
     984              :    * Indirectly determines when the wire transfer is (likely)
     985              :    * to happen.
     986              :    */
     987              :   struct GNUNET_TIME_TimestampNBO timestamp;
     988              : 
     989              :   /**
     990              :    * How much of the coin's value will the exchange transfer?
     991              :    * (Needed in case the coin was partially spent.)
     992              :    */
     993              :   struct TALER_AmountNBO recoup_amount;
     994              : 
     995              :   /**
     996              :    * Public key of the refreshed coin.
     997              :    */
     998              :   struct TALER_CoinSpendPublicKeyP coin_pub;
     999              : 
    1000              :   /**
    1001              :    * Public key of the old coin that will receive the recoup.
    1002              :    */
    1003              :   struct TALER_CoinSpendPublicKeyP old_coin_pub;
    1004              : };
    1005              : 
    1006              : GNUNET_NETWORK_STRUCT_END
    1007              : 
    1008              : 
    1009              : enum TALER_ErrorCode
    1010            0 : TALER_exchange_online_confirm_recoup_refresh_sign (
    1011              :   TALER_ExchangeSignCallback scb,
    1012              :   struct GNUNET_TIME_Timestamp timestamp,
    1013              :   const struct TALER_Amount *recoup_amount,
    1014              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    1015              :   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
    1016              :   struct TALER_ExchangePublicKeyP *pub,
    1017              :   struct TALER_ExchangeSignatureP *sig)
    1018              : {
    1019            0 :   struct TALER_RecoupRefreshConfirmationPS pc = {
    1020            0 :     .purpose.purpose = htonl (
    1021              :       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
    1022            0 :     .purpose.size = htonl (sizeof (pc)),
    1023            0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1024              :     .coin_pub = *coin_pub,
    1025              :     .old_coin_pub = *old_coin_pub
    1026              :   };
    1027              : 
    1028            0 :   TALER_amount_hton (&pc.recoup_amount,
    1029              :                      recoup_amount);
    1030            0 :   return scb (&pc.purpose,
    1031              :               pub,
    1032              :               sig);
    1033              : }
    1034              : 
    1035              : 
    1036              : enum GNUNET_GenericReturnValue
    1037            0 : TALER_exchange_online_confirm_recoup_refresh_verify (
    1038              :   struct GNUNET_TIME_Timestamp timestamp,
    1039              :   const struct TALER_Amount *recoup_amount,
    1040              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    1041              :   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
    1042              :   const struct TALER_ExchangePublicKeyP *pub,
    1043              :   const struct TALER_ExchangeSignatureP *sig)
    1044              : {
    1045            0 :   struct TALER_RecoupRefreshConfirmationPS pc = {
    1046            0 :     .purpose.purpose = htonl (
    1047              :       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
    1048            0 :     .purpose.size = htonl (sizeof (pc)),
    1049            0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1050              :     .coin_pub = *coin_pub,
    1051              :     .old_coin_pub = *old_coin_pub
    1052              :   };
    1053              : 
    1054            0 :   TALER_amount_hton (&pc.recoup_amount,
    1055              :                      recoup_amount);
    1056              : 
    1057              :   return
    1058            0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH,
    1059              :                                 &pc,
    1060              :                                 &sig->eddsa_signature,
    1061              :                                 &pub->eddsa_pub);
    1062              : }
    1063              : 
    1064              : 
    1065              : void
    1066           74 : TALER_recoup_batch_hash (
    1067              :   size_t num_recoups,
    1068              :   const struct TALER_RecoupedCoin recoups[static num_recoups],
    1069              :   struct GNUNET_HashCode *h_recoups)
    1070           74 : {
    1071              :   struct GNUNET_HashContext *hc;
    1072              : 
    1073           74 :   hc = GNUNET_CRYPTO_hash_context_start ();
    1074          164 :   for (size_t i = 0; i < num_recoups; i++)
    1075              :   {
    1076              :     struct TALER_AmountNBO amount_nbo;
    1077              : 
    1078           90 :     GNUNET_CRYPTO_hash_context_read (hc,
    1079           90 :                                      &recoups[i].coin_pub,
    1080              :                                      sizeof (recoups[i].coin_pub));
    1081           90 :     TALER_amount_hton (&amount_nbo,
    1082           90 :                        &recoups[i].amount);
    1083           90 :     GNUNET_CRYPTO_hash_context_read (hc,
    1084              :                                      &amount_nbo,
    1085              :                                      sizeof (amount_nbo));
    1086              :   }
    1087           74 :   GNUNET_CRYPTO_hash_context_finish (hc,
    1088              :                                      h_recoups);
    1089           74 : }
    1090              : 
    1091              : 
    1092              : GNUNET_NETWORK_STRUCT_BEGIN
    1093              : 
    1094              : /**
    1095              :  * Response by which the exchange affirms that it credited a reserve
    1096              :  * for all coins recouped in one /recoup-withdraw request.
    1097              :  */
    1098              : struct TALER_RecoupWithdrawBatchConfirmationPS
    1099              : {
    1100              : 
    1101              :   /**
    1102              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_WITHDRAW_BATCH
    1103              :    */
    1104              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    1105              : 
    1106              :   /**
    1107              :    * When did the exchange accept the recoup request?
    1108              :    */
    1109              :   struct GNUNET_TIME_TimestampNBO timestamp;
    1110              : 
    1111              :   /**
    1112              :    * Public key of the reserve that was credited.
    1113              :    */
    1114              :   struct TALER_ReservePublicKeyP reserve_pub;
    1115              : 
    1116              :   /**
    1117              :    * Commitment of the withdraw operation the coins originated from.
    1118              :    */
    1119              :   struct TALER_HashBlindedPlanchetsP planchets_h;
    1120              : 
    1121              :   /**
    1122              :    * Total amount credited to the reserve.
    1123              :    */
    1124              :   struct TALER_AmountNBO total_amount;
    1125              : 
    1126              :   /**
    1127              :    * Hash over the recouped coins and their amounts,
    1128              :    * see #TALER_recoup_batch_hash().
    1129              :    */
    1130              :   struct GNUNET_HashCode h_recoups;
    1131              : };
    1132              : 
    1133              : GNUNET_NETWORK_STRUCT_END
    1134              : 
    1135              : 
    1136              : enum TALER_ErrorCode
    1137           19 : TALER_exchange_online_confirm_recoup_withdraw_batch_sign (
    1138              :   TALER_ExchangeSignCallback scb,
    1139              :   struct GNUNET_TIME_Timestamp timestamp,
    1140              :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1141              :   const struct TALER_HashBlindedPlanchetsP *planchets_h,
    1142              :   const struct TALER_Amount *total_amount,
    1143              :   const struct GNUNET_HashCode *h_recoups,
    1144              :   struct TALER_ExchangePublicKeyP *pub,
    1145              :   struct TALER_ExchangeSignatureP *sig)
    1146              : {
    1147           38 :   struct TALER_RecoupWithdrawBatchConfirmationPS pc = {
    1148           19 :     .purpose.size = htonl (sizeof (pc)),
    1149           19 :     .purpose.purpose = htonl (
    1150              :       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_WITHDRAW_BATCH),
    1151           19 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1152              :     .reserve_pub = *reserve_pub,
    1153              :     .planchets_h = *planchets_h,
    1154              :     .h_recoups = *h_recoups
    1155              :   };
    1156              : 
    1157           19 :   TALER_amount_hton (&pc.total_amount,
    1158              :                      total_amount);
    1159           19 :   return scb (&pc.purpose,
    1160              :               pub,
    1161              :               sig);
    1162              : }
    1163              : 
    1164              : 
    1165              : enum GNUNET_GenericReturnValue
    1166           21 : TALER_exchange_online_confirm_recoup_withdraw_batch_verify (
    1167              :   struct GNUNET_TIME_Timestamp timestamp,
    1168              :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1169              :   const struct TALER_HashBlindedPlanchetsP *planchets_h,
    1170              :   const struct TALER_Amount *total_amount,
    1171              :   const struct GNUNET_HashCode *h_recoups,
    1172              :   const struct TALER_ExchangePublicKeyP *pub,
    1173              :   const struct TALER_ExchangeSignatureP *sig)
    1174              : {
    1175           42 :   struct TALER_RecoupWithdrawBatchConfirmationPS pc = {
    1176           21 :     .purpose.size = htonl (sizeof (pc)),
    1177           21 :     .purpose.purpose = htonl (
    1178              :       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_WITHDRAW_BATCH),
    1179           21 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1180              :     .reserve_pub = *reserve_pub,
    1181              :     .planchets_h = *planchets_h,
    1182              :     .h_recoups = *h_recoups
    1183              :   };
    1184              : 
    1185           21 :   TALER_amount_hton (&pc.total_amount,
    1186              :                      total_amount);
    1187              :   return
    1188           21 :     GNUNET_CRYPTO_eddsa_verify (
    1189              :     TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_WITHDRAW_BATCH,
    1190              :     &pc,
    1191              :     &sig->eddsa_signature,
    1192              :     &pub->eddsa_pub);
    1193              : }
    1194              : 
    1195              : 
    1196              : GNUNET_NETWORK_STRUCT_BEGIN
    1197              : 
    1198              : /**
    1199              :  * Response by which the exchange affirms that it credited an old coin
    1200              :  * for all coins recouped in one /recoup-refresh request.
    1201              :  */
    1202              : struct TALER_RecoupRefreshBatchConfirmationPS
    1203              : {
    1204              : 
    1205              :   /**
    1206              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH_BATCH
    1207              :    */
    1208              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    1209              : 
    1210              :   /**
    1211              :    * When did the exchange accept the recoup request?
    1212              :    */
    1213              :   struct GNUNET_TIME_TimestampNBO timestamp;
    1214              : 
    1215              :   /**
    1216              :    * Public key of the old coin that was credited.
    1217              :    */
    1218              :   struct TALER_CoinSpendPublicKeyP old_coin_pub;
    1219              : 
    1220              :   /**
    1221              :    * Commitment of the refresh operation the coins originated from.
    1222              :    */
    1223              :   struct TALER_RefreshCommitmentP rc;
    1224              : 
    1225              :   /**
    1226              :    * Total amount credited to the old coin.
    1227              :    */
    1228              :   struct TALER_AmountNBO total_amount;
    1229              : 
    1230              :   /**
    1231              :    * Hash over the recouped coins and their amounts,
    1232              :    * see #TALER_recoup_batch_hash().
    1233              :    */
    1234              :   struct GNUNET_HashCode h_recoups;
    1235              : };
    1236              : 
    1237              : GNUNET_NETWORK_STRUCT_END
    1238              : 
    1239              : 
    1240              : enum TALER_ErrorCode
    1241           19 : TALER_exchange_online_confirm_recoup_refresh_batch_sign (
    1242              :   TALER_ExchangeSignCallback scb,
    1243              :   struct GNUNET_TIME_Timestamp timestamp,
    1244              :   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
    1245              :   const struct TALER_RefreshCommitmentP *rc,
    1246              :   const struct TALER_Amount *total_amount,
    1247              :   const struct GNUNET_HashCode *h_recoups,
    1248              :   struct TALER_ExchangePublicKeyP *pub,
    1249              :   struct TALER_ExchangeSignatureP *sig)
    1250              : {
    1251           38 :   struct TALER_RecoupRefreshBatchConfirmationPS pc = {
    1252           19 :     .purpose.size = htonl (sizeof (pc)),
    1253           19 :     .purpose.purpose = htonl (
    1254              :       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH_BATCH),
    1255           19 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1256              :     .old_coin_pub = *old_coin_pub,
    1257              :     .rc = *rc,
    1258              :     .h_recoups = *h_recoups
    1259              :   };
    1260              : 
    1261           19 :   TALER_amount_hton (&pc.total_amount,
    1262              :                      total_amount);
    1263           19 :   return scb (&pc.purpose,
    1264              :               pub,
    1265              :               sig);
    1266              : }
    1267              : 
    1268              : 
    1269              : enum GNUNET_GenericReturnValue
    1270           20 : TALER_exchange_online_confirm_recoup_refresh_batch_verify (
    1271              :   struct GNUNET_TIME_Timestamp timestamp,
    1272              :   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
    1273              :   const struct TALER_RefreshCommitmentP *rc,
    1274              :   const struct TALER_Amount *total_amount,
    1275              :   const struct GNUNET_HashCode *h_recoups,
    1276              :   const struct TALER_ExchangePublicKeyP *pub,
    1277              :   const struct TALER_ExchangeSignatureP *sig)
    1278              : {
    1279           40 :   struct TALER_RecoupRefreshBatchConfirmationPS pc = {
    1280           20 :     .purpose.size = htonl (sizeof (pc)),
    1281           20 :     .purpose.purpose = htonl (
    1282              :       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH_BATCH),
    1283           20 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1284              :     .old_coin_pub = *old_coin_pub,
    1285              :     .rc = *rc,
    1286              :     .h_recoups = *h_recoups
    1287              :   };
    1288              : 
    1289           20 :   TALER_amount_hton (&pc.total_amount,
    1290              :                      total_amount);
    1291              :   return
    1292           20 :     GNUNET_CRYPTO_eddsa_verify (
    1293              :     TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH_BATCH,
    1294              :     &pc,
    1295              :     &sig->eddsa_signature,
    1296              :     &pub->eddsa_pub);
    1297              : }
    1298              : 
    1299              : 
    1300              : GNUNET_NETWORK_STRUCT_BEGIN
    1301              : 
    1302              : /**
    1303              :  * Response by which the exchange affirms that it does not
    1304              :  * currently know a denomination by the given hash.
    1305              :  */
    1306              : struct TALER_DenominationUnknownAffirmationPS
    1307              : {
    1308              : 
    1309              :   /**
    1310              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN
    1311              :    */
    1312              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    1313              : 
    1314              :   /**
    1315              :    * When did the exchange sign this message.
    1316              :    */
    1317              :   struct GNUNET_TIME_TimestampNBO timestamp;
    1318              : 
    1319              :   /**
    1320              :    * Hash of the public denomination key we do not know.
    1321              :    */
    1322              :   struct TALER_DenominationHashP h_denom_pub;
    1323              : };
    1324              : 
    1325              : GNUNET_NETWORK_STRUCT_END
    1326              : 
    1327              : 
    1328              : enum TALER_ErrorCode
    1329            0 : TALER_exchange_online_denomination_unknown_sign (
    1330              :   TALER_ExchangeSignCallback scb,
    1331              :   struct GNUNET_TIME_Timestamp timestamp,
    1332              :   const struct TALER_DenominationHashP *h_denom_pub,
    1333              :   struct TALER_ExchangePublicKeyP *pub,
    1334              :   struct TALER_ExchangeSignatureP *sig)
    1335              : {
    1336            0 :   struct TALER_DenominationUnknownAffirmationPS dua = {
    1337            0 :     .purpose.size = htonl (sizeof (dua)),
    1338            0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
    1339            0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1340              :     .h_denom_pub = *h_denom_pub,
    1341              :   };
    1342              : 
    1343            0 :   return scb (&dua.purpose,
    1344              :               pub,
    1345              :               sig);
    1346              : }
    1347              : 
    1348              : 
    1349              : enum GNUNET_GenericReturnValue
    1350            0 : TALER_exchange_online_denomination_unknown_verify (
    1351              :   struct GNUNET_TIME_Timestamp timestamp,
    1352              :   const struct TALER_DenominationHashP *h_denom_pub,
    1353              :   const struct TALER_ExchangePublicKeyP *pub,
    1354              :   const struct TALER_ExchangeSignatureP *sig)
    1355              : {
    1356            0 :   struct TALER_DenominationUnknownAffirmationPS dua = {
    1357            0 :     .purpose.size = htonl (sizeof (dua)),
    1358            0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
    1359            0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1360              :     .h_denom_pub = *h_denom_pub,
    1361              :   };
    1362              : 
    1363              :   return
    1364            0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN,
    1365              :                                 &dua,
    1366              :                                 &sig->eddsa_signature,
    1367              :                                 &pub->eddsa_pub);
    1368              : }
    1369              : 
    1370              : 
    1371              : GNUNET_NETWORK_STRUCT_BEGIN
    1372              : 
    1373              : /**
    1374              :  * Response by which the exchange affirms that it does not
    1375              :  * currently consider the given denomination to be valid
    1376              :  * for the requested operation.
    1377              :  */
    1378              : struct TALER_DenominationExpiredAffirmationPS
    1379              : {
    1380              : 
    1381              :   /**
    1382              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED
    1383              :    */
    1384              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    1385              : 
    1386              :   /**
    1387              :    * When did the exchange sign this message.
    1388              :    */
    1389              :   struct GNUNET_TIME_TimestampNBO timestamp;
    1390              : 
    1391              :   /**
    1392              :    * Name of the operation that is not allowed at this time.  Might NOT be 0-terminated, but is padded with 0s.
    1393              :    */
    1394              :   char operation[8];
    1395              : 
    1396              :   /**
    1397              :    * Hash of the public denomination key we do not know.
    1398              :    */
    1399              :   struct TALER_DenominationHashP h_denom_pub;
    1400              : 
    1401              : };
    1402              : 
    1403              : GNUNET_NETWORK_STRUCT_END
    1404              : 
    1405              : 
    1406              : enum TALER_ErrorCode
    1407            6 : TALER_exchange_online_denomination_expired_sign (
    1408              :   TALER_ExchangeSignCallback scb,
    1409              :   struct GNUNET_TIME_Timestamp timestamp,
    1410              :   const struct TALER_DenominationHashP *h_denom_pub,
    1411              :   const char *op,
    1412              :   struct TALER_ExchangePublicKeyP *pub,
    1413              :   struct TALER_ExchangeSignatureP *sig)
    1414              : {
    1415           12 :   struct TALER_DenominationExpiredAffirmationPS dua = {
    1416            6 :     .purpose.size = htonl (sizeof (dua)),
    1417            6 :     .purpose.purpose = htonl (
    1418              :       TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED),
    1419            6 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1420              :     .h_denom_pub = *h_denom_pub,
    1421              :   };
    1422              : 
    1423              :   /* strncpy would create a compiler warning */
    1424            6 :   GNUNET_memcpy (dua.operation,
    1425              :                  op,
    1426              :                  GNUNET_MIN (sizeof (dua.operation),
    1427              :                              strlen (op)));
    1428            6 :   return scb (&dua.purpose,
    1429              :               pub,
    1430              :               sig);
    1431              : }
    1432              : 
    1433              : 
    1434              : enum GNUNET_GenericReturnValue
    1435            0 : TALER_exchange_online_denomination_expired_verify (
    1436              :   struct GNUNET_TIME_Timestamp timestamp,
    1437              :   const struct TALER_DenominationHashP *h_denom_pub,
    1438              :   const char *op,
    1439              :   const struct TALER_ExchangePublicKeyP *pub,
    1440              :   const struct TALER_ExchangeSignatureP *sig)
    1441              : {
    1442            0 :   struct TALER_DenominationExpiredAffirmationPS dua = {
    1443            0 :     .purpose.size = htonl (sizeof (dua)),
    1444            0 :     .purpose.purpose = htonl (
    1445              :       TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED),
    1446            0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1447              :     .h_denom_pub = *h_denom_pub,
    1448              :   };
    1449              : 
    1450              :   /* strncpy would create a compiler warning */
    1451            0 :   GNUNET_memcpy (dua.operation,
    1452              :                  op,
    1453              :                  GNUNET_MIN (sizeof (dua.operation),
    1454              :                              strlen (op)));
    1455              :   return
    1456            0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED,
    1457              :                                 &dua,
    1458              :                                 &sig->eddsa_signature,
    1459              :                                 &pub->eddsa_pub);
    1460              : }
    1461              : 
    1462              : 
    1463              : GNUNET_NETWORK_STRUCT_BEGIN
    1464              : 
    1465              : /**
    1466              :  * Response by which the exchange affirms that it has
    1467              :  * closed a reserve and send back the funds.
    1468              :  */
    1469              : struct TALER_ReserveCloseConfirmationPS
    1470              : {
    1471              : 
    1472              :   /**
    1473              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED
    1474              :    */
    1475              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    1476              : 
    1477              :   /**
    1478              :    * When did the exchange initiate the wire transfer.
    1479              :    */
    1480              :   struct GNUNET_TIME_TimestampNBO timestamp;
    1481              : 
    1482              :   /**
    1483              :    * How much did the exchange send?
    1484              :    */
    1485              :   struct TALER_AmountNBO closing_amount;
    1486              : 
    1487              :   /**
    1488              :    * How much did the exchange charge for closing the reserve?
    1489              :    */
    1490              :   struct TALER_AmountNBO closing_fee;
    1491              : 
    1492              :   /**
    1493              :    * Public key of the reserve that was closed.
    1494              :    */
    1495              :   struct TALER_ReservePublicKeyP reserve_pub;
    1496              : 
    1497              :   /**
    1498              :    * Hash of the receiver's bank account.
    1499              :    */
    1500              :   struct TALER_FullPaytoHashP h_payto;
    1501              : 
    1502              :   /**
    1503              :    * Wire transfer subject.
    1504              :    */
    1505              :   struct TALER_WireTransferIdentifierRawP wtid;
    1506              : };
    1507              : 
    1508              : GNUNET_NETWORK_STRUCT_END
    1509              : 
    1510              : 
    1511              : enum TALER_ErrorCode
    1512            0 : TALER_exchange_online_reserve_closed_sign (
    1513              :   TALER_ExchangeSignCallback scb,
    1514              :   struct GNUNET_TIME_Timestamp timestamp,
    1515              :   const struct TALER_Amount *closing_amount,
    1516              :   const struct TALER_Amount *closing_fee,
    1517              :   const struct TALER_FullPayto payto,
    1518              :   const struct TALER_WireTransferIdentifierRawP *wtid,
    1519              :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1520              :   struct TALER_ExchangePublicKeyP *pub,
    1521              :   struct TALER_ExchangeSignatureP *sig)
    1522              : {
    1523            0 :   struct TALER_ReserveCloseConfirmationPS rcc = {
    1524            0 :     .purpose.size = htonl (sizeof (rcc)),
    1525            0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED),
    1526              :     .wtid = *wtid,
    1527              :     .reserve_pub = *reserve_pub,
    1528            0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp)
    1529              :   };
    1530              : 
    1531            0 :   TALER_amount_hton (&rcc.closing_amount,
    1532              :                      closing_amount);
    1533            0 :   TALER_amount_hton (&rcc.closing_fee,
    1534              :                      closing_fee);
    1535            0 :   TALER_full_payto_hash (payto,
    1536              :                          &rcc.h_payto);
    1537            0 :   return scb (&rcc.purpose,
    1538              :               pub,
    1539              :               sig);
    1540              : }
    1541              : 
    1542              : 
    1543              : enum GNUNET_GenericReturnValue
    1544            0 : TALER_exchange_online_reserve_closed_verify (
    1545              :   struct GNUNET_TIME_Timestamp timestamp,
    1546              :   const struct TALER_Amount *closing_amount,
    1547              :   const struct TALER_Amount *closing_fee,
    1548              :   const struct TALER_FullPayto payto,
    1549              :   const struct TALER_WireTransferIdentifierRawP *wtid,
    1550              :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1551              :   const struct TALER_ExchangePublicKeyP *pub,
    1552              :   const struct TALER_ExchangeSignatureP *sig)
    1553              : {
    1554            0 :   struct TALER_ReserveCloseConfirmationPS rcc = {
    1555            0 :     .purpose.size = htonl (sizeof (rcc)),
    1556            0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED),
    1557              :     .wtid = *wtid,
    1558              :     .reserve_pub = *reserve_pub,
    1559            0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp)
    1560              :   };
    1561              : 
    1562            0 :   TALER_amount_hton (&rcc.closing_amount,
    1563              :                      closing_amount);
    1564            0 :   TALER_amount_hton (&rcc.closing_fee,
    1565              :                      closing_fee);
    1566            0 :   TALER_full_payto_hash (payto,
    1567              :                          &rcc.h_payto);
    1568            0 :   return GNUNET_CRYPTO_eddsa_verify (
    1569              :     TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED,
    1570              :     &rcc,
    1571              :     &sig->eddsa_signature,
    1572              :     &pub->eddsa_pub);
    1573              : }
    1574              : 
    1575              : 
    1576              : GNUNET_NETWORK_STRUCT_BEGIN
    1577              : 
    1578              : /**
    1579              :  * Response by which the exchange affirms that it has
    1580              :  * received funds deposited into a purse.
    1581              :  */
    1582              : struct TALER_PurseCreateDepositConfirmationPS
    1583              : {
    1584              : 
    1585              :   /**
    1586              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION
    1587              :    */
    1588              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    1589              : 
    1590              :   /**
    1591              :    * When did the exchange receive the deposits.
    1592              :    */
    1593              :   struct GNUNET_TIME_TimestampNBO exchange_time;
    1594              : 
    1595              :   /**
    1596              :    * When will the purse expire?
    1597              :    */
    1598              :   struct GNUNET_TIME_TimestampNBO purse_expiration;
    1599              : 
    1600              :   /**
    1601              :    * How much should the purse ultimately contain.
    1602              :    */
    1603              :   struct TALER_AmountNBO amount_without_fee;
    1604              : 
    1605              :   /**
    1606              :    * How much was deposited so far.
    1607              :    */
    1608              :   struct TALER_AmountNBO total_deposited;
    1609              : 
    1610              :   /**
    1611              :    * Public key of the purse.
    1612              :    */
    1613              :   struct TALER_PurseContractPublicKeyP purse_pub;
    1614              : 
    1615              :   /**
    1616              :    * Hash of the contract of the purse.
    1617              :    */
    1618              :   struct TALER_PrivateContractHashP h_contract_terms;
    1619              : 
    1620              : };
    1621              : 
    1622              : GNUNET_NETWORK_STRUCT_END
    1623              : 
    1624              : 
    1625              : enum TALER_ErrorCode
    1626           25 : TALER_exchange_online_purse_created_sign (
    1627              :   TALER_ExchangeSignCallback scb,
    1628              :   struct GNUNET_TIME_Timestamp exchange_time,
    1629              :   struct GNUNET_TIME_Timestamp purse_expiration,
    1630              :   const struct TALER_Amount *amount_without_fee,
    1631              :   const struct TALER_Amount *total_deposited,
    1632              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1633              :   const struct TALER_PrivateContractHashP *h_contract_terms,
    1634              :   struct TALER_ExchangePublicKeyP *pub,
    1635              :   struct TALER_ExchangeSignatureP *sig)
    1636              : {
    1637           50 :   struct TALER_PurseCreateDepositConfirmationPS dc = {
    1638           25 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
    1639           25 :     .purpose.size = htonl (sizeof (dc)),
    1640              :     .h_contract_terms = *h_contract_terms,
    1641              :     .purse_pub = *purse_pub,
    1642           25 :     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
    1643           25 :     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
    1644              :   };
    1645              : 
    1646           25 :   TALER_amount_hton (&dc.amount_without_fee,
    1647              :                      amount_without_fee);
    1648           25 :   TALER_amount_hton (&dc.total_deposited,
    1649              :                      total_deposited);
    1650           25 :   return scb (&dc.purpose,
    1651              :               pub,
    1652              :               sig);
    1653              : }
    1654              : 
    1655              : 
    1656              : enum GNUNET_GenericReturnValue
    1657           25 : TALER_exchange_online_purse_created_verify (
    1658              :   struct GNUNET_TIME_Timestamp exchange_time,
    1659              :   struct GNUNET_TIME_Timestamp purse_expiration,
    1660              :   const struct TALER_Amount *amount_without_fee,
    1661              :   const struct TALER_Amount *total_deposited,
    1662              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1663              :   const struct TALER_PrivateContractHashP *h_contract_terms,
    1664              :   const struct TALER_ExchangePublicKeyP *pub,
    1665              :   const struct TALER_ExchangeSignatureP *sig)
    1666              : {
    1667           50 :   struct TALER_PurseCreateDepositConfirmationPS dc = {
    1668           25 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
    1669           25 :     .purpose.size = htonl (sizeof (dc)),
    1670              :     .h_contract_terms = *h_contract_terms,
    1671              :     .purse_pub = *purse_pub,
    1672           25 :     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
    1673           25 :     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
    1674              :   };
    1675              : 
    1676           25 :   TALER_amount_hton (&dc.amount_without_fee,
    1677              :                      amount_without_fee);
    1678           25 :   TALER_amount_hton (&dc.total_deposited,
    1679              :                      total_deposited);
    1680           25 :   return GNUNET_CRYPTO_eddsa_verify (
    1681              :     TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION,
    1682              :     &dc,
    1683              :     &sig->eddsa_signature,
    1684              :     &pub->eddsa_pub);
    1685              : }
    1686              : 
    1687              : 
    1688              : GNUNET_NETWORK_STRUCT_BEGIN
    1689              : 
    1690              : /**
    1691              :  * Response by which the exchange affirms that it has
    1692              :  * received funds deposited into a purse.
    1693              :  */
    1694              : struct TALER_CoinPurseRefundConfirmationPS
    1695              : {
    1696              : 
    1697              :   /**
    1698              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND
    1699              :    */
    1700              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    1701              : 
    1702              :   /**
    1703              :    * Public key of the purse.
    1704              :    */
    1705              :   struct TALER_PurseContractPublicKeyP purse_pub;
    1706              : 
    1707              :   /**
    1708              :    * Public key of the coin.
    1709              :    */
    1710              :   struct TALER_CoinSpendPublicKeyP coin_pub;
    1711              : 
    1712              :   /**
    1713              :    * How much will be refunded to the purse.
    1714              :    */
    1715              :   struct TALER_AmountNBO refunded_amount;
    1716              : 
    1717              :   /**
    1718              :    * How much was the refund fee.
    1719              :    */
    1720              :   struct TALER_AmountNBO refund_fee;
    1721              : 
    1722              : };
    1723              : 
    1724              : GNUNET_NETWORK_STRUCT_END
    1725              : 
    1726              : 
    1727              : enum TALER_ErrorCode
    1728            0 : TALER_exchange_online_purse_refund_sign (
    1729              :   TALER_ExchangeSignCallback scb,
    1730              :   const struct TALER_Amount *amount_without_fee,
    1731              :   const struct TALER_Amount *refund_fee,
    1732              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    1733              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1734              :   struct TALER_ExchangePublicKeyP *pub,
    1735              :   struct TALER_ExchangeSignatureP *sig)
    1736              : {
    1737            0 :   struct TALER_CoinPurseRefundConfirmationPS dc = {
    1738            0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND),
    1739            0 :     .purpose.size = htonl (sizeof (dc)),
    1740              :     .coin_pub = *coin_pub,
    1741              :     .purse_pub = *purse_pub,
    1742              :   };
    1743              : 
    1744            0 :   TALER_amount_hton (&dc.refunded_amount,
    1745              :                      amount_without_fee);
    1746            0 :   TALER_amount_hton (&dc.refund_fee,
    1747              :                      refund_fee);
    1748            0 :   return scb (&dc.purpose,
    1749              :               pub,
    1750              :               sig);
    1751              : }
    1752              : 
    1753              : 
    1754              : enum GNUNET_GenericReturnValue
    1755            0 : TALER_exchange_online_purse_refund_verify (
    1756              :   const struct TALER_Amount *amount_without_fee,
    1757              :   const struct TALER_Amount *refund_fee,
    1758              :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    1759              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1760              :   const struct TALER_ExchangePublicKeyP *pub,
    1761              :   const struct TALER_ExchangeSignatureP *sig)
    1762              : {
    1763            0 :   struct TALER_CoinPurseRefundConfirmationPS dc = {
    1764            0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND),
    1765            0 :     .purpose.size = htonl (sizeof (dc)),
    1766              :     .coin_pub = *coin_pub,
    1767              :     .purse_pub = *purse_pub,
    1768              :   };
    1769              : 
    1770            0 :   TALER_amount_hton (&dc.refunded_amount,
    1771              :                      amount_without_fee);
    1772            0 :   TALER_amount_hton (&dc.refund_fee,
    1773              :                      refund_fee);
    1774            0 :   return GNUNET_CRYPTO_eddsa_verify (
    1775              :     TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND,
    1776              :     &dc,
    1777              :     &sig->eddsa_signature,
    1778              :     &pub->eddsa_pub);
    1779              : }
    1780              : 
    1781              : 
    1782              : GNUNET_NETWORK_STRUCT_BEGIN
    1783              : 
    1784              : /**
    1785              :  * Response by which the exchange affirms that it has
    1786              :  * merged a purse into a reserve.
    1787              :  */
    1788              : struct TALER_PurseMergedConfirmationPS
    1789              : {
    1790              : 
    1791              :   /**
    1792              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED
    1793              :    */
    1794              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    1795              : 
    1796              :   /**
    1797              :    * When did the exchange receive the deposits.
    1798              :    */
    1799              :   struct GNUNET_TIME_TimestampNBO exchange_time;
    1800              : 
    1801              :   /**
    1802              :    * When will the purse expire?
    1803              :    */
    1804              :   struct GNUNET_TIME_TimestampNBO purse_expiration;
    1805              : 
    1806              :   /**
    1807              :    * How much should the purse ultimately contain.
    1808              :    */
    1809              :   struct TALER_AmountNBO amount_without_fee;
    1810              : 
    1811              :   /**
    1812              :    * Public key of the purse.
    1813              :    */
    1814              :   struct TALER_PurseContractPublicKeyP purse_pub;
    1815              : 
    1816              :   /**
    1817              :    * Public key of the reserve.
    1818              :    */
    1819              :   struct TALER_ReservePublicKeyP reserve_pub;
    1820              : 
    1821              :   /**
    1822              :    * Hash of the contract of the purse.
    1823              :    */
    1824              :   struct TALER_PrivateContractHashP h_contract_terms;
    1825              : 
    1826              :   /**
    1827              :    * Hash of the provider URL hosting the reserve.
    1828              :    */
    1829              :   struct GNUNET_HashCode h_provider_url;
    1830              : 
    1831              : };
    1832              : 
    1833              : GNUNET_NETWORK_STRUCT_END
    1834              : 
    1835              : 
    1836              : enum TALER_ErrorCode
    1837            3 : TALER_exchange_online_purse_merged_sign (
    1838              :   TALER_ExchangeSignCallback scb,
    1839              :   struct GNUNET_TIME_Timestamp exchange_time,
    1840              :   struct GNUNET_TIME_Timestamp purse_expiration,
    1841              :   const struct TALER_Amount *amount_without_fee,
    1842              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1843              :   const struct TALER_PrivateContractHashP *h_contract_terms,
    1844              :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1845              :   const char *exchange_url,
    1846              :   struct TALER_ExchangePublicKeyP *pub,
    1847              :   struct TALER_ExchangeSignatureP *sig)
    1848              : {
    1849            6 :   struct TALER_PurseMergedConfirmationPS dc = {
    1850            3 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED),
    1851            3 :     .purpose.size = htonl (sizeof (dc)),
    1852              :     .h_contract_terms = *h_contract_terms,
    1853              :     .purse_pub = *purse_pub,
    1854              :     .reserve_pub = *reserve_pub,
    1855            3 :     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
    1856            3 :     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
    1857              :   };
    1858              : 
    1859            3 :   TALER_amount_hton (&dc.amount_without_fee,
    1860              :                      amount_without_fee);
    1861            3 :   GNUNET_CRYPTO_hash (exchange_url,
    1862            3 :                       strlen (exchange_url) + 1,
    1863              :                       &dc.h_provider_url);
    1864            3 :   return scb (&dc.purpose,
    1865              :               pub,
    1866              :               sig);
    1867              : }
    1868              : 
    1869              : 
    1870              : enum GNUNET_GenericReturnValue
    1871            3 : TALER_exchange_online_purse_merged_verify (
    1872              :   struct GNUNET_TIME_Timestamp exchange_time,
    1873              :   struct GNUNET_TIME_Timestamp purse_expiration,
    1874              :   const struct TALER_Amount *amount_without_fee,
    1875              :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1876              :   const struct TALER_PrivateContractHashP *h_contract_terms,
    1877              :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1878              :   const char *exchange_url,
    1879              :   const struct TALER_ExchangePublicKeyP *pub,
    1880              :   const struct TALER_ExchangeSignatureP *sig)
    1881              : {
    1882            6 :   struct TALER_PurseMergedConfirmationPS dc = {
    1883            3 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED),
    1884            3 :     .purpose.size = htonl (sizeof (dc)),
    1885              :     .h_contract_terms = *h_contract_terms,
    1886              :     .purse_pub = *purse_pub,
    1887              :     .reserve_pub = *reserve_pub,
    1888            3 :     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
    1889            3 :     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
    1890              :   };
    1891              : 
    1892            3 :   TALER_amount_hton (&dc.amount_without_fee,
    1893              :                      amount_without_fee);
    1894            3 :   GNUNET_CRYPTO_hash (exchange_url,
    1895            3 :                       strlen (exchange_url) + 1,
    1896              :                       &dc.h_provider_url);
    1897              :   return
    1898            3 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED,
    1899              :                                 &dc,
    1900              :                                 &sig->eddsa_signature,
    1901              :                                 &pub->eddsa_pub);
    1902              : }
    1903              : 
    1904              : 
    1905              : GNUNET_NETWORK_STRUCT_BEGIN
    1906              : 
    1907              : /**
    1908              :  * @brief Format used to generate the signature on a purse status
    1909              :  * from the exchange.
    1910              :  */
    1911              : struct TALER_PurseStatusPS
    1912              : {
    1913              :   /**
    1914              :    * Purpose must be #TALER_SIGNATURE_EXCHANGE_PURSE_STATUS.  Signed
    1915              :    * by a `struct TALER_ExchangePublicKeyP` using EdDSA.
    1916              :    */
    1917              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    1918              : 
    1919              :   /**
    1920              :    * Time when the purse was merged, possibly 'never'.
    1921              :    */
    1922              :   struct GNUNET_TIME_TimestampNBO merge_timestamp;
    1923              : 
    1924              :   /**
    1925              :    * Time when the purse was deposited last, possibly 'never'.
    1926              :    */
    1927              :   struct GNUNET_TIME_TimestampNBO deposit_timestamp;
    1928              : 
    1929              :   /**
    1930              :    * Amount deposited in total in the purse without fees.
    1931              :    * May be possibly less than the target amount.
    1932              :    */
    1933              :   struct TALER_AmountNBO balance;
    1934              : 
    1935              : };
    1936              : 
    1937              : GNUNET_NETWORK_STRUCT_END
    1938              : 
    1939              : 
    1940              : enum TALER_ErrorCode
    1941            6 : TALER_exchange_online_purse_status_sign (
    1942              :   TALER_ExchangeSignCallback scb,
    1943              :   struct GNUNET_TIME_Timestamp merge_timestamp,
    1944              :   struct GNUNET_TIME_Timestamp deposit_timestamp,
    1945              :   const struct TALER_Amount *balance,
    1946              :   struct TALER_ExchangePublicKeyP *pub,
    1947              :   struct TALER_ExchangeSignatureP *sig)
    1948              : {
    1949            6 :   struct TALER_PurseStatusPS dcs = {
    1950            6 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS),
    1951            6 :     .purpose.size = htonl (sizeof (dcs)),
    1952            6 :     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
    1953            6 :     .deposit_timestamp = GNUNET_TIME_timestamp_hton (deposit_timestamp)
    1954              :   };
    1955              : 
    1956            6 :   TALER_amount_hton (&dcs.balance,
    1957              :                      balance);
    1958            6 :   return scb (&dcs.purpose,
    1959              :               pub,
    1960              :               sig);
    1961              : }
    1962              : 
    1963              : 
    1964              : enum GNUNET_GenericReturnValue
    1965            6 : TALER_exchange_online_purse_status_verify (
    1966              :   struct GNUNET_TIME_Timestamp merge_timestamp,
    1967              :   struct GNUNET_TIME_Timestamp deposit_timestamp,
    1968              :   const struct TALER_Amount *balance,
    1969              :   const struct TALER_ExchangePublicKeyP *exchange_pub,
    1970              :   const struct TALER_ExchangeSignatureP *exchange_sig)
    1971              : {
    1972            6 :   struct TALER_PurseStatusPS dcs = {
    1973            6 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS),
    1974            6 :     .purpose.size = htonl (sizeof (dcs)),
    1975            6 :     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
    1976            6 :     .deposit_timestamp = GNUNET_TIME_timestamp_hton (deposit_timestamp)
    1977              :   };
    1978              : 
    1979            6 :   TALER_amount_hton (&dcs.balance,
    1980              :                      balance);
    1981            6 :   if (GNUNET_OK !=
    1982            6 :       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS,
    1983              :                                   &dcs,
    1984              :                                   &exchange_sig->eddsa_signature,
    1985              :                                   &exchange_pub->eddsa_pub))
    1986              :   {
    1987            0 :     GNUNET_break_op (0);
    1988            0 :     return GNUNET_SYSERR;
    1989              :   }
    1990            6 :   return GNUNET_OK;
    1991              : }
    1992              : 
    1993              : 
    1994              : GNUNET_NETWORK_STRUCT_BEGIN
    1995              : 
    1996              : /**
    1997              :  * Message signed by the exchange to affirm that the
    1998              :  * owner of a reserve has certain attributes.
    1999              :  */
    2000              : struct TALER_ExchangeAttestPS
    2001              : {
    2002              : 
    2003              :   /**
    2004              :    * Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS
    2005              :    */
    2006              :   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    2007              : 
    2008              :   /**
    2009              :    * Time when the attestation was made.
    2010              :    */
    2011              :   struct GNUNET_TIME_TimestampNBO attest_timestamp;
    2012              : 
    2013              :   /**
    2014              :    * Time when the attestation expires.
    2015              :    */
    2016              :   struct GNUNET_TIME_TimestampNBO expiration_time;
    2017              : 
    2018              :   /**
    2019              :    * Public key of the reserve for which the attributes
    2020              :    * are attested.
    2021              :    */
    2022              :   struct TALER_ReservePublicKeyP reserve_pub;
    2023              : 
    2024              :   /**
    2025              :    * Hash over the attributes.
    2026              :    */
    2027              :   struct GNUNET_HashCode h_attributes;
    2028              : 
    2029              : };
    2030              : 
    2031              : GNUNET_NETWORK_STRUCT_END
    2032              : 
    2033              : 
    2034              : enum TALER_ErrorCode
    2035            1 : TALER_exchange_online_reserve_attest_details_sign (
    2036              :   TALER_ExchangeSignCallback scb,
    2037              :   struct GNUNET_TIME_Timestamp attest_timestamp,
    2038              :   struct GNUNET_TIME_Timestamp expiration_time,
    2039              :   const struct TALER_ReservePublicKeyP *reserve_pub,
    2040              :   const json_t *attributes,
    2041              :   struct TALER_ExchangePublicKeyP *pub,
    2042              :   struct TALER_ExchangeSignatureP *sig)
    2043              : {
    2044            2 :   struct TALER_ExchangeAttestPS rap = {
    2045            1 :     .purpose.size = htonl (sizeof (rap)),
    2046            1 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS),
    2047            1 :     .attest_timestamp = GNUNET_TIME_timestamp_hton (attest_timestamp),
    2048            1 :     .expiration_time = GNUNET_TIME_timestamp_hton (expiration_time),
    2049              :     .reserve_pub = *reserve_pub
    2050              :   };
    2051              : 
    2052            1 :   TALER_json_hash (attributes,
    2053              :                    &rap.h_attributes);
    2054            1 :   return scb (&rap.purpose,
    2055              :               pub,
    2056              :               sig);
    2057              : }
    2058              : 
    2059              : 
    2060              : enum GNUNET_GenericReturnValue
    2061            1 : TALER_exchange_online_reserve_attest_details_verify (
    2062              :   struct GNUNET_TIME_Timestamp attest_timestamp,
    2063              :   struct GNUNET_TIME_Timestamp expiration_time,
    2064              :   const struct TALER_ReservePublicKeyP *reserve_pub,
    2065              :   const json_t *attributes,
    2066              :   struct TALER_ExchangePublicKeyP *pub,
    2067              :   struct TALER_ExchangeSignatureP *sig)
    2068              : {
    2069            2 :   struct TALER_ExchangeAttestPS rap = {
    2070            1 :     .purpose.size = htonl (sizeof (rap)),
    2071            1 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS),
    2072            1 :     .attest_timestamp = GNUNET_TIME_timestamp_hton (attest_timestamp),
    2073            1 :     .expiration_time = GNUNET_TIME_timestamp_hton (expiration_time),
    2074              :     .reserve_pub = *reserve_pub
    2075              :   };
    2076              : 
    2077            1 :   TALER_json_hash (attributes,
    2078              :                    &rap.h_attributes);
    2079            1 :   if (GNUNET_OK !=
    2080            1 :       GNUNET_CRYPTO_eddsa_verify (
    2081              :         TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS,
    2082              :         &rap,
    2083              :         &sig->eddsa_signature,
    2084              :         &pub->eddsa_pub))
    2085              :   {
    2086            0 :     GNUNET_break_op (0);
    2087            0 :     return GNUNET_SYSERR;
    2088              :   }
    2089            1 :   return GNUNET_OK;
    2090              : }
    2091              : 
    2092              : 
    2093              : /* end of exchange_signatures.c */
        

Generated by: LCOV version 2.0-1