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 (67462B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2021-2026 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   };
   1372 
   1373   if (NULL != h_age_commitment)
   1374     pm.h_age_commitment = *h_age_commitment;
   1375   GNUNET_CRYPTO_hash (exchange_base_url,
   1376                       strlen (exchange_base_url) + 1,
   1377                       &pm.h_exchange_base_url);
   1378   TALER_amount_hton (&pm.coin_amount,
   1379                      amount);
   1380   GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
   1381                             &pm,
   1382                             &coin_sig->eddsa_signature);
   1383 }
   1384 
   1385 
   1386 enum GNUNET_GenericReturnValue
   1387 TALER_wallet_purse_deposit_verify (
   1388   const char *exchange_base_url,
   1389   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1390   const struct TALER_Amount *amount,
   1391   const struct TALER_DenominationHashP *h_denom_pub,
   1392   const struct TALER_AgeCommitmentHashP *h_age_commitment,
   1393   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1394   const struct TALER_CoinSpendSignatureP *coin_sig)
   1395 {
   1396   struct TALER_PurseDepositPS pm = {
   1397     .purpose.size = htonl (sizeof (pm)),
   1398     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_DEPOSIT),
   1399     .purse_pub = *purse_pub,
   1400     .h_denom_pub = *h_denom_pub
   1401   };
   1402 
   1403   if (NULL != h_age_commitment)
   1404     pm.h_age_commitment = *h_age_commitment;
   1405   GNUNET_CRYPTO_hash (exchange_base_url,
   1406                       strlen (exchange_base_url) + 1,
   1407                       &pm.h_exchange_base_url);
   1408   TALER_amount_hton (&pm.coin_amount,
   1409                      amount);
   1410   return GNUNET_CRYPTO_eddsa_verify (
   1411     TALER_SIGNATURE_WALLET_PURSE_DEPOSIT,
   1412     &pm,
   1413     &coin_sig->eddsa_signature,
   1414     &coin_pub->eddsa_pub);
   1415 }
   1416 
   1417 
   1418 GNUNET_NETWORK_STRUCT_BEGIN
   1419 
   1420 /**
   1421  * Message signed to merge a purse into a reserve.
   1422  */
   1423 struct TALER_PurseMergePS
   1424 {
   1425 
   1426   /**
   1427    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_MERGE
   1428    */
   1429   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1430 
   1431   /**
   1432    * Time when the purse is merged into the reserve.
   1433    */
   1434   struct GNUNET_TIME_TimestampNBO merge_timestamp;
   1435 
   1436   /**
   1437    * Which purse is being merged?
   1438    */
   1439   struct TALER_PurseContractPublicKeyP purse_pub;
   1440 
   1441   /**
   1442    * Which reserve should the purse be merged with.
   1443    * Hash of the reserve's payto:// URI.
   1444    */
   1445   struct TALER_NormalizedPaytoHashP h_payto;
   1446 
   1447 };
   1448 
   1449 GNUNET_NETWORK_STRUCT_END
   1450 
   1451 void
   1452 TALER_wallet_purse_merge_sign (
   1453   const struct TALER_NormalizedPayto reserve_uri,
   1454   struct GNUNET_TIME_Timestamp merge_timestamp,
   1455   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1456   const struct TALER_PurseMergePrivateKeyP *merge_priv,
   1457   struct TALER_PurseMergeSignatureP *merge_sig)
   1458 {
   1459   struct TALER_PurseMergePS pm = {
   1460     .purpose.size = htonl (sizeof (pm)),
   1461     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_MERGE),
   1462     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1463     .purse_pub = *purse_pub
   1464   };
   1465 
   1466   GNUNET_assert (0 ==
   1467                  strncasecmp (reserve_uri.normalized_payto,
   1468                               "payto://taler-reserve",
   1469                               strlen ("payto://taler-reserve")));
   1470   TALER_normalized_payto_hash (reserve_uri,
   1471                                &pm.h_payto);
   1472   GNUNET_CRYPTO_eddsa_sign (&merge_priv->eddsa_priv,
   1473                             &pm,
   1474                             &merge_sig->eddsa_signature);
   1475 }
   1476 
   1477 
   1478 enum GNUNET_GenericReturnValue
   1479 TALER_wallet_purse_merge_verify (
   1480   const struct TALER_NormalizedPayto reserve_uri,
   1481   struct GNUNET_TIME_Timestamp merge_timestamp,
   1482   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1483   const struct TALER_PurseMergePublicKeyP *merge_pub,
   1484   const struct TALER_PurseMergeSignatureP *merge_sig)
   1485 {
   1486   struct TALER_PurseMergePS pm = {
   1487     .purpose.size = htonl (sizeof (pm)),
   1488     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_MERGE),
   1489     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1490     .purse_pub = *purse_pub
   1491   };
   1492 
   1493   if (0 !=
   1494       strncasecmp (reserve_uri.normalized_payto,
   1495                    "payto://taler-reserve",
   1496                    strlen ("payto://taler-reserve")))
   1497   {
   1498     GNUNET_break (0);
   1499     return GNUNET_NO;
   1500   }
   1501   TALER_normalized_payto_hash (reserve_uri,
   1502                                &pm.h_payto);
   1503   return GNUNET_CRYPTO_eddsa_verify (
   1504     TALER_SIGNATURE_WALLET_PURSE_MERGE,
   1505     &pm,
   1506     &merge_sig->eddsa_signature,
   1507     &merge_pub->eddsa_pub);
   1508 }
   1509 
   1510 
   1511 GNUNET_NETWORK_STRUCT_BEGIN
   1512 
   1513 /**
   1514  * Message signed by account to merge a purse into a reserve.
   1515  */
   1516 struct TALER_AccountMergePS
   1517 {
   1518 
   1519   /**
   1520    * Purpose is #TALER_SIGNATURE_WALLET_ACCOUNT_MERGE
   1521    */
   1522   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1523 
   1524   /**
   1525    * Time when the purse will expire if still unmerged or unpaid.
   1526    */
   1527   struct GNUNET_TIME_TimestampNBO purse_expiration;
   1528 
   1529   /**
   1530    * Total amount (with fees) to be put into the purse.
   1531    */
   1532   struct TALER_AmountNBO purse_amount;
   1533 
   1534   /**
   1535    * Purse creation fee to be paid by the reserve for
   1536    * this operation.
   1537    */
   1538   struct TALER_AmountNBO purse_fee;
   1539 
   1540   /**
   1541    * Contract this purse pays for.
   1542    */
   1543   struct TALER_PrivateContractHashP h_contract_terms;
   1544 
   1545   /**
   1546    * Purse to merge.
   1547    */
   1548   struct TALER_PurseContractPublicKeyP purse_pub;
   1549 
   1550   /**
   1551    * Time when the purse is merged into the reserve.
   1552    */
   1553   struct GNUNET_TIME_TimestampNBO merge_timestamp;
   1554 
   1555   /**
   1556    * Minimum age required for payments into this purse,
   1557    * in NBO.
   1558    */
   1559   uint32_t min_age GNUNET_PACKED;
   1560 
   1561   /**
   1562    * Flags for the operation, in NBO. See
   1563    * `enum TALER_WalletAccountMergeFlags`.
   1564    */
   1565   uint32_t flags GNUNET_PACKED;
   1566 };
   1567 
   1568 GNUNET_NETWORK_STRUCT_END
   1569 
   1570 
   1571 void
   1572 TALER_wallet_account_merge_sign (
   1573   struct GNUNET_TIME_Timestamp merge_timestamp,
   1574   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1575   struct GNUNET_TIME_Timestamp purse_expiration,
   1576   const struct TALER_PrivateContractHashP *h_contract_terms,
   1577   const struct TALER_Amount *amount,
   1578   const struct TALER_Amount *purse_fee,
   1579   uint32_t min_age,
   1580   enum TALER_WalletAccountMergeFlags flags,
   1581   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1582   struct TALER_ReserveSignatureP *reserve_sig)
   1583 {
   1584   struct TALER_AccountMergePS pm = {
   1585     .purpose.size = htonl (sizeof (pm)),
   1586     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_MERGE),
   1587     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1588     .purse_pub = *purse_pub,
   1589     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1590     .h_contract_terms = *h_contract_terms,
   1591     .min_age = htonl (min_age),
   1592     .flags = htonl ((uint32_t) flags)
   1593   };
   1594 
   1595   TALER_amount_hton (&pm.purse_amount,
   1596                      amount);
   1597   TALER_amount_hton (&pm.purse_fee,
   1598                      purse_fee);
   1599   GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
   1600                             &pm,
   1601                             &reserve_sig->eddsa_signature);
   1602 }
   1603 
   1604 
   1605 enum GNUNET_GenericReturnValue
   1606 TALER_wallet_account_merge_verify (
   1607   struct GNUNET_TIME_Timestamp merge_timestamp,
   1608   const struct TALER_PurseContractPublicKeyP *purse_pub,
   1609   struct GNUNET_TIME_Timestamp purse_expiration,
   1610   const struct TALER_PrivateContractHashP *h_contract_terms,
   1611   const struct TALER_Amount *amount,
   1612   const struct TALER_Amount *purse_fee,
   1613   uint32_t min_age,
   1614   enum TALER_WalletAccountMergeFlags flags,
   1615   const struct TALER_ReservePublicKeyP *reserve_pub,
   1616   const struct TALER_ReserveSignatureP *reserve_sig)
   1617 {
   1618   struct TALER_AccountMergePS pm = {
   1619     .purpose.size = htonl (sizeof (pm)),
   1620     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ACCOUNT_MERGE),
   1621     .merge_timestamp = GNUNET_TIME_timestamp_hton (merge_timestamp),
   1622     .purse_pub = *purse_pub,
   1623     .purse_expiration = GNUNET_TIME_timestamp_hton (purse_expiration),
   1624     .h_contract_terms = *h_contract_terms,
   1625     .min_age = htonl (min_age),
   1626     .flags = htonl ((uint32_t) flags)
   1627   };
   1628 
   1629   TALER_amount_hton (&pm.purse_amount,
   1630                      amount);
   1631   TALER_amount_hton (&pm.purse_fee,
   1632                      purse_fee);
   1633   return GNUNET_CRYPTO_eddsa_verify (
   1634     TALER_SIGNATURE_WALLET_ACCOUNT_MERGE,
   1635     &pm,
   1636     &reserve_sig->eddsa_signature,
   1637     &reserve_pub->eddsa_pub);
   1638 }
   1639 
   1640 
   1641 GNUNET_NETWORK_STRUCT_BEGIN
   1642 
   1643 /**
   1644  * Message signed by reserve key.
   1645  */
   1646 struct TALER_ReserveOpenPS
   1647 {
   1648 
   1649   /**
   1650    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_OPEN
   1651    */
   1652   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1653 
   1654   /**
   1655    * Amount to be paid from the reserve balance to open
   1656    * the reserve.
   1657    */
   1658   struct TALER_AmountNBO reserve_payment;
   1659 
   1660   /**
   1661    * When was the request created.
   1662    */
   1663   struct GNUNET_TIME_TimestampNBO request_timestamp;
   1664 
   1665   /**
   1666    * For how long should the reserve be kept open.
   1667    * (Determines amount to be paid.)
   1668    */
   1669   struct GNUNET_TIME_TimestampNBO reserve_expiration;
   1670 
   1671   /**
   1672    * How many open purses should be included with the
   1673    * open reserve?
   1674    * (Determines amount to be paid.)
   1675    */
   1676   uint32_t purse_limit GNUNET_PACKED;
   1677 
   1678 };
   1679 
   1680 GNUNET_NETWORK_STRUCT_END
   1681 
   1682 
   1683 void
   1684 TALER_wallet_reserve_open_sign (
   1685   const struct TALER_Amount *reserve_payment,
   1686   struct GNUNET_TIME_Timestamp request_timestamp,
   1687   struct GNUNET_TIME_Timestamp reserve_expiration,
   1688   uint32_t purse_limit,
   1689   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1690   struct TALER_ReserveSignatureP *reserve_sig)
   1691 {
   1692   struct TALER_ReserveOpenPS rop = {
   1693     .purpose.size = htonl (sizeof (rop)),
   1694     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN),
   1695     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp),
   1696     .reserve_expiration = GNUNET_TIME_timestamp_hton (reserve_expiration),
   1697     .purse_limit = htonl (purse_limit)
   1698   };
   1699 
   1700   TALER_amount_hton (&rop.reserve_payment,
   1701                      reserve_payment);
   1702   GNUNET_assert (GNUNET_OK ==
   1703                  GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv,
   1704                                             &rop.purpose,
   1705                                             &reserve_sig->eddsa_signature));
   1706 }
   1707 
   1708 
   1709 enum GNUNET_GenericReturnValue
   1710 TALER_wallet_reserve_open_verify (
   1711   const struct TALER_Amount *reserve_payment,
   1712   struct GNUNET_TIME_Timestamp request_timestamp,
   1713   struct GNUNET_TIME_Timestamp reserve_expiration,
   1714   uint32_t purse_limit,
   1715   const struct TALER_ReservePublicKeyP *reserve_pub,
   1716   const struct TALER_ReserveSignatureP *reserve_sig)
   1717 {
   1718   struct TALER_ReserveOpenPS rop = {
   1719     .purpose.size = htonl (sizeof (rop)),
   1720     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN),
   1721     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp),
   1722     .reserve_expiration = GNUNET_TIME_timestamp_hton (reserve_expiration),
   1723     .purse_limit = htonl (purse_limit)
   1724   };
   1725 
   1726   TALER_amount_hton (&rop.reserve_payment,
   1727                      reserve_payment);
   1728   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_RESERVE_OPEN,
   1729                                       &rop.purpose,
   1730                                       &reserve_sig->eddsa_signature,
   1731                                       &reserve_pub->eddsa_pub);
   1732 }
   1733 
   1734 
   1735 GNUNET_NETWORK_STRUCT_BEGIN
   1736 
   1737 /**
   1738  * Message signed by
   1739  */
   1740 struct TALER_ReserveOpenDepositPS
   1741 {
   1742 
   1743   /**
   1744    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT
   1745    */
   1746   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1747 
   1748   /**
   1749    * Which reserve's opening signature should be paid for?
   1750    */
   1751   struct TALER_ReserveSignatureP reserve_sig;
   1752 
   1753   /**
   1754    * Specifies how much of the coin's value should be spent on opening this
   1755    * reserve.
   1756    */
   1757   struct TALER_AmountNBO coin_contribution;
   1758 
   1759   /**
   1760    * Hash over the coin's age commitment, all zero if the coin had
   1761    * no age restriction.
   1762    */
   1763   struct TALER_AgeCommitmentHashP h_age_commitment;
   1764 
   1765   /**
   1766    * Hash over the coin's denomination public key.
   1767    */
   1768   struct TALER_DenominationHashP h_denom_pub;
   1769 };
   1770 
   1771 GNUNET_NETWORK_STRUCT_END
   1772 
   1773 
   1774 void
   1775 TALER_wallet_reserve_open_deposit_sign (
   1776   const struct TALER_Amount *coin_contribution,
   1777   const struct TALER_DenominationHashP *h_denom_pub,
   1778   const struct TALER_AgeCommitmentHashP *h_age_commitment,
   1779   const struct TALER_ReserveSignatureP *reserve_sig,
   1780   const struct TALER_CoinSpendPrivateKeyP *coin_priv,
   1781   struct TALER_CoinSpendSignatureP *coin_sig)
   1782 {
   1783   struct TALER_ReserveOpenDepositPS rod = {
   1784     .purpose.size = htonl (sizeof (rod)),
   1785     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT),
   1786     .reserve_sig = *reserve_sig,
   1787     .h_denom_pub = *h_denom_pub
   1788   };
   1789 
   1790   if (NULL != h_age_commitment)
   1791     rod.h_age_commitment = *h_age_commitment;
   1792   TALER_amount_hton (&rod.coin_contribution,
   1793                      coin_contribution);
   1794   GNUNET_assert (GNUNET_OK ==
   1795                  GNUNET_CRYPTO_eddsa_sign_ (&coin_priv->eddsa_priv,
   1796                                             &rod.purpose,
   1797                                             &coin_sig->eddsa_signature));
   1798 }
   1799 
   1800 
   1801 enum GNUNET_GenericReturnValue
   1802 TALER_wallet_reserve_open_deposit_verify (
   1803   const struct TALER_Amount *coin_contribution,
   1804   const struct TALER_DenominationHashP *h_denom_pub,
   1805   const struct TALER_AgeCommitmentHashP *h_age_commitment,
   1806   const struct TALER_ReserveSignatureP *reserve_sig,
   1807   const struct TALER_CoinSpendPublicKeyP *coin_pub,
   1808   const struct TALER_CoinSpendSignatureP *coin_sig)
   1809 {
   1810   struct TALER_ReserveOpenDepositPS rod = {
   1811     .purpose.size = htonl (sizeof (rod)),
   1812     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT),
   1813     .reserve_sig = *reserve_sig,
   1814     .h_denom_pub = *h_denom_pub
   1815   };
   1816 
   1817   if (NULL != h_age_commitment)
   1818     rod.h_age_commitment = *h_age_commitment;
   1819   TALER_amount_hton (&rod.coin_contribution,
   1820                      coin_contribution);
   1821   return GNUNET_CRYPTO_eddsa_verify_ (
   1822     TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT,
   1823     &rod.purpose,
   1824     &coin_sig->eddsa_signature,
   1825     &coin_pub->eddsa_pub);
   1826 }
   1827 
   1828 
   1829 GNUNET_NETWORK_STRUCT_BEGIN
   1830 
   1831 /**
   1832  * Message signed by reserve key.
   1833  */
   1834 struct TALER_ReserveClosePS
   1835 {
   1836 
   1837   /**
   1838    * Purpose is #TALER_SIGNATURE_WALLET_RESERVE_CLOSE
   1839    */
   1840   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1841 
   1842   /**
   1843    * When was the request created.
   1844    */
   1845   struct GNUNET_TIME_TimestampNBO request_timestamp;
   1846 
   1847   /**
   1848    * Hash of the payto://-URI of the target account
   1849    * for the closure, or all zeros for the reserve
   1850    * origin account.
   1851    */
   1852   struct TALER_FullPaytoHashP target_account_h_payto;
   1853 
   1854 };
   1855 
   1856 GNUNET_NETWORK_STRUCT_END
   1857 
   1858 
   1859 void
   1860 TALER_wallet_reserve_close_sign (
   1861   struct GNUNET_TIME_Timestamp request_timestamp,
   1862   const struct TALER_FullPaytoHashP *h_payto,
   1863   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1864   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   GNUNET_assert (GNUNET_OK ==
   1875                  GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv,
   1876                                             &rcp.purpose,
   1877                                             &reserve_sig->eddsa_signature));
   1878 }
   1879 
   1880 
   1881 enum GNUNET_GenericReturnValue
   1882 TALER_wallet_reserve_close_verify (
   1883   struct GNUNET_TIME_Timestamp request_timestamp,
   1884   const struct TALER_FullPaytoHashP *h_payto,
   1885   const struct TALER_ReservePublicKeyP *reserve_pub,
   1886   const struct TALER_ReserveSignatureP *reserve_sig)
   1887 {
   1888   struct TALER_ReserveClosePS rcp = {
   1889     .purpose.size = htonl (sizeof (rcp)),
   1890     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_CLOSE),
   1891     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1892   };
   1893 
   1894   if (NULL != h_payto)
   1895     rcp.target_account_h_payto = *h_payto;
   1896   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_RESERVE_CLOSE,
   1897                                       &rcp.purpose,
   1898                                       &reserve_sig->eddsa_signature,
   1899                                       &reserve_pub->eddsa_pub);
   1900 }
   1901 
   1902 
   1903 GNUNET_NETWORK_STRUCT_BEGIN
   1904 
   1905 /**
   1906  * Message signed by reserve private key.
   1907  */
   1908 struct TALER_ReserveAttestRequestPS
   1909 {
   1910 
   1911   /**
   1912    * Purpose is #TALER_SIGNATURE_WALLET_ATTEST_REQUEST
   1913    */
   1914   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1915 
   1916   /**
   1917    * When was the request created.
   1918    */
   1919   struct GNUNET_TIME_TimestampNBO request_timestamp;
   1920 
   1921   /**
   1922    * Hash over the JSON array of requested attributes.
   1923    */
   1924   struct GNUNET_HashCode h_details;
   1925 
   1926 };
   1927 
   1928 GNUNET_NETWORK_STRUCT_END
   1929 
   1930 
   1931 void
   1932 TALER_wallet_reserve_attest_request_sign (
   1933   struct GNUNET_TIME_Timestamp request_timestamp,
   1934   const json_t *details,
   1935   const struct TALER_ReservePrivateKeyP *reserve_priv,
   1936   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   GNUNET_assert (GNUNET_OK ==
   1947                  GNUNET_CRYPTO_eddsa_sign_ (&reserve_priv->eddsa_priv,
   1948                                             &rcp.purpose,
   1949                                             &reserve_sig->eddsa_signature));
   1950 }
   1951 
   1952 
   1953 enum GNUNET_GenericReturnValue
   1954 TALER_wallet_reserve_attest_request_verify (
   1955   struct GNUNET_TIME_Timestamp request_timestamp,
   1956   const json_t *details,
   1957   const struct TALER_ReservePublicKeyP *reserve_pub,
   1958   const struct TALER_ReserveSignatureP *reserve_sig)
   1959 {
   1960   struct TALER_ReserveAttestRequestPS rcp = {
   1961     .purpose.size = htonl (sizeof (rcp)),
   1962     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS),
   1963     .request_timestamp = GNUNET_TIME_timestamp_hton (request_timestamp)
   1964   };
   1965 
   1966   TALER_json_hash (details,
   1967                    &rcp.h_details);
   1968   return GNUNET_CRYPTO_eddsa_verify_ (
   1969     TALER_SIGNATURE_WALLET_RESERVE_ATTEST_DETAILS,
   1970     &rcp.purpose,
   1971     &reserve_sig->eddsa_signature,
   1972     &reserve_pub->eddsa_pub);
   1973 }
   1974 
   1975 
   1976 GNUNET_NETWORK_STRUCT_BEGIN
   1977 
   1978 /**
   1979  * Message signed by purse to associate an encrypted contract.
   1980  */
   1981 struct TALER_PurseContractPS
   1982 {
   1983 
   1984   /**
   1985    * Purpose is #TALER_SIGNATURE_WALLET_PURSE_ECONTRACT
   1986    */
   1987   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   1988 
   1989   /**
   1990    * Hash over the encrypted contract.
   1991    */
   1992   struct GNUNET_HashCode h_econtract;
   1993 
   1994   /**
   1995    * Public key to decrypt the contract.
   1996    */
   1997   struct TALER_ContractDiffiePublicP contract_pub;
   1998 };
   1999 
   2000 GNUNET_NETWORK_STRUCT_END
   2001 
   2002 void
   2003 TALER_wallet_econtract_upload_sign (
   2004   const void *econtract,
   2005   size_t econtract_size,
   2006   const struct TALER_ContractDiffiePublicP *contract_pub,
   2007   const struct TALER_PurseContractPrivateKeyP *purse_priv,
   2008   struct TALER_PurseContractSignatureP *purse_sig)
   2009 {
   2010   struct TALER_PurseContractPS pc = {
   2011     .purpose.size = htonl (sizeof (pc)),
   2012     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT),
   2013     .contract_pub = *contract_pub
   2014   };
   2015 
   2016   GNUNET_CRYPTO_hash (econtract,
   2017                       econtract_size,
   2018                       &pc.h_econtract);
   2019   GNUNET_assert (GNUNET_OK ==
   2020                  GNUNET_CRYPTO_eddsa_sign_ (&purse_priv->eddsa_priv,
   2021                                             &pc.purpose,
   2022                                             &purse_sig->eddsa_signature));
   2023 }
   2024 
   2025 
   2026 enum GNUNET_GenericReturnValue
   2027 TALER_wallet_econtract_upload_verify2 (
   2028   const struct GNUNET_HashCode *h_econtract,
   2029   const struct TALER_ContractDiffiePublicP *contract_pub,
   2030   const struct TALER_PurseContractPublicKeyP *purse_pub,
   2031   const struct TALER_PurseContractSignatureP *purse_sig)
   2032 {
   2033   struct TALER_PurseContractPS pc = {
   2034     .purpose.size = htonl (sizeof (pc)),
   2035     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT),
   2036     .contract_pub = *contract_pub,
   2037     .h_econtract = *h_econtract
   2038   };
   2039 
   2040   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_PURSE_ECONTRACT,
   2041                                       &pc.purpose,
   2042                                       &purse_sig->eddsa_signature,
   2043                                       &purse_pub->eddsa_pub);
   2044 }
   2045 
   2046 
   2047 enum GNUNET_GenericReturnValue
   2048 TALER_wallet_econtract_upload_verify (
   2049   const void *econtract,
   2050   size_t econtract_size,
   2051   const struct TALER_ContractDiffiePublicP *contract_pub,
   2052   const struct TALER_PurseContractPublicKeyP *purse_pub,
   2053   const struct TALER_PurseContractSignatureP *purse_sig)
   2054 {
   2055   struct GNUNET_HashCode h_econtract;
   2056 
   2057   GNUNET_CRYPTO_hash (econtract,
   2058                       econtract_size,
   2059                       &h_econtract);
   2060   return TALER_wallet_econtract_upload_verify2 (&h_econtract,
   2061                                                 contract_pub,
   2062                                                 purse_pub,
   2063                                                 purse_sig);
   2064 }
   2065 
   2066 
   2067 GNUNET_NETWORK_STRUCT_BEGIN
   2068 
   2069 /**
   2070  * Message signed by wallet to confirm usage of a token for a transaction.
   2071  */
   2072 struct TALER_TokenUseRequestPS
   2073 {
   2074 
   2075   /**
   2076    * Purpose is #TALER_SIGNATURE_WALLET_TOKEN_USE
   2077    */
   2078   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   2079 
   2080   /**
   2081    * Hash over the contract for which this token is used.
   2082    */
   2083   struct TALER_PrivateContractHashP h_contract_terms GNUNET_PACKED;
   2084 
   2085   /**
   2086    * Hash over a JSON containing data provided by the
   2087    * wallet to complete the contract upon payment.
   2088    */
   2089   struct GNUNET_HashCode wallet_data_hash;
   2090 
   2091 };
   2092 
   2093 GNUNET_NETWORK_STRUCT_END
   2094 
   2095 
   2096 void
   2097 TALER_wallet_token_use_sign (
   2098   const struct TALER_PrivateContractHashP *h_contract_terms,
   2099   const struct GNUNET_HashCode *wallet_data_hash,
   2100   const struct TALER_TokenUsePrivateKeyP *token_use_priv,
   2101   struct TALER_TokenUseSignatureP *token_sig)
   2102 {
   2103   struct TALER_TokenUseRequestPS tur = {
   2104     .purpose.size = htonl (sizeof (tur)),
   2105     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_TOKEN_USE),
   2106     .h_contract_terms = *h_contract_terms,
   2107     .wallet_data_hash = *wallet_data_hash
   2108   };
   2109 
   2110   GNUNET_CRYPTO_eddsa_sign (&token_use_priv->private_key,
   2111                             &tur,
   2112                             &token_sig->signature);
   2113 }
   2114 
   2115 
   2116 enum GNUNET_GenericReturnValue
   2117 TALER_wallet_token_use_verify (
   2118   const struct TALER_PrivateContractHashP *h_contract_terms,
   2119   const struct GNUNET_HashCode *wallet_data_hash,
   2120   const struct TALER_TokenUsePublicKeyP *token_use_pub,
   2121   const struct TALER_TokenUseSignatureP *token_sig)
   2122 {
   2123   struct TALER_TokenUseRequestPS tur = {
   2124     .purpose.size = htonl (sizeof (tur)),
   2125     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_TOKEN_USE),
   2126     .h_contract_terms = *h_contract_terms,
   2127     .wallet_data_hash = *wallet_data_hash
   2128   };
   2129 
   2130   return GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_TOKEN_USE,
   2131                                      &tur,
   2132                                      &token_sig->signature,
   2133                                      &token_use_pub->public_key);
   2134 }
   2135 
   2136 
   2137 GNUNET_NETWORK_STRUCT_BEGIN
   2138 
   2139 /**
   2140  * Message signed by reserve key.
   2141  */
   2142 struct TALER_OrderUnclaimPS
   2143 {
   2144 
   2145   /**
   2146    * Purpose is #TALER_SIGNATURE_WALLET_ORDER_UNCLAIM
   2147    */
   2148   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   2149 
   2150   /**
   2151    * Hash of the contract being unclaimed.
   2152    */
   2153   struct GNUNET_HashCode h_contract;
   2154 
   2155 };
   2156 
   2157 GNUNET_NETWORK_STRUCT_END
   2158 
   2159 
   2160 void
   2161 TALER_wallet_order_unclaim_sign (
   2162   const struct GNUNET_HashCode *h_contract,
   2163   const struct GNUNET_CRYPTO_EddsaPrivateKey *nonce_priv,
   2164   struct GNUNET_CRYPTO_EddsaSignature *nsig)
   2165 {
   2166   struct TALER_OrderUnclaimPS rcp = {
   2167     .purpose.size = htonl (sizeof (rcp)),
   2168     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ORDER_UNCLAIM),
   2169     .h_contract = *h_contract
   2170   };
   2171 
   2172   GNUNET_assert (GNUNET_OK ==
   2173                  GNUNET_CRYPTO_eddsa_sign_ (nonce_priv,
   2174                                             &rcp.purpose,
   2175                                             nsig));
   2176 }
   2177 
   2178 
   2179 enum GNUNET_GenericReturnValue
   2180 TALER_wallet_order_unclaim_verify (
   2181   const struct GNUNET_HashCode *h_contract,
   2182   const struct GNUNET_CRYPTO_EddsaPublicKey *nonce,
   2183   const struct GNUNET_CRYPTO_EddsaSignature *nsig)
   2184 {
   2185   struct TALER_OrderUnclaimPS rcp = {
   2186     .purpose.size = htonl (sizeof (rcp)),
   2187     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_ORDER_UNCLAIM),
   2188     .h_contract = *h_contract
   2189   };
   2190 
   2191   return GNUNET_CRYPTO_eddsa_verify_ (TALER_SIGNATURE_WALLET_ORDER_UNCLAIM,
   2192                                       &rcp.purpose,
   2193                                       nsig,
   2194                                       nonce);
   2195 }
   2196 
   2197 
   2198 GNUNET_NETWORK_STRUCT_BEGIN
   2199 
   2200 /**
   2201  * Message signed by prepared transfer authorization key.
   2202  */
   2203 struct TALER_PreparedTransferRegisterPS
   2204 {
   2205   /**
   2206   * Purpose is #TALER_SIGNATURE_WALLET_PREPARED_TRANSFER_REGISTER
   2207   */
   2208   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   2209   struct TALER_FullPaytoHashP credit_account;
   2210   struct TALER_AmountNBO credit_amount;
   2211   /**
   2212   * 1: reserve, 2: kyc
   2213   */
   2214   uint32_t type;
   2215   /**
   2216   * 1: one-time, 2: recurrent
   2217   */
   2218   uint16_t recurrent;
   2219   /**
   2220   * 1: EdDSA
   2221   */
   2222   uint16_t alg;
   2223   union TALER_AccountPublicKeyP account_pub;
   2224 };
   2225 
   2226 
   2227 GNUNET_NETWORK_STRUCT_END
   2228 
   2229 
   2230 void
   2231 TALER_wallet_prepared_transfer_registration_sign (
   2232   const struct TALER_FullPayto credit_account,
   2233   const struct TALER_Amount *credit_amount,
   2234   // enum TALER_BANK_RegistrationType type, TODO solve the include cycle
   2235   bool is_reserve,
   2236   bool recurrent,
   2237   const union TALER_AccountPublicKeyP *account_pub,
   2238   const struct TALER_PreparedTransferAuthorizationPrivateKeyP *auth_priv,
   2239   struct TALER_PreparedTransferAuthorizationSignatureP *auth_sig)
   2240 {
   2241   struct TALER_PreparedTransferRegisterPS rcp = {
   2242     .purpose.size = htonl (sizeof (rcp)),
   2243     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PREPARED_TRANSFER_REGISTER)
   2244     ,
   2245     .alg = htons (1),
   2246     .account_pub = *account_pub
   2247   };
   2248 
   2249   TALER_full_payto_hash (credit_account,
   2250                          &rcp.credit_account);
   2251   TALER_amount_hton (&rcp.credit_amount,
   2252                      credit_amount);
   2253 
   2254   if (is_reserve)
   2255   {
   2256     rcp.type = htonl (1);
   2257   }
   2258   else
   2259   {
   2260     rcp.type = htonl (2);
   2261   }
   2262 
   2263   if (recurrent)
   2264   {
   2265     rcp.recurrent = htons (2);
   2266   }
   2267   else
   2268   {
   2269     rcp.recurrent = htons (1);
   2270   }
   2271 
   2272   GNUNET_assert (GNUNET_OK ==
   2273                  GNUNET_CRYPTO_eddsa_sign_ (
   2274                    &auth_priv->eddsa_priv,
   2275                    &rcp.purpose,
   2276                    &auth_sig->eddsa_signature));
   2277 }
   2278 
   2279 
   2280 enum GNUNET_GenericReturnValue
   2281 TALER_wallet_prepared_transfer_registration_verify (
   2282   const struct TALER_FullPayto credit_account,
   2283   const struct TALER_Amount *credit_amount,
   2284   // enum TALER_BANK_RegistrationType type, TODO solve the include cycle
   2285   bool is_reserve,
   2286   bool recurrent,
   2287   const union TALER_AccountPublicKeyP *account_pub,
   2288   const struct TALER_PreparedTransferAuthorizationPublicKeyP *auth_pub,
   2289   const struct TALER_PreparedTransferAuthorizationSignatureP *auth_sig)
   2290 {
   2291   struct TALER_PreparedTransferRegisterPS rcp = {
   2292     .purpose.size = htonl (sizeof (rcp)),
   2293     .purpose.purpose = htonl (TALER_SIGNATURE_WALLET_PREPARED_TRANSFER_REGISTER)
   2294     ,
   2295     .alg = htonl (1),
   2296     .account_pub = *account_pub
   2297   };
   2298 
   2299   TALER_full_payto_hash (credit_account,
   2300                          &rcp.credit_account);
   2301   TALER_amount_hton (&rcp.credit_amount,
   2302                      credit_amount);
   2303 
   2304   if (is_reserve)
   2305   {
   2306     rcp.type = htonl (1);
   2307   }
   2308   else
   2309   {
   2310     rcp.type = htonl (2);
   2311   }
   2312 
   2313   if (recurrent)
   2314   {
   2315     rcp.recurrent = htonl (1);
   2316   }
   2317   else
   2318   {
   2319     rcp.recurrent = htonl (2);
   2320   }
   2321 
   2322   return GNUNET_CRYPTO_eddsa_verify_ (
   2323     TALER_SIGNATURE_WALLET_PREPARED_TRANSFER_REGISTER,
   2324     &rcp.purpose,
   2325     &auth_sig->eddsa_signature,
   2326     &auth_pub->eddsa_pub);
   2327 }
   2328 
   2329 
   2330 GNUNET_NETWORK_STRUCT_BEGIN
   2331 
   2332 /**
   2333  * Message signed by prepared transfer authorization key.
   2334  */
   2335 struct TALER_PreparedTransferUnregisterPS
   2336 {
   2337   /**
   2338   * Purpose is #TALER_SIGNATURE_WALLET_PREPARED_TRANSFER_UNREGISTER
   2339   */
   2340   struct GNUNET_CRYPTO_SignaturePurpose purpose;
   2341   struct GNUNET_TIME_TimestampNBO timestamp;
   2342 };
   2343 
   2344 GNUNET_NETWORK_STRUCT_END
   2345 
   2346 /* end of wallet_signatures.c */