LCOV - code coverage report
Current view: top level - util - exchange_signatures.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 0 248 0.0 %
Date: 2022-08-25 06:15:09 Functions: 0 31 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2021, 2022 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 "platform.h"
      22             : #include "taler_util.h"
      23             : #include "taler_signatures.h"
      24             : 
      25             : 
      26             : GNUNET_NETWORK_STRUCT_BEGIN
      27             : 
      28             : /**
      29             :  * @brief Format used to generate the signature on a confirmation
      30             :  * from the exchange that a deposit request succeeded.
      31             :  */
      32             : struct TALER_DepositConfirmationPS
      33             : {
      34             :   /**
      35             :    * Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT.  Signed
      36             :    * by a `struct TALER_ExchangePublicKeyP` using EdDSA.
      37             :    */
      38             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
      39             : 
      40             :   /**
      41             :    * Hash over the contract for which this deposit is made.
      42             :    */
      43             :   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
      44             : 
      45             :   /**
      46             :    * Hash over the wiring information of the merchant.
      47             :    */
      48             :   struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
      49             : 
      50             :   /**
      51             :    * Hash over the extension options of the deposit, 0 if there
      52             :    * were not extension options.
      53             :    */
      54             :   struct TALER_ExtensionContractHashP h_extensions GNUNET_PACKED;
      55             : 
      56             :   /**
      57             :    * Time when this confirmation was generated / when the exchange received
      58             :    * the deposit request.
      59             :    */
      60             :   struct GNUNET_TIME_TimestampNBO exchange_timestamp;
      61             : 
      62             :   /**
      63             :    * By when does the exchange expect to pay the merchant
      64             :    * (as per the merchant's request).
      65             :    */
      66             :   struct GNUNET_TIME_TimestampNBO wire_deadline;
      67             : 
      68             :   /**
      69             :    * How much time does the @e merchant have to issue a refund
      70             :    * request?  Zero if refunds are not allowed.  After this time, the
      71             :    * coin cannot be refunded.  Note that the wire transfer will not be
      72             :    * performed by the exchange until the refund deadline.  This value
      73             :    * is taken from the original deposit request.
      74             :    */
      75             :   struct GNUNET_TIME_TimestampNBO refund_deadline;
      76             : 
      77             :   /**
      78             :    * Amount to be deposited, excluding fee.  Calculated from the
      79             :    * amount with fee and the fee from the deposit request.
      80             :    */
      81             :   struct TALER_AmountNBO amount_without_fee;
      82             : 
      83             :   /**
      84             :    * The public key of the coin that was deposited.
      85             :    */
      86             :   struct TALER_CoinSpendPublicKeyP coin_pub;
      87             : 
      88             :   /**
      89             :    * The Merchant's public key.  Allows the merchant to later refund
      90             :    * the transaction or to inquire about the wire transfer identifier.
      91             :    */
      92             :   struct TALER_MerchantPublicKeyP merchant_pub;
      93             : 
      94             : };
      95             : 
      96             : GNUNET_NETWORK_STRUCT_END
      97             : 
      98             : 
      99             : enum TALER_ErrorCode
     100           0 : TALER_exchange_online_deposit_confirmation_sign (
     101             :   TALER_ExchangeSignCallback scb,
     102             :   const struct TALER_PrivateContractHashP *h_contract_terms,
     103             :   const struct TALER_MerchantWireHashP *h_wire,
     104             :   const struct TALER_ExtensionContractHashP *h_extensions,
     105             :   struct GNUNET_TIME_Timestamp exchange_timestamp,
     106             :   struct GNUNET_TIME_Timestamp wire_deadline,
     107             :   struct GNUNET_TIME_Timestamp refund_deadline,
     108             :   const struct TALER_Amount *amount_without_fee,
     109             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     110             :   const struct TALER_MerchantPublicKeyP *merchant_pub,
     111             :   struct TALER_ExchangePublicKeyP *pub,
     112             :   struct TALER_ExchangeSignatureP *sig)
     113             : {
     114           0 :   struct TALER_DepositConfirmationPS dcs = {
     115           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
     116           0 :     .purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
     117             :     .h_contract_terms = *h_contract_terms,
     118             :     .h_wire = *h_wire,
     119           0 :     .exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
     120           0 :     .wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
     121           0 :     .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
     122             :     .coin_pub = *coin_pub,
     123             :     .merchant_pub = *merchant_pub
     124             :   };
     125             : 
     126           0 :   if (NULL != h_extensions)
     127           0 :     dcs.h_extensions = *h_extensions;
     128           0 :   TALER_amount_hton (&dcs.amount_without_fee,
     129             :                      amount_without_fee);
     130           0 :   return scb (&dcs.purpose,
     131             :               pub,
     132             :               sig);
     133             : }
     134             : 
     135             : 
     136             : enum GNUNET_GenericReturnValue
     137           0 : TALER_exchange_online_deposit_confirmation_verify (
     138             :   const struct TALER_PrivateContractHashP *h_contract_terms,
     139             :   const struct TALER_MerchantWireHashP *h_wire,
     140             :   const struct TALER_ExtensionContractHashP *h_extensions,
     141             :   struct GNUNET_TIME_Timestamp exchange_timestamp,
     142             :   struct GNUNET_TIME_Timestamp wire_deadline,
     143             :   struct GNUNET_TIME_Timestamp refund_deadline,
     144             :   const struct TALER_Amount *amount_without_fee,
     145             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     146             :   const struct TALER_MerchantPublicKeyP *merchant_pub,
     147             :   const struct TALER_ExchangePublicKeyP *exchange_pub,
     148             :   const struct TALER_ExchangeSignatureP *exchange_sig)
     149             : {
     150           0 :   struct TALER_DepositConfirmationPS dcs = {
     151           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT),
     152           0 :     .purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
     153             :     .h_contract_terms = *h_contract_terms,
     154             :     .h_wire = *h_wire,
     155           0 :     .exchange_timestamp = GNUNET_TIME_timestamp_hton (exchange_timestamp),
     156           0 :     .wire_deadline = GNUNET_TIME_timestamp_hton (wire_deadline),
     157           0 :     .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
     158             :     .coin_pub = *coin_pub,
     159             :     .merchant_pub = *merchant_pub
     160             :   };
     161             : 
     162           0 :   if (NULL != h_extensions)
     163           0 :     dcs.h_extensions = *h_extensions;
     164           0 :   TALER_amount_hton (&dcs.amount_without_fee,
     165             :                      amount_without_fee);
     166           0 :   if (GNUNET_OK !=
     167           0 :       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT,
     168             :                                   &dcs,
     169             :                                   &exchange_sig->eddsa_signature,
     170             :                                   &exchange_pub->eddsa_pub))
     171             :   {
     172           0 :     GNUNET_break_op (0);
     173           0 :     return GNUNET_SYSERR;
     174             :   }
     175           0 :   return GNUNET_OK;
     176             : }
     177             : 
     178             : 
     179             : GNUNET_NETWORK_STRUCT_BEGIN
     180             : 
     181             : /**
     182             :  * @brief Format used to generate the signature on a request to refund
     183             :  * a coin into the account of the customer.
     184             :  */
     185             : struct TALER_RefundConfirmationPS
     186             : {
     187             :   /**
     188             :    * Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND.
     189             :    */
     190             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
     191             : 
     192             :   /**
     193             :    * Hash over the proposal data to identify the contract
     194             :    * which is being refunded.
     195             :    */
     196             :   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
     197             : 
     198             :   /**
     199             :    * The coin's public key.  This is the value that must have been
     200             :    * signed (blindly) by the Exchange.
     201             :    */
     202             :   struct TALER_CoinSpendPublicKeyP coin_pub;
     203             : 
     204             :   /**
     205             :    * The Merchant's public key.  Allows the merchant to later refund
     206             :    * the transaction or to inquire about the wire transfer identifier.
     207             :    */
     208             :   struct TALER_MerchantPublicKeyP merchant;
     209             : 
     210             :   /**
     211             :    * Merchant-generated transaction ID for the refund.
     212             :    */
     213             :   uint64_t rtransaction_id GNUNET_PACKED;
     214             : 
     215             :   /**
     216             :    * Amount to be refunded, including refund fee charged by the
     217             :    * exchange to the customer.
     218             :    */
     219             :   struct TALER_AmountNBO refund_amount;
     220             : };
     221             : 
     222             : GNUNET_NETWORK_STRUCT_END
     223             : 
     224             : 
     225             : enum TALER_ErrorCode
     226           0 : TALER_exchange_online_refund_confirmation_sign (
     227             :   TALER_ExchangeSignCallback scb,
     228             :   const struct TALER_PrivateContractHashP *h_contract_terms,
     229             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     230             :   const struct TALER_MerchantPublicKeyP *merchant,
     231             :   uint64_t rtransaction_id,
     232             :   const struct TALER_Amount *refund_amount,
     233             :   struct TALER_ExchangePublicKeyP *pub,
     234             :   struct TALER_ExchangeSignatureP *sig)
     235             : {
     236           0 :   struct TALER_RefundConfirmationPS rc = {
     237           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND),
     238           0 :     .purpose.size = htonl (sizeof (rc)),
     239             :     .h_contract_terms = *h_contract_terms,
     240             :     .coin_pub = *coin_pub,
     241             :     .merchant = *merchant,
     242           0 :     .rtransaction_id = GNUNET_htonll (rtransaction_id)
     243             :   };
     244             : 
     245           0 :   TALER_amount_hton (&rc.refund_amount,
     246             :                      refund_amount);
     247           0 :   return scb (&rc.purpose,
     248             :               pub,
     249             :               sig);
     250             : }
     251             : 
     252             : 
     253             : enum GNUNET_GenericReturnValue
     254           0 : TALER_exchange_online_refund_confirmation_verify (
     255             :   const struct TALER_PrivateContractHashP *h_contract_terms,
     256             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     257             :   const struct TALER_MerchantPublicKeyP *merchant,
     258             :   uint64_t rtransaction_id,
     259             :   const struct TALER_Amount *refund_amount,
     260             :   const struct TALER_ExchangePublicKeyP *pub,
     261             :   const struct TALER_ExchangeSignatureP *sig)
     262             : {
     263           0 :   struct TALER_RefundConfirmationPS rc = {
     264           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND),
     265           0 :     .purpose.size = htonl (sizeof (rc)),
     266             :     .h_contract_terms = *h_contract_terms,
     267             :     .coin_pub = *coin_pub,
     268             :     .merchant = *merchant,
     269           0 :     .rtransaction_id = GNUNET_htonll (rtransaction_id)
     270             :   };
     271             : 
     272           0 :   TALER_amount_hton (&rc.refund_amount,
     273             :                      refund_amount);
     274           0 :   if (GNUNET_OK !=
     275           0 :       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND,
     276             :                                   &rc,
     277             :                                   &sig->eddsa_signature,
     278             :                                   &pub->eddsa_pub))
     279             :   {
     280           0 :     GNUNET_break_op (0);
     281           0 :     return GNUNET_SYSERR;
     282             :   }
     283           0 :   return GNUNET_OK;
     284             : }
     285             : 
     286             : 
     287             : GNUNET_NETWORK_STRUCT_BEGIN
     288             : 
     289             : /**
     290             :  * @brief Format of the block signed by the Exchange in response to a successful
     291             :  * "/refresh/melt" request.  Hereby the exchange affirms that all of the
     292             :  * coins were successfully melted.  This also commits the exchange to a
     293             :  * particular index to not be revealed during the refresh.
     294             :  */
     295             : struct TALER_RefreshMeltConfirmationPS
     296             : {
     297             :   /**
     298             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT.   Signed
     299             :    * by a `struct TALER_ExchangePublicKeyP` using EdDSA.
     300             :    */
     301             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
     302             : 
     303             :   /**
     304             :    * Commitment made in the /refresh/melt.
     305             :    */
     306             :   struct TALER_RefreshCommitmentP rc GNUNET_PACKED;
     307             : 
     308             :   /**
     309             :    * Index that the client will not have to reveal, in NBO.
     310             :    * Must be smaller than #TALER_CNC_KAPPA.
     311             :    */
     312             :   uint32_t noreveal_index GNUNET_PACKED;
     313             : 
     314             : };
     315             : 
     316             : GNUNET_NETWORK_STRUCT_END
     317             : 
     318             : 
     319             : enum TALER_ErrorCode
     320           0 : TALER_exchange_online_melt_confirmation_sign (
     321             :   TALER_ExchangeSignCallback scb,
     322             :   const struct TALER_RefreshCommitmentP *rc,
     323             :   uint32_t noreveal_index,
     324             :   struct TALER_ExchangePublicKeyP *pub,
     325             :   struct TALER_ExchangeSignatureP *sig)
     326             : {
     327           0 :   struct TALER_RefreshMeltConfirmationPS confirm = {
     328           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
     329           0 :     .purpose.size = htonl (sizeof (confirm)),
     330             :     .rc = *rc,
     331           0 :     .noreveal_index = htonl (noreveal_index)
     332             :   };
     333             : 
     334           0 :   return scb (&confirm.purpose,
     335             :               pub,
     336             :               sig);
     337             : }
     338             : 
     339             : 
     340             : enum GNUNET_GenericReturnValue
     341           0 : TALER_exchange_online_melt_confirmation_verify (
     342             :   const struct TALER_RefreshCommitmentP *rc,
     343             :   uint32_t noreveal_index,
     344             :   const struct TALER_ExchangePublicKeyP *exchange_pub,
     345             :   const struct TALER_ExchangeSignatureP *exchange_sig)
     346             : {
     347           0 :   struct TALER_RefreshMeltConfirmationPS confirm = {
     348           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT),
     349           0 :     .purpose.size = htonl (sizeof (confirm)),
     350             :     .rc = *rc,
     351           0 :     .noreveal_index = htonl (noreveal_index)
     352             :   };
     353             : 
     354             :   return
     355           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT,
     356             :                                 &confirm,
     357             :                                 &exchange_sig->eddsa_signature,
     358             :                                 &exchange_pub->eddsa_pub);
     359             : }
     360             : 
     361             : 
     362             : GNUNET_NETWORK_STRUCT_BEGIN
     363             : 
     364             : /**
     365             :  * @brief Signature made by the exchange over the full set of keys, used
     366             :  * to detect cheating exchanges that give out different sets to
     367             :  * different users.
     368             :  */
     369             : struct TALER_ExchangeKeySetPS
     370             : {
     371             : 
     372             :   /**
     373             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_KEY_SET.   Signed
     374             :    * by a `struct TALER_ExchangePublicKeyP` using EdDSA.
     375             :    */
     376             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
     377             : 
     378             :   /**
     379             :    * Time of the key set issue.
     380             :    */
     381             :   struct GNUNET_TIME_TimestampNBO list_issue_date;
     382             : 
     383             :   /**
     384             :    * Hash over the various denomination signing keys returned.
     385             :    */
     386             :   struct GNUNET_HashCode hc GNUNET_PACKED;
     387             : };
     388             : 
     389             : GNUNET_NETWORK_STRUCT_END
     390             : 
     391             : 
     392             : enum TALER_ErrorCode
     393           0 : TALER_exchange_online_key_set_sign (
     394             :   TALER_ExchangeSignCallback2 scb,
     395             :   void *cls,
     396             :   struct GNUNET_TIME_Timestamp timestamp,
     397             :   const struct GNUNET_HashCode *hc,
     398             :   struct TALER_ExchangePublicKeyP *pub,
     399             :   struct TALER_ExchangeSignatureP *sig)
     400             : {
     401           0 :   struct TALER_ExchangeKeySetPS ks = {
     402           0 :     .purpose.size = htonl (sizeof (ks)),
     403           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET),
     404           0 :     .list_issue_date = GNUNET_TIME_timestamp_hton (timestamp),
     405             :     .hc = *hc
     406             :   };
     407             : 
     408           0 :   return scb (cls,
     409             :               &ks.purpose,
     410             :               pub,
     411             :               sig);
     412             : }
     413             : 
     414             : 
     415             : enum GNUNET_GenericReturnValue
     416           0 : TALER_exchange_online_key_set_verify (
     417             :   struct GNUNET_TIME_Timestamp timestamp,
     418             :   const struct GNUNET_HashCode *hc,
     419             :   const struct TALER_ExchangePublicKeyP *pub,
     420             :   const struct TALER_ExchangeSignatureP *sig)
     421             : {
     422           0 :   struct TALER_ExchangeKeySetPS ks = {
     423           0 :     .purpose.size = htonl (sizeof (ks)),
     424           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_KEY_SET),
     425           0 :     .list_issue_date = GNUNET_TIME_timestamp_hton (timestamp),
     426             :     .hc = *hc
     427             :   };
     428             : 
     429             :   return
     430           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_KEY_SET,
     431             :                                 &ks,
     432             :                                 &sig->eddsa_signature,
     433             :                                 &pub->eddsa_pub);
     434             : }
     435             : 
     436             : 
     437             : GNUNET_NETWORK_STRUCT_BEGIN
     438             : 
     439             : /**
     440             :  * @brief Signature by which an exchange affirms that an account
     441             :  * successfully passed the KYC checks.
     442             :  */
     443             : struct TALER_ExchangeAccountSetupSuccessPS
     444             : {
     445             :   /**
     446             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS.  Signed by a
     447             :    * `struct TALER_ExchangePublicKeyP` using EdDSA.
     448             :    */
     449             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
     450             : 
     451             :   /**
     452             :    * Hash over the payto for which the signature was
     453             :    * made.
     454             :    */
     455             :   struct TALER_PaytoHashP h_payto;
     456             : 
     457             :   // FIXME: include details on *which* KYC process
     458             :   // was satisfied!
     459             : 
     460             :   /**
     461             :    * When was the signature made.
     462             :    * FIXME: replace by *expiration* time!
     463             :    */
     464             :   struct GNUNET_TIME_TimestampNBO timestamp;
     465             : };
     466             : 
     467             : GNUNET_NETWORK_STRUCT_END
     468             : 
     469             : 
     470             : enum TALER_ErrorCode
     471           0 : TALER_exchange_online_account_setup_success_sign (
     472             :   TALER_ExchangeSignCallback scb,
     473             :   const struct TALER_PaytoHashP *h_payto,
     474             :   struct GNUNET_TIME_Timestamp timestamp,
     475             :   struct TALER_ExchangePublicKeyP *pub,
     476             :   struct TALER_ExchangeSignatureP *sig)
     477             : {
     478           0 :   struct TALER_ExchangeAccountSetupSuccessPS kyc_purpose = {
     479           0 :     .purpose.size = htonl (sizeof (kyc_purpose)),
     480           0 :     .purpose.purpose = htonl (
     481             :       TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
     482             :     .h_payto = *h_payto,
     483           0 :     .timestamp = GNUNET_TIME_timestamp_hton (
     484             :       timestamp)
     485             :   };
     486             : 
     487           0 :   return scb (&kyc_purpose.purpose,
     488             :               pub,
     489             :               sig);
     490             : }
     491             : 
     492             : 
     493             : enum GNUNET_GenericReturnValue
     494           0 : TALER_exchange_online_account_setup_success_verify (
     495             :   const struct TALER_PaytoHashP *h_payto,
     496             :   struct GNUNET_TIME_Timestamp timestamp,
     497             :   const struct TALER_ExchangePublicKeyP *pub,
     498             :   const struct TALER_ExchangeSignatureP *sig)
     499             : {
     500           0 :   struct TALER_ExchangeAccountSetupSuccessPS kyc_purpose = {
     501           0 :     .purpose.size = htonl (sizeof (kyc_purpose)),
     502           0 :     .purpose.purpose = htonl (
     503             :       TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS),
     504             :     .h_payto = *h_payto,
     505           0 :     .timestamp = GNUNET_TIME_timestamp_hton (
     506             :       timestamp)
     507             :   };
     508             : 
     509             :   return
     510           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS,
     511             :                                 &kyc_purpose,
     512             :                                 &sig->eddsa_signature,
     513             :                                 &pub->eddsa_pub);
     514             : }
     515             : 
     516             : 
     517             : GNUNET_NETWORK_STRUCT_BEGIN
     518             : 
     519             : /**
     520             :  * @brief Format internally used for packing the detailed information
     521             :  * to generate the signature for /track/transfer signatures.
     522             :  */
     523             : struct TALER_WireDepositDetailP
     524             : {
     525             : 
     526             :   /**
     527             :    * Hash of the contract
     528             :    */
     529             :   struct TALER_PrivateContractHashP h_contract_terms;
     530             : 
     531             :   /**
     532             :    * Time when the wire transfer was performed by the exchange.
     533             :    */
     534             :   struct GNUNET_TIME_TimestampNBO execution_time;
     535             : 
     536             :   /**
     537             :    * Coin's public key.
     538             :    */
     539             :   struct TALER_CoinSpendPublicKeyP coin_pub;
     540             : 
     541             :   /**
     542             :    * Total value of the coin.
     543             :    */
     544             :   struct TALER_AmountNBO deposit_value;
     545             : 
     546             :   /**
     547             :    * Fees charged by the exchange for the deposit.
     548             :    */
     549             :   struct TALER_AmountNBO deposit_fee;
     550             : 
     551             : };
     552             : 
     553             : GNUNET_NETWORK_STRUCT_END
     554             : 
     555             : 
     556             : void
     557           0 : TALER_exchange_online_wire_deposit_append (
     558             :   struct GNUNET_HashContext *hash_context,
     559             :   const struct TALER_PrivateContractHashP *h_contract_terms,
     560             :   struct GNUNET_TIME_Timestamp execution_time,
     561             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     562             :   const struct TALER_Amount *deposit_value,
     563             :   const struct TALER_Amount *deposit_fee)
     564             : {
     565           0 :   struct TALER_WireDepositDetailP dd = {
     566             :     .h_contract_terms = *h_contract_terms,
     567           0 :     .execution_time = GNUNET_TIME_timestamp_hton (execution_time),
     568             :     .coin_pub = *coin_pub
     569             :   };
     570           0 :   TALER_amount_hton (&dd.deposit_value,
     571             :                      deposit_value);
     572           0 :   TALER_amount_hton (&dd.deposit_fee,
     573             :                      deposit_fee);
     574           0 :   GNUNET_CRYPTO_hash_context_read (hash_context,
     575             :                                    &dd,
     576             :                                    sizeof (dd));
     577           0 : }
     578             : 
     579             : 
     580             : GNUNET_NETWORK_STRUCT_BEGIN
     581             : 
     582             : /**
     583             :  * @brief Format used to generate the signature for /wire/deposit
     584             :  * replies.
     585             :  */
     586             : struct TALER_WireDepositDataPS
     587             : {
     588             :   /**
     589             :    * Purpose header for the signature over the contract with
     590             :    * purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT.
     591             :    */
     592             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
     593             : 
     594             :   /**
     595             :    * Total amount that was transferred.
     596             :    */
     597             :   struct TALER_AmountNBO total;
     598             : 
     599             :   /**
     600             :    * Wire fee that was charged.
     601             :    */
     602             :   struct TALER_AmountNBO wire_fee;
     603             : 
     604             :   /**
     605             :    * Public key of the merchant (for all aggregated transactions).
     606             :    */
     607             :   struct TALER_MerchantPublicKeyP merchant_pub;
     608             : 
     609             :   /**
     610             :    * Hash of bank account of the merchant.
     611             :    */
     612             :   struct TALER_PaytoHashP h_payto;
     613             : 
     614             :   /**
     615             :    * Hash of the individual deposits that were aggregated,
     616             :    * each in the format of a `struct TALER_WireDepositDetailP`.
     617             :    */
     618             :   struct GNUNET_HashCode h_details;
     619             : 
     620             : };
     621             : 
     622             : GNUNET_NETWORK_STRUCT_END
     623             : 
     624             : 
     625             : enum TALER_ErrorCode
     626           0 : TALER_exchange_online_wire_deposit_sign (
     627             :   TALER_ExchangeSignCallback scb,
     628             :   const struct TALER_Amount *total,
     629             :   const struct TALER_Amount *wire_fee,
     630             :   const struct TALER_MerchantPublicKeyP *merchant_pub,
     631             :   const char *payto,
     632             :   const struct GNUNET_HashCode *h_details,
     633             :   struct TALER_ExchangePublicKeyP *pub,
     634             :   struct TALER_ExchangeSignatureP *sig)
     635             : {
     636           0 :   struct TALER_WireDepositDataPS wdp = {
     637           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
     638           0 :     .purpose.size = htonl (sizeof (wdp)),
     639             :     .merchant_pub = *merchant_pub,
     640             :     .h_details = *h_details
     641             :   };
     642             : 
     643           0 :   TALER_amount_hton (&wdp.total,
     644             :                      total);
     645           0 :   TALER_amount_hton (&wdp.wire_fee,
     646             :                      wire_fee);
     647           0 :   TALER_payto_hash (payto,
     648             :                     &wdp.h_payto);
     649           0 :   return scb (&wdp.purpose,
     650             :               pub,
     651             :               sig);
     652             : }
     653             : 
     654             : 
     655             : enum GNUNET_GenericReturnValue
     656           0 : TALER_exchange_online_wire_deposit_verify (
     657             :   const struct TALER_Amount *total,
     658             :   const struct TALER_Amount *wire_fee,
     659             :   const struct TALER_MerchantPublicKeyP *merchant_pub,
     660             :   const struct TALER_PaytoHashP *h_payto,
     661             :   const struct GNUNET_HashCode *h_details,
     662             :   const struct TALER_ExchangePublicKeyP *pub,
     663             :   const struct TALER_ExchangeSignatureP *sig)
     664             : {
     665           0 :   struct TALER_WireDepositDataPS wdp = {
     666           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT),
     667           0 :     .purpose.size = htonl (sizeof (wdp)),
     668             :     .merchant_pub = *merchant_pub,
     669             :     .h_details = *h_details,
     670             :     .h_payto = *h_payto
     671             :   };
     672             : 
     673           0 :   TALER_amount_hton (&wdp.total,
     674             :                      total);
     675           0 :   TALER_amount_hton (&wdp.wire_fee,
     676             :                      wire_fee);
     677             :   return
     678           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT,
     679             :                                 &wdp,
     680             :                                 &sig->eddsa_signature,
     681             :                                 &pub->eddsa_pub);
     682             : }
     683             : 
     684             : 
     685             : GNUNET_NETWORK_STRUCT_BEGIN
     686             : 
     687             : /**
     688             :  * Details affirmed by the exchange about a wire transfer the exchange
     689             :  * claims to have done with respect to a deposit operation.
     690             :  */
     691             : struct TALER_ConfirmWirePS
     692             : {
     693             :   /**
     694             :    * Purpose header for the signature over the contract with
     695             :    * purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE.
     696             :    */
     697             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
     698             : 
     699             :   /**
     700             :    * Hash over the wiring information of the merchant.
     701             :    */
     702             :   struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
     703             : 
     704             :   /**
     705             :    * Hash over the contract for which this deposit is made.
     706             :    */
     707             :   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
     708             : 
     709             :   /**
     710             :    * Raw value (binary encoding) of the wire transfer subject.
     711             :    */
     712             :   struct TALER_WireTransferIdentifierRawP wtid;
     713             : 
     714             :   /**
     715             :    * The coin's public key.  This is the value that must have been
     716             :    * signed (blindly) by the Exchange.
     717             :    */
     718             :   struct TALER_CoinSpendPublicKeyP coin_pub;
     719             : 
     720             :   /**
     721             :    * When did the exchange execute this transfer? Note that the
     722             :    * timestamp may not be exactly the same on the wire, i.e.
     723             :    * because the wire has a different timezone or resolution.
     724             :    */
     725             :   struct GNUNET_TIME_TimestampNBO execution_time;
     726             : 
     727             :   /**
     728             :    * The contribution of @e coin_pub to the total transfer volume.
     729             :    * This is the value of the deposit minus the fee.
     730             :    */
     731             :   struct TALER_AmountNBO coin_contribution;
     732             : 
     733             : };
     734             : 
     735             : GNUNET_NETWORK_STRUCT_END
     736             : 
     737             : 
     738             : enum TALER_ErrorCode
     739           0 : TALER_exchange_online_confirm_wire_sign (
     740             :   TALER_ExchangeSignCallback scb,
     741             :   const struct TALER_MerchantWireHashP *h_wire,
     742             :   const struct TALER_PrivateContractHashP *h_contract_terms,
     743             :   const struct TALER_WireTransferIdentifierRawP *wtid,
     744             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     745             :   struct GNUNET_TIME_Timestamp execution_time,
     746             :   const struct TALER_Amount *coin_contribution,
     747             :   struct TALER_ExchangePublicKeyP *pub,
     748             :   struct TALER_ExchangeSignatureP *sig)
     749             : 
     750             : {
     751           0 :   struct TALER_ConfirmWirePS cw = {
     752           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE),
     753           0 :     .purpose.size = htonl (sizeof (cw)),
     754             :     .h_wire = *h_wire,
     755             :     .h_contract_terms = *h_contract_terms,
     756             :     .wtid = *wtid,
     757             :     .coin_pub = *coin_pub,
     758           0 :     .execution_time = GNUNET_TIME_timestamp_hton (execution_time)
     759             :   };
     760             : 
     761           0 :   TALER_amount_hton (&cw.coin_contribution,
     762             :                      coin_contribution);
     763           0 :   return scb (&cw.purpose,
     764             :               pub,
     765             :               sig);
     766             : }
     767             : 
     768             : 
     769             : enum GNUNET_GenericReturnValue
     770           0 : TALER_exchange_online_confirm_wire_verify (
     771             :   const struct TALER_MerchantWireHashP *h_wire,
     772             :   const struct TALER_PrivateContractHashP *h_contract_terms,
     773             :   const struct TALER_WireTransferIdentifierRawP *wtid,
     774             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     775             :   struct GNUNET_TIME_Timestamp execution_time,
     776             :   const struct TALER_Amount *coin_contribution,
     777             :   const struct TALER_ExchangePublicKeyP *pub,
     778             :   const struct TALER_ExchangeSignatureP *sig)
     779             : {
     780           0 :   struct TALER_ConfirmWirePS cw = {
     781           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE),
     782           0 :     .purpose.size = htonl (sizeof (cw)),
     783             :     .h_wire = *h_wire,
     784             :     .h_contract_terms = *h_contract_terms,
     785             :     .wtid = *wtid,
     786             :     .coin_pub = *coin_pub,
     787           0 :     .execution_time = GNUNET_TIME_timestamp_hton (execution_time)
     788             :   };
     789             : 
     790           0 :   TALER_amount_hton (&cw.coin_contribution,
     791             :                      coin_contribution);
     792             :   return
     793           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE,
     794             :                                 &cw,
     795             :                                 &sig->eddsa_signature,
     796             :                                 &pub->eddsa_pub);
     797             : }
     798             : 
     799             : 
     800             : GNUNET_NETWORK_STRUCT_BEGIN
     801             : 
     802             : /**
     803             :  * Response by which the exchange affirms that it will
     804             :  * refund a coin as part of the emergency /recoup
     805             :  * protocol.  The recoup will go back to the bank
     806             :  * account that created the reserve.
     807             :  */
     808             : struct TALER_RecoupConfirmationPS
     809             : {
     810             : 
     811             :   /**
     812             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP
     813             :    */
     814             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
     815             : 
     816             :   /**
     817             :    * When did the exchange receive the recoup request?
     818             :    * Indirectly determines when the wire transfer is (likely)
     819             :    * to happen.
     820             :    */
     821             :   struct GNUNET_TIME_TimestampNBO timestamp;
     822             : 
     823             :   /**
     824             :    * How much of the coin's value will the exchange transfer?
     825             :    * (Needed in case the coin was partially spent.)
     826             :    */
     827             :   struct TALER_AmountNBO recoup_amount;
     828             : 
     829             :   /**
     830             :    * Public key of the coin.
     831             :    */
     832             :   struct TALER_CoinSpendPublicKeyP coin_pub;
     833             : 
     834             :   /**
     835             :    * Public key of the reserve that will receive the recoup.
     836             :    */
     837             :   struct TALER_ReservePublicKeyP reserve_pub;
     838             : };
     839             : 
     840             : GNUNET_NETWORK_STRUCT_END
     841             : 
     842             : 
     843             : enum TALER_ErrorCode
     844           0 : TALER_exchange_online_confirm_recoup_sign (
     845             :   TALER_ExchangeSignCallback scb,
     846             :   struct GNUNET_TIME_Timestamp timestamp,
     847             :   const struct TALER_Amount *recoup_amount,
     848             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     849             :   const struct TALER_ReservePublicKeyP *reserve_pub,
     850             :   struct TALER_ExchangePublicKeyP *pub,
     851             :   struct TALER_ExchangeSignatureP *sig)
     852             : {
     853           0 :   struct TALER_RecoupConfirmationPS pc = {
     854           0 :     .purpose.size = htonl (sizeof (pc)),
     855           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
     856           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
     857             :     .coin_pub = *coin_pub,
     858             :     .reserve_pub = *reserve_pub
     859             :   };
     860             : 
     861           0 :   TALER_amount_hton (&pc.recoup_amount,
     862             :                      recoup_amount);
     863           0 :   return scb (&pc.purpose,
     864             :               pub,
     865             :               sig);
     866             : }
     867             : 
     868             : 
     869             : enum GNUNET_GenericReturnValue
     870           0 : TALER_exchange_online_confirm_recoup_verify (
     871             :   struct GNUNET_TIME_Timestamp timestamp,
     872             :   const struct TALER_Amount *recoup_amount,
     873             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     874             :   const struct TALER_ReservePublicKeyP *reserve_pub,
     875             :   const struct TALER_ExchangePublicKeyP *pub,
     876             :   const struct TALER_ExchangeSignatureP *sig)
     877             : {
     878           0 :   struct TALER_RecoupConfirmationPS pc = {
     879           0 :     .purpose.size = htonl (sizeof (pc)),
     880           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP),
     881           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
     882             :     .coin_pub = *coin_pub,
     883             :     .reserve_pub = *reserve_pub
     884             :   };
     885             : 
     886           0 :   TALER_amount_hton (&pc.recoup_amount,
     887             :                      recoup_amount);
     888             :   return
     889           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP,
     890             :                                 &pc,
     891             :                                 &sig->eddsa_signature,
     892             :                                 &pub->eddsa_pub);
     893             : }
     894             : 
     895             : 
     896             : GNUNET_NETWORK_STRUCT_BEGIN
     897             : 
     898             : /**
     899             :  * Response by which the exchange affirms that it will refund a refreshed coin
     900             :  * as part of the emergency /recoup protocol.  The recoup will go back to the
     901             :  * old coin's balance.
     902             :  */
     903             : struct TALER_RecoupRefreshConfirmationPS
     904             : {
     905             : 
     906             :   /**
     907             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH
     908             :    */
     909             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
     910             : 
     911             :   /**
     912             :    * When did the exchange receive the recoup request?
     913             :    * Indirectly determines when the wire transfer is (likely)
     914             :    * to happen.
     915             :    */
     916             :   struct GNUNET_TIME_TimestampNBO timestamp;
     917             : 
     918             :   /**
     919             :    * How much of the coin's value will the exchange transfer?
     920             :    * (Needed in case the coin was partially spent.)
     921             :    */
     922             :   struct TALER_AmountNBO recoup_amount;
     923             : 
     924             :   /**
     925             :    * Public key of the refreshed coin.
     926             :    */
     927             :   struct TALER_CoinSpendPublicKeyP coin_pub;
     928             : 
     929             :   /**
     930             :    * Public key of the old coin that will receive the recoup.
     931             :    */
     932             :   struct TALER_CoinSpendPublicKeyP old_coin_pub;
     933             : };
     934             : 
     935             : GNUNET_NETWORK_STRUCT_END
     936             : 
     937             : 
     938             : enum TALER_ErrorCode
     939           0 : TALER_exchange_online_confirm_recoup_refresh_sign (
     940             :   TALER_ExchangeSignCallback scb,
     941             :   struct GNUNET_TIME_Timestamp timestamp,
     942             :   const struct TALER_Amount *recoup_amount,
     943             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     944             :   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
     945             :   struct TALER_ExchangePublicKeyP *pub,
     946             :   struct TALER_ExchangeSignatureP *sig)
     947             : {
     948           0 :   struct TALER_RecoupRefreshConfirmationPS pc = {
     949           0 :     .purpose.purpose = htonl (
     950             :       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
     951           0 :     .purpose.size = htonl (sizeof (pc)),
     952           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
     953             :     .coin_pub = *coin_pub,
     954             :     .old_coin_pub = *old_coin_pub
     955             :   };
     956             : 
     957           0 :   TALER_amount_hton (&pc.recoup_amount,
     958             :                      recoup_amount);
     959           0 :   return scb (&pc.purpose,
     960             :               pub,
     961             :               sig);
     962             : }
     963             : 
     964             : 
     965             : enum GNUNET_GenericReturnValue
     966           0 : TALER_exchange_online_confirm_recoup_refresh_verify (
     967             :   struct GNUNET_TIME_Timestamp timestamp,
     968             :   const struct TALER_Amount *recoup_amount,
     969             :   const struct TALER_CoinSpendPublicKeyP *coin_pub,
     970             :   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
     971             :   const struct TALER_ExchangePublicKeyP *pub,
     972             :   const struct TALER_ExchangeSignatureP *sig)
     973             : {
     974           0 :   struct TALER_RecoupRefreshConfirmationPS pc = {
     975           0 :     .purpose.purpose = htonl (
     976             :       TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH),
     977           0 :     .purpose.size = htonl (sizeof (pc)),
     978           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
     979             :     .coin_pub = *coin_pub,
     980             :     .old_coin_pub = *old_coin_pub
     981             :   };
     982             : 
     983           0 :   TALER_amount_hton (&pc.recoup_amount,
     984             :                      recoup_amount);
     985             : 
     986             :   return
     987           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH,
     988             :                                 &pc,
     989             :                                 &sig->eddsa_signature,
     990             :                                 &pub->eddsa_pub);
     991             : }
     992             : 
     993             : 
     994             : GNUNET_NETWORK_STRUCT_BEGIN
     995             : 
     996             : /**
     997             :  * Response by which the exchange affirms that it does not
     998             :  * currently know a denomination by the given hash.
     999             :  */
    1000             : struct TALER_DenominationUnknownAffirmationPS
    1001             : {
    1002             : 
    1003             :   /**
    1004             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN
    1005             :    */
    1006             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
    1007             : 
    1008             :   /**
    1009             :    * When did the exchange sign this message.
    1010             :    */
    1011             :   struct GNUNET_TIME_TimestampNBO timestamp;
    1012             : 
    1013             :   /**
    1014             :    * Hash of the public denomination key we do not know.
    1015             :    */
    1016             :   struct TALER_DenominationHashP h_denom_pub;
    1017             : };
    1018             : 
    1019             : GNUNET_NETWORK_STRUCT_END
    1020             : 
    1021             : 
    1022             : enum TALER_ErrorCode
    1023           0 : TALER_exchange_online_denomination_unknown_sign (
    1024             :   TALER_ExchangeSignCallback scb,
    1025             :   struct GNUNET_TIME_Timestamp timestamp,
    1026             :   const struct TALER_DenominationHashP *h_denom_pub,
    1027             :   struct TALER_ExchangePublicKeyP *pub,
    1028             :   struct TALER_ExchangeSignatureP *sig)
    1029             : {
    1030           0 :   struct TALER_DenominationUnknownAffirmationPS dua = {
    1031           0 :     .purpose.size = htonl (sizeof (dua)),
    1032           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
    1033           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1034             :     .h_denom_pub = *h_denom_pub,
    1035             :   };
    1036             : 
    1037           0 :   return scb (&dua.purpose,
    1038             :               pub,
    1039             :               sig);
    1040             : }
    1041             : 
    1042             : 
    1043             : enum GNUNET_GenericReturnValue
    1044           0 : TALER_exchange_online_denomination_unknown_verify (
    1045             :   struct GNUNET_TIME_Timestamp timestamp,
    1046             :   const struct TALER_DenominationHashP *h_denom_pub,
    1047             :   const struct TALER_ExchangePublicKeyP *pub,
    1048             :   const struct TALER_ExchangeSignatureP *sig)
    1049             : {
    1050           0 :   struct TALER_DenominationUnknownAffirmationPS dua = {
    1051           0 :     .purpose.size = htonl (sizeof (dua)),
    1052           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
    1053           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1054             :     .h_denom_pub = *h_denom_pub,
    1055             :   };
    1056             : 
    1057             :   return
    1058           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN,
    1059             :                                 &dua,
    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 consider the given denomination to be valid
    1070             :  * for the requested operation.
    1071             :  */
    1072             : struct TALER_DenominationExpiredAffirmationPS
    1073             : {
    1074             : 
    1075             :   /**
    1076             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED
    1077             :    */
    1078             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
    1079             : 
    1080             :   /**
    1081             :    * When did the exchange sign this message.
    1082             :    */
    1083             :   struct GNUNET_TIME_TimestampNBO timestamp;
    1084             : 
    1085             :   /**
    1086             :    * Name of the operation that is not allowed at this time.  Might NOT be 0-terminated, but is padded with 0s.
    1087             :    */
    1088             :   char operation[8];
    1089             : 
    1090             :   /**
    1091             :    * Hash of the public denomination key we do not know.
    1092             :    */
    1093             :   struct TALER_DenominationHashP h_denom_pub;
    1094             : 
    1095             : };
    1096             : 
    1097             : GNUNET_NETWORK_STRUCT_END
    1098             : 
    1099             : 
    1100             : enum TALER_ErrorCode
    1101           0 : TALER_exchange_online_denomination_expired_sign (
    1102             :   TALER_ExchangeSignCallback scb,
    1103             :   struct GNUNET_TIME_Timestamp timestamp,
    1104             :   const struct TALER_DenominationHashP *h_denom_pub,
    1105             :   const char *op,
    1106             :   struct TALER_ExchangePublicKeyP *pub,
    1107             :   struct TALER_ExchangeSignatureP *sig)
    1108             : {
    1109           0 :   struct TALER_DenominationExpiredAffirmationPS dua = {
    1110           0 :     .purpose.size = htonl (sizeof (dua)),
    1111           0 :     .purpose.purpose = htonl (
    1112             :       TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED),
    1113           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1114             :     .h_denom_pub = *h_denom_pub,
    1115             :   };
    1116             : 
    1117             :   /* strncpy would create a compiler warning */
    1118           0 :   memcpy (dua.operation,
    1119             :           op,
    1120           0 :           GNUNET_MIN (sizeof (dua.operation),
    1121             :                       strlen (op)));
    1122           0 :   return scb (&dua.purpose,
    1123             :               pub,
    1124             :               sig);
    1125             : }
    1126             : 
    1127             : 
    1128             : enum GNUNET_GenericReturnValue
    1129           0 : TALER_exchange_online_denomination_expired_verify (
    1130             :   struct GNUNET_TIME_Timestamp timestamp,
    1131             :   const struct TALER_DenominationHashP *h_denom_pub,
    1132             :   const char *op,
    1133             :   const struct TALER_ExchangePublicKeyP *pub,
    1134             :   const struct TALER_ExchangeSignatureP *sig)
    1135             : {
    1136           0 :   struct TALER_DenominationExpiredAffirmationPS dua = {
    1137           0 :     .purpose.size = htonl (sizeof (dua)),
    1138           0 :     .purpose.purpose = htonl (
    1139             :       TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED),
    1140           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp),
    1141             :     .h_denom_pub = *h_denom_pub,
    1142             :   };
    1143             : 
    1144             :   /* strncpy would create a compiler warning */
    1145           0 :   memcpy (dua.operation,
    1146             :           op,
    1147           0 :           GNUNET_MIN (sizeof (dua.operation),
    1148             :                       strlen (op)));
    1149             :   return
    1150           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED,
    1151             :                                 &dua,
    1152             :                                 &sig->eddsa_signature,
    1153             :                                 &pub->eddsa_pub);
    1154             : }
    1155             : 
    1156             : 
    1157             : GNUNET_NETWORK_STRUCT_BEGIN
    1158             : 
    1159             : /**
    1160             :  * Response by which the exchange affirms that it has
    1161             :  * closed a reserve and send back the funds.
    1162             :  */
    1163             : struct TALER_ReserveCloseConfirmationPS
    1164             : {
    1165             : 
    1166             :   /**
    1167             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED
    1168             :    */
    1169             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
    1170             : 
    1171             :   /**
    1172             :    * When did the exchange initiate the wire transfer.
    1173             :    */
    1174             :   struct GNUNET_TIME_TimestampNBO timestamp;
    1175             : 
    1176             :   /**
    1177             :    * How much did the exchange send?
    1178             :    */
    1179             :   struct TALER_AmountNBO closing_amount;
    1180             : 
    1181             :   /**
    1182             :    * How much did the exchange charge for closing the reserve?
    1183             :    */
    1184             :   struct TALER_AmountNBO closing_fee;
    1185             : 
    1186             :   /**
    1187             :    * Public key of the reserve that was closed.
    1188             :    */
    1189             :   struct TALER_ReservePublicKeyP reserve_pub;
    1190             : 
    1191             :   /**
    1192             :    * Hash of the receiver's bank account.
    1193             :    */
    1194             :   struct TALER_PaytoHashP h_payto;
    1195             : 
    1196             :   /**
    1197             :    * Wire transfer subject.
    1198             :    */
    1199             :   struct TALER_WireTransferIdentifierRawP wtid;
    1200             : };
    1201             : 
    1202             : GNUNET_NETWORK_STRUCT_END
    1203             : 
    1204             : 
    1205             : enum TALER_ErrorCode
    1206           0 : TALER_exchange_online_reserve_closed_sign (
    1207             :   TALER_ExchangeSignCallback scb,
    1208             :   struct GNUNET_TIME_Timestamp timestamp,
    1209             :   const struct TALER_Amount *closing_amount,
    1210             :   const struct TALER_Amount *closing_fee,
    1211             :   const char *payto,
    1212             :   const struct TALER_WireTransferIdentifierRawP *wtid,
    1213             :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1214             :   struct TALER_ExchangePublicKeyP *pub,
    1215             :   struct TALER_ExchangeSignatureP *sig)
    1216             : {
    1217           0 :   struct TALER_ReserveCloseConfirmationPS rcc = {
    1218           0 :     .purpose.size = htonl (sizeof (rcc)),
    1219           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED),
    1220             :     .wtid = *wtid,
    1221             :     .reserve_pub = *reserve_pub,
    1222           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp)
    1223             :   };
    1224             : 
    1225           0 :   TALER_amount_hton (&rcc.closing_amount,
    1226             :                      closing_amount);
    1227           0 :   TALER_amount_hton (&rcc.closing_fee,
    1228             :                      closing_fee);
    1229           0 :   TALER_payto_hash (payto,
    1230             :                     &rcc.h_payto);
    1231           0 :   return scb (&rcc.purpose,
    1232             :               pub,
    1233             :               sig);
    1234             : }
    1235             : 
    1236             : 
    1237             : enum GNUNET_GenericReturnValue
    1238           0 : TALER_exchange_online_reserve_closed_verify (
    1239             :   struct GNUNET_TIME_Timestamp timestamp,
    1240             :   const struct TALER_Amount *closing_amount,
    1241             :   const struct TALER_Amount *closing_fee,
    1242             :   const char *payto,
    1243             :   const struct TALER_WireTransferIdentifierRawP *wtid,
    1244             :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1245             :   const struct TALER_ExchangePublicKeyP *pub,
    1246             :   const struct TALER_ExchangeSignatureP *sig)
    1247             : {
    1248           0 :   struct TALER_ReserveCloseConfirmationPS rcc = {
    1249           0 :     .purpose.size = htonl (sizeof (rcc)),
    1250           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED),
    1251             :     .wtid = *wtid,
    1252             :     .reserve_pub = *reserve_pub,
    1253           0 :     .timestamp = GNUNET_TIME_timestamp_hton (timestamp)
    1254             :   };
    1255             : 
    1256           0 :   TALER_amount_hton (&rcc.closing_amount,
    1257             :                      closing_amount);
    1258           0 :   TALER_amount_hton (&rcc.closing_fee,
    1259             :                      closing_fee);
    1260           0 :   TALER_payto_hash (payto,
    1261             :                     &rcc.h_payto);
    1262             :   return
    1263           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED,
    1264             :                                 &rcc,
    1265             :                                 &sig->eddsa_signature,
    1266             :                                 &pub->eddsa_pub);
    1267             : }
    1268             : 
    1269             : 
    1270             : GNUNET_NETWORK_STRUCT_BEGIN
    1271             : 
    1272             : /**
    1273             :  * Response by which the exchange affirms that it has
    1274             :  * received funds deposited into a purse.
    1275             :  */
    1276             : struct TALER_PurseCreateDepositConfirmationPS
    1277             : {
    1278             : 
    1279             :   /**
    1280             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION
    1281             :    */
    1282             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
    1283             : 
    1284             :   /**
    1285             :    * When did the exchange receive the deposits.
    1286             :    */
    1287             :   struct GNUNET_TIME_TimestampNBO exchange_time;
    1288             : 
    1289             :   /**
    1290             :    * When will the purse expire?
    1291             :    */
    1292             :   struct GNUNET_TIME_TimestampNBO purse_expiration;
    1293             : 
    1294             :   /**
    1295             :    * How much should the purse ultimately contain.
    1296             :    */
    1297             :   struct TALER_AmountNBO amount_without_fee;
    1298             : 
    1299             :   /**
    1300             :    * How much was deposited so far.
    1301             :    */
    1302             :   struct TALER_AmountNBO total_deposited;
    1303             : 
    1304             :   /**
    1305             :    * Public key of the purse.
    1306             :    */
    1307             :   struct TALER_PurseContractPublicKeyP purse_pub;
    1308             : 
    1309             :   /**
    1310             :    * Hash of the contract of the purse.
    1311             :    */
    1312             :   struct TALER_PrivateContractHashP h_contract_terms;
    1313             : 
    1314             : };
    1315             : 
    1316             : GNUNET_NETWORK_STRUCT_END
    1317             : 
    1318             : 
    1319             : enum TALER_ErrorCode
    1320           0 : TALER_exchange_online_purse_created_sign (
    1321             :   TALER_ExchangeSignCallback scb,
    1322             :   struct GNUNET_TIME_Timestamp exchange_time,
    1323             :   struct GNUNET_TIME_Timestamp purse_expiration,
    1324             :   const struct TALER_Amount *amount_without_fee,
    1325             :   const struct TALER_Amount *total_deposited,
    1326             :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1327             :   const struct TALER_PrivateContractHashP *h_contract_terms,
    1328             :   struct TALER_ExchangePublicKeyP *pub,
    1329             :   struct TALER_ExchangeSignatureP *sig)
    1330             : {
    1331           0 :   struct TALER_PurseCreateDepositConfirmationPS dc = {
    1332           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
    1333           0 :     .purpose.size = htonl (sizeof (dc)),
    1334             :     .h_contract_terms = *h_contract_terms,
    1335             :     .purse_pub = *purse_pub,
    1336           0 :     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
    1337           0 :     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
    1338             :   };
    1339             : 
    1340           0 :   TALER_amount_hton (&dc.amount_without_fee,
    1341             :                      amount_without_fee);
    1342           0 :   TALER_amount_hton (&dc.total_deposited,
    1343             :                      total_deposited);
    1344           0 :   return scb (&dc.purpose,
    1345             :               pub,
    1346             :               sig);
    1347             : }
    1348             : 
    1349             : 
    1350             : enum GNUNET_GenericReturnValue
    1351           0 : TALER_exchange_online_purse_created_verify (
    1352             :   struct GNUNET_TIME_Timestamp exchange_time,
    1353             :   struct GNUNET_TIME_Timestamp purse_expiration,
    1354             :   const struct TALER_Amount *amount_without_fee,
    1355             :   const struct TALER_Amount *total_deposited,
    1356             :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1357             :   const struct TALER_PrivateContractHashP *h_contract_terms,
    1358             :   const struct TALER_ExchangePublicKeyP *pub,
    1359             :   const struct TALER_ExchangeSignatureP *sig)
    1360             : {
    1361           0 :   struct TALER_PurseCreateDepositConfirmationPS dc = {
    1362           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION),
    1363           0 :     .purpose.size = htonl (sizeof (dc)),
    1364             :     .h_contract_terms = *h_contract_terms,
    1365             :     .purse_pub = *purse_pub,
    1366           0 :     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
    1367           0 :     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
    1368             :   };
    1369             : 
    1370           0 :   TALER_amount_hton (&dc.amount_without_fee,
    1371             :                      amount_without_fee);
    1372           0 :   TALER_amount_hton (&dc.total_deposited,
    1373             :                      total_deposited);
    1374             :   return
    1375           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_CREATION,
    1376             :                                 &dc,
    1377             :                                 &sig->eddsa_signature,
    1378             :                                 &pub->eddsa_pub);
    1379             : }
    1380             : 
    1381             : 
    1382             : GNUNET_NETWORK_STRUCT_BEGIN
    1383             : 
    1384             : /**
    1385             :  * Response by which the exchange affirms that it has
    1386             :  * merged a purse into a reserve.
    1387             :  */
    1388             : struct TALER_PurseMergedConfirmationPS
    1389             : {
    1390             : 
    1391             :   /**
    1392             :    * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED
    1393             :    */
    1394             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
    1395             : 
    1396             :   /**
    1397             :    * When did the exchange receive the deposits.
    1398             :    */
    1399             :   struct GNUNET_TIME_TimestampNBO exchange_time;
    1400             : 
    1401             :   /**
    1402             :    * When will the purse expire?
    1403             :    */
    1404             :   struct GNUNET_TIME_TimestampNBO purse_expiration;
    1405             : 
    1406             :   /**
    1407             :    * How much should the purse ultimately contain.
    1408             :    */
    1409             :   struct TALER_AmountNBO amount_without_fee;
    1410             : 
    1411             :   /**
    1412             :    * Public key of the purse.
    1413             :    */
    1414             :   struct TALER_PurseContractPublicKeyP purse_pub;
    1415             : 
    1416             :   /**
    1417             :    * Public key of the reserve.
    1418             :    */
    1419             :   struct TALER_ReservePublicKeyP reserve_pub;
    1420             : 
    1421             :   /**
    1422             :    * Hash of the contract of the purse.
    1423             :    */
    1424             :   struct TALER_PrivateContractHashP h_contract_terms;
    1425             : 
    1426             :   /**
    1427             :    * Hash of the provider URL hosting the reserve.
    1428             :    */
    1429             :   struct GNUNET_HashCode h_provider_url;
    1430             : 
    1431             : };
    1432             : 
    1433             : GNUNET_NETWORK_STRUCT_END
    1434             : 
    1435             : 
    1436             : enum TALER_ErrorCode
    1437           0 : TALER_exchange_online_purse_merged_sign (
    1438             :   TALER_ExchangeSignCallback scb,
    1439             :   struct GNUNET_TIME_Timestamp exchange_time,
    1440             :   struct GNUNET_TIME_Timestamp purse_expiration,
    1441             :   const struct TALER_Amount *amount_without_fee,
    1442             :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1443             :   const struct TALER_PrivateContractHashP *h_contract_terms,
    1444             :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1445             :   const char *exchange_url,
    1446             :   struct TALER_ExchangePublicKeyP *pub,
    1447             :   struct TALER_ExchangeSignatureP *sig)
    1448             : {
    1449           0 :   struct TALER_PurseMergedConfirmationPS dc = {
    1450           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED),
    1451           0 :     .purpose.size = htonl (sizeof (dc)),
    1452             :     .h_contract_terms = *h_contract_terms,
    1453             :     .purse_pub = *purse_pub,
    1454             :     .reserve_pub = *reserve_pub,
    1455           0 :     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
    1456           0 :     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
    1457             :   };
    1458             : 
    1459           0 :   TALER_amount_hton (&dc.amount_without_fee,
    1460             :                      amount_without_fee);
    1461           0 :   GNUNET_CRYPTO_hash (exchange_url,
    1462           0 :                       strlen (exchange_url) + 1,
    1463             :                       &dc.h_provider_url);
    1464           0 :   return scb (&dc.purpose,
    1465             :               pub,
    1466             :               sig);
    1467             : }
    1468             : 
    1469             : 
    1470             : enum GNUNET_GenericReturnValue
    1471           0 : TALER_exchange_online_purse_merged_verify (
    1472             :   struct GNUNET_TIME_Timestamp exchange_time,
    1473             :   struct GNUNET_TIME_Timestamp purse_expiration,
    1474             :   const struct TALER_Amount *amount_without_fee,
    1475             :   const struct TALER_PurseContractPublicKeyP *purse_pub,
    1476             :   const struct TALER_PrivateContractHashP *h_contract_terms,
    1477             :   const struct TALER_ReservePublicKeyP *reserve_pub,
    1478             :   const char *exchange_url,
    1479             :   const struct TALER_ExchangePublicKeyP *pub,
    1480             :   const struct TALER_ExchangeSignatureP *sig)
    1481             : {
    1482           0 :   struct TALER_PurseMergedConfirmationPS dc = {
    1483           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED),
    1484           0 :     .purpose.size = htonl (sizeof (dc)),
    1485             :     .h_contract_terms = *h_contract_terms,
    1486             :     .purse_pub = *purse_pub,
    1487             :     .reserve_pub = *reserve_pub,
    1488           0 :     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
    1489           0 :     .exchange_time = GNUNET_TIME_timestamp_hton (exchange_time)
    1490             :   };
    1491             : 
    1492           0 :   TALER_amount_hton (&dc.amount_without_fee,
    1493             :                      amount_without_fee);
    1494           0 :   GNUNET_CRYPTO_hash (exchange_url,
    1495           0 :                       strlen (exchange_url) + 1,
    1496             :                       &dc.h_provider_url);
    1497             :   return
    1498           0 :     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_MERGED,
    1499             :                                 &dc,
    1500             :                                 &sig->eddsa_signature,
    1501             :                                 &pub->eddsa_pub);
    1502             : }
    1503             : 
    1504             : 
    1505             : GNUNET_NETWORK_STRUCT_BEGIN
    1506             : 
    1507             : /**
    1508             :  * @brief Format used to generate the signature on a purse status
    1509             :  * from the exchange.
    1510             :  */
    1511             : struct TALER_PurseStatusPS
    1512             : {
    1513             :   /**
    1514             :    * Purpose must be #TALER_SIGNATURE_EXCHANGE_PURSE_STATUS.  Signed
    1515             :    * by a `struct TALER_ExchangePublicKeyP` using EdDSA.
    1516             :    */
    1517             :   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
    1518             : 
    1519             :   /**
    1520             :    * Time when the purse was merged, possibly 'never'.
    1521             :    */
    1522             :   struct GNUNET_TIME_TimestampNBO merge_timestamp;
    1523             : 
    1524             :   /**
    1525             :    * Time when the purse was deposited last, possibly 'never'.
    1526             :    */
    1527             :   struct GNUNET_TIME_TimestampNBO deposit_timestamp;
    1528             : 
    1529             :   /**
    1530             :    * Amount deposited in total in the purse without fees.
    1531             :    * May be possibly less than the target amount.
    1532             :    */
    1533             :   struct TALER_AmountNBO balance;
    1534             : 
    1535             : };
    1536             : 
    1537             : GNUNET_NETWORK_STRUCT_END
    1538             : 
    1539             : 
    1540             : enum TALER_ErrorCode
    1541           0 : TALER_exchange_online_purse_status_sign (
    1542             :   TALER_ExchangeSignCallback scb,
    1543             :   struct GNUNET_TIME_Timestamp merge_timestamp,
    1544             :   struct GNUNET_TIME_Timestamp deposit_timestamp,
    1545             :   const struct TALER_Amount *balance,
    1546             :   struct TALER_ExchangePublicKeyP *pub,
    1547             :   struct TALER_ExchangeSignatureP *sig)
    1548             : {
    1549           0 :   struct TALER_PurseStatusPS dcs = {
    1550           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS),
    1551           0 :     .purpose.size = htonl (sizeof (dcs)),
    1552           0 :     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
    1553           0 :     .deposit_timestamp = GNUNET_TIME_timestamp_hton (deposit_timestamp)
    1554             :   };
    1555             : 
    1556           0 :   TALER_amount_hton (&dcs.balance,
    1557             :                      balance);
    1558           0 :   return scb (&dcs.purpose,
    1559             :               pub,
    1560             :               sig);
    1561             : }
    1562             : 
    1563             : 
    1564             : enum GNUNET_GenericReturnValue
    1565           0 : TALER_exchange_online_purse_status_verify (
    1566             :   struct GNUNET_TIME_Timestamp merge_timestamp,
    1567             :   struct GNUNET_TIME_Timestamp deposit_timestamp,
    1568             :   const struct TALER_Amount *balance,
    1569             :   const struct TALER_ExchangePublicKeyP *exchange_pub,
    1570             :   const struct TALER_ExchangeSignatureP *exchange_sig)
    1571             : {
    1572           0 :   struct TALER_PurseStatusPS dcs = {
    1573           0 :     .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS),
    1574           0 :     .purpose.size = htonl (sizeof (dcs)),
    1575           0 :     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
    1576           0 :     .deposit_timestamp = GNUNET_TIME_timestamp_hton (deposit_timestamp)
    1577             :   };
    1578             : 
    1579           0 :   TALER_amount_hton (&dcs.balance,
    1580             :                      balance);
    1581           0 :   if (GNUNET_OK !=
    1582           0 :       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_EXCHANGE_PURSE_STATUS,
    1583             :                                   &dcs,
    1584             :                                   &exchange_sig->eddsa_signature,
    1585             :                                   &exchange_pub->eddsa_pub))
    1586             :   {
    1587           0 :     GNUNET_break_op (0);
    1588           0 :     return GNUNET_SYSERR;
    1589             :   }
    1590           0 :   return GNUNET_OK;
    1591             : }
    1592             : 
    1593             : 
    1594             : /* end of exchange_signatures.c */

Generated by: LCOV version 1.14