exchange

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

exchange_signatures.c (53410B)


      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 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 {
    114   struct TALER_DepositConfirmationPS dcs = {
    115     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
    116     .purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
    117     .h_contract_terms = *h_contract_terms,
    118     .h_wire = *h_wire,
    119     .exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
    120     .wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
    121     .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   hc = GNUNET_CRYPTO_hash_context_start ();
    128   for (unsigned int i = 0; i<num_coins; i++)
    129     GNUNET_CRYPTO_hash_context_read (hc,
    130                                      coin_sigs[i],
    131                                      sizeof (*coin_sigs[i]));
    132   GNUNET_CRYPTO_hash_context_finish (hc,
    133                                      &dcs.h_coin_sigs);
    134   if (NULL != h_policy)
    135     dcs.h_policy = *h_policy;
    136   TALER_amount_hton (&dcs.total_without_fee,
    137                      total_without_fee);
    138   return scb (&dcs.purpose,
    139               pub,
    140               sig);
    141 }
    142 
    143 
    144 enum GNUNET_GenericReturnValue
    145 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 {
    159   struct TALER_DepositConfirmationPS dcs = {
    160     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
    161     .purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
    162     .h_contract_terms = *h_contract_terms,
    163     .h_wire = *h_wire,
    164     .exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
    165     .wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
    166     .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
    167     .merchant_pub = *merchant_pub
    168   };
    169   struct GNUNET_HashContext *hc;
    170 
    171   hc = GNUNET_CRYPTO_hash_context_start ();
    172   for (unsigned int i = 0; i<num_coins; i++)
    173     GNUNET_CRYPTO_hash_context_read (hc,
    174                                      coin_sigs[i],
    175                                      sizeof (*coin_sigs[i]));
    176   GNUNET_CRYPTO_hash_context_finish (hc,
    177                                      &dcs.h_coin_sigs);
    178   if (NULL != h_policy)
    179     dcs.h_policy = *h_policy;
    180   TALER_amount_hton (&dcs.total_without_fee,
    181                      total_without_fee);
    182   if (GNUNET_OK !=
    183       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
    184                                   &dcs,
    185                                   &exchange_sig->eddsa_signature,
    186                                   &exchange_pub->eddsa_pub))
    187   {
    188     GNUNET_break_op (0);
    189     return GNUNET_SYSERR;
    190   }
    191   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 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   struct TALER_RefundConfirmationPS rc = {
    253     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND),
    254     .purpose.size = htonl (sizeof (rc)),
    255     .h_contract_terms = *h_contract_terms,
    256     .coin_pub = *coin_pub,
    257     .merchant = *merchant,
    258     .rtransaction_id = GNUNET_htonll (rtransaction_id)
    259   };
    260 
    261   TALER_amount_hton (&rc.refund_amount,
    262                      refund_amount);
    263   return scb (&rc.purpose,
    264               pub,
    265               sig);
    266 }
    267 
    268 
    269 enum GNUNET_GenericReturnValue
    270 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   struct TALER_RefundConfirmationPS rc = {
    280     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND),
    281     .purpose.size = htonl (sizeof (rc)),
    282     .h_contract_terms = *h_contract_terms,
    283     .coin_pub = *coin_pub,
    284     .merchant = *merchant,
    285     .rtransaction_id = GNUNET_htonll (rtransaction_id)
    286   };
    287 
    288   TALER_amount_hton (&rc.refund_amount,
    289                      refund_amount);
    290   if (GNUNET_OK !=
    291       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND,
    292                                   &rc,
    293                                   &sig->eddsa_signature,
    294                                   &pub->eddsa_pub))
    295   {
    296     GNUNET_break_op (0);
    297     return GNUNET_SYSERR;
    298   }
    299   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 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   struct TALER_RefreshMeltConfirmationPS confirm = {
    344     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
    345     .purpose.size = htonl (sizeof (confirm)),
    346     .rc = *rc,
    347     .noreveal_index = htonl (noreveal_index)
    348   };
    349 
    350   return scb (&confirm.purpose,
    351               pub,
    352               sig);
    353 }
    354 
    355 
    356 enum GNUNET_GenericReturnValue
    357 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   struct TALER_RefreshMeltConfirmationPS confirm = {
    364     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
    365     .purpose.size = htonl (sizeof (confirm)),
    366     .rc = *rc,
    367     .noreveal_index = htonl (noreveal_index)
    368   };
    369 
    370   return
    371     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 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   struct TALER_WithdrawConfirmationPS confirm = {
    425     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW),
    426     .purpose.size = htonl (sizeof (confirm)),
    427     .h_planchets = *h_planchets,
    428     .noreveal_index = htonl (noreveal_index)
    429   };
    430 
    431   return scb (&confirm.purpose,
    432               pub,
    433               sig);
    434 }
    435 
    436 
    437 enum TALER_ErrorCode
    438 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   struct TALER_WithdrawConfirmationPS confirm = {
    446     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW),
    447     .purpose.size = htonl (sizeof (confirm)),
    448     .h_planchets = *h_planchets,
    449     .noreveal_index = htonl (0xFFFFFFFF)
    450   };
    451 
    452   return scb (&confirm.purpose,
    453               pub,
    454               sig);
    455 }
    456 
    457 
    458 enum GNUNET_GenericReturnValue
    459 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   struct TALER_WithdrawConfirmationPS confirm = {
    466     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW),
    467     .purpose.size = htonl (sizeof (confirm)),
    468     .h_planchets = *h_planchets,
    469     .noreveal_index = htonl (noreveal_index)
    470   };
    471 
    472   if (GNUNET_OK !=
    473       GNUNET_CRYPTO_eddsa_verify (
    474         TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW,
    475         &confirm,
    476         &exchange_sig->eddsa_signature,
    477         &exchange_pub->eddsa_pub))
    478   {
    479     GNUNET_break_op (0);
    480     return GNUNET_SYSERR;
    481   }
    482   return GNUNET_OK;
    483 }
    484 
    485 
    486 enum GNUNET_GenericReturnValue
    487 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   struct TALER_WithdrawConfirmationPS confirm = {
    493     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW),
    494     .purpose.size = htonl (sizeof (confirm)),
    495     .h_planchets = *h_planchets,
    496     .noreveal_index = htonl (0xFFFFFFFF)
    497   };
    498 
    499   if (GNUNET_OK !=
    500       GNUNET_CRYPTO_eddsa_verify (
    501         TALER_SIGNATURE_EXCHANGE_CONFIRM_WITHDRAW,
    502         &confirm,
    503         &exchange_sig->eddsa_signature,
    504         &exchange_pub->eddsa_pub))
    505   {
    506     GNUNET_break_op (0);
    507     return GNUNET_SYSERR;
    508   }
    509   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 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   struct TALER_ExchangeKeySetPS ks = {
    553     .purpose.size = htonl (sizeof (ks)),
    554     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET),
    555     .list_issue_date = GNUNET_TIME_timestamp_hton (timestamp),
    556     .hc = *hc
    557   };
    558 
    559   return scb (cls,
    560               &ks.purpose,
    561               pub,
    562               sig);
    563 }
    564 
    565 
    566 enum GNUNET_GenericReturnValue
    567 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   struct TALER_ExchangeKeySetPS ks = {
    574     .purpose.size = htonl (sizeof (ks)),
    575     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET),
    576     .list_issue_date = GNUNET_TIME_timestamp_hton (timestamp),
    577     .hc = *hc
    578   };
    579 
    580   return
    581     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 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   struct TALER_WireDepositDetailP dd = {
    637     .h_contract_terms = *h_contract_terms,
    638     .execution_time = GNUNET_TIME_timestamp_hton (execution_time),
    639     .coin_pub = *coin_pub
    640   };
    641   TALER_amount_hton (&dd.deposit_value,
    642                      deposit_value);
    643   TALER_amount_hton (&dd.deposit_fee,
    644                      deposit_fee);
    645   GNUNET_CRYPTO_hash_context_read (hash_context,
    646                                    &dd,
    647                                    sizeof (dd));
    648 }
    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 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   struct TALER_WireDepositDataPS wdp = {
    708     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
    709     .purpose.size = htonl (sizeof (wdp)),
    710     .merchant_pub = *merchant_pub,
    711     .h_details = *h_details
    712   };
    713 
    714   TALER_amount_hton (&wdp.total,
    715                      total);
    716   TALER_amount_hton (&wdp.wire_fee,
    717                      wire_fee);
    718   TALER_full_payto_hash (payto,
    719                          &wdp.h_payto);
    720   return scb (&wdp.purpose,
    721               pub,
    722               sig);
    723 }
    724 
    725 
    726 enum GNUNET_GenericReturnValue
    727 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   struct TALER_WireDepositDataPS wdp = {
    737     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
    738     .purpose.size = htonl (sizeof (wdp)),
    739     .merchant_pub = *merchant_pub,
    740     .h_details = *h_details,
    741     .h_payto = *h_payto
    742   };
    743 
    744   TALER_amount_hton (&wdp.total,
    745                      total);
    746   TALER_amount_hton (&wdp.wire_fee,
    747                      wire_fee);
    748   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 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   struct TALER_ConfirmWirePS cw = {
    823     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE),
    824     .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     .execution_time = GNUNET_TIME_timestamp_hton (execution_time)
    830   };
    831 
    832   TALER_amount_hton (&cw.coin_contribution,
    833                      coin_contribution);
    834   return scb (&cw.purpose,
    835               pub,
    836               sig);
    837 }
    838 
    839 
    840 enum GNUNET_GenericReturnValue
    841 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   struct TALER_ConfirmWirePS cw = {
    852     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE),
    853     .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     .execution_time = GNUNET_TIME_timestamp_hton (execution_time)
    859   };
    860 
    861   TALER_amount_hton (&cw.coin_contribution,
    862                      coin_contribution);
    863   return
    864     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 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   struct TALER_RecoupConfirmationPS pc = {
    925     .purpose.size = htonl (sizeof (pc)),
    926     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
    927     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    928     .coin_pub = *coin_pub,
    929     .reserve_pub = *reserve_pub
    930   };
    931 
    932   TALER_amount_hton (&pc.recoup_amount,
    933                      recoup_amount);
    934   return scb (&pc.purpose,
    935               pub,
    936               sig);
    937 }
    938 
    939 
    940 enum GNUNET_GenericReturnValue
    941 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   struct TALER_RecoupConfirmationPS pc = {
    950     .purpose.size = htonl (sizeof (pc)),
    951     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
    952     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    953     .coin_pub = *coin_pub,
    954     .reserve_pub = *reserve_pub
    955   };
    956 
    957   TALER_amount_hton (&pc.recoup_amount,
    958                      recoup_amount);
    959   return
    960     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 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   struct TALER_RecoupRefreshConfirmationPS pc = {
   1020     .purpose.purpose = htonl (
   1021       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
   1022     .purpose.size = htonl (sizeof (pc)),
   1023     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
   1024     .coin_pub = *coin_pub,
   1025     .old_coin_pub = *old_coin_pub
   1026   };
   1027 
   1028   TALER_amount_hton (&pc.recoup_amount,
   1029                      recoup_amount);
   1030   return scb (&pc.purpose,
   1031               pub,
   1032               sig);
   1033 }
   1034 
   1035 
   1036 enum GNUNET_GenericReturnValue
   1037 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   struct TALER_RecoupRefreshConfirmationPS pc = {
   1046     .purpose.purpose = htonl (
   1047       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
   1048     .purpose.size = htonl (sizeof (pc)),
   1049     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
   1050     .coin_pub = *coin_pub,
   1051     .old_coin_pub = *old_coin_pub
   1052   };
   1053 
   1054   TALER_amount_hton (&pc.recoup_amount,
   1055                      recoup_amount);
   1056 
   1057   return
   1058     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH,
   1059                                 &pc,
   1060                                 &sig->eddsa_signature,
   1061                                 &pub->eddsa_pub);
   1062 }
   1063 
   1064 
   1065 GNUNET_NETWORK_STRUCT_BEGIN
   1066 
   1067 /**
   1068  * Response by which the exchange affirms that it does not
   1069  * currently know a denomination by the given hash.
   1070  */
   1071 struct TALER_DenominationUnknownAffirmationPS
   1072 {
   1073 
   1074   /**
   1075    * Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN
   1076    */
   1077   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1078 
   1079   /**
   1080    * When did the exchange sign this message.
   1081    */
   1082   struct GNUNET_TIME_TimestampNBO timestamp;
   1083 
   1084   /**
   1085    * Hash of the public denomination key we do not know.
   1086    */
   1087   struct TALER_DenominationHashP h_denom_pub;
   1088 };
   1089 
   1090 GNUNET_NETWORK_STRUCT_END
   1091 
   1092 
   1093 enum TALER_ErrorCode
   1094 TALER_exchange_online_denomination_unknown_sign (
   1095   TALER_ExchangeSignCallback scb,
   1096   struct GNUNET_TIME_Timestamp timestamp,
   1097   const struct TALER_DenominationHashP *h_denom_pub,
   1098   struct TALER_ExchangePublicKeyP *pub,
   1099   struct TALER_ExchangeSignatureP *sig)
   1100 {
   1101   struct TALER_DenominationUnknownAffirmationPS dua = {
   1102     .purpose.size = htonl (sizeof (dua)),
   1103     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
   1104     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
   1105     .h_denom_pub = *h_denom_pub,
   1106   };
   1107 
   1108   return scb (&dua.purpose,
   1109               pub,
   1110               sig);
   1111 }
   1112 
   1113 
   1114 enum GNUNET_GenericReturnValue
   1115 TALER_exchange_online_denomination_unknown_verify (
   1116   struct GNUNET_TIME_Timestamp timestamp,
   1117   const struct TALER_DenominationHashP *h_denom_pub,
   1118   const struct TALER_ExchangePublicKeyP *pub,
   1119   const struct TALER_ExchangeSignatureP *sig)
   1120 {
   1121   struct TALER_DenominationUnknownAffirmationPS dua = {
   1122     .purpose.size = htonl (sizeof (dua)),
   1123     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
   1124     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
   1125     .h_denom_pub = *h_denom_pub,
   1126   };
   1127 
   1128   return
   1129     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN,
   1130                                 &dua,
   1131                                 &sig->eddsa_signature,
   1132                                 &pub->eddsa_pub);
   1133 }
   1134 
   1135 
   1136 GNUNET_NETWORK_STRUCT_BEGIN
   1137 
   1138 /**
   1139  * Response by which the exchange affirms that it does not
   1140  * currently consider the given denomination to be valid
   1141  * for the requested operation.
   1142  */
   1143 struct TALER_DenominationExpiredAffirmationPS
   1144 {
   1145 
   1146   /**
   1147    * Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED
   1148    */
   1149   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1150 
   1151   /**
   1152    * When did the exchange sign this message.
   1153    */
   1154   struct GNUNET_TIME_TimestampNBO timestamp;
   1155 
   1156   /**
   1157    * Name of the operation that is not allowed at this time.  Might NOT be 0-terminated, but is padded with 0s.
   1158    */
   1159   char operation[8];
   1160 
   1161   /**
   1162    * Hash of the public denomination key we do not know.
   1163    */
   1164   struct TALER_DenominationHashP h_denom_pub;
   1165 
   1166 };
   1167 
   1168 GNUNET_NETWORK_STRUCT_END
   1169 
   1170 
   1171 enum TALER_ErrorCode
   1172 TALER_exchange_online_denomination_expired_sign (
   1173   TALER_ExchangeSignCallback scb,
   1174   struct GNUNET_TIME_Timestamp timestamp,
   1175   const struct TALER_DenominationHashP *h_denom_pub,
   1176   const char *op,
   1177   struct TALER_ExchangePublicKeyP *pub,
   1178   struct TALER_ExchangeSignatureP *sig)
   1179 {
   1180   struct TALER_DenominationExpiredAffirmationPS dua = {
   1181     .purpose.size = htonl (sizeof (dua)),
   1182     .purpose.purpose = htonl (
   1183       TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED),
   1184     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
   1185     .h_denom_pub = *h_denom_pub,
   1186   };
   1187 
   1188   /* strncpy would create a compiler warning */
   1189   GNUNET_memcpy (dua.operation,
   1190                  op,
   1191                  GNUNET_MIN (sizeof (dua.operation),
   1192                              strlen (op)));
   1193   return scb (&dua.purpose,
   1194               pub,
   1195               sig);
   1196 }
   1197 
   1198 
   1199 enum GNUNET_GenericReturnValue
   1200 TALER_exchange_online_denomination_expired_verify (
   1201   struct GNUNET_TIME_Timestamp timestamp,
   1202   const struct TALER_DenominationHashP *h_denom_pub,
   1203   const char *op,
   1204   const struct TALER_ExchangePublicKeyP *pub,
   1205   const struct TALER_ExchangeSignatureP *sig)
   1206 {
   1207   struct TALER_DenominationExpiredAffirmationPS dua = {
   1208     .purpose.size = htonl (sizeof (dua)),
   1209     .purpose.purpose = htonl (
   1210       TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED),
   1211     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
   1212     .h_denom_pub = *h_denom_pub,
   1213   };
   1214 
   1215   /* strncpy would create a compiler warning */
   1216   GNUNET_memcpy (dua.operation,
   1217                  op,
   1218                  GNUNET_MIN (sizeof (dua.operation),
   1219                              strlen (op)));
   1220   return
   1221     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED,
   1222                                 &dua,
   1223                                 &sig->eddsa_signature,
   1224                                 &pub->eddsa_pub);
   1225 }
   1226 
   1227 
   1228 GNUNET_NETWORK_STRUCT_BEGIN
   1229 
   1230 /**
   1231  * Response by which the exchange affirms that it has
   1232  * closed a reserve and send back the funds.
   1233  */
   1234 struct TALER_ReserveCloseConfirmationPS
   1235 {
   1236 
   1237   /**
   1238    * Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED
   1239    */
   1240   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1241 
   1242   /**
   1243    * When did the exchange initiate the wire transfer.
   1244    */
   1245   struct GNUNET_TIME_TimestampNBO timestamp;
   1246 
   1247   /**
   1248    * How much did the exchange send?
   1249    */
   1250   struct TALER_AmountNBO closing_amount;
   1251 
   1252   /**
   1253    * How much did the exchange charge for closing the reserve?
   1254    */
   1255   struct TALER_AmountNBO closing_fee;
   1256 
   1257   /**
   1258    * Public key of the reserve that was closed.
   1259    */
   1260   struct TALER_ReservePublicKeyP reserve_pub;
   1261 
   1262   /**
   1263    * Hash of the receiver's bank account.
   1264    */
   1265   struct TALER_FullPaytoHashP h_payto;
   1266 
   1267   /**
   1268    * Wire transfer subject.
   1269    */
   1270   struct TALER_WireTransferIdentifierRawP wtid;
   1271 };
   1272 
   1273 GNUNET_NETWORK_STRUCT_END
   1274 
   1275 
   1276 enum TALER_ErrorCode
   1277 TALER_exchange_online_reserve_closed_sign (
   1278   TALER_ExchangeSignCallback scb,
   1279   struct GNUNET_TIME_Timestamp timestamp,
   1280   const struct TALER_Amount *closing_amount,
   1281   const struct TALER_Amount *closing_fee,
   1282   const struct TALER_FullPayto payto,
   1283   const struct TALER_WireTransferIdentifierRawP *wtid,
   1284   const struct TALER_ReservePublicKeyP *reserve_pub,
   1285   struct TALER_ExchangePublicKeyP *pub,
   1286   struct TALER_ExchangeSignatureP *sig)
   1287 {
   1288   struct TALER_ReserveCloseConfirmationPS rcc = {
   1289     .purpose.size = htonl (sizeof (rcc)),
   1290     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED),
   1291     .wtid = *wtid,
   1292     .reserve_pub = *reserve_pub,
   1293     .timestamp = GNUNET_TIME_timestamp_hton (timestamp)
   1294   };
   1295 
   1296   TALER_amount_hton (&rcc.closing_amount,
   1297                      closing_amount);
   1298   TALER_amount_hton (&rcc.closing_fee,
   1299                      closing_fee);
   1300   TALER_full_payto_hash (payto,
   1301                          &rcc.h_payto);
   1302   return scb (&rcc.purpose,
   1303               pub,
   1304               sig);
   1305 }
   1306 
   1307 
   1308 enum GNUNET_GenericReturnValue
   1309 TALER_exchange_online_reserve_closed_verify (
   1310   struct GNUNET_TIME_Timestamp timestamp,
   1311   const struct TALER_Amount *closing_amount,
   1312   const struct TALER_Amount *closing_fee,
   1313   const struct TALER_FullPayto payto,
   1314   const struct TALER_WireTransferIdentifierRawP *wtid,
   1315   const struct TALER_ReservePublicKeyP *reserve_pub,
   1316   const struct TALER_ExchangePublicKeyP *pub,
   1317   const struct TALER_ExchangeSignatureP *sig)
   1318 {
   1319   struct TALER_ReserveCloseConfirmationPS rcc = {
   1320     .purpose.size = htonl (sizeof (rcc)),
   1321     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED),
   1322     .wtid = *wtid,
   1323     .reserve_pub = *reserve_pub,
   1324     .timestamp = GNUNET_TIME_timestamp_hton (timestamp)
   1325   };
   1326 
   1327   TALER_amount_hton (&rcc.closing_amount,
   1328                      closing_amount);
   1329   TALER_amount_hton (&rcc.closing_fee,
   1330                      closing_fee);
   1331   TALER_full_payto_hash (payto,
   1332                          &rcc.h_payto);
   1333   return GNUNET_CRYPTO_eddsa_verify (
   1334     TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED,
   1335     &rcc,
   1336     &sig->eddsa_signature,
   1337     &pub->eddsa_pub);
   1338 }
   1339 
   1340 
   1341 GNUNET_NETWORK_STRUCT_BEGIN
   1342 
   1343 /**
   1344  * Response by which the exchange affirms that it has
   1345  * received funds deposited into a purse.
   1346  */
   1347 struct TALER_PurseCreateDepositConfirmationPS
   1348 {
   1349 
   1350   /**
   1351    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION
   1352    */
   1353   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1354 
   1355   /**
   1356    * When did the exchange receive the deposits.
   1357    */
   1358   struct GNUNET_TIME_TimestampNBO exchange_time;
   1359 
   1360   /**
   1361    * When will the purse expire?
   1362    */
   1363   struct GNUNET_TIME_TimestampNBO purse_expiration;
   1364 
   1365   /**
   1366    * How much should the purse ultimately contain.
   1367    */
   1368   struct TALER_AmountNBO amount_without_fee;
   1369 
   1370   /**
   1371    * How much was deposited so far.
   1372    */
   1373   struct TALER_AmountNBO total_deposited;
   1374 
   1375   /**
   1376    * Public key of the purse.
   1377    */
   1378   struct TALER_PurseContractPublicKeyP purse_pub;
   1379 
   1380   /**
   1381    * Hash of the contract of the purse.
   1382    */
   1383   struct TALER_PrivateContractHashP h_contract_terms;
   1384 
   1385 };
   1386 
   1387 GNUNET_NETWORK_STRUCT_END
   1388 
   1389 
   1390 enum TALER_ErrorCode
   1391 TALER_exchange_online_purse_created_sign (
   1392   TALER_ExchangeSignCallback scb,
   1393   struct GNUNET_TIME_Timestamp exchange_time,
   1394   struct GNUNET_TIME_Timestamp purse_expiration,
   1395   const struct TALER_Amount *amount_without_fee,
   1396   const struct TALER_Amount *total_deposited,
   1397   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1398   const struct TALER_PrivateContractHashP *h_contract_terms,
   1399   struct TALER_ExchangePublicKeyP *pub,
   1400   struct TALER_ExchangeSignatureP *sig)
   1401 {
   1402   struct TALER_PurseCreateDepositConfirmationPS dc = {
   1403     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
   1404     .purpose.size = htonl (sizeof (dc)),
   1405     .h_contract_terms = *h_contract_terms,
   1406     .purse_pub = *purse_pub,
   1407     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1408     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
   1409   };
   1410 
   1411   TALER_amount_hton (&dc.amount_without_fee,
   1412                      amount_without_fee);
   1413   TALER_amount_hton (&dc.total_deposited,
   1414                      total_deposited);
   1415   return scb (&dc.purpose,
   1416               pub,
   1417               sig);
   1418 }
   1419 
   1420 
   1421 enum GNUNET_GenericReturnValue
   1422 TALER_exchange_online_purse_created_verify (
   1423   struct GNUNET_TIME_Timestamp exchange_time,
   1424   struct GNUNET_TIME_Timestamp purse_expiration,
   1425   const struct TALER_Amount *amount_without_fee,
   1426   const struct TALER_Amount *total_deposited,
   1427   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1428   const struct TALER_PrivateContractHashP *h_contract_terms,
   1429   const struct TALER_ExchangePublicKeyP *pub,
   1430   const struct TALER_ExchangeSignatureP *sig)
   1431 {
   1432   struct TALER_PurseCreateDepositConfirmationPS dc = {
   1433     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
   1434     .purpose.size = htonl (sizeof (dc)),
   1435     .h_contract_terms = *h_contract_terms,
   1436     .purse_pub = *purse_pub,
   1437     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1438     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
   1439   };
   1440 
   1441   TALER_amount_hton (&dc.amount_without_fee,
   1442                      amount_without_fee);
   1443   TALER_amount_hton (&dc.total_deposited,
   1444                      total_deposited);
   1445   return GNUNET_CRYPTO_eddsa_verify (
   1446     TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION,
   1447     &dc,
   1448     &sig->eddsa_signature,
   1449     &pub->eddsa_pub);
   1450 }
   1451 
   1452 
   1453 GNUNET_NETWORK_STRUCT_BEGIN
   1454 
   1455 /**
   1456  * Response by which the exchange affirms that it has
   1457  * received funds deposited into a purse.
   1458  */
   1459 struct TALER_CoinPurseRefundConfirmationPS
   1460 {
   1461 
   1462   /**
   1463    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND
   1464    */
   1465   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1466 
   1467   /**
   1468    * Public key of the purse.
   1469    */
   1470   struct TALER_PurseContractPublicKeyP purse_pub;
   1471 
   1472   /**
   1473    * Public key of the coin.
   1474    */
   1475   struct TALER_CoinSpendPublicKeyP coin_pub;
   1476 
   1477   /**
   1478    * How much will be refunded to the purse.
   1479    */
   1480   struct TALER_AmountNBO refunded_amount;
   1481 
   1482   /**
   1483    * How much was the refund fee.
   1484    */
   1485   struct TALER_AmountNBO refund_fee;
   1486 
   1487 };
   1488 
   1489 GNUNET_NETWORK_STRUCT_END
   1490 
   1491 
   1492 enum TALER_ErrorCode
   1493 TALER_exchange_online_purse_refund_sign (
   1494   TALER_ExchangeSignCallback scb,
   1495   const struct TALER_Amount *amount_without_fee,
   1496   const struct TALER_Amount *refund_fee,
   1497   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1498   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1499   struct TALER_ExchangePublicKeyP *pub,
   1500   struct TALER_ExchangeSignatureP *sig)
   1501 {
   1502   struct TALER_CoinPurseRefundConfirmationPS dc = {
   1503     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND),
   1504     .purpose.size = htonl (sizeof (dc)),
   1505     .coin_pub = *coin_pub,
   1506     .purse_pub = *purse_pub,
   1507   };
   1508 
   1509   TALER_amount_hton (&dc.refunded_amount,
   1510                      amount_without_fee);
   1511   TALER_amount_hton (&dc.refund_fee,
   1512                      refund_fee);
   1513   return scb (&dc.purpose,
   1514               pub,
   1515               sig);
   1516 }
   1517 
   1518 
   1519 enum GNUNET_GenericReturnValue
   1520 TALER_exchange_online_purse_refund_verify (
   1521   const struct TALER_Amount *amount_without_fee,
   1522   const struct TALER_Amount *refund_fee,
   1523   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1524   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1525   const struct TALER_ExchangePublicKeyP *pub,
   1526   const struct TALER_ExchangeSignatureP *sig)
   1527 {
   1528   struct TALER_CoinPurseRefundConfirmationPS dc = {
   1529     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND),
   1530     .purpose.size = htonl (sizeof (dc)),
   1531     .coin_pub = *coin_pub,
   1532     .purse_pub = *purse_pub,
   1533   };
   1534 
   1535   TALER_amount_hton (&dc.refunded_amount,
   1536                      amount_without_fee);
   1537   TALER_amount_hton (&dc.refund_fee,
   1538                      refund_fee);
   1539   return GNUNET_CRYPTO_eddsa_verify (
   1540     TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND,
   1541     &dc,
   1542     &sig->eddsa_signature,
   1543     &pub->eddsa_pub);
   1544 }
   1545 
   1546 
   1547 GNUNET_NETWORK_STRUCT_BEGIN
   1548 
   1549 /**
   1550  * Response by which the exchange affirms that it has
   1551  * merged a purse into a reserve.
   1552  */
   1553 struct TALER_PurseMergedConfirmationPS
   1554 {
   1555 
   1556   /**
   1557    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED
   1558    */
   1559   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1560 
   1561   /**
   1562    * When did the exchange receive the deposits.
   1563    */
   1564   struct GNUNET_TIME_TimestampNBO exchange_time;
   1565 
   1566   /**
   1567    * When will the purse expire?
   1568    */
   1569   struct GNUNET_TIME_TimestampNBO purse_expiration;
   1570 
   1571   /**
   1572    * How much should the purse ultimately contain.
   1573    */
   1574   struct TALER_AmountNBO amount_without_fee;
   1575 
   1576   /**
   1577    * Public key of the purse.
   1578    */
   1579   struct TALER_PurseContractPublicKeyP purse_pub;
   1580 
   1581   /**
   1582    * Public key of the reserve.
   1583    */
   1584   struct TALER_ReservePublicKeyP reserve_pub;
   1585 
   1586   /**
   1587    * Hash of the contract of the purse.
   1588    */
   1589   struct TALER_PrivateContractHashP h_contract_terms;
   1590 
   1591   /**
   1592    * Hash of the provider URL hosting the reserve.
   1593    */
   1594   struct GNUNET_HashCode h_provider_url;
   1595 
   1596 };
   1597 
   1598 GNUNET_NETWORK_STRUCT_END
   1599 
   1600 
   1601 enum TALER_ErrorCode
   1602 TALER_exchange_online_purse_merged_sign (
   1603   TALER_ExchangeSignCallback scb,
   1604   struct GNUNET_TIME_Timestamp exchange_time,
   1605   struct GNUNET_TIME_Timestamp purse_expiration,
   1606   const struct TALER_Amount *amount_without_fee,
   1607   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1608   const struct TALER_PrivateContractHashP *h_contract_terms,
   1609   const struct TALER_ReservePublicKeyP *reserve_pub,
   1610   const char *exchange_url,
   1611   struct TALER_ExchangePublicKeyP *pub,
   1612   struct TALER_ExchangeSignatureP *sig)
   1613 {
   1614   struct TALER_PurseMergedConfirmationPS dc = {
   1615     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED),
   1616     .purpose.size = htonl (sizeof (dc)),
   1617     .h_contract_terms = *h_contract_terms,
   1618     .purse_pub = *purse_pub,
   1619     .reserve_pub = *reserve_pub,
   1620     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1621     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
   1622   };
   1623 
   1624   TALER_amount_hton (&dc.amount_without_fee,
   1625                      amount_without_fee);
   1626   GNUNET_CRYPTO_hash (exchange_url,
   1627                       strlen (exchange_url) + 1,
   1628                       &dc.h_provider_url);
   1629   return scb (&dc.purpose,
   1630               pub,
   1631               sig);
   1632 }
   1633 
   1634 
   1635 enum GNUNET_GenericReturnValue
   1636 TALER_exchange_online_purse_merged_verify (
   1637   struct GNUNET_TIME_Timestamp exchange_time,
   1638   struct GNUNET_TIME_Timestamp purse_expiration,
   1639   const struct TALER_Amount *amount_without_fee,
   1640   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1641   const struct TALER_PrivateContractHashP *h_contract_terms,
   1642   const struct TALER_ReservePublicKeyP *reserve_pub,
   1643   const char *exchange_url,
   1644   const struct TALER_ExchangePublicKeyP *pub,
   1645   const struct TALER_ExchangeSignatureP *sig)
   1646 {
   1647   struct TALER_PurseMergedConfirmationPS dc = {
   1648     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED),
   1649     .purpose.size = htonl (sizeof (dc)),
   1650     .h_contract_terms = *h_contract_terms,
   1651     .purse_pub = *purse_pub,
   1652     .reserve_pub = *reserve_pub,
   1653     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1654     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
   1655   };
   1656 
   1657   TALER_amount_hton (&dc.amount_without_fee,
   1658                      amount_without_fee);
   1659   GNUNET_CRYPTO_hash (exchange_url,
   1660                       strlen (exchange_url) + 1,
   1661                       &dc.h_provider_url);
   1662   return
   1663     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED,
   1664                                 &dc,
   1665                                 &sig->eddsa_signature,
   1666                                 &pub->eddsa_pub);
   1667 }
   1668 
   1669 
   1670 GNUNET_NETWORK_STRUCT_BEGIN
   1671 
   1672 /**
   1673  * @brief Format used to generate the signature on a purse status
   1674  * from the exchange.
   1675  */
   1676 struct TALER_PurseStatusPS
   1677 {
   1678   /**
   1679    * Purpose must be #TALER_SIGNATURE_EXCHANGE_PURSE_STATUS.  Signed
   1680    * by a `struct TALER_ExchangePublicKeyP` using EdDSA.
   1681    */
   1682   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1683 
   1684   /**
   1685    * Time when the purse was merged, possibly 'never'.
   1686    */
   1687   struct GNUNET_TIME_TimestampNBO merge_timestamp;
   1688 
   1689   /**
   1690    * Time when the purse was deposited last, possibly 'never'.
   1691    */
   1692   struct GNUNET_TIME_TimestampNBO deposit_timestamp;
   1693 
   1694   /**
   1695    * Amount deposited in total in the purse without fees.
   1696    * May be possibly less than the target amount.
   1697    */
   1698   struct TALER_AmountNBO balance;
   1699 
   1700 };
   1701 
   1702 GNUNET_NETWORK_STRUCT_END
   1703 
   1704 
   1705 enum TALER_ErrorCode
   1706 TALER_exchange_online_purse_status_sign (
   1707   TALER_ExchangeSignCallback scb,
   1708   struct GNUNET_TIME_Timestamp merge_timestamp,
   1709   struct GNUNET_TIME_Timestamp deposit_timestamp,
   1710   const struct TALER_Amount *balance,
   1711   struct TALER_ExchangePublicKeyP *pub,
   1712   struct TALER_ExchangeSignatureP *sig)
   1713 {
   1714   struct TALER_PurseStatusPS dcs = {
   1715     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS),
   1716     .purpose.size = htonl (sizeof (dcs)),
   1717     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1718     .deposit_timestamp = GNUNET_TIME_timestamp_hton (deposit_timestamp)
   1719   };
   1720 
   1721   TALER_amount_hton (&dcs.balance,
   1722                      balance);
   1723   return scb (&dcs.purpose,
   1724               pub,
   1725               sig);
   1726 }
   1727 
   1728 
   1729 enum GNUNET_GenericReturnValue
   1730 TALER_exchange_online_purse_status_verify (
   1731   struct GNUNET_TIME_Timestamp merge_timestamp,
   1732   struct GNUNET_TIME_Timestamp deposit_timestamp,
   1733   const struct TALER_Amount *balance,
   1734   const struct TALER_ExchangePublicKeyP *exchange_pub,
   1735   const struct TALER_ExchangeSignatureP *exchange_sig)
   1736 {
   1737   struct TALER_PurseStatusPS dcs = {
   1738     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS),
   1739     .purpose.size = htonl (sizeof (dcs)),
   1740     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1741     .deposit_timestamp = GNUNET_TIME_timestamp_hton (deposit_timestamp)
   1742   };
   1743 
   1744   TALER_amount_hton (&dcs.balance,
   1745                      balance);
   1746   if (GNUNET_OK !=
   1747       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS,
   1748                                   &dcs,
   1749                                   &exchange_sig->eddsa_signature,
   1750                                   &exchange_pub->eddsa_pub))
   1751   {
   1752     GNUNET_break_op (0);
   1753     return GNUNET_SYSERR;
   1754   }
   1755   return GNUNET_OK;
   1756 }
   1757 
   1758 
   1759 GNUNET_NETWORK_STRUCT_BEGIN
   1760 
   1761 /**
   1762  * Message signed by the exchange to affirm that the
   1763  * owner of a reserve has certain attributes.
   1764  */
   1765 struct TALER_ExchangeAttestPS
   1766 {
   1767 
   1768   /**
   1769    * Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS
   1770    */
   1771   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1772 
   1773   /**
   1774    * Time when the attestation was made.
   1775    */
   1776   struct GNUNET_TIME_TimestampNBO attest_timestamp;
   1777 
   1778   /**
   1779    * Time when the attestation expires.
   1780    */
   1781   struct GNUNET_TIME_TimestampNBO expiration_time;
   1782 
   1783   /**
   1784    * Public key of the reserve for which the attributes
   1785    * are attested.
   1786    */
   1787   struct TALER_ReservePublicKeyP reserve_pub;
   1788 
   1789   /**
   1790    * Hash over the attributes.
   1791    */
   1792   struct GNUNET_HashCode h_attributes;
   1793 
   1794 };
   1795 
   1796 GNUNET_NETWORK_STRUCT_END
   1797 
   1798 
   1799 enum TALER_ErrorCode
   1800 TALER_exchange_online_reserve_attest_details_sign (
   1801   TALER_ExchangeSignCallback scb,
   1802   struct GNUNET_TIME_Timestamp attest_timestamp,
   1803   struct GNUNET_TIME_Timestamp expiration_time,
   1804   const struct TALER_ReservePublicKeyP *reserve_pub,
   1805   const json_t *attributes,
   1806   struct TALER_ExchangePublicKeyP *pub,
   1807   struct TALER_ExchangeSignatureP *sig)
   1808 {
   1809   struct TALER_ExchangeAttestPS rap = {
   1810     .purpose.size = htonl (sizeof (rap)),
   1811     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS),
   1812     .attest_timestamp = GNUNET_TIME_timestamp_hton (attest_timestamp),
   1813     .expiration_time = GNUNET_TIME_timestamp_hton (expiration_time),
   1814     .reserve_pub = *reserve_pub
   1815   };
   1816 
   1817   TALER_json_hash (attributes,
   1818                    &rap.h_attributes);
   1819   return scb (&rap.purpose,
   1820               pub,
   1821               sig);
   1822 }
   1823 
   1824 
   1825 enum GNUNET_GenericReturnValue
   1826 TALER_exchange_online_reserve_attest_details_verify (
   1827   struct GNUNET_TIME_Timestamp attest_timestamp,
   1828   struct GNUNET_TIME_Timestamp expiration_time,
   1829   const struct TALER_ReservePublicKeyP *reserve_pub,
   1830   const json_t *attributes,
   1831   struct TALER_ExchangePublicKeyP *pub,
   1832   struct TALER_ExchangeSignatureP *sig)
   1833 {
   1834   struct TALER_ExchangeAttestPS rap = {
   1835     .purpose.size = htonl (sizeof (rap)),
   1836     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS),
   1837     .attest_timestamp = GNUNET_TIME_timestamp_hton (attest_timestamp),
   1838     .expiration_time = GNUNET_TIME_timestamp_hton (expiration_time),
   1839     .reserve_pub = *reserve_pub
   1840   };
   1841 
   1842   TALER_json_hash (attributes,
   1843                    &rap.h_attributes);
   1844   if (GNUNET_OK !=
   1845       GNUNET_CRYPTO_eddsa_verify (
   1846         TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS,
   1847         &rap,
   1848         &sig->eddsa_signature,
   1849         &pub->eddsa_pub))
   1850   {
   1851     GNUNET_break_op (0);
   1852     return GNUNET_SYSERR;
   1853   }
   1854   return GNUNET_OK;
   1855 }
   1856 
   1857 
   1858 /* end of exchange_signatures.c */