exchange

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

wallet_signatures.c (65015B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2021-2023 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 wallet_signatures.c
     18  * @brief Utility functions for Taler wallet signatures
     19  * @author Christian Grothoff
     20  * @author Özgür Kesim
     21  */
     22 #include "taler/taler_util.h"
     23 #include "taler/taler_signatures.h"
     24 #include <gnunet/gnunet_common.h>
     25 #include <stdint.h>
     26 
     27 
     28 GNUNET_NETWORK_STRUCT_BEGIN
     29 
     30 /**
     31  * @brief Format used to generate the signature on a request to deposit
     32  * a coin into the account of a merchant.
     33  */
     34 struct TALER_DepositRequestPS
     35 {
     36   /**
     37    * Purpose must be #TALER_SIGNATURE_WALLET_COIN_DEPOSIT.
     38    * Used for an EdDSA signature with the `struct TALER_CoinSpendPublicKeyP`.
     39    */
     40   struct GNUNET_CRYPTO_SignaturePurpose purpose;
     41 
     42   /**
     43    * Hash over the contract for which this deposit is made.
     44    */
     45   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
     46 
     47   /**
     48    * Hash over the age commitment that went into the coin. Maybe all zero, if
     49    * age commitment isn't applicable to the denomination.
     50    */
     51   struct TALER_AgeCommitmentHashP h_age_commitment GNUNET_PACKED;
     52 
     53   /**
     54    * Hash over optional policy extension attributes shared with the exchange.
     55    */
     56   struct TALER_ExtensionPolicyHashP h_policy GNUNET_PACKED;
     57 
     58   /**
     59    * Hash over the wiring information of the merchant.
     60    */
     61   struct TALER_MerchantWireHashP h_wire GNUNET_PACKED;
     62 
     63   /**
     64    * Hash over the denomination public key used to sign the coin.
     65    */
     66   struct TALER_DenominationHashP h_denom_pub GNUNET_PACKED;
     67 
     68   /**
     69    * Time when this request was generated.  Used, for example, to
     70    * assess when (roughly) the income was achieved for tax purposes.
     71    * Note that the Exchange will only check that the timestamp is not "too
     72    * far" into the future (i.e. several days).  The fact that the
     73    * timestamp falls within the validity period of the coin's
     74    * denomination key is irrelevant for the validity of the deposit
     75    * request, as obviously the customer and merchant could conspire to
     76    * set any timestamp.  Also, the Exchange must accept very old deposit
     77    * requests, as the merchant might have been unable to transmit the
     78    * deposit request in a timely fashion (so back-dating is not
     79    * prevented).
     80    */
     81   struct GNUNET_TIME_TimestampNBO wallet_timestamp;
     82 
     83   /**
     84    * How much time does the merchant have to issue a refund request?
     85    * Zero if refunds are not allowed.  After this time, the coin
     86    * cannot be refunded.
     87    */
     88   struct GNUNET_TIME_TimestampNBO refund_deadline;
     89 
     90   /**
     91    * Amount to be deposited, including deposit fee charged by the
     92    * exchange.  This is the total amount that the coin's value at the exchange
     93    * will be reduced by.
     94    */
     95   struct TALER_AmountNBO amount_with_fee;
     96 
     97   /**
     98    * Depositing fee charged by the exchange.  This must match the Exchange's
     99    * denomination key's depositing fee.  If the client puts in an
    100    * invalid deposit fee (too high or too low) that does not match the
    101    * Exchange's denomination key, the deposit operation is invalid and
    102    * will be rejected by the exchange.  The @e amount_with_fee minus the
    103    * @e deposit_fee is the amount that will be transferred to the
    104    * account identified by @e h_wire.
    105    */
    106   struct TALER_AmountNBO deposit_fee;
    107 
    108   /**
    109    * The Merchant's public key.  Allows the merchant to later refund
    110    * the transaction or to inquire about the wire transfer identifier.
    111    */
    112   struct TALER_MerchantPublicKeyP merchant;
    113 
    114   /**
    115    * Hash over a JSON containing data provided by the
    116    * wallet to complete the contract upon payment.
    117    */
    118   struct GNUNET_HashCode wallet_data_hash;
    119 
    120 };
    121 
    122 GNUNET_NETWORK_STRUCT_END
    123 
    124 void
    125 TALER_wallet_deposit_sign (
    126   const struct TALER_Amount *amount,
    127   const struct TALER_Amount *deposit_fee,
    128   const struct TALER_MerchantWireHashP *h_wire,
    129   const struct TALER_PrivateContractHashP *h_contract_terms,
    130   const struct GNUNET_HashCode *wallet_data_hash,
    131   const struct TALER_AgeCommitmentHashP *h_age_commitment,
    132   const struct TALER_ExtensionPolicyHashP *h_policy,
    133   const struct TALER_DenominationHashP *h_denom_pub,
    134   const struct GNUNET_TIME_Timestamp wallet_timestamp,
    135   const struct TALER_MerchantPublicKeyP *merchant_pub,
    136   const struct GNUNET_TIME_Timestamp refund_deadline,
    137   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    138   struct TALER_CoinSpendSignatureP *coin_sig)
    139 {
    140   struct TALER_DepositRequestPS dr = {
    141     .purpose.size = htonl (sizeof (dr)),
    142     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
    143     .h_contract_terms = *h_contract_terms,
    144     .h_wire = *h_wire,
    145     .h_denom_pub = *h_denom_pub,
    146     .wallet_timestamp = GNUNET_TIME_timestamp_hton (wallet_timestamp),
    147     .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
    148     .merchant = *merchant_pub
    149   };
    150 
    151   if (NULL != wallet_data_hash)
    152     dr.wallet_data_hash = *wallet_data_hash;
    153   if (NULL != h_age_commitment)
    154     dr.h_age_commitment = *h_age_commitment;
    155   if (NULL != h_policy)
    156     dr.h_policy = *h_policy;
    157   TALER_amount_hton (&dr.amount_with_fee,
    158                      amount);
    159   TALER_amount_hton (&dr.deposit_fee,
    160                      deposit_fee);
    161   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
    162                             &dr,
    163                             &coin_sig->eddsa_signature);
    164 }
    165 
    166 
    167 enum GNUNET_GenericReturnValue
    168 TALER_wallet_deposit_verify (
    169   const struct TALER_Amount *amount,
    170   const struct TALER_Amount *deposit_fee,
    171   const struct TALER_MerchantWireHashP *h_wire,
    172   const struct TALER_PrivateContractHashP *h_contract_terms,
    173   const struct GNUNET_HashCode *wallet_data_hash,
    174   const struct TALER_AgeCommitmentHashP *h_age_commitment,
    175   const struct TALER_ExtensionPolicyHashP *h_policy,
    176   const struct TALER_DenominationHashP *h_denom_pub,
    177   struct GNUNET_TIME_Timestamp wallet_timestamp,
    178   const struct TALER_MerchantPublicKeyP *merchant_pub,
    179   struct GNUNET_TIME_Timestamp refund_deadline,
    180   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    181   const struct TALER_CoinSpendSignatureP *coin_sig)
    182 {
    183   struct TALER_DepositRequestPS dr = {
    184     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
    185     .purpose.size = htonl (sizeof (dr)),
    186     .h_contract_terms = *h_contract_terms,
    187     .h_wire = *h_wire,
    188     .h_denom_pub = *h_denom_pub,
    189     .wallet_timestamp = GNUNET_TIME_timestamp_hton (wallet_timestamp),
    190     .refund_deadline = GNUNET_TIME_timestamp_hton (refund_deadline),
    191     .merchant = *merchant_pub,
    192   };
    193 
    194   if (NULL != wallet_data_hash)
    195     dr.wallet_data_hash = *wallet_data_hash;
    196   if (NULL != h_age_commitment)
    197     dr.h_age_commitment = *h_age_commitment;
    198   if (NULL != h_policy)
    199     dr.h_policy = *h_policy;
    200   TALER_amount_hton (&dr.amount_with_fee,
    201                      amount);
    202   TALER_amount_hton (&dr.deposit_fee,
    203                      deposit_fee);
    204   if (GNUNET_OK !=
    205       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
    206                                   &dr,
    207                                   &coin_sig->eddsa_signature,
    208                                   &coin_pub->eddsa_pub))
    209   {
    210     GNUNET_break_op (0);
    211     return GNUNET_SYSERR;
    212   }
    213   return GNUNET_OK;
    214 }
    215 
    216 
    217 GNUNET_NETWORK_STRUCT_BEGIN
    218 
    219 /**
    220  * @brief Format used for to allow the wallet to authenticate
    221  * link data provided by the exchange.
    222  */
    223 struct TALER_LinkDataPS
    224 {
    225 
    226   /**
    227    * Purpose must be #TALER_SIGNATURE_WALLET_COIN_LINK.
    228    * Used with an EdDSA signature of a `struct TALER_CoinPublicKeyP`.
    229    */
    230   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    231 
    232   /**
    233    * Hash of the denomination public key of the new coin.
    234    */
    235   struct TALER_DenominationHashP h_denom_pub;
    236 
    237   /**
    238    * Transfer public key (for which the private key was not revealed)
    239    */
    240   struct TALER_TransferPublicKeyP transfer_pub;
    241 
    242   /**
    243    * Hash of the age commitment, if applicable.  Can be all zero
    244    */
    245   struct TALER_AgeCommitmentHashP h_age_commitment;
    246 
    247   /**
    248    * Hash of the blinded new coin.
    249    */
    250   struct TALER_BlindedCoinHashP coin_envelope_hash;
    251 };
    252 
    253 GNUNET_NETWORK_STRUCT_END
    254 
    255 void
    256 TALER_wallet_link_sign (const struct TALER_DenominationHashP *h_denom_pub,
    257                         const struct TALER_TransferPublicKeyP *transfer_pub,
    258                         const struct TALER_BlindedCoinHashP *bch,
    259                         const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
    260                         struct TALER_CoinSpendSignatureP *coin_sig)
    261 {
    262   struct TALER_LinkDataPS ldp = {
    263     .purpose.size = htonl (sizeof (ldp)),
    264     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
    265     .h_denom_pub = *h_denom_pub,
    266     .transfer_pub = *transfer_pub,
    267     .coin_envelope_hash = *bch
    268   };
    269 
    270   GNUNET_CRYPTO_eddsa_sign (&old_coin_priv->eddsa_priv,
    271                             &ldp,
    272                             &coin_sig->eddsa_signature);
    273 }
    274 
    275 
    276 enum GNUNET_GenericReturnValue
    277 TALER_wallet_link_verify (
    278   const struct TALER_DenominationHashP *h_denom_pub,
    279   const struct TALER_TransferPublicKeyP *transfer_pub,
    280   const struct TALER_BlindedCoinHashP *h_coin_ev,
    281   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
    282   const struct TALER_CoinSpendSignatureP *coin_sig)
    283 {
    284   struct TALER_LinkDataPS ldp = {
    285     .purpose.size = htonl (sizeof (ldp)),
    286     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
    287     .h_denom_pub = *h_denom_pub,
    288     .transfer_pub = *transfer_pub,
    289     .coin_envelope_hash = *h_coin_ev,
    290   };
    291 
    292   return
    293     GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_LINK,
    294                                 &ldp,
    295                                 &coin_sig->eddsa_signature,
    296                                 &old_coin_pub->eddsa_pub);
    297 }
    298 
    299 
    300 GNUNET_NETWORK_STRUCT_BEGIN
    301 
    302 /**
    303  * Signed data to request that a coin should be refunded as part of
    304  * the "emergency" /recoup protocol.  The refund will go back to the bank
    305  * account that created the reserve.
    306  */
    307 struct TALER_RecoupRequestPS
    308 {
    309   /**
    310    * Purpose is #TALER_SIGNATURE_WALLET_COIN_RECOUP
    311    * or #TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH.
    312    */
    313   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    314 
    315   /**
    316    * Hash of the (revoked) denomination public key of the coin.
    317    */
    318   struct TALER_DenominationHashP h_denom_pub;
    319 
    320   /**
    321    * Blinding factor that was used to withdraw the coin.
    322    */
    323   union GNUNET_CRYPTO_BlindingSecretP coin_blind;
    324 
    325 };
    326 
    327 GNUNET_NETWORK_STRUCT_END
    328 
    329 
    330 enum GNUNET_GenericReturnValue
    331 TALER_wallet_recoup_verify (
    332   const struct TALER_DenominationHashP *h_denom_pub,
    333   const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
    334   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    335   const struct TALER_CoinSpendSignatureP *coin_sig)
    336 {
    337   struct TALER_RecoupRequestPS pr = {
    338     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
    339     .purpose.size = htonl (sizeof (pr)),
    340     .h_denom_pub = *h_denom_pub,
    341     .coin_blind = *coin_bks
    342   };
    343 
    344   return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP,
    345                                      &pr,
    346                                      &coin_sig->eddsa_signature,
    347                                      &coin_pub->eddsa_pub);
    348 }
    349 
    350 
    351 void
    352 TALER_wallet_recoup_sign (
    353   const struct TALER_DenominationHashP *h_denom_pub,
    354   const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
    355   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    356   struct TALER_CoinSpendSignatureP *coin_sig)
    357 {
    358   struct TALER_RecoupRequestPS pr = {
    359     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP),
    360     .purpose.size = htonl (sizeof (pr)),
    361     .h_denom_pub = *h_denom_pub,
    362     .coin_blind = *coin_bks
    363   };
    364 
    365   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
    366                             &pr,
    367                             &coin_sig->eddsa_signature);
    368 }
    369 
    370 
    371 enum GNUNET_GenericReturnValue
    372 TALER_wallet_recoup_refresh_verify (
    373   const struct TALER_DenominationHashP *h_denom_pub,
    374   const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
    375   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    376   const struct TALER_CoinSpendSignatureP *coin_sig)
    377 {
    378   struct TALER_RecoupRequestPS pr = {
    379     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH),
    380     .purpose.size = htonl (sizeof (pr)),
    381     .h_denom_pub = *h_denom_pub,
    382     .coin_blind = *coin_bks
    383   };
    384 
    385   return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH,
    386                                      &pr,
    387                                      &coin_sig->eddsa_signature,
    388                                      &coin_pub->eddsa_pub);
    389 }
    390 
    391 
    392 void
    393 TALER_wallet_recoup_refresh_sign (
    394   const struct TALER_DenominationHashP *h_denom_pub,
    395   const union GNUNET_CRYPTO_BlindingSecretP *coin_bks,
    396   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    397   struct TALER_CoinSpendSignatureP *coin_sig)
    398 {
    399   struct TALER_RecoupRequestPS pr = {
    400     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_RECOUP_REFRESH),
    401     .purpose.size = htonl (sizeof (struct TALER_RecoupRequestPS)),
    402     .h_denom_pub = *h_denom_pub,
    403     .coin_blind = *coin_bks
    404   };
    405 
    406   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
    407                             &pr,
    408                             &coin_sig->eddsa_signature);
    409 }
    410 
    411 
    412 GNUNET_NETWORK_STRUCT_BEGIN
    413 
    414 /**
    415  * @brief Message signed by a coin to indicate that the coin should be
    416  * melted.
    417  */
    418 struct TALER_RefreshMeltCoinAffirmationPS
    419 {
    420   /**
    421    * Purpose is #TALER_SIGNATURE_WALLET_COIN_MELT.
    422    * Used for an EdDSA signature with the `struct TALER_CoinSpendPublicKeyP`.
    423    */
    424   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    425 
    426   /**
    427    * Which melt commitment is made by the wallet.
    428    */
    429   struct TALER_RefreshCommitmentP rc GNUNET_PACKED;
    430 
    431   /**
    432    * Hash over the denomination public key used to sign the coin.
    433    */
    434   struct TALER_DenominationHashP h_denom_pub GNUNET_PACKED;
    435 
    436   /**
    437    * If age commitment was provided during the withdrawal of the coin, this is
    438    * the hash of the age commitment vector.  It must be all zeroes if no age
    439    * commitment was provided.
    440    */
    441   struct TALER_AgeCommitmentHashP h_age_commitment GNUNET_PACKED;
    442 
    443   /**
    444    * How much of the value of the coin should be melted?  This amount
    445    * includes the fees, so the final amount contributed to the melt is
    446    * this value minus the fee for melting the coin.  We include the
    447    * fee in what is being signed so that we can verify a reserve's
    448    * remaining total balance without needing to access the respective
    449    * denomination key information each time.
    450    */
    451   struct TALER_AmountNBO amount_with_fee;
    452 
    453   /**
    454    * Melting fee charged by the exchange.  This must match the Exchange's
    455    * denomination key's melting fee.  If the client puts in an invalid
    456    * melting fee (too high or too low) that does not match the Exchange's
    457    * denomination key, the melting operation is invalid and will be
    458    * rejected by the exchange.  The @e amount_with_fee minus the @e
    459    * melt_fee is the amount that will be credited to the melting
    460    * session.
    461    */
    462   struct TALER_AmountNBO melt_fee;
    463 };
    464 
    465 GNUNET_NETWORK_STRUCT_END
    466 
    467 void
    468 TALER_wallet_melt_sign (
    469   const struct TALER_Amount *amount_with_fee,
    470   const struct TALER_Amount *melt_fee,
    471   const struct TALER_RefreshCommitmentP *rc,
    472   const struct TALER_DenominationHashP *h_denom_pub,
    473   const struct TALER_AgeCommitmentHashP *h_age_commitment,
    474   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
    475   struct TALER_CoinSpendSignatureP *coin_sig)
    476 {
    477   struct TALER_RefreshMeltCoinAffirmationPS melt = {
    478     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT),
    479     .purpose.size = htonl (sizeof (melt)),
    480     .rc = *rc,
    481     .h_denom_pub = *h_denom_pub
    482   };
    483 
    484   if (NULL != h_age_commitment)
    485     melt.h_age_commitment = *h_age_commitment;
    486   TALER_amount_hton (&melt.amount_with_fee,
    487                      amount_with_fee);
    488   TALER_amount_hton (&melt.melt_fee,
    489                      melt_fee);
    490   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
    491                             &melt,
    492                             &coin_sig->eddsa_signature);
    493 }
    494 
    495 
    496 enum GNUNET_GenericReturnValue
    497 TALER_wallet_melt_verify (
    498   const struct TALER_Amount *amount_with_fee,
    499   const struct TALER_Amount *melt_fee,
    500   const struct TALER_RefreshCommitmentP *rc,
    501   const struct TALER_DenominationHashP *h_denom_pub,
    502   const struct TALER_AgeCommitmentHashP *h_age_commitment,
    503   const struct TALER_CoinSpendPublicKeyP *coin_pub,
    504   const struct TALER_CoinSpendSignatureP *coin_sig)
    505 {
    506   struct TALER_RefreshMeltCoinAffirmationPS melt = {
    507     .purpose.size = htonl (sizeof (melt)),
    508     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT),
    509     .rc = *rc,
    510     .h_denom_pub = *h_denom_pub
    511   };
    512 
    513   if (NULL != h_age_commitment)
    514     melt.h_age_commitment = *h_age_commitment;
    515   TALER_amount_hton (&melt.amount_with_fee,
    516                      amount_with_fee);
    517   TALER_amount_hton (&melt.melt_fee,
    518                      melt_fee);
    519   return GNUNET_CRYPTO_eddsa_verify (
    520     TALER_SIGNATURE_WALLET_COIN_MELT,
    521     &melt,
    522     &coin_sig->eddsa_signature,
    523     &coin_pub->eddsa_pub);
    524 }
    525 
    526 
    527 GNUNET_NETWORK_STRUCT_BEGIN
    528 
    529 /**
    530  * @brief Format used for to generate the signature on a refresh nonce,
    531  *  a) to prove ownership of the old coin's private key and
    532  *  b) to derive the planchet master secrets for the batch of fresh coins
    533  */
    534 struct TALER_RefreshNonceSignaturePS
    535 {
    536 
    537   /**
    538    * Purpose must be #TALER_SIGNATURE_WALLET_COIN_LINK
    539    */
    540   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    541 
    542   /**
    543    * The nonce to sign
    544    */
    545   struct TALER_PublicRefreshNonceP nonce GNUNET_PACKED;
    546 
    547   /**
    548    * The running hash of the (hashes of) denomination public keys
    549    */
    550   struct GNUNET_HashCode h_denoms_h GNUNET_PACKED;
    551 
    552   /**
    553    * The kappa index for this signature, in NBO
    554    */
    555   uint32_t kappa_index GNUNET_PACKED;
    556 };
    557 
    558 GNUNET_NETWORK_STRUCT_END
    559 
    560 
    561 void
    562 TALER_wallet_refresh_nonce_sign (
    563   const struct TALER_CoinSpendPrivateKeyP *old_coin_priv,
    564   const struct TALER_PublicRefreshNonceP *nonce,
    565   size_t num_denoms_h,
    566   const struct TALER_DenominationHashP *denoms_h[static num_denoms_h],
    567   uint8_t kappa_index,
    568   struct TALER_PrivateRefreshNonceSignatureP *sig)
    569 {
    570   struct TALER_RefreshNonceSignaturePS req = {
    571     .purpose.size = htonl (sizeof (req)),
    572     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
    573     .nonce = *nonce,
    574     .kappa_index = htonl (kappa_index),
    575   };
    576   struct GNUNET_HashContext *ctx = GNUNET_CRYPTO_hash_context_start ();
    577   GNUNET_assert (ctx);
    578 
    579   for (size_t i = 0; i<num_denoms_h; i++)
    580     GNUNET_CRYPTO_hash_context_read (ctx,
    581                                      denoms_h[i],
    582                                      sizeof(*denoms_h[i]));
    583 
    584   GNUNET_CRYPTO_hash_context_finish (ctx,
    585                                      &req.h_denoms_h);
    586   GNUNET_CRYPTO_eddsa_sign (&old_coin_priv->eddsa_priv,
    587                             &req,
    588                             &sig->coin_sig.eddsa_signature);
    589 }
    590 
    591 
    592 enum GNUNET_GenericReturnValue
    593 TALER_wallet_refresh_nonce_verify (
    594   const struct TALER_CoinSpendPublicKeyP *old_coin_pub,
    595   const struct TALER_PublicRefreshNonceP *nonce,
    596   size_t num_denoms_h,
    597   struct TALER_DenominationHashP *const denoms_h[static num_denoms_h],
    598   uint8_t kappa_index,
    599   const struct TALER_PrivateRefreshNonceSignatureP *sig)
    600 {
    601   struct TALER_RefreshNonceSignaturePS req = {
    602     .purpose.size = htonl (sizeof (req)),
    603     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK),
    604     .nonce = *nonce,
    605     .kappa_index = htonl (kappa_index),
    606   };
    607   struct GNUNET_HashContext *ctx = GNUNET_CRYPTO_hash_context_start ();
    608   GNUNET_assert (ctx);
    609 
    610   for (size_t i = 0; i<num_denoms_h; i++)
    611     GNUNET_CRYPTO_hash_context_read (ctx,
    612                                      denoms_h[i],
    613                                      sizeof(*denoms_h[i]));
    614 
    615   GNUNET_CRYPTO_hash_context_finish (ctx,
    616                                      &req.h_denoms_h);
    617   return GNUNET_CRYPTO_eddsa_verify (
    618     TALER_SIGNATURE_WALLET_COIN_LINK,
    619     &req,
    620     &sig->coin_sig.eddsa_signature,
    621     &old_coin_pub->eddsa_pub);
    622 }
    623 
    624 
    625 GNUNET_NETWORK_STRUCT_BEGIN
    626 
    627 
    628 /**
    629  * @brief Format used for to generate the signature on a request to withdraw
    630  * coins from a reserve.
    631  * @note: deprecated.  Will be removed at some point after v24 of the protocol.
    632  */
    633 struct TALER_WithdrawCommitmentPre24PS
    634 {
    635 
    636   /**
    637    * Purpose must be #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW.
    638    * Used with an EdDSA signature of a `struct TALER_ReservePublicKeyP`.
    639    */
    640   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    641 
    642   /**
    643    * Value of the coin being exchanged (matching the denomination key)
    644    * plus the transaction fee.  We include this in what is being
    645    * signed so that we can verify a reserve's remaining total balance
    646    * without needing to access the respective denomination key
    647    * information each time.
    648    */
    649   struct TALER_AmountNBO amount_with_fee;
    650 
    651   /**
    652    * Hash of the denomination public key for the coin that is withdrawn.
    653    */
    654   struct TALER_DenominationHashP h_denomination_pub GNUNET_PACKED;
    655 
    656   /**
    657    * Hash of the (blinded) message to be signed by the Exchange.
    658    */
    659   struct TALER_BlindedCoinHashP h_coin_envelope GNUNET_PACKED;
    660 };
    661 
    662 
    663 GNUNET_NETWORK_STRUCT_END
    664 
    665 void
    666 TALER_wallet_withdraw_sign_pre26 (
    667   const struct TALER_DenominationHashP *h_denom_pub,
    668   const struct TALER_Amount *amount_with_fee,
    669   const struct TALER_BlindedCoinHashP *bch,
    670   const struct TALER_ReservePrivateKeyP *reserve_priv,
    671   struct TALER_ReserveSignatureP *reserve_sig)
    672 {
    673   struct TALER_WithdrawCommitmentPre24PS req = {
    674     .purpose.size = htonl (sizeof (req)),
    675     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
    676     .h_denomination_pub = *h_denom_pub,
    677     .h_coin_envelope = *bch
    678   };
    679 
    680   TALER_amount_hton (&req.amount_with_fee,
    681                      amount_with_fee);
    682   GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
    683                             &req,
    684                             &reserve_sig->eddsa_signature);
    685 }
    686 
    687 
    688 enum GNUNET_GenericReturnValue
    689 TALER_wallet_withdraw_verify_pre26 (
    690   const struct TALER_DenominationHashP *h_denom_pub,
    691   const struct TALER_Amount *amount_with_fee,
    692   const struct TALER_BlindedCoinHashP *bch,
    693   const struct TALER_ReservePublicKeyP *reserve_pub,
    694   const struct TALER_ReserveSignatureP *reserve_sig)
    695 {
    696   struct TALER_WithdrawCommitmentPre24PS req = {
    697     .purpose.size = htonl (sizeof (req)),
    698     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
    699     .h_denomination_pub = *h_denom_pub,
    700     .h_coin_envelope = *bch
    701   };
    702 
    703   TALER_amount_hton (&req.amount_with_fee,
    704                      amount_with_fee);
    705   return GNUNET_CRYPTO_eddsa_verify (
    706     TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
    707     &req,
    708     &reserve_sig->eddsa_signature,
    709     &reserve_pub->eddsa_pub);
    710 }
    711 
    712 
    713 GNUNET_NETWORK_STRUCT_BEGIN
    714 
    715 /**
    716  * @brief Format used for to generate the signature on a request to withdraw
    717  * coins from a reserve.
    718  *
    719  */
    720 struct TALER_WithdrawRequestPS
    721 {
    722   /**
    723    * Purpose is #TALER_SIGNATURE_WALLET_WITHDRAW
    724    */
    725   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    726 
    727   /**
    728    * Total value of all coins being exchanged (matching the denomination keys),
    729    * without the fee.
    730    * Note that the reserve must have a value of at least amount+fee.
    731    */
    732   struct TALER_AmountNBO amount;
    733 
    734   /**
    735    * Total fee for the withdrawal.
    736    * Note that the reserve must have a value of at least amount+fee.
    737    */
    738   struct TALER_AmountNBO fee;
    739 
    740   /**
    741    * Running SHA512 hash of all TALER_BlindedCoinHashP's
    742    * of the of n coins, or n*kappa candidate coins in case of age restriction.
    743    * In the later case, the coins' hashes are arranged [0..num_coins)...[0..num_coins),
    744    * i.e. the coins are grouped per kappa-index.
    745    * Note that each coin's TALER_BlindedCoinHashP also captures
    746    * the hash of the public key of the corresponding denomination.
    747    */
    748   struct TALER_HashBlindedPlanchetsP h_planchets GNUNET_PACKED;
    749 
    750   /**
    751    * If any of the denominations is of cipher type Clause-Schnorr,
    752    * the client had to call /blinding-prepare prior to the withdraw
    753    * to retrieve public R-values for the CS signature scheme.
    754    * The input seed for that request must be provided here.
    755    * Otherwise, if no CS denomination is used, the struct must be all zeros.
    756    */
    757   struct TALER_BlindingMasterSeedP blinding_seed;
    758 
    759   /**
    760    * Maximum age group that the coins are going to be restricted to.
    761    * MUST be 0 if no age restriction applies.
    762    */
    763   uint32_t max_age_group;
    764 
    765   /**
    766    * The mask that defines the age groups.
    767    * MUST be the same for all denominations.
    768    * MUST be 0 if no age restriction applies.
    769    */
    770   struct TALER_AgeMask mask;
    771 
    772 };
    773 
    774 
    775 GNUNET_NETWORK_STRUCT_END
    776 
    777 void
    778 TALER_wallet_blinded_planchets_hash (
    779   size_t num_planchets,
    780   const struct TALER_BlindedPlanchet blinded_planchets[static num_planchets],
    781   const struct TALER_DenominationHashP h_denom_pubs[static num_planchets],
    782   struct TALER_HashBlindedPlanchetsP *h_planchets)
    783 {
    784   struct TALER_BlindedCoinHashP bch;
    785   struct GNUNET_HashContext *coins_hctx;
    786 
    787   GNUNET_assert (num_planchets > 0);
    788   GNUNET_assert (NULL != h_planchets);
    789 
    790   coins_hctx = GNUNET_CRYPTO_hash_context_start ();
    791   GNUNET_assert (NULL != coins_hctx);
    792 
    793   for (size_t i = 0; i < num_planchets; i++)
    794   {
    795     TALER_coin_ev_hash (
    796       &blinded_planchets[i],
    797       &h_denom_pubs[i],
    798       &bch);
    799     GNUNET_CRYPTO_hash_context_read (
    800       coins_hctx,
    801       &bch,
    802       sizeof(bch));
    803   }
    804 
    805   GNUNET_CRYPTO_hash_context_finish (
    806     coins_hctx,
    807     &h_planchets->hash);
    808 }
    809 
    810 
    811 void
    812 TALER_wallet_blinded_planchet_details_hash (
    813   size_t num_planchets,
    814   const struct TALER_PlanchetDetail planchet_details[static num_planchets],
    815   struct TALER_HashBlindedPlanchetsP *h_planchets)
    816 {
    817   struct TALER_BlindedCoinHashP bch;
    818   struct GNUNET_HashContext *coins_hctx;
    819 
    820   GNUNET_assert (num_planchets > 0);
    821   GNUNET_assert (NULL != h_planchets);
    822 
    823   coins_hctx = GNUNET_CRYPTO_hash_context_start ();
    824   GNUNET_assert (NULL != coins_hctx);
    825 
    826   for (size_t i = 0; i < num_planchets; i++)
    827   {
    828     TALER_coin_ev_hash (
    829       &planchet_details[i].blinded_planchet,
    830       &planchet_details[i].denom_pub_hash,
    831       &bch);
    832     GNUNET_CRYPTO_hash_context_read (
    833       coins_hctx,
    834       &bch,
    835       sizeof(bch));
    836   }
    837 
    838   GNUNET_CRYPTO_hash_context_finish (
    839     coins_hctx,
    840     &h_planchets->hash);
    841 }
    842 
    843 
    844 struct TALER_HashReservePublicKeyP
    845 TALER_wallet_hash_reserve_pub (
    846   const struct TALER_ReservePublicKeyP *reserve_pub)
    847 {
    848   struct TALER_HashReservePublicKeyP hr;
    849 
    850   GNUNET_CRYPTO_hash (reserve_pub,
    851                       sizeof(*reserve_pub),
    852                       &hr.hash);
    853   return hr;
    854 }
    855 
    856 
    857 void
    858 TALER_wallet_withdraw_sign (
    859   const struct TALER_Amount *amount,
    860   const struct TALER_Amount *fee,
    861   const struct TALER_HashBlindedPlanchetsP *h_planchets,
    862   const struct TALER_BlindingMasterSeedP *blinding_seed,
    863   const struct TALER_AgeMask *mask,
    864   uint8_t max_age,
    865   const struct TALER_ReservePrivateKeyP *reserve_priv,
    866   struct TALER_ReserveSignatureP *reserve_sig)
    867 {
    868   struct TALER_WithdrawRequestPS req = {
    869     .purpose.size = htonl (sizeof(req)),
    870     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
    871   };
    872 
    873   GNUNET_assert (NULL != h_planchets);
    874   req.h_planchets = *h_planchets;
    875   if (NULL != mask)
    876   {
    877     req.mask = *mask;
    878     req.max_age_group =
    879       TALER_get_age_group (mask,
    880                            max_age);
    881   }
    882   TALER_amount_hton (&req.amount,
    883                      amount);
    884   TALER_amount_hton (&req.fee,
    885                      fee);
    886   if (NULL != blinding_seed)
    887     req.blinding_seed = *blinding_seed;
    888 
    889   GNUNET_CRYPTO_eddsa_sign (
    890     &reserve_priv->eddsa_priv,
    891     &req,
    892     &reserve_sig->eddsa_signature);
    893 
    894 }
    895 
    896 
    897 enum GNUNET_GenericReturnValue
    898 TALER_wallet_withdraw_verify (
    899   const struct TALER_Amount *amount,
    900   const struct TALER_Amount *fee,
    901   const struct TALER_HashBlindedPlanchetsP *h_planchets,
    902   const struct TALER_BlindingMasterSeedP *blinding_seed,
    903   const struct TALER_AgeMask *mask,
    904   uint8_t max_age,
    905   const struct TALER_ReservePublicKeyP *reserve_pub,
    906   const struct TALER_ReserveSignatureP *reserve_sig)
    907 {
    908   struct TALER_WithdrawRequestPS req = {
    909     .purpose.size = htonl (sizeof(req)),
    910     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW),
    911   };
    912 
    913   GNUNET_assert (NULL != h_planchets);
    914   req.h_planchets = *h_planchets;
    915   if (NULL != mask)
    916   {
    917     req.mask = *mask;
    918     req.max_age_group =
    919       TALER_get_age_group (mask,
    920                            max_age);
    921   }
    922   TALER_amount_hton (&req.amount,
    923                      amount);
    924   TALER_amount_hton (&req.fee,
    925                      fee);
    926   if (NULL != blinding_seed)
    927     req.blinding_seed = *blinding_seed;
    928 
    929   return GNUNET_CRYPTO_eddsa_verify (
    930     TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW,
    931     &req,
    932     &reserve_sig->eddsa_signature,
    933     &reserve_pub->eddsa_pub);
    934 }
    935 
    936 
    937 GNUNET_NETWORK_STRUCT_BEGIN
    938 
    939 
    940 /**
    941  * @brief Format used for to generate the signature on a request to withdraw
    942  * coins from a reserve.
    943  */
    944 struct TALER_AccountSetupRequestSignaturePS
    945 {
    946 
    947   /**
    948    * Purpose must be #TALER_SIGNATURE_WALLET_ACCOUNT_SETUP.
    949    * Used with an EdDSA signature of a `struct TALER_ReservePublicKeyP`.
    950    */
    951   struct GNUNET_CRYPTO_SignaturePurpose purpose;
    952 
    953   /**
    954    * Balance threshold the wallet is about to cross.
    955    */
    956   struct TALER_AmountNBO threshold;
    957 
    958 };
    959 
    960 
    961 GNUNET_NETWORK_STRUCT_END
    962 
    963 
    964 void
    965 TALER_wallet_account_setup_sign (
    966   const struct TALER_ReservePrivateKeyP *reserve_priv,
    967   const struct TALER_Amount *balance_threshold,
    968   struct TALER_ReserveSignatureP *reserve_sig)
    969 {
    970   struct TALER_AccountSetupRequestSignaturePS asap = {
    971     .purpose.size = htonl (sizeof (asap)),
    972     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP)
    973   };
    974 
    975   TALER_amount_hton (&asap.threshold,
    976                      balance_threshold);
    977   GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
    978                             &asap,
    979                             &reserve_sig->eddsa_signature);
    980 }
    981 
    982 
    983 enum GNUNET_GenericReturnValue
    984 TALER_wallet_account_setup_verify (
    985   const struct TALER_ReservePublicKeyP *reserve_pub,
    986   const struct TALER_Amount *balance_threshold,
    987   const struct TALER_ReserveSignatureP *reserve_sig)
    988 {
    989   struct TALER_AccountSetupRequestSignaturePS asap = {
    990     .purpose.size = htonl (sizeof (asap)),
    991     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_SETUP)
    992   };
    993 
    994   TALER_amount_hton (&asap.threshold,
    995                      balance_threshold);
    996   return GNUNET_CRYPTO_eddsa_verify (
    997     TALER_SIGNATURE_WALLET_ACCOUNT_SETUP,
    998     &asap,
    999     &reserve_sig->eddsa_signature,
   1000     &reserve_pub->eddsa_pub);
   1001 }
   1002 
   1003 
   1004 GNUNET_NETWORK_STRUCT_BEGIN
   1005 
   1006 
   1007 /**
   1008  * Response by which a wallet requests a reserve history.
   1009  */
   1010 struct TALER_ReserveHistoryRequestPS
   1011 {
   1012 
   1013   /**
   1014    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_HISTORY
   1015    */
   1016   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1017 
   1018   /**
   1019    * Which entries to exclude. Only return above this offset.
   1020    */
   1021   uint64_t start_off;
   1022 
   1023 };
   1024 
   1025 GNUNET_NETWORK_STRUCT_END
   1026 
   1027 
   1028 enum GNUNET_GenericReturnValue
   1029 TALER_wallet_reserve_history_verify (
   1030   uint64_t start_off,
   1031   const struct TALER_ReservePublicKeyP *reserve_pub,
   1032   const struct TALER_ReserveSignatureP *reserve_sig)
   1033 {
   1034   struct TALER_ReserveHistoryRequestPS rhr = {
   1035     .purpose.size = htonl (sizeof (rhr)),
   1036     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_HISTORY),
   1037     .start_off = GNUNET_htonll (start_off)
   1038   };
   1039 
   1040   return GNUNET_CRYPTO_eddsa_verify (
   1041     TALER_SIGNATURE_WALLET_RESERVE_HISTORY,
   1042     &rhr,
   1043     &reserve_sig->eddsa_signature,
   1044     &reserve_pub->eddsa_pub);
   1045 }
   1046 
   1047 
   1048 void
   1049 TALER_wallet_reserve_history_sign (
   1050   uint64_t start_off,
   1051   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1052   struct TALER_ReserveSignatureP *reserve_sig)
   1053 {
   1054   struct TALER_ReserveHistoryRequestPS rhr = {
   1055     .purpose.size = htonl (sizeof (rhr)),
   1056     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_HISTORY),
   1057     .start_off = GNUNET_htonll (start_off)
   1058   };
   1059 
   1060   GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
   1061                             &rhr,
   1062                             &reserve_sig->eddsa_signature);
   1063 }
   1064 
   1065 
   1066 GNUNET_NETWORK_STRUCT_BEGIN
   1067 
   1068 /**
   1069  * Response by which a wallet requests a coin history.
   1070  */
   1071 struct TALER_CoinHistoryRequestPS
   1072 {
   1073 
   1074   /**
   1075    * Purpose is #TALER_SIGNATURE_WALLET_COIN_HISTORY
   1076    */
   1077   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1078 
   1079   /**
   1080    * Which entries to exclude. Only return above this offset.
   1081    */
   1082   uint64_t start_off;
   1083 
   1084 };
   1085 
   1086 GNUNET_NETWORK_STRUCT_END
   1087 
   1088 enum GNUNET_GenericReturnValue
   1089 TALER_wallet_coin_history_verify (
   1090   uint64_t start_off,
   1091   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1092   const struct TALER_CoinSpendSignatureP *coin_sig)
   1093 {
   1094   struct TALER_CoinHistoryRequestPS rsr = {
   1095     .purpose.size = htonl (sizeof (rsr)),
   1096     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_HISTORY),
   1097     .start_off = GNUNET_htonll (start_off)
   1098   };
   1099 
   1100   return GNUNET_CRYPTO_eddsa_verify (
   1101     TALER_SIGNATURE_WALLET_COIN_HISTORY,
   1102     &rsr,
   1103     &coin_sig->eddsa_signature,
   1104     &coin_pub->eddsa_pub);
   1105 }
   1106 
   1107 
   1108 void
   1109 TALER_wallet_coin_history_sign (
   1110   uint64_t start_off,
   1111   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   1112   struct TALER_CoinSpendSignatureP *coin_sig)
   1113 {
   1114   struct TALER_CoinHistoryRequestPS rsr = {
   1115     .purpose.size = htonl (sizeof (rsr)),
   1116     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_HISTORY),
   1117     .start_off = GNUNET_htonll (start_off)
   1118   };
   1119 
   1120   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
   1121                             &rsr,
   1122                             &coin_sig->eddsa_signature);
   1123 }
   1124 
   1125 
   1126 GNUNET_NETWORK_STRUCT_BEGIN
   1127 
   1128 /**
   1129  * Message signed to create a purse (without reserve).
   1130  */
   1131 struct TALER_PurseCreatePS
   1132 {
   1133 
   1134   /**
   1135    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_CREATE
   1136    */
   1137   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1138 
   1139   /**
   1140    * Time when the purse will expire if still unmerged or unpaid.
   1141    */
   1142   struct GNUNET_TIME_TimestampNBO purse_expiration;
   1143 
   1144   /**
   1145    * Total amount (with fees) to be put into the purse.
   1146    */
   1147   struct TALER_AmountNBO purse_amount;
   1148 
   1149   /**
   1150    * Contract this purse pays for.
   1151    */
   1152   struct TALER_PrivateContractHashP h_contract_terms;
   1153 
   1154   /**
   1155    * Public key identifying the merge capability.
   1156    */
   1157   struct TALER_PurseMergePublicKeyP merge_pub;
   1158 
   1159   /**
   1160    * Minimum age required for payments into this purse.
   1161    */
   1162   uint32_t min_age GNUNET_PACKED;
   1163 
   1164 };
   1165 
   1166 
   1167 GNUNET_NETWORK_STRUCT_END
   1168 
   1169 
   1170 void
   1171 TALER_wallet_purse_create_sign (
   1172   struct GNUNET_TIME_Timestamp purse_expiration,
   1173   const struct TALER_PrivateContractHashP *h_contract_terms,
   1174   const struct TALER_PurseMergePublicKeyP *merge_pub,
   1175   uint32_t min_age,
   1176   const struct TALER_Amount *amount,
   1177   const struct TALER_PurseContractPrivateKeyP *purse_priv,
   1178   struct TALER_PurseContractSignatureP *purse_sig)
   1179 {
   1180   struct TALER_PurseCreatePS pm = {
   1181     .purpose.size = htonl (sizeof (pm)),
   1182     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_CREATE),
   1183     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1184     .h_contract_terms = *h_contract_terms,
   1185     .merge_pub = *merge_pub,
   1186     .min_age = htonl (min_age)
   1187   };
   1188 
   1189   TALER_amount_hton (&pm.purse_amount,
   1190                      amount);
   1191   GNUNET_CRYPTO_eddsa_sign (&purse_priv->eddsa_priv,
   1192                             &pm,
   1193                             &purse_sig->eddsa_signature);
   1194 }
   1195 
   1196 
   1197 enum GNUNET_GenericReturnValue
   1198 TALER_wallet_purse_create_verify (
   1199   struct GNUNET_TIME_Timestamp purse_expiration,
   1200   const struct TALER_PrivateContractHashP *h_contract_terms,
   1201   const struct TALER_PurseMergePublicKeyP *merge_pub,
   1202   uint32_t min_age,
   1203   const struct TALER_Amount *amount,
   1204   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1205   const struct TALER_PurseContractSignatureP *purse_sig)
   1206 {
   1207   struct TALER_PurseCreatePS pm = {
   1208     .purpose.size = htonl (sizeof (pm)),
   1209     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_CREATE),
   1210     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1211     .h_contract_terms = *h_contract_terms,
   1212     .merge_pub = *merge_pub,
   1213     .min_age = htonl (min_age)
   1214   };
   1215 
   1216   TALER_amount_hton (&pm.purse_amount,
   1217                      amount);
   1218   return GNUNET_CRYPTO_eddsa_verify (
   1219     TALER_SIGNATURE_WALLET_PURSE_CREATE,
   1220     &pm,
   1221     &purse_sig->eddsa_signature,
   1222     &purse_pub->eddsa_pub);
   1223 }
   1224 
   1225 
   1226 GNUNET_NETWORK_STRUCT_BEGIN
   1227 
   1228 /**
   1229  * Message signed to delete a purse.
   1230  */
   1231 struct TALER_PurseDeletePS
   1232 {
   1233 
   1234   /**
   1235    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_DELETE
   1236    */
   1237   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1238 
   1239 };
   1240 
   1241 
   1242 GNUNET_NETWORK_STRUCT_END
   1243 
   1244 
   1245 void
   1246 TALER_wallet_purse_delete_sign (
   1247   const struct TALER_PurseContractPrivateKeyP *purse_priv,
   1248   struct TALER_PurseContractSignatureP *purse_sig)
   1249 {
   1250   struct TALER_PurseDeletePS pm = {
   1251     .purpose.size = htonl (sizeof (pm)),
   1252     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DELETE)
   1253   };
   1254 
   1255   GNUNET_CRYPTO_eddsa_sign (&purse_priv->eddsa_priv,
   1256                             &pm,
   1257                             &purse_sig->eddsa_signature);
   1258 }
   1259 
   1260 
   1261 enum GNUNET_GenericReturnValue
   1262 TALER_wallet_purse_delete_verify (
   1263   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1264   const struct TALER_PurseContractSignatureP *purse_sig)
   1265 {
   1266   struct TALER_PurseDeletePS pm = {
   1267     .purpose.size = htonl (sizeof (pm)),
   1268     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DELETE)
   1269   };
   1270 
   1271   return GNUNET_CRYPTO_eddsa_verify (
   1272     TALER_SIGNATURE_WALLET_PURSE_DELETE,
   1273     &pm,
   1274     &purse_sig->eddsa_signature,
   1275     &purse_pub->eddsa_pub);
   1276 }
   1277 
   1278 
   1279 void
   1280 TALER_wallet_purse_status_sign (
   1281   const struct TALER_PurseContractPrivateKeyP *purse_priv,
   1282   struct TALER_PurseContractSignatureP *purse_sig)
   1283 {
   1284   struct GNUNET_CRYPTO_SignaturePurpose purpose = {
   1285     .size = htonl (sizeof (purpose)),
   1286     .purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_STATUS)
   1287   };
   1288 
   1289   GNUNET_assert (GNUNET_OK ==
   1290                  GNUNET_CRYPTO_eddsa_sign_ (&purse_priv->eddsa_priv,
   1291                                             &purpose,
   1292                                             &purse_sig->eddsa_signature));
   1293 }
   1294 
   1295 
   1296 enum GNUNET_GenericReturnValue
   1297 TALER_wallet_purse_status_verify (
   1298   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1299   const struct TALER_PurseContractSignatureP *purse_sig)
   1300 {
   1301   struct GNUNET_CRYPTO_SignaturePurpose purpose = {
   1302     .size = htonl (sizeof (purpose)),
   1303     .purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_STATUS)
   1304   };
   1305 
   1306   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_PURSE_STATUS,
   1307                                       &purpose,
   1308                                       &purse_sig->eddsa_signature,
   1309                                       &purse_pub->eddsa_pub);
   1310 }
   1311 
   1312 
   1313 GNUNET_NETWORK_STRUCT_BEGIN
   1314 
   1315 /**
   1316  * Message signed to deposit a coin into a purse.
   1317  */
   1318 struct TALER_PurseDepositPS
   1319 {
   1320 
   1321   /**
   1322    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_DEPOSIT
   1323    */
   1324   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1325 
   1326   /**
   1327    * Amount (with deposit fee) to be deposited into the purse.
   1328    */
   1329   struct TALER_AmountNBO coin_amount;
   1330 
   1331   /**
   1332    * Hash over the denomination public key used to sign the coin.
   1333    */
   1334   struct TALER_DenominationHashP h_denom_pub GNUNET_PACKED;
   1335 
   1336   /**
   1337    * Hash over the age commitment that went into the coin. Maybe all zero, if
   1338    * age commitment isn't applicable to the denomination.
   1339    */
   1340   struct TALER_AgeCommitmentHashP h_age_commitment GNUNET_PACKED;
   1341 
   1342   /**
   1343    * Purse to deposit funds into.
   1344    */
   1345   struct TALER_PurseContractPublicKeyP purse_pub;
   1346 
   1347   /**
   1348    * Hash of the base URL of the exchange hosting the
   1349    * @e purse_pub.
   1350    */
   1351   struct GNUNET_HashCode h_exchange_base_url GNUNET_PACKED;
   1352 };
   1353 
   1354 GNUNET_NETWORK_STRUCT_END
   1355 
   1356 void
   1357 TALER_wallet_purse_deposit_sign (
   1358   const char *exchange_base_url,
   1359   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1360   const struct TALER_Amount *amount,
   1361   const struct TALER_DenominationHashP *h_denom_pub,
   1362   const struct TALER_AgeCommitmentHashP *h_age_commitment,
   1363   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   1364   struct TALER_CoinSpendSignatureP *coin_sig)
   1365 {
   1366   struct TALER_PurseDepositPS pm = {
   1367     .purpose.size = htonl (sizeof (pm)),
   1368     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DEPOSIT),
   1369     .purse_pub = *purse_pub,
   1370     .h_denom_pub = *h_denom_pub,
   1371     .h_age_commitment = *h_age_commitment
   1372   };
   1373 
   1374   GNUNET_CRYPTO_hash (exchange_base_url,
   1375                       strlen (exchange_base_url) + 1,
   1376                       &pm.h_exchange_base_url);
   1377   TALER_amount_hton (&pm.coin_amount,
   1378                      amount);
   1379   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
   1380                             &pm,
   1381                             &coin_sig->eddsa_signature);
   1382 }
   1383 
   1384 
   1385 enum GNUNET_GenericReturnValue
   1386 TALER_wallet_purse_deposit_verify (
   1387   const char *exchange_base_url,
   1388   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1389   const struct TALER_Amount *amount,
   1390   const struct TALER_DenominationHashP *h_denom_pub,
   1391   const struct TALER_AgeCommitmentHashP *h_age_commitment,
   1392   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1393   const struct TALER_CoinSpendSignatureP *coin_sig)
   1394 {
   1395   struct TALER_PurseDepositPS pm = {
   1396     .purpose.size = htonl (sizeof (pm)),
   1397     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DEPOSIT),
   1398     .purse_pub = *purse_pub,
   1399     .h_denom_pub = *h_denom_pub,
   1400     .h_age_commitment = *h_age_commitment
   1401   };
   1402 
   1403   GNUNET_CRYPTO_hash (exchange_base_url,
   1404                       strlen (exchange_base_url) + 1,
   1405                       &pm.h_exchange_base_url);
   1406   TALER_amount_hton (&pm.coin_amount,
   1407                      amount);
   1408   return GNUNET_CRYPTO_eddsa_verify (
   1409     TALER_SIGNATURE_WALLET_PURSE_DEPOSIT,
   1410     &pm,
   1411     &coin_sig->eddsa_signature,
   1412     &coin_pub->eddsa_pub);
   1413 }
   1414 
   1415 
   1416 GNUNET_NETWORK_STRUCT_BEGIN
   1417 
   1418 /**
   1419  * Message signed to merge a purse into a reserve.
   1420  */
   1421 struct TALER_PurseMergePS
   1422 {
   1423 
   1424   /**
   1425    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_MERGE
   1426    */
   1427   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1428 
   1429   /**
   1430    * Time when the purse is merged into the reserve.
   1431    */
   1432   struct GNUNET_TIME_TimestampNBO merge_timestamp;
   1433 
   1434   /**
   1435    * Which purse is being merged?
   1436    */
   1437   struct TALER_PurseContractPublicKeyP purse_pub;
   1438 
   1439   /**
   1440    * Which reserve should the purse be merged with.
   1441    * Hash of the reserve's payto:// URI.
   1442    */
   1443   struct TALER_NormalizedPaytoHashP h_payto;
   1444 
   1445 };
   1446 
   1447 GNUNET_NETWORK_STRUCT_END
   1448 
   1449 void
   1450 TALER_wallet_purse_merge_sign (
   1451   const struct TALER_NormalizedPayto reserve_uri,
   1452   struct GNUNET_TIME_Timestamp merge_timestamp,
   1453   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1454   const struct TALER_PurseMergePrivateKeyP *merge_priv,
   1455   struct TALER_PurseMergeSignatureP *merge_sig)
   1456 {
   1457   struct TALER_PurseMergePS pm = {
   1458     .purpose.size = htonl (sizeof (pm)),
   1459     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_MERGE),
   1460     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1461     .purse_pub = *purse_pub
   1462   };
   1463 
   1464   GNUNET_assert (0 ==
   1465                  strncasecmp (reserve_uri.normalized_payto,
   1466                               "payto://taler-reserve",
   1467                               strlen ("payto://taler-reserve")));
   1468   TALER_normalized_payto_hash (reserve_uri,
   1469                                &pm.h_payto);
   1470   GNUNET_CRYPTO_eddsa_sign (&merge_priv->eddsa_priv,
   1471                             &pm,
   1472                             &merge_sig->eddsa_signature);
   1473 }
   1474 
   1475 
   1476 enum GNUNET_GenericReturnValue
   1477 TALER_wallet_purse_merge_verify (
   1478   const struct TALER_NormalizedPayto reserve_uri,
   1479   struct GNUNET_TIME_Timestamp merge_timestamp,
   1480   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1481   const struct TALER_PurseMergePublicKeyP *merge_pub,
   1482   const struct TALER_PurseMergeSignatureP *merge_sig)
   1483 {
   1484   struct TALER_PurseMergePS pm = {
   1485     .purpose.size = htonl (sizeof (pm)),
   1486     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_MERGE),
   1487     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1488     .purse_pub = *purse_pub
   1489   };
   1490 
   1491   if (0 !=
   1492       strncasecmp (reserve_uri.normalized_payto,
   1493                    "payto://taler-reserve",
   1494                    strlen ("payto://taler-reserve")))
   1495   {
   1496     GNUNET_break (0);
   1497     return GNUNET_NO;
   1498   }
   1499   TALER_normalized_payto_hash (reserve_uri,
   1500                                &pm.h_payto);
   1501   return GNUNET_CRYPTO_eddsa_verify (
   1502     TALER_SIGNATURE_WALLET_PURSE_MERGE,
   1503     &pm,
   1504     &merge_sig->eddsa_signature,
   1505     &merge_pub->eddsa_pub);
   1506 }
   1507 
   1508 
   1509 GNUNET_NETWORK_STRUCT_BEGIN
   1510 
   1511 /**
   1512  * Message signed by account to merge a purse into a reserve.
   1513  */
   1514 struct TALER_AccountMergePS
   1515 {
   1516 
   1517   /**
   1518    * Purpose is #TALER_SIGNATURE_WALLET_ACCOUNT_MERGE
   1519    */
   1520   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1521 
   1522   /**
   1523    * Time when the purse will expire if still unmerged or unpaid.
   1524    */
   1525   struct GNUNET_TIME_TimestampNBO purse_expiration;
   1526 
   1527   /**
   1528    * Total amount (with fees) to be put into the purse.
   1529    */
   1530   struct TALER_AmountNBO purse_amount;
   1531 
   1532   /**
   1533    * Purse creation fee to be paid by the reserve for
   1534    * this operation.
   1535    */
   1536   struct TALER_AmountNBO purse_fee;
   1537 
   1538   /**
   1539    * Contract this purse pays for.
   1540    */
   1541   struct TALER_PrivateContractHashP h_contract_terms;
   1542 
   1543   /**
   1544    * Purse to merge.
   1545    */
   1546   struct TALER_PurseContractPublicKeyP purse_pub;
   1547 
   1548   /**
   1549    * Time when the purse is merged into the reserve.
   1550    */
   1551   struct GNUNET_TIME_TimestampNBO merge_timestamp;
   1552 
   1553   /**
   1554    * Minimum age required for payments into this purse,
   1555    * in NBO.
   1556    */
   1557   uint32_t min_age GNUNET_PACKED;
   1558 
   1559   /**
   1560    * Flags for the operation, in NBO. See
   1561    * `enum TALER_WalletAccountMergeFlags`.
   1562    */
   1563   uint32_t flags GNUNET_PACKED;
   1564 };
   1565 
   1566 GNUNET_NETWORK_STRUCT_END
   1567 
   1568 
   1569 void
   1570 TALER_wallet_account_merge_sign (
   1571   struct GNUNET_TIME_Timestamp merge_timestamp,
   1572   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1573   struct GNUNET_TIME_Timestamp purse_expiration,
   1574   const struct TALER_PrivateContractHashP *h_contract_terms,
   1575   const struct TALER_Amount *amount,
   1576   const struct TALER_Amount *purse_fee,
   1577   uint32_t min_age,
   1578   enum TALER_WalletAccountMergeFlags flags,
   1579   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1580   struct TALER_ReserveSignatureP *reserve_sig)
   1581 {
   1582   struct TALER_AccountMergePS pm = {
   1583     .purpose.size = htonl (sizeof (pm)),
   1584     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_MERGE),
   1585     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1586     .purse_pub = *purse_pub,
   1587     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1588     .h_contract_terms = *h_contract_terms,
   1589     .min_age = htonl (min_age),
   1590     .flags = htonl ((uint32_t) flags)
   1591   };
   1592 
   1593   TALER_amount_hton (&pm.purse_amount,
   1594                      amount);
   1595   TALER_amount_hton (&pm.purse_fee,
   1596                      purse_fee);
   1597   GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
   1598                             &pm,
   1599                             &reserve_sig->eddsa_signature);
   1600 }
   1601 
   1602 
   1603 enum GNUNET_GenericReturnValue
   1604 TALER_wallet_account_merge_verify (
   1605   struct GNUNET_TIME_Timestamp merge_timestamp,
   1606   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1607   struct GNUNET_TIME_Timestamp purse_expiration,
   1608   const struct TALER_PrivateContractHashP *h_contract_terms,
   1609   const struct TALER_Amount *amount,
   1610   const struct TALER_Amount *purse_fee,
   1611   uint32_t min_age,
   1612   enum TALER_WalletAccountMergeFlags flags,
   1613   const struct TALER_ReservePublicKeyP *reserve_pub,
   1614   const struct TALER_ReserveSignatureP *reserve_sig)
   1615 {
   1616   struct TALER_AccountMergePS pm = {
   1617     .purpose.size = htonl (sizeof (pm)),
   1618     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_MERGE),
   1619     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1620     .purse_pub = *purse_pub,
   1621     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1622     .h_contract_terms = *h_contract_terms,
   1623     .min_age = htonl (min_age),
   1624     .flags = htonl ((uint32_t) flags)
   1625   };
   1626 
   1627   TALER_amount_hton (&pm.purse_amount,
   1628                      amount);
   1629   TALER_amount_hton (&pm.purse_fee,
   1630                      purse_fee);
   1631   return GNUNET_CRYPTO_eddsa_verify (
   1632     TALER_SIGNATURE_WALLET_ACCOUNT_MERGE,
   1633     &pm,
   1634     &reserve_sig->eddsa_signature,
   1635     &reserve_pub->eddsa_pub);
   1636 }
   1637 
   1638 
   1639 GNUNET_NETWORK_STRUCT_BEGIN
   1640 
   1641 /**
   1642  * Message signed by reserve key.
   1643  */
   1644 struct TALER_ReserveOpenPS
   1645 {
   1646 
   1647   /**
   1648    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_OPEN
   1649    */
   1650   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1651 
   1652   /**
   1653    * Amount to be paid from the reserve balance to open
   1654    * the reserve.
   1655    */
   1656   struct TALER_AmountNBO reserve_payment;
   1657 
   1658   /**
   1659    * When was the request created.
   1660    */
   1661   struct GNUNET_TIME_TimestampNBO request_timestamp;
   1662 
   1663   /**
   1664    * For how long should the reserve be kept open.
   1665    * (Determines amount to be paid.)
   1666    */
   1667   struct GNUNET_TIME_TimestampNBO reserve_expiration;
   1668 
   1669   /**
   1670    * How many open purses should be included with the
   1671    * open reserve?
   1672    * (Determines amount to be paid.)
   1673    */
   1674   uint32_t purse_limit GNUNET_PACKED;
   1675 
   1676 };
   1677 
   1678 GNUNET_NETWORK_STRUCT_END
   1679 
   1680 
   1681 void
   1682 TALER_wallet_reserve_open_sign (
   1683   const struct TALER_Amount *reserve_payment,
   1684   struct GNUNET_TIME_Timestamp request_timestamp,
   1685   struct GNUNET_TIME_Timestamp reserve_expiration,
   1686   uint32_t purse_limit,
   1687   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1688   struct TALER_ReserveSignatureP *reserve_sig)
   1689 {
   1690   struct TALER_ReserveOpenPS rop = {
   1691     .purpose.size = htonl (sizeof (rop)),
   1692     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN),
   1693     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp),
   1694     .reserve_expiration = GNUNET_TIME_timestamp_hton (reserve_expiration),
   1695     .purse_limit = htonl (purse_limit)
   1696   };
   1697 
   1698   TALER_amount_hton (&rop.reserve_payment,
   1699                      reserve_payment);
   1700   GNUNET_assert (GNUNET_OK ==
   1701                  GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv,
   1702                                             &rop.purpose,
   1703                                             &reserve_sig->eddsa_signature));
   1704 }
   1705 
   1706 
   1707 enum GNUNET_GenericReturnValue
   1708 TALER_wallet_reserve_open_verify (
   1709   const struct TALER_Amount *reserve_payment,
   1710   struct GNUNET_TIME_Timestamp request_timestamp,
   1711   struct GNUNET_TIME_Timestamp reserve_expiration,
   1712   uint32_t purse_limit,
   1713   const struct TALER_ReservePublicKeyP *reserve_pub,
   1714   const struct TALER_ReserveSignatureP *reserve_sig)
   1715 {
   1716   struct TALER_ReserveOpenPS rop = {
   1717     .purpose.size = htonl (sizeof (rop)),
   1718     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN),
   1719     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp),
   1720     .reserve_expiration = GNUNET_TIME_timestamp_hton (reserve_expiration),
   1721     .purse_limit = htonl (purse_limit)
   1722   };
   1723 
   1724   TALER_amount_hton (&rop.reserve_payment,
   1725                      reserve_payment);
   1726   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_RESERVE_OPEN,
   1727                                       &rop.purpose,
   1728                                       &reserve_sig->eddsa_signature,
   1729                                       &reserve_pub->eddsa_pub);
   1730 }
   1731 
   1732 
   1733 GNUNET_NETWORK_STRUCT_BEGIN
   1734 
   1735 /**
   1736  * Message signed by
   1737  */
   1738 struct TALER_ReserveOpenDepositPS
   1739 {
   1740 
   1741   /**
   1742    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT
   1743    */
   1744   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1745 
   1746   /**
   1747    * Which reserve's opening signature should be paid for?
   1748    */
   1749   struct TALER_ReserveSignatureP reserve_sig;
   1750 
   1751   /**
   1752    * Specifies how much of the coin's value should be spent on opening this
   1753    * reserve.
   1754    */
   1755   struct TALER_AmountNBO coin_contribution;
   1756 };
   1757 
   1758 GNUNET_NETWORK_STRUCT_END
   1759 
   1760 
   1761 // FIXME-#11318: add h_age_commitment, h_denom_pub to have proof!
   1762 void
   1763 TALER_wallet_reserve_open_deposit_sign (
   1764   const struct TALER_Amount *coin_contribution,
   1765   const struct TALER_ReserveSignatureP *reserve_sig,
   1766   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   1767   struct TALER_CoinSpendSignatureP *coin_sig)
   1768 {
   1769   struct TALER_ReserveOpenDepositPS rod = {
   1770     .purpose.size = htonl (sizeof (rod)),
   1771     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT),
   1772     .reserve_sig = *reserve_sig
   1773   };
   1774 
   1775   TALER_amount_hton (&rod.coin_contribution,
   1776                      coin_contribution);
   1777   GNUNET_assert (GNUNET_OK ==
   1778                  GNUNET_CRYPTO_eddsa_sign_ (&coin_priv->eddsa_priv,
   1779                                             &rod.purpose,
   1780                                             &coin_sig->eddsa_signature));
   1781 }
   1782 
   1783 
   1784 enum GNUNET_GenericReturnValue
   1785 TALER_wallet_reserve_open_deposit_verify (
   1786   const struct TALER_Amount *coin_contribution,
   1787   const struct TALER_ReserveSignatureP *reserve_sig,
   1788   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1789   const struct TALER_CoinSpendSignatureP *coin_sig)
   1790 {
   1791   struct TALER_ReserveOpenDepositPS rod = {
   1792     .purpose.size = htonl (sizeof (rod)),
   1793     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT),
   1794     .reserve_sig = *reserve_sig
   1795   };
   1796 
   1797   TALER_amount_hton (&rod.coin_contribution,
   1798                      coin_contribution);
   1799   return GNUNET_CRYPTO_eddsa_verify_ (
   1800     TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT,
   1801     &rod.purpose,
   1802     &coin_sig->eddsa_signature,
   1803     &coin_pub->eddsa_pub);
   1804 }
   1805 
   1806 
   1807 GNUNET_NETWORK_STRUCT_BEGIN
   1808 
   1809 /**
   1810  * Message signed by reserve key.
   1811  */
   1812 struct TALER_ReserveClosePS
   1813 {
   1814 
   1815   /**
   1816    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_CLOSE
   1817    */
   1818   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1819 
   1820   /**
   1821    * When was the request created.
   1822    */
   1823   struct GNUNET_TIME_TimestampNBO request_timestamp;
   1824 
   1825   /**
   1826    * Hash of the payto://-URI of the target account
   1827    * for the closure, or all zeros for the reserve
   1828    * origin account.
   1829    */
   1830   struct TALER_FullPaytoHashP target_account_h_payto;
   1831 
   1832 };
   1833 
   1834 GNUNET_NETWORK_STRUCT_END
   1835 
   1836 
   1837 void
   1838 TALER_wallet_reserve_close_sign (
   1839   struct GNUNET_TIME_Timestamp request_timestamp,
   1840   const struct TALER_FullPaytoHashP *h_payto,
   1841   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1842   struct TALER_ReserveSignatureP *reserve_sig)
   1843 {
   1844   struct TALER_ReserveClosePS rcp = {
   1845     .purpose.size = htonl (sizeof (rcp)),
   1846     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE),
   1847     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1848   };
   1849 
   1850   if (NULL != h_payto)
   1851     rcp.target_account_h_payto = *h_payto;
   1852   GNUNET_assert (GNUNET_OK ==
   1853                  GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv,
   1854                                             &rcp.purpose,
   1855                                             &reserve_sig->eddsa_signature));
   1856 }
   1857 
   1858 
   1859 enum GNUNET_GenericReturnValue
   1860 TALER_wallet_reserve_close_verify (
   1861   struct GNUNET_TIME_Timestamp request_timestamp,
   1862   const struct TALER_FullPaytoHashP *h_payto,
   1863   const struct TALER_ReservePublicKeyP *reserve_pub,
   1864   const struct TALER_ReserveSignatureP *reserve_sig)
   1865 {
   1866   struct TALER_ReserveClosePS rcp = {
   1867     .purpose.size = htonl (sizeof (rcp)),
   1868     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE),
   1869     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1870   };
   1871 
   1872   if (NULL != h_payto)
   1873     rcp.target_account_h_payto = *h_payto;
   1874   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_RESERVE_CLOSE,
   1875                                       &rcp.purpose,
   1876                                       &reserve_sig->eddsa_signature,
   1877                                       &reserve_pub->eddsa_pub);
   1878 }
   1879 
   1880 
   1881 GNUNET_NETWORK_STRUCT_BEGIN
   1882 
   1883 /**
   1884  * Message signed by reserve private key.
   1885  */
   1886 struct TALER_ReserveAttestRequestPS
   1887 {
   1888 
   1889   /**
   1890    * Purpose is #TALER_SIGNATURE_WALLET_ATTEST_REQUEST
   1891    */
   1892   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1893 
   1894   /**
   1895    * When was the request created.
   1896    */
   1897   struct GNUNET_TIME_TimestampNBO request_timestamp;
   1898 
   1899   /**
   1900    * Hash over the JSON array of requested attributes.
   1901    */
   1902   struct GNUNET_HashCode h_details;
   1903 
   1904 };
   1905 
   1906 GNUNET_NETWORK_STRUCT_END
   1907 
   1908 
   1909 void
   1910 TALER_wallet_reserve_attest_request_sign (
   1911   struct GNUNET_TIME_Timestamp request_timestamp,
   1912   const json_t *details,
   1913   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1914   struct TALER_ReserveSignatureP *reserve_sig)
   1915 {
   1916   struct TALER_ReserveAttestRequestPS rcp = {
   1917     .purpose.size = htonl (sizeof (rcp)),
   1918     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS),
   1919     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1920   };
   1921 
   1922   TALER_json_hash (details,
   1923                    &rcp.h_details);
   1924   GNUNET_assert (GNUNET_OK ==
   1925                  GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv,
   1926                                             &rcp.purpose,
   1927                                             &reserve_sig->eddsa_signature));
   1928 }
   1929 
   1930 
   1931 enum GNUNET_GenericReturnValue
   1932 TALER_wallet_reserve_attest_request_verify (
   1933   struct GNUNET_TIME_Timestamp request_timestamp,
   1934   const json_t *details,
   1935   const struct TALER_ReservePublicKeyP *reserve_pub,
   1936   const struct TALER_ReserveSignatureP *reserve_sig)
   1937 {
   1938   struct TALER_ReserveAttestRequestPS rcp = {
   1939     .purpose.size = htonl (sizeof (rcp)),
   1940     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS),
   1941     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1942   };
   1943 
   1944   TALER_json_hash (details,
   1945                    &rcp.h_details);
   1946   return GNUNET_CRYPTO_eddsa_verify_ (
   1947     TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS,
   1948     &rcp.purpose,
   1949     &reserve_sig->eddsa_signature,
   1950     &reserve_pub->eddsa_pub);
   1951 }
   1952 
   1953 
   1954 GNUNET_NETWORK_STRUCT_BEGIN
   1955 
   1956 /**
   1957  * Message signed by purse to associate an encrypted contract.
   1958  */
   1959 struct TALER_PurseContractPS
   1960 {
   1961 
   1962   /**
   1963    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_ECONTRACT
   1964    */
   1965   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1966 
   1967   /**
   1968    * Hash over the encrypted contract.
   1969    */
   1970   struct GNUNET_HashCode h_econtract;
   1971 
   1972   /**
   1973    * Public key to decrypt the contract.
   1974    */
   1975   struct TALER_ContractDiffiePublicP contract_pub;
   1976 };
   1977 
   1978 GNUNET_NETWORK_STRUCT_END
   1979 
   1980 void
   1981 TALER_wallet_econtract_upload_sign (
   1982   const void *econtract,
   1983   size_t econtract_size,
   1984   const struct TALER_ContractDiffiePublicP *contract_pub,
   1985   const struct TALER_PurseContractPrivateKeyP *purse_priv,
   1986   struct TALER_PurseContractSignatureP *purse_sig)
   1987 {
   1988   struct TALER_PurseContractPS pc = {
   1989     .purpose.size = htonl (sizeof (pc)),
   1990     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT),
   1991     .contract_pub = *contract_pub
   1992   };
   1993 
   1994   GNUNET_CRYPTO_hash (econtract,
   1995                       econtract_size,
   1996                       &pc.h_econtract);
   1997   GNUNET_assert (GNUNET_OK ==
   1998                  GNUNET_CRYPTO_eddsa_sign_ (&purse_priv->eddsa_priv,
   1999                                             &pc.purpose,
   2000                                             &purse_sig->eddsa_signature));
   2001 }
   2002 
   2003 
   2004 enum GNUNET_GenericReturnValue
   2005 TALER_wallet_econtract_upload_verify2 (
   2006   const struct GNUNET_HashCode *h_econtract,
   2007   const struct TALER_ContractDiffiePublicP *contract_pub,
   2008   const struct TALER_PurseContractPublicKeyP *purse_pub,
   2009   const struct TALER_PurseContractSignatureP *purse_sig)
   2010 {
   2011   struct TALER_PurseContractPS pc = {
   2012     .purpose.size = htonl (sizeof (pc)),
   2013     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT),
   2014     .contract_pub = *contract_pub,
   2015     .h_econtract = *h_econtract
   2016   };
   2017 
   2018   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT,
   2019                                       &pc.purpose,
   2020                                       &purse_sig->eddsa_signature,
   2021                                       &purse_pub->eddsa_pub);
   2022 }
   2023 
   2024 
   2025 enum GNUNET_GenericReturnValue
   2026 TALER_wallet_econtract_upload_verify (
   2027   const void *econtract,
   2028   size_t econtract_size,
   2029   const struct TALER_ContractDiffiePublicP *contract_pub,
   2030   const struct TALER_PurseContractPublicKeyP *purse_pub,
   2031   const struct TALER_PurseContractSignatureP *purse_sig)
   2032 {
   2033   struct GNUNET_HashCode h_econtract;
   2034 
   2035   GNUNET_CRYPTO_hash (econtract,
   2036                       econtract_size,
   2037                       &h_econtract);
   2038   return TALER_wallet_econtract_upload_verify2 (&h_econtract,
   2039                                                 contract_pub,
   2040                                                 purse_pub,
   2041                                                 purse_sig);
   2042 }
   2043 
   2044 
   2045 GNUNET_NETWORK_STRUCT_BEGIN
   2046 
   2047 /**
   2048  * Message signed by wallet to confirm usage of a token for a transaction.
   2049  */
   2050 struct TALER_TokenUseRequestPS
   2051 {
   2052 
   2053   /**
   2054    * Purpose is #TALER_SIGNATURE_WALLET_TOKEN_USE
   2055    */
   2056   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   2057 
   2058   /**
   2059    * Hash over the contract for which this token is used.
   2060    */
   2061   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
   2062 
   2063   /**
   2064    * Hash over a JSON containing data provided by the
   2065    * wallet to complete the contract upon payment.
   2066    */
   2067   struct GNUNET_HashCode wallet_data_hash;
   2068 
   2069 };
   2070 
   2071 GNUNET_NETWORK_STRUCT_END
   2072 
   2073 
   2074 void
   2075 TALER_wallet_token_use_sign (
   2076   const struct TALER_PrivateContractHashP *h_contract_terms,
   2077   const struct GNUNET_HashCode *wallet_data_hash,
   2078   const struct TALER_TokenUsePrivateKeyP *token_use_priv,
   2079   struct TALER_TokenUseSignatureP *token_sig)
   2080 {
   2081   struct TALER_TokenUseRequestPS tur = {
   2082     .purpose.size = htonl (sizeof (tur)),
   2083     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_TOKEN_USE),
   2084     .h_contract_terms = *h_contract_terms,
   2085     .wallet_data_hash = *wallet_data_hash
   2086   };
   2087 
   2088   GNUNET_CRYPTO_eddsa_sign (&token_use_priv->private_key,
   2089                             &tur,
   2090                             &token_sig->signature);
   2091 }
   2092 
   2093 
   2094 enum GNUNET_GenericReturnValue
   2095 TALER_wallet_token_use_verify (
   2096   const struct TALER_PrivateContractHashP *h_contract_terms,
   2097   const struct GNUNET_HashCode *wallet_data_hash,
   2098   const struct TALER_TokenUsePublicKeyP *token_use_pub,
   2099   const struct TALER_TokenUseSignatureP *token_sig)
   2100 {
   2101   struct TALER_TokenUseRequestPS tur = {
   2102     .purpose.size = htonl (sizeof (tur)),
   2103     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_TOKEN_USE),
   2104     .h_contract_terms = *h_contract_terms,
   2105     .wallet_data_hash = *wallet_data_hash
   2106   };
   2107 
   2108   return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_TOKEN_USE,
   2109                                      &tur,
   2110                                      &token_sig->signature,
   2111                                      &token_use_pub->public_key);
   2112 }
   2113 
   2114 
   2115 GNUNET_NETWORK_STRUCT_BEGIN
   2116 
   2117 /**
   2118  * Message signed by reserve key.
   2119  */
   2120 struct TALER_OrderUnclaimPS
   2121 {
   2122 
   2123   /**
   2124    * Purpose is #TALER_SIGNATURE_WALLET_ORDER_UNCLAIM
   2125    */
   2126   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   2127 
   2128   /**
   2129    * Hash of the contract being unclaimed.
   2130    */
   2131   struct GNUNET_HashCode h_contract;
   2132 
   2133 };
   2134 
   2135 GNUNET_NETWORK_STRUCT_END
   2136 
   2137 
   2138 void
   2139 TALER_wallet_order_unclaim_sign (
   2140   const struct GNUNET_HashCode *h_contract,
   2141   const struct GNUNET_CRYPTO_EddsaPrivateKey *nonce_priv,
   2142   struct GNUNET_CRYPTO_EddsaSignature *nsig)
   2143 {
   2144   struct TALER_OrderUnclaimPS rcp = {
   2145     .purpose.size = htonl (sizeof (rcp)),
   2146     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ORDER_UNCLAIM),
   2147     .h_contract = *h_contract
   2148   };
   2149 
   2150   GNUNET_assert (GNUNET_OK ==
   2151                  GNUNET_CRYPTO_eddsa_sign_ (nonce_priv,
   2152                                             &rcp.purpose,
   2153                                             nsig));
   2154 }
   2155 
   2156 
   2157 enum GNUNET_GenericReturnValue
   2158 TALER_wallet_order_unclaim_verify (
   2159   const struct GNUNET_HashCode *h_contract,
   2160   const struct GNUNET_CRYPTO_EddsaPublicKey *nonce,
   2161   const struct GNUNET_CRYPTO_EddsaSignature *nsig)
   2162 {
   2163   struct TALER_OrderUnclaimPS rcp = {
   2164     .purpose.size = htonl (sizeof (rcp)),
   2165     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE),
   2166     .h_contract = *h_contract
   2167   };
   2168 
   2169   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_ORDER_UNCLAIM,
   2170                                       &rcp.purpose,
   2171                                       nsig,
   2172                                       nonce);
   2173 }
   2174 
   2175 
   2176 GNUNET_NETWORK_STRUCT_BEGIN
   2177 
   2178 /**
   2179  * Message signed by reserve map authorization key.
   2180  */
   2181 struct TALER_ReserveMapAuthorizationPS
   2182 {
   2183 
   2184   /**
   2185    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_MAP_AUTHORIZATION
   2186    */
   2187   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   2188 
   2189   /**
   2190    * Account key to associate with the authorization key subject.
   2191    */
   2192   union TALER_AccountPublicKeyP account_pub;
   2193 
   2194 };
   2195 
   2196 GNUNET_NETWORK_STRUCT_END
   2197 
   2198 
   2199 void
   2200 TALER_wallet_reserve_map_authorization_sign (
   2201   const union TALER_AccountPublicKeyP *account_pub,
   2202   const struct TALER_ReserveMapAuthorizationPrivateKeyP *auth_priv,
   2203   struct TALER_ReserveMapAuthorizationSignatureP *auth_sig)
   2204 {
   2205   struct TALER_ReserveMapAuthorizationPS rcp = {
   2206     .purpose.size = htonl (sizeof (rcp)),
   2207     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_MAP_AUTHORIZATION),
   2208     .account_pub = *account_pub
   2209   };
   2210 
   2211   GNUNET_assert (GNUNET_OK ==
   2212                  GNUNET_CRYPTO_eddsa_sign_ (
   2213                    &auth_priv->eddsa_priv,
   2214                    &rcp.purpose,
   2215                    &auth_sig->eddsa_signature));
   2216 }
   2217 
   2218 
   2219 enum GNUNET_GenericReturnValue
   2220 TALER_wallet_reserve_map_authorization_verify (
   2221   const union TALER_AccountPublicKeyP *account_pub,
   2222   const struct TALER_ReserveMapAuthorizationPublicKeyP *auth_pub,
   2223   const struct TALER_ReserveMapAuthorizationSignatureP *auth_sig)
   2224 {
   2225   struct TALER_ReserveMapAuthorizationPS rcp = {
   2226     .purpose.size = htonl (sizeof (rcp)),
   2227     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_MAP_AUTHORIZATION),
   2228     .account_pub = *account_pub
   2229   };
   2230 
   2231   return GNUNET_CRYPTO_eddsa_verify_ (
   2232     TALER_SIGNATURE_WALLET_RESERVE_MAP_AUTHORIZATION,
   2233     &rcp.purpose,
   2234     &auth_sig->eddsa_signature,
   2235     &auth_pub->eddsa_pub);
   2236 }
   2237 
   2238 
   2239 /* end of wallet_signatures.c */